Commit | Line | Data |
---|---|---|
f179d8ba FT |
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 { | |
5f3753cb FT |
10 | private Properties props = defprops(); |
11 | private JarOutputStream zipout = null; | |
12 | private final OutputStream realout; | |
13 | ||
14 | public Archive(OutputStream out) { | |
15 | this.realout = out; | |
16 | } | |
17 | ||
18 | private void initzip() throws IOException { | |
19 | Manifest man = new Manifest(); | |
20 | man.getMainAttributes().put(new Attributes.Name("Manifest-Version"), "1.0"); | |
21 | man.getMainAttributes().put(new Attributes.Name("Created-By"), "jsvc"); | |
22 | JarOutputStream zip = new JarOutputStream(realout, man); | |
23 | zip.putNextEntry(new ZipEntry("WEB-INF/")); | |
24 | zip.putNextEntry(new ZipEntry("WEB-INF/lib/")); | |
25 | this.zipout = zip; | |
26 | } | |
27 | ||
28 | private ZipOutputStream zip() throws IOException { | |
29 | if(zipout == null) | |
30 | initzip(); | |
31 | return(this.zipout); | |
f179d8ba FT |
32 | } |
33 | ||
5f3753cb FT |
34 | public void putprop(String key, String val) { |
35 | props.put(key, val); | |
36 | } | |
37 | ||
38 | public void loadprops(InputStream in) throws IOException { | |
39 | props.load(in); | |
40 | } | |
41 | ||
42 | public void jarprops(String[] jars, String propres) throws IOException { | |
f179d8ba FT |
43 | URL[] urls = new URL[jars.length]; |
44 | try { | |
45 | for(int i = 0; i < jars.length; i++) | |
46 | urls[i] = new URL("file", "", jars[i]); | |
47 | } catch(MalformedURLException e) { | |
48 | throw(new Error(e)); | |
49 | } | |
50 | ClassLoader cl = new URLClassLoader(urls); | |
51 | InputStream in = cl.getResourceAsStream(propres); | |
52 | if(in != null) { | |
53 | try { | |
54 | props.load(in); | |
55 | } finally { | |
56 | in.close(); | |
57 | } | |
58 | } | |
59 | } | |
60 | ||
61 | private static Properties defprops() { | |
62 | Properties props = new Properties(); | |
63 | props.put("jsvc.j2ee.webxml.coding", "UTF-8"); | |
64 | return(props); | |
65 | } | |
66 | ||
67 | private static void cpstream(InputStream in, OutputStream out) throws IOException { | |
68 | byte[] buf = new byte[4096]; | |
69 | while(true) { | |
70 | int ret = in.read(buf, 0, buf.length); | |
71 | if(ret < 0) | |
72 | return; | |
73 | out.write(buf, 0, ret); | |
74 | } | |
75 | } | |
76 | ||
77 | private static String subst(String ln, Properties props) { | |
78 | int p = 0; | |
79 | while((p = ln.indexOf("${", p)) >= 0) { | |
80 | int p2 = ln.indexOf('}', p + 2); | |
81 | String pn = ln.substring(p + 2, p2); | |
82 | String pv = (String)props.get(pn); | |
83 | if(pv == null) | |
84 | throw(new RuntimeException("Missing required property " + pn)); | |
85 | ln = ln.substring(0, p) + pv + ln.substring(p2 + 1); | |
86 | p = p + pv.length(); | |
87 | } | |
88 | return(ln); | |
89 | } | |
90 | ||
5f3753cb FT |
91 | private void writewebxml() throws IOException { |
92 | zip().putNextEntry(new ZipEntry("WEB-INF/web.xml")); | |
f179d8ba FT |
93 | InputStream tmpl = Archive.class.getResourceAsStream("web.xml.template"); |
94 | String cs = (String)props.get("jsvc.j2ee.webxml.coding"); | |
95 | try { | |
96 | BufferedReader r = new BufferedReader(new InputStreamReader(tmpl, "US-ASCII")); | |
5f3753cb | 97 | BufferedWriter w = new BufferedWriter(new OutputStreamWriter(zip(), cs)); |
f179d8ba FT |
98 | String ln; |
99 | while((ln = r.readLine()) != null) { | |
100 | w.write(subst(ln, props)); | |
101 | w.write('\n'); | |
102 | } | |
103 | w.flush(); | |
104 | } finally { | |
105 | tmpl.close(); | |
106 | } | |
107 | } | |
108 | ||
5f3753cb FT |
109 | public void addcode(String name, InputStream in) throws IOException { |
110 | zip().putNextEntry(new ZipEntry("WEB-INF/classes/" + name)); | |
111 | cpstream(in, zip()); | |
112 | } | |
113 | ||
114 | private static String basename(String fn) { | |
115 | int p = fn.lastIndexOf('/'); | |
116 | if(p >= 0) | |
117 | return(fn.substring(p + 1)); | |
118 | return(fn); | |
119 | } | |
120 | ||
121 | public void addjars(String[] jars) throws IOException { | |
104fa785 | 122 | jarprops(jars, "jsvc.properties"); |
5f3753cb | 123 | ZipOutputStream zip = zip(); |
f179d8ba | 124 | for(String jar : jars) { |
5f3753cb | 125 | zip.putNextEntry(new ZipEntry("WEB-INF/lib/" + basename(jar))); |
f179d8ba FT |
126 | InputStream jarin = new FileInputStream(jar); |
127 | try { | |
128 | cpstream(jarin, zip); | |
129 | } finally { | |
130 | jarin.close(); | |
131 | } | |
132 | } | |
f179d8ba FT |
133 | } |
134 | ||
5f3753cb FT |
135 | public void finish() throws IOException { |
136 | zip().finish(); | |
137 | } | |
138 | ||
139 | private static void usage(PrintStream out) { | |
140 | out.println("usage: dolda.jsvc.j2ee.Archive [-h] [-p PROPFILE] [-n DISPLAY-NAME] [(-c CODE-FILE)...] WAR-FILE JAR-FILE..."); | |
141 | } | |
142 | ||
f179d8ba | 143 | public static void main(String[] args) throws IOException { |
5f3753cb | 144 | PosixArgs opt = PosixArgs.getopt(args, "hp:n:c:"); |
f179d8ba FT |
145 | if(opt == null) { |
146 | usage(System.err); | |
147 | System.exit(1); | |
148 | } | |
149 | if(opt.rest.length < 2) { | |
150 | usage(System.err); | |
151 | System.exit(1); | |
152 | } | |
153 | String war = opt.rest[0]; | |
154 | String[] jars = Arrays.copyOfRange(opt.rest, 1, opt.rest.length); | |
155 | ||
5f3753cb FT |
156 | OutputStream out = new FileOutputStream(war); |
157 | try { | |
158 | Archive ar = new Archive(out); | |
f179d8ba | 159 | |
5f3753cb FT |
160 | for(char c : opt.parsed()) { |
161 | switch(c) { | |
162 | case 'p': | |
163 | { | |
164 | InputStream in = new FileInputStream(opt.arg); | |
165 | try { | |
166 | ar.loadprops(in); | |
167 | } finally { | |
168 | in.close(); | |
169 | } | |
170 | } | |
171 | break; | |
172 | case 'n': | |
173 | ar.putprop("jsvc.j2ee.appname", opt.arg); | |
174 | break; | |
175 | case 'c': | |
176 | { | |
177 | InputStream in = new FileInputStream(opt.arg); | |
178 | try { | |
179 | ar.addcode(basename(opt.arg), in); | |
180 | } finally { | |
181 | in.close(); | |
182 | } | |
f179d8ba | 183 | } |
5f3753cb FT |
184 | break; |
185 | case 'h': | |
186 | usage(System.out); | |
187 | return; | |
f179d8ba | 188 | } |
f179d8ba | 189 | } |
5f3753cb FT |
190 | |
191 | ar.addjars(jars); | |
192 | ar.writewebxml(); | |
193 | ||
194 | ar.finish(); | |
f179d8ba FT |
195 | } finally { |
196 | out.close(); | |
197 | } | |
198 | } | |
199 | } |