diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/store/DefaultPropertyStore.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/store/DefaultPropertyStore.java new file mode 100644 index 000000000..b512c9f72 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/store/DefaultPropertyStore.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon.components.store; + +import java.io.File; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import org.apache.avalon.excalibur.i18n.ResourceManager; +import org.apache.avalon.excalibur.i18n.Resources; +import org.apache.myrmidon.api.TaskContext; +import org.apache.myrmidon.api.TaskException; +import org.apache.myrmidon.interfaces.model.DefaultNameValidator; +import org.apache.myrmidon.interfaces.model.NameValidator; +import org.apache.myrmidon.interfaces.store.PropertyStore; + +/** + * This is the Default implementation of PropertyStore. It follows + * the following rules; + * + *
true
if the specified property is set.
+ *
+ * @param name the name of property
+ */
+ public boolean isPropertySet( final String name )
+ {
+ try
+ {
+ final Object value = getProperty( name );
+ if( null != value )
+ {
+ return true;
+ }
+ }
+ catch( Exception e )
+ {
+ }
+ return false;
+ }
+
+ /**
+ * Retrieve the value of specified property.
+ * Will return null if no such property exists.
+ *
+ * @param name the name of the property
+ * @return the value of the property, or null if no such property
+ * @throws Exception if theres an error retrieving property, such
+ * as an invalid property name
+ */
+ public Object getProperty( String name )
+ throws Exception
+ {
+ Object value = m_contextData.get( name );
+ if( value == null && m_parent != null )
+ {
+ value = m_parent.getProperty( name );
+ }
+ return value;
+ }
+
+ /**
+ * Retrieve a copy of all the properties that are "in-scope"
+ * for store.
+ *
+ * @return a copy of all the properties that are "in-scope"
+ * for store.
+ * @throws Exception if theres an error retrieving propertys
+ */
+ public Map getProperties()
+ throws Exception
+ {
+ final Map properties = new HashMap();
+ if( m_parent != null )
+ {
+ properties.putAll( m_parent.getProperties() );
+ }
+ properties.putAll( m_contextData );
+ return properties;
+ }
+
+ /**
+ * Return a child PropertyStore with specified name.
+ * This is to allow support for scoped stores. However a
+ * store may choose to be unscoped and just return a
+ * reference to itself.
+ *
+ * @param name the name of child store
+ * @return the child store
+ * @throws Exception if theres an error creating child store
+ */
+ public PropertyStore createChildStore( final String name )
+ throws Exception
+ {
+ final DefaultPropertyStore store = new DefaultPropertyStore( this, m_validator );
+
+ final String newName = getProperty( TaskContext.NAME ) + "." + name;
+ store.setProperty( TaskContext.NAME, newName );
+
+ return store;
+ }
+
+ /**
+ * Checks that the supplied property name is valid.
+ */
+ private void checkPropertyName( final String name )
+ throws TaskException
+ {
+ try
+ {
+ m_validator.validate( name );
+ }
+ catch( Exception e )
+ {
+ String message = REZ.getString( "bad-property-name.error" );
+ throw new TaskException( message, e );
+ }
+ }
+
+ /**
+ * Make sure property is valid if it is one of the "magic" properties.
+ *
+ * @param name the name of property
+ * @param value the value of proeprty
+ * @exception TaskException if an error occurs
+ */
+ private void checkPropertyValid( final String name, final Object value )
+ throws TaskException
+ {
+ if( TaskContext.BASE_DIRECTORY.equals( name ) && !( value instanceof File ) )
+ {
+ final String message =
+ REZ.getString( "bad-property.error",
+ TaskContext.BASE_DIRECTORY,
+ File.class.getName() );
+ throw new TaskException( message );
+ }
+ else if( TaskContext.NAME.equals( name ) && !( value instanceof String ) )
+ {
+ final String message =
+ REZ.getString( "bad-property.error",
+ TaskContext.NAME,
+ String.class.getName() );
+ throw new TaskException( message );
+ }
+ }
+
+ /**
+ * Create an instance of the default the name validator.
+ *
+ * @return the default NameValidator
+ */
+ private static NameValidator createDefaultNameValidator()
+ {
+ final DefaultNameValidator defaultValidator = new DefaultNameValidator();
+ defaultValidator.setAllowInternalWhitespace( false );
+ defaultValidator.setAdditionalInternalCharacters( "_-.+" );
+ return defaultValidator;
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/store/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/components/store/Resources.properties
new file mode 100644
index 000000000..835067974
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/store/Resources.properties
@@ -0,0 +1,5 @@
+unknown-prop.error=Unknown property {0}.
+bad-property.error=Property {0} must have a value of type {1}.
+bad-property-name.error=Invalid property name.
+null-resolved-value.error=Value "{0}" resolved to null.
+bad-resolve.error=Unable to resolve value "{0}".
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
index a71e1f497..83498b3a1 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
@@ -8,19 +8,18 @@
package org.apache.myrmidon.components.workspace;
import java.io.File;
-import java.util.Hashtable;
import java.util.Map;
-import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.excalibur.io.FileUtil;
import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
-import org.apache.myrmidon.interfaces.model.DefaultNameValidator;
import org.apache.myrmidon.interfaces.property.PropertyResolver;
+import org.apache.myrmidon.interfaces.store.PropertyStore;
/**
* Default implementation of TaskContext.
@@ -34,33 +33,35 @@ public class DefaultTaskContext
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultTaskContext.class );
- // Property name validator allows digits, but no internal whitespace.
- private static DefaultNameValidator c_propertyNameValidator =
- new DefaultNameValidator();
-
- static
- {
- c_propertyNameValidator.setAllowInternalWhitespace( false );
- c_propertyNameValidator.setAdditionalInternalCharacters( "_-.+" );
- }
-
- private final Map m_contextData = new Hashtable();
- private final TaskContext m_parent;
private final ServiceManager m_serviceManager;
private final Logger m_logger;
+ private final PropertyStore m_store;
private PropertyResolver m_propertyResolver;
/**
* Constructor that takes both parent context and a service directory.
*/
- public DefaultTaskContext( final TaskContext parent,
- final ServiceManager serviceManager,
- final Logger logger )
+ public DefaultTaskContext( final ServiceManager serviceManager,
+ final Logger logger,
+ final PropertyStore store )
throws TaskException
{
- m_parent = parent;
m_serviceManager = serviceManager;
m_logger = logger;
+ m_store = store;
+
+ if( null == m_serviceManager )
+ {
+ throw new NullPointerException( "serviceManager" );
+ }
+ if( null == m_logger )
+ {
+ throw new NullPointerException( "logger" );
+ }
+ if( null == m_store )
+ {
+ throw new NullPointerException( "store" );
+ }
}
/**
@@ -96,8 +97,8 @@ public class DefaultTaskContext
public Object getService( final Class serviceClass )
throws TaskException
{
- // Try this context first
final String name = serviceClass.getName();
+ //Note that this will chain up to parent ServiceManagers (if any)
if( null != m_serviceManager && m_serviceManager.hasService( name ) )
{
try
@@ -110,12 +111,6 @@ public class DefaultTaskContext
}
}
- // Try parent
- if( null != m_parent )
- {
- return m_parent.getService( serviceClass );
- }
-
// Not found
final String message = REZ.getString( "bad-find-service.error", name );
throw new TaskException( message );
@@ -179,12 +174,14 @@ public class DefaultTaskContext
*/
public Object getProperty( final String name )
{
- Object value = m_contextData.get( name );
- if( value == null && m_parent != null )
+ try
+ {
+ return m_store.getProperty( name );
+ }
+ catch( final Exception e )
{
- value = m_parent.getProperty( name );
+ return null;
}
- return value;
}
/**
@@ -193,14 +190,16 @@ public class DefaultTaskContext
* @return the map of all property names to values
*/
public Map getProperties()
+ throws TaskException
{
- Map props = new HashMap();
- if( m_parent != null )
+ try
+ {
+ return m_store.getProperties();
+ }
+ catch( final Exception e )
{
- props.putAll( m_parent.getProperties() );
+ throw new TaskException( e.getMessage(), e );
}
- props.putAll( m_contextData );
- return props;
}
/**
@@ -212,16 +211,13 @@ public class DefaultTaskContext
public void setProperty( final String name, final Object value )
throws TaskException
{
- checkPropertyName( name );
- checkPropertyValid( name, value );
-
- if ( value == null )
+ try
{
- m_contextData.remove( name );
+ m_store.setProperty( name, value );
}
- else
+ catch( final Exception e )
{
- m_contextData.put( name, value );
+ throw new TaskException( e.getMessage(), e );
}
}
@@ -390,53 +386,19 @@ public class DefaultTaskContext
*/
public TaskContext createSubContext( final String name )
throws TaskException
- {
- final DefaultTaskContext context =
- new DefaultTaskContext( this, m_serviceManager, m_logger );
-
- context.setProperty( TaskContext.NAME, getName() + "." + name );
- context.setProperty( TaskContext.BASE_DIRECTORY, getBaseDirectory() );
-
- return context;
- }
-
- /**
- * Checks that the supplied property name is valid.
- */
- private void checkPropertyName( final String name ) throws TaskException
{
try
{
- c_propertyNameValidator.validate( name );
- }
- catch( Exception e )
- {
- String message = REZ.getString( "bad-property-name.error" );
- throw new TaskException( message, e );
- }
- }
+ final PropertyStore store = m_store.createChildStore( name );
+ final DefaultServiceManager serviceManager =
+ new DefaultServiceManager( m_serviceManager );
+ final Logger logger = m_logger.getChildLogger( name );
- /**
- * Make sure property is valid if it is one of the "magic" properties.
- *
- * @param name the name of property
- * @param value the value of proeprty
- * @exception TaskException if an error occurs
- */
- private void checkPropertyValid( final String name, final Object value )
- throws TaskException
- {
- if( BASE_DIRECTORY.equals( name ) && !( value instanceof File ) )
- {
- final String message =
- REZ.getString( "bad-property.error", BASE_DIRECTORY, File.class.getName() );
- throw new TaskException( message );
+ return new DefaultTaskContext( serviceManager, logger, store );
}
- else if( NAME.equals( name ) && !( value instanceof String ) )
+ catch( final Exception e )
{
- final String message =
- REZ.getString( "bad-property.error", NAME, String.class.getName() );
- throw new TaskException( message );
+ throw new TaskException( e.getMessage(), e );
}
}
}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java
index 1c4ae8e22..e71d84c4d 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java
@@ -37,7 +37,9 @@ import org.apache.myrmidon.interfaces.model.Target;
import org.apache.myrmidon.interfaces.model.TypeLib;
import org.apache.myrmidon.interfaces.type.TypeManager;
import org.apache.myrmidon.interfaces.workspace.Workspace;
+import org.apache.myrmidon.interfaces.store.PropertyStore;
import org.apache.myrmidon.listeners.ProjectListener;
+import org.apache.myrmidon.components.store.DefaultPropertyStore;
/**
* This is the default implementation of Workspace.
@@ -56,7 +58,7 @@ public class DefaultWorkspace
private ProjectListenerSupport m_listenerSupport = new ProjectListenerSupport();
private ServiceManager m_serviceManager;
private Parameters m_parameters;
- private TaskContext m_baseContext;
+ private PropertyStore m_baseStore;
private HashMap m_entries = new HashMap();
private TypeManager m_typeManager;
private Deployer m_deployer;
@@ -105,7 +107,7 @@ public class DefaultWorkspace
public void initialize()
throws Exception
{
- m_baseContext = createBaseContext();
+ m_baseStore = createBaseStore();
}
/**
@@ -128,22 +130,22 @@ public class DefaultWorkspace
m_listenerSupport.projectFinished( project.getProjectName() );
}
- private TaskContext createBaseContext()
- throws TaskException
+ private PropertyStore createBaseStore()
+ throws Exception
{
- final TaskContext context = new DefaultTaskContext( null, null, null );
+ final DefaultPropertyStore store = new DefaultPropertyStore();
final String[] names = m_parameters.getNames();
for( int i = 0; i < names.length; i++ )
{
final String value = m_parameters.getParameter( names[ i ], null );
- context.setProperty( names[ i ], value );
+ store.setProperty( names[ i ], value );
}
//Add system properties so that they overide user-defined properties
- addToContext( context, System.getProperties() );
+ addToStore( store, System.getProperties() );
- return context;
+ return store;
}
private File findTypeLib( final String libraryName )
@@ -250,9 +252,12 @@ public class DefaultWorkspace
final Logger logger =
new RoutingLogger( getLogger(), m_listenerSupport );
- // Create and configure the context
+ //TODO: Put this in Execution Frame
+ final PropertyStore store = m_baseStore.createChildStore("");
+
+ // Create and configure the context
final DefaultTaskContext context =
- new DefaultTaskContext( m_baseContext, serviceManager, logger );
+ new DefaultTaskContext( serviceManager, logger, store );
context.setProperty( TaskContext.BASE_DIRECTORY, project.getBaseDirectory() );
final DefaultExecutionFrame frame =
@@ -467,13 +472,13 @@ public class DefaultWorkspace
}
/**
- * Helper method to add values to a context
+ * Helper method to add values to a store.
*
- * @param context the context
+ * @param store the store
* @param map the map of names->values
*/
- private void addToContext( final TaskContext context, final Map map )
- throws TaskException
+ private void addToStore( final PropertyStore store, final Map map )
+ throws Exception
{
final Iterator keys = map.keySet().iterator();
@@ -481,7 +486,7 @@ public class DefaultWorkspace
{
final String key = (String)keys.next();
final Object value = map.get( key );
- context.setProperty( key, value );
+ store.setProperty( key, value );
}
}
}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/NameValidator.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/NameValidator.java
index d754a50e4..ecf0209fb 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/NameValidator.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/NameValidator.java
@@ -17,8 +17,10 @@ public interface NameValidator
{
/**
* Validates the supplied name, failing if it is not.
+ *
* @param name The name to be validated.
* @throws Exception is the supplied name is not valid.
*/
- void validate( String name ) throws Exception;
+ void validate( String name )
+ throws Exception;
}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/store/PropertyStore.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/store/PropertyStore.java
new file mode 100644
index 000000000..1a66864d5
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/store/PropertyStore.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE.txt file.
+ */
+package org.apache.myrmidon.interfaces.store;
+
+import java.util.Map;
+
+/**
+ * This component stores and manages properties. It is also
+ * responsible for instituting the various policies regarding
+ * propertys. ie It will enforce rules regarding
+ *
+ * true
if the specified property is set.
+ *
+ * @param name the name of property
+ */
+ boolean isPropertySet( String name );
+
+ /**
+ * Retrieve the value of specified property.
+ * Will return null if no such property exists.
+ *
+ * @param name the name of the property
+ * @return the value of the property, or null if no such property
+ * @throws Exception if theres an error retrieving property, such
+ * as an invalid property name
+ */
+ Object getProperty( String name )
+ throws Exception;
+
+ /**
+ * Retrieve a copy of all the properties that are "in-scope"
+ * for store.
+ *
+ * @return a copy of all the properties that are "in-scope"
+ * for store.
+ * @throws Exception if theres an error retrieving propertys
+ */
+ Map getProperties()
+ throws Exception;
+
+ /**
+ * Return a child PropertyStore with specified name.
+ * This is to allow support for scoped stores. However a
+ * store may choose to be unscoped and just return a
+ * reference to itself.
+ *
+ * @param name the name of child store
+ * @return the child store
+ * @throws Exception if theres an error creating child store
+ */
+ PropertyStore createChildStore( String name )
+ throws Exception;
+}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/test/DefaultConfigurerTestCase.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/test/DefaultConfigurerTestCase.java
index bf723f5aa..eced05dfc 100644
--- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/test/DefaultConfigurerTestCase.java
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/configurer/test/DefaultConfigurerTestCase.java
@@ -15,6 +15,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.components.AbstractComponentTest;
+import org.apache.myrmidon.components.store.DefaultPropertyStore;
import org.apache.myrmidon.components.configurer.DefaultConfigurer;
import org.apache.myrmidon.components.configurer.test.data.ConfigTestAttributeConvert;
import org.apache.myrmidon.components.configurer.test.data.ConfigTestConfigAdder;
@@ -76,7 +77,9 @@ public class DefaultConfigurerTestCase
m_configurer = (Configurer)getServiceManager().lookup( Configurer.ROLE );
// Setup a context
- m_context = new DefaultTaskContext( null, getServiceManager(), getLogger() );
+ final DefaultPropertyStore store = new DefaultPropertyStore();
+ m_context =
+ new DefaultTaskContext( getServiceManager(), getLogger(), store );
final File baseDir = new File( "." ).getAbsoluteFile();
m_context.setProperty( TaskContext.BASE_DIRECTORY, baseDir );
}
diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/AbstractPropertyResolverTestCase.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/AbstractPropertyResolverTestCase.java
index ec2039ff5..74d959cd2 100644
--- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/AbstractPropertyResolverTestCase.java
+++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/property/test/AbstractPropertyResolverTestCase.java
@@ -11,9 +11,11 @@ import java.io.File;
import java.util.Date;
import org.apache.aut.converter.lib.ObjectToStringConverter;
import org.apache.avalon.excalibur.i18n.Resources;
+import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.components.AbstractComponentTest;
+import org.apache.myrmidon.components.store.DefaultPropertyStore;
import org.apache.myrmidon.components.workspace.DefaultTaskContext;
import org.apache.myrmidon.interfaces.property.PropertyResolver;
@@ -40,7 +42,9 @@ public abstract class AbstractPropertyResolverTestCase
{
m_resolver = (PropertyResolver)getServiceManager().lookup( PropertyResolver.ROLE );
- m_context = new DefaultTaskContext( null, null, getLogger() );
+ final DefaultPropertyStore store = new DefaultPropertyStore();
+ final DefaultServiceManager serviceManager = new DefaultServiceManager();
+ m_context = new DefaultTaskContext( serviceManager, getLogger(), store );
m_context.setProperty( "intProp", new Integer( 333 ) );
m_context.setProperty( "stringProp", "String property" );