You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@etch.apache.org by sc...@apache.org on 2009/02/26 20:44:59 UTC

svn commit: r748283 - in /incubator/etch/branches/config: ./ services/ services/config/ services/config/src/ services/config/src/main/ services/config/src/main/etch/ services/config/src/main/java/ services/config/src/main/java/org/ services/config/src/...

Author: sccomer
Date: Thu Feb 26 19:44:58 2009
New Revision: 748283

URL: http://svn.apache.org/viewvc?rev=748283&view=rev
Log:
initial grant of config based on 1.1 stream.

Added:
    incubator/etch/branches/config/   (props changed)
      - copied from r748281, incubator/etch/trunk/
    incubator/etch/branches/config/services/
    incubator/etch/branches/config/services/config/   (with props)
    incubator/etch/branches/config/services/config/src/
    incubator/etch/branches/config/services/config/src/main/
    incubator/etch/branches/config/services/config/src/main/etch/
    incubator/etch/branches/config/services/config/src/main/etch/Configuration.etch   (with props)
    incubator/etch/branches/config/services/config/src/main/java/
    incubator/etch/branches/config/services/config/src/main/java/org/
    incubator/etch/branches/config/services/config/src/main/java/org/apache/
    incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/
    incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/
    incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/
    incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java   (with props)
    incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java   (with props)
    incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java   (with props)
    incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java   (with props)
Modified:
    incubator/etch/branches/config/.classpath

Propchange: incubator/etch/branches/config/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Feb 26 19:44:58 2009
@@ -0,0 +1,32 @@
+build-output
+doc
+snot
+xbuild
+barClient.java
+barHelper.java
+barServer.java
+ImplbarClient.java
+ImplbarServer.java
+MainbarClient.java
+MainbarListener.java
+RemotebarClient.java
+RemotebarServer.java
+StubbarClient.java
+StubbarServer.java
+ValueFactorybar.java
+bar.java
+Remotebar.java
+Stubbar.java
+BasebarClient.java
+BasebarServer.java
+bin
+readme-etch-java-files.txt
+build
+keys
+x.bat
+target
+CSharp.suo
+CSharp.4.0.resharper
+CSharp.4.0.resharper.user
+_ReSharper.CSharp
+CSharp.4.1.resharper.user

Propchange: incubator/etch/branches/config/
------------------------------------------------------------------------------
    svn:mergeinfo = incubator/etch/branches/sccomer-compiler-1:712739-712771

Modified: incubator/etch/branches/config/.classpath
URL: http://svn.apache.org/viewvc/incubator/etch/branches/config/.classpath?rev=748283&r1=748281&r2=748283&view=diff
==============================================================================
--- incubator/etch/branches/config/.classpath (original)
+++ incubator/etch/branches/config/.classpath Thu Feb 26 19:44:58 2009
@@ -43,6 +43,9 @@
 	<classpathentry kind="src" path="interoptester/src/test/java"/>
 	<classpathentry kind="src" path="interoptester/example/src/main/java"/>
 	<classpathentry kind="src" path="interoptester/example/target/generated-sources/main/etch/java"/>
+	<classpathentry kind="src" path="services/config/src/main/java"/>
+	<classpathentry kind="src" path="services/config/src/test/java"/>
+	<classpathentry kind="src" path="services/config/target/generated-sources/main/etch/java"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ETCH_DEPENDENT_JARS"/>
 	<classpathentry kind="output" path="bin"/>

Propchange: incubator/etch/branches/config/services/config/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Feb 26 19:44:58 2009
@@ -0,0 +1 @@
+target

