package test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.Map; import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import aQute.bnd.osgi.Builder; import aQute.bnd.osgi.Jar; import aQute.bnd.osgi.JarResource; import aQute.bnd.osgi.Processor; import aQute.bnd.osgi.Resource; import aQute.lib.io.IO; import aQute.lib.io.IOConstants; import junit.framework.TestCase; @SuppressWarnings("resource") public class ResourcesTest extends TestCase { static final int BUFFER_SIZE = IOConstants.PAGE_SIZE * 1; /** * Command facility in Include-Resource */ public void testCommand() throws Exception { if (!onWindows()) { Builder b = new Builder(); b.setProperty("Include-Resource", "xkeystore; requires='testresources/keystore';cmd='echo ${@requires}', "); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); assertTrue(b.check()); Resource r = jar.getResource("xkeystore"); assertNotNull(r); String s = IO.collect(r.openInputStream()); assertEquals("testresources/keystore\n", s); } } /** * Test the Include-Resource facility to generate resources on the fly. This * is a a case where multiple resources and up in a single combined * resource. */ public static void testOnTheFlyMerge() throws Exception { if (!onWindows()) { Builder b = new Builder(); b.setIncludeResource("count;for='1,2,3';cmd='echo YES_${@}'"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); assertTrue(b.check()); Resource r = jar.getResource("count"); assertNotNull(r); String s = IO.collect(r.openInputStream()); assertEquals("YES_1\nYES_2\nYES_3\n", s); b.close(); } } /** * Test the Include-Resource facility to generate resources on the fly. This * is a simple case of one resource. */ public static void testOnTheFlySingle() throws Exception { if (onWindows()) return; Builder b = new Builder(); b.setIncludeResource("testresources/ls;cmd='ls /etc | grep hosts'"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); assertTrue(b.check()); Resource r = jar.getResource("testresources/ls"); assertNotNull(r); String s = IO.collect(r.openInputStream()); assertTrue(s.contains("hosts")); } /** * Test the Include-Resource facility to generate resources on the fly. This * is a simple case of one resource with an error. */ public static void testOnTheFlySingleError() throws Exception { if (onWindows()) return; Builder b = new Builder(); b.setIncludeResource("testresources/x;cmd='I do not exist!!!!!!!!!!!'"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); assertTrue(b.check("Cmd 'I do not exist!!!!!!!!!!!' failed")); b.close(); } /** * Test the Include-Resource facility to generate resources on the fly. This * is a a case where multiple resources and up in a single combined * resource. */ public static void testOnTheFlyMultiple() throws Exception { if (onWindows()) return; Builder b = new Builder(); b.setIncludeResource("count/${@};for='1,2,3';cmd='echo YES_${@}'"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); assertTrue(b.check()); assertNotNull(jar.getResource("count/1")); Resource r = jar.getResource("count/2"); assertNotNull(jar.getResource("count/3")); String s = IO.collect(r.openInputStream()); assertEquals("YES_2\n", s); } /** * If a name starts with a - sign then it is ok if it does not exist. The - * sign must be skipped obviously. * * @throws Exception */ public static void testAbsentIsOk() throws Exception { { Builder b = new Builder(); b.setProperty("Include-Resource", "TargetFolder=-testresources/ws/p2/Resources"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); assertTrue(b.check()); Resource r = jar.getResource("TargetFolder/resource1.res"); assertNotNull(r); r = jar.getResource("TargetFolder/resource2.res"); assertNotNull(r); r = jar.getResource("TargetFolder/resource5.asc"); assertNotNull(r); } { Builder b = new Builder(); b.setProperty("Include-Resource", "TargetFolder=-doesnotexist, text;literal='Hello'"); b.setProperty("-resourceonly", "true"); b.build(); assertTrue(b.check()); } { Builder b = new Builder(); b.setProperty("Include-Resource", "-doesnotexist, text;literal='Hello'"); b.setProperty("-resourceonly", "true"); b.build(); assertTrue(b.check()); } { Builder b = new Builder(); b.setProperty("Include-Resource", "-testresources/ws/p2/Resources"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); assertTrue(b.check()); Resource r = jar.getResource("resource1.res"); assertNotNull(r); } } public static void testNegativeFilter() throws Exception { Builder b = new Builder(); b.setProperty("Include-Resource", "TargetFolder=testresources/ws/p2/Resources;filter:=!*.txt"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/resource1.res"); assertNotNull(r); r = jar.getResource("TargetFolder/resource2.res"); assertNotNull(r); r = jar.getResource("TargetFolder/resource5.asc"); assertNotNull(r); } public static void testCopyToRoot() throws Exception { Builder bmaker = new Builder(); Properties p = new Properties(); p.setProperty("-resourceonly", "true"); p.setProperty("Include-Resource", "/=src/test/activator"); bmaker.setProperties(p); Jar jar = bmaker.build(); for (String s : jar.getResources().keySet()) System.err.println(s); assertNotNull(jar.getResource("Activator.java")); assertEquals(0, bmaker.getErrors().size()); assertEquals(0, bmaker.getWarnings().size()); } public static void testIncludeResourceDirectivesDefault() throws Exception { Builder b = new Builder(); b.setProperty("Include-Resource", "TargetFolder=testresources/ws/p2/Resources"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/resource3.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource4.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource6.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource7.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/stuff/resource9.res"); assertNotNull(r); r = jar.getResource("TargetFolder/text.txt"); assertNotNull(r); } public static void testIncludeResourceDoNotCopy() throws Exception { Builder b = new Builder(); // Use Properties file otherwise -donotcopy is not picked up Properties p = new Properties(); p.put("-donotcopy", "CVS|.svn|stuff"); p.put("Include-Resource", "TargetFolder=testresources/ws/p2/Resources"); p.put("-resourceonly", "true"); b.setProperties(p); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/resource3.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource4.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource6.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource7.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/stuff/resource9.res"); assertNull(r); r = jar.getResource("TargetFolder/text.txt"); assertNotNull(r); } public static void testIncludeResourceDoNotCopyPath() throws Exception { Builder b = new Builder(); // Use Properties file otherwise -donotcopy is not picked up Properties p = new Properties(); p.put("-donotcopy", ".*/more/.*"); p.put("Include-Resource", "TargetFolder=testresources/ws/p2/Resources"); p.put("-resourceonly", "true"); p.put("-upto", "3.0"); b.setProperties(p); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/resource3.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource4.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource6.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource7.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/stuff/resource9.res"); assertNotNull(r); r = jar.getResource("TargetFolder/text.txt"); assertNotNull(r); } public static void testIncludeResourceDoNotCopyPath_Since_3_1() throws Exception { Builder b = new Builder(); // Use Properties file otherwise -donotcopy is not picked up Properties p = new Properties(); p.put("-donotcopy", ".*/more/.*"); p.put("Include-Resource", "TargetFolder=testresources/ws/p2/Resources"); p.put("-resourceonly", "true"); b.setProperties(p); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/resource3.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource4.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource6.txt"); assertNull(r); r = jar.getResource("TargetFolder/more/resource7.txt"); assertNull(r); r = jar.getResource("TargetFolder/stuff/resource9.res"); assertNotNull(r); r = jar.getResource("TargetFolder/text.txt"); assertNotNull(r); } public static void testIncludeResourceDirectivesFilterRecursive() throws Exception { Builder b = new Builder(); b.setProperty("Include-Resource", "TargetFolder=testresources/ws/p2/Resources;filter:=re*.txt"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/resource3.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource4.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource6.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource7.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/text.txt"); assertNull(r); } public static void testIncludeResourceDirectivesFilterRecursive2() throws Exception { Builder b = new Builder(); b.setProperty("Include-Resource", "testresources/ws/p2/Resources;filter:=re*.txt"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); Resource r = jar.getResource("resource3.txt"); assertNotNull(r); r = jar.getResource("resource4.txt"); assertNotNull(r); r = jar.getResource("more/resource6.txt"); assertNotNull(r); r = jar.getResource("more/resource7.txt"); assertNotNull(r); r = jar.getResource("text.txt"); assertNull(r); } public static void testIncludeResourceDirectivesFilterNonRecursive() throws Exception { Builder b = new Builder(); b.setProperty("Include-Resource", "TargetFolder=testresources/ws/p2/Resources;filter:=re*.txt;recursive:=false"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/resource3.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource4.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/more/resource6.txt"); assertNull(r); r = jar.getResource("TargetFolder/more/resource7.txt"); assertNull(r); } public static void testIncludeResourceDirectivesFilterRecursiveFlatten() throws Exception { Builder b = new Builder(); b.setProperty("Include-Resource", "TargetFolder=testresources/ws/p2/Resources;filter:=re*.txt;flatten:=true"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/resource3.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource4.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource6.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource7.txt"); assertNotNull(r); r = jar.getResource("TargetFolder/resource1.res"); assertNull(r); } public static void testEmpty() throws Exception { Builder bmaker = new Builder(); Properties p = new Properties(); p.setProperty("-resourceonly", "true"); p.setProperty("Include-Resource", " "); bmaker.setProperties(p); Jar jar = bmaker.build(); assertEquals(0, jar.getResources().size()); assertTrue(bmaker.check("The JAR is empty")); } public static void testLiteral() throws Exception { Builder bmaker = new Builder(); Properties p = new Properties(); p.setProperty("-resourceonly", "true"); p.setProperty("Include-Resource", "text;literal=TEXT;extra='hello/world;charset=UTF-8'"); bmaker.setProperties(p); bmaker.setClasspath(new String[] { "src" }); Jar jar = bmaker.build(); Resource resource = jar.getResource("text"); assertNotNull(resource); byte buffer[] = new byte[BUFFER_SIZE]; int size = resource.openInputStream().read(buffer); String s = new String(buffer, 0, size); assertEquals("TEXT", s); assertEquals("hello/world;charset=UTF-8", resource.getExtra()); report(bmaker); } /** * Check if we can create a jar on demand through the make facility. * * @throws Exception */ public static void testOnDemandResource() throws Exception { Builder bmaker = new Builder(); Properties p = new Properties(); p.setProperty("-resourceonly", "true"); p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy"); p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd"); p.setProperty("Include-Resource", "ondemand.jar"); bmaker.setProperties(p); bmaker.setClasspath(new String[] { "bin" }); Jar jar = bmaker.build(); Resource resource = jar.getResource("ondemand.jar"); assertNotNull(resource); assertTrue(bmaker.check()); assertTrue(resource instanceof JarResource); report(bmaker); } public void testEmptyDirs() throws Exception { Builder b = new Builder(); b.setProperty("-resourceonly", "true"); b.setProperty("Include-Resource", "hello/world/<<EMPTY>>;literal=''"); Jar jar = b.build(); Map<String,Map<String,Resource>> directories = jar.getDirectories(); assertTrue(directories.containsKey("hello/world")); // report(b); //error due to empty literal ByteArrayOutputStream baos = new ByteArrayOutputStream(); jar.write(baos); byte[] contents = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(contents); ZipInputStream zis = new ZipInputStream(bais); boolean hasDir = false; boolean hasContent = false; ZipEntry ze = zis.getNextEntry(); while (null != ze) { if (ze.getName().equals("hello/world/") && ze.isDirectory()) hasDir = true; if (ze.getName().startsWith("hello/world/") && ze.getName().length() > "hello/world/".length()) hasContent = true; ze = zis.getNextEntry(); } assertTrue(hasDir); assertFalse(hasContent); } public void testEmptyDirs2() throws Exception { File tstDir = IO.getFile("testresources/ws/p2/Resources/empty"); tstDir.mkdirs(); Builder b = new Builder(); b.setProperty("Include-Resource", "TargetFolder=testresources/ws/p2/Resources"); b.setProperty("-resourceonly", "true"); Jar jar = b.build(); Resource r = jar.getResource("TargetFolder/empty/<<EMPTY>>"); assertNotNull(r); ByteArrayOutputStream baos = new ByteArrayOutputStream(); jar.write(baos); byte[] contents = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(contents); ZipInputStream zis = new ZipInputStream(bais); boolean hasDir = false; boolean hasContent = false; ZipEntry ze = zis.getNextEntry(); while (null != ze) { if (ze.getName().equals("TargetFolder/empty/") && ze.isDirectory()) hasDir = true; if (ze.getName().startsWith("TargetFolder/empty/") && ze.getName().length() > "TargetFolder/empty/".length()) hasContent = true; ze = zis.getNextEntry(); } assertTrue(hasDir); assertFalse(hasContent); IO.delete(tstDir); } static void report(Processor processor) { System.err.println(); for (int i = 0; i < processor.getErrors().size(); i++) System.err.println(processor.getErrors().get(i)); for (int i = 0; i < processor.getWarnings().size(); i++) System.err.println(processor.getWarnings().get(i)); assertEquals(0, processor.getErrors().size()); assertEquals(0, processor.getWarnings().size()); } private static boolean onWindows() { return File.separatorChar == '\\'; } }