DNA SVN: r124 - trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-05-07 18:02:54 -0400 (Wed, 07 May 2008)
New Revision: 124
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java
Log:
Corrected a log message's use of parameters, and changed a catch to catch Throwable (rather than just Exception)
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java 2008-05-07 22:01:29 UTC (rev 123)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java 2008-05-07 22:02:54 UTC (rev 124)
@@ -501,7 +501,7 @@
if (sequencers.isEmpty()) {
this.statistics.recordNodeSkipped();
if (this.logger.isDebugEnabled()) {
- this.logger.trace("Skipping '{}': no sequencers matched this condition", changedNode);
+ this.logger.trace("Skipping '{0}': no sequencers matched this condition", changedNode);
}
} else {
// Run each of those sequencers ...
@@ -557,7 +557,7 @@
}
} catch (RepositoryException e) {
this.logger.error(e, RepositoryI18n.errorInRepositoryWhileFindingSequencersToRunAgainstNode, changedNode);
- } catch (Exception e) {
+ } catch (Throwable e) {
this.logger.error(e, RepositoryI18n.errorFindingSequencersToRunAgainstNode, changedNode);
}
}
16 years
DNA SVN: r123 - trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-05-07 18:01:29 -0400 (Wed, 07 May 2008)
New Revision: 123
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java
Log:
Added a check to the code that unregisters workspace listeners to first see if the session is live before attempting to close it.
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java 2008-05-07 20:43:55 UTC (rev 122)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java 2008-05-07 22:01:29 UTC (rev 123)
@@ -216,7 +216,7 @@
try {
listener.unregister();
} catch (RepositoryException e) {
- this.logger.error(RepositoryI18n.errorUnregisteringWorkspaceListenerWhileShuttingDownObservationService);
+ this.logger.error(e, RepositoryI18n.errorUnregisteringWorkspaceListenerWhileShuttingDownObservationService);
}
}
}
@@ -586,8 +586,10 @@
public synchronized WorkspaceListener unregister() throws UnsupportedRepositoryOperationException, RepositoryException {
if (this.session == null) return this;
try {
- this.session.getWorkspace().getObservationManager().removeEventListener(this);
- this.session.logout();
+ if (this.session.isLive()) {
+ this.session.getWorkspace().getObservationManager().removeEventListener(this);
+ this.session.logout();
+ }
} finally {
this.session = null;
unregisterListener(this);
16 years
DNA SVN: r122 - in trunk: docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers and 3 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-05-07 16:43:55 -0400 (Wed, 07 May 2008)
New Revision: 122
Added:
trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/MockUserInterface.java
trunk/docs/gettingstarted/en/images/example-sequencer-cli-client.png
trunk/docs/gettingstarted/en/images/example-sequencer-search.png
trunk/docs/gettingstarted/en/images/example-sequencer-search2.png
trunk/docs/gettingstarted/en/images/example-sequencer-statistics.png
trunk/docs/gettingstarted/en/images/example-sequencer-statistics2.png
trunk/docs/gettingstarted/en/images/example-sequencer-upload.png
trunk/docs/gettingstarted/en/images/example-sequencer-upload2.png
Modified:
trunk/build/assembly/examples.xml
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java
trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java
trunk/docs/gettingstarted/en/master.xml
Log:
Update the sequencing example and Getting Started document.
Modified: trunk/build/assembly/examples.xml
===================================================================
--- trunk/build/assembly/examples.xml 2008-05-07 16:26:20 UTC (rev 121)
+++ trunk/build/assembly/examples.xml 2008-05-07 20:43:55 UTC (rev 122)
@@ -1,5 +1,5 @@
<assembly>
- <id>examples</id>
+ <id>gettingstarted-examples</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<!--<format>tar.gz</format>
Modified: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java 2008-05-07 16:26:20 UTC (rev 121)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java 2008-05-07 20:43:55 UTC (rev 122)
@@ -25,6 +25,7 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.net.URL;
import java.util.List;
import java.util.Map;
import org.jboss.dna.repository.sequencers.SequencingService;
@@ -134,7 +135,10 @@
return buffer.toString();
}
- public File getPathOfFileToUpload() throws IllegalArgumentException, IOException {
+ /**
+ * {@inheritDoc}
+ */
+ public URL getFileToUpload() throws IllegalArgumentException, IOException {
System.out.println("Please enter the file to upload:");
String path = in.readLine();
File file = new File(path);
@@ -147,7 +151,7 @@
if (!file.isFile()) {
throw new IllegalArgumentException("Please specify a file. The file \"" + file.getAbsolutePath() + "\" is a directory.");
}
- return file;
+ return file.toURL();
}
public String getRepositoryPath( String defaultPath ) throws IllegalArgumentException, IOException {
Modified: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java 2008-05-07 16:26:20 UTC (rev 121)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java 2008-05-07 20:43:55 UTC (rev 122)
@@ -22,8 +22,6 @@
package org.jboss.example.dna.sequencers;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
@@ -50,6 +48,7 @@
import org.jboss.dna.repository.sequencers.SequencingService;
import org.jboss.dna.repository.util.ExecutionContext;
import org.jboss.dna.repository.util.JcrTools;
+import org.jboss.dna.repository.util.SessionFactory;
import org.jboss.dna.repository.util.SimpleExecutionContext;
/**
@@ -90,10 +89,6 @@
setRepositoryInformation(DEFAULT_REPOSITORY_NAME, DEFAULT_WORKSPACE_NAME, DEFAULT_USERNAME, DEFAULT_PASSWORD);
}
- public void setUserInterface( UserInterface userInterface ) {
- this.userInterface = userInterface;
- }
-
protected void setWorkingDirectory( String workingDirectoryPath ) {
this.workingDirectory = workingDirectoryPath != null ? workingDirectoryPath : DEFAULT_WORKING_DIRECTORY;
}
@@ -112,6 +107,18 @@
this.password = password;
}
+ /**
+ * Set the user interface that this client should use.
+ * @param userInterface
+ */
+ public void setUserInterface( UserInterface userInterface ) {
+ this.userInterface = userInterface;
+ }
+
+ /**
+ * Start up the JCR repository. This method only operates using the JCR API and Jackrabbit-specific API.
+ * @throws Exception
+ */
public void startRepository() throws Exception {
if (this.repository == null) {
try {
@@ -163,6 +170,10 @@
}
}
+ /**
+ * Shutdown the repository. This method only uses the JCR API.
+ * @throws Exception
+ */
public void shutdownRepository() throws Exception {
if (this.repository != null) {
try {
@@ -174,93 +185,125 @@
}
}
+ /**
+ * Start the DNA services.
+ * @throws Exception
+ */
public void startDnaServices() throws Exception {
if (this.repository == null) {
this.startRepository();
}
- if (this.sequencingService != null) {
- return;
- }
- // Create an execution context for the sequencing service.
- // The repository instances and workspace names are registered, and that the service will reference.
- // the repository ...
- SimpleExecutionContext executionContext = new SimpleExecutionContext();
- // Register the JCR repository ...
- executionContext.registerRepository(this.repositoryName, this.repository);
- if (this.username != null) {
- Credentials credentials = new SimpleCredentials(this.username, this.password);
- executionContext.registerCredentials(this.repositoryName + "/" + this.workspaceName, credentials);
- }
- this.executionContext = executionContext;
+ if (this.sequencingService == null) {
- // Create the sequencing service ...
- this.sequencingService = new SequencingService();
- this.sequencingService.setExecutionContext(executionContext);
+ // Create an execution context for the sequencing service. This execution context provides an environment
+ // for the DNA services which knows about the JCR repositories, workspaces, and credentials used to
+ // establish sessions to these workspaces. This example uses the SimpleExecutionContext, but there is
+ // implementation for use with JCR repositories registered in JNDI.
+ SimpleExecutionContext executionContext = new SimpleExecutionContext();
+ executionContext.registerRepository(this.repositoryName, this.repository);
+ if (this.username != null) {
+ Credentials credentials = new SimpleCredentials(this.username, this.password);
+ executionContext.registerCredentials(this.repositoryName + "/" + this.workspaceName, credentials);
+ }
+ this.executionContext = executionContext;
- // Add the configuration for the image sequencer. This sequencer class should be on the thread's current context class
- // loader, or if that's null the classloader that loaded the SequencingService class.
- //
- // The path expressions tell the service that this sequencer should be invoked on the "jcr:data" property
- // on the "jcr:content" child node of any node uploaded to the repository whose name ends with one of the
- // supported extensions, and it should place the output metadata in a node with the same name as the file
- // but immediately below the "/images" node. Path expressions can be fairly complex, and can even
- // specify that the generated information be placed in a different repository.
- //
- // Sequencers can be added before or after the service is started.
- String name = "Image Sequencer";
- String desc = "Sequences image files to extract the characteristics of the image";
- String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
- String[] classpath = null; // Use the current classpath
- String[] pathExpressions = {"//(*.(jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data] => /images/$1"};
- SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
- this.sequencingService.addSequencer(imageSequencerConfig);
+ // Create the sequencing service, passing in the execution context ...
+ this.sequencingService = new SequencingService();
+ this.sequencingService.setExecutionContext(executionContext);
+ // Configure the sequencers. In this example, we only use a single sequencer that processes image files.
+ // So create a configuration. Note that the sequencing service expects the class to be on the thread's current context
+ // classloader, or if that's null the classloader that loaded the SequencingService class.
+ //
+ // Part of the configuration includes telling DNA which JCR paths should be processed by the sequencer.
+ // These path expressions tell the service that this sequencer should be invoked on the "jcr:data" property
+ // on the "jcr:content" child node of any node uploaded to the repository whose name ends with one of the
+ // supported extensions, and the sequencer should place the generated output metadata in a node with the same name as
+ // the file but immediately below the "/images" node. Path expressions can be fairly complex, and can even
+ // specify that the generated information be placed in a different repository.
+ //
+ // Sequencer configurations can be added before or after the service is started, but here we do it before the service
+ // is running.
+ String name = "Image Sequencer";
+ String desc = "Sequences image files to extract the characteristics of the image";
+ String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
+ String[] classpath = null; // Use the current classpath
+ String[] pathExpressions = {"//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data] => /images/$1"};
+ SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
+ this.sequencingService.addSequencer(imageSequencerConfig);
+
+ // Use the DNA observation service to listen to the JCR repository (or multiple ones), and
+ // then register the sequencing service as a listener to this observation service...
+ this.observationService = new ObservationService(this.executionContext.getSessionFactory());
+ this.observationService.getAdministrator().start();
+ this.observationService.addListener(this.sequencingService);
+ this.observationService.monitor(this.repositoryName + "/" + this.workspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED);
+ }
// Start up the sequencing service ...
this.sequencingService.getAdministrator().start();
-
- // Register the sequencing service as a listener using the observation service ...
- this.observationService = new ObservationService(this.executionContext.getSessionFactory());
- this.observationService.getAdministrator().start();
- this.observationService.addListener(this.sequencingService);
- this.observationService.monitor(this.repositoryName + "/" + this.workspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED);
}
+ /**
+ * Shut down the DNA services.
+ * @throws Exception
+ */
public void shutdownDnaServices() throws Exception {
if (this.sequencingService == null) return;
- try {
- // Shut down the service and wait until it's all shut down ...
- this.sequencingService.getAdministrator().shutdown();
- this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+ // Shut down the service and wait until it's all shut down ...
+ this.sequencingService.getAdministrator().shutdown();
+ this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
- // Shut down the observation service ...
- this.observationService.getAdministrator().shutdown();
- this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
-
- } finally {
- this.sequencingService = null;
- this.observationService = null;
- }
+ // Shut down the observation service ...
+ this.observationService.getAdministrator().shutdown();
+ this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
}
+ /**
+ * Get the sequencing statistics.
+ * @return the statistics; never null
+ */
public SequencingService.Statistics getStatistics() {
return this.sequencingService.getStatistics();
}
+ /**
+ * Prompt the user interface for the file to upload into the JCR repository, then upload it using the JCR API.
+ * @throws Exception
+ */
public void uploadFile() throws Exception {
- File file = this.userInterface.getPathOfFileToUpload();
- String nodePath = this.userInterface.getRepositoryPath("/a/b/" + file.getName());
- String mimeType = getMimeType(file);
- uploadFile(new FileInputStream(file), nodePath, mimeType);
+ URL url = this.userInterface.getFileToUpload();
+ // Grab the last segment of the URL path, using it as the filename
+ String filename = url.getPath().replaceAll("([^/]*/)*", "");
+ String nodePath = this.userInterface.getRepositoryPath("/a/b/" + filename);
+ String mimeType = getMimeType(url);
+
+ // Now use the JCR API to upload the file ...
+ Session session = createSession();
+ JcrTools tools = this.executionContext.getTools();
+ try {
+ // Create the node at the supplied path ...
+ Node node = tools.findOrCreateNode(session, nodePath, "nt:folder", "nt:file");
+
+ // Upload the file to that node ...
+ Node contentNode = tools.findOrCreateChild(session, node, "jcr:content", "nt:resource");
+ contentNode.setProperty("jcr:mimeType", mimeType);
+ contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
+ contentNode.setProperty("jcr:data", url.openStream());
+
+ // Save the session ...
+ session.save();
+ } finally {
+ session.logout();
+ }
}
+ /**
+ * Perform a search of the repository for all image metadata automatically created by the image sequencer.
+ * @throws Exception
+ */
public void search() throws Exception {
- List<ImageInfo> images = getImages();
- // Display the search results ...
- this.userInterface.displaySearchResults(images);
- }
-
- protected List<ImageInfo> getImages() throws Exception {
+ // Use JCR to search the repository for image metadata ...
List<ImageInfo> images = new ArrayList<ImageInfo>();
Session session = createSession();
try {
@@ -308,45 +351,31 @@
} finally {
session.logout();
}
- return images;
+
+ // Display the search results ...
+ this.userInterface.displaySearchResults(images);
}
+ /**
+ * Utility method to create a new JCR session from the execution context's {@link SessionFactory}.
+ * @return the session
+ * @throws RepositoryException
+ */
protected Session createSession() throws RepositoryException {
return this.executionContext.getSessionFactory().createSession(this.repositoryName + "/" + this.workspaceName);
}
- protected boolean uploadFile( InputStream content, String nodePath, String mimeType ) throws Exception {
- Session session = createSession();
- JcrTools tools = this.executionContext.getTools();
- try {
- // Create the node at the supplied path ...
- Node node = tools.findOrCreateNode(session, nodePath, "nt:folder", "nt:file");
-
- // Upload the file to that node ...
- Node contentNode = tools.findOrCreateChild(session, node, "jcr:content", "nt:resource");
- contentNode.setProperty("jcr:mimeType", mimeType);
- contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
- contentNode.setProperty("jcr:data", content);
-
- // Save the session ...
- session.save();
- } finally {
- session.logout();
- }
- return true;
+ protected String getMimeType( URL file ) {
+ String filename = file.getPath().toLowerCase();
+ if (filename.endsWith(".gif")) return "image/gif";
+ if (filename.endsWith(".png")) return "image/png";
+ if (filename.endsWith(".pict")) return "image/x-pict";
+ if (filename.endsWith(".bmp")) return "image/bmp";
+ if (filename.endsWith(".jpg")) return "image/jpeg";
+ if (filename.endsWith(".jpe")) return "image/jpeg";
+ if (filename.endsWith(".jpeg")) return "image/jpeg";
+ if (filename.endsWith(".ras")) return "image/x-cmu-raster";
+ throw new SystemFailureException("Unknown mime type for " + file);
}
- protected String getMimeType( File file ) {
- String extension = file.getName().toLowerCase();
- if (extension.endsWith(".gif")) return "image/gif";
- if (extension.endsWith(".png")) return "image/png";
- if (extension.endsWith(".pict")) return "image/x-pict";
- if (extension.endsWith(".bmp")) return "image/bmp";
- if (extension.endsWith(".jpg")) return "image/jpeg";
- if (extension.endsWith(".jpe")) return "image/jpeg";
- if (extension.endsWith(".jpeg")) return "image/jpeg";
- if (extension.endsWith(".ras")) return "image/x-cmu-raster";
- throw new SystemFailureException("Unknown mime type for file " + file);
- }
-
}
Modified: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java 2008-05-07 16:26:20 UTC (rev 121)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java 2008-05-07 20:43:55 UTC (rev 122)
@@ -21,8 +21,8 @@
*/
package org.jboss.example.dna.sequencers;
-import java.io.File;
import java.io.IOException;
+import java.net.URL;
import java.util.List;
/**
@@ -30,7 +30,7 @@
*/
public interface UserInterface {
- public File getPathOfFileToUpload() throws IllegalArgumentException, IOException;
+ public URL getFileToUpload() throws IllegalArgumentException, IOException;
public String getRepositoryPath( String defaultPath ) throws IllegalArgumentException, IOException;
Added: trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/MockUserInterface.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/MockUserInterface.java (rev 0)
+++ trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/MockUserInterface.java 2008-05-07 20:43:55 UTC (rev 122)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencers;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.net.URL;
+import java.util.List;
+
+/**
+ * @author Randall Hauch
+ */
+public class MockUserInterface implements UserInterface {
+
+ private final String repositoryPath;
+ private final URL fileToUpload;
+
+ public MockUserInterface( URL fileToUpload, String repositoryPath ) {
+ this.repositoryPath = repositoryPath;
+ this.fileToUpload = fileToUpload;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void displaySearchResults( List<ImageInfo> images ) {
+ assertThat(images.size(), is(1));
+ for (ImageInfo image : images) {
+ System.out.println("Image: " + image);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public URL getFileToUpload() throws IllegalArgumentException {
+ return this.fileToUpload;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getRepositoryPath( String defaultPath ) {
+ return this.repositoryPath != null ? this.repositoryPath : defaultPath;
+ }
+
+}
Modified: trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java 2008-05-07 16:26:20 UTC (rev 121)
+++ trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java 2008-05-07 20:43:55 UTC (rev 122)
@@ -24,7 +24,6 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import java.net.URL;
-import java.util.List;
import org.jboss.dna.common.util.FileUtil;
import org.junit.After;
import org.junit.Before;
@@ -71,19 +70,21 @@
@Test
public void shouldUploadFile() throws Exception {
+ client.setUserInterface(new MockUserInterface(this.file, "/a/b/caution.png"));
client.startRepository();
client.startDnaServices();
- client.uploadFile(file.openStream(), "/a/b/caution.png", "image/png");
+ client.uploadFile();
- // Let the sequencing start ...
+ // Use a trick to wait until the sequencing has been done by sleeping (to give the sequencing time to start)
+ // and to then shut down the DNA services (which will block until all sequencing has been completed) ...
Thread.sleep(1000);
- client.shutdownDnaServices(); // this will block untill all processing has been done ...
+ client.shutdownDnaServices();
- List<ImageInfo> images = client.getImages();
- assertThat(images.size(), is(1));
- for (ImageInfo image : images) {
- System.out.println("Image: " + image);
- }
+ // The sequencers should have run, so perform the search.
+ // The mock user interface checks the results.
+ client.search();
+
+ assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
}
}
Added: trunk/docs/gettingstarted/en/images/example-sequencer-cli-client.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/gettingstarted/en/images/example-sequencer-cli-client.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/gettingstarted/en/images/example-sequencer-search.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/gettingstarted/en/images/example-sequencer-search.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/gettingstarted/en/images/example-sequencer-search2.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/gettingstarted/en/images/example-sequencer-search2.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/gettingstarted/en/images/example-sequencer-statistics.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/gettingstarted/en/images/example-sequencer-statistics.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/gettingstarted/en/images/example-sequencer-statistics2.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/gettingstarted/en/images/example-sequencer-statistics2.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/gettingstarted/en/images/example-sequencer-upload.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/gettingstarted/en/images/example-sequencer-upload.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/gettingstarted/en/images/example-sequencer-upload2.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/gettingstarted/en/images/example-sequencer-upload2.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: trunk/docs/gettingstarted/en/master.xml
===================================================================
--- trunk/docs/gettingstarted/en/master.xml 2008-05-07 16:26:20 UTC (rev 121)
+++ trunk/docs/gettingstarted/en/master.xml 2008-05-07 20:43:55 UTC (rev 122)
@@ -611,18 +611,18 @@
you can package into a distributable form.</para>
<para>
The examples created for this User Guide use Maven2 to achieve exactly this so it is highly recommended that you
- <ulink url="http://labs.jboss.com/file-access/default/members/jbossmc/downloads/userG...">download</ulink>
+ <ulink url="http://www.jboss.org/file-access/default/members/dna/downloads/0.1/jboss-...">download</ulink>
these first and take a look at how they work.
</para>
<note>
<para>
- To build and run the examples you first need to install and configure Maven 2.0.7 available from
+ To build and run the examples you first need to install and configure Maven 2.0.7 (or higher), available from
<ulink url="http://maven.apache.org/">http://maven.apache.org/</ulink>
</para>
<para>Installation is performed by downloading and unzipping the maven-2.0.7-bin.zip file to a convenient
location on your local disk. Configuration consists of adding $MAVEN_HOME/bin to your path and adding the following
profile to your ~/.m2/settings.xml file:</para>
- <programlisting role="XML"><settings>
+ <programlisting role="XML" language="xml"><settings>
<profiles>
<profile>
<id>jboss.repository</id>
@@ -666,28 +666,216 @@
</profile>
</profiles>
</settings></programlisting>
- <para>This profile informs maven of the two JBoss repositories (snapshots and releases) that are needed to download the JBoss Microcontainer and dependant JARs.</para>
+ <para>This profile informs Maven of the two JBoss repositories (snapshots and releases) that are needed to download the JARs for JBoss DNA and all dependent libraries.</para>
</note>
- <para>Once you have configured Maven and downloaded the examples then you can go to one of the following subdirectories in the <code>examples/User_Guide</code> directory and enter <code>mvn install</code> to perform a build:</para>
- <itemizedlist>
- <listitem>
- <para>gettingStarted - projects for creating and using a service together with AOP</para>
- </listitem>
- <listitem>
- <para>pojoDevelopment - examples of creating and configuring POJOs using XML and annotations</para>
- </listitem>
- <listitem>
- <para>aopDevelopment - examples of using AOP to add behaviour to POJOs</para>
- </listitem>
- <listitem>
- <para>extending - examples of how we created various extensions to the microcontainer by creating new dependencies</para>
- </listitem>
- </itemizedlist>
- <para>Instructions on how to run the individual examples can be found in the corresponding parts of this guide.</para>
+ <para>After you have configured Maven and extracted the examples to a working folder, you can go to the <code>examples</code>
+ subdirectory and enter <code>mvn install</code> to perform a build. Maven will automatically download all of the libraries
+ that are needed by the build, saving them to your local machine. (This means the next time you run <code>mvn install</code>,
+ all the libraries will be local, and the build will run much faster.)
+ </para>
+ <para>The build is successful if you see the following:</para>
+ <programlisting language="bash">$ mvn install
+...
+[INFO] ------------------------------------------------------------------------
+[INFO] Reactor Summary:
+[INFO] ------------------------------------------------------------------------
+[INFO] Getting Started examples .............................. SUCCESS [2.106s]
+[INFO] Sequencer Examples .................................... SUCCESS [9.768s]
+[INFO] ------------------------------------------------------------------------
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESSFUL
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 12 seconds
+[INFO] Finished at: Wed May 07 12:00:06 CDT 2008
+[INFO] Final Memory: 14M/28M
+[INFO] ------------------------------------------------------------------------
+$ </programlisting>
+ <para>If there are errors, check whether you have the correct version of Maven installed and that you've correctly updated
+ your Maven settings as described above.</para>
+ <para>
+ The <link linkend="using_dna">next chapter</link> shows you how to run the examples and walks through the source code to
+ show you how to use JBoss DNA.</para>
</chapter>
<chapter id="using_dna">
<title>Using JBoss DNA</title>
- <para></para>
+ <para>With this release, JBoss DNA is able to monitor existing JCR repositories and automatically sequence newly upload files and updated content.
+ The information produced by the sequencers are saved to the repository, making it available to any repository client.
+ Using JBoss DNA, therefore, consists of setting up the DNA Java components and connecting them to the JCR repositories.
+ This chapter walks you through this process, using the examples downloaded in the <link linkend="downloading">previous chapter</link>.
+ </para>
+ <para>You will find all of the necessary files for the example in the <code>examples/sequencers</code> directory, which follows the
+ Maven Standard Directory Layout:
+ <programlisting>
+sequencers/pom.xml
+ /src/main/assembly
+ /config
+ /java
+ /resources
+ /test/java
+ /resources
+ </programlisting>
+ </para>
+ <para>This example consists of a client application that sets up an in-memory JCR repository and that allows a user
+ to upload files into that repository. The client also sets up the DNA services with an image sequencer so that
+ if any of the uploaded files are PNG, JPEG, GIF, BMP or other images, DNA will automatically extract the image's
+ metadata (e.g., image format, physical size, pixel density, etc.) and store that in the repository.
+ </para>
+ <para>The example is comprised of 3 classes and 1 interface, located in the <code>src/main/java</code> directory:
+ <programlisting>
+org/jboss/example/dna/sequencers/ConsoleInput.java
+ /ImageInfo.java
+ /SequencingClient.java
+ /UserInterface.java
+ </programlisting>
+ </para>
+ <para>
+ <code>SequencingClient</code> is the class that contains the main application. <code>ImageInfo</code> is a simple
+ Java object that encapsulates metadata about an image (as generated by the sequencer), and used by the client to pass
+ information to the <code>UserInterface</code>, which is an interface with methods that will be called at
+ runtime to request data from the user. <code>ConsoleInput</code> is an implementation of this that creates a text user interface,
+ allowing the user to operate the client from the command line. We can easily create a graphical implementation of
+ <code>UserInterface</code> at a later date. We can also create a mock implementation for
+ testing purposes that simulates a user entering data. This allows us to check the behaviour of the client automatically using conventional
+ JUnit test cases, as demonstrated by the code in the <code>src/test/java</code> directory:
+ <programlisting>
+org/jboss/example/dna/sequencers/SequencingClientTest.java
+ /MockUserInterface.java
+ </programlisting>
+ </para>
+ <para>
+ As mentioned in the <ulink url="downloading">previous chapter</ulink>, simply type <code>mvn package</code> from the <code>example/sequencer</code>
+ directory to compile the source code, run the unit tests, build a client JAR and assemble a distribution containing all of the necessary files.
+ </para>
+ <para>If you successfully built the examples, there will be a <code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
+ directory that contains the following:
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="strong"><code>run.sh</code></emphasis> is the *nix shell script that will run the example.</para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>log4j.properties</code>
+ </emphasis>
+ is the Log4J configuration file.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>jackrabbitConfig.xml</code>
+ </emphasis>
+ is the Jackrabbit configuration file, which is set up to use a transient in-memory repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>jackrabbitNodeTypes.cnd</code>
+ </emphasis>
+ defines the additional JCR node types used by this example.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>caution.gif</code>
+ </emphasis>, <emphasis role="strong">
+ <code>caution.png</code>
+ </emphasis>, and <emphasis role="strong">
+ <code>caution.jpg</code>
+ </emphasis>
+ are images that you'll use later and upload into the repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">
+ <code>lib</code>
+ </emphasis>
+ subdirectory contains the JARs for all of the JBoss DNA artifacts as well as those for other libraries required
+ by JBoss DNA and the example.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <note>
+ <para>JBoss DNA 0.1 and the examples are currently tested with <ulink url="http://jackrabbit.apache.org/">Apache Jackrabbit</ulink> version 1.3.3.
+ This version is stable and used by a number of other projects and applications. However, you should be able to use a newer
+ version of Jackrabbit, as long as that version uses the same JCR API. For example, version 1.4.2 was released on March 26, 2008 and
+ should be compatible.
+ </para>
+ <para>Just remember, if the version of Jackrabbit you want to use for these examples is not in the Maven repository,
+ you'll have to either add it or add it locally. For more information, see the <ulink url="http://maven.apache.org/">Maven documentation</ulink>.
+ </para>
+ </note>
+ </para>
+ <para>
+ To run the client application, go to the <code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code>
+ directory and type <code>./run.sh</code>. You should see the command line client and its menus in your terminal:
+ <figure id="xample-sequencer-cli-client">
+ <title>Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-cli-client.png" />
+ </figure>
+ From this menu, you can upload a file into the repository, search for images in the repository, print sequencing statistics, or quit the application.
+ </para>
+ <para>
+ The first step is to upload one of the example images. If you type 'u' and press return, you'll be prompted
+ to supply the path to the file you want to upload. Since the application is running from within the
+ <code>examples/sequencers/target/dna-example-sequencers-basic.dir/</code> directory, you can specify any
+ of the files in that directory without specifying the path:
+ <figure id="example-sequencer-upload">
+ <title>Uploading an image using the Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-upload.png" />
+ </figure>
+ However, you can specify any fully-qualified or relative path. The application will notify you if it cannot
+ find the file you specified.
+ </para>
+ <para>
+ After you specified the file you want to upload, the example application asks you where in the repository you'd
+ like to place the file. (If you want to use the suggested location, just press <code>return</code>.)
+ The client application uses the JCR API to upload the file to that location in the repository, creating any nodes (of type <code>nt:folder</code>)
+ for any directories that don't exist, and creating a node (of type <code>nt:file</code>) for the file. And,
+ per the JCR specification, the application creates a <code>jcr:content</code> node (of type <code>nt:resource</code>)
+ under the file node. The file contents are placed on this <code>jcr:content</code> node in the <code>jcr:data</code> property.
+ For example, if you specify <code>/a/b/caution.png</code>, the following structure will be created in the repository:
+ <programlisting>
+ /a (nt:folder)
+ /b (nt:folder)
+ /caution.png (nt:file)
+ /jcr:content (nt:resource)
+ @jcr:data = {contents of the file}
+ @jcr:mimeType = {mime type of the file}
+ @jcr:lastModified = {now}
+ </programlisting>
+ </para>
+ <para>
+ When the client uploads the file using the JCR API, DNA gets notified of the changes, consults the sequencers
+ to see whether any of them are interested in the new or updated content, and if so runs the sequencers. The image
+ sequencer processes image files for metadata, and any metadata found is stored under the <code>/images</code>
+ branch of the repository.
+ </para>
+ <para>
+ So, very soon after the file is uploaded, DNA will sequence the image file and store the metadata.
+ You can search the repository for this metadata using the "s" menu option:
+ <figure id="example-sequencer-search">
+ <title>Uploading an image using the Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-search.png" />
+ </figure>
+ You can also print the statistics for the sequencer using the "p" menu option:
+ <figure id="example-sequencer-statistics">
+ <title>Uploading an image using the Example Client</title>
+ <graphic align="center" scale="100" fileref="images/example-sequencer-statistics.png" />
+ </figure>
+ </para>
+ <para>
+ You can repeat this process with other files. Any file that isn't an image (as recognized by the sequencing configuration
+ described later) will not be sequenced.
+ </para>
+
+
+
+
+
</chapter>
<chapter id="custom_sequencers">
<title>Custom sequencers</title>
16 years
DNA SVN: r121 - in trunk/dna-common/src/main: resources/org/jboss/dna/common and 1 other directory.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-05-07 12:26:20 -0400 (Wed, 07 May 2008)
New Revision: 121
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java
trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties
Log:
DNA-59: Removed I18n.replaceParameters methods and replaced all usages with StringUtil.createString, which now contains the same logic sans i18n stuff. The I18n usage of createString modifies any thrown exception to include information identifying where the exception occurred. Also added some test cases for createString to StringUtilTest.
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java 2008-05-07 16:25:17 UTC (rev 120)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java 2008-05-07 16:26:20 UTC (rev 121)
@@ -34,21 +34,6 @@
// Make sure the following I18n.java-related fields are defined before all other fields to ensure a valid error message is
// produced in the event of a missing/duplicate/unused property
- /**
- * Parameters:
- * <ol>
- * <li>{@link I18n#id() ID}</li>
- * <li>Number of supplied arguments</li>
- * <li>Localized text before parameter substitution</li>
- * <li>Localized text after parameter substitution</li>
- * </ol>
- */
- public static I18n i18nArgumentsMismatchedParameter;
- public static I18n i18nArgumentMismatchedParameters;
- public static I18n i18nArgumentsMismatchedParameters;
- public static I18n i18nReplaceArgumentsMismatchedParameter;
- public static I18n i18nReplaceArgumentMismatchedParameters;
- public static I18n i18nReplaceArgumentsMismatchedParameters;
public static I18n i18nClassInterface;
public static I18n i18nClassNotPublic;
public static I18n i18nFieldFinal;
@@ -56,26 +41,21 @@
public static I18n i18nFieldNotPublic;
public static I18n i18nFieldNotStatic;
public static I18n i18nLocalizationFileNotFound;
- public static I18n i18nLocalizationProblems;
+ public static I18n i18nLocalizationProblems;
+ public static I18n i18nRequiredToSuppliedParameterMismatch;
- /**
- * Parameters:
- * <ol>
- * <li>{@link I18n#id() Property}</li>
- * <li>Localization file URL</li>
- * </ol>
- */
+ /**
+ * Parameters:
+ * <ol>
+ * <li>{@link I18n#id() Property}</li>
+ * <li>Localization file URL</li>
+ * </ol>
+ */
public static I18n i18nPropertyDuplicate;
public static I18n i18nPropertyMissing;
public static I18n i18nPropertyUnused;
// Core-related fields
- public static I18n componentClassnameNotValid;
- public static I18n componentNotConfigured;
- public static I18n progressMonitorBeginTask;
- public static I18n progressMonitorStatus;
- public static I18n nullProgressMonitorTaskName;
-
public static I18n argumentMayNotBeNegative;
public static I18n argumentMayNotBePositive;
public static I18n argumentMustBeNegative;
@@ -94,14 +74,19 @@
public static I18n argumentDidNotContainObject;
public static I18n argumentDidNotContainKey;
public static I18n argumentMayNotContainNullValue;
-
+ public static I18n componentClassnameNotValid;
+ public static I18n componentNotConfigured;
public static I18n dateParsingFailure;
-
+ public static I18n initialProgressMonitorTaskName;
+ public static I18n nullProgressMonitorTaskName;
public static I18n pathAncestorDegreeIsInvalid;
public static I18n pathIsAlreadyAbsolute;
public static I18n pathIsNotAbsolute;
public static I18n pathIsNotRelative;
public static I18n pathCannotBeNormalized;
+ public static I18n progressMonitorBeginTask;
+ public static I18n progressMonitorStatus;
+ public static I18n requiredToSuppliedParameterMismatch;
static {
try {
@@ -112,14 +97,14 @@
}
public static Set<Locale> getLocalizationProblemLocales() {
- return I18n.getLocalizationProblemLocales(CommonI18n.class);
- }
+ return I18n.getLocalizationProblemLocales(CommonI18n.class);
+ }
public static Set<String> getLocalizationProblems() {
- return I18n.getLocalizationProblems(CommonI18n.class);
- }
+ return I18n.getLocalizationProblems(CommonI18n.class);
+ }
public static Set<String> getLocalizationProblems( Locale locale ) {
- return I18n.getLocalizationProblems(CommonI18n.class, locale);
- }
+ return I18n.getLocalizationProblems(CommonI18n.class, locale);
+ }
}
Modified: trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties
===================================================================
--- trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties 2008-05-07 16:25:17 UTC (rev 120)
+++ trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties 2008-05-07 16:26:20 UTC (rev 121)
@@ -1,12 +1,6 @@
# Make sure the following I18n.java-related properties are defined before all other properties to ensure a valid error message is
# produced in the event of a missing/duplicate/unused property
-i18nArgumentsMismatchedParameter = {0} arguments were supplied to internationalization object "{1}", but 1 parameter is required: "{2}" => "{3}"
-i18nArgumentMismatchedParameters = 1 argument was supplied to internationalization object "{0}", but {1} parameters are required: "{2}" => "{3}"
-i18nArgumentsMismatchedParameters = {0} arguments were supplied to internationalization object "{1}", but {2} parameters are required: "{3}" => "{4}"
-i18nReplaceArgumentsMismatchedParameter = {0} arguments were supplied, but 1 parameter is required: "{1}" => "{2}"
-i18nReplaceArgumentMismatchedParameters = 1 argument was supplied, but {0} parameters are required: "{1}" => "{2}"
-i18nReplaceArgumentsMismatchedParameters = {0} arguments were supplied, but {1} parameters are required: "{2}" => "{3}"
i18nClassInterface = Internationalization class {0} must not be an interface.
i18nClassNotPublic = Internationalization {0} must be public.
i18nFieldFinal = Internationalization field "{0}" in {1} must not be final.
@@ -18,14 +12,9 @@
i18nPropertyDuplicate = Duplicate property values were found for property "{0}" in localization file "{1}";
i18nPropertyMissing = Missing property "{0}" in localization file "{1}".
i18nPropertyUnused = An unused property, "{0}", was found in localization file "{1}".
+i18nRequiredToSuppliedParameterMismatch = Internationalization field "{0}" in {1}: {2}
# Core-related fields
-componentClassnameNotValid = The class name {0} specified for {1} is not a valid Java class name
-componentNotConfigured = The component {0} was not configured and will not be used
-progressMonitorBeginTask = Beginning {0} ({1})
-progressMonitorStatus = {0}
-nullProgressMonitorTaskName = Not available
-
argumentMayNotBeNegative = The {0} argument value, {1}, may not be negative
argumentMayNotBePositive = The {0} argument value, {1}, may not be positive
argumentMustBeNegative = The {0} argument value, {1}, must be negative
@@ -44,11 +33,16 @@
argumentDidNotContainObject = "The {0} argument did not contain the expected object {1}
argumentDidNotContainKey = "The {0} argument did not contain the expected key {1}
argumentMayNotContainNullValue = The {0} argument may not contain a null value (first null found at position {1})
-
+componentClassnameNotValid = The class name {0} specified for {1} is not a valid Java class name
+componentNotConfigured = The component {0} was not configured and will not be used
+dateParsingFailure = Unable to parse the date "{0}" using the standard ISO 8601 format
+initialProgressMonitorTaskName =
+nullProgressMonitorTaskName = Not available
pathAncestorDegreeIsInvalid = Unable to obtain the {1} ancestor for {0}
pathIsAlreadyAbsolute = The path {0} is already an absolute path
pathIsNotAbsolute = The path {0} is not an absolute path
pathIsNotRelative = The path {0} is not a relative path
pathCannotBeNormalized = The path {0} is invalid and cannot be normalized
-
-dateParsingFailure = Unable to parse the date "{0}" using the standard ISO 8601 format
+progressMonitorBeginTask = Beginning {0} ({1})
+progressMonitorStatus = {0}
+requiredToSuppliedParameterMismatch = {0} parameter{1} supplied, but {2} parameter{3} required: "{4}" => "{5}"
16 years
DNA SVN: r120 - in trunk/dna-common/src: main/java/org/jboss/dna/common/util and 2 other directories.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-05-07 12:25:17 -0400 (Wed, 07 May 2008)
New Revision: 120
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/i18n/I18n.java
trunk/dna-common/src/main/java/org/jboss/dna/common/util/Logger.java
trunk/dna-common/src/main/java/org/jboss/dna/common/util/StringUtil.java
trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/I18nTest.java
trunk/dna-common/src/test/java/org/jboss/dna/common/util/StringUtilTest.java
Log:
DNA-59: Removed I18n.replaceParameters methods and replaced all usages with StringUtil.createString, which now contains the same logic sans i18n stuff. The I18n usage of createString modifies any thrown exception to include information identifying where the exception occurred. Also added some test cases for createString to StringUtilTest.
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/i18n/I18n.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/i18n/I18n.java 2008-05-07 13:37:37 UTC (rev 119)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/i18n/I18n.java 2008-05-07 16:25:17 UTC (rev 120)
@@ -36,13 +36,12 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.CommonI18n;
import org.jboss.dna.common.SystemFailureException;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.common.util.ClassUtil;
+import org.jboss.dna.common.util.StringUtil;
/**
* Manages the initialization of internationalization (i18n) files, substitution of values within i18n message placeholders, and
@@ -54,8 +53,6 @@
@ThreadSafe
public final class I18n {
- private static final Pattern PARAMETER_COUNT_PATTERN = Pattern.compile("\\{(\\d+)\\}");
- private static final Object[] EMPTY_ARGUMENTS = new Object[] {};
private static final LocalizationRepository DEFAULT_LOCALIZATION_REPOSITORY = new ClasspathLocalizationRepository();
/**
@@ -309,86 +306,6 @@
}
}
- /**
- * Substitute the arguments into the message, ensuring that the number of arguments matches the number of parameters in the
- * text.
- *
- * @param id the id of the internationalization object
- * @param text
- * @param arguments
- * @return the text with parameters replaced
- */
- protected static String replaceParameters( String id,
- String text,
- Object... arguments ) {
- if (arguments == null) arguments = EMPTY_ARGUMENTS;
- Matcher matcher = PARAMETER_COUNT_PATTERN.matcher(text);
- StringBuffer newText = new StringBuffer();
- int argCount = 0;
- boolean err = false;
- while (matcher.find()) {
- int ndx = Integer.valueOf(matcher.group(1));
- if (argCount <= ndx) {
- argCount = ndx + 1;
- }
- if (ndx >= arguments.length) {
- err = true;
- matcher.appendReplacement(newText, matcher.group());
- } else {
- Object arg = arguments[ndx];
- if (arg != null) {
- matcher.appendReplacement(newText, Matcher.quoteReplacement(arg.toString()));
- } else {
- matcher.appendReplacement(newText, Matcher.quoteReplacement("null"));
- }
- }
- }
- if (err || argCount < arguments.length) {
- String msg = null;
- if (id != null) {
- if (arguments.length == 1) {
- msg = CommonI18n.i18nArgumentMismatchedParameters.text(id, argCount, text, newText.toString());
- } else if (argCount == 1) {
- msg = CommonI18n.i18nArgumentsMismatchedParameter.text(arguments.length, id, text, newText.toString());
- } else {
- msg = CommonI18n.i18nArgumentsMismatchedParameters.text(arguments.length,
- id,
- argCount,
- text,
- newText.toString());
- }
- throw new IllegalArgumentException(msg);
- }
- if (arguments.length == 1) {
- msg = CommonI18n.i18nReplaceArgumentMismatchedParameters.text(argCount, text, newText.toString());
- } else if (argCount == 1) {
- msg = CommonI18n.i18nReplaceArgumentsMismatchedParameter.text(arguments.length, text, newText.toString());
- } else {
- msg = CommonI18n.i18nReplaceArgumentsMismatchedParameters.text(arguments.length,
- argCount,
- text,
- newText.toString());
- }
- throw new IllegalArgumentException(msg);
- }
- matcher.appendTail(newText);
-
- return newText.toString();
- }
-
- /**
- * Substitute the arguments into the message, ensuring that the number of arguments matches the number of parameters in the
- * text.
- *
- * @param text
- * @param arguments
- * @return the text with parameters replaced
- */
- public static String replaceParameters( String text,
- Object... arguments ) {
- return replaceParameters(null, text, arguments);
- }
-
private final String id;
private final Class i18nClass;
final ConcurrentHashMap<Locale, String> localeToTextMap = new ConcurrentHashMap<Locale, String>();
@@ -495,7 +412,11 @@
Object... arguments ) {
try {
String rawText = rawText(locale == null ? Locale.getDefault() : locale);
- return replaceParameters(id, rawText, arguments);
+ return StringUtil.createString(rawText, arguments);
+ } catch (IllegalArgumentException err) {
+ throw new IllegalArgumentException(CommonI18n.i18nRequiredToSuppliedParameterMismatch.text(id,
+ i18nClass,
+ err.getMessage()));
} catch (SystemFailureException err) {
return '<' + err.getMessage() + '>';
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/util/Logger.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/util/Logger.java 2008-05-07 13:37:37 UTC (rev 119)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/util/Logger.java 2008-05-07 16:25:17 UTC (rev 120)
@@ -2,7 +2,7 @@
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -36,348 +36,391 @@
@ThreadSafe
public final class Logger {
- public enum Level {
- OFF,
- ERROR,
- WARNING,
- INFO,
- DEBUG,
- TRACE;
- }
+ public enum Level {
+ OFF,
+ ERROR,
+ WARNING,
+ INFO,
+ DEBUG,
+ TRACE;
+ }
- private static final AtomicReference<Locale> LOGGING_LOCALE = new AtomicReference<Locale>(null);
+ private static final AtomicReference<Locale> LOGGING_LOCALE = new AtomicReference<Locale>(null);
- /**
- * Get the locale used for the logs. If null, the {@link Locale#getDefault() default locale} is used.
- * @return the current locale used for logging, or null if the system locale is used
- * @see #setLoggingLocale(Locale)
- */
- public static Locale getLoggingLocale() {
- return LOGGING_LOCALE.get();
- }
+ /**
+ * Get the locale used for the logs. If null, the {@link Locale#getDefault() default locale} is used.
+ *
+ * @return the current locale used for logging, or null if the system locale is used
+ * @see #setLoggingLocale(Locale)
+ */
+ public static Locale getLoggingLocale() {
+ return LOGGING_LOCALE.get();
+ }
- /**
- * Set the locale used for the logs. This should be used when the logs are to be written is a specific locale, independent of
- * the {@link Locale#getDefault() default locale}. To use the default locale, call this method with a null value.
- * @param locale the desired locale to use for the logs, or null if the system locale should be used
- * @return the previous locale
- * @see #getLoggingLocale()
- */
- public static Locale setLoggingLocale( Locale locale ) {
- return LOGGING_LOCALE.getAndSet(locale != null ? locale : Locale.getDefault());
- }
+ /**
+ * Set the locale used for the logs. This should be used when the logs are to be written is a specific locale, independent of
+ * the {@link Locale#getDefault() default locale}. To use the default locale, call this method with a null value.
+ *
+ * @param locale the desired locale to use for the logs, or null if the system locale should be used
+ * @return the previous locale
+ * @see #getLoggingLocale()
+ */
+ public static Locale setLoggingLocale( Locale locale ) {
+ return LOGGING_LOCALE.getAndSet(locale != null ? locale : Locale.getDefault());
+ }
- /**
- * Return a logger named corresponding to the class passed as parameter, using the statically bound {@link ILoggerFactory}
- * instance.
- * @param clazz the returned logger will be named after clazz
- * @return logger
- */
- public static Logger getLogger( Class clazz ) {
- return new Logger(LoggerFactory.getLogger(clazz));
- }
+ /**
+ * Return a logger named corresponding to the class passed as parameter, using the statically bound {@link ILoggerFactory}
+ * instance.
+ *
+ * @param clazz the returned logger will be named after clazz
+ * @return logger
+ */
+ public static Logger getLogger( Class clazz ) {
+ return new Logger(LoggerFactory.getLogger(clazz));
+ }
- /**
- * Return a logger named according to the name parameter using the statically bound {@link ILoggerFactory} instance.
- * @param name The name of the logger.
- * @return logger
- */
- public static Logger getLogger( String name ) {
- return new Logger(LoggerFactory.getLogger(name));
- }
+ /**
+ * Return a logger named according to the name parameter using the statically bound {@link ILoggerFactory} instance.
+ *
+ * @param name The name of the logger.
+ * @return logger
+ */
+ public static Logger getLogger( String name ) {
+ return new Logger(LoggerFactory.getLogger(name));
+ }
- private final org.slf4j.Logger delegate;
+ private final org.slf4j.Logger delegate;
- private Logger( org.slf4j.Logger delegate ) {
- this.delegate = delegate;
- }
+ private Logger( org.slf4j.Logger delegate ) {
+ this.delegate = delegate;
+ }
- /**
- * Return the name of this logger instance.
- * @return the logger's name
- */
- public String getName() {
- return this.delegate.getName();
- }
+ /**
+ * Return the name of this logger instance.
+ *
+ * @return the logger's name
+ */
+ public String getName() {
+ return this.delegate.getName();
+ }
- /**
- * Log a message at the suplied level according to the specified format and (optional) parameters. The message should contain
- * a pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is
- * efficient and avoids superfluous object creation when the logger is disabled for the desired level.
- * @param level the level at which to log
- * @param message the (localized) message string
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void log( Level level, I18n message, Object... params ) {
- if (message == null) return;
- switch (level) {
- case DEBUG:
- debug(message.text(LOGGING_LOCALE.get(), params));
- break;
- case ERROR:
- error(message, params);
- break;
- case INFO:
- info(message, params);
- break;
- case TRACE:
- trace(message.text(LOGGING_LOCALE.get(), params));
- break;
- case WARNING:
- warn(message, params);
- break;
- case OFF:
- break;
- }
- }
+ /**
+ * Log a message at the suplied level according to the specified format and (optional) parameters. The message should contain
+ * a pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is
+ * efficient and avoids superfluous object creation when the logger is disabled for the desired level.
+ *
+ * @param level the level at which to log
+ * @param message the (localized) message string
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void log( Level level,
+ I18n message,
+ Object... params ) {
+ if (message == null) return;
+ switch (level) {
+ case DEBUG:
+ debug(message.text(LOGGING_LOCALE.get(), params));
+ break;
+ case ERROR:
+ error(message, params);
+ break;
+ case INFO:
+ info(message, params);
+ break;
+ case TRACE:
+ trace(message.text(LOGGING_LOCALE.get(), params));
+ break;
+ case WARNING:
+ warn(message, params);
+ break;
+ case OFF:
+ break;
+ }
+ }
- /**
- * Log an exception (throwable) at the supplied level with an accompanying message. If the exception is null, then this method
- * calls {@link #debug(String, Object...)}.
- * @param level the level at which to log
- * @param t the exception (throwable) to log
- * @param message the message accompanying the exception
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void log( Level level, Throwable t, I18n message, Object... params ) {
- if (message == null) return;
- switch (level) {
- case DEBUG:
- debug(t, message.text(LOGGING_LOCALE.get(), params));
- break;
- case ERROR:
- error(t, message, params);
- break;
- case INFO:
- info(t, message, params);
- break;
- case TRACE:
- trace(t, message.text(LOGGING_LOCALE.get(), params));
- break;
- case WARNING:
- warn(t, message, params);
- break;
- case OFF:
- break;
- }
- }
+ /**
+ * Log an exception (throwable) at the supplied level with an accompanying message. If the exception is null, then this method
+ * calls {@link #debug(String, Object...)}.
+ *
+ * @param level the level at which to log
+ * @param t the exception (throwable) to log
+ * @param message the message accompanying the exception
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void log( Level level,
+ Throwable t,
+ I18n message,
+ Object... params ) {
+ if (message == null) return;
+ switch (level) {
+ case DEBUG:
+ debug(t, message.text(LOGGING_LOCALE.get(), params));
+ break;
+ case ERROR:
+ error(t, message, params);
+ break;
+ case INFO:
+ info(t, message, params);
+ break;
+ case TRACE:
+ trace(t, message.text(LOGGING_LOCALE.get(), params));
+ break;
+ case WARNING:
+ warn(t, message, params);
+ break;
+ case OFF:
+ break;
+ }
+ }
- /**
- * Log a message at the DEBUG level according to the specified format and (optional) parameters. The message should contain a
- * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
- * and avoids superfluous object creation when the logger is disabled for the DEBUG level.
- * @param message the message string
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void debug( String message, Object... params ) {
- if (!isDebugEnabled()) return;
- if (message == null) return;
- this.delegate.debug(I18n.replaceParameters(message, params));
- }
+ /**
+ * Log a message at the DEBUG level according to the specified format and (optional) parameters. The message should contain a
+ * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
+ * and avoids superfluous object creation when the logger is disabled for the DEBUG level.
+ *
+ * @param message the message string
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void debug( String message,
+ Object... params ) {
+ if (!isDebugEnabled()) return;
+ if (message == null) return;
+ this.delegate.debug(StringUtil.createString(message, params));
+ }
- /**
- * Log an exception (throwable) at the DEBUG level with an accompanying message. If the exception is null, then this method
- * calls {@link #debug(String, Object...)}.
- * @param t the exception (throwable) to log
- * @param message the message accompanying the exception
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void debug( Throwable t, String message, Object... params ) {
- if (!isDebugEnabled()) return;
- if (t == null) {
- debug(message, params);
- return;
- }
- if (message == null) {
- this.delegate.debug(null, t);
- return;
- }
- this.delegate.debug(I18n.replaceParameters(message, params), t);
- }
+ /**
+ * Log an exception (throwable) at the DEBUG level with an accompanying message. If the exception is null, then this method
+ * calls {@link #debug(String, Object...)}.
+ *
+ * @param t the exception (throwable) to log
+ * @param message the message accompanying the exception
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void debug( Throwable t,
+ String message,
+ Object... params ) {
+ if (!isDebugEnabled()) return;
+ if (t == null) {
+ debug(message, params);
+ return;
+ }
+ if (message == null) {
+ this.delegate.debug(null, t);
+ return;
+ }
+ this.delegate.debug(StringUtil.createString(message, params), t);
+ }
- /**
- * Log a message at the ERROR level according to the specified format and (optional) parameters. The message should contain a
- * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
- * and avoids superfluous object creation when the logger is disabled for the ERROR level.
- * @param message the message string
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void error( I18n message, Object... params ) {
- if (!isErrorEnabled()) return;
- if (message == null) return;
- this.delegate.error(message.text(LOGGING_LOCALE.get(), params));
- }
+ /**
+ * Log a message at the ERROR level according to the specified format and (optional) parameters. The message should contain a
+ * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
+ * and avoids superfluous object creation when the logger is disabled for the ERROR level.
+ *
+ * @param message the message string
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void error( I18n message,
+ Object... params ) {
+ if (!isErrorEnabled()) return;
+ if (message == null) return;
+ this.delegate.error(message.text(LOGGING_LOCALE.get(), params));
+ }
- /**
- * Log an exception (throwable) at the ERROR level with an accompanying message. If the exception is null, then this method
- * calls {@link #error(I18n, Object...)}.
- * @param t the exception (throwable) to log
- * @param message the message accompanying the exception
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void error( Throwable t, I18n message, Object... params ) {
- if (!isErrorEnabled()) return;
- if (t == null) {
- error(message, params);
- return;
- }
- if (message == null) {
- this.delegate.error(null, t);
- return;
- }
- this.delegate.error(message.text(LOGGING_LOCALE.get(), params), t);
- }
+ /**
+ * Log an exception (throwable) at the ERROR level with an accompanying message. If the exception is null, then this method
+ * calls {@link #error(I18n, Object...)}.
+ *
+ * @param t the exception (throwable) to log
+ * @param message the message accompanying the exception
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void error( Throwable t,
+ I18n message,
+ Object... params ) {
+ if (!isErrorEnabled()) return;
+ if (t == null) {
+ error(message, params);
+ return;
+ }
+ if (message == null) {
+ this.delegate.error(null, t);
+ return;
+ }
+ this.delegate.error(message.text(LOGGING_LOCALE.get(), params), t);
+ }
- /**
- * Log a message at the INFO level according to the specified format and (optional) parameters. The message should contain a
- * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
- * and avoids superfluous object creation when the logger is disabled for the INFO level.
- * @param message the message string
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void info( I18n message, Object... params ) {
- if (!isInfoEnabled()) return;
- if (message == null) return;
- this.delegate.info(message.text(LOGGING_LOCALE.get(), params));
- }
+ /**
+ * Log a message at the INFO level according to the specified format and (optional) parameters. The message should contain a
+ * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
+ * and avoids superfluous object creation when the logger is disabled for the INFO level.
+ *
+ * @param message the message string
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void info( I18n message,
+ Object... params ) {
+ if (!isInfoEnabled()) return;
+ if (message == null) return;
+ this.delegate.info(message.text(LOGGING_LOCALE.get(), params));
+ }
- /**
- * Log an exception (throwable) at the INFO level with an accompanying message. If the exception is null, then this method
- * calls {@link #info(I18n, Object...)}.
- * @param t the exception (throwable) to log
- * @param message the message accompanying the exception
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void info( Throwable t, I18n message, Object... params ) {
- if (!isInfoEnabled()) return;
- if (t == null) {
- info(message, params);
- return;
- }
- if (message == null) {
- this.delegate.info(null, t);
- return;
- }
- this.delegate.info(message.text(LOGGING_LOCALE.get(), params), t);
- }
+ /**
+ * Log an exception (throwable) at the INFO level with an accompanying message. If the exception is null, then this method
+ * calls {@link #info(I18n, Object...)}.
+ *
+ * @param t the exception (throwable) to log
+ * @param message the message accompanying the exception
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void info( Throwable t,
+ I18n message,
+ Object... params ) {
+ if (!isInfoEnabled()) return;
+ if (t == null) {
+ info(message, params);
+ return;
+ }
+ if (message == null) {
+ this.delegate.info(null, t);
+ return;
+ }
+ this.delegate.info(message.text(LOGGING_LOCALE.get(), params), t);
+ }
- /**
- * Log a message at the TRACE level according to the specified format and (optional) parameters. The message should contain a
- * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
- * and avoids superfluous object creation when the logger is disabled for the TRACE level.
- * @param message the message string
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void trace( String message, Object... params ) {
- if (!isTraceEnabled()) return;
- if (message == null) return;
- this.delegate.trace(I18n.replaceParameters(message, params));
- }
+ /**
+ * Log a message at the TRACE level according to the specified format and (optional) parameters. The message should contain a
+ * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient
+ * and avoids superfluous object creation when the logger is disabled for the TRACE level.
+ *
+ * @param message the message string
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void trace( String message,
+ Object... params ) {
+ if (!isTraceEnabled()) return;
+ if (message == null) return;
+ this.delegate.trace(StringUtil.createString(message, params));
+ }
- /**
- * Log an exception (throwable) at the TRACE level with an accompanying message. If the exception is null, then this method
- * calls {@link #trace(String, Object...)}.
- * @param t the exception (throwable) to log
- * @param message the message accompanying the exception
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void trace( Throwable t, String message, Object... params ) {
- if (!isTraceEnabled()) return;
- if (t == null) {
- this.trace(message, params);
- return;
- }
- if (message == null) {
- this.delegate.trace(null, t);
- return;
- }
- this.delegate.trace(I18n.replaceParameters(message, params), t);
- }
+ /**
+ * Log an exception (throwable) at the TRACE level with an accompanying message. If the exception is null, then this method
+ * calls {@link #trace(String, Object...)}.
+ *
+ * @param t the exception (throwable) to log
+ * @param message the message accompanying the exception
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void trace( Throwable t,
+ String message,
+ Object... params ) {
+ if (!isTraceEnabled()) return;
+ if (t == null) {
+ this.trace(message, params);
+ return;
+ }
+ if (message == null) {
+ this.delegate.trace(null, t);
+ return;
+ }
+ this.delegate.trace(StringUtil.createString(message, params), t);
+ }
- /**
- * Log a message at the WARNING level according to the specified format and (optional) parameters. The message should contain
- * a pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is
- * efficient and avoids superfluous object creation when the logger is disabled for the WARNING level.
- * @param message the message string
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void warn( I18n message, Object... params ) {
- if (!isWarnEnabled()) return;
- if (message == null) return;
- this.delegate.warn(message.text(LOGGING_LOCALE.get(), params));
- }
+ /**
+ * Log a message at the WARNING level according to the specified format and (optional) parameters. The message should contain
+ * a pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is
+ * efficient and avoids superfluous object creation when the logger is disabled for the WARNING level.
+ *
+ * @param message the message string
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void warn( I18n message,
+ Object... params ) {
+ if (!isWarnEnabled()) return;
+ if (message == null) return;
+ this.delegate.warn(message.text(LOGGING_LOCALE.get(), params));
+ }
- /**
- * Log an exception (throwable) at the WARNING level with an accompanying message. If the exception is null, then this method
- * calls {@link #warn(I18n, Object...)}.
- * @param t the exception (throwable) to log
- * @param message the message accompanying the exception
- * @param params the parameter values that are to replace the variables in the format string
- */
- public void warn( Throwable t, I18n message, Object... params ) {
- if (!isWarnEnabled()) return;
- if (t == null) {
- warn(message, params);
- return;
- }
- if (message == null) {
- this.delegate.warn(null, t);
- return;
- }
- this.delegate.warn(message.text(LOGGING_LOCALE.get(), params), t);
- }
+ /**
+ * Log an exception (throwable) at the WARNING level with an accompanying message. If the exception is null, then this method
+ * calls {@link #warn(I18n, Object...)}.
+ *
+ * @param t the exception (throwable) to log
+ * @param message the message accompanying the exception
+ * @param params the parameter values that are to replace the variables in the format string
+ */
+ public void warn( Throwable t,
+ I18n message,
+ Object... params ) {
+ if (!isWarnEnabled()) return;
+ if (t == null) {
+ warn(message, params);
+ return;
+ }
+ if (message == null) {
+ this.delegate.warn(null, t);
+ return;
+ }
+ this.delegate.warn(message.text(LOGGING_LOCALE.get(), params), t);
+ }
- /**
- * Return whether messages at the INFORMATION level are being logged.
- * @return true if INFORMATION log messages are currently being logged, or false otherwise.
- */
- public boolean isInfoEnabled() {
- return this.delegate.isInfoEnabled();
- }
+ /**
+ * Return whether messages at the INFORMATION level are being logged.
+ *
+ * @return true if INFORMATION log messages are currently being logged, or false otherwise.
+ */
+ public boolean isInfoEnabled() {
+ return this.delegate.isInfoEnabled();
+ }
- /**
- * Return whether messages at the WARNING level are being logged.
- * @return true if WARNING log messages are currently being logged, or false otherwise.
- */
- public boolean isWarnEnabled() {
- return this.delegate.isWarnEnabled();
- }
+ /**
+ * Return whether messages at the WARNING level are being logged.
+ *
+ * @return true if WARNING log messages are currently being logged, or false otherwise.
+ */
+ public boolean isWarnEnabled() {
+ return this.delegate.isWarnEnabled();
+ }
- /**
- * Return whether messages at the ERROR level are being logged.
- * @return true if ERROR log messages are currently being logged, or false otherwise.
- */
- public boolean isErrorEnabled() {
- return this.delegate.isErrorEnabled();
- }
+ /**
+ * Return whether messages at the ERROR level are being logged.
+ *
+ * @return true if ERROR log messages are currently being logged, or false otherwise.
+ */
+ public boolean isErrorEnabled() {
+ return this.delegate.isErrorEnabled();
+ }
- /**
- * Return whether messages at the DEBUG level are being logged.
- * @return true if DEBUG log messages are currently being logged, or false otherwise.
- */
- public boolean isDebugEnabled() {
- return this.delegate.isDebugEnabled();
- }
+ /**
+ * Return whether messages at the DEBUG level are being logged.
+ *
+ * @return true if DEBUG log messages are currently being logged, or false otherwise.
+ */
+ public boolean isDebugEnabled() {
+ return this.delegate.isDebugEnabled();
+ }
- /**
- * Return whether messages at the TRACE level are being logged.
- * @return true if TRACE log messages are currently being logged, or false otherwise.
- */
- public boolean isTraceEnabled() {
- return this.delegate.isTraceEnabled();
- }
+ /**
+ * Return whether messages at the TRACE level are being logged.
+ *
+ * @return true if TRACE log messages are currently being logged, or false otherwise.
+ */
+ public boolean isTraceEnabled() {
+ return this.delegate.isTraceEnabled();
+ }
- /**
- * Get the logging level at which this logger is current set.
- * @return the current logging level
- */
- public Level getLevel() {
- if (this.isTraceEnabled()) return Level.TRACE;
- if (this.isDebugEnabled()) return Level.DEBUG;
- if (this.isInfoEnabled()) return Level.INFO;
- if (this.isWarnEnabled()) return Level.WARNING;
- if (this.isErrorEnabled()) return Level.ERROR;
- return Level.OFF;
- }
+ /**
+ * Get the logging level at which this logger is current set.
+ *
+ * @return the current logging level
+ */
+ public Level getLevel() {
+ if (this.isTraceEnabled()) return Level.TRACE;
+ if (this.isDebugEnabled()) return Level.DEBUG;
+ if (this.isInfoEnabled()) return Level.INFO;
+ if (this.isWarnEnabled()) return Level.WARNING;
+ if (this.isErrorEnabled()) return Level.ERROR;
+ return Level.OFF;
+ }
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/util/StringUtil.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/util/StringUtil.java 2008-05-07 13:37:37 UTC (rev 119)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/util/StringUtil.java 2008-05-07 16:25:17 UTC (rev 120)
@@ -2,7 +2,7 @@
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -35,543 +35,607 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.jboss.dna.common.CommonI18n;
import org.jboss.dna.common.SystemFailureException;
-import org.jboss.dna.common.i18n.I18n;
/**
* Utilities for string processing and manipulation.
*/
public class StringUtil {
- /**
- */
- public static final String[] EMPTY_STRING_ARRAY = new String[0];
+ public static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private static final Pattern PARAMETER_COUNT_PATTERN = Pattern.compile("\\{(\\d+)\\}");
- /**
- * Split the supplied content into lines, returning each line as an element in the returned list.
- * @param content the string content that is to be split
- * @return the list of lines; never null but may be an empty (unmodifiable) list if the supplied content is null or empty
- */
- public static List<String> splitLines( final String content ) {
- if (content == null || content.length() == 0) return Collections.emptyList();
- String[] lines = content.split("[\\r]?\\n");
- return Arrays.asList(lines);
- }
+ /**
+ * Split the supplied content into lines, returning each line as an element in the returned list.
+ *
+ * @param content the string content that is to be split
+ * @return the list of lines; never null but may be an empty (unmodifiable) list if the supplied content is null or empty
+ */
+ public static List<String> splitLines( final String content ) {
+ if (content == null || content.length() == 0) return Collections.emptyList();
+ String[] lines = content.split("[\\r]?\\n");
+ return Arrays.asList(lines);
+ }
- /**
- * Create a string by substituting the parameters into all key occurrences in the supplied format. The pattern consists of
- * zero or more keys of the form <code>{n}</code>, where <code>n</code> is an integer starting at 1. Therefore, the first
- * parameter replaces all occurrences of "{1}", the second parameter replaces all occurrences of "{2}", etc.
- * <p>
- * If any parameter is null, the corresponding key is replaced with the string "null". Therefore, consider using an empty
- * string when keys are to be removed altogether.
- * </p>
- * <p>
- * If there are no parameters, this method does nothing and returns the supplied pattern as is.
- * </p>
- * @param pattern the pattern
- * @param parameters the parameters used to replace keys
- * @return the string with all keys replaced (or removed)
- */
- public static String createString( String pattern, Object... parameters ) {
- return I18n.replaceParameters(pattern, parameters);
- }
+ /**
+ * Create a string by substituting the parameters into all key occurrences in the supplied format. The pattern consists of
+ * zero or more keys of the form <code>{n}</code>, where <code>n</code> is an integer starting at 1. Therefore, the first
+ * parameter replaces all occurrences of "{1}", the second parameter replaces all occurrences of "{2}", etc.
+ * <p>
+ * If any parameter is null, the corresponding key is replaced with the string "null". Therefore, consider using an empty
+ * string when keys are to be removed altogether.
+ * </p>
+ * <p>
+ * If there are no parameters, this method does nothing and returns the supplied pattern as is.
+ * </p>
+ *
+ * @param pattern the pattern
+ * @param parameters the parameters used to replace keys
+ * @return the string with all keys replaced (or removed)
+ */
+ public static String createString( String pattern,
+ Object... parameters ) {
+ ArgCheck.isNotNull(pattern, "pattern");
+ if (parameters == null) parameters = EMPTY_STRING_ARRAY;
+ Matcher matcher = PARAMETER_COUNT_PATTERN.matcher(pattern);
+ StringBuffer text = new StringBuffer();
+ int requiredParameterCount = 0;
+ boolean err = false;
+ while (matcher.find()) {
+ int ndx = Integer.valueOf(matcher.group(1));
+ if (requiredParameterCount <= ndx) {
+ requiredParameterCount = ndx + 1;
+ }
+ if (ndx >= parameters.length) {
+ err = true;
+ matcher.appendReplacement(text, matcher.group());
+ } else {
+ Object parameter = parameters[ndx];
+ matcher.appendReplacement(text, Matcher.quoteReplacement(parameter == null ? "null" : parameter.toString()));
+ }
+ }
+ if (err || requiredParameterCount < parameters.length) {
+ throw new IllegalArgumentException(
+ CommonI18n.requiredToSuppliedParameterMismatch.text(parameters.length,
+ parameters.length == 1 ? "" : "s",
+ requiredParameterCount,
+ requiredParameterCount == 1 ? "" : "s",
+ pattern,
+ text.toString()));
+ }
+ matcher.appendTail(text);
- /**
- * Create a new string containing the specified character repeated a specific number of times.
- * @param charToRepeat the character to repeat
- * @param numberOfRepeats the number of times the character is to repeat in the result; must be greater than 0
- * @return the resulting string
- */
- public static String createString( final char charToRepeat, int numberOfRepeats ) {
- assert numberOfRepeats >= 0;
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < numberOfRepeats; ++i) {
- sb.append(charToRepeat);
- }
- return sb.toString();
- }
+ return text.toString();
+ }
- /**
- * Set the length of the string, padding with the supplied character if the supplied string is shorter than desired, or
- * truncating the string if it is longer than desired. Unlike {@link #justifyLeft(String, int, char)}, this method does not
- * remove leading and trailing whitespace.
- * @param original the string for which the length is to be set; may not be null
- * @param length the desired length; must be positive
- * @param padChar the character to use for padding, if the supplied string is not long enough
- * @return the string of the desired length
- * @see #justifyLeft(String, int, char)
- */
- public static String setLength( String original, int length, char padChar ) {
- return justifyLeft(original, length, padChar, false);
- }
+ /**
+ * Create a new string containing the specified character repeated a specific number of times.
+ *
+ * @param charToRepeat the character to repeat
+ * @param numberOfRepeats the number of times the character is to repeat in the result; must be greater than 0
+ * @return the resulting string
+ */
+ public static String createString( final char charToRepeat,
+ int numberOfRepeats ) {
+ assert numberOfRepeats >= 0;
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < numberOfRepeats; ++i) {
+ sb.append(charToRepeat);
+ }
+ return sb.toString();
+ }
- /**
- * Right justify the contents of the string, ensuring that the string ends at the last character. If the supplied string is
- * longer than the desired width, the leading characters are removed so that the last character in the supplied string at the
- * last position. If the supplied string is shorter than the desired width, the padding character is inserted one or more
- * times such that the last character in the supplied string appears as the last character in the resulting string and that
- * the length matches that specified.
- * @param str the string to be right justified; if null, an empty string is used
- * @param width the desired width of the string; must be positive
- * @param padWithChar the character to use for padding, if needed
- * @return the right justified string
- */
- public static String justifyRight( String str, final int width, char padWithChar ) {
- assert width > 0;
- // Trim the leading and trailing whitespace ...
- str = str != null ? str.trim() : "";
+ /**
+ * Set the length of the string, padding with the supplied character if the supplied string is shorter than desired, or
+ * truncating the string if it is longer than desired. Unlike {@link #justifyLeft(String, int, char)}, this method does not
+ * remove leading and trailing whitespace.
+ *
+ * @param original the string for which the length is to be set; may not be null
+ * @param length the desired length; must be positive
+ * @param padChar the character to use for padding, if the supplied string is not long enough
+ * @return the string of the desired length
+ * @see #justifyLeft(String, int, char)
+ */
+ public static String setLength( String original,
+ int length,
+ char padChar ) {
+ return justifyLeft(original, length, padChar, false);
+ }
- final int length = str.length();
- int addChars = width - length;
- if (addChars < 0) {
- // truncate the first characters, keep the last
- return str.subSequence(length - width, length).toString();
- }
- // Prepend the whitespace ...
- final StringBuilder sb = new StringBuilder();
- while (addChars > 0) {
- sb.append(padWithChar);
- --addChars;
- }
+ /**
+ * Right justify the contents of the string, ensuring that the string ends at the last character. If the supplied string is
+ * longer than the desired width, the leading characters are removed so that the last character in the supplied string at the
+ * last position. If the supplied string is shorter than the desired width, the padding character is inserted one or more
+ * times such that the last character in the supplied string appears as the last character in the resulting string and that
+ * the length matches that specified.
+ *
+ * @param str the string to be right justified; if null, an empty string is used
+ * @param width the desired width of the string; must be positive
+ * @param padWithChar the character to use for padding, if needed
+ * @return the right justified string
+ */
+ public static String justifyRight( String str,
+ final int width,
+ char padWithChar ) {
+ assert width > 0;
+ // Trim the leading and trailing whitespace ...
+ str = str != null ? str.trim() : "";
- // Write the content ...
- sb.append(str);
- return sb.toString();
- }
+ final int length = str.length();
+ int addChars = width - length;
+ if (addChars < 0) {
+ // truncate the first characters, keep the last
+ return str.subSequence(length - width, length).toString();
+ }
+ // Prepend the whitespace ...
+ final StringBuilder sb = new StringBuilder();
+ while (addChars > 0) {
+ sb.append(padWithChar);
+ --addChars;
+ }
- /**
- * Left justify the contents of the string, ensuring that the supplied string begins at the first character and that the
- * resulting string is of the desired length. If the supplied string is longer than the desired width, it is truncated to the
- * specified length. If the supplied string is shorter than the desired width, the padding character is added to the end of
- * the string one or more times such that the length is that specified. All leading and trailing whitespace is removed.
- * @param str the string to be left justified; if null, an empty string is used
- * @param width the desired width of the string; must be positive
- * @param padWithChar the character to use for padding, if needed
- * @return the left justified string
- * @see #setLength(String, int, char)
- */
- public static String justifyLeft( String str, final int width, char padWithChar ) {
- return justifyLeft(str, width, padWithChar, true);
- }
+ // Write the content ...
+ sb.append(str);
+ return sb.toString();
+ }
- protected static String justifyLeft( String str, final int width, char padWithChar, boolean trimWhitespace ) {
- // Trim the leading and trailing whitespace ...
- str = str != null ? (trimWhitespace ? str.trim() : str) : "";
+ /**
+ * Left justify the contents of the string, ensuring that the supplied string begins at the first character and that the
+ * resulting string is of the desired length. If the supplied string is longer than the desired width, it is truncated to the
+ * specified length. If the supplied string is shorter than the desired width, the padding character is added to the end of
+ * the string one or more times such that the length is that specified. All leading and trailing whitespace is removed.
+ *
+ * @param str the string to be left justified; if null, an empty string is used
+ * @param width the desired width of the string; must be positive
+ * @param padWithChar the character to use for padding, if needed
+ * @return the left justified string
+ * @see #setLength(String, int, char)
+ */
+ public static String justifyLeft( String str,
+ final int width,
+ char padWithChar ) {
+ return justifyLeft(str, width, padWithChar, true);
+ }
- int addChars = width - str.length();
- if (addChars < 0) {
- // truncate
- return str.subSequence(0, width).toString();
- }
- // Write the content ...
- final StringBuilder sb = new StringBuilder();
- sb.append(str);
+ protected static String justifyLeft( String str,
+ final int width,
+ char padWithChar,
+ boolean trimWhitespace ) {
+ // Trim the leading and trailing whitespace ...
+ str = str != null ? (trimWhitespace ? str.trim() : str) : "";
- // Append the whitespace ...
- while (addChars > 0) {
- sb.append(padWithChar);
- --addChars;
- }
+ int addChars = width - str.length();
+ if (addChars < 0) {
+ // truncate
+ return str.subSequence(0, width).toString();
+ }
+ // Write the content ...
+ final StringBuilder sb = new StringBuilder();
+ sb.append(str);
- return sb.toString();
- }
+ // Append the whitespace ...
+ while (addChars > 0) {
+ sb.append(padWithChar);
+ --addChars;
+ }
- /**
- * Center the contents of the string. If the supplied string is longer than the desired width, it is truncated to the
- * specified length. If the supplied string is shorter than the desired width, padding characters are added to the beginning
- * and end of the string such that the length is that specified; one additional padding character is prepended if required.
- * All leading and trailing whitespace is removed before centering.
- * @param str the string to be left justified; if null, an empty string is used
- * @param width the desired width of the string; must be positive
- * @param padWithChar the character to use for padding, if needed
- * @return the left justified string
- * @see #setLength(String, int, char)
- */
- public static String justifyCenter( String str, final int width, char padWithChar ) {
- // Trim the leading and trailing whitespace ...
- str = str != null ? str.trim() : "";
+ return sb.toString();
+ }
- int addChars = width - str.length();
- if (addChars < 0) {
- // truncate
- return str.subSequence(0, width).toString();
- }
- // Write the content ...
- int prependNumber = addChars / 2;
- int appendNumber = prependNumber;
- if ((prependNumber + appendNumber) != addChars) {
- ++prependNumber;
- }
+ /**
+ * Center the contents of the string. If the supplied string is longer than the desired width, it is truncated to the
+ * specified length. If the supplied string is shorter than the desired width, padding characters are added to the beginning
+ * and end of the string such that the length is that specified; one additional padding character is prepended if required.
+ * All leading and trailing whitespace is removed before centering.
+ *
+ * @param str the string to be left justified; if null, an empty string is used
+ * @param width the desired width of the string; must be positive
+ * @param padWithChar the character to use for padding, if needed
+ * @return the left justified string
+ * @see #setLength(String, int, char)
+ */
+ public static String justifyCenter( String str,
+ final int width,
+ char padWithChar ) {
+ // Trim the leading and trailing whitespace ...
+ str = str != null ? str.trim() : "";
- final StringBuilder sb = new StringBuilder();
+ int addChars = width - str.length();
+ if (addChars < 0) {
+ // truncate
+ return str.subSequence(0, width).toString();
+ }
+ // Write the content ...
+ int prependNumber = addChars / 2;
+ int appendNumber = prependNumber;
+ if ((prependNumber + appendNumber) != addChars) {
+ ++prependNumber;
+ }
- // Prepend the pad character(s) ...
- while (prependNumber > 0) {
- sb.append(padWithChar);
- --prependNumber;
- }
+ final StringBuilder sb = new StringBuilder();
- // Add the actual content
- sb.append(str);
+ // Prepend the pad character(s) ...
+ while (prependNumber > 0) {
+ sb.append(padWithChar);
+ --prependNumber;
+ }
- // Append the pad character(s) ...
- while (appendNumber > 0) {
- sb.append(padWithChar);
- --appendNumber;
- }
+ // Add the actual content
+ sb.append(str);
- return sb.toString();
- }
+ // Append the pad character(s) ...
+ while (appendNumber > 0) {
+ sb.append(padWithChar);
+ --appendNumber;
+ }
- /**
- * Truncate the supplied string to be no more than the specified length. This method returns an empty string if the supplied
- * object is null.
- * @param obj the object from which the string is to be obtained using {@link Object#toString()}.
- * @param maxLength the maximum length of the string being returned
- * @return the supplied string if no longer than the maximum length, or the supplied string truncated to be no longer than the
- * maximum length (including the suffix)
- * @throws IllegalArgumentException if the maximum length is negative
- */
- public static String truncate( Object obj, int maxLength ) {
- return truncate(obj, maxLength, null);
- }
+ return sb.toString();
+ }
- /**
- * Truncate the supplied string to be no more than the specified length. This method returns an empty string if the supplied
- * object is null.
- * @param obj the object from which the string is to be obtained using {@link Object#toString()}.
- * @param maxLength the maximum length of the string being returned
- * @param suffix the suffix that should be added to the content if the string must be truncated, or null if the default suffix
- * of "..." should be used
- * @return the supplied string if no longer than the maximum length, or the supplied string truncated to be no longer than the
- * maximum length (including the suffix)
- * @throws IllegalArgumentException if the maximum length is negative
- */
- public static String truncate( Object obj, int maxLength, String suffix ) {
- ArgCheck.isNonNegative(maxLength, "maxLength");
- if (obj == null || maxLength == 0) {
- return "";
- }
- String str = obj.toString();
- if (str.length() <= maxLength) return str;
- if (suffix == null) suffix = "...";
- int maxNumChars = maxLength - suffix.length();
- if (maxNumChars < 0) {
- // Then the max length is actually shorter than the suffix ...
- str = suffix.substring(0, maxLength);
- } else if (str.length() > maxNumChars) {
- str = str.substring(0, maxNumChars) + suffix;
- }
- return str;
- }
+ /**
+ * Truncate the supplied string to be no more than the specified length. This method returns an empty string if the supplied
+ * object is null.
+ *
+ * @param obj the object from which the string is to be obtained using {@link Object#toString()}.
+ * @param maxLength the maximum length of the string being returned
+ * @return the supplied string if no longer than the maximum length, or the supplied string truncated to be no longer than the
+ * maximum length (including the suffix)
+ * @throws IllegalArgumentException if the maximum length is negative
+ */
+ public static String truncate( Object obj,
+ int maxLength ) {
+ return truncate(obj, maxLength, null);
+ }
- /**
- * Read and return the entire contents of the supplied {@link Reader}. This method always closes the reader when finished
- * reading.
- * @param reader the reader of the contents; may be null
- * @return the contents, or an empty string if the supplied reader is null
- * @throws IOException if there is an error reading the content
- */
- public static String read( Reader reader ) throws IOException {
- return IoUtil.read(reader);
- }
+ /**
+ * Truncate the supplied string to be no more than the specified length. This method returns an empty string if the supplied
+ * object is null.
+ *
+ * @param obj the object from which the string is to be obtained using {@link Object#toString()}.
+ * @param maxLength the maximum length of the string being returned
+ * @param suffix the suffix that should be added to the content if the string must be truncated, or null if the default suffix
+ * of "..." should be used
+ * @return the supplied string if no longer than the maximum length, or the supplied string truncated to be no longer than the
+ * maximum length (including the suffix)
+ * @throws IllegalArgumentException if the maximum length is negative
+ */
+ public static String truncate( Object obj,
+ int maxLength,
+ String suffix ) {
+ ArgCheck.isNonNegative(maxLength, "maxLength");
+ if (obj == null || maxLength == 0) {
+ return "";
+ }
+ String str = obj.toString();
+ if (str.length() <= maxLength) return str;
+ if (suffix == null) suffix = "...";
+ int maxNumChars = maxLength - suffix.length();
+ if (maxNumChars < 0) {
+ // Then the max length is actually shorter than the suffix ...
+ str = suffix.substring(0, maxLength);
+ } else if (str.length() > maxNumChars) {
+ str = str.substring(0, maxNumChars) + suffix;
+ }
+ return str;
+ }
- /**
- * Read and return the entire contents of the supplied {@link InputStream}. This method always closes the stream when
- * finished reading.
- * @param stream the streamed contents; may be null
- * @return the contents, or an empty string if the supplied stream is null
- * @throws IOException if there is an error reading the content
- */
- public static String read( InputStream stream ) throws IOException {
- return IoUtil.read(stream);
- }
+ /**
+ * Read and return the entire contents of the supplied {@link Reader}. This method always closes the reader when finished
+ * reading.
+ *
+ * @param reader the reader of the contents; may be null
+ * @return the contents, or an empty string if the supplied reader is null
+ * @throws IOException if there is an error reading the content
+ */
+ public static String read( Reader reader ) throws IOException {
+ return IoUtil.read(reader);
+ }
- /**
- * Write the entire contents of the supplied string to the given stream. This method always flushes and closes the stream when
- * finished.
- * @param content the content to write to the stream; may be null
- * @param stream the stream to which the content is to be written
- * @throws IOException
- * @throws IllegalArgumentException if the stream is null
- */
- public static void write( String content, OutputStream stream ) throws IOException {
- IoUtil.write(content, stream);
- }
+ /**
+ * Read and return the entire contents of the supplied {@link InputStream}. This method always closes the stream when
+ * finished reading.
+ *
+ * @param stream the streamed contents; may be null
+ * @return the contents, or an empty string if the supplied stream is null
+ * @throws IOException if there is an error reading the content
+ */
+ public static String read( InputStream stream ) throws IOException {
+ return IoUtil.read(stream);
+ }
- /**
- * Write the entire contents of the supplied string to the given writer. This method always flushes and closes the writer when
- * finished.
- * @param content the content to write to the writer; may be null
- * @param writer the writer to which the content is to be written
- * @throws IOException
- * @throws IllegalArgumentException if the writer is null
- */
- public static void write( String content, Writer writer ) throws IOException {
- IoUtil.write(content, writer);
- }
+ /**
+ * Write the entire contents of the supplied string to the given stream. This method always flushes and closes the stream when
+ * finished.
+ *
+ * @param content the content to write to the stream; may be null
+ * @param stream the stream to which the content is to be written
+ * @throws IOException
+ * @throws IllegalArgumentException if the stream is null
+ */
+ public static void write( String content,
+ OutputStream stream ) throws IOException {
+ IoUtil.write(content, stream);
+ }
- /**
- * Create a human-readable form of the supplied object by choosing the representation format based upon the object type.
- * <p>
- * <ul>
- * <li>A null reference results in the "null" string.</li>
- * <li>A string is written wrapped by double quotes.</li>
- * <li>A boolean is written using {@link Boolean#toString()}.</li>
- * <li>A {@link Number number} is written using the standard {@link Number#toString() toString()} method.</li>
- * <li>A {@link java.util.Date date} is written using the the {@link DateUtil#getDateAsStandardString(java.util.Date)}
- * utility method.</li>
- * <li>A {@link java.sql.Date SQL date} is written using the the {@link DateUtil#getDateAsStandardString(java.util.Date)}
- * utility method.</li>
- * <li>A {@link Calendar Calendar instance} is written using the the {@link DateUtil#getDateAsStandardString(Calendar)}
- * utility method.</li>
- * <li>An array of bytes is written with a leading "[ " and trailing " ]" surrounding the bytes written as UTF-8.
- * <li>An array of objects is written with a leading "[ " and trailing " ]", and with all objects sent through
- * {@link #readableString(Object)} and separated by ", ".</li>
- * <li>A collection of objects (e.g, <code>Collection<?></code>) is written with a leading "[ " and trailing " ]", and
- * with all objects sent through {@link #readableString(Object)} and separated by ", ".</li>
- * <li>A map of objects (e.g, <code>Map<?></code>) is written with a leading "{ " and trailing " }", and with all map
- * entries written in the form "key => value" and separated by ", ". All key and value objects are sent through the
- * {@link #readableString(Object)} method.</li>
- * <li>Any other object is written using the object's {@link Object#toString() toString()} method.</li>
- * </ul>
- * </p>
- * <p>
- * This method is capable of generating strings for nested objects. For example, a <code>Map<Date,Object[]></code> would be
- * written in the form:
- *
- * <pre>
- * { 2008-02-03T14:22:49 => [ "description", 3, [ 003459de7389g23aef, true ] ] }
- * </pre>
- *
- * </p>
- * @param obj the object that is to be converted to a string.
- * @return the string representation that is to be human readable
- */
- public static String readableString( Object obj ) {
- if (obj == null) return "null";
- if (obj instanceof Boolean) return ((Boolean)obj).toString();
- if (obj instanceof String) return "\"" + obj.toString() + "\"";
- if (obj instanceof Number) return obj.toString();
- if (obj instanceof Map) return readableString((Map)obj);
- if (obj instanceof Collection) return readableString((Collection)obj);
- if (obj instanceof byte[]) return readableString((byte[])obj);
- if (obj instanceof boolean[]) return readableString((boolean[])obj);
- if (obj instanceof short[]) return readableString((short[])obj);
- if (obj instanceof int[]) return readableString((int[])obj);
- if (obj instanceof long[]) return readableString((long[])obj);
- if (obj instanceof float[]) return readableString((float[])obj);
- if (obj instanceof double[]) return readableString((double[])obj);
- if (obj instanceof Object[]) return readableString((Object[])obj);
- if (obj instanceof Calendar) return DateUtil.getDateAsStandardString((Calendar)obj);
- if (obj instanceof java.util.Date) return DateUtil.getDateAsStandardString((java.util.Date)obj);
- if (obj instanceof java.sql.Date) return DateUtil.getDateAsStandardString((java.sql.Date)obj);
- return obj.toString();
- }
+ /**
+ * Write the entire contents of the supplied string to the given writer. This method always flushes and closes the writer when
+ * finished.
+ *
+ * @param content the content to write to the writer; may be null
+ * @param writer the writer to which the content is to be written
+ * @throws IOException
+ * @throws IllegalArgumentException if the writer is null
+ */
+ public static void write( String content,
+ Writer writer ) throws IOException {
+ IoUtil.write(content, writer);
+ }
- protected static String readableEmptyArray( Class arrayClass ) {
- assert arrayClass != null;
- Class componentType = arrayClass.getComponentType();
- if (componentType.isArray()) return "[" + readableEmptyArray(componentType) + "]";
- return "[]";
- }
+ /**
+ * Create a human-readable form of the supplied object by choosing the representation format based upon the object type.
+ * <p>
+ * <ul>
+ * <li>A null reference results in the "null" string.</li>
+ * <li>A string is written wrapped by double quotes.</li>
+ * <li>A boolean is written using {@link Boolean#toString()}.</li>
+ * <li>A {@link Number number} is written using the standard {@link Number#toString() toString()} method.</li>
+ * <li>A {@link java.util.Date date} is written using the the {@link DateUtil#getDateAsStandardString(java.util.Date)}
+ * utility method.</li>
+ * <li>A {@link java.sql.Date SQL date} is written using the the {@link DateUtil#getDateAsStandardString(java.util.Date)}
+ * utility method.</li>
+ * <li>A {@link Calendar Calendar instance} is written using the the {@link DateUtil#getDateAsStandardString(Calendar)}
+ * utility method.</li>
+ * <li>An array of bytes is written with a leading "[ " and trailing " ]" surrounding the bytes written as UTF-8.
+ * <li>An array of objects is written with a leading "[ " and trailing " ]", and with all objects sent through
+ * {@link #readableString(Object)} and separated by ", ".</li>
+ * <li>A collection of objects (e.g, <code>Collection<?></code>) is written with a leading "[ " and trailing " ]", and
+ * with all objects sent through {@link #readableString(Object)} and separated by ", ".</li>
+ * <li>A map of objects (e.g, <code>Map<?></code>) is written with a leading "{ " and trailing " }", and with all map
+ * entries written in the form "key => value" and separated by ", ". All key and value objects are sent through the
+ * {@link #readableString(Object)} method.</li>
+ * <li>Any other object is written using the object's {@link Object#toString() toString()} method.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This method is capable of generating strings for nested objects. For example, a <code>Map<Date,Object[]></code> would be
+ * written in the form:
+ *
+ * <pre>
+ * { 2008-02-03T14:22:49 => [ "description", 3, [ 003459de7389g23aef, true ] ] }
+ * </pre>
+ *
+ * </p>
+ *
+ * @param obj the object that is to be converted to a string.
+ * @return the string representation that is to be human readable
+ */
+ public static String readableString( Object obj ) {
+ if (obj == null) return "null";
+ if (obj instanceof Boolean) return ((Boolean)obj).toString();
+ if (obj instanceof String) return "\"" + obj.toString() + "\"";
+ if (obj instanceof Number) return obj.toString();
+ if (obj instanceof Map) return readableString((Map)obj);
+ if (obj instanceof Collection) return readableString((Collection)obj);
+ if (obj instanceof byte[]) return readableString((byte[])obj);
+ if (obj instanceof boolean[]) return readableString((boolean[])obj);
+ if (obj instanceof short[]) return readableString((short[])obj);
+ if (obj instanceof int[]) return readableString((int[])obj);
+ if (obj instanceof long[]) return readableString((long[])obj);
+ if (obj instanceof float[]) return readableString((float[])obj);
+ if (obj instanceof double[]) return readableString((double[])obj);
+ if (obj instanceof Object[]) return readableString((Object[])obj);
+ if (obj instanceof Calendar) return DateUtil.getDateAsStandardString((Calendar)obj);
+ if (obj instanceof java.util.Date) return DateUtil.getDateAsStandardString((java.util.Date)obj);
+ if (obj instanceof java.sql.Date) return DateUtil.getDateAsStandardString((java.sql.Date)obj);
+ return obj.toString();
+ }
- protected static String readableString( Object[] array ) {
- assert array != null;
- if (array.length == 0) return readableEmptyArray(array.getClass());
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("[ ");
- for (Object value : array) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(value));
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableEmptyArray( Class arrayClass ) {
+ assert arrayClass != null;
+ Class componentType = arrayClass.getComponentType();
+ if (componentType.isArray()) return "[" + readableEmptyArray(componentType) + "]";
+ return "[]";
+ }
- protected static String readableString( int[] array ) {
- assert array != null;
- if (array.length == 0) return readableEmptyArray(array.getClass());
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("[ ");
- for (int value : array) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(value));
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableString( Object[] array ) {
+ assert array != null;
+ if (array.length == 0) return readableEmptyArray(array.getClass());
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("[ ");
+ for (Object value : array) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(value));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- protected static String readableString( short[] array ) {
- assert array != null;
- if (array.length == 0) return readableEmptyArray(array.getClass());
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("[ ");
- for (short value : array) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(value));
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableString( int[] array ) {
+ assert array != null;
+ if (array.length == 0) return readableEmptyArray(array.getClass());
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("[ ");
+ for (int value : array) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(value));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- protected static String readableString( long[] array ) {
- assert array != null;
- if (array.length == 0) return readableEmptyArray(array.getClass());
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("[ ");
- for (long value : array) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(value));
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableString( short[] array ) {
+ assert array != null;
+ if (array.length == 0) return readableEmptyArray(array.getClass());
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("[ ");
+ for (short value : array) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(value));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- protected static String readableString( boolean[] array ) {
- assert array != null;
- if (array.length == 0) return readableEmptyArray(array.getClass());
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("[ ");
- for (boolean value : array) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(value));
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableString( long[] array ) {
+ assert array != null;
+ if (array.length == 0) return readableEmptyArray(array.getClass());
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("[ ");
+ for (long value : array) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(value));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- protected static String readableString( float[] array ) {
- assert array != null;
- if (array.length == 0) return readableEmptyArray(array.getClass());
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("[ ");
- for (float value : array) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(value));
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableString( boolean[] array ) {
+ assert array != null;
+ if (array.length == 0) return readableEmptyArray(array.getClass());
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("[ ");
+ for (boolean value : array) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(value));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- protected static String readableString( double[] array ) {
- assert array != null;
- if (array.length == 0) return readableEmptyArray(array.getClass());
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("[ ");
- for (double value : array) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(value));
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableString( float[] array ) {
+ assert array != null;
+ if (array.length == 0) return readableEmptyArray(array.getClass());
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("[ ");
+ for (float value : array) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(value));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- protected static String readableString( byte[] array ) {
- assert array != null;
- if (array.length == 0) return readableEmptyArray(array.getClass());
- StringBuilder sb = new StringBuilder();
- sb.append("[ ");
- try {
- sb.append(new String(array, "UTF-8"));
- } catch (UnsupportedEncodingException e) {
- throw new SystemFailureException(e);
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableString( double[] array ) {
+ assert array != null;
+ if (array.length == 0) return readableEmptyArray(array.getClass());
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("[ ");
+ for (double value : array) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(value));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- protected static String readableString( Collection<?> collection ) {
- assert collection != null;
- if (collection.isEmpty()) return "[]";
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("[ ");
- for (Object value : collection) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(value));
- }
- sb.append(" ]");
- return sb.toString();
- }
+ protected static String readableString( byte[] array ) {
+ assert array != null;
+ if (array.length == 0) return readableEmptyArray(array.getClass());
+ StringBuilder sb = new StringBuilder();
+ sb.append("[ ");
+ try {
+ sb.append(new String(array, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ throw new SystemFailureException(e);
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- protected static String readableString( Map<?, ?> map ) {
- assert map != null;
- if (map.isEmpty()) return "{}";
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- sb.append("{ ");
- for (Map.Entry<?, ?> entry : map.entrySet()) {
- Object key = entry.getKey();
- Object value = entry.getValue();
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- sb.append(readableString(key));
- sb.append(" => ");
- sb.append(readableString(value));
- }
- sb.append(" }");
- return sb.toString();
- }
+ protected static String readableString( Collection<?> collection ) {
+ assert collection != null;
+ if (collection.isEmpty()) return "[]";
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("[ ");
+ for (Object value : collection) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(value));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
- /**
- * Get the stack trace of the supplied exception.
- * @param t the exception for which the stack trace is to be returned
- * @return the stack trace, or null if the supplied exception is null
- */
- public static String getStackTrace( Throwable t ) {
- if (t == null) return null;
- final ByteArrayOutputStream bas = new ByteArrayOutputStream();
- final PrintWriter pw = new PrintWriter(bas);
- t.printStackTrace(pw);
- pw.close();
- return bas.toString();
- }
+ protected static String readableString( Map<?, ?> map ) {
+ assert map != null;
+ if (map.isEmpty()) return "{}";
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ sb.append("{ ");
+ for (Map.Entry<?, ?> entry : map.entrySet()) {
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(readableString(key));
+ sb.append(" => ");
+ sb.append(readableString(value));
+ }
+ sb.append(" }");
+ return sb.toString();
+ }
- private StringUtil() {
- // Prevent construction
- }
+ /**
+ * Get the stack trace of the supplied exception.
+ *
+ * @param t the exception for which the stack trace is to be returned
+ * @return the stack trace, or null if the supplied exception is null
+ */
+ public static String getStackTrace( Throwable t ) {
+ if (t == null) return null;
+ final ByteArrayOutputStream bas = new ByteArrayOutputStream();
+ final PrintWriter pw = new PrintWriter(bas);
+ t.printStackTrace(pw);
+ pw.close();
+ return bas.toString();
+ }
+
+ private StringUtil() {
+ // Prevent construction
+ }
}
Modified: trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/I18nTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/I18nTest.java 2008-05-07 13:37:37 UTC (rev 119)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/I18nTest.java 2008-05-07 16:25:17 UTC (rev 120)
@@ -349,7 +349,6 @@
try {
TestI18n.testMessage1.text();
} catch (IllegalArgumentException err) {
- assertThat(err.getMessage(), is(CommonI18n.i18nArgumentsMismatchedParameter.text(0, "testMessage1", 1, "{0}", "{0}")));
System.err.println(err);
throw err;
}
@@ -361,8 +360,6 @@
try {
TestI18n.testMessage1.text("Test", "Message");
} catch (IllegalArgumentException err) {
- assertThat(err.getMessage(),
- is(CommonI18n.i18nArgumentsMismatchedParameter.text(2, "testMessage1", 1, "{0}", "Test")));
System.err.println(err);
throw err;
}
Modified: trunk/dna-common/src/test/java/org/jboss/dna/common/util/StringUtilTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/util/StringUtilTest.java 2008-05-07 13:37:37 UTC (rev 119)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/util/StringUtilTest.java 2008-05-07 16:25:17 UTC (rev 120)
@@ -2,7 +2,7 @@
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -41,370 +41,431 @@
public class StringUtilTest {
- @Before
- public void beforeEach() throws Exception {
- }
+ @Before
+ public void beforeEach() throws Exception {
+ }
- public void compareSeparatedLines( Object... lines ) {
- ByteArrayOutputStream content = new ByteArrayOutputStream();
- PrintStream stream = new PrintStream(content);
- for (Object line : lines) {
- stream.println(line);
- }
- List<String> actualLines = StringUtil.splitLines(content.toString());
- assertArrayEquals(lines, actualLines.toArray());
- }
+ public void compareSeparatedLines( Object... lines ) {
+ ByteArrayOutputStream content = new ByteArrayOutputStream();
+ PrintStream stream = new PrintStream(content);
+ for (Object line : lines) {
+ stream.println(line);
+ }
+ List<String> actualLines = StringUtil.splitLines(content.toString());
+ assertArrayEquals(lines, actualLines.toArray());
+ }
- @Test
- public void splitLinesShouldWorkCorrectly() {
- compareSeparatedLines("Line 1", "Line 2", "Line 3", "Line 4");
- }
+ @Test
+ public void splitLinesShouldWorkCorrectly() {
+ compareSeparatedLines("Line 1", "Line 2", "Line 3", "Line 4");
+ }
- @Test
- public void createStringShouldCreateStringFromPattern() {
- String pattern = "This {0} is {1} should {2} not {3} last {4}";
- assertEquals("This one is two should three not four last five", StringUtil.createString(pattern, "one", "two", "three", "four", "five"));
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void createStringShouldFailIfNoPatternSupplied() {
+ StringUtil.createString(null, (Object[])null);
+ }
- @Test
- public void setLengthShouldTruncateStringsThatAreTooLong() {
- assertEquals("This is the st", StringUtil.setLength("This is the string", 14, ' '));
- }
+ @Test
+ public void createStringShouldAllowNoParametersSupplied() {
+ assertThat(StringUtil.createString("test", (Object[])null), is("test"));
+ }
- @Test
- public void setLengthShouldAppendCharacterForStringsThatAreTooShort() {
- assertEquals("This ", StringUtil.setLength("This", 10, ' '));
- }
+ @Test
+ public void createStringShouldCreateStringFromPattern() {
+ String pattern = "This {0} is {1} should {2} not {3} last {4}";
+ assertEquals("This one is two should three not four last five", StringUtil.createString(pattern,
+ "one",
+ "two",
+ "three",
+ "four",
+ "five"));
+ }
- @Test
- public void setLengthShouldNotRemoveLeadingWhitespace() {
- assertEquals(" This ", StringUtil.setLength(" This", 10, ' '));
- assertEquals("\tThis ", StringUtil.setLength("\tThis", 10, ' '));
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void createStringShouldFailIfTooFewArgumentsSupplied() {
+ String pattern = "This {0} is {1} should {2} not {3} last {4}";
+ try {
+ StringUtil.createString(pattern, "one", "two", "three", "four");
+ } catch (IllegalArgumentException err) {
+ System.err.println(err);
+ throw err;
+ }
+ }
- @Test
- public void setLengthShouldAppendCharacterForEmptyStrings() {
- assertEquals(" ", StringUtil.setLength("", 10, ' '));
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void createStringShouldFailIfTooManyArgumentsSupplied() {
+ String pattern = "This {0} is {1} should {2} not {3} last {4}";
+ try {
+ StringUtil.createString(pattern, "one", "two", "three", "four", "five", "six");
+ } catch (IllegalArgumentException err) {
+ System.err.println(err);
+ throw err;
+ }
+ }
- @Test
- public void setLengthShouldAppendCharacterForNullStrings() {
- assertEquals(" ", StringUtil.setLength(null, 10, ' '));
- }
+ @Test
+ public void createStringExceptionMessageShouldbeGrammaticallyCorrect() {
+ String pattern = "One = {0}";
+ try {
+ StringUtil.createString(pattern);
+ } catch (IllegalArgumentException err) {
+ assertThat(err.getMessage().startsWith("0 parameters supplied, but 1 parameter required"), is(true));
+ }
+ pattern = "One";
+ try {
+ StringUtil.createString(pattern, "one");
+ } catch (IllegalArgumentException err) {
+ assertThat(err.getMessage().startsWith("1 parameter supplied, but 0 parameters required"), is(true));
+ }
+ pattern = "One = {0}, Two = {1}";
+ try {
+ StringUtil.createString(pattern);
+ } catch (IllegalArgumentException err) {
+ assertThat(err.getMessage().startsWith("0 parameters supplied, but 2 parameters required"), is(true));
+ }
+ }
- @Test
- public void setLengthShouldReturnStringsThatAreTheDesiredLength() {
- assertEquals("This is the string", StringUtil.setLength("This is the string", 18, ' '));
- }
+ @Test
+ public void setLengthShouldTruncateStringsThatAreTooLong() {
+ assertEquals("This is the st", StringUtil.setLength("This is the string", 14, ' '));
+ }
- @Test
- public void justifyLeftShouldTruncateStringsThatAreTooLong() {
- assertEquals("This is the st", StringUtil.justifyLeft("This is the string", 14, ' '));
- }
+ @Test
+ public void setLengthShouldAppendCharacterForStringsThatAreTooShort() {
+ assertEquals("This ", StringUtil.setLength("This", 10, ' '));
+ }
- @Test
- public void justifyLeftShouldAppendCharacterForStringsThatAreTooShort() {
- assertEquals("This ", StringUtil.justifyLeft("This", 10, ' '));
- }
+ @Test
+ public void setLengthShouldNotRemoveLeadingWhitespace() {
+ assertEquals(" This ", StringUtil.setLength(" This", 10, ' '));
+ assertEquals("\tThis ", StringUtil.setLength("\tThis", 10, ' '));
+ }
- @Test
- public void justifyLeftShouldRemoveLeadingWhitespace() {
- assertEquals("This ", StringUtil.justifyLeft(" This", 10, ' '));
- assertEquals("This ", StringUtil.justifyLeft("\tThis", 10, ' '));
- }
+ @Test
+ public void setLengthShouldAppendCharacterForEmptyStrings() {
+ assertEquals(" ", StringUtil.setLength("", 10, ' '));
+ }
- @Test
- public void justifyLeftShouldAppendCharacterForEmptyStrings() {
- assertEquals(" ", StringUtil.justifyLeft("", 10, ' '));
- }
+ @Test
+ public void setLengthShouldAppendCharacterForNullStrings() {
+ assertEquals(" ", StringUtil.setLength(null, 10, ' '));
+ }
- @Test
- public void justifyLeftShouldAppendCharacterForNullStrings() {
- assertEquals(" ", StringUtil.justifyLeft(null, 10, ' '));
- }
+ @Test
+ public void setLengthShouldReturnStringsThatAreTheDesiredLength() {
+ assertEquals("This is the string", StringUtil.setLength("This is the string", 18, ' '));
+ }
- @Test
- public void justifyLeftShouldReturnStringsThatAreTheDesiredLength() {
- assertEquals("This is the string", StringUtil.justifyLeft("This is the string", 18, ' '));
- }
+ @Test
+ public void justifyLeftShouldTruncateStringsThatAreTooLong() {
+ assertEquals("This is the st", StringUtil.justifyLeft("This is the string", 14, ' '));
+ }
- @Test
- public void justifyRightShouldTruncateStringsThatAreTooLong() {
- assertEquals(" is the string", StringUtil.justifyRight("This is the string", 14, ' '));
- }
+ @Test
+ public void justifyLeftShouldAppendCharacterForStringsThatAreTooShort() {
+ assertEquals("This ", StringUtil.justifyLeft("This", 10, ' '));
+ }
- @Test
- public void justifyRightShouldPrependCharacterForStringsThatAreTooShort() {
- assertEquals(" This", StringUtil.justifyRight("This", 10, ' '));
- }
+ @Test
+ public void justifyLeftShouldRemoveLeadingWhitespace() {
+ assertEquals("This ", StringUtil.justifyLeft(" This", 10, ' '));
+ assertEquals("This ", StringUtil.justifyLeft("\tThis", 10, ' '));
+ }
- @Test
- public void justifyRightShouldPrependCharacterForEmptyStrings() {
- assertEquals(" ", StringUtil.justifyRight("", 10, ' '));
- }
+ @Test
+ public void justifyLeftShouldAppendCharacterForEmptyStrings() {
+ assertEquals(" ", StringUtil.justifyLeft("", 10, ' '));
+ }
- @Test
- public void justifyRightShouldPrependCharacterForNullStrings() {
- assertEquals(" ", StringUtil.justifyRight(null, 10, ' '));
- }
+ @Test
+ public void justifyLeftShouldAppendCharacterForNullStrings() {
+ assertEquals(" ", StringUtil.justifyLeft(null, 10, ' '));
+ }
- @Test
- public void justifyRightShouldReturnStringsThatAreTheDesiredLength() {
- assertEquals("This is the string", StringUtil.justifyRight("This is the string", 18, ' '));
- }
+ @Test
+ public void justifyLeftShouldReturnStringsThatAreTheDesiredLength() {
+ assertEquals("This is the string", StringUtil.justifyLeft("This is the string", 18, ' '));
+ }
- @Test
- public void justifyCenterShouldTruncateStringsThatAreTooLong() {
- assertEquals("This is the st", StringUtil.justifyCenter("This is the string", 14, ' '));
- }
+ @Test
+ public void justifyRightShouldTruncateStringsThatAreTooLong() {
+ assertEquals(" is the string", StringUtil.justifyRight("This is the string", 14, ' '));
+ }
- @Test
- public void justifyCenterShouldPrependAndAppendSameNumberOfCharacterForStringsThatAreTooShortButOfAnEvenLength() {
- assertEquals(" This ", StringUtil.justifyCenter("This", 10, ' '));
- }
+ @Test
+ public void justifyRightShouldPrependCharacterForStringsThatAreTooShort() {
+ assertEquals(" This", StringUtil.justifyRight("This", 10, ' '));
+ }
- @Test
- public void justifyCenterShouldPrependOneMoreCharacterThanAppendingForStringsThatAreTooShortButOfAnOddLength() {
- assertEquals(" Thing ", StringUtil.justifyCenter("Thing", 10, ' '));
- }
+ @Test
+ public void justifyRightShouldPrependCharacterForEmptyStrings() {
+ assertEquals(" ", StringUtil.justifyRight("", 10, ' '));
+ }
- @Test
- public void justifyCenterShouldPrependCharacterForEmptyStrings() {
- assertEquals(" ", StringUtil.justifyCenter("", 10, ' '));
- }
+ @Test
+ public void justifyRightShouldPrependCharacterForNullStrings() {
+ assertEquals(" ", StringUtil.justifyRight(null, 10, ' '));
+ }
- @Test
- public void justifyCenterShouldPrependCharacterForNullStrings() {
- assertEquals(" ", StringUtil.justifyCenter(null, 10, ' '));
- }
+ @Test
+ public void justifyRightShouldReturnStringsThatAreTheDesiredLength() {
+ assertEquals("This is the string", StringUtil.justifyRight("This is the string", 18, ' '));
+ }
- @Test
- public void justifyCenterShouldReturnStringsThatAreTheDesiredLength() {
- assertEquals("This is the string", StringUtil.justifyCenter("This is the string", 18, ' '));
- }
+ @Test
+ public void justifyCenterShouldTruncateStringsThatAreTooLong() {
+ assertEquals("This is the st", StringUtil.justifyCenter("This is the string", 14, ' '));
+ }
- @Test
- public void truncateShouldReturnEmptyStringIfNullReferenceIsSupplied() {
- assertThat(StringUtil.truncate(null, 0), is(""));
- assertThat(StringUtil.truncate(null, 1), is(""));
- assertThat(StringUtil.truncate(null, 100), is(""));
- }
+ @Test
+ public void justifyCenterShouldPrependAndAppendSameNumberOfCharacterForStringsThatAreTooShortButOfAnEvenLength() {
+ assertEquals(" This ", StringUtil.justifyCenter("This", 10, ' '));
+ }
- @Test( expected = IllegalArgumentException.class )
- public void truncateShouldNotAllowNegativeLength() {
- StringUtil.truncate("some string", -1);
- }
+ @Test
+ public void justifyCenterShouldPrependOneMoreCharacterThanAppendingForStringsThatAreTooShortButOfAnOddLength() {
+ assertEquals(" Thing ", StringUtil.justifyCenter("Thing", 10, ' '));
+ }
- @Test
- public void truncateShouldReturnEmptyStringForMaximumLengthOfZero() {
- String str = "This is the string with some text";
- assertThat(StringUtil.truncate(str, 0), is(""));
- assertThat(StringUtil.truncate("", 0), is(""));
- assertThat(StringUtil.truncate(str, 0, "123"), is(""));
- assertThat(StringUtil.truncate("", 0, "123"), is(""));
- }
+ @Test
+ public void justifyCenterShouldPrependCharacterForEmptyStrings() {
+ assertEquals(" ", StringUtil.justifyCenter("", 10, ' '));
+ }
- @Test
- public void truncateShouldNotTruncateStringShorterThanMaximumLength() {
- String str = "This is the string with some text";
- assertThat(StringUtil.truncate(str, str.length() + 2), is(str));
- assertThat(StringUtil.truncate(str, str.length() + 2, null), is(str));
- assertThat(StringUtil.truncate(str, str.length() + 2, "really long suffix"), is(str));
- }
+ @Test
+ public void justifyCenterShouldPrependCharacterForNullStrings() {
+ assertEquals(" ", StringUtil.justifyCenter(null, 10, ' '));
+ }
- @Test
- public void truncateShouldNotTruncateStringWithLengthEqualToMaximumLength() {
- String str = "This is the string with some text";
- assertThat(StringUtil.truncate(str, str.length()), is(str));
- assertThat(StringUtil.truncate(str, str.length(), null), is(str));
- assertThat(StringUtil.truncate(str, str.length(), "really long suffix"), is(str));
- }
+ @Test
+ public void justifyCenterShouldReturnStringsThatAreTheDesiredLength() {
+ assertEquals("This is the string", StringUtil.justifyCenter("This is the string", 18, ' '));
+ }
- @Test
- public void truncateShouldProperlyTruncateStringWithLengthGreaterThanMaximumLength() {
- String str = "This is the string";
- assertThat(StringUtil.truncate(str, str.length() - 1), is("This is the st..."));
- assertThat(StringUtil.truncate(str, str.length() - 1, null), is("This is the st..."));
- assertThat(StringUtil.truncate(str, str.length() - 1, "X"), is("This is the striX"));
- }
+ @Test
+ public void truncateShouldReturnEmptyStringIfNullReferenceIsSupplied() {
+ assertThat(StringUtil.truncate(null, 0), is(""));
+ assertThat(StringUtil.truncate(null, 1), is(""));
+ assertThat(StringUtil.truncate(null, 100), is(""));
+ }
- @Test
- public void truncateShouldProperlyTruncateStringWithLengthGreaterThanMaximumLengthAndMaximumLengthLongerThanPrefixLength() {
- String str = "This is the string";
- assertThat(StringUtil.truncate(str, 2), is(".."));
- assertThat(StringUtil.truncate(str, 2, null), is(".."));
- assertThat(StringUtil.truncate(str, 1, "XX"), is("X"));
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void truncateShouldNotAllowNegativeLength() {
+ StringUtil.truncate("some string", -1);
+ }
- @Test
- public void readShouldReturnEmptyStringForNullInputStream() throws Exception {
- assertThat(StringUtil.read((InputStream)null), is(""));
- }
+ @Test
+ public void truncateShouldReturnEmptyStringForMaximumLengthOfZero() {
+ String str = "This is the string with some text";
+ assertThat(StringUtil.truncate(str, 0), is(""));
+ assertThat(StringUtil.truncate("", 0), is(""));
+ assertThat(StringUtil.truncate(str, 0, "123"), is(""));
+ assertThat(StringUtil.truncate("", 0, "123"), is(""));
+ }
- @Test
- public void readShouldReturnEmptyStringForNullReader() throws Exception {
- assertThat(StringUtil.read((Reader)null), is(""));
- }
+ @Test
+ public void truncateShouldNotTruncateStringShorterThanMaximumLength() {
+ String str = "This is the string with some text";
+ assertThat(StringUtil.truncate(str, str.length() + 2), is(str));
+ assertThat(StringUtil.truncate(str, str.length() + 2, null), is(str));
+ assertThat(StringUtil.truncate(str, str.length() + 2, "really long suffix"), is(str));
+ }
- @Test
- public void readShouldReadInputStreamCorrectlyAndShouldCloseStream() throws Exception {
- // Read content shorter than buffer size ...
- String content = "This is the way to grandma's house.";
- InputStream stream = new ByteArrayInputStream(content.getBytes());
- InputStreamWrapper wrapper = new InputStreamWrapper(stream);
- assertThat(wrapper.isClosed(), is(false));
- assertThat(StringUtil.read(wrapper), is(content));
- assertThat(wrapper.isClosed(), is(true));
+ @Test
+ public void truncateShouldNotTruncateStringWithLengthEqualToMaximumLength() {
+ String str = "This is the string with some text";
+ assertThat(StringUtil.truncate(str, str.length()), is(str));
+ assertThat(StringUtil.truncate(str, str.length(), null), is(str));
+ assertThat(StringUtil.truncate(str, str.length(), "really long suffix"), is(str));
+ }
- // Read content longer than buffer size ...
- for (int i = 0; i != 10; ++i) {
- content += content; // note this doubles each time!
- }
- stream = new ByteArrayInputStream(content.getBytes());
- wrapper = new InputStreamWrapper(stream);
- assertThat(wrapper.isClosed(), is(false));
- assertThat(StringUtil.read(wrapper), is(content));
- assertThat(wrapper.isClosed(), is(true));
- }
+ @Test
+ public void truncateShouldProperlyTruncateStringWithLengthGreaterThanMaximumLength() {
+ String str = "This is the string";
+ assertThat(StringUtil.truncate(str, str.length() - 1), is("This is the st..."));
+ assertThat(StringUtil.truncate(str, str.length() - 1, null), is("This is the st..."));
+ assertThat(StringUtil.truncate(str, str.length() - 1, "X"), is("This is the striX"));
+ }
- @Test
- public void readShouldReadReaderCorrectlyAndShouldCloseStream() throws Exception {
- // Read content shorter than buffer size ...
- String content = "This is the way to grandma's house.";
- Reader reader = new StringReader(content);
- ReaderWrapper wrapper = new ReaderWrapper(reader);
- assertThat(wrapper.isClosed(), is(false));
- assertThat(StringUtil.read(wrapper), is(content));
- assertThat(wrapper.isClosed(), is(true));
+ @Test
+ public void truncateShouldProperlyTruncateStringWithLengthGreaterThanMaximumLengthAndMaximumLengthLongerThanPrefixLength() {
+ String str = "This is the string";
+ assertThat(StringUtil.truncate(str, 2), is(".."));
+ assertThat(StringUtil.truncate(str, 2, null), is(".."));
+ assertThat(StringUtil.truncate(str, 1, "XX"), is("X"));
+ }
- // Read content longer than buffer size ...
- for (int i = 0; i != 10; ++i) {
- content += content; // note this doubles each time!
- }
- reader = new StringReader(content);
- wrapper = new ReaderWrapper(reader);
- assertThat(wrapper.isClosed(), is(false));
- assertThat(StringUtil.read(wrapper), is(content));
- assertThat(wrapper.isClosed(), is(true));
- }
+ @Test
+ public void readShouldReturnEmptyStringForNullInputStream() throws Exception {
+ assertThat(StringUtil.read((InputStream)null), is(""));
+ }
- @Test
- public void getStackTraceShouldReturnStackTrace() {
- String msg = "This is the message for a test exception";
- Throwable t = new IllegalArgumentException(msg);
- String trace = StringUtil.getStackTrace(t);
- assertThat(trace, containsString(msg));
- assertThat(trace, containsString(this.getClass().getName()));
- }
+ @Test
+ public void readShouldReturnEmptyStringForNullReader() throws Exception {
+ assertThat(StringUtil.read((Reader)null), is(""));
+ }
- @Test
- public void readableStringShouldReturnStringForNull() {
- assertThat(StringUtil.readableString((Object)null), is("null"));
- }
+ @Test
+ public void readShouldReadInputStreamCorrectlyAndShouldCloseStream() throws Exception {
+ // Read content shorter than buffer size ...
+ String content = "This is the way to grandma's house.";
+ InputStream stream = new ByteArrayInputStream(content.getBytes());
+ InputStreamWrapper wrapper = new InputStreamWrapper(stream);
+ assertThat(wrapper.isClosed(), is(false));
+ assertThat(StringUtil.read(wrapper), is(content));
+ assertThat(wrapper.isClosed(), is(true));
- @Test
- public void readableStringShouldReturnStringFormOfBoolean() {
- assertThat(StringUtil.readableString(true), is(Boolean.TRUE.toString()));
- assertThat(StringUtil.readableString(false), is(Boolean.FALSE.toString()));
- assertThat(StringUtil.readableString(Boolean.TRUE), is(Boolean.TRUE.toString()));
- assertThat(StringUtil.readableString(Boolean.FALSE), is(Boolean.FALSE.toString()));
- }
+ // Read content longer than buffer size ...
+ for (int i = 0; i != 10; ++i) {
+ content += content; // note this doubles each time!
+ }
+ stream = new ByteArrayInputStream(content.getBytes());
+ wrapper = new InputStreamWrapper(stream);
+ assertThat(wrapper.isClosed(), is(false));
+ assertThat(StringUtil.read(wrapper), is(content));
+ assertThat(wrapper.isClosed(), is(true));
+ }
- @Test
- public void readableStringShouldReturnStringFormOfNumber() {
- assertThat(StringUtil.readableString(1), is("1"));
- assertThat(StringUtil.readableString(-513), is("-513"));
- assertThat(StringUtil.readableString(-513.3f), is("-513.3"));
- assertThat(StringUtil.readableString(-513.3d), is("-513.3"));
- assertThat(StringUtil.readableString(new Short((short)1)), is("1"));
- assertThat(StringUtil.readableString(new Integer(-513)), is("-513"));
- assertThat(StringUtil.readableString(new Float(-513.3f)), is("-513.3"));
- assertThat(StringUtil.readableString(new Double(-513.3d)), is("-513.3"));
- }
+ @Test
+ public void readShouldReadReaderCorrectlyAndShouldCloseStream() throws Exception {
+ // Read content shorter than buffer size ...
+ String content = "This is the way to grandma's house.";
+ Reader reader = new StringReader(content);
+ ReaderWrapper wrapper = new ReaderWrapper(reader);
+ assertThat(wrapper.isClosed(), is(false));
+ assertThat(StringUtil.read(wrapper), is(content));
+ assertThat(wrapper.isClosed(), is(true));
- @Test
- public void readableStringShouldWrapObjectArrayWithSquareBraces() {
- assertThat(StringUtil.readableString(new int[] {}), is("[]"));
- assertThat(StringUtil.readableString(new int[] {1}), is("[ 1 ]"));
- assertThat(StringUtil.readableString(new int[] {1, 2, 3, 4}), is("[ 1, 2, 3, 4 ]"));
- assertThat(StringUtil.readableString(new short[] {1, 2, 3, 4}), is("[ 1, 2, 3, 4 ]"));
- assertThat(StringUtil.readableString(new boolean[] {true, false}), is("[ true, false ]"));
- assertThat(StringUtil.readableString(new long[] {1, 2, 3, 4}), is("[ 1, 2, 3, 4 ]"));
- assertThat(StringUtil.readableString(new float[] {51.0f, 52.0f, 53.0f, 54.0f}), is("[ 51.0, 52.0, 53.0, 54.0 ]"));
- assertThat(StringUtil.readableString(new double[] {51.0d, 52.0d, 53.0d, 54.0d}), is("[ 51.0, 52.0, 53.0, 54.0 ]"));
- }
+ // Read content longer than buffer size ...
+ for (int i = 0; i != 10; ++i) {
+ content += content; // note this doubles each time!
+ }
+ reader = new StringReader(content);
+ wrapper = new ReaderWrapper(reader);
+ assertThat(wrapper.isClosed(), is(false));
+ assertThat(StringUtil.read(wrapper), is(content));
+ assertThat(wrapper.isClosed(), is(true));
+ }
- @Test
- public void readableStringShouldHandleEmptyArraysOfArrays() {
- assertThat(StringUtil.readableString(new int[][] {}), is("[[]]"));
- assertThat(StringUtil.readableString(new boolean[][][][][][] {}), is("[[[[[[]]]]]]"));
- assertThat(StringUtil.readableString(new ArrayList<List<List<?>>>()), is("[]"));
- }
+ @Test
+ public void getStackTraceShouldReturnStackTrace() {
+ String msg = "This is the message for a test exception";
+ Throwable t = new IllegalArgumentException(msg);
+ String trace = StringUtil.getStackTrace(t);
+ assertThat(trace, containsString(msg));
+ assertThat(trace, containsString(this.getClass().getName()));
+ }
- @Test
- public void readableStringShouldHandleNestedObjects() {
- assertThat(StringUtil.readableString(new int[][] {new int[] {1, 2}, new int[] {3, 4}}), is("[ [ 1, 2 ], [ 3, 4 ] ]"));
- List<String> list1 = new ArrayList<String>();
- list1.add("a1");
- list1.add("a2");
- List<String> list2 = new ArrayList<String>();
- list2.add("b1");
- list2.add("b2");
- List<List<String>> list3 = new ArrayList<List<String>>();
- list3.add(list1);
- list3.add(list2);
- assertThat(StringUtil.readableString(list3), is("[ [ \"a1\", \"a2\" ], [ \"b1\", \"b2\" ] ]"));
- }
+ @Test
+ public void readableStringShouldReturnStringForNull() {
+ assertThat(StringUtil.readableString((Object)null), is("null"));
+ }
- protected class InputStreamWrapper extends InputStream {
+ @Test
+ public void readableStringShouldReturnStringFormOfBoolean() {
+ assertThat(StringUtil.readableString(true), is(Boolean.TRUE.toString()));
+ assertThat(StringUtil.readableString(false), is(Boolean.FALSE.toString()));
+ assertThat(StringUtil.readableString(Boolean.TRUE), is(Boolean.TRUE.toString()));
+ assertThat(StringUtil.readableString(Boolean.FALSE), is(Boolean.FALSE.toString()));
+ }
- private boolean closed = false;
- private final InputStream stream;
+ @Test
+ public void readableStringShouldReturnStringFormOfNumber() {
+ assertThat(StringUtil.readableString(1), is("1"));
+ assertThat(StringUtil.readableString(-513), is("-513"));
+ assertThat(StringUtil.readableString(-513.3f), is("-513.3"));
+ assertThat(StringUtil.readableString(-513.3d), is("-513.3"));
+ assertThat(StringUtil.readableString(new Short((short)1)), is("1"));
+ assertThat(StringUtil.readableString(new Integer(-513)), is("-513"));
+ assertThat(StringUtil.readableString(new Float(-513.3f)), is("-513.3"));
+ assertThat(StringUtil.readableString(new Double(-513.3d)), is("-513.3"));
+ }
- protected InputStreamWrapper( InputStream stream ) {
- this.stream = stream;
- }
+ @Test
+ public void readableStringShouldWrapObjectArrayWithSquareBraces() {
+ assertThat(StringUtil.readableString(new int[] {}), is("[]"));
+ assertThat(StringUtil.readableString(new int[] {1}), is("[ 1 ]"));
+ assertThat(StringUtil.readableString(new int[] {1, 2, 3, 4}), is("[ 1, 2, 3, 4 ]"));
+ assertThat(StringUtil.readableString(new short[] {1, 2, 3, 4}), is("[ 1, 2, 3, 4 ]"));
+ assertThat(StringUtil.readableString(new boolean[] {true, false}), is("[ true, false ]"));
+ assertThat(StringUtil.readableString(new long[] {1, 2, 3, 4}), is("[ 1, 2, 3, 4 ]"));
+ assertThat(StringUtil.readableString(new float[] {51.0f, 52.0f, 53.0f, 54.0f}), is("[ 51.0, 52.0, 53.0, 54.0 ]"));
+ assertThat(StringUtil.readableString(new double[] {51.0d, 52.0d, 53.0d, 54.0d}), is("[ 51.0, 52.0, 53.0, 54.0 ]"));
+ }
- public boolean isClosed() {
- return closed;
- }
+ @Test
+ public void readableStringShouldHandleEmptyArraysOfArrays() {
+ assertThat(StringUtil.readableString(new int[][] {}), is("[[]]"));
+ assertThat(StringUtil.readableString(new boolean[][][][][][] {}), is("[[[[[[]]]]]]"));
+ assertThat(StringUtil.readableString(new ArrayList<List<List<?>>>()), is("[]"));
+ }
- @Override
- public int read() throws IOException {
- return stream.read();
- }
+ @Test
+ public void readableStringShouldHandleNestedObjects() {
+ assertThat(StringUtil.readableString(new int[][] {new int[] {1, 2}, new int[] {3, 4}}), is("[ [ 1, 2 ], [ 3, 4 ] ]"));
+ List<String> list1 = new ArrayList<String>();
+ list1.add("a1");
+ list1.add("a2");
+ List<String> list2 = new ArrayList<String>();
+ list2.add("b1");
+ list2.add("b2");
+ List<List<String>> list3 = new ArrayList<List<String>>();
+ list3.add(list1);
+ list3.add(list2);
+ assertThat(StringUtil.readableString(list3), is("[ [ \"a1\", \"a2\" ], [ \"b1\", \"b2\" ] ]"));
+ }
- @Override
- public void close() throws IOException {
- stream.close();
- this.closed = true;
- }
+ protected class InputStreamWrapper extends InputStream {
- }
+ private boolean closed = false;
+ private final InputStream stream;
- protected class ReaderWrapper extends Reader {
+ protected InputStreamWrapper( InputStream stream ) {
+ this.stream = stream;
+ }
- private boolean closed = false;
- private final Reader reader;
+ public boolean isClosed() {
+ return closed;
+ }
- protected ReaderWrapper( Reader reader ) {
- this.reader = reader;
- }
+ @Override
+ public int read() throws IOException {
+ return stream.read();
+ }
- public boolean isClosed() {
- return closed;
- }
+ @Override
+ public void close() throws IOException {
+ stream.close();
+ this.closed = true;
+ }
- @Override
- public void close() throws IOException {
- reader.close();
- this.closed = true;
- }
+ }
- @Override
- public int read( char[] cbuf, int off, int len ) throws IOException {
- return reader.read(cbuf, off, len);
- }
- }
+ protected class ReaderWrapper extends Reader {
+ private boolean closed = false;
+ private final Reader reader;
+
+ protected ReaderWrapper( Reader reader ) {
+ this.reader = reader;
+ }
+
+ public boolean isClosed() {
+ return closed;
+ }
+
+ @Override
+ public void close() throws IOException {
+ reader.close();
+ this.closed = true;
+ }
+
+ @Override
+ public int read( char[] cbuf,
+ int off,
+ int len ) throws IOException {
+ return reader.read(cbuf, off, len);
+ }
+ }
+
}
16 years
DNA SVN: r119 - trunk/build/assembly.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-05-07 09:37:37 -0400 (Wed, 07 May 2008)
New Revision: 119
Modified:
trunk/build/assembly/examples.xml
Log:
Changed how the examples ZIP file is produced, ensuring that target is excluded.
Modified: trunk/build/assembly/examples.xml
===================================================================
--- trunk/build/assembly/examples.xml 2008-05-07 13:36:32 UTC (rev 118)
+++ trunk/build/assembly/examples.xml 2008-05-07 13:37:37 UTC (rev 119)
@@ -24,8 +24,11 @@
<!--
Gather into the distribution the examples
-->
- <directory>docs/examples/gettingstarted/sequencers/target/dna-example-sequencers-basic.dir/</directory>
+ <directory>docs/examples/gettingstarted/sequencers</directory>
<outputDirectory>examples/sequencers</outputDirectory>
+ <excludes>
+ <exclude>target/**</exclude>
+ </excludes>
</fileSet>
</fileSets>
</assembly>
16 years
DNA SVN: r118 - trunk.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-05-07 09:36:32 -0400 (Wed, 07 May 2008)
New Revision: 118
Modified:
trunk/pom.xml
Log:
Added production of source JARs to the 'verify' phase.
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2008-05-06 22:25:58 UTC (rev 117)
+++ trunk/pom.xml 2008-05-07 13:36:32 UTC (rev 118)
@@ -19,7 +19,7 @@
<module>dna-maven-classloader</module>
</modules>
<properties>
- <dna-version>0.1-SNAPSHOT</dna-version>
+ <dna-version>${project.version}</dna-version>
</properties>
<profiles>
<profile>
@@ -136,7 +136,21 @@
<showWarnings>false</showWarnings>
</configuration>
</plugin>
+ <!-- Produce source jars during the 'verify' phase -->
<plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
16 years
DNA SVN: r117 - in trunk: build and 6 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-05-06 18:25:58 -0400 (Tue, 06 May 2008)
New Revision: 117
Added:
trunk/build/
trunk/build/JBossORG-EULA.txt
trunk/build/assembly/
trunk/build/assembly/dist.xml
trunk/build/assembly/examples.xml
trunk/build/assembly/javadoc.xml
trunk/build/assembly/src.xml
trunk/dna-common/src/main/java/org/jboss/dna/common/util/FileUtil.java
trunk/docs/pom.xml
Removed:
trunk/dna-common/src/test/java/org/jboss/dna/common/util/FileUtil.java
Modified:
trunk/docs/
trunk/docs/examples/gettingstarted/sequencers/pom.xml
trunk/docs/gettingstarted/pom.xml
trunk/pom.xml
Log:
Added Maven assemblies that automate the production of the various distributable artifacts, including archives for sources, examples, javadoc and all.
Added: trunk/build/JBossORG-EULA.txt
===================================================================
--- trunk/build/JBossORG-EULA.txt (rev 0)
+++ trunk/build/JBossORG-EULA.txt 2008-05-06 22:25:58 UTC (rev 117)
@@ -0,0 +1,106 @@
+LICENSE AGREEMENT
+JBOSS(r)
+
+This License Agreement governs the use of the Software Packages and any updates to the Software
+Packages, regardless of the delivery mechanism. Each Software Package is a collective work
+under U.S. Copyright Law. Subject to the following terms, Red Hat, Inc. ("Red Hat") grants to
+the user ("Client") a license to the applicable collective work(s) pursuant to the
+GNU Lesser General Public License v. 2.1 except for the following Software Packages:
+(a) JBoss Portal Forums and JBoss Transactions JTS, each of which is licensed pursuant to the
+GNU General Public License v.2;
+
+(b) JBoss Rules, which is licensed pursuant to the Apache License v.2.0;
+
+(c) an optional download for JBoss Cache for the Berkeley DB for Java database, which is licensed under the
+(open source) Sleepycat License (if Client does not wish to use the open source version of this database,
+it may purchase a license from Sleepycat Software);
+
+and (d) the BPEL extension for JBoss jBPM, which is licensed under the Common Public License v.1,
+and, pursuant to the OASIS BPEL4WS standard, requires parties wishing to redistribute to enter various
+royalty-free patent licenses.
+
+Each of the foregoing licenses is available at http://www.opensource.org/licenses/index.php.
+
+1. The Software. "Software Packages" refer to the various software modules that are created and made available
+for distribution by the JBoss.org open source community at http://www.jboss.org. Each of the Software Packages
+may be comprised of hundreds of software components. The end user license agreement for each component is located in
+the component's source code. With the exception of certain image files identified in Section 2 below,
+the license terms for the components permit Client to copy, modify, and redistribute the component,
+in both source code and binary code forms. This agreement does not limit Client's rights under,
+or grant Client rights that supersede, the license terms of any particular component.
+
+2. Intellectual Property Rights. The Software Packages are owned by Red Hat and others and are protected under copyright
+and other laws. Title to the Software Packages and any component, or to any copy, modification, or merged portion shall
+remain with the aforementioned, subject to the applicable license. The "JBoss" trademark, "Red Hat" trademark, the
+individual Software Package trademarks, and the "Shadowman" logo are registered trademarks of Red Hat and its affiliates
+in the U.S. and other countries. This agreement permits Client to distribute unmodified copies of the Software Packages
+using the Red Hat trademarks that Red Hat has inserted in the Software Packages on the condition that Client follows Red Hat's
+trademark guidelines for those trademarks located at http://www.redhat.com/about/corporate/trademark/. Client must abide by
+these trademark guidelines when distributing the Software Packages, regardless of whether the Software Packages have been modified.
+If Client modifies the Software Packages, then Client must replace all Red Hat trademarks and logos identified at
+http://www.jboss.com/company/logos, unless a separate agreement with Red Hat is executed or other permission granted.
+Merely deleting the files containing the Red Hat trademarks may corrupt the Software Packages.
+
+3. Limited Warranty. Except as specifically stated in this Paragraph 3 or a license for a particular
+component, to the maximum extent permitted under applicable law, the Software Packages and the
+components are provided and licensed "as is" without warranty of any kind, expressed or implied,
+including the implied warranties of merchantability, non-infringement or fitness for a particular purpose.
+Red Hat warrants that the media on which Software Packages may be furnished will be free from defects in
+materials and manufacture under normal use for a period of 30 days from the date of delivery to Client.
+Red Hat does not warrant that the functions contained in the Software Packages will meet Client's requirements
+or that the operation of the Software Packages will be entirely error free or appear precisely as described
+in the accompanying documentation. This warranty extends only to the party that purchases the Services
+pertaining to the Software Packages from Red Hat or a Red Hat authorized distributor.
+
+4. Limitation of Remedies and Liability. To the maximum extent permitted by applicable law, the remedies
+described below are accepted by Client as its only remedies. Red Hat's entire liability, and Client's
+exclusive remedies, shall be: If the Software media is defective, Client may return it within 30 days of
+delivery along with a copy of Client's payment receipt and Red Hat, at its option, will replace it or
+refund the money paid by Client for the Software. To the maximum extent permitted by applicable law,
+Red Hat or any Red Hat authorized dealer will not be liable to Client for any incidental or consequential
+damages, including lost profits or lost savings arising out of the use or inability to use the Software,
+even if Red Hat or such dealer has been advised of the possibility of such damages. In no event shall
+Red Hat's liability under this agreement exceed the amount that Client paid to Red Hat under this
+Agreement during the twelve months preceding the action.
+
+5. Export Control. As required by U.S. law, Client represents and warrants that it:
+(a) understands that the Software Packages are subject to export controls under the
+U.S. Commerce Department's Export Administration Regulations ("EAR");
+
+(b) is not located in a prohibited destination country under the EAR or U.S. sanctions regulations
+(currently Cuba, Iran, Iraq, Libya, North Korea, Sudan and Syria);
+
+(c) will not export, re-export, or transfer the Software Packages to any prohibited destination, entity,
+or individual without the necessary export license(s) or authorizations(s) from the U.S. Government;
+
+(d) will not use or transfer the Software Packages for use in any sensitive nuclear, chemical or
+biological weapons, or missile technology end-uses unless authorized by the U.S. Government by
+regulation or specific license;
+
+(e) understands and agrees that if it is in the United States and exports or transfers the Software
+Packages to eligible end users, it will, as required by EAR Section 740.17(e), submit semi-annual
+reports to the Commerce Department's Bureau of Industry & Security (BIS), which include the name and
+address (including country) of each transferee;
+
+and (f) understands that countries other than the United States may restrict the import, use, or
+export of encryption products and that it shall be solely responsible for compliance with any such
+import, use, or export restrictions.
+
+6. Third Party Programs. Red Hat may distribute third party software programs with the Software Packages
+that are not part of the Software Packages and which Client must install separately. These third party
+programs are subject to their own license terms. The license terms either accompany the programs or
+can be viewed at http://www.redhat.com/licenses/. If Client does not agree to abide by the applicable
+license terms for such programs, then Client may not install them. If Client wishes to install the programs
+on more than one system or transfer the programs to another party, then Client must contact the licensor
+of the programs.
+
+7. General. If any provision of this agreement is held to be unenforceable, that shall not affect the
+enforceability of the remaining provisions. This License Agreement shall be governed by the laws of the
+State of North Carolina and of the United States, without regard to any conflict of laws provisions,
+except that the United Nations Convention on the International Sale of Goods shall not apply.
+
+Copyright 2006 Red Hat, Inc. All rights reserved.
+"JBoss" and the JBoss logo are registered trademarks of Red Hat, Inc.
+All other trademarks are the property of their respective owners.
+
+ Page 1 of 1 18 October 2006
Added: trunk/build/assembly/dist.xml
===================================================================
--- trunk/build/assembly/dist.xml (rev 0)
+++ trunk/build/assembly/dist.xml 2008-05-06 22:25:58 UTC (rev 117)
@@ -0,0 +1,67 @@
+<assembly>
+ <id>dist</id>
+ <formats>
+ <!--<format>tar.gz</format>
+ <format>tar.bz2</format-->
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <!--
+ Gather into the distribution the various text files for inclusion
+ -->
+ <directory>build</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>README*</include>
+ <include>LICENSE*</include>
+ <include>NOTICE*</include>
+ <include>*.txt</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <!--
+ Gather into the distribution the JavaDoc for all projects
+ -->
+ <directory>target/site/apidocs</directory>
+ <outputDirectory>apidocs</outputDirectory>
+ </fileSet>
+ <fileSet>
+ <!--
+ Gather into the distribution the Getting Started document
+ -->
+ <directory>docs/gettingstarted/target/docbook</directory>
+ <outputDirectory>manuals/gettingstarted</outputDirectory>
+ </fileSet>
+ </fileSets>
+ <moduleSets>
+ <moduleSet>
+ <!--
+ Gather into the distribution the source, jars, and test-jars for all projects
+ -->
+ <sources>
+ <includeModuleDirectory>false</includeModuleDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>src</directory>
+ <outputDirectory>src</outputDirectory>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory>lib</outputDirectory>
+ <includes>
+ <include>*-${project.version}.jar</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory>lib/test</outputDirectory>
+ <includes>
+ <include>*-${project.version}-tests.jar</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ </sources>
+ </moduleSet>
+ </moduleSets>
+</assembly>
Added: trunk/build/assembly/examples.xml
===================================================================
--- trunk/build/assembly/examples.xml (rev 0)
+++ trunk/build/assembly/examples.xml 2008-05-06 22:25:58 UTC (rev 117)
@@ -0,0 +1,31 @@
+<assembly>
+ <id>examples</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <!--<format>tar.gz</format>
+ <format>tar.bz2</format-->
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <!--
+ Gather into the distribution the various text files for inclusion
+ -->
+ <directory>build</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>README*</include>
+ <include>LICENSE*</include>
+ <include>NOTICE*</include>
+ <include>*.txt</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <!--
+ Gather into the distribution the examples
+ -->
+ <directory>docs/examples/gettingstarted/sequencers/target/dna-example-sequencers-basic.dir/</directory>
+ <outputDirectory>examples/sequencers</outputDirectory>
+ </fileSet>
+ </fileSets>
+</assembly>
Added: trunk/build/assembly/javadoc.xml
===================================================================
--- trunk/build/assembly/javadoc.xml (rev 0)
+++ trunk/build/assembly/javadoc.xml 2008-05-06 22:25:58 UTC (rev 117)
@@ -0,0 +1,18 @@
+<assembly>
+ <id>javadoc</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <!--<format>tar.gz</format>
+ <format>tar.bz2</format-->
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <!--
+ Gather into the distribution the JavaDoc for all projects
+ -->
+ <directory>target/site/apidocs</directory>
+ <outputDirectory>apidocs</outputDirectory>
+ </fileSet>
+ </fileSets>
+</assembly>
Added: trunk/build/assembly/src.xml
===================================================================
--- trunk/build/assembly/src.xml (rev 0)
+++ trunk/build/assembly/src.xml 2008-05-06 22:25:58 UTC (rev 117)
@@ -0,0 +1,21 @@
+<assembly>
+ <id>src</id>
+ <formats>
+ <!--<format>tar.gz</format>
+ <format>tar.bz2</format-->
+ <format>zip</format>
+ </formats>
+ <moduleSets>
+ <moduleSet>
+ <sources>
+ <fileSets>
+ <fileSet>
+ <excludes>
+ <exclude>target/**</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+ </sources>
+ </moduleSet>
+ </moduleSets>
+</assembly>
Copied: trunk/dna-common/src/main/java/org/jboss/dna/common/util/FileUtil.java (from rev 110, trunk/dna-common/src/test/java/org/jboss/dna/common/util/FileUtil.java)
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/util/FileUtil.java (rev 0)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/util/FileUtil.java 2008-05-06 22:25:58 UTC (rev 117)
@@ -0,0 +1,61 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.dna.common.util;
+
+import java.io.File;
+
+public class FileUtil {
+
+ /**
+ * Delete the file or directory at the supplied path. This method works on a directory that is not empty, unlike the
+ * {@link File#delete()} method.
+ * @param path the path to the file or directory that is to be deleted
+ * @return true if the file or directory at the supplied path existed and was successfully deleted, or false otherwise
+ */
+ public static boolean delete( String path ) {
+ if (path == null || path.trim().length() == 0) return false;
+ return delete(new File(path));
+ }
+
+ /**
+ * Delete the file or directory given by the supplied reference. This method works on a directory that is not empty, unlike
+ * the {@link File#delete()} method.
+ * @param fileOrDirectory the reference to the Java File object that is to be deleted
+ * @return true if the supplied file or directory existed and was successfully deleted, or false otherwise
+ */
+ public static boolean delete( File fileOrDirectory ) {
+ if (fileOrDirectory == null) return false;
+ if (!fileOrDirectory.exists()) return false;
+
+ // The file/directory exists, so if a directory delete all of the contents ...
+ if (fileOrDirectory.isDirectory()) {
+ for (File childFile : fileOrDirectory.listFiles()) {
+ delete(childFile); // recursive call (good enough for now until we need something better)
+ }
+ // Now an empty directory ...
+ }
+ // Whether this is a file or empty directory, just delete it ...
+ return fileOrDirectory.delete();
+ }
+
+}
Deleted: trunk/dna-common/src/test/java/org/jboss/dna/common/util/FileUtil.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/util/FileUtil.java 2008-05-06 16:12:11 UTC (rev 116)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/util/FileUtil.java 2008-05-06 22:25:58 UTC (rev 117)
@@ -1,61 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.dna.common.util;
-
-import java.io.File;
-
-public class FileUtil {
-
- /**
- * Delete the file or directory at the supplied path. This method works on a directory that is not empty, unlike the
- * {@link File#delete()} method.
- * @param path the path to the file or directory that is to be deleted
- * @return true if the file or directory at the supplied path existed and was successfully deleted, or false otherwise
- */
- public static boolean delete( String path ) {
- if (path == null || path.trim().length() == 0) return false;
- return delete(new File(path));
- }
-
- /**
- * Delete the file or directory given by the supplied reference. This method works on a directory that is not empty, unlike
- * the {@link File#delete()} method.
- * @param fileOrDirectory the reference to the Java File object that is to be deleted
- * @return true if the supplied file or directory existed and was successfully deleted, or false otherwise
- */
- public static boolean delete( File fileOrDirectory ) {
- if (fileOrDirectory == null) return false;
- if (!fileOrDirectory.exists()) return false;
-
- // The file/directory exists, so if a directory delete all of the contents ...
- if (fileOrDirectory.isDirectory()) {
- for (File childFile : fileOrDirectory.listFiles()) {
- delete(childFile); // recursive call (good enough for now until we need something better)
- }
- // Now an empty directory ...
- }
- // Whether this is a file or empty directory, just delete it ...
- return fileOrDirectory.delete();
- }
-
-}
Property changes on: trunk/docs
___________________________________________________________________
Name: svn:ignore
+ target
Modified: trunk/docs/examples/gettingstarted/sequencers/pom.xml
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/pom.xml 2008-05-06 16:12:11 UTC (rev 116)
+++ trunk/docs/examples/gettingstarted/sequencers/pom.xml 2008-05-06 22:25:58 UTC (rev 117)
@@ -24,6 +24,11 @@
</dependency>
<dependency>
<groupId>org.jboss.dna</groupId>
+ <artifactId>dna-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
<artifactId>dna-sequencer-images</artifactId>
<scope>runtime</scope>
</dependency>
Modified: trunk/docs/gettingstarted/pom.xml
===================================================================
--- trunk/docs/gettingstarted/pom.xml 2008-05-06 16:12:11 UTC (rev 116)
+++ trunk/docs/gettingstarted/pom.xml 2008-05-06 22:25:58 UTC (rev 117)
@@ -14,6 +14,6 @@
<artifactId>getting-started-${translation}</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jdocbook</packaging>
- <name>Getting_Started_(${translation})</name>
+ <name>JBoss DNA Getting Started Document (${translation})</name>
</project>
Added: trunk/docs/pom.xml
===================================================================
--- trunk/docs/pom.xml (rev 0)
+++ trunk/docs/pom.xml 2008-05-06 22:25:58 UTC (rev 117)
@@ -0,0 +1,17 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.jboss.dna.docs</groupId>
+ <artifactId>dna-docs</artifactId>
+ <packaging>pom</packaging>
+ <name>JBoss DNA Documents</name>
+ <url>http://www.jboss.org/dna</url>
+ <description>JBoss DNA Documentation</description>
+ <modules>
+ <module>gettingstarted</module>
+ </modules>
+</project>
\ No newline at end of file
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2008-05-06 16:12:11 UTC (rev 116)
+++ trunk/pom.xml 2008-05-06 22:25:58 UTC (rev 117)
@@ -5,17 +5,104 @@
<artifactId>dna</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>pom</packaging>
- <name>JBoss DNA Parent POM</name>
- <url>http://labs.jboss.org/dna</url>
- <description>JBoss DNA (aggregator)</description>
+ <name>JBoss DNA</name>
+ <url>http://www.jboss.org/dna</url>
+ <description>JBoss DNA provides tools for working with JCR repositories.</description>
+ <scm>
+ <connection>scm:svn:https://svn.jboss.org/repos/dna/trunk</connection>
+ </scm>
<modules>
<module>dna-common</module>
<module>dna-spi</module>
<module>dna-repository</module>
<module>sequencers/dna-sequencer-images</module>
<module>dna-maven-classloader</module>
- <module>dna-integration-tests</module>
</modules>
+ <properties>
+ <dna-version>0.1-SNAPSHOT</dna-version>
+ </properties>
+ <profiles>
+ <profile>
+ <!--
+ This profile is activated when the "integration.tests" property is set,
+ as in "mvn ... -Dintegration.tests=true ..."
+ -->
+ <id>integration-tests</id>
+ <activation>
+ <property>
+ <name>integration.tests</name>
+ </property>
+ </activation>
+ <modules>
+ <module>dna-integration-tests</module>
+ </modules>
+ </profile>
+ <profile>
+ <!--
+ This profile is activated when the "generate.docs" property is set,
+ as in "mvn ... -Dgenerate.docs=true ..."
+ -->
+ <id>docs</id>
+ <activation>
+ <property>
+ <name>generate.docs</name>
+ </property>
+ </activation>
+ <modules>
+ <module>docs</module>
+ </modules>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <aggregate>true</aggregate>
+ <show>public</show>
+ <title>JBoss DNA ${project.version}</title>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ </profile>
+ <profile>
+ <!--
+ This profile is activated manually, as in "mvn ... -P assembly ..."
+ -->
+ <id>assembly</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <inherited>false</inherited>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>install</phase>
+ <goals>
+ <goal>assembly</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <finalName>jboss-dna-${project.version}</finalName>
+ <descriptors>
+ <descriptor>build/assembly/examples.xml</descriptor>
+ <descriptor>build/assembly/javadoc.xml</descriptor>
+ <descriptor>build/assembly/dist.xml</descriptor>
+ <descriptor>build/assembly/src.xml</descriptor>
+ </descriptors>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <modules>
+ <module>dna-integration-tests</module>
+ <module>docs</module>
+ <module>docs/examples/gettingstarted</module>
+ </modules>
+ </profile>
+ </profiles>
<build>
<!-- This section defines the default plugin settings inherited by child projects. -->
<pluginManagement>
@@ -26,6 +113,14 @@
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.2</version>
+ <configuration>
+ <aggregate>true</aggregate>
+ </configuration>
+ </plugin>
</plugins>
</pluginManagement>
<plugins>
@@ -92,22 +187,22 @@
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-common</artifactId>
- <version>0.1-SNAPSHOT</version>
+ <version>${dna-version}</version>
</dependency>
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-maven-classloader</artifactId>
- <version>0.1-SNAPSHOT</version>
+ <version>${dna-version}</version>
</dependency>
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-spi</artifactId>
- <version>0.1-SNAPSHOT</version>
+ <version>${dna-version}</version>
</dependency>
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-repository</artifactId>
- <version>0.1-SNAPSHOT</version>
+ <version>${dna-version}</version>
</dependency>
<!--
Rules
@@ -243,6 +338,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
</plugin>
- </plugins>
+ </plugins>
</reporting>
</project>
16 years
DNA SVN: r116 - in trunk/docs: examples and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-05-06 12:12:11 -0400 (Tue, 06 May 2008)
New Revision: 116
Added:
trunk/docs/examples/gettingstarted/
trunk/docs/gettingstarted/
Removed:
trunk/docs/examples/getting_started/
trunk/docs/getting_started/
Log:
Moved to match Microcontainer pattern
Copied: trunk/docs/examples/gettingstarted (from rev 115, trunk/docs/examples/getting_started)
Copied: trunk/docs/gettingstarted (from rev 115, trunk/docs/getting_started)
16 years
DNA SVN: r115 - in trunk: dna-common/src/main/java/org/jboss/dna/common/component and 31 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-05-06 10:57:52 -0400 (Tue, 06 May 2008)
New Revision: 115
Added:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerLibrary.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/AbstractSessionFactory.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleSessionFactory.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java
trunk/docs/examples/
trunk/docs/examples/getting_started/
trunk/docs/examples/getting_started/pom.xml
trunk/docs/examples/getting_started/sequencers/
trunk/docs/examples/getting_started/sequencers/.classpath
trunk/docs/examples/getting_started/sequencers/.project
trunk/docs/examples/getting_started/sequencers/pom.xml
trunk/docs/examples/getting_started/sequencers/src/
trunk/docs/examples/getting_started/sequencers/src/main/
trunk/docs/examples/getting_started/sequencers/src/main/assembly/
trunk/docs/examples/getting_started/sequencers/src/main/assembly/basic.xml
trunk/docs/examples/getting_started/sequencers/src/main/config/
trunk/docs/examples/getting_started/sequencers/src/main/config/run.sh
trunk/docs/examples/getting_started/sequencers/src/main/java/
trunk/docs/examples/getting_started/sequencers/src/main/java/org/
trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/
trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/
trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/
trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/
trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java
trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/ImageInfo.java
trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java
trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java
trunk/docs/examples/getting_started/sequencers/src/main/resources/
trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.gif
trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.jpg
trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.pict
trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.png
trunk/docs/examples/getting_started/sequencers/src/main/resources/jackrabbitConfig.xml
trunk/docs/examples/getting_started/sequencers/src/main/resources/jackrabbitNodeTypes.cnd
trunk/docs/examples/getting_started/sequencers/src/main/resources/log4j.properties
trunk/docs/examples/getting_started/sequencers/src/test/
trunk/docs/examples/getting_started/sequencers/src/test/java/
trunk/docs/examples/getting_started/sequencers/src/test/java/org/
trunk/docs/examples/getting_started/sequencers/src/test/java/org/jboss/
trunk/docs/examples/getting_started/sequencers/src/test/java/org/jboss/example/
trunk/docs/examples/getting_started/sequencers/src/test/java/org/jboss/example/dna/
trunk/docs/examples/getting_started/sequencers/src/test/java/org/jboss/example/dna/sequencers/
trunk/docs/examples/getting_started/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java
trunk/docs/getting_started/.project
Removed:
trunk/dna-repository/src/main/java/org/jboss/dna/services/
trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/SimpleExecutionContext.java
trunk/docs/.project
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/component/ComponentLibrary.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerPathExpression.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrTools.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JndiSessionFactory.java
trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerPathExpressionTest.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java
trunk/pom.xml
Log:
Added example, changed some of the implementation classes to be used more easily.
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/component/ComponentLibrary.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/component/ComponentLibrary.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/component/ComponentLibrary.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -202,7 +202,7 @@
// Don't use ClassLoader.loadClass(String), as it doesn't properly initialize the class
// (specifically static initializers may not be called)
Class<?> componentClass = Class.forName(config.getComponentClassname(), true, classLoader);
- newInstance = (ComponentType)componentClass.newInstance();
+ newInstance = doCreateInstance(componentClass);
if (newInstance instanceof Component) {
((Component<ConfigType>)newInstance).setConfiguration(config);
}
@@ -216,6 +216,19 @@
}
/**
+ * Method that instantiates the supplied class. This method can be overridden by subclasses that may need to wrap or adapt the
+ * instance to be a ComponentType.
+ * @param componentClass
+ * @return
+ * @throws InstantiationException
+ * @throws IllegalAccessException
+ */
+ @SuppressWarnings( "unchecked" )
+ protected ComponentType doCreateInstance( Class<?> componentClass ) throws InstantiationException, IllegalAccessException {
+ return (ComponentType)componentClass.newInstance();
+ }
+
+ /**
* Find the index for the matching {@link #configurations configuration} and {@link #sequencerInstances sequencer}.
* @param config the configuration; may not be null
* @return the index, or -1 if not found
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -30,85 +30,91 @@
*/
public final class RepositoryI18n {
- public static I18n invalidStateString;
- public static I18n serviceShutdowAndMayNotBeStarted;
- public static I18n serviceShutdowAndMayNotBePaused;
- public static I18n unableToFindRepositoryInJndi;
- public static I18n errorProcessingEvents;
- public static I18n errorFindingPropertyNameInPropertyAddedEvent;
- public static I18n errorFindingPropertyNameInPropertyChangedEvent;
- public static I18n errorFindingPropertyNameInPropertyRemovedEvent;
+ public static I18n invalidStateString;
+ public static I18n serviceShutdowAndMayNotBeStarted;
+ public static I18n serviceShutdowAndMayNotBePaused;
+ public static I18n unableToFindRepositoryInJndi;
+ public static I18n unableToRegisterRepositoryInJndi;
+ public static I18n unableToUnregisterRepositoryInJndi;
+ public static I18n unableToRemoveRepository;
+ public static I18n unableToFindRepositoryWithName;
+ public static I18n errorProcessingEvents;
+ public static I18n errorFindingPropertyNameInPropertyAddedEvent;
+ public static I18n errorFindingPropertyNameInPropertyChangedEvent;
+ public static I18n errorFindingPropertyNameInPropertyRemovedEvent;
- public static I18n unableToObtainJsr94RuleAdministrator;
- public static I18n errorUsingJsr94RuleAdministrator;
- public static I18n unableToObtainJsr94ServiceProvider;
- public static I18n errorAddingOrUpdatingRuleSet;
- public static I18n errorRollingBackRuleSetAfterUpdateFailed;
- public static I18n errorReadingRulesAndProperties;
- public static I18n errorDeregisteringRuleSetBeforeUpdatingIt;
- public static I18n errorRecreatingRuleSet;
- public static I18n errorRemovingRuleSet;
- public static I18n errorRemovingRuleSetUponShutdown;
- public static I18n unableToFindRuleSet;
- public static I18n errorExecutingRuleSetWithGlobalsAndFacts;
- public static I18n unableToBuildRuleSetRegularExpressionPattern;
+ public static I18n unableToObtainJsr94RuleAdministrator;
+ public static I18n errorUsingJsr94RuleAdministrator;
+ public static I18n unableToObtainJsr94ServiceProvider;
+ public static I18n errorAddingOrUpdatingRuleSet;
+ public static I18n errorRollingBackRuleSetAfterUpdateFailed;
+ public static I18n errorReadingRulesAndProperties;
+ public static I18n errorDeregisteringRuleSetBeforeUpdatingIt;
+ public static I18n errorRecreatingRuleSet;
+ public static I18n errorRemovingRuleSet;
+ public static I18n errorRemovingRuleSetUponShutdown;
+ public static I18n unableToFindRuleSet;
+ public static I18n errorExecutingRuleSetWithGlobalsAndFacts;
+ public static I18n unableToBuildRuleSetRegularExpressionPattern;
- public static I18n errorObtainingSessionToRepositoryWorkspace;
- public static I18n errorWritingProblemsOnRuleSet;
+ public static I18n errorObtainingSessionToRepositoryWorkspace;
+ public static I18n errorWritingProblemsOnRuleSet;
- public static I18n sequencingServiceName;
- public static I18n unableToChangeExecutionContextWhileRunning;
- public static I18n unableToStartSequencingServiceWithoutExecutionContext;
- public static I18n errorWhileSequencingNode;
- public static I18n errorInRepositoryWhileSequencingNode;
- public static I18n errorFindingSequencersToRunAgainstNode;
- public static I18n errorInRepositoryWhileFindingSequencersToRunAgainstNode;
- public static I18n executionContextHasBeenClosed;
- public static I18n sequencerTask;
- public static I18n sequencerSubtask;
- public static I18n unableToFindPropertyForSequencing;
- public static I18n sequencingPropertyOnNode;
- public static I18n writingOutputSequencedFromPropertyOnNodes;
+ public static I18n sequencingServiceName;
+ public static I18n unableToChangeExecutionContextWhileRunning;
+ public static I18n unableToStartSequencingServiceWithoutExecutionContext;
+ public static I18n errorWhileSequencingNode;
+ public static I18n errorInRepositoryWhileSequencingNode;
+ public static I18n errorFindingSequencersToRunAgainstNode;
+ public static I18n errorInRepositoryWhileFindingSequencersToRunAgainstNode;
+ public static I18n executionContextHasBeenClosed;
+ public static I18n sequencerTask;
+ public static I18n sequencerSubtask;
+ public static I18n unableToFindPropertyForSequencing;
+ public static I18n sequencingPropertyOnNode;
+ public static I18n writingOutputSequencedFromPropertyOnNodes;
- public static I18n errorReadingPropertiesFromContainerNode;
- public static I18n requiredPropertyOnNodeWasExpectedToBeStringValue;
- public static I18n optionalPropertyOnNodeWasExpectedToBeStringValue;
- public static I18n requiredPropertyOnNodeWasExpectedToBeStringArrayValue;
- public static I18n optionalPropertyOnNodeWasExpectedToBeStringArrayValue;
- public static I18n requiredPropertyOnNodeCouldNotBeRead;
- public static I18n optionalPropertyOnNodeCouldNotBeRead;
- public static I18n requiredPropertyIsMissingFromNode;
- public static I18n errorGettingRequiredPropertyFromNode;
- public static I18n errorGettingOptionalPropertyFromNode;
- public static I18n errorClosingBinaryStreamForPropertyFromNode;
- public static I18n requiredNodeDoesNotExistRelativeToNode;
- public static I18n errorGettingNodeRelativeToNode;
- public static I18n unknownPropertyValueType;
+ public static I18n errorReadingPropertiesFromContainerNode;
+ public static I18n requiredPropertyOnNodeWasExpectedToBeStringValue;
+ public static I18n optionalPropertyOnNodeWasExpectedToBeStringValue;
+ public static I18n requiredPropertyOnNodeWasExpectedToBeStringArrayValue;
+ public static I18n optionalPropertyOnNodeWasExpectedToBeStringArrayValue;
+ public static I18n requiredPropertyOnNodeCouldNotBeRead;
+ public static I18n optionalPropertyOnNodeCouldNotBeRead;
+ public static I18n requiredPropertyIsMissingFromNode;
+ public static I18n errorGettingRequiredPropertyFromNode;
+ public static I18n errorGettingOptionalPropertyFromNode;
+ public static I18n errorClosingBinaryStreamForPropertyFromNode;
+ public static I18n requiredNodeDoesNotExistRelativeToNode;
+ public static I18n errorGettingNodeRelativeToNode;
+ public static I18n unknownPropertyValueType;
- public static I18n pathExpressionIsInvalid;
- public static I18n pathExpressionMayNotBeBlank;
- public static I18n pathExpressionHasInvalidSelect;
- public static I18n pathExpressionHasInvalidMatch;
+ public static I18n pathExpressionIsInvalid;
+ public static I18n pathExpressionMayNotBeBlank;
+ public static I18n pathExpressionHasInvalidSelect;
+ public static I18n pathExpressionHasInvalidMatch;
- public static I18n invalidRepositoryNodePath;
+ public static I18n errorUnregisteringWorkspaceListenerWhileShuttingDownObservationService;
- static {
- try {
- I18n.initialize(RepositoryI18n.class);
- } catch (final Exception err) {
- System.err.println(err);
- }
- }
+ public static I18n invalidRepositoryNodePath;
- public static Set<Locale> getLocalizationProblemLocales() {
- return I18n.getLocalizationProblemLocales(RepositoryI18n.class);
- }
+ static {
+ try {
+ I18n.initialize(RepositoryI18n.class);
+ } catch (final Exception err) {
+ System.err.println(err);
+ }
+ }
- public static Set<String> getLocalizationProblems() {
- return I18n.getLocalizationProblems(RepositoryI18n.class);
- }
+ public static Set<Locale> getLocalizationProblemLocales() {
+ return I18n.getLocalizationProblemLocales(RepositoryI18n.class);
+ }
- public static Set<String> getLocalizationProblems( Locale locale ) {
- return I18n.getLocalizationProblems(RepositoryI18n.class, locale);
- }
+ public static Set<String> getLocalizationProblems() {
+ return I18n.getLocalizationProblems(RepositoryI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems( Locale locale ) {
+ return I18n.getLocalizationProblems(RepositoryI18n.class, locale);
+ }
}
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -109,6 +109,15 @@
/**
* {@inheritDoc}
*/
+ @Override
+ protected void doShutdown( State fromState ) {
+ super.doShutdown(fromState);
+ shutdownService();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public boolean awaitTermination( long timeout, TimeUnit unit ) {
return true;
}
@@ -119,6 +128,7 @@
private ProblemLog problemLog = new DefaultProblemLog();
private final Statistics statistics = new Statistics();
private final SessionFactory sessionFactory;
+ private final CopyOnWriteArrayList<WorkspaceListener> workspaceListeners = new CopyOnWriteArrayList<WorkspaceListener>();
private final CopyOnWriteArrayList<EventListener> eventListeners = new CopyOnWriteArrayList<EventListener>();
private final CopyOnWriteArrayList<NodeChangeListener> nodeChangeListeners = new CopyOnWriteArrayList<NodeChangeListener>();
private final Administrator administrator = new Administrator();
@@ -200,6 +210,17 @@
return this.nodeChangeListeners.remove(listener);
}
+ protected void shutdownService() {
+ // Unregister all listeners ...
+ for (WorkspaceListener listener : this.workspaceListeners) {
+ try {
+ listener.unregister();
+ } catch (RepositoryException e) {
+ this.logger.error(RepositoryI18n.errorUnregisteringWorkspaceListenerWhileShuttingDownObservationService);
+ }
+ }
+ }
+
/**
* Monitor the supplied workspace for events of the given type on any node at or under the supplied path.
* <p>
@@ -262,6 +283,7 @@
throws RepositoryException {
WorkspaceListener listener = new WorkspaceListener(repositoryWorkspaceName, eventTypes, absolutePath, isDeep, uuids, nodeTypeNames, noLocal);
listener.register();
+ this.workspaceListeners.add(listener);
return listener;
}
@@ -315,6 +337,10 @@
return monitor(repositoryWorkspaceName, WorkspaceListener.DEFAULT_ABSOLUTE_PATH, eventTypes, WorkspaceListener.DEFAULT_IS_DEEP, null, nodeTypeNames, WorkspaceListener.DEFAULT_NO_LOCAL);
}
+ protected void unregisterListener( WorkspaceListener listener ) {
+ if (listener != null) this.workspaceListeners.remove(listener);
+ }
+
/**
* From section 2.8.8 of the JSR-170 specification:
* <p>
@@ -564,6 +590,7 @@
this.session.logout();
} finally {
this.session = null;
+ unregisterListener(this);
}
return this;
}
Added: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerLibrary.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerLibrary.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerLibrary.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.sequencers;
+
+import org.jboss.dna.common.component.ComponentLibrary;
+import org.jboss.dna.spi.sequencers.StreamSequencer;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencerLibrary extends ComponentLibrary<Sequencer, SequencerConfig> {
+
+ /**
+ *
+ */
+ public SequencerLibrary() {
+ super();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Sequencer doCreateInstance( Class<?> componentClass ) throws InstantiationException, IllegalAccessException {
+ Object sequencerImpl = componentClass.newInstance();
+ if (sequencerImpl instanceof StreamSequencer) {
+ sequencerImpl = new StreamSequencerAdapter((StreamSequencer)sequencerImpl);
+ }
+ return (Sequencer)sequencerImpl;
+ }
+
+}
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerPathExpression.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerPathExpression.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerPathExpression.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -265,8 +265,9 @@
}
// Order is important here
- expression = expression.replaceAll("[*]", "[^/]*");
- expression = expression.replaceAll("[/]{2,}", "(/[^/]*)*/");
+ expression = expression.replaceAll("[*]([^/])", "[^/$1]*$1");
+ expression = expression.replaceAll("(?<!\\[\\^/\\])[*]", "[^/]*");
+ expression = expression.replaceAll("[/]{2,}", "(?:/[^/]*)*/");
return expression;
}
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -29,6 +29,7 @@
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
@@ -185,7 +186,7 @@
}
private ExecutionContext executionContext;
- private ComponentLibrary<Sequencer, SequencerConfig> sequencerLibrary = new ComponentLibrary<Sequencer, SequencerConfig>();
+ private SequencerLibrary sequencerLibrary = new SequencerLibrary();
private Selector sequencerSelector = DEFAULT_SEQUENCER_SELECTOR;
private NodeFilter nodeFilter = DEFAULT_NODE_FILTER;
private ExecutorService executorService;
@@ -431,12 +432,16 @@
for (final NodeChange changedNode : changes) {
// Only care about new nodes or nodes that have new/changed properies ...
if (filter.accept(changedNode)) {
- this.executorService.execute(new Runnable() {
+ try {
+ this.executorService.execute(new Runnable() {
- public void run() {
- processChangedNode(changedNode);
- }
- });
+ public void run() {
+ processChangedNode(changedNode);
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // The executor service has been shut down, so do nothing with this set of changes
+ }
}
}
}
Added: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/AbstractSessionFactory.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/AbstractSessionFactory.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/AbstractSessionFactory.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,218 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.dna.repository.util;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import org.jboss.dna.common.SystemFailureException;
+import org.jboss.dna.common.util.ArgCheck;
+
+/**
+ * A SessionFactory implementation that creates {@link Session} instances using {@link Repository} instances.
+ * <p>
+ * This factory using a naming convention where the name supplied to the {@link #createSession(String)} contains both the name of
+ * the repository and the name of the workspace. Typically, this is <i><code>repositoryName/workspaceName</code></i>, where
+ * <code>repositoryName</code> is the name under which the Repository instance was bound, and <code>workspaceName</code> is
+ * the name of the workspace. Note that this method looks for the last delimiter in the whole name to distinguish between the
+ * repository and workspace names.
+ * </p>
+ * <p>
+ * For example, if "<code>java:comp/env/repository/dataRepository/myWorkspace</code>" is passed to the
+ * {@link #createSession(String)} method, this factory will look for a {@link Repository} instance registered with the name "<code>java:comp/env/repository/dataRepository</code>"
+ * and use it to {@link Repository#login(String) create a session} to the workspace named "<code>myWorkspace</code>".
+ * </p>
+ * <p>
+ * By default, this factory creates an anonymous JCR session. To use sessions with specific {@link Credentials}, simply
+ * {@link #registerCredentials(String, Credentials) register} credentials for the appropriate repository/workspace name. For
+ * security reasons, it is not possible to retrieve the Credentials once registered with this factory.
+ * </p>
+ * @author Randall Hauch
+ */
+public abstract class AbstractSessionFactory implements SessionFactory {
+
+ protected static char[] DEFAULT_DELIMITERS = new char[] {'/'};
+
+ private final char[] workspaceDelims;
+ private final String workspaceDelimsRegexCharacterSet;
+ private final Map<String, Credentials> credentials = new ConcurrentHashMap<String, Credentials>();
+
+ /**
+ * Create an instance of the factory with the default delimiters.
+ */
+ public AbstractSessionFactory() {
+ this(null);
+ }
+
+ /**
+ * Create an instance of the factory by supplying naming context and the characters that may be used to delimit the workspace
+ * name from the repository name.
+ * @param workspaceDelimiters the delimiters, or null/empty if the default delimiter of '/' should be used.
+ * @throws IllegalArgumentException if the context parameter is null
+ */
+ public AbstractSessionFactory( char... workspaceDelimiters ) {
+ this.workspaceDelims = (workspaceDelimiters == null || workspaceDelimiters.length == 0) ? DEFAULT_DELIMITERS : workspaceDelimiters;
+ StringBuilder sb = new StringBuilder();
+ for (char delim : this.workspaceDelims) {
+ switch (delim) {
+ case '\\':
+ sb.append("\\");
+ break;
+ // case '[' : sb.append("\\["); break;
+ case ']':
+ sb.append("\\]");
+ break;
+ case '-':
+ sb.append("\\-");
+ break;
+ case '^':
+ sb.append("\\^");
+ break;
+ default:
+ sb.append(delim);
+ }
+ }
+ this.workspaceDelimsRegexCharacterSet = sb.toString();
+ }
+
+ /**
+ * Convenience method to bind a repository in JNDI. Repository instances can be bound into JNDI using any technique, so this
+ * method need not be used. <i>Note that the name should not contain the workspace part.</i>
+ * @param name the name of the repository, without the workspace name component.
+ * @param repository the repository to be bound, or null if an existing repository should be unbound.
+ */
+ public void registerRepository( String name, Repository repository ) {
+ assert name != null;
+ // Remove all trailing delimiters ...
+ name = name.replaceAll("[" + this.workspaceDelimsRegexCharacterSet + "]+$", "");
+ if (repository != null) {
+ this.doRegisterRepository(name, repository);
+ } else {
+ this.doUnregisterRepository(name);
+ }
+ }
+
+ protected abstract void doRegisterRepository( String name, Repository repository ) throws SystemFailureException;
+
+ protected abstract void doUnregisterRepository( String name ) throws SystemFailureException;
+
+ protected abstract Repository findRegisteredRepository( String name ) throws SystemFailureException;
+
+ /**
+ * Register the credentials for the repository and workspace given by the supplied name, username and password. This is
+ * equivalent to calling <code>registerCredentials(name, new SimpleCredentials(username,password))</code>, although if
+ * <code>username</code> is null then this is equivalent to <code>registerCredentials(name,null)</code>.
+ * @param name the name of the repository and workspace
+ * @param username the username to use, or null if the existing credentials for the named workspace should be removed
+ * @param password the password, may be null or empty
+ * @return true if this overwrote existing credentials
+ * @see #registerCredentials(String, Credentials)
+ * @see #removeCredentials(String)
+ */
+ public boolean registerCredentials( String name, String username, char[] password ) {
+ if (password == null && username != null) password = new char[] {};
+ Credentials creds = username == null ? null : new SimpleCredentials(username, password);
+ return registerCredentials(name, creds);
+ }
+
+ /**
+ * Register the credentials to be used for the named repository and workspace. Use the same name as used to
+ * {@link #createSession(String) create sessions}.
+ * @param name the name of the repository and workspace
+ * @param credentials the credentials to use, or null if the existing credentials for the named workspace should be removed
+ * @return true if this overwrote existing credentials
+ * @see #registerCredentials(String, String, char[])
+ * @see #removeCredentials(String)
+ */
+ public boolean registerCredentials( String name, Credentials credentials ) {
+ boolean foundExisting = false;
+ name = name != null ? name.trim() : null;
+ if (credentials == null) {
+ foundExisting = this.credentials.remove(name) != null;
+ } else {
+ foundExisting = this.credentials.put(name, credentials) != null;
+ }
+ return foundExisting;
+ }
+
+ /**
+ * Remove any credentials associated with the named repository and workspace. This is equivalent to calling
+ * <code>registerCredentials(name,null)</code>.
+ * @param name the name of the repository and workspace
+ * @return true if existing credentials were found and removed, or false if no such credentials existed
+ * @see #registerCredentials(String, Credentials)
+ */
+ public boolean removeCredentials( String name ) {
+ return registerCredentials(name, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Session createSession( String name ) throws RepositoryException {
+ ArgCheck.isNotNull(name, "session name");
+ name = name.trim();
+ // Look up the Repository object in JNDI ...
+ String repositoryName = getRepositoryName(name);
+ Repository repository = findRegisteredRepository(repositoryName);
+
+ // Determine the name of the workspace ...
+ String workspaceName = getWorkspaceName(name);
+
+ // Look up any credentials, which may be null ...
+ Credentials creds = this.credentials.get(name);
+
+ // Create a session to the specified workspace and using the credentials (either or both may be null) ...
+ return repository.login(creds, workspaceName);
+ }
+
+ protected String getWorkspaceName( String name ) {
+ assert name != null;
+ int index = getIndexOfLastWorkspaceDelimiter(name);
+ if (index == -1) return null;
+ if ((index + 1) == name.length()) return null; // delim is the last character
+ return name.substring(index + 1);
+ }
+
+ protected String getRepositoryName( String name ) {
+ assert name != null;
+ int index = getIndexOfLastWorkspaceDelimiter(name);
+ if (index == -1) return name; // no delim
+ if ((index + 1) == name.length()) return name.substring(0, index); // delim as last character
+ return name.substring(0, index);
+ }
+
+ protected int getIndexOfLastWorkspaceDelimiter( String name ) {
+ int index = -1;
+ for (char delim : this.workspaceDelims) {
+ int i = name.lastIndexOf(delim);
+ index = Math.max(index, i);
+ }
+ return index;
+ }
+
+}
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrTools.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrTools.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrTools.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -268,20 +268,33 @@
}
public Node findOrCreateNode( Session session, String path ) throws RepositoryException {
+ return findOrCreateNode(session, path, null, null);
+ }
+
+ public Node findOrCreateNode( Session session, String path, String nodeType ) throws RepositoryException {
+ return findOrCreateNode(session, path, nodeType, nodeType);
+ }
+
+ public Node findOrCreateNode( Session session, String path, String defaultNodeType, String finalNodeType ) throws RepositoryException {
Node root = session.getRootNode();
+ return findOrCreateNode(session, root, path, defaultNodeType, finalNodeType);
+ }
+
+ public Node findOrCreateNode( Session session, Node parentNode, String path, String defaultNodeType, String finalNodeType ) throws RepositoryException {
// Remove leading and trailing slashes ...
String relPath = path.replaceAll("^/+", "").replaceAll("/+$", "");
// Look for the node first ...
try {
- return root.getNode(relPath);
+ return parentNode.getNode(relPath);
} catch (PathNotFoundException e) {
// continue
}
// Create the node, which has to be done segment by segment ...
String[] pathSegments = relPath.split("/");
- Node node = root;
- for (String pathSegment : pathSegments) {
+ Node node = parentNode;
+ for (int i = 0, len = pathSegments.length; i != len; ++i) {
+ String pathSegment = pathSegments[i];
pathSegment = pathSegment.trim();
if (pathSegment.length() == 0) continue;
if (node.hasNode(pathSegment)) {
@@ -291,10 +304,24 @@
// Make sure there is no index on the final segment ...
String pathSegmentWithNoIndex = pathSegment.replaceAll("(\\[\\d+\\])+$", "");
// Create the node ...
- node = node.addNode(pathSegmentWithNoIndex);
+ String nodeType = defaultNodeType;
+ if (i == len - 1 && finalNodeType != null) nodeType = finalNodeType;
+ if (nodeType != null) {
+ node = node.addNode(pathSegmentWithNoIndex, nodeType);
+ } else {
+ node = node.addNode(pathSegmentWithNoIndex);
+ }
}
}
return node;
}
+ public Node findOrCreateChild( Session session, Node parent, String name ) throws RepositoryException {
+ return findOrCreateChild(session, parent, name, null);
+ }
+
+ public Node findOrCreateChild( Session session, Node parent, String name, String nodeType ) throws RepositoryException {
+ return findOrCreateNode(session, parent, name, nodeType, nodeType);
+ }
+
}
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JndiSessionFactory.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JndiSessionFactory.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JndiSessionFactory.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -22,13 +22,9 @@
package org.jboss.dna.repository.util;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
import javax.jcr.Credentials;
import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
@@ -58,14 +54,9 @@
* </p>
* @author Randall Hauch
*/
-public class JndiSessionFactory implements SessionFactory {
+public class JndiSessionFactory extends AbstractSessionFactory {
- protected static char[] DEFAULT_DELIMITERS = new char[] {'/'};
-
- private final char[] workspaceDelims;
- private final String workspaceDelimsRegexCharacterSet;
private final Context context;
- private final Map<String, Credentials> credentials = new ConcurrentHashMap<String, Credentials>();
/**
* Create an instance of the factory by creating a new {@link InitialContext}. This is equivalent to calling
@@ -104,146 +95,44 @@
* @throws IllegalArgumentException if the context parameter is null
*/
public JndiSessionFactory( Context context, char... workspaceDelimiters ) {
+ super(workspaceDelimiters);
ArgCheck.isNotNull(context, "initial context");
this.context = context;
- this.workspaceDelims = (workspaceDelimiters == null || workspaceDelimiters.length == 0) ? DEFAULT_DELIMITERS : workspaceDelimiters;
- StringBuilder sb = new StringBuilder();
- for (char delim : this.workspaceDelims) {
- switch (delim) {
- case '\\':
- sb.append("\\");
- break;
- // case '[' : sb.append("\\["); break;
- case ']':
- sb.append("\\]");
- break;
- case '-':
- sb.append("\\-");
- break;
- case '^':
- sb.append("\\^");
- break;
- default:
- sb.append(delim);
- }
- }
- this.workspaceDelimsRegexCharacterSet = sb.toString();
}
/**
- * Convenience method to bind a repository in JNDI. Repository instances can be bound into JNDI using any technique, so this
- * method need not be used. <i>Note that the name should not contain the workspace part.</i>
- * @param name the name of the repository, without the workspace name component.
- * @param repository the repository to be bound, or null if an existing repository should be unbound.
- * @throws NamingException if there is a problem registering the supplied repository
+ * {@inheritDoc}
*/
- public void registerRepository( String name, Repository repository ) throws NamingException {
- assert name != null;
- // Remove all trailing delimiters ...
- name = name.replaceAll("[" + this.workspaceDelimsRegexCharacterSet + "]+$", "");
- if (repository != null) {
+ @Override
+ protected void doRegisterRepository( String name, Repository repository ) throws SystemFailureException {
+ try {
this.context.bind(name, repository);
- } else {
- this.context.unbind(name);
+ } catch (NamingException e) {
+ throw new SystemFailureException(RepositoryI18n.unableToRegisterRepositoryInJndi.text(name));
}
}
/**
- * Register the credentials for the repository and workspace given by the supplied name, username and password. This is
- * equivalent to calling <code>registerCredentials(name, new SimpleCredentials(username,password))</code>, although if
- * <code>username</code> is null then this is equivalent to <code>registerCredentials(name,null)</code>.
- * @param name the name of the repository and workspace
- * @param username the username to use, or null if the existing credentials for the named workspace should be removed
- * @param password the password, may be null or empty
- * @return true if this overwrote existing credentials
- * @see #registerCredentials(String, Credentials)
- * @see #removeCredentials(String)
+ * {@inheritDoc}
*/
- public boolean registerCredentials( String name, String username, char[] password ) {
- if (password == null && username != null) password = new char[] {};
- Credentials creds = username == null ? null : new SimpleCredentials(username, password);
- return registerCredentials(name, creds);
- }
-
- /**
- * Register the credentials to be used for the named repository and workspace. Use the same name as used to
- * {@link #createSession(String) create sessions}.
- * @param name the name of the repository and workspace
- * @param credentials the credentials to use, or null if the existing credentials for the named workspace should be removed
- * @return true if this overwrote existing credentials
- * @see #registerCredentials(String, String, char[])
- * @see #removeCredentials(String)
- */
- public boolean registerCredentials( String name, Credentials credentials ) {
- boolean foundExisting = false;
- name = name != null ? name.trim() : null;
- if (credentials == null) {
- foundExisting = this.credentials.remove(name) != null;
- } else {
- foundExisting = this.credentials.put(name, credentials) != null;
+ @Override
+ protected void doUnregisterRepository( String name ) throws SystemFailureException {
+ try {
+ this.context.unbind(name);
+ } catch (NamingException e) {
+ throw new SystemFailureException(RepositoryI18n.unableToUnregisterRepositoryInJndi.text(name));
}
- return foundExisting;
}
/**
- * Remove any credentials associated with the named repository and workspace. This is equivalent to calling
- * <code>registerCredentials(name,null)</code>.
- * @param name the name of the repository and workspace
- * @return true if existing credentials were found and removed, or false if no such credentials existed
- * @see #registerCredentials(String, Credentials)
- */
- public boolean removeCredentials( String name ) {
- return registerCredentials(name, null);
- }
-
- /**
* {@inheritDoc}
*/
- public Session createSession( String name ) throws RepositoryException {
- ArgCheck.isNotNull(name, "session name");
- name = name.trim();
- // Look up the Repository object in JNDI ...
- String repositoryName = getRepositoryName(name);
- Repository repository = null;
+ @Override
+ protected Repository findRegisteredRepository( String name ) throws SystemFailureException {
try {
- repository = (Repository)this.context.lookup(repositoryName);
- } catch (NamingException err) {
- throw new SystemFailureException(RepositoryI18n.unableToFindRepositoryInJndi.text(repositoryName));
+ return (Repository)this.context.lookup(name);
+ } catch (NamingException e) {
+ throw new SystemFailureException(RepositoryI18n.unableToFindRepositoryInJndi.text(name));
}
-
- // Determine the name of the workspace ...
- String workspaceName = getWorkspaceName(name);
-
- // Look up any credentials, which may be null ...
- Credentials creds = this.credentials.get(name);
-
- // Create a session to the specified workspace and using the credentials (either or both may be null) ...
- return repository.login(creds, workspaceName);
}
-
- protected String getWorkspaceName( String name ) {
- assert name != null;
- int index = getIndexOfLastWorkspaceDelimiter(name);
- if (index == -1) return null;
- if ((index + 1) == name.length()) return null; // delim is the last character
- return name.substring(index + 1);
- }
-
- protected String getRepositoryName( String name ) {
- assert name != null;
- int index = getIndexOfLastWorkspaceDelimiter(name);
- if (index == -1) return name; // no delim
- if ((index + 1) == name.length()) return name.substring(0, index); // delim as last character
- return name.substring(0, index);
- }
-
- protected int getIndexOfLastWorkspaceDelimiter( String name ) {
- int index = -1;
- for (char delim : this.workspaceDelims) {
- int i = name.lastIndexOf(delim);
- index = Math.max(index, i);
- }
- return index;
- }
-
}
Added: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.util;
+
+/**
+ * @author Randall Hauch
+ */
+public class SimpleExecutionContext extends SimpleSessionFactory implements ExecutionContext {
+
+ private final JcrTools tools = new JcrTools();
+
+ public SimpleExecutionContext() {
+ super();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SessionFactory getSessionFactory() {
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public JcrTools getTools() {
+ return this.tools;
+ }
+
+}
Added: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleSessionFactory.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleSessionFactory.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleSessionFactory.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.dna.repository.util;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+import javax.naming.InitialContext;
+import org.jboss.dna.common.SystemFailureException;
+import org.jboss.dna.repository.RepositoryI18n;
+
+/**
+ * A SessionFactory implementation that creates {@link Session} instances using {@link Repository} instances registered in JNDI.
+ * <p>
+ * This factory using a naming convention where the name supplied to the {@link #createSession(String)} contains both the name of
+ * the repository and the name of the workspace. Typically, this is <i><code>repositoryName/workspaceName</code></i>, where
+ * <code>repositoryName</code> is the JNDI name under which the Repository instance was bound, and <code>workspaceName</code>
+ * is the name of the workspace. Note that this method looks for the last delimiter in the whole name to distinguish between the
+ * repository and workspace names.
+ * </p>
+ * <p>
+ * For example, if "<code>java:comp/env/repository/dataRepository/myWorkspace</code>" is passed to the
+ * {@link #createSession(String)} method, this factory will look for a {@link Repository} instance registered in JDNI with the
+ * name "<code>java:comp/env/repository/dataRepository</code>" and use it to {@link Repository#login(String) create a session}
+ * to the workspace named "<code>myWorkspace</code>".
+ * </p>
+ * <p>
+ * By default, this factory creates an anonymous JCR session. To use sessions with specific {@link Credentials}, simply
+ * {@link #registerCredentials(String, Credentials) register} credentials for the appropriate repository/workspace name. For
+ * security reasons, it is not possible to retrieve the Credentials once registered with this factory.
+ * </p>
+ * @author Randall Hauch
+ */
+public class SimpleSessionFactory extends AbstractSessionFactory {
+
+ private final Map<String, Repository> repositories = new ConcurrentHashMap<String, Repository>();
+
+ /**
+ * Create an instance of the factory by creating a new {@link InitialContext}.
+ */
+ public SimpleSessionFactory() {
+ super();
+ }
+
+ /**
+ * Create an instance of the factory by supplying the characters that may be used to delimit the workspace name from the
+ * repository name.
+ * @param workspaceDelimiters the delimiters, or null/empty if the default delimiter of '/' should be used.
+ */
+ public SimpleSessionFactory( char... workspaceDelimiters ) {
+ super(workspaceDelimiters);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doRegisterRepository( String name, Repository repository ) throws SystemFailureException {
+ this.repositories.put(name, repository);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doUnregisterRepository( String name ) throws SystemFailureException {
+ if (this.repositories.remove(name) == null) {
+ throw new SystemFailureException(RepositoryI18n.unableToRemoveRepository.text(name));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Repository findRegisteredRepository( String name ) throws SystemFailureException {
+ Repository repository = this.repositories.get(name);
+ if (repository == null) {
+ throw new SystemFailureException(RepositoryI18n.unableToFindRepositoryWithName.text(name));
+ }
+ return repository;
+ }
+
+}
Modified: trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties
===================================================================
--- trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties 2008-05-06 14:57:52 UTC (rev 115)
@@ -2,6 +2,10 @@
serviceShutdowAndMayNotBeStarted = The {0} has been shutdown and may not be (re)started
serviceShutdowAndMayNotBePaused = The {0} has been shutdown and my not be paused
unableToFindRepositoryInJndi = Unable to find a JCR repository in JNDI at '{0}'
+unableToRegisterRepositoryInJndi = Unable to register a JCR repository in JNDI at '{0}'
+unableToUnregisterRepositoryInJndi = Unable to unregister a JCR repository at JNDI at '{0}'
+unableToRemoveRepository = Unable to remove a JCR repository named '{0}'
+unableToFindRepositoryWithName = Unable to find a JCR repository named '{0}'
errorProcessingEvents = Error processing events from {0}
errorFindingPropertyNameInPropertyAddedEvent = Error finding the name of the added property in the event path {0}
errorFindingPropertyNameInPropertyChangedEvent = Error finding the name of the changed property in the event path {0}
@@ -58,4 +62,6 @@
pathExpressionHasInvalidSelect = Invalid select expression '{0}' in the path expression '{1}=>{2}'
pathExpressionHasInvalidMatch = Invalid match expression '{0}' in the path expression '{1}=>{2}'
+errorUnregisteringWorkspaceListenerWhileShuttingDownObservationService = Error unregistering workspace listener while shutting down observation service
+
invalidRepositoryNodePath = The repository node path '{0}' is not valid: {1}
Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerPathExpressionTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerPathExpressionTest.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerPathExpressionTest.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -177,9 +177,9 @@
assertThat(expr.replaceXPathPatterns("/a/(b/c)[(d|e)/(f|g)/@something]"), is("/a/(b/c)/(d|e)/(f|g)/@something"));
assertThat(expr.replaceXPathPatterns("/a/*/f"), is("/a/[^/]*/f"));
- assertThat(expr.replaceXPathPatterns("/a//f"), is("/a(/[^/]*)*/f"));
- assertThat(expr.replaceXPathPatterns("/a///f"), is("/a(/[^/]*)*/f"));
- assertThat(expr.replaceXPathPatterns("/a/////f"), is("/a(/[^/]*)*/f"));
+ assertThat(expr.replaceXPathPatterns("/a//f"), is("/a(?:/[^/]*)*/f"));
+ assertThat(expr.replaceXPathPatterns("/a///f"), is("/a(?:/[^/]*)*/f"));
+ assertThat(expr.replaceXPathPatterns("/a/////f"), is("/a(?:/[^/]*)*/f"));
}
protected void assertNotMatches( SequencerPathExpression.Matcher matcher ) {
@@ -235,6 +235,21 @@
}
@Test
+ public void shouldMatchExpressionsWithFilenameLikeWildcardSelection() {
+ expr = SequencerPathExpression.compile("/a/*.txt[@something] => .");
+ assertMatches(expr.matcher("/a/b.txt/@something"), "/a/b.txt", "/a/b.txt");
+ assertNotMatches(expr.matcher("/a/b.tx/@something"));
+
+ expr = SequencerPathExpression.compile("/a/*.txt/c[@something] => .");
+ assertMatches(expr.matcher("/a/b.txt/c/@something"), "/a/b.txt/c", "/a/b.txt/c");
+ assertNotMatches(expr.matcher("/a/b.tx/c/@something"));
+
+ expr = SequencerPathExpression.compile("//*.txt[*]/c[@something] => .");
+ assertMatches(expr.matcher("/a/b.txt/c/@something"), "/a/b.txt/c", "/a/b.txt/c");
+ assertNotMatches(expr.matcher("/a/b.tx/c/@something"));
+ }
+
+ @Test
public void shouldMatchExpressionsWithSegmentWildcardSelection() {
expr = SequencerPathExpression.compile("/a//c[d/e/@something] => .");
assertMatches(expr.matcher("/a/c/d/e/@something"), "/a/c", "/a/c");
@@ -353,4 +368,10 @@
assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/b/c/z");
}
+ @Test
+ public void shouldMatchExpressionWithFilenamePatternAndChildProperty() {
+ expr = SequencerPathExpression.compile("//(*.(jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data]=>/images/$1");
+ assertMatches(expr.matcher("/a/b/caution.png/jcr:content/@jcr:data"), "/a/b/caution.png/jcr:content", "/images/caution.png");
+ }
+
}
Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -39,7 +39,7 @@
import org.jboss.dna.repository.sequencers.SequencingService;
import org.jboss.dna.repository.services.ServiceAdministrator;
import org.jboss.dna.repository.util.ExecutionContext;
-import org.jboss.dna.repository.util.SimpleExecutionContext;
+import org.jboss.dna.repository.util.MockExecutionContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +58,7 @@
@Before
public void beforeEach() throws Exception {
- this.executionContext = new SimpleExecutionContext(this, REPOSITORY_WORKSPACE_NAME);
+ this.executionContext = new MockExecutionContext(this, REPOSITORY_WORKSPACE_NAME);
this.sequencingService = new SequencingService();
this.sequencingService.setExecutionContext(this.executionContext);
this.observationService = new ObservationService(this.executionContext.getSessionFactory());
@@ -69,6 +69,7 @@
public void afterEach() throws Exception {
super.shutdownRepository();
this.sequencingService.getAdministrator().shutdown();
+ this.observationService.getAdministrator().shutdown();
}
@Test
Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java (from rev 110, trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/SimpleExecutionContext.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.util;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import org.jboss.dna.common.SystemFailureException;
+import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
+import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrTools;
+import org.jboss.dna.repository.util.SessionFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public class MockExecutionContext implements ExecutionContext {
+
+ private JcrTools tools = new JcrTools();
+ private SessionFactory sessionFactory;
+
+ public MockExecutionContext( final AbstractJcrRepositoryTest test, final String repositoryName ) {
+ this.sessionFactory = new SessionFactory() {
+
+ public Session createSession( String name ) throws RepositoryException {
+ assertThat(name, is(repositoryName));
+ try {
+ return test.getRepository().login(test.getTestCredentials());
+ } catch (IOException e) {
+ throw new SystemFailureException(e);
+ }
+ }
+ };
+ }
+
+ public SessionFactory getSessionFactory() {
+ return sessionFactory;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public JcrTools getTools() {
+ return tools;
+ }
+}
Property changes on: trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/SimpleExecutionContext.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/SimpleExecutionContext.java 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/SimpleExecutionContext.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -1,67 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.repository.util;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.io.IOException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import org.jboss.dna.common.SystemFailureException;
-import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
-import org.jboss.dna.repository.util.ExecutionContext;
-import org.jboss.dna.repository.util.JcrTools;
-import org.jboss.dna.repository.util.SessionFactory;
-
-/**
- * @author Randall Hauch
- */
-public class SimpleExecutionContext implements ExecutionContext {
-
- private JcrTools tools = new JcrTools();
- private SessionFactory sessionFactory;
-
- public SimpleExecutionContext( final AbstractJcrRepositoryTest test, final String repositoryName ) {
- this.sessionFactory = new SessionFactory() {
-
- public Session createSession( String name ) throws RepositoryException {
- assertThat(name, is(repositoryName));
- try {
- return test.getRepository().login(test.getTestCredentials());
- } catch (IOException e) {
- throw new SystemFailureException(e);
- }
- }
- };
- }
-
- public SessionFactory getSessionFactory() {
- return sessionFactory;
- }
-
- /**
- * {@inheritDoc}
- */
- public JcrTools getTools() {
- return tools;
- }
-}
Deleted: trunk/docs/.project
===================================================================
--- trunk/docs/.project 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/docs/.project 2008-05-06 14:57:52 UTC (rev 115)
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>docs</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- </buildSpec>
- <natures>
- </natures>
-</projectDescription>
Added: trunk/docs/examples/getting_started/pom.xml
===================================================================
--- trunk/docs/examples/getting_started/pom.xml (rev 0)
+++ trunk/docs/examples/getting_started/pom.xml 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,133 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.jboss.dna.examples</groupId>
+ <artifactId>getting_started</artifactId>
+ <packaging>pom</packaging>
+ <version>0.1</version>
+ <name>Getting Started examples</name>
+ <description></description>
+
+ <modules>
+ <module>sequencers</module>
+ </modules>
+
+ <properties>
+ <dna-version>0.1-SNAPSHOT</dna-version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-common</artifactId>
+ <version>${dna-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-spi</artifactId>
+ <version>${dna-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-repository</artifactId>
+ <version>${dna-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-maven-classloader</artifactId>
+ <version>${dna-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-sequencer-images</artifactId>
+ <version>${dna-version}</version>
+ </dependency>
+ <!-- Logging (require SLF4J API for compiling, but use Log4J and its SLF4J binding for testing) -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.4.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.4.3</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ </dependency>
+ <!-- Java Content Repository API -->
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <version>1.0.1</version>
+ <scope>compile</scope>
+ </dependency>
+ <!-- Apache Jackrabbit (JCR Implementation) -->
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-api</artifactId>
+ <version>1.3.3</version>
+ <scope>compile</scope>
+ <!-- Exclude these since they are included in JDK 1.5 -->
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-core</artifactId>
+ <version>1.3.3</version>
+ <scope>compile</scope>
+ <!-- Exclude these since they are included in JDK 1.5 -->
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <!-- Testing (note the scope) -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ <debug>true</debug>
+ <showDeprecation>true</showDeprecation>
+ <showWarnings>true</showWarnings>
+ <optimize>true</optimize>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
Property changes on: trunk/docs/examples/getting_started/sequencers
___________________________________________________________________
Name: svn:ignore
+ target
Added: trunk/docs/examples/getting_started/sequencers/.classpath
===================================================================
--- trunk/docs/examples/getting_started/sequencers/.classpath (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/.classpath 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" path="src/main/resources"/>
+ <classpathentry kind="src" path="src/test/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
Added: trunk/docs/examples/getting_started/sequencers/.project
===================================================================
--- trunk/docs/examples/getting_started/sequencers/.project (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/.project 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>docs-getting-started-examples-sequencers</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ </natures>
+</projectDescription>
Added: trunk/docs/examples/getting_started/sequencers/pom.xml
===================================================================
--- trunk/docs/examples/getting_started/sequencers/pom.xml (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/pom.xml 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,95 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <parent>
+ <groupId>org.jboss.dna.examples</groupId>
+ <artifactId>getting_started</artifactId>
+ <version>0.1</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.jboss.dna.examples</groupId>
+ <artifactId>dna-example-sequencers</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>Sequencer Examples</name>
+ <description>Examples that showcase how to use sequencers with a JCR repository.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-repository</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-sequencer-images</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <!--
+ Logging (require SLF4J API for compiling, but use Log4J and its SLF4J binding for testing)
+ -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <!--
+ Java Content Repository API
+ -->
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ </dependency>
+ <!--
+ Apache Jackrabbit (JCR Implementation) for repository implementation
+ -->
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-core</artifactId>
+ </dependency>
+ <!--
+ Test cases use JUnit
+ -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/basic.xml</descriptor>
+ </descriptors>
+ <finalName>${pom.artifactId}</finalName>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>directory-inline</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
Added: trunk/docs/examples/getting_started/sequencers/src/main/assembly/basic.xml
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/assembly/basic.xml (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/assembly/basic.xml 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,57 @@
+<assembly>
+ <id>basic</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory/>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>src/main/resources/</directory>
+ <outputDirectory/>
+ <includes>
+ <include>*.png</include>
+ <include>*.gif</include>
+ <include>*.jpg</include>
+ <include>*.pict</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ <files>
+ <file>
+ <source>src/main/config/run.sh</source>
+ <fileMode>0744</fileMode>
+ </file>
+ <file>
+ <source>src/main/resources/jackrabbitConfig.xml</source>
+ <fileMode>0644</fileMode>
+ </file>
+ <file>
+ <source>src/main/resources/jackrabbitNodeTypes.cnd</source>
+ <fileMode>0644</fileMode>
+ </file>
+ <file>
+ <source>src/main/resources/log4j.properties</source>
+ <fileMode>0644</fileMode>
+ </file>
+ </files>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/lib</outputDirectory>
+ <unpack>false</unpack>
+ <includes>
+ <!-- Include everything needed by the examples. -->
+ <include>*:jar:*</include>
+ </includes>
+ <!--excludes>
+ <exclude>*:sources</exclude>
+ </excludes-->
+ </dependencySet>
+ </dependencySets>
+</assembly>
\ No newline at end of file
Added: trunk/docs/examples/getting_started/sequencers/src/main/config/run.sh
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/config/run.sh (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/config/run.sh 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+java -Djava.ext.dirs=`pwd`/lib -cp .:dna-example-sequencers-0.1-SNAPSHOT.jar org.jboss.example.dna.sequencers.SequencingClient $1
\ No newline at end of file
Added: trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/ConsoleInput.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,200 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencers;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.Map;
+import org.jboss.dna.repository.sequencers.SequencingService;
+
+/**
+ * @author Randall Hauch
+ */
+public class ConsoleInput implements UserInterface {
+
+ protected static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+
+ public ConsoleInput( final SequencingClient client ) {
+ try {
+ System.out.println();
+ System.out.print("Starting repository and sequencing service ... ");
+ client.startRepository();
+ System.out.print("done.\nStarting sequencing service ... ");
+ client.startDnaServices();
+ System.out.println("done.");
+ System.out.println();
+
+ System.out.println(getMenu());
+ Thread eventThread = new Thread(new Runnable() {
+
+ private boolean quit = false;
+
+ public void run() {
+ try {
+ while (!quit) {
+ System.out.print(">");
+ try {
+ String input = in.readLine();
+ if (input.length() != 1) {
+ System.out.println("Please enter a valid option.");
+ continue;
+ }
+
+ char option = input.charAt(0);
+ switch (option) {
+ case 'u':
+ client.uploadFile();
+ break;
+ case 's':
+ client.search();
+ break;
+ case 'm':
+ System.out.println(getMenu());
+ break;
+ case 'p':
+ System.out.println(getStatistics(client.getStatistics()));
+ break;
+ case 'q':
+ quit = true;
+ break;
+ default:
+ System.out.println("Invalid option.");
+ break;
+ }
+ } catch (NumberFormatException e) {
+ System.out.println("Invalid integer " + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ } finally {
+ try {
+ // Terminate ...
+ System.out.println();
+ System.out.print("Shutting down sequencing service ... ");
+ client.shutdownDnaServices();
+ System.out.print("done.\nShutting down repository ... ");
+ client.shutdownRepository();
+ System.out.print("done.");
+ System.out.println();
+ System.out.println();
+ } catch (Exception err) {
+ System.out.println("Error shutting down sequencing service and repository: " + err.getLocalizedMessage());
+ err.printStackTrace(System.err);
+ }
+ }
+ }
+ });
+
+ eventThread.start();
+ } catch (Exception err) {
+ System.out.println("Error: " + err.getLocalizedMessage());
+ err.printStackTrace(System.err);
+ }
+ }
+
+ protected String getMenu() {
+ StringBuilder buffer = new StringBuilder();
+ buffer.append("-----------------------------------\n");
+ buffer.append("Menu:\n");
+ buffer.append("\n");
+ buffer.append("u) Upload a file to the repository\n");
+ buffer.append("s) Search the repository using extracted metadata\n");
+ buffer.append("\n");
+ buffer.append("p) Print statistics\n");
+ buffer.append("\n");
+ buffer.append("m) Display menu\n");
+ buffer.append("q) Quit");
+ return buffer.toString();
+ }
+
+ public File getPathOfFileToUpload() throws IllegalArgumentException, IOException {
+ System.out.println("Please enter the file to upload:");
+ String path = in.readLine();
+ File file = new File(path);
+ if (!file.exists()) {
+ throw new IllegalArgumentException("The file \"" + file.getAbsolutePath() + "\" does not exist.");
+ }
+ if (!file.canRead()) {
+ throw new IllegalArgumentException("Unable to read \"" + file.getAbsolutePath() + "\".");
+ }
+ if (!file.isFile()) {
+ throw new IllegalArgumentException("Please specify a file. The file \"" + file.getAbsolutePath() + "\" is a directory.");
+ }
+ return file;
+ }
+
+ public String getRepositoryPath( String defaultPath ) throws IllegalArgumentException, IOException {
+ if (defaultPath != null) defaultPath = defaultPath.trim();
+ if (defaultPath.length() == 0) defaultPath = null;
+ String displayDefaultPath = defaultPath == null ? "" : " [" + defaultPath.trim() + "]";
+ System.out.println("Please enter the repository path where the file should be placed" + displayDefaultPath + ":");
+ String path = in.readLine().trim();
+ if (path.length() == 0) {
+ if (defaultPath == null) {
+ throw new IllegalArgumentException("The path \"" + path + "\" is not valid.");
+ }
+ path = defaultPath;
+ }
+ return path;
+ }
+
+ public void displaySearchResults( List<ImageInfo> images ) {
+ System.out.println();
+ if (images.isEmpty()) {
+ System.out.println("No results were found.");
+ System.out.println();
+ return;
+ }
+ if (images.size() == 1) {
+ System.out.println("1 image was found:");
+ } else {
+ System.out.println("" + images.size() + " images were found:");
+ }
+ int counter = 1;
+ for (ImageInfo image : images) {
+ System.out.println(" Image " + counter++);
+ System.out.println(" Name: " + image.getName());
+ System.out.println(" Path: " + image.getPath());
+ for (Map.Entry<Object, Object> entry : image.getProperties().entrySet()) {
+ System.out.println(" " + entry.getKey() + ": " + entry.getValue());
+ }
+ }
+ System.out.println();
+ }
+
+ public String getStatistics( SequencingService.Statistics stats ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("\n");
+ sb.append("# nodes sequenced: ").append(stats.getNumberOfNodesSequenced()).append("\n");
+ sb.append("# nodes skipped: ").append(stats.getNumberOfNodesSkipped()).append("\n");
+ sb.append("\n");
+ return sb.toString();
+ }
+}
Added: trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/ImageInfo.java
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/ImageInfo.java (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/ImageInfo.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,69 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencers;
+
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author Randall Hauch
+ */
+public class ImageInfo {
+
+ private final Properties properties = new Properties();
+ private final String name;
+ private final String path;
+
+ protected ImageInfo( String path, String name, Properties props ) {
+ this.name = name;
+ this.path = path;
+ if (props != null) this.properties.putAll(props);
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getPath() {
+ return this.path;
+ }
+
+ public Properties getProperties() {
+ return this.properties;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (Map.Entry<Object, Object> entry : this.properties.entrySet()) {
+ sb.append(entry.getKey()).append("=>").append(entry.getValue());
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ }
+ return this.name + " (at " + this.path + ") with properties {" + sb.toString() + "}";
+ }
+
+}
Added: trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,352 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
+import javax.jcr.observation.Event;
+import net.jcip.annotations.NotThreadSafe;
+import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
+import org.apache.jackrabbit.core.TransientRepository;
+import org.jboss.dna.common.SystemFailureException;
+import org.jboss.dna.repository.observation.ObservationService;
+import org.jboss.dna.repository.sequencers.SequencerConfig;
+import org.jboss.dna.repository.sequencers.SequencingService;
+import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrTools;
+import org.jboss.dna.repository.util.SimpleExecutionContext;
+
+/**
+ * @author Randall Hauch
+ */
+@NotThreadSafe
+public class SequencingClient {
+
+ public static final String DEFAULT_JACKRABBIT_CONFIG_PATH = "jackrabbitConfig.xml";
+ public static final String DEFAULT_WORKING_DIRECTORY = "repositoryData";
+ public static final String DEFAULT_REPOSITORY_NAME = "repo";
+ public static final String DEFAULT_WORKSPACE_NAME = "default";
+ public static final String DEFAULT_USERNAME = "jsmith";
+ public static final char[] DEFAULT_PASSWORD = "secret".toCharArray();
+
+ public static void main( String[] args ) throws Exception {
+ SequencingClient client = new SequencingClient();
+ client.setRepositoryInformation(DEFAULT_REPOSITORY_NAME, DEFAULT_WORKSPACE_NAME, "jsmith", "secret".toCharArray());
+ client.setUserInterface(new ConsoleInput(client));
+ }
+
+ private String repositoryName;
+ private String workspaceName;
+ private String username;
+ private char[] password;
+ private String jackrabbitConfigPath;
+ private String workingDirectory;
+ private Session keepAliveSession;
+ private Repository repository;
+ private SequencingService sequencingService;
+ private ObservationService observationService;
+ private UserInterface userInterface;
+ private ExecutionContext executionContext;
+
+ public SequencingClient() {
+ setJackrabbitConfigPath(DEFAULT_JACKRABBIT_CONFIG_PATH);
+ setWorkingDirectory(DEFAULT_WORKING_DIRECTORY);
+ setRepositoryInformation(DEFAULT_REPOSITORY_NAME, DEFAULT_WORKSPACE_NAME, DEFAULT_USERNAME, DEFAULT_PASSWORD);
+ }
+
+ public void setUserInterface( UserInterface userInterface ) {
+ this.userInterface = userInterface;
+ }
+
+ protected void setWorkingDirectory( String workingDirectoryPath ) {
+ this.workingDirectory = workingDirectoryPath != null ? workingDirectoryPath : DEFAULT_WORKING_DIRECTORY;
+ }
+
+ protected void setJackrabbitConfigPath( String jackrabbitConfigPath ) {
+ this.jackrabbitConfigPath = jackrabbitConfigPath != null ? jackrabbitConfigPath : DEFAULT_JACKRABBIT_CONFIG_PATH;
+ }
+
+ protected void setRepositoryInformation( String repositoryName, String workspaceName, String username, char[] password ) {
+ if (this.repository != null) {
+ throw new IllegalArgumentException("Unable to set repository information when repository is already running");
+ }
+ this.repositoryName = repositoryName != null ? repositoryName : DEFAULT_REPOSITORY_NAME;
+ this.workspaceName = workspaceName != null ? workspaceName : DEFAULT_WORKSPACE_NAME;
+ this.username = username;
+ this.password = password;
+ }
+
+ public void startRepository() throws Exception {
+ if (this.repository == null) {
+ try {
+
+ // Load the Jackrabbit configuration ...
+ File configFile = new File(this.jackrabbitConfigPath);
+ if (!configFile.exists()) {
+ throw new SystemFailureException("The Jackrabbit configuration file cannot be found at " + configFile.getAbsoluteFile());
+ }
+ if (!configFile.canRead()) {
+ throw new SystemFailureException("Unable to read the Jackrabbit configuration file at " + configFile.getAbsoluteFile());
+ }
+ String pathToConfig = configFile.getAbsolutePath();
+
+ // Find the directory where the Jackrabbit repository data will be stored ...
+ File workingDirectory = new File(this.workingDirectory);
+ if (workingDirectory.exists()) {
+ if (!workingDirectory.isDirectory()) {
+ throw new SystemFailureException("Unable to create working directory at " + workingDirectory.getAbsolutePath());
+ }
+ }
+ String workingDirectoryPath = workingDirectory.getAbsolutePath();
+
+ // Get the Jackrabbit custom node definition (CND) file ...
+ URL cndFile = Thread.currentThread().getContextClassLoader().getResource("jackrabbitNodeTypes.cnd");
+
+ // Create the Jackrabbit repository instance and establish a session to keep the repository alive ...
+ this.repository = new TransientRepository(pathToConfig, workingDirectoryPath);
+ if (this.username != null) {
+ Credentials credentials = new SimpleCredentials(this.username, this.password);
+ this.keepAliveSession = this.repository.login(credentials, this.workspaceName);
+ } else {
+ this.keepAliveSession = this.repository.login();
+ }
+
+ try {
+ // Register the node types (only valid the first time) ...
+ JackrabbitNodeTypeManager mgr = (JackrabbitNodeTypeManager)this.keepAliveSession.getWorkspace().getNodeTypeManager();
+ mgr.registerNodeTypes(cndFile.openStream(), JackrabbitNodeTypeManager.TEXT_X_JCR_CND);
+ } catch (RepositoryException e) {
+ if (!e.getMessage().contains("already exists")) throw e;
+ }
+
+ } catch (Exception e) {
+ this.repository = null;
+ this.keepAliveSession = null;
+ throw e;
+ }
+ }
+ }
+
+ public void shutdownRepository() throws Exception {
+ if (this.repository != null) {
+ try {
+ this.keepAliveSession.logout();
+ } finally {
+ this.repository = null;
+ this.keepAliveSession = null;
+ }
+ }
+ }
+
+ public void startDnaServices() throws Exception {
+ if (this.repository == null) {
+ this.startRepository();
+ }
+ if (this.sequencingService != null) {
+ return;
+ }
+ // Create an execution context for the sequencing service.
+ // The repository instances and workspace names are registered, and that the service will reference.
+ // the repository ...
+ SimpleExecutionContext executionContext = new SimpleExecutionContext();
+ // Register the JCR repository ...
+ executionContext.registerRepository(this.repositoryName, this.repository);
+ if (this.username != null) {
+ Credentials credentials = new SimpleCredentials(this.username, this.password);
+ executionContext.registerCredentials(this.repositoryName + "/" + this.workspaceName, credentials);
+ }
+ this.executionContext = executionContext;
+
+ // Create the sequencing service ...
+ this.sequencingService = new SequencingService();
+ this.sequencingService.setExecutionContext(executionContext);
+
+ // Add the configuration for the image sequencer. This sequencer class should be on the thread's current context class
+ // loader, or if that's null the classloader that loaded the SequencingService class.
+ //
+ // The path expressions tell the service that this sequencer should be invoked on the "jcr:data" property
+ // on the "jcr:content" child node of any node uploaded to the repository whose name ends with one of the
+ // supported extensions, and it should place the output metadata in a node with the same name as the file
+ // but immediately below the "/images" node. Path expressions can be fairly complex, and can even
+ // specify that the generated information be placed in a different repository.
+ //
+ // Sequencers can be added before or after the service is started.
+ String name = "Image Sequencer";
+ String desc = "Sequences image files to extract the characteristics of the image";
+ String classname = "org.jboss.dna.sequencer.images.ImageMetadataSequencer";
+ String[] classpath = null; // Use the current classpath
+ String[] pathExpressions = {"//(*.(jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data] => /images/$1"};
+ SequencerConfig imageSequencerConfig = new SequencerConfig(name, desc, classname, classpath, pathExpressions);
+ this.sequencingService.addSequencer(imageSequencerConfig);
+
+ // Start up the sequencing service ...
+ this.sequencingService.getAdministrator().start();
+
+ // Register the sequencing service as a listener using the observation service ...
+ this.observationService = new ObservationService(this.executionContext.getSessionFactory());
+ this.observationService.getAdministrator().start();
+ this.observationService.addListener(this.sequencingService);
+ this.observationService.monitor(this.repositoryName + "/" + this.workspaceName, Event.NODE_ADDED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED);
+ }
+
+ public void shutdownDnaServices() throws Exception {
+ if (this.sequencingService == null) return;
+
+ try {
+ // Shut down the service and wait until it's all shut down ...
+ this.sequencingService.getAdministrator().shutdown();
+ this.sequencingService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+
+ // Shut down the observation service ...
+ this.observationService.getAdministrator().shutdown();
+ this.observationService.getAdministrator().awaitTermination(5, TimeUnit.SECONDS);
+
+ } finally {
+ this.sequencingService = null;
+ this.observationService = null;
+ }
+ }
+
+ public SequencingService.Statistics getStatistics() {
+ return this.sequencingService.getStatistics();
+ }
+
+ public void uploadFile() throws Exception {
+ File file = this.userInterface.getPathOfFileToUpload();
+ String nodePath = this.userInterface.getRepositoryPath("/a/b/" + file.getName());
+ String mimeType = getMimeType(file);
+ uploadFile(new FileInputStream(file), nodePath, mimeType);
+ }
+
+ public void search() throws Exception {
+ List<ImageInfo> images = getImages();
+ // Display the search results ...
+ this.userInterface.displaySearchResults(images);
+ }
+
+ protected List<ImageInfo> getImages() throws Exception {
+ List<ImageInfo> images = new ArrayList<ImageInfo>();
+ Session session = createSession();
+ try {
+ // Find the image node ...
+ Node root = session.getRootNode();
+ if (root.hasNode("images")) {
+ Node imagesNode = root.getNode("images");
+
+ // Iterate over each child ...
+ for (NodeIterator iter = imagesNode.getNodes(); iter.hasNext();) {
+ Node imageNode = iter.nextNode();
+ String nodePath = imageNode.getPath();
+ String nodeName = imageNode.getName();
+ if (imageNode.hasNode("image:metadata")) {
+ imageNode = imageNode.getNode("image:metadata");
+
+ // Create a Properties object containing the properties for this node; ignore any children ...
+ Properties props = new Properties();
+ for (PropertyIterator propertyIter = imageNode.getProperties(); propertyIter.hasNext();) {
+ Property property = propertyIter.nextProperty();
+ String name = property.getName();
+ String stringValue = null;
+ if (property.getDefinition().isMultiple()) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (Value value : property.getValues()) {
+ if (!first) {
+ sb.append(", ");
+ first = false;
+ }
+ sb.append(value.getString());
+ }
+ stringValue = sb.toString();
+ } else {
+ stringValue = property.getValue().getString();
+ }
+ props.put(name, stringValue);
+ }
+ // Create the image information object, and add it to the collection ...
+ ImageInfo info = new ImageInfo(nodePath, nodeName, props);
+ images.add(info);
+ }
+ }
+ }
+ } finally {
+ session.logout();
+ }
+ return images;
+ }
+
+ protected Session createSession() throws RepositoryException {
+ return this.executionContext.getSessionFactory().createSession(this.repositoryName + "/" + this.workspaceName);
+ }
+
+ protected boolean uploadFile( InputStream content, String nodePath, String mimeType ) throws Exception {
+ Session session = createSession();
+ JcrTools tools = this.executionContext.getTools();
+ try {
+ // Create the node at the supplied path ...
+ Node node = tools.findOrCreateNode(session, nodePath, "nt:folder", "nt:file");
+
+ // Upload the file to that node ...
+ Node contentNode = tools.findOrCreateChild(session, node, "jcr:content", "nt:resource");
+ contentNode.setProperty("jcr:mimeType", mimeType);
+ contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
+ contentNode.setProperty("jcr:data", content);
+
+ // Save the session ...
+ session.save();
+ } finally {
+ session.logout();
+ }
+ return true;
+ }
+
+ protected String getMimeType( File file ) {
+ String extension = file.getName().toLowerCase();
+ if (extension.endsWith(".gif")) return "image/gif";
+ if (extension.endsWith(".png")) return "image/png";
+ if (extension.endsWith(".pict")) return "image/x-pict";
+ if (extension.endsWith(".bmp")) return "image/bmp";
+ if (extension.endsWith(".jpg")) return "image/jpeg";
+ if (extension.endsWith(".jpe")) return "image/jpeg";
+ if (extension.endsWith(".jpeg")) return "image/jpeg";
+ if (extension.endsWith(".ras")) return "image/x-cmu-raster";
+ throw new SystemFailureException("Unknown mime type for file " + file);
+ }
+
+}
Added: trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/java/org/jboss/example/dna/sequencers/UserInterface.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencers;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Randall Hauch
+ */
+public interface UserInterface {
+
+ public File getPathOfFileToUpload() throws IllegalArgumentException, IOException;
+
+ public String getRepositoryPath( String defaultPath ) throws IllegalArgumentException, IOException;
+
+ public void displaySearchResults( List<ImageInfo> images ) throws IOException;
+}
Added: trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.gif
===================================================================
(Binary files differ)
Property changes on: trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.jpg
===================================================================
(Binary files differ)
Property changes on: trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.pict
===================================================================
(Binary files differ)
Property changes on: trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.pict
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/examples/getting_started/sequencers/src/main/resources/caution.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/docs/examples/getting_started/sequencers/src/main/resources/jackrabbitConfig.xml
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/resources/jackrabbitConfig.xml (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/resources/jackrabbitConfig.xml 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,115 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.2//EN"
+ "http://jackrabbit.apache.org/dtd/repository-1.2.dtd">
+<!-- Example Repository Configuration File -->
+<Repository>
+ <!--
+ virtual file system where the repository stores global state
+ (e.g. registered namespaces, custom node types, etc.)
+ -->
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+ <param name="path" value="${rep.home}/repository"/>
+ </FileSystem>
+
+ <!--
+ security configuration
+ -->
+ <Security appName="Jackrabbit">
+ <!--
+ access manager:
+ class: FQN of class implementing the AccessManager interface
+ -->
+ <AccessManager class="org.apache.jackrabbit.core.security.SimpleAccessManager">
+ <!-- <param name="config" value="${rep.home}/access.xml"/> -->
+ </AccessManager>
+
+ <LoginModule class="org.apache.jackrabbit.core.security.SimpleLoginModule">
+ <!-- anonymous user name ('anonymous' is the default value) -->
+ <param name="anonymousId" value="anonymous"/>
+ <!--
+ default user name to be used instead of the anonymous user
+ when no login credentials are provided (unset by default)
+ -->
+ <!-- <param name="defaultUserId" value="superuser"/> -->
+ </LoginModule>
+ </Security>
+
+ <!--
+ location of workspaces root directory and name of default workspace
+ -->
+ <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default"/>
+ <!--
+ workspace configuration template:
+ used to create the initial workspace if there's no workspace yet
+ -->
+ <Workspace name="Jackrabbit Core">
+ <!--
+ virtual file system of the workspace:
+ class: FQN of class implementing the FileSystem interface
+ -->
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+ <param name="path" value="${wsp.home}"/>
+ </FileSystem>
+ <!--
+ persistence manager of the workspace:
+ class: FQN of class implementing the PersistenceManager interface
+ -->
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager">
+ <param name="persistent" value="false"/>
+ </PersistenceManager>
+ <!--
+ Search index and the file system it uses.
+ class: FQN of class implementing the QueryHandler interface
+ -->
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+ <param name="path" value="${wsp.home}/index"/>
+ </SearchIndex>
+ </Workspace>
+
+ <!--
+ Configures the versioning
+ -->
+ <Versioning rootPath="${rep.home}/version">
+ <!--
+ Configures the filesystem to use for versioning for the respective
+ persistence manager
+ -->
+ <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+ <param name="path" value="${rep.home}/version" />
+ </FileSystem>
+
+ <!--
+ Configures the persistence manager to be used for persisting version state.
+ Please note that the current versioning implementation is based on
+ a 'normal' persistence manager, but this could change in future
+ implementations.
+ -->
+ <PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager">
+ <param name="persistent" value="false"/>
+ </PersistenceManager>
+ </Versioning>
+
+ <!--
+ Search index for content that is shared repository wide
+ (/jcr:system tree, contains mainly versions)
+ -->
+ <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+ <param name="path" value="${rep.home}/repository/index"/>
+ </SearchIndex>
+</Repository>
Added: trunk/docs/examples/getting_started/sequencers/src/main/resources/jackrabbitNodeTypes.cnd
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/resources/jackrabbitNodeTypes.cnd (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/resources/jackrabbitNodeTypes.cnd 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,37 @@
+<jcr='http://www.jcp.org/jcr/1.0'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+<mix='http://www.jcp.org/jcr/mix/1.0'>
+<image='http://jboss.org/dna/images/1.0'>
+
+// ----------------------------------------------------------
+// JCR Pre-defined Mixin Types that are not loaded by default
+// ----------------------------------------------------------
+
+[mix:mimeType] mixin
+ - jcr:mimeType (string)
+ - jcr:encoding (string)
+
+
+// -------------------
+// DNA Image Sequencer
+// -------------------
+
+/**
+ * Marker mixin that defines the root of a Maven 2 repository.
+ */
+[image:metadata] > nt:unstructured
+ - image:mimeType (string)
+ - image:encoding (string)
+ - image:formatName (string) mandatory
+ - image:width (long)
+ - image:height (long)
+ - image:bitsPerPixel (long)
+ - image:progressive (boolean)
+ - image:numberOfImages (long)
+ - image:physicalWidthDpi (long)
+ - image:physicalHeightDpi (long)
+ - image:physicalWidthInches (long)
+ - image:physicalHeightInches (long)
+
+
+
Added: trunk/docs/examples/getting_started/sequencers/src/main/resources/log4j.properties
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/main/resources/log4j.properties (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/main/resources/log4j.properties 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,17 @@
+# Direct log messages to stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %m%n
+
+# Root logger option
+log4j.rootLogger=INFO, stdout
+
+# Set up the default logging to be INFO level, then override specific units
+log4j.logger.org.jboss.dna=INFO
+log4j.logger.org.jboss.dna.tests.integration.jackrabbit.JackrabbitMySqlStressTest=DEBUG
+
+# Jackrabbit logging
+log4j.logger.org.apache.jackrabbit=WARN, stdout
+log4j.logger.org.apache.derby=INFO, stdout
+
Added: trunk/docs/examples/getting_started/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java
===================================================================
--- trunk/docs/examples/getting_started/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java (rev 0)
+++ trunk/docs/examples/getting_started/sequencers/src/test/java/org/jboss/example/dna/sequencers/SequencingClientTest.java 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.example.dna.sequencers;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.net.URL;
+import java.util.List;
+import org.jboss.dna.common.util.FileUtil;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class SequencingClientTest {
+
+ private URL file;
+ private SequencingClient client;
+
+ @Before
+ public void beforeEach() throws Exception {
+ this.file = Thread.currentThread().getContextClassLoader().getResource("caution.png");
+ client = new SequencingClient();
+ client.setWorkingDirectory("target/repositoryData");
+ client.setJackrabbitConfigPath("src/main/resources/jackrabbitConfig.xml");
+ FileUtil.delete("target/repositoryData");
+ }
+
+ @After
+ public void afterEach() throws Exception {
+ client.shutdownDnaServices();
+ client.shutdownRepository();
+ FileUtil.delete("target/repositoryData");
+ }
+
+ @Test
+ public void shouldStartupAndShutdownRepository() throws Exception {
+ client.startRepository();
+ client.shutdownRepository();
+
+ }
+
+ @Test
+ public void shouldStartupAndShutdownRepositoryAndSequencingService() throws Exception {
+ client.startRepository();
+ client.startDnaServices();
+ client.shutdownDnaServices();
+ client.shutdownRepository();
+ }
+
+ @Test
+ public void shouldUploadFile() throws Exception {
+ client.startRepository();
+ client.startDnaServices();
+ client.uploadFile(file.openStream(), "/a/b/caution.png", "image/png");
+
+ // Let the sequencing start ...
+ Thread.sleep(1000);
+ client.shutdownDnaServices(); // this will block untill all processing has been done ...
+
+ List<ImageInfo> images = client.getImages();
+ assertThat(images.size(), is(1));
+ for (ImageInfo image : images) {
+ System.out.println("Image: " + image);
+ }
+ }
+
+}
Added: trunk/docs/getting_started/.project
===================================================================
--- trunk/docs/getting_started/.project (rev 0)
+++ trunk/docs/getting_started/.project 2008-05-06 14:57:52 UTC (rev 115)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>docs-getting-started</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ </buildSpec>
+ <natures>
+ </natures>
+</projectDescription>
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2008-04-30 19:30:18 UTC (rev 114)
+++ trunk/pom.xml 2008-05-06 14:57:52 UTC (rev 115)
@@ -33,6 +33,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
16 years