<target name="build-env">
<mkdir dir="build" />
<mkdir dir="build/classes" />
- <mkdir dir="build/webapp" />
- <mkdir dir="build/webapp/WEB-INF/classes" />
</target>
<target name="jsvc" depends="build-env">
<!-- <classpath refid="classpath" /> -->
<compilerarg value="-Xlint:unchecked" />
</javac>
+ <copy todir="build/classes/dolda/jsvc/j2ee" file="etc/web.xml.template" />
</target>
<target name="jsvc-jar" depends="build-env, jsvc">
<jar destfile="build/jsvc.jar" basedir="build/classes" />
</target>
- <target name="webapp" depends="build-env">
- <mkdir dir="build/webapp/WEB-INF/lib" />
- <copy file="build/jsvc.jar" tofile="build/webapp/WEB-INF/lib/jsvc.jar" />
- <copy todir="build/webapp/WEB-INF/lib">
- <fileset dir="lib" />
- </copy>
- </target>
-
- <target name="war" depends="build-env, jsvc-jar, webapp">
- <war destfile="build/jsvc.war"
- basedir="build/webapp"
- webxml="www/web.xml"
- />
- </target>
-
<target name="clean">
<delete dir="build" />
</target>
--- /dev/null
+package dolda.jsvc.j2ee;
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+import java.util.zip.*;
+import java.util.jar.*;
+
+public class Archive {
+ private static void usage(PrintStream out) {
+ out.println("usage: dolda.jsvc.j2ee.Archive [-h] [-p PROPFILE] [-n DISPLAY-NAME] WAR-FILE JAR-FILE...");
+ }
+
+ private static void jarprops(String[] jars, String propres, Properties props) throws IOException {
+ URL[] urls = new URL[jars.length];
+ try {
+ for(int i = 0; i < jars.length; i++)
+ urls[i] = new URL("file", "", jars[i]);
+ } catch(MalformedURLException e) {
+ throw(new Error(e));
+ }
+ ClassLoader cl = new URLClassLoader(urls);
+ InputStream in = cl.getResourceAsStream(propres);
+ if(in != null) {
+ try {
+ props.load(in);
+ } finally {
+ in.close();
+ }
+ }
+ }
+
+ private static Properties defprops() {
+ Properties props = new Properties();
+ props.put("jsvc.j2ee.webxml.coding", "UTF-8");
+ return(props);
+ }
+
+ private static void cpstream(InputStream in, OutputStream out) throws IOException {
+ byte[] buf = new byte[4096];
+ while(true) {
+ int ret = in.read(buf, 0, buf.length);
+ if(ret < 0)
+ return;
+ out.write(buf, 0, ret);
+ }
+ }
+
+ private static String subst(String ln, Properties props) {
+ int p = 0;
+ while((p = ln.indexOf("${", p)) >= 0) {
+ int p2 = ln.indexOf('}', p + 2);
+ String pn = ln.substring(p + 2, p2);
+ String pv = (String)props.get(pn);
+ if(pv == null)
+ throw(new RuntimeException("Missing required property " + pn));
+ ln = ln.substring(0, p) + pv + ln.substring(p2 + 1);
+ p = p + pv.length();
+ }
+ return(ln);
+ }
+
+ private static void writewebxml(Properties props, OutputStream out) throws IOException {
+ InputStream tmpl = Archive.class.getResourceAsStream("web.xml.template");
+ String cs = (String)props.get("jsvc.j2ee.webxml.coding");
+ try {
+ BufferedReader r = new BufferedReader(new InputStreamReader(tmpl, "US-ASCII"));
+ BufferedWriter w = new BufferedWriter(new OutputStreamWriter(out, cs));
+ String ln;
+ while((ln = r.readLine()) != null) {
+ w.write(subst(ln, props));
+ w.write('\n');
+ }
+ w.flush();
+ } finally {
+ tmpl.close();
+ }
+ }
+
+ public static void makewar(String[] jars, Properties props, OutputStream out) throws IOException {
+ Manifest man = new Manifest();
+ man.getMainAttributes().put(new Attributes.Name("Manifest-Version"), "1.0");
+ man.getMainAttributes().put(new Attributes.Name("Created-By"), "jsvc");
+ JarOutputStream zip = new JarOutputStream(out, man);
+ zip.putNextEntry(new ZipEntry("WEB-INF/"));
+ zip.putNextEntry(new ZipEntry("WEB-INF/lib/"));
+ for(String jar : jars) {
+ String bn = jar;
+ int p = bn.lastIndexOf('/');
+ if(p >= 0)
+ bn = bn.substring(p + 1);
+ zip.putNextEntry(new ZipEntry("WEB-INF/lib/" + bn));
+ InputStream jarin = new FileInputStream(jar);
+ try {
+ cpstream(jarin, zip);
+ } finally {
+ jarin.close();
+ }
+ }
+ zip.putNextEntry(new ZipEntry("WEB-INF/web.xml"));
+ writewebxml(props, zip);
+ zip.finish();
+ }
+
+ public static void main(String[] args) throws IOException {
+ PosixArgs opt = PosixArgs.getopt(args, "hp:n:");
+ if(opt == null) {
+ usage(System.err);
+ System.exit(1);
+ }
+ if(opt.rest.length < 2) {
+ usage(System.err);
+ System.exit(1);
+ }
+ String war = opt.rest[0];
+ String[] jars = Arrays.copyOfRange(opt.rest, 1, opt.rest.length);
+
+ Properties props = defprops();
+ jarprops(jars, "/jsvc.properties", props);
+
+ for(char c : opt.parsed()) {
+ switch(c) {
+ case 'p':
+ {
+ InputStream in = new FileInputStream(opt.arg);
+ try {
+ props.load(in);
+ } finally {
+ in.close();
+ }
+ }
+ break;
+ case 'n':
+ props.put("jsvc.j2ee.appname", opt.arg);
+ break;
+ case 'h':
+ usage(System.out);
+ return;
+ }
+ }
+
+ OutputStream out = new FileOutputStream(war);
+ try {
+ makewar(jars, props, out);
+ } finally {
+ out.close();
+ }
+ }
+}
--- /dev/null
+package dolda.jsvc.j2ee;
+
+import java.util.*;
+
+public class PosixArgs {
+ private List<Arg> parsed;
+ public String[] rest;
+ public String arg = null;
+
+ private static class Arg {
+ private char ch;
+ private String arg;
+
+ private Arg(char ch, String arg) {
+ this.ch = ch;
+ this.arg = arg;
+ }
+ }
+
+ private PosixArgs() {
+ parsed = new ArrayList<Arg>();
+ }
+
+ public static PosixArgs getopt(String[] argv, int start, String desc) {
+ PosixArgs ret = new PosixArgs();
+ List<Character> fl = new ArrayList<Character>(), fla = new ArrayList<Character>();
+ List<String> rest = new ArrayList<String>();
+ for(int i = 0; i < desc.length();) {
+ char ch = desc.charAt(i++);
+ if((i < desc.length()) && (desc.charAt(i) == ':')) {
+ i++;
+ fla.add(ch);
+ } else {
+ fl.add(ch);
+ }
+ }
+ boolean acc = true;
+ for(int i = start; i < argv.length;) {
+ String arg = argv[i++];
+ if(acc && arg.equals("--")) {
+ acc = false;
+ } if(acc && (arg.charAt(0) == '-')) {
+ for(int o = 1; o < arg.length();) {
+ char ch = arg.charAt(o++);
+ if(fl.contains(ch)) {
+ ret.parsed.add(new Arg(ch, null));
+ } else if(fla.contains(ch)) {
+ if(o < arg.length()) {
+ ret.parsed.add(new Arg(ch, arg.substring(o)));
+ break;
+ } else if(i < argv.length) {
+ ret.parsed.add(new Arg(ch, argv[i++]));
+ break;
+ } else {
+ System.err.println("option requires an argument -- '" + ch + "'");
+ return(null);
+ }
+ } else {
+ System.err.println("invalid option -- '" + ch + "'");
+ return(null);
+ }
+ }
+ } else {
+ rest.add(arg);
+ }
+ }
+ ret.rest = rest.toArray(new String[0]);
+ return(ret);
+ }
+
+ public static PosixArgs getopt(String[] argv, String desc) {
+ return(getopt(argv, 0, desc));
+ }
+
+ public Iterable<Character> parsed() {
+ return(new Iterable<Character>() {
+ public Iterator<Character> iterator() {
+ return(new Iterator<Character>() {
+ private int i = 0;
+
+ public boolean hasNext() {
+ return(i < parsed.size());
+ }
+
+ public Character next() {
+ if(i >= parsed.size())
+ throw(new NoSuchElementException());
+ Arg a = parsed.get(i++);
+ arg = a.arg;
+ return(a.ch);
+ }
+
+ public void remove() {
+ throw(new UnsupportedOperationException());
+ }
+ });
+ }
+ });
+ }
+}