Added: incubator/etch/branches/config/services/config/src/main/etch/Configuration.etch
URL: http://svn.apache.org/viewvc/incubator/etch/branches/config/services/config/src/main/etch/Configuration.etch?rev=748283&view=auto
==============================================================================
--- incubator/etch/branches/config/services/config/src/main/etch/Configuration.etch (added)
+++ incubator/etch/branches/config/services/config/src/main/etch/Configuration.etch Thu Feb 26 19:44:58 2009
@@ -0,0 +1,398 @@
+module org.apache.etch.services.config
+
+/**
+ * Configuration service provides access to configuration data. The data is
+ * modeled as a general tree structure with a root node which might be a scalar
+ * (boolean, int, double, string, Datetime), a List, or a Map. A List is
+ * indexed by int starting at 0, while a Map is indexed by non-empty string,
+ * generally following identifier syntax (case-sensitive, initial alpha then
+ * alphanumeric) but not required to. Each node in this tree is assigned an id.
+ * The id of the root node is null.
+ *
+ * At a given node in the tree, you may navigate up to the parent, down to the
+ * children, get the name, get the path (absolute, from the root), get the value
+ * if a scalar, enumerate the children if a List or Map, test if it is the root,
+ * a List, or a Map.
+ *
+ * This interface is only used to query configuration data, it does not include
+ * a facility to list available configurations, nor to manage configurations. It
+ * also does not include methods to alter existing configuration data, but it
+ * does allow you to subscribe to receive notification of changes.
+ *
+ * Configuration data is organized into separate spaces. The space is called out
+ * by name. You must have authorization to access the named space. There is no
+ * particular meaning to the name outside the interpretation given by the target
+ * service implementation. The configurations might come from a database, a
+ * directory tree of yaml files, etc. For services, anyway, a good idea would be
+ * to use the service name as it appears in the name service directory entry.
+ *
+ * Here is an example use of these interfaces:
+ *
+ * RemoteConfigurationServer server = ConfigurationHelper.newServer( ... );
+ * server._startAndWaitUp( 4000 );
+ * server.loadConfig( "org.apache.etch.services.ns.NameService/titan" );
+ * String host = server.getStringPath( null, "host" );
+ * int port = server.getIntegerPath( null, "port" );
+ *
+ * A path is a string delimited with '/' characters, much like a file system
+ * path. A path which begins with a '/' is absolute and begins at the root.
+ * Otherwise the path is relative to a specified node. The special names '.'
+ * and '..' may be used to refer to the current node and the parent node.
+ * When a path traverses a List, the index in the list is give as an integer in
+ * the path (e.g., /users/1/age). This would refer to the age of the 2nd user
+ * in a list of users. When a path is specified as null or blank, it is the same
+ * as '.'.
+ */
+@Timeout( 30000 )
+service Configuration
+{
+	/**
+	 * ConfigurationException is used to report any problem loading a
+	 * Configuration.
+	 * @param msg a text description of the problem.
+	 */
+	exception ConfigurationException( string msg )
+	
+	/**
+	 * Loads a configuration. Any previous configuration is discarded along
+	 * with any subscriptions. Depending upon the configuration service
+	 * capabilities, it may be able to monitor the configuration for changes
+	 * and automatically load them.
+	 * @param name the name of the configuration.
+	 * @throws ConfigurationException if there is any problem.
+	 */
+	@Authorize( canLoad, name )
+	void loadConfig( string name )
+		throws ConfigurationException
+	
+	/**
+	 * Unloads the current configuration if any.
+	 */
+	void unloadConfig()
+	
+	/**
+	 * Tests whether the configuration exists and can be loaded by this user.
+	 * @param name the name of the configuration.
+	 * @return true if the configuration exists and can be loaded by this user.
+	 */
+	boolean canLoad( string name )
+	
+	/**
+	 * Tests whether a configuration has been loaded.
+	 * @return true if a configuration has been loaded.
+	 */
+	boolean isLoaded()
+	
+	//////////////////////
+	// NODE PROPERTIES //
+	//////////////////////
+	
+	/**
+	 * Gets the parent of a node.
+	 * @param id the id of a node.
+	 * @return the id of the parent of the node, or null if it is the root.
+	 */
+	object getParent( object id )
+	
+	/**
+	 * Gets the name of a node which is a child of a map or list.
+	 * @param id the id of a node.
+	 * @return the name of the node. The name is a string if the parent is a
+	 * Map or a List, or "" (the empty string) if the value is the root.
+	 */
+	string getName( object id )
+	
+	/**
+	 * Gets the index of a node which is a child of a list.
+	 * @param id the id of a node.
+	 * @return the index of the node if the parent is a list, or null otherwise.
+	 */
+	int getIndex( object id )
+	
+	/**
+	 * Gets the path of a node.
+	 * @param id the id of a node.
+	 * @return the concatenation of the names of the ancestors of the node
+	 * with "/" between the names.
+	 */
+	string getPath( object id )
+	
+	/**
+	 * Tests whether a node is the root.
+	 * @param id the id of a node.
+	 * @return true if the node is the root.
+	 */
+	boolean isRoot( object id )
+	
+	/**
+	 * Tests whether a node is a List.
+	 * @param id the id of a node.
+	 * @return true if the node is a List.
+	 */
+	boolean isList( object id )
+	
+	/**
+	 * Tests whether a node is a Map.
+	 * @param id the id of a node.
+	 * @return true if the node is a Map.
+	 */
+	boolean isMap( object id )
+	
+	/**
+	 * Gets the number of children of a node which is a List or Map.
+	 * @param id the id of a node.
+	 * @return the number of children.
+	 */
+	int size( object id )
+	
+	//////////////
+	// CHILDREN //
+	//////////////
+	
+	/**
+	 * Lists the ids of the children of a node.
+	 * @param id the id of a node.
+	 * @param offset index into the result set of the first item to return. If
+	 * null, 0 is used.
+	 * @param count count of items to return. If null, all remaining items are
+	 * returned.
+	 * @return array of child ids, or null if the node is a scalar node.
+	 */
+	object[] listConfigIds( object id, int offset, int count )
+	
+	/**
+	 * Lists the ids of the children of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @param offset index into the result set of the first item to return. If
+	 * null, 0 is used.
+	 * @param count count of items to return. If null, all remaining items are
+	 * returned.
+	 * @return array of child ids, or null if the node is a scalar node.
+	 */
+	object[] listConfigPathIds( object id, string path, int offset, int count )
+	
+	/**
+	 * Gets the id of a child of a node by index. The node must be a List.
+	 * @param id the id of a node.
+	 * @param index an index of the child node. Starts at 0.
+	 * @return id of the child.
+	 */
+	object getConfigIndex( object id, int index )
+
+	/**
+	 * Gets the id of a child of a node by path. The nodes along the path must
+	 * all be a List or Map except the last. Whenever a path element is being
+	 * applied to a list node, it must be an integer.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return id of the child.
+	 */
+	object getConfigPath( object id, string path )
+	
+	////////////////////////
+	// NODE / PATH ACCESS //
+	////////////////////////
+	
+	/**
+	 * Tests whether a node has a value.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return true if the node has a value.
+     */
+	boolean hasValuePath( object id, string path )
+	
+	/**
+	 * Gets the value value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none. Note that the value may
+	 * not be the expected type. That depends upon the underlying
+	 * implementation. If you want the value as a specific type, use
+	 * getTypePath() methods below.
+     */
+	object getValuePath( object id, string path )
+
+	/**
+	 * Gets the boolean value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	boolean getBooleanPath( object id, string path )
+
+	/**
+	 * Gets the integer value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	int getIntegerPath( object id, string path )
+
+	/**
+	 * Gets the double value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	double getDoublePath( object id, string path )
+
+	/**
+	 * Gets the string value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	string getStringPath( object id, string path )
+
+	/**
+	 * Gets the Datetime value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @return the value of the node, or null if none.
+     */
+	Datetime getDatePath( object id, string path )
+	
+	/**
+	 * Gets the List value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @param depth if any of the values in the list are themselves maps or
+	 * lists, recursively get those values too up to the specified depth. Depth
+	 * value of 0 means only get the values of the node itself.
+	 * @return the List value of the node.
+	 */
+	List getListPath( object id, string path, int depth )
+	
+	/**
+	 * Gets the Map value of a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 * @param depth if any of the values in the map are themselves maps or
+	 * lists, recursively get those values too up to the specified depth. Depth
+	 * value of 0 means only get the values of the node itself.
+	 * @return the Map value of the node.
+	 */
+	Map getMapPath( object id, string path, int depth )
+	
+	/////////////////
+	// NODE ACCESS //
+	/////////////////
+
+	/**
+	 * Tests whether a node has a value.
+	 * @param id the id of a node.
+	 * @return true if the node has a value.
+     */
+	boolean hasValue( object id )
+	
+	/**
+	 * Gets the value value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none. Note that the value may
+	 * not be the expected type. That depends upon the underlying
+	 * implementation. If you want the value as a specific type, use getType()
+	 * methods below.
+     */
+	object getValue( object id )
+
+	/**
+	 * Gets the boolean value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	boolean getBoolean( object id )
+
+	/**
+	 * Gets the integer value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	int getInteger( object id )
+
+	/**
+	 * Gets the double value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	double getDouble( object id )
+
+	/**
+	 * Gets the string value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	string getString( object id )
+
+	/**
+	 * Gets the Datetime value of a node.
+	 * @param id the id of a node.
+	 * @return the value of the node, or null if none.
+     */
+	Datetime getDate( object id )
+	
+	/**
+	 * Gets the List value of a node.
+	 * @param id the id of a node.
+	 * @param depth if any of the values in the list are themselves maps or
+	 * lists, recursively get those values too up to the specified depth. Depth
+	 * value of 0 means only get the values of the node itself.
+	 * @return the List value of the node.
+	 */
+	List getList( object id, int depth )
+	
+	/**
+	 * Gets the Map value of a node.
+	 * @param id the id of a node.
+	 * @param depth if any of the values in the map are themselves maps or
+	 * lists, recursively get those values too up to the specified depth. Depth
+	 * value of 0 means only get the values of the node itself.
+	 * @return the Map value of the node.
+	 */
+	Map getMap( object id, int depth )
+	
+	/////////////////////////
+	// CHANGE NOTIFICATION //
+	/////////////////////////
+	
+	/**
+	 * Subscribes to changes at or below a node.
+	 * @param id the id of a node.
+	 */
+	void subscribe( object id )
+	
+	/**
+	 * Subscribes to changes at or below a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 */
+	void subscribePath( object id, string path )
+	
+	/**
+	 * Unsubscribes to changes at or below a node.
+	 * @param id the id of a node.
+	 */
+	void unsubscribe( object id )
+	
+	/**
+	 * Unsubscribes to changes at or below a node.
+	 * @param id the id of a node.
+	 * @param path a path relative to the node.
+	 */
+	void unsubscribePath( object id, string path )
+	
+	/**
+	 * Unsubscribes to all changes.
+	 */
+	void unsubscribeAll()
+	
+	/**
+	 * Notifies client of changes to the values of nodes. Added or deleted nodes
+	 * are treated as updates to the parent. Reporting is done on a best effort
+	 * basis. The nodes reported might be an ancestor of the nodes which
+	 * actually changed.
+	 * @param updated the ids of nodes that have been updated.
+	 */
+	@Direction( Client )
+	void configValuesChanged( object[] updated )
+}

