Index: docs/examples/gettingstarted/sequencers/pom.xml =================================================================== --- docs/examples/gettingstarted/sequencers/pom.xml (revision 1125) +++ docs/examples/gettingstarted/sequencers/pom.xml (working copy) @@ -46,6 +46,12 @@ ${pom.version} runtime + + org.jboss.dna + dna-sequencer-zip + ${pom.version} + test + Index: docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java =================================================================== --- docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java (revision 1125) +++ docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java (working copy) @@ -26,6 +26,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Calendar; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; @@ -245,6 +246,25 @@ } } + if (root.hasNode("zips")) { + LinkedList nodesToVisit = new LinkedList(); + + for (NodeIterator i = root.getNode("zips").getNodes(); i.hasNext();) { + nodesToVisit.addLast(i.nextNode()); + } + + while (!nodesToVisit.isEmpty()) { + Node node = nodesToVisit.pop(); + + String nodeType = "nt:file".equals(node.getPrimaryNodeType()) ? "file" : "folder"; + infos.add(new MediaInfo(node.getPath(), node.getName(), nodeType, new Properties())); + + for (NodeIterator i = node.getNodes(); i.hasNext();) { + nodesToVisit.addLast(i.nextNode()); + } + + } + } if (root.hasNode("java")) { Map> tree = new TreeMap>(); // Find the compilation unit node ... @@ -443,6 +463,7 @@ if (filename.endsWith(".jpeg")) return "image/jpeg"; if (filename.endsWith(".ras")) return "image/x-cmu-raster"; if (filename.endsWith(".mp3")) return "audio/mpeg"; + if (filename.endsWith(".jar")) return "application/java-archive"; if (filename.endsWith(".java")) return "text/x-java-source"; return null; } Index: docs/examples/gettingstarted/sequencers/src/main/resources/sequencing.cnd =================================================================== --- docs/examples/gettingstarted/sequencers/src/main/resources/sequencing.cnd (revision 1125) +++ docs/examples/gettingstarted/sequencers/src/main/resources/sequencing.cnd (working copy) @@ -4,6 +4,7 @@ + // ---------------------------------------------------------- // JCR Pre-defined Mixin Types that are not loaded by default @@ -263,4 +264,23 @@ + java:package (java:packageDeclaration) = java:packageDeclaration + java:import (java:importDeclaration) = java:importDeclaration + java:unitType (java:classDeclaration, java:interfaceDeclaration) + + +// ------------------- +// DNA Zip Sequencer +// ------------------- + +/** + * JCR Pre-defined Mixin Types that are not loaded by default + */ +[mix:mimeType] mixin + - jcr:mimeType (string) + - jcr:encoding (string) + +/** + * Primary type for root of generated structure + */ +[zip:content] > nt:unstructured, mix:mimeTyped + + * (nt:folder) + + * (nt:file) \ No newline at end of file Index: docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java =================================================================== --- docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java (revision 1125) +++ docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java (working copy) @@ -37,6 +37,7 @@ import org.jboss.dna.jcr.JcrRepository; import org.jboss.dna.sequencer.java.JavaMetadataSequencer; import org.jboss.dna.sequencer.mp3.Mp3MetadataSequencer; +import org.jboss.dna.sequencer.zip.ZipSequencer; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -50,6 +51,7 @@ private URL pictImageUrl; private URL jpegImageUrl; private URL mp3Url; + private URL jarUrl; private URL javaSourceUrl; private SequencingClient client; @@ -59,6 +61,7 @@ this.pictImageUrl = Thread.currentThread().getContextClassLoader().getResource("caution.pict"); this.jpegImageUrl = Thread.currentThread().getContextClassLoader().getResource("caution.jpg"); this.mp3Url = Thread.currentThread().getContextClassLoader().getResource("sample1.mp3"); + this.jarUrl = Thread.currentThread().getContextClassLoader().getResource("test.jar"); // Get the URL of source (MySource.java), that have to be sequencing this.javaSourceUrl = FileUtil.convertFileToURL("workspace/project1/src/org/acme/MySource.java"); @@ -88,6 +91,12 @@ .setDescription("Sequences mp3 files to extract the id3 tags of the audio file") .sequencingFrom("//(*.mp3[*])/jcr:content[@jcr:data]") .andOutputtingTo("/mp3s/$1"); + // Set up the zip sequencer ... + config.sequencer("Zip Sequencer") + .usingClass(ZipSequencer.class) + .setDescription("Sequences Zip, WAR, and JAR files to extract the contents") + .sequencingFrom("//(*.(zip|war|jar)[*])/jcr:content[@jcr:data]") + .andOutputtingTo("/zips/$1"); // Set up the Java source file sequencer ... config.sequencer("Java Sequencer") .usingClass(JavaMetadataSequencer.class) @@ -159,6 +168,19 @@ } @Test + public void shouldUploadAndSequenceZipFile() throws Exception { + client.setUserInterface(new MockUserInterface(this.jarUrl, "/a/b/test.jar", 168)); + client.startRepository(); + client.uploadFile(); + + waitUntilSequencedNodesIs(1); + + // The sequencers should have run, so perform the search. + // The mock user interface checks the results. + client.search(); + } + + @Test public void shouldUploadAndSequenceJavaSourceFile() throws Exception { client.setUserInterface(new MockUserInterface(this.javaSourceUrl, "/a/b/MySource.java", 1)); client.startRepository(); Index: extensions/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java =================================================================== --- extensions/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java (revision 1125) +++ extensions/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java (working copy) @@ -28,9 +28,11 @@ import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import org.jboss.dna.graph.sequencer.StreamSequencerContext; +import org.jboss.dna.graph.property.BinaryFactory; +import org.jboss.dna.graph.property.DateTimeFactory; import org.jboss.dna.graph.sequencer.SequencerOutput; import org.jboss.dna.graph.sequencer.StreamSequencer; +import org.jboss.dna.graph.sequencer.StreamSequencerContext; /** * @author Michael Trezzi @@ -47,6 +49,9 @@ public void sequence( InputStream stream, SequencerOutput output, StreamSequencerContext context ) { + BinaryFactory binaryFactory = context.getValueFactories().getBinaryFactory(); + DateTimeFactory dateFactory = context.getValueFactories().getDateFactory(); + try { ZipInputStream in = new ZipInputStream(stream); ZipEntry entry = in.getNextEntry(); @@ -59,14 +64,27 @@ if (entry.isDirectory()) { // If entry is directory, create nt:folder node output.setProperty("zip:content/" + entry.getName(), "jcr:primaryType", "nt:folder"); } else { // If entry is File, create nt:file - output.setProperty("zip:content/" + entry.getName() + "/jcr:content", "jcr:primaryType", "nt:resource"); - int n; + output.setProperty("zip:content/" + entry.getName(), "jcr:primaryType", "nt:file"); + output.setProperty("zip:content/" + entry.getName() + "/jcr:content", "jcr:primaryType", "dna:resource"); + int n; ByteArrayOutputStream baout = new ByteArrayOutputStream(); while ((n = in.read(buf, 0, 1024)) > -1) { baout.write(buf, 0, n); } - output.setProperty("zip:content/" + entry.getName() + "/jcr:content", "jcr:data", baout.toByteArray()); - // all other nt:file properties should be generated by other sequencers (mimetype, encoding,...) + byte[] bytes = baout.toByteArray(); + output.setProperty("zip:content/" + entry.getName() + "/jcr:content", + "jcr:data", + binaryFactory.create(bytes)); + // all other nt:file properties should be generated by other sequencers (mimetype, encoding,...) but we'll + // default them here + output.setProperty("zip:content/" + entry.getName() + "/jcr:content", "jcr:encoding", "binary"); + output.setProperty("zip:content/" + entry.getName() + "/jcr:content", + "jcr:lastModified", + dateFactory.create(entry.getTime()).toString()); + output.setProperty("zip:content/" + entry.getName() + "/jcr:content", + "jcr:mimeType", + "application/octet-stream"); + } in.closeEntry(); entry = in.getNextEntry(); Index: extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java =================================================================== --- extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java (revision 1125) +++ extensions/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java (working copy) @@ -27,7 +27,9 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.stub; import java.io.InputStream; +import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.sequencer.StreamSequencerContext; import org.junit.After; import org.junit.Test; @@ -59,9 +61,11 @@ ZipSequencer zs = new ZipSequencer(); SequencingOutputTestClass seqtest = new SequencingOutputTestClass(); StreamSequencerContext context = mock(StreamSequencerContext.class); + stub(context.getValueFactories()).toReturn(new ExecutionContext().getValueFactories()); + zs.sequence(is, seqtest, context); - assertThat(seqtest.properties.get(2).getPath(), is("zip:content/test subfolder/test2.txt/jcr:content")); + assertThat(seqtest.properties.get(3).getPath(), is("zip:content/test subfolder/test2.txt/jcr:content")); } }