From f179d8ba3acb55d1419a9de851d0fcf996798cc4 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Mon, 12 Oct 2009 17:54:44 +0200 Subject: [PATCH] Moved WAR making to an explicit function. --- build.xml | 18 +---- www/web.xml => etc/web.xml.template | 4 +- src/dolda/jsvc/j2ee/Archive.java | 149 ++++++++++++++++++++++++++++++++++++ src/dolda/jsvc/j2ee/PosixArgs.java | 100 ++++++++++++++++++++++++ 4 files changed, 252 insertions(+), 19 deletions(-) rename www/web.xml => etc/web.xml.template (79%) create mode 100644 src/dolda/jsvc/j2ee/Archive.java create mode 100644 src/dolda/jsvc/j2ee/PosixArgs.java diff --git a/build.xml b/build.xml index 0e6d4e6..43314b9 100644 --- a/build.xml +++ b/build.xml @@ -13,8 +13,6 @@ - - @@ -22,27 +20,13 @@ + - - - - - - - - - - - - diff --git a/www/web.xml b/etc/web.xml.template similarity index 79% rename from www/web.xml rename to etc/web.xml.template index e2e5908..487cdd8 100644 --- a/www/web.xml +++ b/etc/web.xml.template @@ -1,4 +1,4 @@ - + - JSvc-wrapping + ${jsvc.j2ee.appname} jsvc diff --git a/src/dolda/jsvc/j2ee/Archive.java b/src/dolda/jsvc/j2ee/Archive.java new file mode 100644 index 0000000..ee9f26e --- /dev/null +++ b/src/dolda/jsvc/j2ee/Archive.java @@ -0,0 +1,149 @@ +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(); + } + } +} diff --git a/src/dolda/jsvc/j2ee/PosixArgs.java b/src/dolda/jsvc/j2ee/PosixArgs.java new file mode 100644 index 0000000..4a23941 --- /dev/null +++ b/src/dolda/jsvc/j2ee/PosixArgs.java @@ -0,0 +1,100 @@ +package dolda.jsvc.j2ee; + +import java.util.*; + +public class PosixArgs { + private List 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(); + } + + public static PosixArgs getopt(String[] argv, int start, String desc) { + PosixArgs ret = new PosixArgs(); + List fl = new ArrayList(), fla = new ArrayList(); + List rest = new ArrayList(); + 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 parsed() { + return(new Iterable() { + public Iterator iterator() { + return(new Iterator() { + 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()); + } + }); + } + }); + } +} -- 2.11.0