Propchange: incubator/etch/branches/config/services/config/src/main/etch/Configuration.etch
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/etch/branches/config/services/config/src/main/etch/Configuration.etch
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java
URL: http://svn.apache.org/viewvc/incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java?rev=748283&view=auto
==============================================================================
--- incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java (added)
+++ incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java Thu Feb 26 19:44:58 2009
@@ -0,0 +1,37 @@
+// This file automatically generated by:
+//   Etch 1.0.0 (LOCAL-0) / java 1.0.0 (LOCAL-0)
+//   Fri Jan 09 11:53:48 CST 2009
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+
+package org.apache.etch.services.config;
+
+
+/**
+ * Your custom implementation of BaseConfigurationClient. Add methods here to provide
+ * implementations of messages from the server.
+ */
+public class ImplConfigurationClient extends BaseConfigurationClient
+{
+	/**
+	 * Constructs the ImplConfigurationClient.
+	 *
+	 * @param server a connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	public ImplConfigurationClient( RemoteConfigurationServer server )
+	{
+		this.server = server;
+	}
+	
+	/**
+	 * A connection to the server session. Use this to send a
+	 * message to the server.
+	 */
+	@SuppressWarnings( "unused" )
+	private final RemoteConfigurationServer server;
+
+	// TODO insert methods here to provide implementations of ConfigurationClient
+	// messages from the server.
+}
\ No newline at end of file

