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"