Author: rhauch
Date: 2009-04-23 14:09:01 -0400 (Thu, 23 Apr 2009)
New Revision: 850
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/DnaConfiguration.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/DnaEngine.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/DnaConfigurationTest.java
Log:
DNA-58 Create repository configuration and component
Changed DnaConfiguration to make it more tolernant of changes to the source pointing to
the configuration repository. In particular, this allows the DnaEngine to obtain an
immutable definition of the configuration source, which allows the engine to properly
access the source even if the DnaConfiguration instance is changed.
The DnaEngine was also refactored to pull into a nested scanner class the code that reads
the configuration content.
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/DnaConfiguration.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/DnaConfiguration.java 2009-04-23
16:43:27 UTC (rev 849)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/DnaConfiguration.java 2009-04-23
18:09:01 UTC (rev 850)
@@ -41,6 +41,7 @@
import org.jboss.dna.graph.property.PathExpression;
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.property.basic.RootPath;
import org.jboss.dna.repository.sequencer.Sequencer;
/**
@@ -61,14 +62,56 @@
NAMES_TO_MAP = Collections.unmodifiableMap(names);
}
- protected class Source {
- protected RepositorySource source;
- protected String description;
- protected Path path;
+ @Immutable
+ protected class ConfigurationRepository {
+ private final RepositorySource source;
+ private final String description;
+ private final Path path;
+
+ protected ConfigurationRepository( RepositorySource source ) {
+ this(source, null, null);
+ }
+
+ protected ConfigurationRepository( RepositorySource source,
+ String description,
+ Path path ) {
+ this.source = source;
+ this.description = description != null ? description : "";
+ this.path = path != null ? path : RootPath.INSTANCE;
+ }
+
+ /**
+ * @return source
+ */
+ public RepositorySource getRepositorySource() {
+ return source;
+ }
+
+ /**
+ * @return description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @return path
+ */
+ public Path getPath() {
+ return path;
+ }
+
+ public ConfigurationRepository with( String description ) {
+ return new ConfigurationRepository(source, description, path);
+ }
+
+ public ConfigurationRepository with( Path path ) {
+ return new ConfigurationRepository(source, description, path);
+ }
}
private final ExecutionContext context;
- protected Source configurationSource;
+ protected ConfigurationRepository configurationSource;
private Path sourcesPath;
private Path sequencersPath;
private Path detectorsPath;
@@ -102,13 +145,10 @@
*
* @return the default repository source
*/
- protected Source createDefaultConfigurationSource() {
+ protected ConfigurationRepository createDefaultConfigurationSource() {
InMemoryRepositorySource defaultSource = new InMemoryRepositorySource();
defaultSource.setName("Configuration");
- Source result = new Source();
- result.source = defaultSource;
- result.path =
this.context.getValueFactories().getPathFactory().createRootPath();
- result.description = "Configuration Repository";
+ ConfigurationRepository result = new ConfigurationRepository(defaultSource,
"Configuration Repository", null);
return result;
}
@@ -129,7 +169,7 @@
*/
protected final Graph graph() {
if (this.graph == null) {
- this.graph = Graph.create(configurationSource.source, context);
+ this.graph = Graph.create(configurationSource.getRepositorySource(),
context);
}
return this.graph;
}
@@ -170,7 +210,6 @@
* be used for the configuration repository; never null
*/
public ChooseClass<RepositorySource, ConfigRepositoryDetails>
withConfigurationRepository() {
- final Source source = this.configurationSource;
// The config repository is different, since it has to load immediately ...
return new ChooseClass<RepositorySource, ConfigRepositoryDetails>() {
public LoadedFrom<ConfigRepositoryDetails> usingClass( final String
className ) {
@@ -203,7 +242,7 @@
public ConfigRepositoryDetails usingClass( Class<? extends
RepositorySource> repositorySource ) {
try {
- source.source = repositorySource.newInstance();
+ DnaConfiguration.this.configurationSource = new
ConfigurationRepository(repositorySource.newInstance());
} catch (InstantiationException err) {
I18n msg = RepositoryI18n.errorCreatingInstanceOfClass;
throw new
DnaConfigurationException(msg.text(repositorySource.getName(), err.getLocalizedMessage()),
err);
@@ -318,7 +357,7 @@
protected Path sourcesPath() {
// Make sure the "dna:sources" node is there
if (sourcesPath == null) {
- Path path = pathFactory().create(this.configurationSource.path,
DnaLexicon.SOURCES);
+ Path path = pathFactory().create(this.configurationSource.getPath(),
DnaLexicon.SOURCES);
Node node = graph().createIfMissing(path).andReturn();
this.sourcesPath = node.getLocation().getPath();
}
@@ -328,7 +367,7 @@
protected Path sequencersPath() {
// Make sure the "dna:sequencers" node is there
if (sequencersPath == null) {
- Path path = pathFactory().create(this.configurationSource.path,
DnaLexicon.SEQUENCERS);
+ Path path = pathFactory().create(this.configurationSource.getPath(),
DnaLexicon.SEQUENCERS);
Node node = graph().createIfMissing(path).andReturn();
this.sequencersPath = node.getLocation().getPath();
}
@@ -338,7 +377,7 @@
protected Path detectorsPath() {
// Make sure the "dna:mimeTypeDetectors" node is there
if (detectorsPath == null) {
- Path path = pathFactory().create(this.configurationSource.path,
DnaLexicon.MIME_TYPE_DETECTORS);
+ Path path = pathFactory().create(this.configurationSource.getPath(),
DnaLexicon.MIME_TYPE_DETECTORS);
Node node = graph().createIfMissing(path).andReturn();
this.detectorsPath = node.getLocation().getPath();
}
@@ -612,7 +651,7 @@
* @see
org.jboss.dna.repository.DnaConfiguration.SetDescription#describedAs(java.lang.String)
*/
public ConfigRepositoryDetails describedAs( String description ) {
- DnaConfiguration.this.configurationSource.description = description;
+ DnaConfiguration.this.configurationSource =
DnaConfiguration.this.configurationSource.with(description);
return this;
}
@@ -622,7 +661,8 @@
* @see
org.jboss.dna.repository.DnaConfiguration.SetProperties#with(java.lang.String)
*/
public PropertySetter<ConfigRepositoryDetails> with( String propertyName )
{
- return new
BeanPropertySetter<ConfigRepositoryDetails>(DnaConfiguration.this.configurationSource.source,
+ return new BeanPropertySetter<ConfigRepositoryDetails>(
+
DnaConfiguration.this.configurationSource.getRepositorySource(),
propertyName, this);
}
@@ -633,7 +673,8 @@
*/
public ConfigRepositoryDetails under( String path ) {
CheckArg.isNotNull(path, "path");
- DnaConfiguration.this.configurationSource.path =
context().getValueFactories().getPathFactory().create(path);
+ Path newPath = context().getValueFactories().getPathFactory().create(path);
+ DnaConfiguration.this.configurationSource =
DnaConfiguration.this.configurationSource.with(newPath);
return null;
}
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/DnaEngine.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/DnaEngine.java 2009-04-23
16:43:27 UTC (rev 849)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/DnaEngine.java 2009-04-23
18:09:01 UTC (rev 850)
@@ -61,13 +61,17 @@
import org.jboss.dna.repository.util.SimpleSessionFactory;
/**
- * @author Randall Hauch
+ * A single instance of the DNA services, which is obtained after setting up the {@link
DnaConfiguration#build() configuration}.
+ *
+ * @see DnaConfiguration
*/
@Immutable
public class DnaEngine {
public static final String CONFIGURATION_REPOSITORY_NAME =
"dna:configuration";
+ private final DnaConfiguration.ConfigurationRepository configuration;
+ private final ConfigurationScanner scanner;
private final Problems problems;
private final ExecutionContext context;
private final List<AdministeredService> services;
@@ -85,17 +89,20 @@
// Use the configuration's context ...
this.context = configuration.context();
+ // And set up the scanner ...
+ this.configuration = configuration.configurationSource;
+ this.scanner = new ConfigurationScanner(this.problems, this.context,
this.configuration);
+
// Add the configuration source to the repository library ...
- final DnaConfiguration.Source configSourceInfo =
configuration.configurationSource;
- final RepositorySource configSource = configSourceInfo.source;
+ final RepositorySource configSource = this.configuration.getRepositorySource();
RepositoryLibrary library = new RepositoryLibrary();
library.addSource(configSource);
// Create the RepositoryService, pointing it to the configuration repository ...
- Path pathToConfigurationRoot = configSourceInfo.path;
+ Path pathToConfigurationRoot = this.configuration.getPath();
repositoryService = new RepositoryService(library, configSource.getName(),
"", pathToConfigurationRoot, context);
- for (MimeTypeDetectorConfig config : loadMimeTypeDetectors(problems, context,
configSourceInfo)) {
+ for (MimeTypeDetectorConfig config : scanner.getMimeTypeDetectors()) {
library.getMimeTypeDetectors().addDetector(config);
}
@@ -106,7 +113,7 @@
JcrExecutionContext jcrContext = new JcrExecutionContext(context, sessionFactory,
"");
sequencingService.setExecutionContext(jcrContext);
sequencingService.setExecutorService(executorService);
- for (SequencerConfig sequencerConfig : loadSequencingConfigurations(problems,
context, configSourceInfo)) {
+ for (SequencerConfig sequencerConfig : scanner.getSequencingConfigurations()) {
sequencingService.addSequencer(sequencerConfig);
}
@@ -127,136 +134,6 @@
};
}
- protected static List<MimeTypeDetectorConfig> loadMimeTypeDetectors( Problems
problems,
- ExecutionContext
context,
-
DnaConfiguration.Source source ) {
- List<MimeTypeDetectorConfig> detectors = new
ArrayList<MimeTypeDetectorConfig>();
- Graph graph = Graph.create(source.source, context);
- Path pathToSequencersNode =
context.getValueFactories().getPathFactory().create(source.path,
-
DnaLexicon.MIME_TYPE_DETECTORS);
- try {
- Subgraph subgraph = graph.getSubgraphOfDepth(2).at(pathToSequencersNode);
-
- Set<Name> skipProperties = new HashSet<Name>();
- skipProperties.add(DnaLexicon.READABLE_NAME);
- skipProperties.add(DnaLexicon.DESCRIPTION);
- skipProperties.add(DnaLexicon.CLASSNAME);
- skipProperties.add(DnaLexicon.CLASSPATH);
- skipProperties.add(DnaLexicon.PATH_EXPRESSIONS);
- Set<String> skipNamespaces = new HashSet<String>();
- skipNamespaces.add(JcrLexicon.Namespace.URI);
- skipNamespaces.add(JcrNtLexicon.Namespace.URI);
- skipNamespaces.add(JcrMixLexicon.Namespace.URI);
-
- for (Location sequencerLocation : subgraph.getRoot().getChildren()) {
- Node sequencerNode = subgraph.getNode(sequencerLocation);
- String name = stringValueOf(context, sequencerNode,
DnaLexicon.READABLE_NAME);
- String desc = stringValueOf(context, sequencerNode,
DnaLexicon.DESCRIPTION);
- String classname = stringValueOf(context, sequencerNode,
DnaLexicon.CLASSNAME);
- String[] classpath = stringValuesOf(context, sequencerNode,
DnaLexicon.CLASSPATH);
- Map<String, Object> properties = new HashMap<String,
Object>();
- for (Property property : sequencerNode.getProperties()) {
- Name propertyName = property.getName();
- if (skipNamespaces.contains(propertyName.getNamespaceUri()))
continue;
- if (skipProperties.contains(propertyName)) continue;
- if (property.isSingle()) {
- properties.put(propertyName.getLocalName(),
property.getFirstValue());
- } else {
- properties.put(propertyName.getLocalName(),
property.getValuesAsArray());
- }
- }
- MimeTypeDetectorConfig config = new MimeTypeDetectorConfig(name, desc,
properties, classname, classpath);
- detectors.add(config);
- }
- } catch (PathNotFoundException e) {
- // no detectors registered ...
- }
- return detectors;
- }
-
- protected static List<SequencerConfig> loadSequencingConfigurations( Problems
problems,
- ExecutionContext
context,
-
DnaConfiguration.Source source ) {
- List<SequencerConfig> configs = new ArrayList<SequencerConfig>();
- Graph graph = Graph.create(source.source, context);
- Path pathToSequencersNode =
context.getValueFactories().getPathFactory().create(source.path, DnaLexicon.SEQUENCERS);
- try {
- Subgraph subgraph = graph.getSubgraphOfDepth(2).at(pathToSequencersNode);
-
- Set<Name> skipProperties = new HashSet<Name>();
- skipProperties.add(DnaLexicon.READABLE_NAME);
- skipProperties.add(DnaLexicon.DESCRIPTION);
- skipProperties.add(DnaLexicon.CLASSNAME);
- skipProperties.add(DnaLexicon.CLASSPATH);
- skipProperties.add(DnaLexicon.PATH_EXPRESSIONS);
- Set<String> skipNamespaces = new HashSet<String>();
- skipNamespaces.add(JcrLexicon.Namespace.URI);
- skipNamespaces.add(JcrNtLexicon.Namespace.URI);
- skipNamespaces.add(JcrMixLexicon.Namespace.URI);
-
- for (Location sequencerLocation : subgraph.getRoot().getChildren()) {
- Node sequencerNode = subgraph.getNode(sequencerLocation);
- String name = stringValueOf(context, sequencerNode,
DnaLexicon.READABLE_NAME);
- String desc = stringValueOf(context, sequencerNode,
DnaLexicon.DESCRIPTION);
- String classname = stringValueOf(context, sequencerNode,
DnaLexicon.CLASSNAME);
- String[] classpath = stringValuesOf(context, sequencerNode,
DnaLexicon.CLASSPATH);
- String[] expressionStrings = stringValuesOf(context, sequencerNode,
DnaLexicon.PATH_EXPRESSIONS);
- List<PathExpression> pathExpressions = new
ArrayList<PathExpression>();
- if (expressionStrings != null) {
- for (String expressionString : expressionStrings) {
- try {
-
pathExpressions.add(PathExpression.compile(expressionString));
- } catch (Throwable t) {
- problems.addError(t,
-
RepositoryI18n.pathExpressionIsInvalidOnSequencer,
- expressionString,
- name,
- t.getLocalizedMessage());
- }
- }
- }
- String[] goodExpressionStrings = new String[pathExpressions.size()];
- for (int i = 0; i != pathExpressions.size(); ++i) {
- PathExpression expression = pathExpressions.get(i);
- goodExpressionStrings[i] = expression.getExpression();
- }
- Map<String, Object> properties = new HashMap<String,
Object>();
- for (Property property : sequencerNode.getProperties()) {
- Name propertyName = property.getName();
- if (skipNamespaces.contains(propertyName.getNamespaceUri()))
continue;
- if (skipProperties.contains(propertyName)) continue;
- if (property.isSingle()) {
- properties.put(propertyName.getLocalName(),
property.getFirstValue());
- } else {
- properties.put(propertyName.getLocalName(),
property.getValuesAsArray());
- }
- }
- SequencerConfig config = new SequencerConfig(name, desc, properties,
classname, classpath, goodExpressionStrings);
- configs.add(config);
- }
- } catch (PathNotFoundException e) {
- // no detectors registered ...
- }
- return configs;
- }
-
- private static String stringValueOf( ExecutionContext context,
- Node node,
- Name propertyName ) {
- Property property = node.getProperty(propertyName);
- if (property == null) return null;
- if (property.isEmpty()) return null;
- return
context.getValueFactories().getStringFactory().create(property.getFirstValue());
- }
-
- private static String[] stringValuesOf( ExecutionContext context,
- Node node,
- Name propertyName ) {
- Property property = node.getProperty(propertyName);
- if (property == null) return null;
- return
context.getValueFactories().getStringFactory().create(property.getValuesAsArray());
- }
-
/**
* Get the problems that were encountered when setting up this engine from the
configuration.
*
@@ -316,4 +193,149 @@
}
executorService.shutdown();
}
+
+ /**
+ * The component responsible for reading the configuration repository and
(eventually) for propagating changes in the
+ * configuration repository into the services.
+ */
+ protected class ConfigurationScanner {
+ private final Problems problems;
+ private final ExecutionContext context;
+ private final DnaConfiguration.ConfigurationRepository configurationRepository;
+
+ protected ConfigurationScanner( Problems problems,
+ ExecutionContext context,
+ DnaConfiguration.ConfigurationRepository
configurationRepository ) {
+ this.problems = problems;
+ this.context = context;
+ this.configurationRepository = configurationRepository;
+ }
+
+ public List<MimeTypeDetectorConfig> getMimeTypeDetectors() {
+ List<MimeTypeDetectorConfig> detectors = new
ArrayList<MimeTypeDetectorConfig>();
+ Graph graph = Graph.create(configurationRepository.getRepositorySource(),
context);
+ Path pathToSequencersNode =
context.getValueFactories().getPathFactory().create(configurationRepository.getPath(),
+
DnaLexicon.MIME_TYPE_DETECTORS);
+ try {
+ Subgraph subgraph =
graph.getSubgraphOfDepth(2).at(pathToSequencersNode);
+
+ Set<Name> skipProperties = new HashSet<Name>();
+ skipProperties.add(DnaLexicon.READABLE_NAME);
+ skipProperties.add(DnaLexicon.DESCRIPTION);
+ skipProperties.add(DnaLexicon.CLASSNAME);
+ skipProperties.add(DnaLexicon.CLASSPATH);
+ skipProperties.add(DnaLexicon.PATH_EXPRESSIONS);
+ Set<String> skipNamespaces = new HashSet<String>();
+ skipNamespaces.add(JcrLexicon.Namespace.URI);
+ skipNamespaces.add(JcrNtLexicon.Namespace.URI);
+ skipNamespaces.add(JcrMixLexicon.Namespace.URI);
+
+ for (Location detectorLocation : subgraph.getRoot().getChildren()) {
+ Node node = subgraph.getNode(detectorLocation);
+ String name = stringValueOf(node, DnaLexicon.READABLE_NAME);
+ String desc = stringValueOf(node, DnaLexicon.DESCRIPTION);
+ String classname = stringValueOf(node, DnaLexicon.CLASSNAME);
+ String[] classpath = stringValuesOf(node, DnaLexicon.CLASSPATH);
+ Map<String, Object> properties = new HashMap<String,
Object>();
+ for (Property property : node.getProperties()) {
+ Name propertyName = property.getName();
+ if (skipNamespaces.contains(propertyName.getNamespaceUri()))
continue;
+ if (skipProperties.contains(propertyName)) continue;
+ if (property.isSingle()) {
+ properties.put(propertyName.getLocalName(),
property.getFirstValue());
+ } else {
+ properties.put(propertyName.getLocalName(),
property.getValuesAsArray());
+ }
+ }
+ MimeTypeDetectorConfig config = new MimeTypeDetectorConfig(name,
desc, properties, classname, classpath);
+ detectors.add(config);
+ }
+ } catch (PathNotFoundException e) {
+ // no detectors registered ...
+ }
+ return detectors;
+ }
+
+ public List<SequencerConfig> getSequencingConfigurations() {
+ List<SequencerConfig> configs = new
ArrayList<SequencerConfig>();
+ Graph graph = Graph.create(configurationRepository.getRepositorySource(),
context);
+ Path pathToSequencersNode =
context.getValueFactories().getPathFactory().create(configurationRepository.getPath(),
+
DnaLexicon.SEQUENCERS);
+ try {
+ Subgraph subgraph =
graph.getSubgraphOfDepth(2).at(pathToSequencersNode);
+
+ Set<Name> skipProperties = new HashSet<Name>();
+ skipProperties.add(DnaLexicon.READABLE_NAME);
+ skipProperties.add(DnaLexicon.DESCRIPTION);
+ skipProperties.add(DnaLexicon.CLASSNAME);
+ skipProperties.add(DnaLexicon.CLASSPATH);
+ skipProperties.add(DnaLexicon.PATH_EXPRESSIONS);
+ Set<String> skipNamespaces = new HashSet<String>();
+ skipNamespaces.add(JcrLexicon.Namespace.URI);
+ skipNamespaces.add(JcrNtLexicon.Namespace.URI);
+ skipNamespaces.add(JcrMixLexicon.Namespace.URI);
+
+ for (Location sequencerLocation : subgraph.getRoot().getChildren()) {
+ Node sequencerNode = subgraph.getNode(sequencerLocation);
+ String name = stringValueOf(sequencerNode,
DnaLexicon.READABLE_NAME);
+ String desc = stringValueOf(sequencerNode, DnaLexicon.DESCRIPTION);
+ String classname = stringValueOf(sequencerNode,
DnaLexicon.CLASSNAME);
+ String[] classpath = stringValuesOf(sequencerNode,
DnaLexicon.CLASSPATH);
+ String[] expressionStrings = stringValuesOf(sequencerNode,
DnaLexicon.PATH_EXPRESSIONS);
+ List<PathExpression> pathExpressions = new
ArrayList<PathExpression>();
+ if (expressionStrings != null) {
+ for (String expressionString : expressionStrings) {
+ try {
+
pathExpressions.add(PathExpression.compile(expressionString));
+ } catch (Throwable t) {
+ problems.addError(t,
+
RepositoryI18n.pathExpressionIsInvalidOnSequencer,
+ expressionString,
+ name,
+ t.getLocalizedMessage());
+ }
+ }
+ }
+ String[] goodExpressionStrings = new String[pathExpressions.size()];
+ for (int i = 0; i != pathExpressions.size(); ++i) {
+ PathExpression expression = pathExpressions.get(i);
+ goodExpressionStrings[i] = expression.getExpression();
+ }
+ Map<String, Object> properties = new HashMap<String,
Object>();
+ for (Property property : sequencerNode.getProperties()) {
+ Name propertyName = property.getName();
+ if (skipNamespaces.contains(propertyName.getNamespaceUri()))
continue;
+ if (skipProperties.contains(propertyName)) continue;
+ if (property.isSingle()) {
+ properties.put(propertyName.getLocalName(),
property.getFirstValue());
+ } else {
+ properties.put(propertyName.getLocalName(),
property.getValuesAsArray());
+ }
+ }
+ SequencerConfig config = new SequencerConfig(name, desc, properties,
classname, classpath,
+ goodExpressionStrings);
+ configs.add(config);
+ }
+ } catch (PathNotFoundException e) {
+ // no detectors registered ...
+ }
+ return configs;
+ }
+
+ private String stringValueOf( Node node,
+ Name propertyName ) {
+ Property property = node.getProperty(propertyName);
+ if (property == null) return null;
+ if (property.isEmpty()) return null;
+ return
context.getValueFactories().getStringFactory().create(property.getFirstValue());
+ }
+
+ private String[] stringValuesOf( Node node,
+ Name propertyName ) {
+ Property property = node.getProperty(propertyName);
+ if (property == null) return null;
+ return
context.getValueFactories().getStringFactory().create(property.getValuesAsArray());
+ }
+
+ }
}
Modified:
trunk/dna-repository/src/test/java/org/jboss/dna/repository/DnaConfigurationTest.java
===================================================================
---
trunk/dna-repository/src/test/java/org/jboss/dna/repository/DnaConfigurationTest.java 2009-04-23
16:43:27 UTC (rev 849)
+++
trunk/dna-repository/src/test/java/org/jboss/dna/repository/DnaConfigurationTest.java 2009-04-23
18:09:01 UTC (rev 850)
@@ -85,8 +85,8 @@
.and()
.save();
assertThat(config, is(notNullValue()));
- assertThat(config.configurationSource.source,
is(instanceOf(InMemoryRepositorySource.class)));
- InMemoryRepositorySource source =
(InMemoryRepositorySource)config.configurationSource.source;
+ assertThat(config.configurationSource.getRepositorySource(),
is(instanceOf(InMemoryRepositorySource.class)));
+ InMemoryRepositorySource source =
(InMemoryRepositorySource)config.configurationSource.getRepositorySource();
assertThat(source.getName(), is("repository name"));
assertThat(source.getRetryLimit(), is(5));
}