Propchange: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/ImplConfigurationClient.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java
URL: http://svn.apache.org/viewvc/incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java?rev=748283&view=auto
==============================================================================
--- incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java (added)
+++ incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java Thu Feb 26 19:44:58 2009
@@ -0,0 +1,67 @@
+// This file automatically generated by:
+// Etch 1.0.0 (LOCAL-0) / java 1.0.0 (LOCAL-0)
+// Fri Jan 09 11:53:48 CST 2009
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+
+package org.apache.etch.services.config;
+
+import org.apache.etch.util.URL;
+
+/**
+ * Main program for ConfigurationClient. This program makes a connection to the
+ * listener created by MainConfigurationListener.
+ */
+public class MainConfigurationClient implements
+	ConfigurationHelper.ConfigurationClientFactory
+{
+	/**
+	 * Main program for ConfigurationClient.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// get our configUri from a local config file.
+		ConfigurationServer local = new YamlConfig( null, "services/config/local" );
+		String configUri = local.getStringPath( null, "configUri" );
+		System.out.println( "configUri = "+configUri );
+		local.unloadConfig();
+		local = null;		
+		
+		RemoteConfigurationServer server = ConfigurationHelper.newServer(
+			configUri, null, new MainConfigurationClient() );
+
+		// Connect to the service.
+		server._startAndWaitUp( 4000 );
+		System.out.println( "connected to config service" );
+		
+		String name = new URL( configUri ).getUri();
+		server.loadConfig( name );
+		System.out.println( "loaded configuration named '"+name+"'" );
+		
+		// Load a config and play with it.
+		System.out.println( "bool = "+server.getBooleanPath( null, "bool" ) );
+		System.out.println( "int = "+server.getIntegerPath( null, "int" ) );
+		System.out.println( "dbl = "+server.getDoublePath( null, "dbl" ) );
+		System.out.println( "str = "+server.getStringPath( null, "str" ) );
+		System.out.println( "date = "+server.getDatePath( null, "date" ) );
+		
+		System.out.println( "users/mary = "+server.getStringPath( null, "users/mary" ) );
+		
+		Object users = server.getConfigPath( null, "users" );
+		System.out.println( "users/mary = "+server.getStringPath( users, "mary" ) );
+		System.out.println( "users/alice = "+server.getStringPath( users, "alice" ) );
+
+		// Disconnect from the service.
+		server._stopAndWaitDown( 4000 );
+	}
+
+	public ConfigurationClient newConfigurationClient(
+		RemoteConfigurationServer server ) throws Exception
+	{
+		return new ImplConfigurationClient( server );
+	}
+}

Propchange: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationClient.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java
URL: http://svn.apache.org/viewvc/incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java?rev=748283&view=auto
==============================================================================
--- incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java (added)
+++ incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java Thu Feb 26 19:44:58 2009
@@ -0,0 +1,70 @@
+// This file automatically generated by:
+//   Etch 1.0.0 (LOCAL-0) / java 1.0.0 (LOCAL-0)
+//   Fri Jan 09 11:53:48 CST 2009
+// This file is automatically created for your convenience and will not be
+// overwritten once it exists! Please edit this file as necessary to implement
+// your service logic.
+
+package org.apache.etch.services.config;
+
+import org.apache.etch.bindings.java.support.ObjSession;
+import org.apache.etch.bindings.java.support.ServerFactory;
+import org.apache.etch.util.core.io.Session;
+import org.apache.etch.util.core.io.Transport;
+
+
+
+/**
+ * Main program for ConfigurationServer. This program makes a listener to accept
+ * connections from MainConfigurationClient.
+ */
+public class MainConfigurationListener implements ConfigurationHelper.ConfigurationServerFactory
+{
+	/**
+	 * Main program for ConfigurationServer.
+	 * 
+	 * @param args command line arguments.
+	 * @throws Exception
+	 */
+	public static void main( String[] args ) throws Exception
+	{
+		// TODO Change to correct URI
+		String uri = "tcp://0.0.0.0:4001";
+		
+		ServerFactory listener = ConfigurationHelper.newListener( uri, null,
+			new MainConfigurationListener() );
+
+		// Start the Listener
+		listener.transportControl( Transport.START_AND_WAIT_UP, 4000 );
+	}
+
+	public ConfigurationServer newConfigurationServer( RemoteConfigurationClient client )
+	{
+		return new MyYamlConfig( client );
+	}
+	
+	public static class MyYamlConfig extends YamlConfig implements ObjSession
+	{
+		public MyYamlConfig( RemoteConfigurationClient client )
+		{
+			super( client );
+		}
+
+		public Object _sessionQuery( Object query ) throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown query "+query );
+		}
+		
+		public void _sessionControl( Object control, Object value )
+			throws Exception
+		{
+			throw new UnsupportedOperationException( "unknown control "+control );
+		}
+
+		public void _sessionNotify( Object event ) throws Exception
+		{
+			if (event == Session.DOWN)
+				unloadConfig();
+		}
+	}
+}

