Moved WAR making to an explicit function.
[jsvc.git] / src / dolda / jsvc / j2ee / Archive.java
1 package dolda.jsvc.j2ee;
2
3 import java.util.*;
4 import java.io.*;
5 import java.net.*;
6 import java.util.zip.*;
7 import java.util.jar.*;
8
9 public class Archive {
10     private static void usage(PrintStream out) {
11         out.println("usage: dolda.jsvc.j2ee.Archive [-h] [-p PROPFILE] [-n DISPLAY-NAME] WAR-FILE JAR-FILE...");
12     }
13     
14     private static void jarprops(String[] jars, String propres, Properties props) throws IOException {
15         URL[] urls = new URL[jars.length];
16         try {
17             for(int i = 0; i < jars.length; i++)
18                 urls[i] = new URL("file", "", jars[i]);
19         } catch(MalformedURLException e) {
20             throw(new Error(e));
21         }
22         ClassLoader cl = new URLClassLoader(urls);
23         InputStream in = cl.getResourceAsStream(propres);
24         if(in != null) {
25             try {
26                 props.load(in);
27             } finally {
28                 in.close();
29             }
30         }
31     }
32
33     private static Properties defprops() {
34         Properties props = new Properties();
35         props.put("jsvc.j2ee.webxml.coding", "UTF-8");
36         return(props);
37     }
38
39     private static void cpstream(InputStream in, OutputStream out) throws IOException {
40         byte[] buf = new byte[4096];
41         while(true) {
42             int ret = in.read(buf, 0, buf.length);
43             if(ret < 0)
44                 return;
45             out.write(buf, 0, ret);
46         }
47     }
48
49     private static String subst(String ln, Properties props) {
50         int p = 0;
51         while((p = ln.indexOf("${", p)) >= 0) {
52             int p2 = ln.indexOf('}', p + 2);
53             String pn = ln.substring(p + 2, p2);
54             String pv = (String)props.get(pn);
55             if(pv == null)
56                 throw(new RuntimeException("Missing required property " + pn));
57             ln = ln.substring(0, p) + pv + ln.substring(p2 + 1);
58             p = p + pv.length();
59         }
60         return(ln);
61     }
62
63     private static void writewebxml(Properties props, OutputStream out) throws IOException {
64         InputStream tmpl = Archive.class.getResourceAsStream("web.xml.template");
65         String cs = (String)props.get("jsvc.j2ee.webxml.coding");
66         try {
67             BufferedReader r = new BufferedReader(new InputStreamReader(tmpl, "US-ASCII"));
68             BufferedWriter w = new BufferedWriter(new OutputStreamWriter(out, cs));
69             String ln;
70             while((ln = r.readLine()) != null) {
71                 w.write(subst(ln, props));
72                 w.write('\n');
73             }
74             w.flush();
75         } finally {
76             tmpl.close();
77         }
78     }
79     
80     public static void makewar(String[] jars, Properties props, OutputStream out) throws IOException {
81         Manifest man = new Manifest();
82         man.getMainAttributes().put(new Attributes.Name("Manifest-Version"), "1.0");
83         man.getMainAttributes().put(new Attributes.Name("Created-By"), "jsvc");
84         JarOutputStream zip = new JarOutputStream(out, man);
85         zip.putNextEntry(new ZipEntry("WEB-INF/"));
86         zip.putNextEntry(new ZipEntry("WEB-INF/lib/"));
87         for(String jar : jars) {
88             String bn = jar;
89             int p = bn.lastIndexOf('/');
90             if(p >= 0)
91                 bn = bn.substring(p + 1);
92             zip.putNextEntry(new ZipEntry("WEB-INF/lib/" + bn));
93             InputStream jarin = new FileInputStream(jar);
94             try {
95                 cpstream(jarin, zip);
96             } finally {
97                 jarin.close();
98             }
99         }
100         zip.putNextEntry(new ZipEntry("WEB-INF/web.xml"));
101         writewebxml(props, zip);
102         zip.finish();
103     }
104
105     public static void main(String[] args) throws IOException {
106         PosixArgs opt = PosixArgs.getopt(args, "hp:n:");
107         if(opt == null) {
108             usage(System.err);
109             System.exit(1);
110         }
111         if(opt.rest.length < 2) {
112             usage(System.err);
113             System.exit(1);
114         }
115         String war = opt.rest[0];
116         String[] jars = Arrays.copyOfRange(opt.rest, 1, opt.rest.length);
117         
118         Properties props = defprops();
119         jarprops(jars, "/jsvc.properties", props);
120         
121         for(char c : opt.parsed()) {
122             switch(c) {
123             case 'p':
124                 {
125                     InputStream in = new FileInputStream(opt.arg);
126                     try {
127                         props.load(in);
128                     } finally {
129                         in.close();
130                     }
131                 }
132                 break;
133             case 'n':
134                 props.put("jsvc.j2ee.appname", opt.arg);
135                 break;
136             case 'h':
137                 usage(System.out);
138                 return;
139             }
140         }
141         
142         OutputStream out = new FileOutputStream(war);
143         try {
144             makewar(jars, props, out);
145         } finally {
146             out.close();
147         }
148     }
149 }