1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.eclipse.jetty.osgi.boot.warurl.internal;
16
17 import java.net.URL;
18 import java.util.ArrayList;
19 import java.util.Enumeration;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map.Entry;
23 import java.util.jar.Attributes;
24 import java.util.jar.JarEntry;
25 import java.util.jar.JarFile;
26 import java.util.jar.Manifest;
27
28 import org.eclipse.jetty.util.MultiMap;
29 import org.eclipse.jetty.util.UrlEncoded;
30 import org.osgi.framework.Constants;
31
32 public class WarBundleManifestGenerator
33 {
34
35
36 private static final String MISSING_VERSION = "0.0.1.unknown";
37 private static final String MISSING_MANIFEST_VERSION = "2";
38
39 public static Manifest createBundleManifest(Manifest originalManifest, URL url, JarFile jarFile)
40 {
41 Manifest res = new Manifest();
42 res.getMainAttributes().putAll(
43 createBundleManifest(originalManifest.getMainAttributes(),
44 url.toString(), jarFile));
45 return res;
46 }
47
48
49 private static Attributes createBundleManifest(Attributes originalManifest, String url, JarFile jarFile)
50 {
51 HashMap<String, String> res = new HashMap<String, String>();
52 for (Entry<Object, Object> entries : originalManifest.entrySet())
53 {
54 res.put(entries.getKey().toString(),String.valueOf(entries.getValue()));
55 }
56 MultiMap<String> params = parseQueryString(url);
57
58
59 String version = params.getString(Constants.BUNDLE_VERSION);
60 if (version != null)
61 {
62 res.put(Constants.BUNDLE_VERSION, version);
63 }
64 else
65 {
66 String versionInManifest = (String) res.get(Constants.BUNDLE_VERSION);
67 if (versionInManifest == null)
68 {
69 res.put(Constants.BUNDLE_VERSION, MISSING_VERSION);
70 }
71 }
72
73
74 String manversion = params.getString(Constants.BUNDLE_MANIFESTVERSION);
75 if (manversion != null)
76 {
77 res.put(Constants.BUNDLE_MANIFESTVERSION, manversion);
78 }
79 else
80 {
81 int manv = 2;
82 try {
83 String versionInManifest = (String) res.get(Constants.BUNDLE_MANIFESTVERSION);
84 if (versionInManifest != null)
85 {
86 manv = Integer.parseInt(versionInManifest.trim());
87 }
88 }
89 catch (NumberFormatException nfe)
90 {
91
92 }
93 res.put(Constants.BUNDLE_MANIFESTVERSION, String.valueOf( manv < 2 ? 2 : manv ));
94 }
95
96
97 String symbname = params.getString(Constants.BUNDLE_SYMBOLICNAME);
98 if (symbname != null)
99 {
100 res.put(Constants.BUNDLE_SYMBOLICNAME, symbname);
101 }
102 else
103 {
104 symbname = (String) res.get(Constants.BUNDLE_SYMBOLICNAME);
105 if (symbname == null)
106 {
107
108 int lastSlash = url.lastIndexOf('/');
109 int beforeQueryString = url.indexOf(lastSlash, '?');
110 if (beforeQueryString == -1)
111 {
112 beforeQueryString = url.indexOf(lastSlash, '#');
113 if (beforeQueryString == -1)
114 {
115 beforeQueryString = url.length();
116 }
117 }
118 symbname = url.substring(lastSlash+1, beforeQueryString);
119
120 res.put(Constants.BUNDLE_SYMBOLICNAME, symbname);
121 }
122 }
123
124
125 String extraBundleClasspath = params.getString(Constants.BUNDLE_CLASSPATH);
126 String alreadyBundleClasspath = res.get(Constants.BUNDLE_CLASSPATH);
127 if (alreadyBundleClasspath == null)
128 {
129 StringBuilder bundleClasspath = new StringBuilder();
130 if (jarFile == null || jarFile.getJarEntry("WEB-INF/classes/") != null)
131 {
132 bundleClasspath.append("WEB-INF/classes");
133 }
134 if (jarFile != null)
135 {
136 List<String> libs = getJarsInWebInfLib(jarFile);
137 if (extraBundleClasspath != null)
138 {
139 libs.add(extraBundleClasspath);
140 }
141 for (String lib : libs)
142 {
143 if (bundleClasspath.length() != 0)
144 {
145 bundleClasspath.append(",");
146 }
147 bundleClasspath.append(lib);
148 }
149 }
150 alreadyBundleClasspath = bundleClasspath.toString();
151 }
152
153
154
155
156
157
158 res.put(Constants.BUNDLE_CLASSPATH,
159 alreadyBundleClasspath + (extraBundleClasspath == null ? "" : "," + extraBundleClasspath ));
160
161
162 String extraImportPackage = params.getString(Constants.IMPORT_PACKAGE);
163 String alreadyImportPackage = res.get(Constants.IMPORT_PACKAGE);
164 if (alreadyImportPackage == null)
165 {
166
167
168 alreadyImportPackage = "javax.servlet; version=\"2.5\"," +
169 "javax.servlet.http;version=\"2.5\"," +
170 "javax.el;version=\"1.0\"" +
171 "javax.jsp;version=\"2.1\";resolution:=optional," +
172 "javax.jsp.tagext;version=\"2.1\";resolution:=optional";
173
174 }
175 if (extraImportPackage != null)
176 {
177
178
179
180
181 res.put(Constants.IMPORT_PACKAGE,
182 (alreadyImportPackage == null ? "" : alreadyImportPackage + ",") +
183 extraImportPackage);
184 }
185
186
187 String extraExportPackage = params.getString(Constants.EXPORT_PACKAGE);
188 String alreadyExportPackage = res.get(Constants.EXPORT_PACKAGE);
189 if (extraExportPackage != null)
190 {
191
192
193
194 res.put(Constants.EXPORT_PACKAGE,
195 (alreadyExportPackage == null ? "" : alreadyExportPackage + ",") +
196 extraImportPackage);
197 }
198
199
200 String webContextPath = params.getString("Web-ContextPath");
201 if (webContextPath != null)
202 {
203 res.put("Web-ContextPath", webContextPath);
204 }
205 else
206 {
207 webContextPath = res.get("Web-ContextPath");
208 if (webContextPath == null)
209 {
210
211 if (symbname.endsWith(".war"))
212 {
213 webContextPath = "/" + symbname.substring(0, symbname.length()-".war".length());
214 }
215 else
216 {
217 webContextPath = "/" + symbname;
218 }
219 res.put("Web-ContextPath", webContextPath);
220 }
221 }
222
223
224 String jspExtractLocation = params.getString("Web-JSPExtractLocation");
225 if (jspExtractLocation != null)
226 {
227 res.put("Web-JSPExtractLocation", jspExtractLocation);
228 }
229 else
230 {
231
232 }
233 Attributes newAttrs = new Attributes();
234 for (Entry<String,String> e : res.entrySet())
235 {
236 newAttrs.putValue(e.getKey(),e.getValue());
237 }
238 return newAttrs;
239 }
240
241
242
243
244
245 private static MultiMap<String> parseQueryString(String url)
246 {
247 MultiMap<String> res = new MultiMap<String>();
248 int questionMarkIndex = url.indexOf('?');
249 if (questionMarkIndex == -1)
250 {
251 return res;
252 }
253 int poundIndex = url.indexOf('#');
254 if (poundIndex == -1)
255 {
256 poundIndex = url.length();
257 }
258 UrlEncoded.decodeUtf8To(url.getBytes(), questionMarkIndex+1,
259 poundIndex - questionMarkIndex - 1, res);
260 return res;
261 }
262
263 private static List<String> getJarsInWebInfLib(JarFile jarFile)
264 {
265 List<String> res = new ArrayList<String>();
266 Enumeration<JarEntry> en = jarFile.entries();
267 while (en.hasMoreElements())
268 {
269 JarEntry e = en.nextElement();
270 if (e.getName().startsWith("WEB-INF/lib/") && e.getName().endsWith(".jar"))
271 {
272 res.add(e.getName());
273 }
274 }
275 return res;
276 }
277
278
279 }