Propchange: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/MainConfigurationListener.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java
URL: http://svn.apache.org/viewvc/incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java?rev=748283&view=auto
==============================================================================
--- incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java (added)
+++ incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java Thu Feb 26 19:44:58 2009
@@ -0,0 +1,758 @@
+package org.apache.etch.services.config;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.etch.util.AlarmListener;
+import org.apache.etch.util.AlarmManager;
+import org.apache.etch.util.Assertion;
+import org.ho.yaml.Yaml;
+
+
+/** Local Yaml implementation of ConfigurationServer */
+public class YamlConfig implements ConfigurationServer
+{
+	/**
+	 * Constructs an empty YamlConfigurationServer.
+	 * @param client 
+	 */
+	public YamlConfig( ConfigurationClient client )
+	{
+		this.client = client;
+	}
+	
+	@SuppressWarnings("unused")
+	private final ConfigurationClient client;
+	
+	/**
+	 * Constructs a YamlConfigurationServer, then loads the config.
+	 * @param client 
+	 * @param name
+	 * @throws ConfigurationException
+	 */
+	public YamlConfig( ConfigurationClient client, String name )
+		throws ConfigurationException
+	{
+		this( client );
+		loadConfig( name );
+	}
+
+	public void loadConfig( String name )
+		throws ConfigurationException
+	{
+		unloadConfig();
+		file = new File( name+".yml" );
+		importConfigs( loadConfig() );
+	}
+	
+	public void unloadConfig()
+	{
+		file = null;
+		lastModified = 0;
+		configs = new ArrayList<Conf>();
+		unsubscribeAll();
+	}
+	
+	private Object loadConfig() throws ConfigurationException
+	{
+		for (int i = 0; i < 4; i++)
+		{
+			try
+			{
+				long t0 = file.lastModified();
+				Object o = Yaml.load( file );
+				long t1 = file.lastModified();
+				if (t1 != t0)
+				{
+					Thread.sleep( 1000 );
+					continue;
+				}
+				lastModified = t1;
+				return o;
+			}
+			catch ( FileNotFoundException e )
+			{
+				throw new ConfigurationException( "file not found: " + file );
+			}
+			catch ( InterruptedException e )
+			{
+				break;
+			}
+		}
+		throw new ConfigurationException( "file changed while loading: " + file );
+	}
+
+	private File file;
+	
+	private long lastModified;
+
+	public Boolean canLoad( String name )
+	{
+		return true;
+	}
+
+	public Object getParent( Object id )
+	{
+		return toId( getConf( id ).parent );
+	}
+
+	public String getName( Object id )
+	{
+		Object n = getConf( id ).name;
+		if (n == null)
+			return "";
+		if (n instanceof String)
+			return (String) n;
+		return n.toString();
+	}
+
+	public String getPath( Object id )
+	{
+		Conf c = getConf( id );
+		
+		if (c.isRoot())
+			return "";
+		
+		return getPath( toId( c.parent ) ) + '/' + c.name;
+	}
+
+	public Boolean isRoot( Object id )
+	{
+		return getConf( id ).isRoot();
+	}
+
+	public Boolean isList( Object id )
+	{
+		return getConf( id ).isList();
+	}
+
+	public Boolean isMap( Object id )
+	{
+		return getConf( id ).isMap();
+	}
+	
+	public Integer size( Object id )
+	{
+		Conf c = getConf( id );
+		
+		if (c.isList())
+			return c.list().size();
+		
+		if (c.isMap())
+			return c.map().size();
+		
+		throw new NoSuchElementException( "value is not a List or a Map" );
+	}
+	
+	//////////////
+	// CHILDREN //
+	//////////////
+
+	public Object[] listConfigIds( Object id, Integer offset, Integer count )
+	{
+		Conf c = getConf( id );
+		
+		if (c.isList())
+			return toIdArray( c.list(), offset, count );
+		
+		if (c.isMap())
+			return toIdArray( c.map().values(), offset, count );
+		
+		throw new NoSuchElementException( "value is not a List or a Map" );
+	}
+	
+	public Object[] listConfigPathIds( Object id, String path, Integer offset, Integer count )
+	{
+		return listConfigIds( getConfigPath( id, path ), offset, count );
+	}
+
+	public Object getConfigIndex( Object id, Integer index )
+	{
+		if (index == null)
+			throw new IllegalArgumentException( "index == null" );
+		
+		Conf c = getConf( id );
+		
+		if (c.isList())
+		{
+			List<Integer> list = c.list();
+			if (index < 0 || index >= list.size())
+				throw new IllegalArgumentException( "index < 0 || index >= list.size()" );
+			return toId( c.list().get( index ) );
+		}
+		
+		throw new IllegalArgumentException( "node is not a list" );
+	}
+
+	public Object getConfigPath( Object id, String path )
+	{
+		if (path == null || path.length() == 0)
+		{
+			getConf( id );
+			return id;
+		}
+		
+		// path is not null and not empty.
+		
+		Integer iid = fromId( id );
+		
+		if (path.indexOf( '/' ) < 0)
+			return toId( getConfig0( iid, path ) );
+		
+		if (iid != null && path.startsWith( "/" ))
+			iid = null;
+		
+		getConf( iid );
+		
+		StringTokenizer st = new StringTokenizer( path, "/" );
+		while (st.hasMoreTokens())
+			iid = getConfig0( iid, st.nextToken() );
+		
+		return toId( iid );
+	}
+
+	//////////////////////
+	// NODE PATH VALUES //
+	//////////////////////
+
+	public Boolean hasValuePath( Object id, String path )
+	{
+		return hasValue( getConfigPath( id, path ) );
+	}
+
+	public Boolean getBooleanPath( Object id, String path )
+	{
+		return getBoolean( getConfigPath( id, path ) );
+	}
+
+	public Integer getIntegerPath( Object id, String path )
+	{
+		return getInteger( getConfigPath( id, path ) );
+	}
+
+	public Double getDoublePath( Object id, String path )
+	{
+		return getDouble( getConfigPath( id, path ) );
+	}
+
+	public String getStringPath( Object id, String path )
+	{
+		return getString( getConfigPath( id, path ) );
+	}
+
+	public Date getDatePath( Object id, String path )
+	{
+		return getDate( getConfigPath( id, path ) );
+	}
+
+	public List<?> getListPath( Object id, String path, Integer depth )
+	{
+		return getList( getConfigPath( id, path ), depth );
+	}
+
+	public Map<?, ?> getMapPath( Object id, String path, Integer depth )
+	{
+		return getMap( getConfigPath( id, path ), depth );
+	}
+	
+	/////////////////
+	// NODE VALUES //
+	/////////////////
+
+	public Boolean hasValue( Object id )
+	{
+		return id != null && getConf( id ).hasValue();
+	}
+
+	public Boolean getBoolean( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getBoolean();
+	}
+
+	public Integer getInteger( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getInteger();
+	}
+
+	public Double getDouble( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getDouble();
+	}
+
+	public String getString( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getString();
+	}
+
+	public Date getDate( Object id )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getDate();
+	}
+
+	public List<?> getList( Object id, Integer depth )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getList( depth );
+	}
+
+	public Map<?, ?> getMap( Object id, Integer depth )
+	{
+		if (id == null)
+			return null;
+		return getConf( id ).getMap( depth );
+	}
+	
+	/////////////////////////
+	// CHANGE NOTIFICATION //
+	/////////////////////////
+	
+	private final static int INTERVAL = 5*1000;
+	
+	private final AlarmListener LISTENER = new AlarmListener()
+	{
+		public int wakeup( AlarmManager manager, Object state,
+			long due )
+		{
+			try
+			{
+				updateConfig();
+			}
+			catch ( Exception e )
+			{
+				e.printStackTrace();
+				return 0;
+			}
+			return INTERVAL;
+		}
+	};
+
+	public void subscribe( Object id )
+	{
+		if (id == null)
+			return;
+		
+		getConf( id );
+		
+		synchronized (subs)
+		{
+			boolean wasEmpty = subs.isEmpty();
+			
+			subs.add( fromId( id ) );
+			
+			if (wasEmpty)
+				AlarmManager.staticAdd( LISTENER, null, INTERVAL );
+		}
+	}
+
+	private Object toId( Integer iid )
+	{
+		return iid;
+	}
+
+	private Integer fromId( Object id )
+	{
+		if (id == null)
+			return null;
+		if (id instanceof Integer)
+			return (Integer) id;
+		return ((Number) id).intValue();
+	}
+
+	public void subscribePath( Object id, String path )
+	{
+		subscribe( getConfigPath( id, path ) );
+	}
+
+	public void unsubscribe( Object id )
+	{
+		if (id == null)
+			return;
+		
+		getConf( id );
+		
+		synchronized (subs)
+		{
+			subs.remove( id );
+			
+			if (subs.isEmpty())
+				AlarmManager.staticRemove( LISTENER );
+		}
+	}
+
+	public void unsubscribePath( Object id, String path )
+	{
+		unsubscribe( getConfigPath( id, path ) );
+	}
+	
+	public void unsubscribeAll()
+	{
+		synchronized (subs)
+		{
+			subs.clear();
+
+			AlarmManager.staticRemove( LISTENER );
+		}
+	}
+	
+	private final Set<Integer> subs = Collections.synchronizedSet( new HashSet<Integer>() );
+
+	/////////////
+	// PRIVATE //
+	/////////////
+
+	private void importConfigs( Object root )
+	{
+		importObject( null, null, root );
+	}
+	
+	private void updateConfig() throws ConfigurationException
+	{
+		if (file.lastModified() != lastModified)
+		{
+			List<Integer> changeSet = new ArrayList<Integer>();
+			updateObject( changeSet, 0, null, null, loadConfig() );
+			// TODO notify about changeSet
+		}
+	}
+
+	private int importObject( Integer parent, Object name, Object value )
+	{
+		if (value instanceof List)
+		{
+			return importList( parent, name, (List<?>) value );
+		}
+		else if (value instanceof Map)
+		{
+			return importMap( parent, name, (Map<?, ?>) value );
+		}
+		else if (isScalar( value ))
+		{
+			int k = configs.size();
+			configs.add( new Conf( parent, name, value ) );
+			return k;
+		}
+		else
+		{
+			throw new IllegalArgumentException(
+				"don't know how to import type "+value.getClass() );
+		}
+	}
+	
+	private boolean isScalar( Object value )
+	{
+		return value instanceof Boolean || value instanceof Number ||
+			value instanceof String || value instanceof Date;
+	}
+
+	private void updateObject( List<Integer> changeSet, int id,
+		Integer parent, Object name, Object value )
+	{
+		if (true) return;
+		
+		Conf c = getConf( id );
+		
+		Assertion.check( (parent == null && c.parent == null) ||
+			(parent != null && c.parent != null && parent.equals( c.parent )),
+				"parents match" );
+		
+		Assertion.check( (name == null && c.name == null) ||
+			(name != null && c.name != null && name.equals( c.name )),
+			"names match" );
+		
+		if (value instanceof List)
+		{
+			// return updateList( changeSet, parent, name, (List<?>) value, c.value );
+			return;
+		}
+		else if (value instanceof Map)
+		{
+			// return updateMap( changeSet, parent, name, (Map<?, ?>) value );
+		}
+		else if (isScalar( value ))
+		{
+			if ((value == null && c.value == null) ||
+				(value != null && c.value != null && value.equals( c.value )))
+				return;
+		}
+		else
+		{
+			throw new IllegalArgumentException(
+				"don't know how to update type "+value.getClass() );
+		}
+	}
+
+	private int importList( Integer parent, Object name, List<?> value )
+	{
+		List<Integer> v = new ArrayList<Integer>( value.size() );
+		int k = configs.size();
+		configs.add( new Conf( parent, name, v ) );
+		
+		int i = 0;
+		for (Object o: value )
+			v.add( importObject( k, i++, o ) );
+		
+		return k;
+	}
+	
+	private int importMap( Integer parent, Object name, Map<?, ?> value )
+	{
+		Map<String, Integer> v = new HashMap<String, Integer>( value.size() * 4 / 3 + 1 );
+		int k = configs.size();
+		configs.add( new Conf( parent, name, v ) );
+		
+		for (Map.Entry<?, ?> me: value.entrySet() )
+		{
+			String n = (String) me.getKey();
+			v.put( n, importObject( k, n, me.getValue() ) );
+		}
+		
+		return k;
+	}
+
+	private List<Conf> configs;
+	
+	private Conf getConf( Integer iid )
+	{
+		if (iid == null)
+			iid = 0;
+//			throw new IllegalArgumentException( "id == null" );
+		
+		if (iid < 0 || iid >= configs.size())
+			throw new IllegalArgumentException( "id < 0 || id >= configs.size()" );
+		
+		return configs.get( iid );
+	}
+	
+	private Conf getConf( Object id )
+	{
+		return getConf( fromId( id ) );
+	}
+
+	private Object[] toIdArray( Collection<Integer> value, Integer offset,
+		Integer count )
+	{
+		int size = value.size();
+		
+		if (offset == null)
+			offset = 0;
+		else if (offset < 0 || offset > size)
+			throw new IllegalArgumentException(
+				"offset < 0 || offset > size" );
+		
+		if (count == null)
+			count = Integer.MAX_VALUE;
+		else if (count < 0)
+			throw new IllegalArgumentException(
+				"count < 0" );
+		
+		int remaining = size - offset;
+		if (count > remaining)
+			count = remaining;
+		
+		Object[] a = new Object[count];
+		
+		int i = 0;
+		for (int v: value)
+		{
+			if (offset > 0)
+				offset--;
+			else
+				a[i++] = toId( v );
+		}
+		
+		return a;
+	}
+	
+	private Integer getConfig0( Integer iid, String name )
+	{
+		Conf c = getConf( iid );
+		
+		if (name.equals( "." ))
+			return iid;
+		
+		if (name.equals( ".." ))
+			return c.parent;
+		
+		if (c.isList())
+			return c.list().get( Integer.valueOf( name ) );
+		
+		if (c.isMap())
+		{
+			Integer i = c.map().get( name );
+			// i might be null.
+			return i;
+		}
+		
+		throw new NoSuchElementException( name );
+	}
+	
+	private static class Conf
+	{
+		public Conf( Integer parent, Object name, Object value )
+		{
+			this.parent = parent;
+			this.name = name;
+			this.value = value;
+		}
+		
+		public Integer parent;
+		
+		public Object name;
+		
+		public Object value;
+
+		public boolean isRoot()
+		{
+			return name == null;
+		}
+		
+		public boolean isList()
+		{
+			return value instanceof List;
+		}
+
+		public boolean isMap()
+		{
+			return value instanceof Map;
+		}
+		
+		@SuppressWarnings("unchecked")
+		public List<Integer> list()
+		{
+			return (List<Integer>) value;
+		}
+		
+		@SuppressWarnings("unchecked")
+		public Map<String, Integer> map()
+		{
+			return (Map<String, Integer>) value;
+		}
+		
+		public boolean hasValue()
+		{
+			return value != null;
+		}
+		
+		public Boolean getBoolean()
+		{
+			if (value == null)
+				return null;
+			if (value instanceof Boolean)
+				return (Boolean) value;
+			if (value instanceof String)
+				return Boolean.valueOf( (String) value );
+			throw new IllegalArgumentException( "cannot convert value to Boolean" );
+		}
+		
+		public Integer getInteger()
+		{
+			if (value == null)
+				return null;
+			if (value instanceof Integer)
+				return (Integer) value;
+			if (value instanceof Number)
+				return ((Number) value).intValue();
+			if (value instanceof String)
+				return Integer.valueOf( (String) value );
+			throw new IllegalArgumentException( "cannot convert value to Integer" );
+		}
+		
+		public Double getDouble()
+		{
+			if (value == null)
+				return null;
+			if (value instanceof Double)
+				return (Double) value;
+			if (value instanceof Number)
+				return ((Number) value).doubleValue();
+			if (value instanceof String)
+				return Double.valueOf( (String) value );
+			throw new IllegalArgumentException( "cannot convert value to Double" );
+		}
+		
+		public String getString()
+		{
+			if (value == null)
+				return null;
+			if (value instanceof String)
+				return (String) value;
+			if (value instanceof Number)
+				return value.toString();
+			if (value instanceof Boolean)
+				return value.toString();
+			if (value instanceof Date)
+				return value.toString();
+			throw new IllegalArgumentException( "cannot convert value to String" );
+		}
+		
+		@SuppressWarnings("deprecation")
+		public Date getDate()
+		{
+			if (value == null)
+				return null;
+			if (value instanceof Date)
+				return (Date) value;
+			if (value instanceof String)
+				return new Date( (String) value );
+			throw new IllegalArgumentException( "cannot convert value to Date" );
+		}
+		
+		public List<?> getList( Integer depth )
+		{
+			// TODO Auto-generated method stub
+			return null;
+		}
+		
+		public Map<?, ?> getMap( Integer depth )
+		{
+			// TODO Auto-generated method stub
+			return null;
+		}
+	}
+
+	public Integer getIndex( Object id )
+	{
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Object getValue( Object id )
+	{
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Object getValuePath( Object id, String path )
+	{
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Boolean isLoaded()
+	{
+		// TODO Auto-generated method stub
+		return null;
+	}
+}

Propchange: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/etch/branches/config/services/config/src/main/java/org/apache/etch/services/config/YamlConfig.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"