Added
Link Here
|
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
4 |
* Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
5 |
* |
6 |
* The contents of this file are subject to the terms of either the GNU |
7 |
* General Public License Version 2 only ("GPL") (the |
8 |
* "License"). You may not use this file except in compliance with the |
9 |
* License. |
10 |
* |
11 |
* Contributor(s): |
12 |
* |
13 |
* The Original Software is NetBeans. The Initial Developer of the Original |
14 |
* Software is Sun Microsystems, Inc. Portions Copyright 2009 Sun |
15 |
* Microsystems, Inc. All Rights Reserved. |
16 |
* |
17 |
* Jaroslav Tulach elects to include this software in this distribution |
18 |
* under the GPL Version 2 license. |
19 |
*/ |
20 |
|
21 |
package org.netbeans; |
22 |
|
23 |
import java.io.ByteArrayOutputStream; |
24 |
import java.io.File; |
25 |
import java.io.FileInputStream; |
26 |
import java.io.FileNotFoundException; |
27 |
import java.io.FileOutputStream; |
28 |
import java.io.IOException; |
29 |
import java.io.InputStream; |
30 |
import java.io.OutputStream; |
31 |
import java.util.ArrayList; |
32 |
import java.util.Arrays; |
33 |
import java.util.Iterator; |
34 |
import java.util.List; |
35 |
import java.util.Locale; |
36 |
import java.util.Map; |
37 |
import java.util.jar.JarEntry; |
38 |
import java.util.jar.JarOutputStream; |
39 |
import java.util.jar.Manifest; |
40 |
import java.util.logging.Level; |
41 |
import java.util.zip.CRC32; |
42 |
import javax.tools.JavaCompiler; |
43 |
import javax.tools.StandardJavaFileManager; |
44 |
import javax.tools.ToolProvider; |
45 |
import org.netbeans.junit.NbTestCase; |
46 |
|
47 |
/** Some infrastructure for module system tests. |
48 |
* @author Jesse Glick |
49 |
*/ |
50 |
public abstract class SetupHid extends NbTestCase { |
51 |
|
52 |
|
53 |
public SetupHid(String name) { |
54 |
super(name); |
55 |
} |
56 |
|
57 |
/** directory of data files for JARs */ |
58 |
protected File data; |
59 |
/** directory full of JAR files to test */ |
60 |
protected File jars; |
61 |
/** shall the generated JARs have all dir entries? */ |
62 |
protected static boolean generateAllDirs; |
63 |
|
64 |
protected @Override void setUp() throws Exception { |
65 |
Locale.setDefault(Locale.US); |
66 |
clearWorkDir(); |
67 |
data = new File(getDataDir(), "jars"); |
68 |
jars = new File(getWorkDir(), "jars"); |
69 |
jars.mkdirs(); |
70 |
createTestJARs(); |
71 |
|
72 |
File ud = new File(getWorkDir(), "ud"); |
73 |
ud.mkdirs(); |
74 |
|
75 |
System.setProperty("netbeans.user", ud.getPath()); |
76 |
} |
77 |
|
78 |
@Override |
79 |
protected Level logLevel() { |
80 |
return Level.FINE; |
81 |
} |
82 |
|
83 |
protected static void deleteRec(File f) throws IOException { |
84 |
if (f.isDirectory()) { |
85 |
File[] kids = f.listFiles(); |
86 |
if (kids == null) throw new IOException("Could not list: " + f); |
87 |
for (int i = 0; i < kids.length; i++) { |
88 |
deleteRec(kids[i]); |
89 |
} |
90 |
} |
91 |
if (! f.delete()) throw new IOException("Could not delete: " + f); |
92 |
} |
93 |
|
94 |
/** same as FileUtil.copy */ |
95 |
protected static void copyStreams(InputStream is, OutputStream os) throws IOException { |
96 |
final byte[] BUFFER = new byte[4096]; |
97 |
int len; |
98 |
for (;;) { |
99 |
len = is.read(BUFFER); |
100 |
if (len == -1) { |
101 |
return; |
102 |
} |
103 |
os.write(BUFFER, 0, len); |
104 |
} |
105 |
} |
106 |
|
107 |
protected static void copy(File a, File b) throws IOException { |
108 |
OutputStream os = new FileOutputStream(b); |
109 |
try { |
110 |
copyStreams(new FileInputStream(a), os); |
111 |
} finally { |
112 |
os.close(); |
113 |
} |
114 |
} |
115 |
|
116 |
/** |
117 |
* Create a fresh JAR file. |
118 |
* @param jar the file to create |
119 |
* @param contents keys are JAR entry paths, values are text contents (will be written in UTF-8) |
120 |
* @param manifest a manifest to store (key/value pairs for main section) |
121 |
*/ |
122 |
public static void createJar(File jar, Map<String,String> contents, Map<String,String> manifest) throws IOException { |
123 |
// XXX use TestFileUtils.writeZipFile |
124 |
Manifest m = new Manifest(); |
125 |
m.getMainAttributes().putValue("Manifest-Version", "1.0"); // workaround for JDK bug |
126 |
for (Map.Entry<String,String> line : manifest.entrySet()) { |
127 |
m.getMainAttributes().putValue(line.getKey(), line.getValue()); |
128 |
} |
129 |
jar.getParentFile().mkdirs(); |
130 |
OutputStream os = new FileOutputStream(jar); |
131 |
try { |
132 |
JarOutputStream jos = new JarOutputStream(os, m); |
133 |
Iterator it = contents.entrySet().iterator(); |
134 |
while (it.hasNext()) { |
135 |
Map.Entry entry = (Map.Entry) it.next(); |
136 |
String path = (String) entry.getKey(); |
137 |
byte[] data = ((String) entry.getValue()).getBytes("UTF-8"); |
138 |
JarEntry je = new JarEntry(path); |
139 |
je.setSize(data.length); |
140 |
CRC32 crc = new CRC32(); |
141 |
crc.update(data); |
142 |
je.setCrc(crc.getValue()); |
143 |
jos.putNextEntry(je); |
144 |
jos.write(data); |
145 |
} |
146 |
jos.close(); |
147 |
} finally { |
148 |
os.close(); |
149 |
} |
150 |
} |
151 |
|
152 |
private void createTestJARs() throws IOException { |
153 |
File simpleModule = createTestJAR("simple-module", null); |
154 |
File dependsOnSimpleModule = createTestJAR("depends-on-simple-module", null, simpleModule); |
155 |
createTestJAR("dep-on-dep-on-simple", null, simpleModule, dependsOnSimpleModule); |
156 |
File cyclic1; |
157 |
{ // cyclic-1 |
158 |
File cyclic1Src = new File(data, "cyclic-1"); |
159 |
File cyclic2Src = new File(data, "cyclic-2"); |
160 |
compile(Arrays.asList( |
161 |
"-sourcepath", cyclic1Src + File.pathSeparator + cyclic2Src, |
162 |
"-d", cyclic1Src.getAbsolutePath()), |
163 |
findSourceFiles(cyclic1Src, cyclic2Src)); |
164 |
cyclic1 = new File(jars, "cyclic-1.jar"); |
165 |
OutputStream os = new FileOutputStream(cyclic1); |
166 |
try { |
167 |
JarOutputStream jos = new JarOutputStream(os, loadManifest(new File(data, "cyclic-1.mf"))); |
168 |
try { |
169 |
jarUp(jos, new File(cyclic1Src, "org/foo"), "org/foo/"); |
170 |
} finally { |
171 |
jos.close(); |
172 |
} |
173 |
} finally { |
174 |
os.close(); |
175 |
} |
176 |
} |
177 |
File cyclic2 = createTestJAR("cyclic-2", null, cyclic1); |
178 |
createTestJAR("depends-on-cyclic-1", null, cyclic1, cyclic2); |
179 |
File libraryUndecl = createTestJAR("library-undecl", "library-src"); |
180 |
createTestJAR("library-unvers", "library-src"); |
181 |
createTestJAR("library-vers", "library-src"); |
182 |
createTestJAR("library-vers-partial", "library-src"); |
183 |
createTestJAR("depends-on-lib-undecl", "depends-on-library-src", libraryUndecl); |
184 |
createTestJAR("depends-on-lib-unvers", "depends-on-library-src", libraryUndecl); |
185 |
createTestJAR("depends-on-lib-vers", "depends-on-library-src", libraryUndecl); |
186 |
createTestJAR("depends-on-lib-vers-partial", "depends-on-library-src", libraryUndecl); |
187 |
createTestJAR("fails-on-lib-undecl", "depends-on-library-src", libraryUndecl); |
188 |
createTestJAR("fails-on-non-existing-package", "depends-on-library-src", libraryUndecl); |
189 |
createTestJAR("fails-on-lib-unvers", "depends-on-library-src", libraryUndecl); |
190 |
createTestJAR("fails-on-lib-old", "depends-on-library-src", libraryUndecl); |
191 |
createTestJAR("prov-foo", null); |
192 |
createTestJAR("req-foo", null); |
193 |
createTestJAR("prov-foo-bar", null); |
194 |
createTestJAR("req-foo-baz", null); |
195 |
createTestJAR("prov-baz", null); |
196 |
createTestJAR("prov-foo-req-bar", null); |
197 |
createTestJAR("prov-bar-req-foo", null); |
198 |
createTestJAR("prov-bar-dep-cyclic", null); |
199 |
createTestJAR("rel-ver-2", null); |
200 |
createTestJAR("dep-on-relvertest-1", null); |
201 |
createTestJAR("dep-on-relvertest-1-2", null); |
202 |
createTestJAR("dep-on-relvertest-1-2-nospec", null); |
203 |
createTestJAR("dep-on-relvertest-2", null); |
204 |
createTestJAR("dep-on-relvertest-2-3", null); |
205 |
createTestJAR("dep-on-relvertest-2-3-late", null); |
206 |
createTestJAR("dep-on-relvertest-2-impl", null); |
207 |
createTestJAR("dep-on-relvertest-2-impl-wrong", null); |
208 |
createTestJAR("dep-on-relvertest-2-late", null); |
209 |
createTestJAR("dep-on-relvertest-3-4", null); |
210 |
createTestJAR("dep-on-relvertest-some", null); |
211 |
createTestJAR("depends-on-simple-module-2", null); |
212 |
createTestJAR("needs-foo", null); |
213 |
createTestJAR("recommends-foo", null); |
214 |
createTestJAR("prov-foo-depends-needs_foo", "prov-foo"); |
215 |
createTestJAR("api-mod-export-all", "exposes-api"); |
216 |
createTestJAR("api-mod-export-none", "exposes-api"); |
217 |
File exposesAPI = createTestJAR("api-mod-export-api", "exposes-api"); |
218 |
createTestJAR("api-mod-export-friend", "exposes-api"); |
219 |
createTestJAR("uses-api-simple-dep", "uses-api", exposesAPI); |
220 |
createTestJAR("uses-api-impl-dep", "uses-api", exposesAPI); |
221 |
createTestJAR("uses-api-impl-dep-for-friends", "uses-api", exposesAPI); |
222 |
createTestJAR("uses-api-spec-dep", "uses-api", exposesAPI); |
223 |
createTestJAR("dep-on-two-modules", null); |
224 |
File usesAPI = createTestJAR("uses-and-exports-api", "uses-api", exposesAPI); |
225 |
createTestJAR("uses-api-transitively", null, exposesAPI, usesAPI); |
226 |
createTestJAR("uses-api-directly", "uses-api-transitively", exposesAPI, usesAPI); |
227 |
createTestJAR("uses-api-transitively-old", "uses-api-transitively", exposesAPI, usesAPI); |
228 |
createTestJAR("uses-api-directly-old", "uses-api-transitively", exposesAPI, usesAPI); |
229 |
createTestJAR("look-for-myself", null); |
230 |
createTestJAR("uses-api-friend", "uses-api", exposesAPI); |
231 |
createTestJAR("little-manifest", null); |
232 |
createTestJAR("medium-manifest", null); |
233 |
createTestJAR("big-manifest", null); |
234 |
createTestJAR("patchable", null); |
235 |
{ // Make the patch JAR specially: |
236 |
File src = new File(data, "patch"); |
237 |
String srcS = src.getAbsolutePath(); |
238 |
compile(Arrays.asList("-sourcepath", srcS, "-d", srcS), findSourceFiles(src)); |
239 |
File jar = new File(jars, "patches/pkg-subpkg/some-patch.jar"); |
240 |
jar.getParentFile().mkdirs(); |
241 |
OutputStream os = new FileOutputStream(jar); |
242 |
try { |
243 |
JarOutputStream jos = new JarOutputStream(os, loadManifest(null)); |
244 |
try { |
245 |
jarUp(jos, src, ""); |
246 |
} finally { |
247 |
jos.close(); |
248 |
} |
249 |
} finally { |
250 |
os.close(); |
251 |
} |
252 |
} |
253 |
File locale = new File(jars, "locale"); |
254 |
locale.mkdirs(); |
255 |
{ |
256 |
OutputStream os = new FileOutputStream(new File(jars, "localized-manifest.jar")); |
257 |
try { |
258 |
JarOutputStream jos = new JarOutputStream(os, loadManifest(new File(data, "localized-manifest.mf"))); |
259 |
try { |
260 |
writeJarEntry(jos, "locmani/Bundle.properties", new File(data, "localized-manifest/locmani/Bundle.properties")); |
261 |
} finally { |
262 |
jos.close(); |
263 |
} |
264 |
} finally { |
265 |
os.close(); |
266 |
} |
267 |
os = new FileOutputStream(new File(locale, "localized-manifest_cs.jar")); |
268 |
try { |
269 |
JarOutputStream jos = new JarOutputStream(os, loadManifest(null)); |
270 |
try { |
271 |
writeJarEntry(jos, "locmani/Bundle_cs.properties", new File(data, "localized-manifest/locmani/Bundle_cs.properties")); |
272 |
} finally { |
273 |
jos.close(); |
274 |
} |
275 |
} finally { |
276 |
os.close(); |
277 |
} |
278 |
} |
279 |
{ |
280 |
OutputStream os = new FileOutputStream(new File(jars, "base-layer-mod.jar")); |
281 |
try { |
282 |
JarOutputStream jos = new JarOutputStream(os, loadManifest(new File(data, "base-layer-mod.mf"))); |
283 |
try { |
284 |
writeJarEntry(jos, "baselayer/layer.xml", new File(data, "base-layer-mod/baselayer/layer.xml")); |
285 |
} finally { |
286 |
jos.close(); |
287 |
} |
288 |
} finally { |
289 |
os.close(); |
290 |
} |
291 |
os = new FileOutputStream(new File(locale, "base-layer-mod_cs.jar")); |
292 |
try { |
293 |
JarOutputStream jos = new JarOutputStream(os, loadManifest(null)); |
294 |
try { |
295 |
writeJarEntry(jos, "baselayer/layer_cs.xml", new File(data, "base-layer-mod/baselayer/layer_cs.xml")); |
296 |
} finally { |
297 |
jos.close(); |
298 |
} |
299 |
} finally { |
300 |
os.close(); |
301 |
} |
302 |
os = new FileOutputStream(new File(locale, "base-layer-mod_foo.jar")); |
303 |
try { |
304 |
JarOutputStream jos = new JarOutputStream(os, loadManifest(null)); |
305 |
try { |
306 |
writeJarEntry(jos, "baselayer/layer_foo.xml", new File(data, "base-layer-mod/baselayer/layer_foo.xml")); |
307 |
} finally { |
308 |
jos.close(); |
309 |
} |
310 |
} finally { |
311 |
os.close(); |
312 |
} |
313 |
createTestJAR("override-layer-mod", null); |
314 |
} |
315 |
} |
316 |
private static void compile(List<String> options, Iterable<File> files) throws IOException { |
317 |
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
318 |
StandardJavaFileManager mgr = compiler.getStandardFileManager(null, null, null); |
319 |
List<String> fullOptions = new ArrayList<String>(options); |
320 |
fullOptions.addAll(Arrays.asList("-source", "1.5", "-target", "1.5")); |
321 |
if (!compiler.getTask(null, mgr, null, fullOptions, null, mgr.getJavaFileObjectsFromFiles(files)).call()) { |
322 |
throw new IOException("compilation failed"); |
323 |
} |
324 |
} |
325 |
private File createTestJAR(String name, String srcdir, File... classpath) throws IOException { |
326 |
return createTestJAR(data, jars, name, srcdir, classpath); |
327 |
} |
328 |
public static File createTestJAR(File data, File jars, String name, String srcdir, File... classpath) throws IOException { |
329 |
File srcdirF = null; |
330 |
File d = new File(data, srcdir != null ? srcdir : name); |
331 |
if (d.isDirectory()) { |
332 |
srcdirF = d; |
333 |
} |
334 |
File manifestF = null; |
335 |
File f = new File(data, name + ".mf"); |
336 |
if (f.isFile()) { |
337 |
manifestF = f; |
338 |
} |
339 |
if (srcdirF != null) { |
340 |
assert srcdirF.isDirectory(); |
341 |
List<File> sourceFiles = findSourceFiles(srcdirF); |
342 |
if (!sourceFiles.isEmpty()) { |
343 |
StringBuilder cp = new StringBuilder(System.getProperty("java.class.path")); // o.o.util, o.o.modules |
344 |
for (File j : classpath) { |
345 |
cp.append(File.pathSeparatorChar); |
346 |
cp.append(j); |
347 |
} |
348 |
compile(Arrays.asList( |
349 |
"-classpath", cp.toString(), |
350 |
"-sourcepath", srcdirF.getAbsolutePath(), |
351 |
"-d", srcdirF.getAbsolutePath()), |
352 |
sourceFiles); |
353 |
} |
354 |
} |
355 |
// Cannot trivially use TestFileUtils.writeZipFile here since we have binary content (classes). |
356 |
File jar = new File(jars, name + ".jar"); |
357 |
jars.mkdirs(); |
358 |
OutputStream os = new FileOutputStream(jar); |
359 |
try { |
360 |
JarOutputStream jos = new JarOutputStream(os, loadManifest(manifestF)); |
361 |
try { |
362 |
if (srcdirF != null) { |
363 |
jarUp(jos, srcdirF, ""); |
364 |
} |
365 |
} finally { |
366 |
jos.close(); |
367 |
} |
368 |
} finally { |
369 |
os.close(); |
370 |
} |
371 |
return jar; |
372 |
} |
373 |
private static Manifest loadManifest(File mani) throws IOException { |
374 |
Manifest m = new Manifest(); |
375 |
if (mani != null) { |
376 |
InputStream is = new FileInputStream(mani); |
377 |
try { |
378 |
m.read(is); |
379 |
} finally { |
380 |
is.close(); |
381 |
} |
382 |
} |
383 |
m.getMainAttributes().putValue("Manifest-Version", "1.0"); // workaround for JDK bug |
384 |
return m; |
385 |
} |
386 |
private static List<File> findSourceFiles(File... roots) { |
387 |
List<File> sourceFiles = new ArrayList<File>(); |
388 |
for (File root : roots) { |
389 |
doFindSourceFiles(sourceFiles, root); |
390 |
} |
391 |
return sourceFiles; |
392 |
} |
393 |
private static void doFindSourceFiles(List<File> sourceFiles, File srcdir) { |
394 |
for (File k : srcdir.listFiles()) { |
395 |
if (k.getName().endsWith(".java")) { |
396 |
sourceFiles.add(k); |
397 |
} else if (k.isDirectory()) { |
398 |
doFindSourceFiles(sourceFiles, k); |
399 |
} |
400 |
} |
401 |
} |
402 |
private static void jarUp(JarOutputStream jos, File dir, String prefix) throws IOException { |
403 |
for (File f : dir.listFiles()) { |
404 |
String path = prefix + f.getName(); |
405 |
if (f.getName().endsWith(".java")) { |
406 |
continue; |
407 |
} else if (f.isDirectory()) { |
408 |
if (generateAllDirs) { |
409 |
JarEntry je = new JarEntry(path + "/"); |
410 |
jos.putNextEntry(je); |
411 |
} |
412 |
jarUp(jos, f, path + "/"); |
413 |
} else { |
414 |
writeJarEntry(jos, path, f); |
415 |
} |
416 |
} |
417 |
} |
418 |
private static void writeJarEntry(JarOutputStream jos, String path, File f) throws IOException, FileNotFoundException { |
419 |
JarEntry je = new JarEntry(path); |
420 |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
421 |
InputStream is = new FileInputStream(f); |
422 |
try { |
423 |
copyStreams(is, baos); |
424 |
} finally { |
425 |
is.close(); |
426 |
} |
427 |
byte[] data = baos.toByteArray(); |
428 |
je.setSize(data.length); |
429 |
CRC32 crc = new CRC32(); |
430 |
crc.update(data); |
431 |
je.setCrc(crc.getValue()); |
432 |
jos.putNextEntry(je); |
433 |
jos.write(data); |
434 |
} |
435 |
|
436 |
} |