r1859 - in trunk/main/lang: . part part/src part/src/main part/src/main/dpml part/src/main/dpml/appliance part/src/main/dpml/lang part/src/main/dpml/state part/src/main/net part/src/main/net/dpml part/src/main/net/dpml/annotation part/src/main/net/dpml/appliance part/src/main/net/dpml/lang part/src/main/net/dpml/runtime part/src/main/net/dpml/state part/src/test part/src/test/META-INF part/src/test/META-INF/services part/src/test/dpml part/src/test/dpml/lang part/src/test/net part/src/test/net/dpml part/src/test/net/dpml/runtime part/src/test/net/dpml/runtime/composition part/src/test/net/dpml/runtime/context part/src/test/net/dpml/runtime/isolation part/src/test/net/dpml/runtime/lifecycle part/src/test/net/dpml/runtime/lifestyle part/src/test/net/dpml/runtime/profile part/src/test/net/dpml/runtime/service part/src/test/org part/src/test/org/acme sample sample/etc sample/src sample/src/main sample/src/main/org sample/src/main/org/acme

mcconnell at BerliOS mcconnell at mail.berlios.de
Thu Feb 8 20:30:10 EST 2007


Author: mcconnell
Date: 2007-02-09 02:29:45 +0100 (Fri, 09 Feb 2007)
New Revision: 1859

Added:
   trunk/main/lang/part/project.xml
   trunk/main/lang/part/src/
   trunk/main/lang/part/src/main/
   trunk/main/lang/part/src/main/dpml/
   trunk/main/lang/part/src/main/dpml/appliance/
   trunk/main/lang/part/src/main/dpml/appliance/AbstractAppliance.java
   trunk/main/lang/part/src/main/dpml/appliance/ApplianceHelper.java
   trunk/main/lang/part/src/main/dpml/appliance/StandardAppliance.java
   trunk/main/lang/part/src/main/dpml/lang/
   trunk/main/lang/part/src/main/dpml/lang/Classpath.java
   trunk/main/lang/part/src/main/dpml/lang/Construct.java
   trunk/main/lang/part/src/main/dpml/lang/ContextInvocationHandler.java
   trunk/main/lang/part/src/main/dpml/lang/DOM3DocumentBuilder.java
   trunk/main/lang/part/src/main/dpml/lang/DOMInput.java
   trunk/main/lang/part/src/main/dpml/lang/DefaultPartManager.java
   trunk/main/lang/part/src/main/dpml/lang/Disposable.java
   trunk/main/lang/part/src/main/dpml/lang/DocumentRuntimeException.java
   trunk/main/lang/part/src/main/dpml/lang/Info.java
   trunk/main/lang/part/src/main/dpml/lang/LoggingInvocationHandler.java
   trunk/main/lang/part/src/main/dpml/lang/Part.java
   trunk/main/lang/part/src/main/dpml/lang/StandardNamespaceResolver.java
   trunk/main/lang/part/src/main/dpml/lang/Value.java
   trunk/main/lang/part/src/main/dpml/lang/ValueDecoder.java
   trunk/main/lang/part/src/main/dpml/lang/ValueException.java
   trunk/main/lang/part/src/main/dpml/lang/ValueRuntimeException.java
   trunk/main/lang/part/src/main/dpml/state/
   trunk/main/lang/part/src/main/dpml/state/DefaultInterface.java
   trunk/main/lang/part/src/main/dpml/state/DefaultOperation.java
   trunk/main/lang/part/src/main/dpml/state/DefaultState.java
   trunk/main/lang/part/src/main/dpml/state/DefaultTransition.java
   trunk/main/lang/part/src/main/dpml/state/DefaultTrigger.java
   trunk/main/lang/part/src/main/dpml/state/NullState.java
   trunk/main/lang/part/src/main/dpml/state/StateBuilderRuntimeException.java
   trunk/main/lang/part/src/main/dpml/state/StateDecoder.java
   trunk/main/lang/part/src/main/dpml/state/StateEncoder.java
   trunk/main/lang/part/src/main/net/
   trunk/main/lang/part/src/main/net/dpml/
   trunk/main/lang/part/src/main/net/dpml/annotation/
   trunk/main/lang/part/src/main/net/dpml/annotation/Activation.java
   trunk/main/lang/part/src/main/net/dpml/annotation/ActivationPolicy.java
   trunk/main/lang/part/src/main/net/dpml/annotation/CollectionPolicy.java
   trunk/main/lang/part/src/main/net/dpml/annotation/Component.java
   trunk/main/lang/part/src/main/net/dpml/annotation/Context.java
   trunk/main/lang/part/src/main/net/dpml/annotation/LifestylePolicy.java
   trunk/main/lang/part/src/main/net/dpml/annotation/Parts.java
   trunk/main/lang/part/src/main/net/dpml/annotation/Services.java
   trunk/main/lang/part/src/main/net/dpml/annotation/package-info.java
   trunk/main/lang/part/src/main/net/dpml/appliance/
   trunk/main/lang/part/src/main/net/dpml/appliance/Appliance.java
   trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceConnector.java
   trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceContentManager.java
   trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceError.java
   trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceEvent.java
   trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceException.java
   trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceFactory.java
   trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceListener.java
   trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceManager.java
   trunk/main/lang/part/src/main/net/dpml/appliance/PlanManager.java
   trunk/main/lang/part/src/main/net/dpml/appliance/package-info.java
   trunk/main/lang/part/src/main/net/dpml/lang/
   trunk/main/lang/part/src/main/net/dpml/lang/AntlibStrategy.java
   trunk/main/lang/part/src/main/net/dpml/lang/AntlibStrategyHandler.java
   trunk/main/lang/part/src/main/net/dpml/lang/Buffer.java
   trunk/main/lang/part/src/main/net/dpml/lang/ClassLoaderHelper.java
   trunk/main/lang/part/src/main/net/dpml/lang/DecodingException.java
   trunk/main/lang/part/src/main/net/dpml/lang/DuplicateKeyException.java
   trunk/main/lang/part/src/main/net/dpml/lang/NamespaceError.java
   trunk/main/lang/part/src/main/net/dpml/lang/PartContentHandler.java
   trunk/main/lang/part/src/main/net/dpml/lang/PartContentManager.java
   trunk/main/lang/part/src/main/net/dpml/lang/PartError.java
   trunk/main/lang/part/src/main/net/dpml/lang/PartException.java
   trunk/main/lang/part/src/main/net/dpml/lang/PartManager.java
   trunk/main/lang/part/src/main/net/dpml/lang/ServiceError.java
   trunk/main/lang/part/src/main/net/dpml/lang/ServiceRegistry.java
   trunk/main/lang/part/src/main/net/dpml/lang/SimpleServiceRegistry.java
   trunk/main/lang/part/src/main/net/dpml/lang/StandardServiceRegistry.java
   trunk/main/lang/part/src/main/net/dpml/lang/Strategy.java
   trunk/main/lang/part/src/main/net/dpml/lang/StrategyHandler.java
   trunk/main/lang/part/src/main/net/dpml/lang/TypeCastException.java
   trunk/main/lang/part/src/main/net/dpml/lang/UnknownKeyException.java
   trunk/main/lang/part/src/main/net/dpml/lang/UnknownServiceException.java
   trunk/main/lang/part/src/main/net/dpml/lang/Version.java
   trunk/main/lang/part/src/main/net/dpml/lang/package-info.java
   trunk/main/lang/part/src/main/net/dpml/runtime/
   trunk/main/lang/part/src/main/net/dpml/runtime/Component.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ComponentError.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ComponentEvent.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ComponentException.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ComponentInvocationHandler.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ComponentListener.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ComponentStrategy.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ComponentStrategyHandler.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ContextDirective.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ContextInvocationHandler.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ContextModel.java
   trunk/main/lang/part/src/main/net/dpml/runtime/DefaultStateMachine.java
   trunk/main/lang/part/src/main/net/dpml/runtime/Directive.java
   trunk/main/lang/part/src/main/net/dpml/runtime/EventQueue.java
   trunk/main/lang/part/src/main/net/dpml/runtime/LifestyleHandler.java
   trunk/main/lang/part/src/main/net/dpml/runtime/PartsDirective.java
   trunk/main/lang/part/src/main/net/dpml/runtime/PartsInvocationHandler.java
   trunk/main/lang/part/src/main/net/dpml/runtime/Profile.java
   trunk/main/lang/part/src/main/net/dpml/runtime/Provider.java
   trunk/main/lang/part/src/main/net/dpml/runtime/ProviderEvent.java
   trunk/main/lang/part/src/main/net/dpml/runtime/Query.java
   trunk/main/lang/part/src/main/net/dpml/runtime/StandardProvider.java
   trunk/main/lang/part/src/main/net/dpml/runtime/Status.java
   trunk/main/lang/part/src/main/net/dpml/runtime/package-info.java
   trunk/main/lang/part/src/main/net/dpml/state/
   trunk/main/lang/part/src/main/net/dpml/state/Action.java
   trunk/main/lang/part/src/main/net/dpml/state/ApplyAction.java
   trunk/main/lang/part/src/main/net/dpml/state/ExecAction.java
   trunk/main/lang/part/src/main/net/dpml/state/IntegrityRuntimeException.java
   trunk/main/lang/part/src/main/net/dpml/state/Interface.java
   trunk/main/lang/part/src/main/net/dpml/state/Operation.java
   trunk/main/lang/part/src/main/net/dpml/state/State.java
   trunk/main/lang/part/src/main/net/dpml/state/StateEvent.java
   trunk/main/lang/part/src/main/net/dpml/state/StateListener.java
   trunk/main/lang/part/src/main/net/dpml/state/StateMachine.java
   trunk/main/lang/part/src/main/net/dpml/state/Transition.java
   trunk/main/lang/part/src/main/net/dpml/state/Trigger.java
   trunk/main/lang/part/src/main/net/dpml/state/TriggerPolicy.java
   trunk/main/lang/part/src/main/net/dpml/state/UnknownOperationException.java
   trunk/main/lang/part/src/main/net/dpml/state/UnknownTransitionException.java
   trunk/main/lang/part/src/main/net/dpml/state/package-info.java
   trunk/main/lang/part/src/test/
   trunk/main/lang/part/src/test/META-INF/
   trunk/main/lang/part/src/test/META-INF/services/
   trunk/main/lang/part/src/test/META-INF/services/org.acme.Gizmo
   trunk/main/lang/part/src/test/META-INF/services/org.acme.Widget
   trunk/main/lang/part/src/test/Widget.java
   trunk/main/lang/part/src/test/dpml/
   trunk/main/lang/part/src/test/dpml/lang/
   trunk/main/lang/part/src/test/dpml/lang/AbstractTestCase.java
   trunk/main/lang/part/src/test/dpml/lang/ConstructTestCase.java
   trunk/main/lang/part/src/test/dpml/lang/ContextTestCase.java
   trunk/main/lang/part/src/test/net/
   trunk/main/lang/part/src/test/net/dpml/
   trunk/main/lang/part/src/test/net/dpml/runtime/
   trunk/main/lang/part/src/test/net/dpml/runtime/AbstractTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/composition/
   trunk/main/lang/part/src/test/net/dpml/runtime/composition/CompositeTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/composition/ControllerTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/composition/GenericTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/composition/LookupTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/composition/SelectTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/context/
   trunk/main/lang/part/src/test/net/dpml/runtime/context/ArrayTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/context/ContextualTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/isolation/
   trunk/main/lang/part/src/test/net/dpml/runtime/isolation/SampleTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/lifecycle/
   trunk/main/lang/part/src/test/net/dpml/runtime/lifecycle/StateTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/
   trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/SingletonTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/TransientTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/profile/
   trunk/main/lang/part/src/test/net/dpml/runtime/profile/ProfileTestCase.java
   trunk/main/lang/part/src/test/net/dpml/runtime/service/
   trunk/main/lang/part/src/test/net/dpml/runtime/service/ForeignTestCase.java
   trunk/main/lang/part/src/test/org/
   trunk/main/lang/part/src/test/org/acme/
   trunk/main/lang/part/src/test/org/acme/ArrayWidget.java
   trunk/main/lang/part/src/test/org/acme/CompositeComponent.java
   trunk/main/lang/part/src/test/org/acme/ContextualWidget.java
   trunk/main/lang/part/src/test/org/acme/ControllerComponent.java
   trunk/main/lang/part/src/test/org/acme/DefaultGizmo.java
   trunk/main/lang/part/src/test/org/acme/DefaultWidget.java
   trunk/main/lang/part/src/test/org/acme/ForeignWidget.java
   trunk/main/lang/part/src/test/org/acme/GenericComponent.java
   trunk/main/lang/part/src/test/org/acme/Gizmo.java
   trunk/main/lang/part/src/test/org/acme/GizmoAdapter.java
   trunk/main/lang/part/src/test/org/acme/Parameterizable.java
   trunk/main/lang/part/src/test/org/acme/Sample.java
   trunk/main/lang/part/src/test/org/acme/SelectComponent.java
   trunk/main/lang/part/src/test/org/acme/SingletonWidget.java
   trunk/main/lang/part/src/test/org/acme/StandaloneWidget.java
   trunk/main/lang/part/src/test/org/acme/StandaloneWidget.xprofile
   trunk/main/lang/part/src/test/org/acme/StandaloneWidgetAdapter.java
   trunk/main/lang/part/src/test/org/acme/StateWidget.java
   trunk/main/lang/part/src/test/org/acme/StateWidget.xgraph
   trunk/main/lang/part/src/test/org/acme/TransientWidget.java
   trunk/main/lang/part/src/test/org/acme/Widget.java
   trunk/main/lang/part/src/test/org/acme/WidgetUsingGizmo.java
   trunk/main/lang/sample/
   trunk/main/lang/sample/etc/
   trunk/main/lang/sample/etc/component.xml
   trunk/main/lang/sample/project.xml
   trunk/main/lang/sample/src/
   trunk/main/lang/sample/src/main/
   trunk/main/lang/sample/src/main/org/
   trunk/main/lang/sample/src/main/org/acme/
   trunk/main/lang/sample/src/main/org/acme/AnotherContext.java
   trunk/main/lang/sample/src/main/org/acme/Hello.java
   trunk/main/lang/sample/src/main/org/acme/HelloComponent.java
   trunk/main/lang/sample/src/main/org/acme/HelloComponent.xgraph
   trunk/main/lang/sample/src/main/org/acme/HelloConfiguration.java
Modified:
   trunk/main/lang/module.xml
   trunk/main/lang/part/bootstrap.properties
   trunk/main/lang/part/bootstrap.xml
   trunk/main/lang/part/build.xml
Log:
SDK 2.X staged commit.

Modified: trunk/main/lang/module.xml
===================================================================
--- trunk/main/lang/module.xml	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/module.xml	2007-02-09 01:29:45 UTC (rev 1859)
@@ -1,92 +1,12 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
-<module name="lang" xmlns="link:xsd:dpml/lang/dpml-module#1.0">
+<module name="lang" xmlns="dpml:library">
    
   <properties>
-    <property name="project.micro.version" value="0"/>
+    <property name="project.javac.lint" value="unchecked"/>
   </properties>
 
-  <project name="dpml-module" basedir="module">
-    <info title="DPML Library XSD Schema">
-      <description>Formal XML specification of the index, module, project and resource elements.</description>
-    </info>
-    <types>
-      <type id="xsd" version="1.0"/>
-    </types>
-    <filters>
-      <feature token="PROJECT-XSD-URI" id="uri" type="xsd"/>
-      <feature token="PROJECT-XSD-SPEC-URI" id="uri" type="xsd" alias="true"/>
-    </filters>
-  </project>
+  <project file="part/project.xml"/>
+  <!--<project file="library/project.xml"/>-->
+  <project file="sample/project.xml"/>
 
-  <project name="dpml-part" basedir="part">
-    <info title="DPML Part XSD Schema">
-      <description>Formal XML specification of a part deployment unit.</description>
-    </info>
-    <types>
-      <type id="xsd" version="1.0"/>
-    </types>
-    <dependencies>
-      <build>
-        <include key="dpml-module"/>
-      </build>
-    </dependencies>
-    <filters>
-      <feature token="MODULE-XSD-SPEC-URI" id="uri" type="xsd" ref="dpml/lang/dpml-module" alias="true"/>
-      <feature token="PROJECT-XSD-SPEC-URI" id="uri" type="xsd" alias="true"/>
-    </filters>
-  </project>
-
-  <project name="dpml-state" basedir="state">
-    <info title="DPML State XSD Schema">
-      <description>Formal XML specification of a state transition model.</description>
-    </info>
-    <types>
-      <type id="xsd" version="1.0"/>
-    </types>
-    <filters>
-      <feature token="PROJECT-XSD-URI" id="uri" type="xsd" alias="true"/>
-    </filters>
-  </project>
-   
-  <project name="dpml-component" basedir="component">
-    <info title="DPML State XSD Schema">
-      <description>Formal XML specification of the Metro component descriptors and deployment directives.</description>
-    </info>
-    <types>
-      <type id="xsd" version="1.0"/>
-    </types>
-    <dependencies>
-      <build>
-        <include key="dpml-part"/>
-        <include key="dpml-type"/>
-      </build>
-    </dependencies>
-    <filters>
-      <feature token="PROJECT-XSD-LINK-URI" id="uri" type="xsd" alias="true"/>
-      <feature token="PART-XSD-LINK-URI" id="uri" type="xsd" ref="dpml/lang/dpml-part" alias="true"/>
-      <feature token="TYPE-XSD-URI" id="uri" type="xsd" ref="dpml/lang/dpml-type" alias="true"/>
-      <feature token="MODULE-XSD-SPEC-URI" id="uri" type="xsd" ref="dpml/lang/dpml-module" alias="true"/>
-    </filters>
-  </project>
-
-  <project name="dpml-type" basedir="type">
-    <info title="DPML Type XSD Schema">
-      <description>Formal XML specification of the Metro component type descriptors.</description>
-    </info>
-    <types>
-      <type id="xsd" version="1.0"/>
-    </types>
-    <dependencies>
-      <build>
-        <include key="dpml-state"/>
-        <include key="dpml-part"/>
-      </build>
-    </dependencies>
-    <filters>
-      <feature token="PROJECT-XSD-URI" id="uri" type="xsd" alias="true"/>
-      <feature token="PART-XSD-URI" id="uri" type="xsd" ref="dpml/lang/dpml-part" alias="true"/>
-      <feature token="STATE-XSD-URI" id="uri" type="xsd" ref="dpml/lang/dpml-state" alias="true"/>
-    </filters>
-  </project>
-
 </module>

Modified: trunk/main/lang/part/bootstrap.properties
===================================================================
--- trunk/main/lang/part/bootstrap.properties	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/bootstrap.properties	2007-02-09 01:29:45 UTC (rev 1859)
@@ -1,2 +1,5 @@
 
+home = ../..
+project.test.fork = true
+
 specification.version = 1.0

Modified: trunk/main/lang/part/bootstrap.xml
===================================================================
--- trunk/main/lang/part/bootstrap.xml	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/bootstrap.xml	2007-02-09 01:29:45 UTC (rev 1859)
@@ -18,30 +18,180 @@
   limitations under the License.
 -->
 
-<project name="dpml-part" default="install" basedir=".">
+<project name="dpml-lang-part" default="install" basedir=".">
 
   <property name="project.group" value="dpml/lang"/>
-  <property name="project.name" value="dpml-part"/>
-
+  <property name="project.name" value="dpml-lang-part"/>
+  
   <property file="${basedir}/bootstrap.properties"/>
-  <property name="home" value="../.."/>
+  <property file="${home}/bootstrap.properties"/>
   <import file="${home}/bootstrap.xml"/>
+    
+  <target name="setup-path" depends="init">
+    <property name="transit.jar.path" 
+        location="${dpml.local.cache}/dpml/transit/jars/dpml-transit-main-${project.version}.jar"/>
+    <path id="project.main.path">
+      <pathelement location="${transit.jar.path}"/>
+      <pathelement location="${target.classes.dir}"/>
+    </path>
+    <path id="project.test.path">
+      <pathelement location="${transit.jar.path}"/>
+      <pathelement location="${ENV.ANT_HOME}/lib/ant.jar"/>
+      <pathelement location="${ENV.ANT_HOME}/lib/ant-junit.jar"/>
+      <pathelement location="${target.deliverables.jars.dir}/${project.filename}"/>
+      <pathelement location="${dpml.local.cache}/junit/jars/${junit.filename}"/>
+    </path>
+  </target>
 
   <target name="init" depends="bootstrap.init">
-    <property name="xsd.spec.uri" value="link:xsd:${project.group}/${project.name}#${specification.version}"/>
-    <filter token="MODULE-XSD-SPEC-URI" value="link:xsd:dpml/lang/dpml-module#${specification.version}"/>
-    <filter token="PROJECT-XSD-SPEC-URI" value="${xsd.spec.uri}"/>
+    <filter token="PROJECT-NAME" value="${project.name}"/>
+    <filter token="PROJECT-GROUP" value="${project.group}"/>
+    <filter token="PROJECT-VERSION" value="${project.version}"/>
+    <filter token="PART-XSD-SPEC-URI" value="link:xsd:${project.group}/dpml-lang-part"/>
+    <filter token="COMPONENT-XSD-SPEC-URI" value="link:xsd:${project.group}/dpml-lang-component"/>
+    <filter token="RESOURCE-NAMESPACE" value="link:xsd:${project.group}/dpml-lang-resource"/>
+    <filter token="DEPOT-CLASSLOADER-CLASS" value="dpml.util.SystemClassLoader"/>
+    <filter token="DEPOT-MAIN-CLASS" value="dpml.util.Main"/>
   </target>
 
   <target name="package" depends="bootstrap.package">
     <property name="xsds" location="${target.deliverables.dir}/xsds"/>
     <mkdir dir="${xsds}"/>
+    <!--
+    Copy part XSD to deliverables and classes.
+    -->
     <property name="filename" value="${project.name}-${project.version}.xsd"/>
-    <copy toFile="${xsds}/${filename}" preservelastmodified="true" overwrite="true" 
-      file="${target.dir}/part.xsd"/>
+    <copy file="${target.dir}/xsds/part.xsd" 
+      toFile="${xsds}/${filename}" preservelastmodified="true" overwrite="true"/>
+    <mkdir dir="${target.dir}/classes/main/${project.group}"/>
+    <copy file="${target.dir}/xsds/part.xsd" 
+      toFile="${target.dir}/classes/main/${project.group}/${project.name}.xsd" 
+      preservelastmodified="true" overwrite="true"/>
     <checksum fileext=".md5" file="${xsds}/${filename}"/>
-    <echo file="${xsds}/${project.name}-${specification.version}.xsd.link"
+    <echo file="${xsds}/${project.name}.xsd.link"
       message="artifact:xsd:${project.group}/${project.name}#${project.version}"/>
+    <mkdir dir="${target.deliverables.jars.dir}"/>
+    <!--
+    Copy state XSD to deliverables and classes.
+    -->
+    <property name="state.filename" value="dpml-lang-state-${project.version}.xsd"/>
+    <copy file="${target.dir}/xsds/state.xsd" 
+      toFile="${xsds}/${state.filename}" preservelastmodified="true" overwrite="true"/>
+    <mkdir dir="${target.dir}/classes/main/${project.group}"/>
+    <copy file="${target.dir}/xsds/state.xsd" 
+      toFile="${target.dir}/classes/main/${project.group}/dpml-lang-state.xsd" 
+      preservelastmodified="true" overwrite="true"/>
+    <checksum fileext=".md5" file="${xsds}/${state.filename}"/>
+    <echo file="${xsds}/dpml-lang-state.xsd.link"
+      message="artifact:xsd:${project.group}/dpml-lang-state#${project.version}"/>
+    <!--
+    Copy component XSD to deliverables and classes.
+    -->
+    <property name="component.filename" value="dpml-lang-component-${project.version}.xsd"/>
+    <copy file="${target.dir}/xsds/component.xsd" 
+      toFile="${xsds}/${component.filename}" preservelastmodified="true" overwrite="true"/>
+    <mkdir dir="${target.dir}/classes/main/${project.group}"/>
+    <copy file="${target.dir}/xsds/component.xsd" 
+      toFile="${target.dir}/classes/main/${project.group}/dpml-lang-component.xsd" 
+      preservelastmodified="true" overwrite="true"/>
+    <checksum fileext=".md5" file="${xsds}/${component.filename}"/>
+    <echo file="${xsds}/dpml-lang-component.xsd.link"
+      message="artifact:xsd:${project.group}/dpml-lang-component#${project.version}"/>
+    <!--
+    Copy resource XSD to deliverables and classes.
+    -->
+    <property name="resource.filename" value="dpml-lang-resource-${project.version}.xsd"/>
+    <copy file="${target.dir}/xsds/resource.xsd" 
+      toFile="${xsds}/${resource.filename}" preservelastmodified="true" overwrite="true"/>
+    <mkdir dir="${target.dir}/classes/main/${project.group}"/>
+    <copy file="${target.dir}/xsds/resource.xsd" 
+      toFile="${target.dir}/classes/main/${project.group}/dpml-lang-resource.xsd" 
+      preservelastmodified="true" overwrite="true"/>
+    <checksum fileext=".md5" file="${xsds}/${resource.filename}"/>
+    <echo file="${xsds}/dpml-lang-resource.xsd.link"
+      message="artifact:xsd:${project.group}/dpml-lang-resource#${project.version}"/>
+    <!--
+    Copy library XSD to deliverables and classes.
+    -->
+    <property name="library.filename" value="dpml-lang-library-${project.version}.xsd"/>
+    <copy file="${target.dir}/xsds/library.xsd" 
+      toFile="${xsds}/${library.filename}" preservelastmodified="true" overwrite="true"/>
+    <mkdir dir="${target.dir}/classes/main/${project.group}"/>
+    <copy file="${target.dir}/xsds/library.xsd" 
+      toFile="${target.dir}/classes/main/${project.group}/dpml-lang-library.xsd" 
+      preservelastmodified="true" overwrite="true"/>
+    <checksum fileext=".md5" file="${xsds}/${library.filename}"/>
+    <echo file="${xsds}/dpml-lang-library.xsd.link"
+      message="artifact:xsd:${project.group}/dpml-lang-library#${project.version}"/>
+    <!--
+    Create and publish the jar file.
+    -->
+    <mkdir dir="${target.deliverables.jars.dir}"/>
+    <jar destfile="${target.deliverables.jars.dir}/${project.filename}"
+       basedir="${target.classes.dir}" 
+       includes="**/*.*" excludes="**/*.html,**/*.png"
+       index="true">
+       <manifest>
+         <attribute name="Created-By" value="The Digital Product Management Laboratory."/>
+         <attribute name="Built-By" value="${user.name}"/>
+         <attribute name="Extension-Name" value="${project.name}"/>
+         <attribute name="Specification-Vendor" value="DPML"/>
+         <attribute name="Specification-Version" value="${project.specification.version}"/>
+         <attribute name="Implementation-Vendor" value="DPML"/>
+         <attribute name="Implementation-Vendor-Id" value="net.dpml"/>
+         <attribute name="Implementation-Version" value="${project.version}"/>
+         <attribute name="Main-Class" value="dpml.util.Main"/>
+       </manifest>
+    </jar>
+    <echo file="${target.deliverables.jars.dir}/${project.name}.jar.link"
+      message="artifact:jar:${project.group}/${project.name}#${project.version}"/>
+    <checksum fileext=".md5" file="${target.deliverables.jars.dir}/${project.filename}"/>
+    <delete file="${target.deliverables.jars.dir}/${project.filename}.asc"/>
+    <antcall target="execute.jar.asc"/>
   </target>
 
+  <target name="install" depends="bootstrap.install">
+    <echo>
+#----------------------------------------------------------------------------------
+# Updating Ant. ${user.home}/.ant/lib
+#----------------------------------------------------------------------------------
+    </echo>
+    <!--
+    <copy tofile="${user.home}/.ant/lib/dpml-lang-part.jar"
+      file="${target.deliverables.jars.dir}/${project.name}-${project.version}.jar"/>
+    -->
+    <property name="lib" location="${dpml.system}/lib"/>
+    <property name="short.filename" value="${project.name}.jar"/>
+    <property name="long.filename" value="${project.name}-${project.version}.jar"/>
+    <mkdir dir="${lib}/ext"/>
+    <echo>
+#----------------------------------------------------------------------------------
+# Updating DPML Lib ${lib}/ext
+#----------------------------------------------------------------------------------
+    </echo>
+    <!--
+    <copy toFile="${lib}/ext/${short.filename}" preservelastmodified="true" overwrite="true" 
+      file="${target.deliverables.jars.dir}/${long.filename}"/>
+    -->
+    <echo>
+#----------------------------------------------------------------------------------
+# Updating ${dpml.system}/bin
+#----------------------------------------------------------------------------------
+    </echo>
+    <mkdir dir="${dpml.system}/bin"/>
+    <copy todir="${dpml.system}" preservelastmodified="true" overwrite="true">
+      <fileset dir="target">
+        <include name="bin/**"/>
+      </fileset>
+    </copy>
+    <chmod perm="755">
+      <fileset dir="${dpml.system}/bin">
+        <include name="**/*.sh"/>
+        <include name="**/depot"/>
+      </fileset>
+    </chmod>
+    <property name="work" location="${dpml.data}/work"/>
+    <mkdir dir="${work}"/>
+  </target>
+
 </project>

Modified: trunk/main/lang/part/build.xml
===================================================================
--- trunk/main/lang/part/build.xml	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/build.xml	2007-02-09 01:29:45 UTC (rev 1859)
@@ -1,19 +1,101 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 
 <project name="dpml-part" default="install" basedir="." 
-    xmlns:transit="antlib:net.dpml.transit"
+    xmlns:transit="antlib:dpml.tools.transit"
     xmlns:x="dpml:depot" >
 
   <transit:import uri="local:template:dpml/tools/standard"/>
-
-  <target name="package" depends="standard.package">
-    <property name="target.file" location="${project.target.dir}/part.xsd"/>
-    <property name="xsds.dir" location="${project.deliverable.xsd.dir}"/>
-    <mkdir dir="${xsds.dir}"/>
-    <property name="filename" value="${project.name}-${project.version}.xsd"/>
-    <copy file="${target.file}" toFile="${project.deliverable.xsd.path}" 
+  
+  <target name="build" depends="standard.build">
+  
+    <!-- part.xsd -->
+    <!--
+    <property name="part.file" location="${project.target.dir}/xsds/part.xsd"/>
+    <mkdir dir="${project.deliverable.xsd.dir}"/>
+    <copy file="${part.file}" toFile="${project.deliverable.xsd.path}" 
         preservelastmodified="true" overwrite="true"/>
     <checksum fileext=".md5" file="${project.deliverable.xsd.path}"/>
+    <property name="packaged.dir" location="${project.target.classes.main.dir}/dpml/lang"/>
+    <mkdir dir="${packaged.dir}"/>
+    <copy file="${part.file}" toFile="${packaged.dir}/${project.name}.xsd" 
+        preservelastmodified="true" overwrite="true"/>
+    -->
+    <!-- state.xsd -->
+    
+    <!--
+    <property name="state.file" location="${project.target.dir}/xsds/state.xsd"/>
+    <mkdir dir="${project.deliverable.xsd.dir}"/>
+    <copy file="${state.file}" toFile="${project.deliverable.xsd#dpml-lang-state.path}" 
+        preservelastmodified="true" overwrite="true"/>
+    <checksum fileext=".md5" file="${project.deliverable.xsd#dpml-lang-state.path}"/>
+    <property name="packaged.dir" location="${project.target.classes.main.dir}/dpml/lang"/>
+    <mkdir dir="${packaged.dir}"/>
+    <copy file="${state.file}" toFile="${packaged.dir}/dpml-lang-state.xsd" 
+        preservelastmodified="true" overwrite="true"/>
+    -->
+        
+    <!-- component.xsd -->
+    
+    <!--
+    <property name="component.file" location="${project.target.dir}/xsds/component.xsd"/>
+    <mkdir dir="${project.deliverable.xsd.dir}"/>
+    <copy file="${component.file}" toFile="${project.deliverable.xsd#dpml-lang-component.path}" 
+        preservelastmodified="true" overwrite="true"/>
+    <checksum fileext=".md5" file="${project.deliverable.xsd#dpml-lang-component.path}"/>
+    <property name="packaged.dir" location="${project.target.classes.main.dir}/dpml/lang"/>
+    <mkdir dir="${packaged.dir}"/>
+    <copy file="${component.file}" toFile="${packaged.dir}/dpml-lang-component.xsd" 
+        preservelastmodified="true" overwrite="true"/>
+    -->
+        
+    <!-- resource.xsd -->
+    
+    <!--
+    <property name="resource.file" location="${project.target.dir}/xsds/resource.xsd"/>
+    <mkdir dir="${project.deliverable.xsd.dir}"/>
+    <copy file="${resource.file}" toFile="${project.deliverable.xsd#dpml-lang-resource.path}" 
+        preservelastmodified="true" overwrite="true"/>
+    <checksum fileext=".md5" file="${project.deliverable.xsd#dpml-lang-resource.path}"/>
+    <property name="packaged.dir" location="${project.target.classes.main.dir}/dpml/lang"/>
+    <mkdir dir="${packaged.dir}"/>
+    <copy file="${resource.file}" toFile="${packaged.dir}/dpml-lang-resource.xsd" 
+        preservelastmodified="true" overwrite="true"/>
+    -->
+        
+    <!-- library.xsd -->
+    
+    <!--
+    <property name="library.file" location="${project.target.dir}/xsds/library.xsd"/>
+    <mkdir dir="${project.deliverable.xsd.dir}"/>
+    <copy file="${library.file}" toFile="${project.deliverable.xsd#dpml-lang-library.path}" 
+        preservelastmodified="true" overwrite="true"/>
+    <checksum fileext=".md5" file="${project.deliverable.xsd#dpml-lang-library.path}"/>
+    <property name="packaged.dir" location="${project.target.classes.main.dir}/dpml/lang"/>
+    <mkdir dir="${packaged.dir}"/>
+    <copy file="${library.file}" toFile="${packaged.dir}/dpml-lang-library.xsd" 
+        preservelastmodified="true" overwrite="true"/>
+    -->
+        
   </target>
 
+  <target name="update">
+    <echo>
+#----------------------------------------------------------------------------------
+# Updating ${dpml.share}/bin
+#----------------------------------------------------------------------------------
+    </echo>
+    <mkdir dir="${dpml.share}/bin"/>
+    <copy todir="${dpml.share}" preservelastmodified="true" overwrite="true">
+      <fileset dir="target">
+        <include name="bin/**"/>
+      </fileset>
+    </copy>
+    <chmod perm="755">
+      <fileset dir="${dpml.share}/bin">
+        <include name="**/*.sh"/>
+        <include name="**/depot"/>
+      </fileset>
+    </chmod>
+  </target>
+
 </project>

Added: trunk/main/lang/part/project.xml
===================================================================
--- trunk/main/lang/part/project.xml	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/project.xml	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<project xmlns="dpml:library" name="dpml-lang-part">
+
+  <info title="DPML Part Content Handler">
+    <description>Part content handler for the Transit system.</description>
+  </info>
+  
+  <properties>
+    <property name="project.package.include-in-classes" value="true"/>
+  </properties>
+  
+  <types>
+    <type id="xsd" alias="true" source="etc/xsds/part.xsd"/>
+    <type id="xsd" alias="true" name="dpml-lang-state" source="etc/xsds/state.xsd"/>
+    <type id="xsd" alias="true" name="dpml-lang-component" source="etc/xsds/component.xsd"/>
+    <type id="xsd" alias="true" name="dpml-lang-resource" source="etc/xsds/resource.xsd"/>
+    <type id="xsd" alias="true" name="dpml-lang-library" source="etc/xsds/library.xsd"/>
+    <type id="jar" alias="true"/>
+  </types>
+  
+  <dependencies>
+    <runtime>
+      <include ref="dpml/transit/dpml-transit-main"/>
+    </runtime>
+    <test>
+      <include ref="org/apache/ant/ant-junit"/>
+    </test>
+  </dependencies>
+  
+  <filters>
+    <feature token="COMPONENT-XSD-SPEC-URI" id="uri" type="xsd#dpml-lang-component" alias="true"/>
+  </filters>
+
+</project>
+

Added: trunk/main/lang/part/src/main/dpml/appliance/AbstractAppliance.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/appliance/AbstractAppliance.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/appliance/AbstractAppliance.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2006-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.appliance;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.MBeanException;
+import javax.management.InstanceAlreadyExistsException;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceListener;
+import net.dpml.appliance.ApplianceEvent;
+import net.dpml.appliance.ApplianceException;
+import net.dpml.appliance.ApplianceManager;
+
+import net.dpml.lang.Strategy;
+
+import net.dpml.runtime.Component;
+import net.dpml.runtime.ComponentEvent;
+import net.dpml.runtime.ComponentListener;
+import net.dpml.runtime.Provider;
+import net.dpml.runtime.ProviderEvent;
+import net.dpml.runtime.Status;
+
+import net.dpml.state.State;
+import net.dpml.state.StateEvent;
+import net.dpml.state.StateListener;
+
+import net.dpml.util.Logger;
+
+/**
+ * Remote adapter to a component.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public abstract class AbstractAppliance extends UnicastRemoteObject
+{
+    protected void setShutdownHook( final Appliance appliance )
+    {
+        Runtime.getRuntime().addShutdownHook(
+          new Thread()
+          {
+              public void run()
+              {
+                  try
+                  {
+                      appliance.decommission();
+                      UnicastRemoteObject.unexportObject( appliance, false );
+                  }
+                  catch( Throwable e )
+                  {
+                  }
+              }
+          }
+        );
+    }
+    
+    private final Logger m_logger;
+    private final URI m_codebase;
+    private final Set<ApplianceListener> m_listeners = new CopyOnWriteArraySet<ApplianceListener>();
+    private final ExecutorService m_queue = Executors.newSingleThreadExecutor();
+
+    private boolean m_commissioned = false;
+    
+    public AbstractAppliance( final Logger logger, final URI uri ) throws IOException
+    {
+        super();
+        
+        if( null == uri )
+        {
+            String spec = System.getProperty( "dpml.appliance.codebase.uri", null );
+            if( null != spec )
+            {
+                m_codebase = URI.create( spec );
+            }
+            else
+            {
+                m_codebase = null;
+            }
+        }
+        else
+        {
+            m_codebase = uri;
+        }
+        m_logger = logger;
+    }
+    
+    public String getCodebaseURI()
+    {
+        return m_codebase.toASCIIString();
+    }
+    
+   /**
+    * Add a listener to the component.
+    * @param listener the component listener
+    */
+    public void addApplianceListener( ApplianceListener listener )
+    {
+        m_listeners.add( listener );
+    }
+    
+   /**
+    * Remove a listener from the component.
+    * @param listener the component listener
+    */
+    public void removeApplianceListener( ApplianceListener listener )
+    {
+        m_listeners.remove( listener );
+    }
+    
+    public boolean isCommissioned()
+    {
+        synchronized( this )
+        {
+            return m_commissioned;
+        }
+    }
+    
+    public void commission() throws IOException
+    {
+        synchronized( this )
+        {
+            m_commissioned = true;
+        }
+    }
+    
+    public void decommission() throws RemoteException
+    {
+        decommission( 10, TimeUnit.SECONDS );
+    }
+    
+    protected void decommission( long timeout, TimeUnit units ) throws RemoteException
+    {
+        synchronized( this )
+        {
+            if( !m_commissioned )
+            {
+                return;
+            }
+            try
+            {
+                m_queue.shutdown();
+                boolean ok = m_queue.awaitTermination( timeout, units );
+                if( !ok )
+                {
+                    final String message = 
+                      "A decommissioning timout (some events from may not have been processed).";
+                    getLogger().warn( message );
+                }
+            }
+            catch( Exception e )
+            {
+                e.printStackTrace();
+            }
+            finally
+            {
+                m_commissioned = false;
+            }
+        }
+    }
+    
+    protected Logger getLogger()
+    {
+        return m_logger;
+    }
+    
+    protected void processEvent( ApplianceEvent event )
+    {
+        Logger logger= getLogger();
+        for( ApplianceListener listener : m_listeners )
+        {
+            m_queue.execute( new ApplianceEventDistatcher( logger, listener, event ) );
+        }
+    }
+    
+    private static class ApplianceEventDistatcher implements Runnable
+    {
+        private Logger m_logger;
+        private ApplianceListener m_listener;
+        private ApplianceEvent m_event;
+        
+        ApplianceEventDistatcher( Logger logger, ApplianceListener listener, ApplianceEvent event )
+        {
+            m_logger = logger;
+            m_listener = listener;
+            m_event = event;
+        }
+        
+        public void run()
+        {
+            try
+            {
+                m_listener.applianceChanged( m_event );
+            }
+            catch( Throwable e )
+            {
+                final String error = 
+                  "Event distatch error.";
+                m_logger.error( error, e );
+            }
+        }
+    }
+}
+

Added: trunk/main/lang/part/src/main/dpml/appliance/ApplianceHelper.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/appliance/ApplianceHelper.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/appliance/ApplianceHelper.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2006-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.appliance;
+
+import dpml.util.PropertyResolver;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Properties;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceException;
+import net.dpml.appliance.ApplianceFactory;
+
+import net.dpml.transit.Artifact;
+import net.dpml.transit.Transit;
+import net.dpml.transit.ContentHandler;
+
+
+/**
+ * Remote adapter to a component.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ApplianceHelper
+{
+    public static Appliance newAppliance( URI uri ) throws IOException
+    {
+        String partition = getPartition();
+        return newAppliance( partition, uri );
+    }
+    
+    public static Appliance newAppliance( String partition, URI uri ) throws IOException
+    {
+        Artifact artifact = Artifact.createArtifact( uri );
+        String type = artifact.getType();
+        ContentHandler handler = Transit.getInstance().getContentHandler( type );
+        if( null == handler )
+        {
+            final String error = 
+              "No content handler found for the type ["
+              + type
+              + "] referenced by the uri ["
+              + uri 
+              + "]";
+            throw new ApplianceException( error, null );
+        }
+        if( handler instanceof ApplianceFactory )
+        {
+            URL url = artifact.toURL();
+            URLConnection connection = url.openConnection();
+            ApplianceFactory factory = (ApplianceFactory) handler;
+            return factory.newAppliance( connection, partition );
+        }
+        else
+        {
+            final String error = 
+              "Content type ["
+              + type
+              + "] referenced by the uri ["
+              + uri 
+              + "] does not support appliance production.";
+            throw new ApplianceException( error, null );
+        }
+    }
+    
+    private static String getPartition()
+    {
+        String partition = System.getProperty( "dpml.station.partition", null );
+        Properties system = System.getProperties();
+        return PropertyResolver.resolve( system, partition );
+    }
+}
+

Added: trunk/main/lang/part/src/main/dpml/appliance/StandardAppliance.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/appliance/StandardAppliance.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/appliance/StandardAppliance.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2006-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.appliance;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.MBeanException;
+import javax.management.InstanceAlreadyExistsException;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceListener;
+import net.dpml.appliance.ApplianceEvent;
+import net.dpml.appliance.ApplianceException;
+import net.dpml.appliance.ApplianceManager;
+
+import net.dpml.lang.Strategy;
+
+import net.dpml.runtime.Component;
+import net.dpml.runtime.ComponentEvent;
+import net.dpml.runtime.ComponentListener;
+import net.dpml.runtime.Provider;
+import net.dpml.runtime.ProviderEvent;
+import net.dpml.runtime.Status;
+
+import net.dpml.state.State;
+import net.dpml.state.StateEvent;
+import net.dpml.state.StateListener;
+
+import net.dpml.util.Logger;
+
+/**
+ * Remote adapter to a component.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StandardAppliance extends AbstractAppliance implements Appliance, ApplianceManager
+{
+    private final Component m_component;
+    private final ComponentListener m_listener; 
+    
+    private Provider m_provider;
+    private Object m_instance;
+    
+    public StandardAppliance( 
+      final Logger logger, final Component component ) throws IOException
+    {
+        super( logger, null );
+        
+        m_component = component;
+        m_listener = new InternalComponentListener( this );
+        m_component.addComponentListener( m_listener );
+        setShutdownHook( this );
+    }
+    
+   /**
+    * Return a value assignable to the supplied remote type or null if the type
+    * cannot be resolved from this strategy.
+    * @param c the target class
+    * @return an instance of the class or null
+    * @exception IOException if an IO error occurs
+    */
+    public <T>T getContentForClass( Class<T> c ) throws IOException
+    {
+        if( null == m_instance )
+        {
+            throw new IllegalStateException( "Appliance has not been commissioned." );
+        }
+        else
+        {
+            if( c.isAssignableFrom( m_instance.getClass() ) )
+            {
+                return c.cast( m_instance );
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+
+
+    public void commission() throws IOException
+    {
+        synchronized( m_component )
+        {
+            super.commission();
+            if( getLogger().isInfoEnabled() )
+            {
+                getLogger().info( "commissioning " + m_component.getName() );
+            }
+            m_provider = m_component.getProvider();
+            m_instance = m_provider.getInstance( Object.class );
+        }
+    }
+    
+    protected void decommission( long timeout, TimeUnit units ) throws RemoteException
+    {
+        synchronized( m_component )
+        {
+            if( !isCommissioned() )
+            {
+                return;
+            }
+            if( getLogger().isInfoEnabled() )
+            {
+                getLogger().info( "decommissioning " + m_component.getName() );
+            }
+            if( null != m_provider )
+            {
+                m_component.release( m_provider );
+            }
+            m_provider = null;
+            m_instance = null;
+            m_component.terminate();
+            m_component.removeComponentListener( m_listener );
+            super.decommission( timeout, units );
+        }
+    }
+    
+    /*
+    public void stateChanged( final StateEvent event ) throws RemoteException
+    {
+        State from = event.getFromState();
+        State to = event.getToState();
+        if( getLogger().isDebugEnabled() )
+        {
+            String name = m_component.getName();
+            getLogger().debug( 
+              "transitioning [" 
+              + name 
+              + "] from [" 
+              + from.getName() 
+              + "] to [" 
+              + to.getName() 
+              + "]" );
+        }
+    }
+    */
+
+    private class InternalComponentListener implements ComponentListener
+    {
+        private Appliance m_appliance;
+        
+        InternalComponentListener( Appliance appliance )
+        {
+            m_appliance = appliance;
+        }
+        
+       /**
+        * Event within the component.
+        *
+        * @param event the component event
+        */
+        public void componentChanged( final ComponentEvent event )
+        {
+            if( event instanceof ProviderEvent )
+            {
+                ProviderEvent e = (ProviderEvent) event;
+                Status status = e.getStatus();
+                ApplianceEvent ae = new ApplianceEvent( m_appliance, status );
+                processEvent( ae );
+            }
+        }
+    }
+}
+

Added: trunk/main/lang/part/src/main/dpml/lang/Classpath.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/Classpath.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/Classpath.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.util.Arrays;
+
+import javax.xml.XMLConstants;
+
+import dpml.util.Category;
+import net.dpml.lang.Strategy;
+import net.dpml.lang.Buffer;
+
+import net.dpml.util.Logger;
+
+import dpml.util.ObjectUtils;
+
+/**
+ * Immutable datastructure defining a classloader stack.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class Classpath
+{
+    private final URI[] m_system;
+    private final URI[] m_public;
+    private final URI[] m_protected;
+    private final URI[] m_private;
+    private final Classpath m_base;
+    
+   /**
+    * Creation of a empty classpath definition.
+    */
+    public Classpath()
+    {
+        this( new URI[0], new URI[0], new URI[0], new URI[0] );
+    }
+    
+   /**
+    * Creation of a new classpath definition.
+    * @param base the base classpath from which this classpath is derived
+    * @param extension the extended classpath definition
+    */
+    public Classpath( final Classpath base, final Classpath extension )
+    {
+        if( null == extension )
+        {
+            throw new NullPointerException( "extension" );
+        }
+        m_base = base;
+        m_system = extension.m_system;
+        m_public = extension.m_public;
+        m_protected = extension.m_protected;
+        m_private = extension.m_private;
+    }
+    
+   /**
+    * Creation of a new classpath definition.
+    * @param systemUris an array of uris representing the system classpath extensions
+    * @param publicUris an array of uris representing the public classpath entries
+    * @param protectedUris an array of uris representing protected classpath entries
+    * @param privateUris an array of uris representing private classpath entries
+    */
+    public Classpath( 
+      URI[] systemUris, URI[] publicUris, URI[] protectedUris, URI[] privateUris )
+    {
+        this( null, systemUris, publicUris, protectedUris, privateUris );
+    }
+    
+   /**
+    * Creation of a new classpath definition.
+    * @param base super classpath (may be null)
+    * @param systemUris an array of uris representing the system classpath extensions
+    * @param publicUris an array of uris representing the public classpath entries
+    * @param protectedUris an array of uris representing protected classpath entries
+    * @param privateUris an array of uris representing private classpath entries
+    */
+    public Classpath( 
+      Classpath base, URI[] systemUris, URI[] publicUris, URI[] protectedUris, URI[] privateUris )
+    {
+        m_base = base;
+        if( null == systemUris )
+        {
+            m_system = new URI[0];
+        }
+        else
+        {
+            m_system = systemUris;
+        }
+        
+        if( null == publicUris )
+        {
+            m_public = new URI[0];
+        }
+        else
+        {
+            m_public = publicUris;
+        }
+        
+        if( null == protectedUris )
+        {
+            m_protected = new URI[0];
+        }
+        else
+        {
+            m_protected = protectedUris;
+        }
+        
+        if( null == privateUris )
+        {
+            m_private = new URI[0];
+        }
+        else
+        {
+            m_private = privateUris;
+        }
+    }
+    
+   /**
+    * Return the base classpath.
+    * @return the base classpath that this classpath extends (possibly null)
+    */
+    public Classpath getBaseClasspath()
+    {
+        return m_base;
+    }
+    
+   /**
+    * Return the classloader dependencies relative to a supplied classloader category.
+    *
+    * @param category the classloader category
+    * @return an array of uris defining the classloader classpath for the supplied category
+    */
+    public URI[] getDependencies( final Category category )
+    {
+        if( Category.SYSTEM.equals( category ) )
+        {
+            return m_system;
+        }
+        else if( Category.PUBLIC.equals( category ) )
+        {
+            return m_public;
+        }
+        else if( Category.PROTECTED.equals( category ) )
+        {
+            return m_protected;
+        }
+        else if( Category.PRIVATE.equals( category ) )
+        {
+            return m_private;
+        }
+        else
+        {
+            final String error = 
+              "Category not recognized."
+              + "\nCategory: " + category;
+            throw new IllegalArgumentException( error );
+        }
+    }
+    
+   /**
+    * Compare this object with another for equality.
+    * @param other the other object
+    * @return TRUE if equal else FALSE
+    */
+    public boolean equals( Object other )
+    {
+        if( other instanceof Classpath )
+        {
+            Classpath classpath = (Classpath) other;
+            if( !Arrays.equals( m_system, classpath.getDependencies( Category.SYSTEM ) ) )
+            {
+                return false;
+            }
+            if( !Arrays.equals( m_public, classpath.getDependencies( Category.PUBLIC ) ) )
+            {
+                return false;
+            }
+            if( !Arrays.equals( m_protected, classpath.getDependencies( Category.PROTECTED ) ) )
+            {
+                return false;
+            }
+            else
+            {
+                return Arrays.equals( m_private, classpath.getDependencies( Category.PRIVATE ) );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Return the hashcode for the plugin definition.
+    * @return the hash code
+    */
+    public int hashCode()
+    {
+        int hash = ObjectUtils.hashArray( m_system );
+        hash ^= ObjectUtils.hashArray( m_public );
+        hash ^= ObjectUtils.hashArray( m_protected );
+        hash ^= ObjectUtils.hashArray( m_private );
+        return hash;
+    }
+    
+   /**
+    * Return the classpath as a string.
+    * @return the string value
+    */
+    public String toString()
+    {
+        return "classpath: [" 
+          + m_system.length 
+          + ", " + m_public.length 
+          + ", " + m_protected.length 
+          + ", " + m_private.length
+          + "]";
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/Construct.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/Construct.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/Construct.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,1086 @@
+/*
+ * Copyright 2005-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import dpml.util.PropertyResolver;
+
+import java.beans.Expression;
+import java.io.Serializable;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Properties;
+
+import net.dpml.lang.Buffer;
+
+/**
+ * A object resolvable from primitive arguments.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class Construct implements Value, Serializable
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+   /**
+    * Utility operation that consolidates an array of values and supplimentary
+    * arguments to an array of objects.
+    * 
+    * @param map a map of keys and values used in symbolic target resolution
+    * @param params the value array
+    * @param args supplimentary arguments
+    * @return the consolidated argument array
+    * @exception Exception if an error occurs in argument resolution
+    */
+    public static Object[] getArgs( Map<String,Object> map, Value[] params, Object[] args ) throws Exception
+    {
+        ArrayList<Object> list = new ArrayList<Object>();
+        if( null != params )
+        {
+            for( int i=0; i < params.length; i++ )
+            {
+                Value value = params[i];
+                Object object = value.resolve( map );
+                if( null != object )
+                {
+                    list.add( object );
+                }
+            }
+        }
+        if( null != args )
+        {
+            for( int i=0; i < args.length; i++ )
+            {
+                Object value = args[i];
+                if( null != value )
+                {
+                    list.add( value );
+                }
+            }
+        }
+        return list.toArray();
+    }
+    
+    private final String m_method;
+    private final String m_target;
+    private final String m_value;
+    private final Value[] m_args;
+    private final boolean m_compound;
+    
+   /**
+    * Create a new construct using the default java.lang.String class as the base type.
+    * @param value the construct value
+    */
+    public Construct( String value )
+    {
+        this( null, null, value );
+    }
+
+   /**
+    * Create a new construct using a supplied target defintion.  The target argument 
+    * may be either a classname or a symbolic reference in the form ${[key]}.  If the 
+    * argument is symbolic it resolved relative to a context map supplied by the 
+    * application resolving construct values.
+    *
+    * @param target a classname or symbolic reference
+    * @param value the construct value
+    */
+    public Construct( String target, String value )
+    {
+        this( target, null, value );
+    }
+
+   /**
+    * Create a new construct using a supplied target defintion.  The target argument 
+    * may be either a classname or a symbolic reference in the form ${[key]}.  If the 
+    * argument is symbolic it is resolved relative to a context map supplied by the 
+    * application resolving construct values.  If the construct value is symbolic
+    * the implementation will attempt to expand the reference relative to a context
+    * map (if supplied) otherwise the implementation will attempt to expand the value 
+    * using system properties.
+    *
+    * @param target a classname or symbolic reference
+    * @param method the method to invoke on the target
+    * @param value the construct value
+    */
+    public Construct( String target, String method, String value )
+    {
+        m_target = target;
+        m_method = method;
+        m_value = value;
+        m_args = new Value[0];
+        m_compound = false;
+    }
+    
+   /**
+    * Create a new construct using a supplied target defintion.  The target argument 
+    * may be either a classname or a symbolic reference in the form ${[key]}.  If the 
+    * argument is symbolic it is resolved relative to a context map supplied by the 
+    * application resolving construct values. Instance values resolved from the 
+    * supplied Value[] will be used as constructor arguments when resolving the target.
+    *
+    * @param target the construct classname
+    * @param args an array of unresolved parameter values
+    */
+    public Construct( String target, Value[] args )
+    {
+        this( target, null, args );
+    }
+
+   /**
+    * Create a new construct using a supplied target definition.  The target argument 
+    * may be either a classname or a symbolic reference in the form ${[key]}.  If the 
+    * argument is symbolic it is resolved relative to a context map supplied by the 
+    * application resolving construct values. Instance values resolved from the 
+    * supplied Value[] will be used as method arguments when resolving the target.
+    *
+    * @param target the construct classname
+    * @param method the method to invoke on the target
+    * @param args an array of unresolved parameter values
+    */
+    public Construct( String target, String method, Value[] args )
+    {
+        if( null == args )
+        {
+            m_args = new Value[0];
+        }
+        else
+        {
+            m_args = args;
+        }
+        m_value = null;
+        m_target = target;
+        m_method = method;
+        m_compound = true;
+    }
+    
+    public void encode( Buffer buffer ) throws IOException
+    {
+        encode( buffer, "param", null );
+    }
+    
+    public void encode( Buffer buffer, String label, String key ) throws IOException
+    {
+        buffer.nl( "<" + label );
+        if( null != key )
+        {
+            buffer.write( " key=\"" + key + "\"" );
+        }
+        if( null != getTargetExpression() )
+        {
+            buffer.write( " class=\"" + getTargetExpression() + "\"" );
+        }
+        if( null != getMethodName() )
+        {
+            buffer.write( " method=\"" + getMethodName()  + "\"" );
+        }
+        if( isCompound() )
+        {
+            buffer.write( ">" );
+            Value[] values = getValues();
+            Buffer b2 = buffer.indent();
+            for( Value v : values )
+            {
+                v.encode( b2 );
+            }
+            buffer.nl( "</" + label + ">" );
+        }
+        else
+        {
+            String v = getBaseValue();
+            if( null != v )
+            {
+                buffer.write( " value=\"" + v  + "\"" );
+            }
+            buffer.write( "/>" );
+        }
+    }
+    
+   /**
+    * Return TRUE if this construct is a compound construct else FALSE.
+    * @return TRUE if this ia a compound construct
+    */
+    public boolean isCompound()
+    {
+        return m_compound;
+    }
+
+   /**
+    * Return the method name to be applied to the target object.
+    * @return the method name
+    */
+    public String getMethodName()
+    {
+        return m_method;
+    }
+
+   /**
+    * Return the set of nested values within this value.
+    * @return the nested values array
+    */
+    public Value[] getValues()
+    {
+        return m_args;
+    }
+
+   /**
+    * Return the classname of the resolved value.
+    * @return the classname
+    */
+    public String getBaseValue()
+    {
+        return m_value;
+    }
+
+   /**
+    * Return the classname of the resolved value.
+    * @return the classname
+    */
+    public String getTargetExpression()
+    {
+        return m_target;
+    }
+
+   /**
+    * Resolve an instance from the value using the context classloader.
+    * @return the resolved instance
+    * @exception Exception if an error occurs during value resolution
+    */
+    public Object resolve() throws Exception
+    {
+        return resolve( null );
+    }
+    
+   /**
+    * Resolve an instance from the value using a supplied map.
+    * @param map the context map
+    * @return the resolved instance
+    * @exception Exception if an error occurs during value resolution
+    */
+    public Object resolve( Map<String,Object> map ) throws Exception
+    {
+        return resolve( null, map );
+    }
+    
+   /**
+    * Resolve an instance from the value using a supplied context map. If any 
+    * target expressions in immediate or nested values contain a symbolic
+    * expression the value will be resolved using the supplied map.
+    *
+    * @param type the implicit target class
+    * @param map the context map
+    * @return the resolved instance
+    * @exception Exception if an error occurs during value resolution
+    */
+    public Object resolve( Class<?> type, Map<String,Object> map ) throws Exception
+    {
+        return resolve( type, map, null );
+    }
+
+   /**
+    * Resolve an instance from the value.
+    * @param type the implicit target class
+    * @param map the context map
+    * @param classloader the classloader
+    * @return the resolved instance
+    * @exception Exception if an error occurs during value resolution
+    */
+    private Object resolve( 
+      Class type, Map<String,Object> map, ClassLoader classloader ) throws Exception
+    {
+        ClassLoader loader = resolveClassLoader( classloader );
+        Class t = getTargetClass( loader, type );
+        if( isCompound() )
+        {
+            return resolveCompoundExpression( t, map, loader );
+        }
+        else
+        {
+            return resolveSimpleExpression( t, map, loader );
+        }
+    }
+    
+    private Object resolveSimpleExpression( 
+      Class type, Map map, ClassLoader classloader ) throws Exception
+    {
+        Properties properties = System.getProperties();
+        String value = PropertyResolver.resolve( properties, m_value );
+        
+        if( ( null != value ) && ( null != map ) )
+        {
+            if( value.startsWith( "${" ) && m_value.endsWith( "}" ) )
+            {
+                String pre = m_value.substring( 2 );
+                String key = pre.substring( 0, pre.length() -1 );
+                if( map.containsKey( key ) )
+                {
+                    return map.get( key );
+                }
+            }
+        }
+        
+        String method = getMethodName();
+        if( null == method )
+        {
+            method = "new";
+        }
+        else
+        {
+            if( null == value ) // check if the method name is a static field
+            {
+                try
+                {
+                    Field field = type.getField( method );
+                    return field.get( type );
+                }
+                catch( NoSuchFieldException e )
+                {
+                    // assume its a method
+                }
+            }
+        }
+        
+        if( null == value )
+        {
+            Expression expression = new Expression( type, method, new Object[0] );
+            try
+            {
+                return expression.getValue();
+            }
+            catch( Throwable e )
+            {
+                final String error = 
+                  "Internal error while evalating simple expression using:"
+                  + "\n target: " 
+                  + m_target 
+                  + " (" 
+                  + type.getName() 
+                  + ")"
+                  + "\n method: " 
+                  + m_method 
+                  + " (" 
+                  + method 
+                  + ")";
+                throw new ValueException( error, e );
+            }
+        }
+        else
+        {
+            Expression expression =  new Expression( type, method, new Object[]{value} );
+            try
+            {
+                return expression.getValue();
+            }
+            catch( Throwable e )
+            {
+                final String error = 
+                  "Internal error while evaluating expression using:"
+                  + "\n target: " + m_target + " (" + type.getName() + ")"
+                  + "\n method: " + m_method + " (" + method + ")"
+                  + "\n value: " + m_value + " (" + value.getClass().getName() + ")";
+                throw new ValueException( error, e );
+            }
+        }
+    }
+    
+    private Object resolveCompoundExpression( 
+      Class<?> type, Map<String,Object> map, ClassLoader classloader ) throws Exception
+    {
+        Value[] args = getValues();
+        Object[] instances = getInstanceValues( type, map, classloader, args );
+        String method = getMethodName();
+        
+        //
+        // check if we are dealing with an array class and if so return an 
+        // array created from the array of nested values
+        //
+        
+        if( type.isArray() )
+        {
+            Class<?> t = type.getComponentType();
+            if( t.isPrimitive() )
+            {
+                return buildPrimitiveArray( t, instances );
+            }
+            else
+            {
+                Object[] result = 
+                  (Object[]) Array.newInstance( t, instances.length );
+                for( int i=0; i<instances.length; i++ )
+                {
+                    Object instance = instances[i];
+                    Class<?> clazz = instance.getClass();
+                    if( t.isAssignableFrom( clazz ) )
+                    {
+                        result[i] = instances[i];
+                    }
+                    else
+                    {
+                        final String error =
+                          "Array [" 
+                          + t.getName() 
+                          + "] contains an invalid element [" 
+                          + instance.getClass().getName() 
+                          + "].";
+                        throw new ValueException( error );
+                    }
+                }
+                return result;
+            }
+        }
+        
+        // otherwise its a regular expression
+        
+        if( null == method )
+        {
+            method = "new";
+        }
+        else
+        {
+            if( instances.length == 0 )
+            {
+                // check if the method name is a static field
+                try
+                {
+                    Field field = type.getField( method );
+                    return field.get( type );
+                }
+                catch( NoSuchFieldException e )
+                {
+                    // assume its a method
+                }
+            }
+        }
+
+        Expression expression = new Expression( type, method, instances );
+        try
+        {
+            return expression.getValue();
+        }
+        catch( Throwable e )
+        {
+            StringBuffer buffer = new StringBuffer();
+            buffer.append( "Internal error while evaluating compound expression." );
+            buffer.append( "\n target: " + m_target + " (" + type.getName() + ")" );
+            buffer.append( "\n method: " + m_method + " (" + method + ")" );
+            for( int i=0; i<instances.length; i++ )
+            {
+                buffer.append( 
+                  "\n param " 
+                  + ( i+1 ) 
+                  + ": " 
+                  + instances[i].getClass().getName()
+                );
+            }
+            String error = buffer.toString();
+            throw new ValueException( error, e );
+        }
+    }
+
+    private Object buildPrimitiveArray( Class type, Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( type, instances.length );
+        if( Integer.TYPE == type )
+        {
+            return buildIntArray( instances );
+        }
+        else if( Short.TYPE == type )
+        {
+            return buildShortArray( instances );
+        }
+        else if( Long.TYPE == type )
+        {
+            return buildLongArray( instances );
+        }
+        else if( Byte.TYPE == type )
+        {
+            return buildByteArray( instances );
+        }
+        else if( Double.TYPE == type )
+        {
+            return buildDoubleArray( instances );
+        }
+        else if( Float.TYPE == type )
+        {
+            return buildFloatArray( instances );
+        }
+        else if( Character.TYPE == type )
+        {
+            return buildCharacterArray( instances );
+        }
+        else if( Boolean.TYPE == type )
+        {
+            return buildBooleanArray( instances );
+        }
+        else
+        {
+            final String error = 
+              "Primitive array class [" 
+              + type.getName() 
+              + "] is not recognized.";
+            throw new UnsupportedOperationException( error );
+        }
+    }
+    
+    private Object buildIntArray( Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( Integer.TYPE, instances.length );
+        for( int i=0; i<instances.length; i++ )
+        {
+            Object instance = instances[i];
+            if( instance instanceof Integer )
+            {
+                Integer integer = (Integer) instance;
+                int v = integer.intValue();
+                Array.setInt( result, i, v );
+            }
+            else
+            {
+                final String error = 
+                  "Supplied int array argument class ["
+                  + instance.getClass().getName()
+                  + "] is not an Integer.";
+                throw new ValueException( error );
+            }
+        }
+        return result;
+    }
+    
+    private Object buildShortArray( Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( Short.TYPE, instances.length );
+        for( int i=0; i<instances.length; i++ )
+        {
+            Object instance = instances[i];
+            if( instance instanceof Short )
+            {
+                Short primitive = (Short) instance;
+                short v = primitive.shortValue();
+                Array.setShort( result, i, v );
+            }
+            else
+            {
+                final String error = 
+                  "Supplied short array argument class ["
+                  + instance.getClass().getName()
+                  + "] is not an Short.";
+                throw new ValueException( error );
+            }
+        }
+        return result;
+    }
+    
+    private Object buildLongArray( Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( Long.TYPE, instances.length );
+        for( int i=0; i<instances.length; i++ )
+        {
+            Object instance = instances[i];
+            if( instance instanceof Long )
+            {
+                Long primitive = (Long) instance;
+                long v = primitive.longValue();
+                Array.setLong( result, i, v );
+            }
+            else
+            {
+                final String error = 
+                  "Supplied long array argument class ["
+                  + instance.getClass().getName()
+                  + "] is not an instance of Long.";
+                throw new ValueException( error );
+            }
+        }
+        return result;
+    }
+    
+    private Object buildByteArray( Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( Byte.TYPE, instances.length );
+        for( int i=0; i<instances.length; i++ )
+        {
+            Object instance = instances[i];
+            if( instance instanceof Byte )
+            {
+                Byte primitive = (Byte) instance;
+                byte v = primitive.byteValue();
+                Array.setByte( result, i, v );
+            }
+            else
+            {
+                final String error = 
+                  "Supplied byte array argument class ["
+                  + instance.getClass().getName()
+                  + "] is not an instance of Byte.";
+                throw new ValueException( error );
+            }
+        }
+        return result;
+    }
+    
+    private Object buildDoubleArray( Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( Double.TYPE, instances.length );
+        for( int i=0; i<instances.length; i++ )
+        {
+            Object instance = instances[i];
+            if( instance instanceof Double )
+            {
+                Double primitive = (Double) instance;
+                double v = primitive.doubleValue();
+                Array.setDouble( result, i, v );
+            }
+            else
+            {
+                final String error = 
+                  "Supplied double array argument class ["
+                  + instance.getClass().getName()
+                  + "] is not an instance of Double.";
+                throw new ValueException( error );
+            }
+        }
+        return result;
+    }
+    
+    private Object buildFloatArray( Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( Float.TYPE, instances.length );
+        for( int i=0; i<instances.length; i++ )
+        {
+            Object instance = instances[i];
+            if( instance instanceof Float )
+            {
+                Float primitive = (Float) instance;
+                float v = primitive.floatValue();
+                Array.setFloat( result, i, v );
+            }
+            else
+            {
+                final String error = 
+                  "Supplied float array argument class ["
+                  + instance.getClass().getName()
+                  + "] is not an instance of Float.";
+                throw new ValueException( error );
+            }
+        }
+        return result;
+    }
+    
+    private Object buildCharacterArray( Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( Character.TYPE, instances.length );
+        for( int i=0; i<instances.length; i++ )
+        {
+            Object instance = instances[i];
+            if( instance instanceof Character )
+            {
+                Character primitive = (Character) instance;
+                char v = primitive.charValue();
+                Array.setChar( result, i, v );
+            }
+            else
+            {
+                final String error = 
+                  "Supplied char array argument class ["
+                  + instance.getClass().getName()
+                  + "] is not an instance of Character.";
+                throw new ValueException( error );
+            }
+        }
+        return result;
+    }
+    
+    private Object buildBooleanArray( Object[] instances ) throws ValueException
+    {
+        Object result = Array.newInstance( Boolean.TYPE, instances.length );
+        for( int i=0; i<instances.length; i++ )
+        {
+            Object instance = instances[i];
+            if( instance instanceof Boolean )
+            {
+                Boolean primitive = (Boolean) instance;
+                boolean v = primitive.booleanValue();
+                Array.setBoolean( result, i, v );
+            }
+            else
+            {
+                final String error = 
+                  "Supplied boolean array argument class ["
+                  + instance.getClass().getName()
+                  + "] is not an instance of Boolean.";
+                throw new ValueException( error );
+            }
+        }
+        return result;
+    }
+    
+    private Object[] getInstanceValues( 
+      Class type, Map<String,Object> map, ClassLoader classloader, Value[] args ) throws Exception
+    {
+        Object[] instances = new Object[ args.length ];
+        for( int i=0; i < args.length; i++ )
+        {
+            Value value = args[i];
+            if( value instanceof Construct )
+            {
+                Construct construct = (Construct) value;
+                if( type.isArray() )
+                {
+                    Class<?> t = type.getComponentType();
+                    instances[i] = construct.resolve( t, map, classloader );
+                }
+                else
+                {
+                    instances[i] = construct.resolve( null, map, classloader );
+                }
+            }
+            else
+            {
+                if( type.isArray() )
+                {
+                    Class<?> t = type.getComponentType();
+                    instances[i] = value.resolve( t, map );
+                }
+                else
+                {
+                    instances[i] = value.resolve( null, map );
+                }
+            }
+        }
+        return instances;
+    }
+
+    private Class getTargetClass( ClassLoader loader, Class type ) 
+      throws ValueException
+    {
+        if( null == m_target )
+        {
+            if( null == type )
+            {
+                return String.class;
+            }
+            else
+            {
+                if( type.isPrimitive() )
+                {
+                    if( type == Integer.TYPE )
+                    {
+                        return Integer.class;
+                    }
+                    else if( type == Short.TYPE )
+                    {
+                        return Short.class;
+                    }
+                    else if( type == Long.TYPE )
+                    {
+                        return Long.class;
+                    }
+                    else if( type == Byte.TYPE )
+                    {
+                        return Byte.class;
+                    }
+                    else if( type == Double.TYPE )
+                    {
+                        return Double.class;
+                    }
+                    else if( type == Float.TYPE )
+                    {
+                        return Float.class;
+                    }
+                    else if( type == Character.TYPE )
+                    {
+                        return Character.class;
+                    }
+                    else if( type == Boolean.TYPE )
+                    {
+                        return Boolean.class;
+                    }
+                    else
+                    {
+                        return Void.class;
+                    }
+                }
+                else
+                {
+                    return type;
+                }
+            }
+        }
+        else
+        {
+            if( m_target.endsWith( "[]" ) )
+            {
+                int n = m_target.length() - 2;
+                String componentClassname = m_target.substring( 0, n );
+                Class componentClass = resolveType( loader, componentClassname );
+                return Array.newInstance( componentClass, 0 ).getClass();
+            }
+            else
+            {
+                return resolveClass( loader, m_target );
+            }
+        }
+    }
+
+    /**
+     * Return the instance class using the context classloader.
+     * @return the class
+     * @exception ComponentException if the parameter class cannot be resolved
+     */
+    private Class resolveClass( ClassLoader loader, String classname ) throws ValueException
+    {
+        if( classname.equals( "int" ) )
+        {
+            return Integer.class;
+        }
+        else if( classname.equals( "short" ) )
+        {
+            return Short.class;
+        }
+        else if( classname.equals( "long" ) )
+        {
+            return Long.class;
+        }
+        else if( classname.equals( "byte" ) )
+        {
+            return Byte.class;
+        }
+        else if( classname.equals( "double" ) )
+        {
+            return Double.class;
+        }
+        else if( classname.equals( "float" ) )
+        {
+            return Float.class;
+        }
+        else if( classname.equals( "char" ) )
+        {
+            return Character.class;
+        }
+        else if( classname.equals( "boolean" ) )
+        {
+            return Boolean.class;
+        }
+        else
+        {
+            try
+            {
+                return Class.forName( classname, false, loader );
+            }
+            catch( final ClassNotFoundException cnfe )
+            {
+                final String error =
+                  "Value class not found ["
+                  + classname 
+                  + "].";
+                throw new ValueException( error, cnfe );
+            }
+        }
+    }
+
+    /**
+     * Return the instance class using the context classloader.
+     * @return the class
+     * @exception ComponentException if the parameter class cannot be resolved
+     */
+    private Class resolveType( ClassLoader loader, String classname ) throws ValueException
+    {
+        if( classname.equals( "int" ) )
+        {
+            return Integer.TYPE;
+        }
+        else if( classname.equals( "short" ) )
+        {
+            return Short.TYPE;
+        }
+        else if( classname.equals( "long" ) )
+        {
+            return Long.TYPE;
+        }
+        else if( classname.equals( "byte" ) )
+        {
+            return Byte.TYPE;
+        }
+        else if( classname.equals( "double" ) )
+        {
+            return Double.TYPE;
+        }
+        else if( classname.equals( "float" ) )
+        {
+            return Float.TYPE;
+        }
+        else if( classname.equals( "char" ) )
+        {
+            return Character.TYPE;
+        }
+        else if( classname.equals( "boolean" ) )
+        {
+            return Boolean.TYPE;
+        }
+        else
+        {
+            try
+            {
+                return loader.loadClass( classname );
+            }
+            catch( final ClassNotFoundException e )
+            {
+                final String error =
+                  "Class not found ["
+                  + classname 
+                  + "].";
+               throw new ValueException( error, e );
+            }
+        }
+    }
+    
+    private ClassLoader resolveClassLoader( ClassLoader classloader )
+    {
+        if( null != classloader )
+        {
+            return classloader;
+        }
+        else
+        {
+            ClassLoader loader = Thread.currentThread().getContextClassLoader();
+            if( null != loader )
+            {
+                return loader;
+            }
+            else
+            {
+                return Construct.class.getClassLoader();
+            }
+        }
+    }
+    
+   /**
+    * Return a string representation of the construct.
+    * @return the string value
+    */
+    public String toString()
+    {
+        if( !m_compound )
+        {
+            return "construct "
+              + " target: " + m_target 
+              + " method: " + m_method 
+              + " value: " + m_value;
+        }
+        else
+        {
+            return "construct "
+              + " target: " + m_target 
+              + " method: " + m_method 
+              + " values: " + m_args.length;
+        }
+    }
+    
+   /**
+    * Compare this instance with a supplied object for equality.
+    * @param other the other object
+    * @return true if the supplied instance is equal to this instance
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        if( other instanceof Construct )
+        {
+            Construct construct = (Construct) other;
+            if( !equals( m_target, construct.m_target ) )
+            {
+                return false;
+            }
+            if( m_compound != construct.m_compound )
+            {
+                return false;
+            }
+            if( !equals( m_method, construct.m_method ) )
+            {
+                return false;
+            }
+            if( m_compound )
+            {
+                return Arrays.equals( m_args, construct.m_args );
+            }
+            else
+            {
+                return equals( m_value, construct.m_value );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Compute the instance hashcode value.
+    * @return the hashcode
+    */
+    public int hashCode()
+    {
+        int hash = 0;
+        if( null != m_target )
+        {
+            hash ^= m_target.hashCode();
+        }
+        if( null != m_method )
+        {
+            hash ^= m_method.hashCode();
+        }
+        if( m_compound )
+        {
+            for( int i=0; i<m_args.length; i++ )
+            {
+                hash ^= m_args[i].hashCode();
+            }
+        }
+        else
+        {
+            if( m_value != null )
+            {
+                hash ^= m_value.hashCode();
+            }
+        }
+        return hash;
+    }
+    
+    private boolean equals( Object a, Object b )
+    {
+        if( null == a )
+        {
+            return ( null == b );
+        }
+        else
+        {
+            return a.equals( b );
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/ContextInvocationHandler.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/ContextInvocationHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/ContextInvocationHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.util.Map;
+import java.beans.Introspector;
+import java.beans.Expression;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import net.dpml.annotation.Context;
+
+import dpml.lang.Value;
+
+/**
+ * Invocation handler utility for a Context class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class ContextInvocationHandler implements InvocationHandler
+{
+    //-------------------------------------------------------------------
+    // static
+    //-------------------------------------------------------------------
+    
+    private static final String GET = "get";
+
+   /**
+    * Test if the supplied class is recognized as a context class. If
+    * the supplied policy is true then evaluation is based on the presence
+    * of the <tt>net.dpml.lang.Context</tt> annotation and resulting 
+    * value of annotation evaluation.  If no context annnotation is present
+    * and strict processing is disabled then evaluation will return true if 
+    * the classname ends with the string <tt>$Context</tt>.
+    *
+    * @param c the candidate class
+    * @param policy the strict evaluation policy
+    * @return true if this class is recognized as a context class
+    */
+    public static boolean isaContext( final Class<?> c, final boolean policy )
+    {
+        boolean flag = c.isAnnotationPresent( Context.class );
+        if( flag )
+        {
+            return c.getAnnotation( Context.class ).value();
+        }
+        else if( policy )
+        {
+            return false;
+        }
+        else
+        {
+            return c.getName().endsWith( "$Context" );
+        }
+    }
+    
+   /**
+    * Validate that the supplied map properly fulfills the required  
+    * context entry.  Specifically, for all non-optional methods declared
+    * by the context class, the validation process checks the the supplied
+    * map has a corresponding key and associated non-null value.
+    *
+    * @param clazz the context class
+    * @param map a map of context entry values
+    * @exception IllegalArgumentException if validation fails
+    */
+    public static void validate( Class clazz, Map<String,Object> map ) 
+      throws IllegalArgumentException
+    {
+        for( Method method : clazz.getMethods() )
+        {
+            String key = getKeyForMethod( method );
+            boolean optional = isOptionalEntry( method );
+            if( !optional )
+            {
+                if( !map.containsKey( key ) )
+                {
+                    final String error = 
+                      "Missing required key ["
+                      + key
+                      + "]";
+                    throw new IllegalArgumentException( error );
+                }
+                else if( null == map.get( key ) )
+                {
+                    final String error = 
+                      "Missing value for the required key ["
+                      + key
+                      + "]";
+                    throw new IllegalArgumentException( error );
+                }
+            }
+        }
+    }
+    
+   /**
+    * Construct a new context instance implementing the supplied class
+    * backed by entries in the supplied map.
+    *
+    * @param clazz the context class
+    * @param map a map of context entry keys and values
+    * @return the constructed context instance
+    */
+    public static <T>T getProxiedInstance( final Class<T> clazz, final Map<String,Object> map )
+    {
+        ClassLoader classloader = clazz.getClassLoader();
+        ContextInvocationHandler handler = 
+          new ContextInvocationHandler( map );
+        final Object instance = 
+          Proxy.newProxyInstance( classloader, new Class[]{clazz}, handler );
+        return clazz.cast( instance );
+    }
+    
+    //-------------------------------------------------------------------
+    // state
+    //-------------------------------------------------------------------
+
+   /**
+    * A map containing key values.
+    */
+    private final Map<String,Object> m_map;
+
+    //-------------------------------------------------------------------
+    // constructor
+    //-------------------------------------------------------------------
+
+   /**
+    * Create a context invocation handler.
+    *
+    * @param map a map containing context key/value pairs.
+    */
+    private ContextInvocationHandler( final Map<String,Object> map )
+    {
+        if( null == map )
+        {
+            throw new NullPointerException( "map" );
+        }
+        m_map = map;
+    }
+
+    //-------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------
+
+   /**
+    * Invoke the specified method on underlying object.
+    * This is called by the proxy object.
+    *
+    * @param proxy the proxy object
+    * @param method the method invoked on proxy object
+    * @param args the arguments supplied to method
+    * @return the return value of method
+    * @throws Throwable if an error occurs
+    */
+    @SuppressWarnings( "unchecked" )
+    public Object invoke( final Object proxy, final Method method, final Object[] args ) throws Throwable
+    {
+        Class source = method.getDeclaringClass();
+        if( Object.class == source )
+        {
+            return method.invoke( this, args );
+        }
+        else
+        {
+            String name = method.getName();
+            if( name.startsWith( "get" ) )
+            {
+                String key = Introspector.decapitalize( name.substring( 3 ) );
+                Object value = m_map.get( key );
+                if( null != value )
+                {
+                    Class<?> clazz = method.getReturnType();
+                    if( isAssignableFrom( clazz, value.getClass() ) )
+                    {
+                        return value;
+                    }
+                    else if( isaContext( clazz, STRICT_PROCESSING ) )
+                    {
+                        if( value instanceof Map )
+                        {
+                            Map m = (Map) value;
+                            return getProxiedInstance( clazz, m );
+                        }
+                        else
+                        {
+                            final String error = 
+                              "Supplied context solution value [" 
+                              + value.getClass().getName() 
+                              + "] is not an instance of java.util.Map.";
+                            throw new IllegalStateException( error );
+                        }
+                    }
+                    else if( value instanceof Value )
+                    {
+                        Value v = (Value) value;
+                        return v.resolve( clazz, (Map) null );
+                    }
+                    else
+                    {
+                        Expression expression = new Expression( clazz, "new", new Object[]{value} );
+                        return expression.getValue();
+                    }
+                }
+                else if( ( null != args ) && args.length > 0 )
+                {
+                    return args[0];
+                }
+                else
+                {
+                    final String error = 
+                      "Unable to resolve a context entry value for the key [" 
+                      + key
+                      + "]";
+                    throw new IllegalStateException( error );
+                }
+            }
+            else
+            {
+                throw new UnsupportedOperationException( name );
+            }
+        }
+    }
+    
+    private static boolean isAssignableFrom( Class<?> clazz, Class<?> c )
+    {
+        if( clazz.isPrimitive() )
+        {
+            if( Integer.TYPE == clazz )
+            {
+                return Integer.class.isAssignableFrom( c );
+            }
+            else if( Boolean.TYPE == clazz )
+            {
+                return Boolean.class.isAssignableFrom( c );
+            }
+            else if( Byte.TYPE == clazz )
+            {
+                return Byte.class.isAssignableFrom( c );
+            }
+            else if( Short.TYPE == clazz )
+            {
+                return Short.class.isAssignableFrom( c );
+            }
+            else if( Long.TYPE == clazz )
+            {
+                return Long.class.isAssignableFrom( c );
+            }
+            else if( Float.TYPE == clazz )
+            {
+                return Float.class.isAssignableFrom( c );
+            }
+            else if( Double.TYPE == clazz )
+            {
+                return Double.class.isAssignableFrom( c );
+            }
+            else
+            {
+                final String error =
+                  "Primitive type ["
+                  + c.getName()
+                  + "] not supported.";
+                throw new RuntimeException( error );
+            }
+        }
+        else
+        {
+            return clazz.isAssignableFrom( c );
+        }
+    }
+    
+    private static boolean isOptionalEntry( Method method )
+    {
+        return method.getParameterTypes().length == 1;
+    }
+    
+    private static String getKeyForMethod( Method method )
+    {
+        String name = method.getName();
+        if( name.startsWith( GET ) )
+        {
+            String remainder = name.substring( GET.length() );
+            return Introspector.decapitalize( remainder );
+        }
+        else
+        {
+            final String error = 
+              "Method name is not a recognized pattern: " 
+              + name;
+            throw new IllegalArgumentException( error );
+        }
+    }
+    
+    private static final String STRICT_PROCESSING_KEY = "dpml.lang.context.policy";
+    private static final String STRICT_PROCESSING_KEYWORD = "strict";
+    private static final boolean STRICT_PROCESSING = getStrictProcessingPolicy();
+    
+    private static boolean getStrictProcessingPolicy()
+    {
+        return STRICT_PROCESSING_KEYWORD.equalsIgnoreCase( 
+          System.getProperty( 
+            STRICT_PROCESSING_KEY, 
+            STRICT_PROCESSING_KEYWORD ) );
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/DOM3DocumentBuilder.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/DOM3DocumentBuilder.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/DOM3DocumentBuilder.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,310 @@
+/*
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import dpml.util.DefaultLogger;
+
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URISyntaxException;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.ServiceLoader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.FileNotFoundException;
+
+import javax.xml.XMLConstants;
+
+import net.dpml.lang.PartError;
+
+import net.dpml.transit.Artifact;
+import net.dpml.transit.InvalidArtifactException;
+
+import net.dpml.util.Logger;
+
+import org.w3c.dom.DOMError;
+import org.w3c.dom.DOMLocator;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.DOMErrorHandler;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.Document;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSParser;
+import org.w3c.dom.ls.LSSerializer;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSException;
+
+/**
+ * Utility class that creates a schema validating DOM3 parser.
+ */
+public class DOM3DocumentBuilder
+{
+    private final Logger m_logger;
+    
+   /**
+    * Creation of a new DOM3 document builder.
+    */
+    public DOM3DocumentBuilder()
+    {
+        this( new DefaultLogger( "dpml.lang" ) );
+    }
+    
+   /**
+    * Creation of a new DOM3 document builder.
+    * @param logger the assigned logging channel
+    */
+    public DOM3DocumentBuilder( final Logger logger )
+    {
+        m_logger = logger;
+    }
+    
+   /**
+    * Parse an xml schema document.
+    * @param uri the document uri 
+    * @return the validated document
+    * @exception IOException if an IO error occurs
+    */
+    public Document parse( final URI uri ) throws IOException
+    {
+        if( null == uri )
+        {
+            throw new NullPointerException( "uri" );
+        }
+        URL url = Artifact.toURL( uri );
+        return parse( url );
+    }
+    
+   /**
+    * Parse an xml schema document.
+    * @param url the document url 
+    * @return the validated document
+    * @exception IOException if an IO error occurs
+    */
+    public Document parse( URL url ) throws IOException
+    {
+        if( null == url )
+        {
+            throw new NullPointerException( "url" );
+        }
+        URLConnection connection = url.openConnection();
+        return parse( connection );
+    }
+    
+    public Document parse( URLConnection connection ) throws IOException
+    {
+        if( null == connection )
+        {
+            throw new NullPointerException( "connection" );
+        }
+        URL url = connection.getURL();
+        try
+        {
+            DOMImplementationRegistry registry =
+                DOMImplementationRegistry.newInstance();
+            DOMImplementationLS impl = 
+                (DOMImplementationLS) registry.getDOMImplementation( "LS" );
+            if( null == impl )
+            {
+                final String error = 
+                  "Unable to locate a DOM3 parser.";
+                throw new IllegalStateException( error );
+            }
+            LSParser builder = impl.createLSParser( DOMImplementationLS.MODE_SYNCHRONOUS, null );
+            DOMConfiguration config = builder.getDomConfig();
+            
+            URI uri = url.toURI();
+            config.setParameter( "error-handler", new InternalErrorHandler( m_logger, uri ) );
+            config.setParameter( "resource-resolver", new InternalResourceResolver( m_logger ) );
+            config.setParameter( "validate", Boolean.TRUE );
+            DOMInput input = new DOMInput();
+            
+            InputStream stream = connection.getInputStream();
+            InputStreamReader reader = new InputStreamReader( stream );
+            input.setCharacterStream( reader );
+            
+            Document doc = builder.parse( input );
+            doc.setDocumentURI( uri.toASCIIString() );
+            return doc;
+        }
+        catch( FileNotFoundException e )
+        {
+            throw e;
+        }
+        catch( InvalidArtifactException e )
+        {
+            throw e;
+        }
+        catch( Exception e )
+        {
+            final String error = 
+              "DOM3 error while attempting to parse document."
+              + "\nSource: " + url;
+            IOException ioe = new IOException( error );
+            ioe.initCause( e );
+            throw ioe;
+        }
+    }
+    
+   /**
+    * Write a document to an output stream.
+    * @param doc the document to write
+    * @param output the output stream
+    * @exception Exception if an error occurs
+    */
+    public void write( Document doc, OutputStream output ) throws Exception
+    {
+        DOMImplementationRegistry registry =
+            DOMImplementationRegistry.newInstance();
+        DOMImplementationLS impl = 
+            (DOMImplementationLS) registry.getDOMImplementation( "LS" );
+        if( null == impl )
+        {
+            final String error = 
+              "Unable to locate a DOM3 implementation.";
+            throw new IllegalStateException( error );
+        }
+        LSSerializer domWriter = impl.createLSSerializer();
+        LSOutput lsOut = impl.createLSOutput();
+        lsOut.setByteStream( output );
+        domWriter.write( doc, lsOut );
+    }
+    
+   /**
+    * Utility class to handle namespace uri resolves.
+    */
+    private static class InternalResourceResolver implements LSResourceResolver
+    {
+        private static StandardNamespaceResolver RESOLVER = 
+          new StandardNamespaceResolver();
+          
+        private final Logger m_logger;
+        
+       /**
+        * Creation of a new InternalResourceResolver.
+        * @param map the namespace to builder map
+        */
+        InternalResourceResolver( Logger logger )
+        {
+            m_logger = logger;
+        }
+        
+       /**
+        * Resolve an LS input. 
+        * @param type the node type
+        * @param namespace the node namespace
+        * @param publicId the public id
+        * @param systemId the system id
+        * @param base the base value
+        * @return the LS input instance
+        */
+        public LSInput resolveResource( 
+          String type, String namespace, String publicId, String systemId, String base )
+        {
+            LSResourceResolver[] resolvers = getNamespaceResolvers();
+            for( LSResourceResolver resolver : resolvers )
+            {
+                LSInput input = resolver.resolveResource( type, namespace, publicId, systemId, base );
+                if( null != input )
+                {
+                    return input;
+                }
+            }
+            
+            final String error = 
+              "Unable to resolve a schema for the namespace [" 
+              + namespace 
+              + "]";
+            throw new LSException( LSException.PARSE_ERR, error );
+        }
+        
+        private LSResourceResolver[] getNamespaceResolvers()
+        {
+            ArrayList<LSResourceResolver> list = new ArrayList<LSResourceResolver>();
+            ServiceLoader<LSResourceResolver> loaders = 
+              ServiceLoader.load( LSResourceResolver.class );
+            for( LSResourceResolver resolver : loaders )
+            {
+                list.add( resolver );
+            }
+            return list.toArray( new LSResourceResolver[0] );
+        }
+    }
+    
+   /**
+    * Internal error handler with room for improvement.
+    */
+    private static final class InternalErrorHandler implements DOMErrorHandler
+    {
+        private final URI m_uri;
+        private final Logger m_logger;
+        
+        InternalErrorHandler( Logger logger, URI uri )
+        {
+            m_uri = uri;
+            m_logger = logger;
+        }
+        
+       /**
+        * Handle the supplied error.
+        * @param error the error
+        * @return a boolean value
+        */
+        public boolean handleError( DOMError error )
+        {
+            DOMLocator locator = error.getLocation();
+            int line = locator.getLineNumber();
+            int column = locator.getColumnNumber();
+            String uri = locator.getUri();
+            if( null == uri )
+            {
+                uri = m_uri.toString();
+            }
+            
+            String source = uri;
+            if( !( ( line == -1 ) && column == -1 ) )
+            {
+                source = source + " [" + line + ":" + column + "]";
+            }
+            String message = error.getMessage();
+            final String notice = 
+              message
+              + "\n" 
+              + source;
+            short severity = error.getSeverity();
+            if( severity == DOMError.SEVERITY_WARNING )
+            {
+                m_logger.warn( notice );
+                return true;
+            }
+            else
+            {
+                m_logger.error( notice );
+                return false;
+            }
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/DOMInput.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/DOMInput.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/DOMInput.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.io.Reader;
+import java.io.InputStream;
+
+import org.w3c.dom.ls.LSInput;
+
+/**
+ * This Class <code>DOMInput</code> represents a single input source for an XML entity.
+ * <p> This Class allows an application to encapsulate information about
+ * an input source in a single object, which may include a public
+ * identifier, a system identifier, a byte stream (possibly with a specified
+ * encoding), and/or a character stream.
+ * <p> The exact definitions of a byte stream and a character stream are
+ * binding dependent.
+ * <p> There are two places that the application will deliver this input
+ * source to the parser: as the argument to the <code>parse</code> method,
+ * or as the return value of the <code>DOMResourceResolver.resolveEntity</code>
+ *  method.
+ * <p> The <code>DOMParser</code> will use the <code>LSInput</code>
+ * object to determine how to read XML input. If there is a character stream
+ * available, the parser will read that stream directly; if not, the parser
+ * will use a byte stream, if available; if neither a character stream nor a
+ * byte stream is available, the parser will attempt to open a URI
+ * connection to the resource identified by the system identifier.
+ * <p> An <code>LSInput</code> object belongs to the application: the
+ * parser shall never modify it in any way (it may modify a copy if
+ * necessary).  Eventhough all attributes in this interface are writable the
+ * DOM implementation is expected to never mutate a LSInput.
+ * <p>See also the <a href='http://www.w3.org/TR/2001/WD-DOM-Level-3-ASLS-20011025'>Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification</a>.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DOMInput implements LSInput 
+{
+    private String m_publicId = null;
+    private String m_systemId = null;
+    private String m_base = null;
+    private InputStream m_byteStream = null;
+    private Reader m_reader    = null;
+    private String m_data = null;
+    private String m_encoding = null;
+    private boolean m_certified = false;
+
+  /**
+    * Default constructor.
+    */
+    public DOMInput()
+    {
+    }
+
+   /**
+    * An attribute of a language-binding dependent type that represents a
+    * stream of bytes.
+    * <br>The parser will ignore this if there is also a character stream
+    * specified, but it will use a byte stream in preference to opening a
+    * URI connection itself.
+    * <br>If the application knows the character encoding of the byte stream,
+    * it should set the encoding property. Setting the encoding in this way
+    * will override any encoding specified in the XML declaration itself.
+    */
+    public InputStream getByteStream()
+    {
+        return m_byteStream;
+    }
+
+    /**
+    * An attribute of a language-binding dependent type that represents a
+    * stream of bytes.
+    * <br>The parser will ignore this if there is also a character stream
+    * specified, but it will use a byte stream in preference to opening a
+    * URI connection itself.
+    * <br>If the application knows the character encoding of the byte stream,
+    * it should set the encoding property. Setting the encoding in this way
+    * will override any encoding specified in the XML declaration itself.
+    */
+    public void setByteStream( InputStream byteStream )
+    {
+        m_byteStream = byteStream;
+    }
+
+    /**
+    *  An attribute of a language-binding dependent type that represents a
+    * stream of 16-bit units. Application must encode the stream using
+    * UTF-16 (defined in  and Amendment 1 of ).
+    * <br>If a character stream is specified, the parser will ignore any byte
+    * stream and will not attempt to open a URI connection to the system
+    * identifier.
+    */
+    public Reader getCharacterStream()
+    {
+        return m_reader;
+    }
+    /**
+    *  An attribute of a language-binding dependent type that represents a
+    * stream of 16-bit units. Application must encode the stream using
+    * UTF-16 (defined in  and Amendment 1 of ).
+    * <br>If a character stream is specified, the parser will ignore any byte
+    * stream and will not attempt to open a URI connection to the system
+    * identifier.
+    */
+    public void setCharacterStream( Reader characterStream )
+    {
+        m_reader = characterStream;
+    }
+
+    /**
+    * A string attribute that represents a sequence of 16 bit units (utf-16
+    * encoded characters).
+    * <br>If string data is available in the input source, the parser will
+    * ignore the character stream and the byte stream and will not attempt
+    * to open a URI connection to the system identifier.
+    */
+    public String getStringData()
+    {
+        return m_data;
+    }
+
+   /**
+    * A string attribute that represents a sequence of 16 bit units (utf-16
+    * encoded characters).
+    * <br>If string data is available in the input source, the parser will
+    * ignore the character stream and the byte stream and will not attempt
+    * to open a URI connection to the system identifier.
+    */
+    public void setStringData( String stringData )
+    {
+        m_data = stringData;
+    }
+
+    /**
+    *  The character encoding, if known. The encoding must be a string
+    * acceptable for an XML encoding declaration ( section 4.3.3 "Character
+    * Encoding in Entities").
+    * <br>This attribute has no effect when the application provides a
+    * character stream. For other sources of input, an encoding specified
+    * by means of this attribute will override any encoding specified in
+    * the XML claration or the Text Declaration, or an encoding obtained
+    * from a higher level protocol, such as HTTP .
+    */
+    public String getEncoding()
+    {
+        return m_encoding;
+    }
+
+    /**
+    *  The character encoding, if known. The encoding must be a string
+    * acceptable for an XML encoding declaration ( section 4.3.3 "Character
+    * Encoding in Entities").
+    * <br>This attribute has no effect when the application provides a
+    * character stream. For other sources of input, an encoding specified
+    * by means of this attribute will override any encoding specified in
+    * the XML claration or the Text Declaration, or an encoding obtained
+    * from a higher level protocol, such as HTTP .
+    */
+    public void setEncoding( String encoding )
+    {
+        m_encoding = encoding;
+    }
+
+    /**
+    * The public identifier for this input source. The public identifier is
+    * always optional: if the application writer includes one, it will be
+    * provided as part of the location information.
+    */
+    public String getPublicId()
+    {
+        return m_publicId;
+    }
+    /**
+    * The public identifier for this input source. The public identifier is
+    * always optional: if the application writer includes one, it will be
+    * provided as part of the location information.
+    */
+    public void setPublicId( String publicId )
+    {
+        m_publicId = publicId;
+    }
+
+    /**
+    * The system identifier, a URI reference , for this input source. The
+    * system identifier is optional if there is a byte stream or a
+    * character stream, but it is still useful to provide one, since the
+    * application can use it to resolve relative URIs and can include it in
+    * error messages and warnings (the parser will attempt to fetch the
+    * ressource identifier by the URI reference only if there is no byte
+    * stream or character stream specified).
+    * <br>If the application knows the character encoding of the object
+    * pointed to by the system identifier, it can register the encoding by
+    * setting the encoding attribute.
+    * <br>If the system ID is a relative URI reference (see section 5 in ),
+    * the behavior is implementation dependent.
+    */
+    public String getSystemId()
+    {
+        return m_systemId;
+    }
+    /**
+    * The system identifier, a URI reference , for this input source. The
+    * system identifier is optional if there is a byte stream or a
+    * character stream, but it is still useful to provide one, since the
+    * application can use it to resolve relative URIs and can include it in
+    * error messages and warnings (the parser will attempt to fetch the
+    * ressource identifier by the URI reference only if there is no byte
+    * stream or character stream specified).
+    * <br>If the application knows the character encoding of the object
+    * pointed to by the system identifier, it can register the encoding by
+    * setting the encoding attribute.
+    * <br>If the system ID is a relative URI reference (see section 5 in ),
+    * the behavior is implementation dependent.
+    */
+    public void setSystemId( String systemId )
+    {
+        m_systemId = systemId;
+    }
+
+   /**
+    *  The base URI to be used (see section 5.1.4 in ) for resolving relative
+    * URIs to absolute URIs. If the baseURI is itself a relative URI, the
+    * behavior is implementation dependent.
+    */
+    public String getBaseURI()
+    {
+        return m_base;
+    }
+    
+   /**
+    *  The base URI to be used (see section 5.1.4 in ) for resolving relative
+    * URIs to absolute URIs. If the baseURI is itself a relative URI, the
+    * behavior is implementation dependent.
+    */
+    public void setBaseURI( String baseURI )
+    {
+        m_base = baseURI;
+    }
+
+   /**
+    *  If set to true, assume that the input is certified (see section 2.13
+    * in [<a href='http://www.w3.org/TR/2002/CR-xml11-20021015/'>XML 1.1</a>]) when
+    * parsing [<a href='http://www.w3.org/TR/2002/CR-xml11-20021015/'>XML 1.1</a>].
+    */
+    public boolean getCertifiedText()
+    {
+        return m_certified;
+    }
+
+   /**
+    *  If set to true, assume that the input is certified (see section 2.13
+    * in [<a href='http://www.w3.org/TR/2002/CR-xml11-20021015/'>XML 1.1</a>]) when
+    * parsing [<a href='http://www.w3.org/TR/2002/CR-xml11-20021015/'>XML 1.1</a>].
+    */
+    public void setCertifiedText( boolean certifiedText )
+    {
+        m_certified = certifiedText;
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/DefaultPartManager.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/DefaultPartManager.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/DefaultPartManager.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 Stephen McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import net.dpml.lang.PartManager;
+
+/**
+ * Abstract base class for artifact content handler.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class DefaultPartManager implements PartManager
+{
+    private final Part m_part;
+    
+    DefaultPartManager( Part part )
+    {
+        m_part = part;
+    }
+    
+   /**
+    * Returns the part URI as a string.
+    * @return the codebase uri
+    */
+    public String getCodebaseURI()
+    {
+        return m_part.getCodebaseURI();
+    }
+    
+   /**
+    * Returns the part title.
+    * @return the title
+    */
+    public String getTitle()
+    {
+        return m_part.getTitle();
+    }
+    
+   /**
+    * Returns the part description.
+    * @return the description
+    */
+    public String getDescription()
+    {
+        return m_part.getDescription();
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/Disposable.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/Disposable.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/Disposable.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+/**
+ * The Disposable interface is implemented by a disposable sub-system within Transit.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Disposable
+{
+   /**
+    * Dispose of the service.  During disposal a sub-system is required to 
+    * release all references such as listeners and internal resources
+    * in preparation for garbage collection.
+    */
+    void dispose();
+}
+

Added: trunk/main/lang/part/src/main/dpml/lang/DocumentRuntimeException.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/DocumentRuntimeException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/DocumentRuntimeException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+/**
+ * Exception throw in the event of a DOM parse fatal condition.
+ 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DocumentRuntimeException extends RuntimeException
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>ValueRuntimeException</code> instance.
+     *
+     * @param message the exception message
+     */
+    public DocumentRuntimeException( final String message )
+    {
+        super( message );
+    }
+
+    /**
+     * Construct a new <code>ValueRuntimeException</code> instance.
+     *
+     * @param message the exception message
+     * @param cause the causal exception
+     */
+    public DocumentRuntimeException( final String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
+

Added: trunk/main/lang/part/src/main/dpml/lang/Info.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/Info.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/Info.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.util.Arrays;
+
+import javax.xml.XMLConstants;
+
+import net.dpml.util.Logger;
+import dpml.util.ObjectUtils;
+
+
+/**
+ * Part info description.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class Info
+{
+    private final String m_title;
+    private final String m_description;
+    private final URI m_uri;
+    
+   /**
+    * Creation of a new part info descriptor.
+    * @param uri the part uri
+    * @param title the title of the part
+    * @param description the part description
+    */
+    public Info( URI uri, String title, String description )
+    {
+        m_uri = uri;
+        m_title = title;
+        m_description = description;
+    }
+    
+   /**
+    * Get the part uri.
+    *
+    * @return the uri
+    */
+    public URI getURI()
+    {
+        return m_uri;
+    }
+    
+   /**
+    * Get the part title.
+    *
+    * @return the title
+    */
+    public String getTitle()
+    {
+        return m_title;
+    }
+    
+   /**
+    * Get the part description.
+    *
+    * @return the description
+    */
+    public String getDescription()
+    {
+        return m_description;
+    }
+    
+   /**
+    * Test if this instance is equal to the supplied instance.
+    * @param other the other instance
+    * @return the equality status
+    */
+    public boolean equals( Object other )
+    {
+        if( other instanceof Info )
+        {
+            Info info = (Info) other;
+            if( !ObjectUtils.equals( m_title, info.m_title ) )
+            {
+                return false;
+            }
+            else
+            {
+                return ObjectUtils.equals( m_description, info.m_description );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Get the hashcode for this instance.
+    * @return the hash value
+    */
+    public int hashCode()
+    {
+        int hash = getClass().hashCode();
+        hash ^= ObjectUtils.hashValue( m_title );
+        hash ^= ObjectUtils.hashValue( m_description );
+        return hash;
+    }
+}
\ No newline at end of file

Added: trunk/main/lang/part/src/main/dpml/lang/LoggingInvocationHandler.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/LoggingInvocationHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/LoggingInvocationHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+import java.util.Hashtable;
+
+import net.dpml.util.Logger;
+
+/**
+ * Invocation handler utility for the legacy net.dpml.util.Logger that
+ * redirects to an instance of net.dpml.util.Logger.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class LoggingInvocationHandler implements InvocationHandler
+{
+    //-------------------------------------------------------------------
+    // static
+    //-------------------------------------------------------------------
+    
+    private static final Map<String,Method> METHODS = getMethodMap();
+    
+   /**
+    * Construct a new context instance implementing the supplied class
+    * backed by entries in the supplied map.
+    *
+    * @param clazz the context class
+    * @param logger the logging channel
+    * @return the constructed context instance
+    */
+    public static <T>T getProxiedInstance( final Class<T> clazz, final Logger logger )
+    {
+        ClassLoader classloader = clazz.getClassLoader();
+        LoggingInvocationHandler handler = new LoggingInvocationHandler( clazz, logger );
+        final Object instance = 
+          Proxy.newProxyInstance( classloader, new Class[]{clazz}, handler );
+        return clazz.cast( instance );
+    }
+    
+    //-------------------------------------------------------------------
+    // state
+    //-------------------------------------------------------------------
+
+   /**
+    * Context datatype.
+    */
+    private final Logger m_logger;
+    private final Class m_class;
+    private final Map<String,Method> m_methods = new Hashtable<String,Method>();
+    
+    //-------------------------------------------------------------------
+    // constructor
+    //-------------------------------------------------------------------
+
+   /**
+    * Create a context invocation handler.
+    *
+    * @param map a map containing context key/value pairs.
+    */
+    private LoggingInvocationHandler( final Class clazz, final Logger logger )
+    {
+        m_logger = logger;
+        m_class = clazz;
+    }
+
+    //-------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------
+
+   /**
+    * Invoke the specified method on underlying object.
+    * This is called by the proxy object.
+    *
+    * @param proxy the proxy object
+    * @param method the method invoked on proxy object
+    * @param args the arguments supplied to method
+    * @return the return value of method
+    * @throws Throwable if an error occurs
+    */
+    @SuppressWarnings( "unchecked" )
+    public Object invoke( final Object proxy, final Method method, final Object[] args ) throws Throwable
+    {
+        String name = method.getName();
+        Method m = METHODS.get( name );
+        if( m.getReturnType() == Logger.class )
+        {
+            Logger logger = (Logger) m.invoke( m_logger, args );
+            return getProxiedInstance( m_class, logger );
+        }
+        else
+        {
+            return m.invoke( m_logger, args );
+        }
+    }
+    
+    private static Map<String,Method> getMethodMap()
+    {
+        Hashtable<String,Method> map = new Hashtable<String,Method>();
+        Method[] methods = Logger.class.getMethods();
+        for( Method method : methods )
+        {
+            map.put( method.getName(), method );
+        }
+        return map;
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/Part.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/Part.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/Part.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import dpml.util.ObjectUtils;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Hashtable;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.MBeanException;
+import javax.management.InstanceAlreadyExistsException;
+
+import javax.xml.XMLConstants;
+
+import dpml.util.Category;
+import net.dpml.lang.Buffer;
+import net.dpml.lang.Strategy;
+import net.dpml.lang.PartContentHandler;
+import net.dpml.lang.ServiceRegistry;
+import net.dpml.lang.SimpleServiceRegistry;
+import net.dpml.lang.PartManager;
+
+import net.dpml.util.Logger;
+
+/**
+ * Part datastructure.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class Part implements PartManager
+{
+    private final Info m_info;
+    private final Strategy m_strategy;
+    private final Classpath m_classpath;
+    
+   /**
+    * Creation of a new part datastructure.
+    * @param info the info descriptor
+    * @param classpath the part classpath definition
+    * @param strategy the part deployment strategy
+    * @exception IOException if an I/O error occurs
+    */
+    public Part( Info info, Classpath classpath, Strategy strategy ) throws IOException
+    {
+        if( null == info )
+        {
+            throw new NullPointerException( "info" );
+        }
+        if( null == strategy )
+        {
+            throw new NullPointerException( "strategy" );
+        }
+        
+        m_info = info;
+        m_strategy = strategy;
+        m_classpath = classpath;
+
+        String flag = System.getProperty( "dpml.jmx.enabled", "false" );
+        if( "true".equals( flag ) )
+        {
+            try
+            {
+                MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+                Hashtable<String,String> table = new Hashtable<String,String>();
+                table.put( "type", "Parts" );
+                table.put( "name", "" + System.identityHashCode( this ) );
+                ObjectName name =
+                  ObjectName.getInstance( "net.dpml.transit", table );
+                server.registerMBean( this, name );
+            }
+            catch( Exception e )
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+    
+   /**
+    * Service instantiation.
+    * @return the instantiated instance
+    * @exception IOException if an error occurs
+    * @deprecated Replaced by getInstance( Class<T> )
+    */
+    public Object getContent() throws IOException
+    {
+        return m_strategy.getContentForClass( Object.class );
+    }
+    
+   /**
+    * Return the part content or null if the result type is unresolvable 
+    * relative to the supplied classes argument. 
+    * @param classes the content type selection classes
+    * @return the content
+    * @exception IOException if an IO error occurs
+    * @deprecated Replaced by getContentForClass(Class) method
+    */
+    public Object getContent( Class[] classes ) throws IOException
+    {
+        if( classes.length == 0 )
+        {
+            return this;
+        }
+        else
+        {
+            for( int i=0; i<classes.length; i++ )
+            {
+                Class<?> c = classes[i];
+                Object content = m_strategy.getContentForClass( c );
+                if( null != content )
+                {
+                    return content;
+                }
+            }
+            return null;
+        }
+    }
+    
+    //-----------------------------------------------------------------------
+    // PartManager
+    //-----------------------------------------------------------------------
+    
+   /**
+    * Returns the part URI as a string.
+    * @return the codebase uri
+    */
+    public String getCodebaseURI()
+    {
+        return m_info.getURI().toASCIIString();
+    }
+    
+   /**
+    * Returns the part title.
+    * @return the title
+    */
+    public String getTitle()
+    {
+        return m_info.getTitle();
+    }
+    
+   /**
+    * Returns the part description.
+    * @return the description
+    */
+    public String getDescription()
+    {
+        return m_info.getDescription();
+    }
+    
+    //-----------------------------------------------------------------------
+    // Part
+    //-----------------------------------------------------------------------
+    
+   /**
+    * Get the part strategy.
+    *
+    * @return the strategy definition.
+    */
+    public Strategy getStrategy()
+    {
+        return m_strategy;
+    }
+    
+   /**
+    * Get the part classpath.
+    *
+    * @return the classpath definition.
+    */
+    public Classpath getClasspath()
+    {
+        return m_classpath;
+    }
+    
+   /**
+    * Instantiate a value.
+    * @param args supplimentary arguments
+    * @return the resolved instance
+    * @exception Exception if a deployment error occurs
+    * @deprecated Replaced by getInstance( Class<T>, Object[] )
+    */
+    public Object instantiate( Object[] args ) throws Exception
+    {
+        Strategy strategy = getStrategy();
+        ServiceRegistry registry = new SimpleServiceRegistry( args );
+        strategy.initialize( registry );
+        return strategy.getInstance( Object.class );
+    }
+    
+    public void save( OutputStream output ) throws IOException
+    {
+        final Writer writer = new OutputStreamWriter( output );
+        Buffer b = new Buffer( writer, PartContentHandler.NAMESPACE, "" );
+        try
+        {
+            b.write( XML_HEADER );
+            b.nl( "\n" + PART_HEADER );
+            Buffer b2 = b.indent( "  " );
+            encodeInfo( b2, m_info );
+            Strategy strategy = getStrategy();
+            strategy.encode( b2, null );
+            encodeClasspath( b2, getClasspath() );
+            b.nl( PART_FOOTER );
+            b.nl( "" );
+        }
+        finally
+        {
+            writer.flush();
+            output.close();
+        }
+    }
+    
+   /**
+    * Test if this part is equivalent to the supplied part.
+    *
+    * @param other the other object
+    * @return true if the parts are equivalent
+    */
+    public boolean equals( Object other )
+    {
+        if( other instanceof Part )
+        {
+            Part part = (Part) other;
+            if( !m_info.equals( part.m_info ) )
+            {
+                return false;
+            }
+            else if( !m_classpath.equals( part.m_classpath ) )
+            {
+                return false;
+            }
+            else
+            {
+                return m_strategy.equals( part.m_strategy );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Get the part hashcode.
+    *
+    * @return the hash value
+    */
+    public int hashCode()
+    {
+        int hash = m_info.hashCode();
+        hash ^= m_strategy.hashCode();
+        hash ^= m_classpath.hashCode();
+        return hash;
+    }
+    
+    private static void encodeInfo( Buffer b, Info info ) throws IOException
+    {
+        String title = info.getTitle();
+        String description = info.getDescription();
+        if( null == description )
+        {
+            if( null == title )
+            {
+                b.nl( "<info/>" );
+            }
+            else
+            {
+                b.nl( "<info title=\"" + title + "\"/>" );
+            }
+        }
+        else
+        {
+            if( null == title )
+            {
+                b.nl( "<info>" );
+            }
+            else
+            {
+                b.nl( "<info title=\"" + title + "\">" );
+            }
+            Buffer b2 = b.indent();
+            b2.nl( "<description>" + description + "</description>" );
+            b.nl( "</info>" );
+        }
+    }
+
+    private static void encodeClasspath( Buffer b, Classpath classpath ) throws IOException
+    {
+        b.nl( "<classpath>" );
+        if( null != classpath ) 
+        {
+            Buffer b2 = b.indent();
+            encodeClasspathCategory( b2, classpath, Category.SYSTEM );
+            encodeClasspathCategory( b2, classpath, Category.PUBLIC );
+            encodeClasspathCategory( b2, classpath, Category.PROTECTED );
+            encodeClasspathCategory( b2, classpath, Category.PRIVATE );
+        }
+        b.nl( "</classpath>" );
+    }
+
+    private static void encodeClasspathCategory( 
+      Buffer b, Classpath classpath, Category category ) throws IOException
+    {
+        URI[] uris = classpath.getDependencies( category );
+        if( uris.length > 0 )
+        {
+            String name = category.name().toLowerCase();
+            b.nl( "<" + name + ">" );
+            Buffer b2 = b.indent();
+            for( int i=0; i<uris.length; i++ )
+            {
+                URI uri = uris[i];
+                b2.nl( "<uri>" + uri.toASCIIString() + "</uri>" );
+            }
+            b.nl( "</" + name + ">" );
+        }
+    }
+    
+   /**
+    * Default XML header.
+    */
+    private static final String XML_HEADER = "<?xml version=\"1.0\"?>";
+
+   /**
+    * Part header.
+    */
+    private static final String PART_HEADER = 
+      "<part xmlns=\"" 
+      + PartContentHandler.NAMESPACE 
+      + "\""
+      + "\n    xmlns:xsi=\"" 
+      + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
+      + "\">";
+      
+   /**
+    * Part footer.
+    */
+    private static final String PART_FOOTER = "</part>";
+}

Added: trunk/main/lang/part/src/main/dpml/lang/StandardNamespaceResolver.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/StandardNamespaceResolver.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/StandardNamespaceResolver.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+import net.dpml.lang.NamespaceError;
+
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+
+/**
+ * LSInput resolver service.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class StandardNamespaceResolver implements LSResourceResolver
+{
+   /**
+    * Return the schema definition for a supplied namespace. This implementation 
+    * handles the resolution of the standard DPML language XDSs through the binding
+    * standard schema uris to resource resolvable from the context classloader.
+    * 
+    * Standard schema uris include:
+    *
+    * <ul>
+    *   <li>dpml:part</li>
+    *   <li>dpml:metro</li>
+    *   <li>dpml:state</li>
+    *   <li>dpml:antlib</li>
+    *   <li>dpml:library</li>
+    * </ul>
+    *
+    * @param type the node type
+    * @param namespace the node namespace
+    * @param publicId the public id
+    * @param systemId the system id
+    * @param base the base value
+    * @return the LS input instance or null if not recognized
+    */
+    public LSInput resolveResource( 
+      String type, String namespace, String publicId, String systemId, String base )
+    {
+        URL url = getNamespaceURL( namespace );
+        if( null == url )
+        {
+            return null;
+        }
+        try
+        {
+            DOMInput input = new DOMInput();
+            input.setPublicId( publicId );
+            input.setSystemId( systemId );
+            input.setBaseURI( base );
+            InputStream stream = url.openStream();
+            InputStreamReader reader = new InputStreamReader( stream );
+            input.setCharacterStream( reader );
+            return input;
+        }
+        catch( Exception e )
+        {
+            final String error = 
+              "Internal error while resolving the resource for the namespace ["
+              + namespace 
+              + "].";
+              
+            throw new NamespaceError( error, e );
+        }
+    }
+    
+    private URL getNamespaceURL( String namespace )
+    {
+        ClassLoader classloader = getClass().getClassLoader();
+        if( "dpml:part".equals( namespace ) )
+        {
+            return classloader.getResource( "dpml/lang/dpml-lang-part.xsd" );
+        }
+        else if( "dpml:metro".equals( namespace ) )
+        {
+            return classloader.getResource( "dpml/lang/dpml-lang-component.xsd" );
+        }
+        else if( "dpml:state".equals( namespace ) )
+        {
+            return classloader.getResource( "dpml/lang/dpml-lang-state.xsd" );
+        }
+        else if( "dpml:antlib".equals( namespace ) )
+        {
+            return classloader.getResource( "dpml/lang/dpml-lang-resource.xsd" );
+        }
+        else if( "dpml:library".equals( namespace ) )
+        {
+            return classloader.getResource( "dpml/lang/dpml-lang-library.xsd" );
+        }
+        else
+        {
+            return null;
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/Value.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/Value.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/Value.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.io.IOException;
+import java.util.Map;
+
+import net.dpml.lang.Buffer;
+
+/**
+ * An object resolvable from primitive and symbolic arguments.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Value
+{
+   /**
+    * Resolve an instance from the value using the context classloader.
+    * @return the resolved instance
+    * @exception Exception if error occurs during instance resolution
+    */
+    Object resolve() throws Exception;
+    
+   /**
+    * Resolve an instance from the value using a supplied context map. If any 
+    * target expressions in immediate or nested values contain a symbolic
+    * expression the value will be resolved using the supplied map.
+    *
+    * @param map the context map
+    * @return the resolved instance
+    * @exception Exception if error occurs during instance resolution
+    */
+    Object resolve( Map<String,Object> map ) throws Exception;
+
+   /**
+    * Resolve an instance from the value using a supplied context map. If any 
+    * target expressions in immediate or nested values contain a symbolic
+    * expression the value will be resolved using the supplied map.
+    *
+    * @param type the type
+    * @param map the context map
+    * @return the resolved instance
+    * @exception Exception if error occurs during instance resolution
+    */
+    Object resolve( Class<?> type, Map<String,Object> map ) throws Exception;
+    
+    void encode( Buffer buffer ) throws IOException;
+    
+    void encode( Buffer buffer, String label, String key ) throws IOException;
+
+}

Added: trunk/main/lang/part/src/main/dpml/lang/ValueDecoder.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/ValueDecoder.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/ValueDecoder.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import dpml.lang.Construct;
+
+import dpml.util.ElementHelper;
+
+import net.dpml.util.Resolver;
+
+import org.w3c.dom.Element;
+
+/**
+ * Utility used to decode values from DOM elements.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class ValueDecoder
+{
+   /**
+    * Build an array of values for the supplied element array.
+    * @param elements the elements
+    * @param resolver symbolic value property resolver
+    * @return the resolved values
+    */
+    public Value[] decodeValues( Element[] elements, Resolver resolver )
+    {
+        Value[] values = new Value[ elements.length ];
+        for( int i=0; i<elements.length; i++ )
+        {
+            values[i] = decodeValue( elements[i], resolver );
+        }
+        return values;
+    }
+    
+   /**
+    * Build a single value instance from a supplied element.
+    * @param element the element
+    * @param resolver symbolic value property resolver
+    * @return the resolved value
+    */
+    public Value decodeValue( Element element, Resolver resolver )
+    {
+        String classname = ElementHelper.getAttribute( element, "class", null, resolver );
+        String method = ElementHelper.getAttribute( element, "method", null, resolver );
+        Element[] elements = ElementHelper.getChildren( element, "param" );
+        if( elements.length > 0 )
+        {
+            Value[] values = decodeValues( elements, resolver );
+            return new Construct( classname, method, values );
+        }
+        else
+        {
+            String value = ElementHelper.getAttribute( element, "value", null, resolver );
+            return new Construct( classname, method, value );
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/lang/ValueException.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/ValueException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/ValueException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+/**
+ * Exception to indicate an error arrising from a value type.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ValueException extends Exception
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>ValueException</code> instance.
+     *
+     * @param message the exception message
+     */
+    public ValueException( final String message )
+    {
+        super( message );
+    }
+
+    /**
+     * Construct a new <code>ValueException</code> instance.
+     *
+     * @param message the exception message
+     * @param cause the causal exception
+     */
+    public ValueException( final String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
+

Added: trunk/main/lang/part/src/main/dpml/lang/ValueRuntimeException.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/lang/ValueRuntimeException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/lang/ValueRuntimeException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+/**
+ * Exception to indicate an error arrising from a value type.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ValueRuntimeException extends RuntimeException
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>ValueRuntimeException</code> instance.
+     *
+     * @param message the exception message
+     */
+    public ValueRuntimeException( final String message )
+    {
+        super( message );
+    }
+
+    /**
+     * Construct a new <code>ValueRuntimeException</code> instance.
+     *
+     * @param message the exception message
+     * @param cause the causal exception
+     */
+    public ValueRuntimeException( final String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
+

Added: trunk/main/lang/part/src/main/dpml/state/DefaultInterface.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/DefaultInterface.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/DefaultInterface.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+import net.dpml.state.Interface;
+
+import java.io.Serializable;
+
+/**
+ * Default implementation of an operation.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DefaultInterface implements Interface, Serializable
+{
+    private final String m_classname;
+    
+   /**
+    * Creation of a new interface declaration.
+    * @param classname the overriding method name
+    * @exception NullPointerException if the operation name is null
+    */
+    public DefaultInterface( String classname ) throws NullPointerException
+    {
+        if( null == classname )
+        {
+            throw new NullPointerException( "classname" );
+        }
+        m_classname = classname;
+    }
+    
+   /**
+    * Overriden method returning the interface classname.
+    * @return the name (interface classname)
+    * @see #getClassname()
+    */
+    public String getName()
+    {
+        return getClassname();
+    }
+    
+   /**
+    * Return the interface classname.
+    * @return the classname
+    */
+    public String getClassname()
+    {
+        return m_classname;
+    }
+    
+   /**
+    * Return a string representation of the instance.
+    * @return the string value
+    */
+    public String toString()
+    {
+        return "interface:" + m_classname;
+    }
+    
+   /**
+    * Compare this object to another for equality.
+    * @param other the other object
+    * @return true if the object is equal to this object
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        else if( other instanceof DefaultInterface )
+        {
+            DefaultInterface description = (DefaultInterface) other;
+            return m_classname.equals( description.m_classname );
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Compute the hashcode for this instance.
+    * @return the hashcode value
+    */
+    public int hashCode()
+    {
+        int hash = getClass().hashCode();
+        hash ^= m_classname.hashCode();
+        return hash;
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/state/DefaultOperation.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/DefaultOperation.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/DefaultOperation.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+import java.io.Serializable;
+
+import net.dpml.state.Operation;
+
+/**
+ * Default implementation of an operation.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DefaultOperation implements Operation, Serializable
+{
+    private final String m_name;
+    private final String m_method;
+    
+   /**
+    * Creation of a new operation.
+    * @param name the operation name
+    * @exception NullPointerException if the operation name is null
+    */
+    public DefaultOperation( final String name ) throws NullPointerException
+    {
+        this( name, null );
+    }
+    
+   /**
+    * Creation of a new operation.
+    * @param name the operation name
+    * @param method the overriding method name
+    * @exception NullPointerException if the operation name is null
+    */
+    public DefaultOperation( final String name, String method ) throws NullPointerException
+    {
+        if( null == name )
+        {
+            throw new NullPointerException( "name" );
+        }
+        m_name = name;
+        m_method = method;
+    }
+    
+   /**
+    * Return the action name.
+    * @return the name
+    */
+    public String getName()
+    {
+        return m_name;
+    }
+    
+   /**
+    * Return the optional overriding method name.  If the 
+    * value returned is null the method shall be assumed to be the 
+    * equivalent of "get[Name]().
+    * @return the operation method name
+    */
+    public String getMethodName()
+    {
+        return m_method;
+    }
+    
+   /**
+    * Return a string representation of the instance.
+    * @return the string value
+    */
+    public String toString()
+    {
+        return "operation:" + m_name;
+    }
+    
+   /**
+    * Compare this object to another for equality.
+    * @param other the other object
+    * @return true if the object is equal to this object
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        else if( other instanceof DefaultOperation )
+        {
+            DefaultOperation operation = (DefaultOperation) other;
+            
+            if( !m_name.equals( operation.getName() ) )
+            {
+                return false;
+            }
+            else if( null == m_method )
+            {
+                return null == operation.m_method;
+            }
+            else
+            {
+                return m_method.equals( operation.m_method );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Compute the hashcode for this instance.
+    * @return the hashcode value
+    */
+    public int hashCode()
+    {
+        int hash = getClass().hashCode();
+        hash ^= m_name.hashCode();
+        if( null != m_method )
+        {
+            hash ^= m_method.hashCode();
+        }
+        return hash;
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/state/DefaultState.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/DefaultState.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/DefaultState.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import net.dpml.state.Action;
+import net.dpml.state.Interface;
+import net.dpml.state.Operation;
+import net.dpml.state.State;
+import net.dpml.state.Transition;
+import net.dpml.state.Trigger;
+
+/**
+ * Default implementation of an application state descriptor.
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DefaultState implements State, Serializable
+{
+   /**
+    * Null state.
+    */
+    public static final State NULL_STATE = new NullState();
+
+    private final String m_name;
+    private final Transition[] m_transitions;
+    private final Operation[] m_operations;
+    private final Interface[] m_interfaces;
+    private final State[] m_states;
+    private final Trigger[] m_triggers;
+    private final boolean m_terminal;
+    
+    private transient State m_parent;
+
+   /**
+    * Creation of a new state.
+    */
+    public DefaultState()
+    {
+        this( "root" );
+    }
+    
+   /**
+    * Creation of a new state.
+    * @param name the state name
+    */
+    public DefaultState( final String name )
+    {
+        this( name, new Trigger[0], new Transition[0], new Interface[0], new Operation[0], new State[0], true );
+    }
+    
+   /**
+    * Creation of a new non-terminal state.
+    * @param name the state name
+    * @param triggers an array of triggers
+    * @param transitions an array of state transitions
+    * @param interfaces an array of management interface declarations
+    * @param operations an array of operations
+    * @param states an array of substates
+    */
+    public DefaultState( 
+      final String name, final Trigger[] triggers, final Transition[] transitions, 
+      final Interface[] interfaces, final Operation[] operations, final State[] states )
+    {
+        this( name, triggers, transitions, interfaces, operations, states, false );
+    }
+    
+   /**
+    * Creation of a new state.
+    * @param name the state name
+    * @param triggers an array of triggers
+    * @param transitions an array of state transitions
+    * @param interfaces an array of management interface declarations
+    * @param operations an array of operations
+    * @param states an array of substates
+    * @param terminal the terminal flag
+    */
+    public DefaultState( 
+      final String name, final Trigger[] triggers, final Transition[] transitions, 
+      final Interface[] interfaces, final Operation[] operations, final State[] states, boolean terminal )
+    {
+        if( null == name )
+        {
+            throw new NullPointerException( "name" );
+        }
+        
+        for( int i=0; i<operations.length; i++ )
+        {
+            Operation operation = operations[i];
+            if( null == operation )
+            {
+                throw new NullPointerException( "operation/" + i );
+            }
+        }
+        
+        m_name = name;
+        m_triggers = triggers;
+        m_transitions = transitions;
+        m_operations = operations;
+        m_interfaces = interfaces;
+        m_states = states;
+        m_terminal = terminal;
+        
+        for( int i=0; i<transitions.length; i++ )
+        {
+            Transition transition = transitions[i];
+            if( null == transition )
+            {
+                throw new NullPointerException( "transition/" + i );
+            }
+            transition.setState( this );
+        }
+        
+        for( int i=0; i<triggers.length; i++ )
+        {
+            Trigger trigger = triggers[i];
+            if( null == trigger )
+            {
+                throw new NullPointerException( "trigger/" + i );
+            }
+            Action action = trigger.getAction();
+            if( action instanceof Transition )
+            {
+                Transition transition = (Transition) action;
+                transition.setState( this );
+            }
+        }
+        
+        for( int i=0; i<interfaces.length; i++ )
+        {
+            Interface description = interfaces[i];
+            if( null == description )
+            {
+                throw new NullPointerException( "interface/" + i );
+            }
+        }
+        
+        for( int i=0; i<states.length; i++ )
+        {
+            State state = states[i];
+            if( null == state )
+            {
+                throw new NullPointerException( "state/ " + i );
+            }
+            state.setParent( this );
+        }
+    }
+    
+   /**
+    * Return the parent state to this state or null if this is the root of a 
+    * state graph.
+    * @return the parent state
+    */
+    public State getParent()
+    {
+        return m_parent;
+    }
+
+   /**
+    * Set the parent state. 
+    * @param state the parent state
+    */
+    public void setParent( State state )
+    {
+        if( null == m_parent )
+        {
+            m_parent = state;
+        }
+        else
+        {
+            final String error = 
+              "Illegal attempt to reassign parent.";
+            throw new IllegalStateException( error );
+        }
+    }
+    
+   /**
+    * Return the name of the state.
+    * @return the state name
+    */
+    public String getName()
+    {
+        return m_name;
+    }
+    
+   /**
+    * Return the array of triggers associated with the state.
+    * @return the trigger array
+    */
+    public Trigger[] getTriggers()
+    {
+        return m_triggers;
+    }
+    
+   /**
+    * Return the state path.  The path is composed of a sequence of states
+    * from the root to this state.
+    * @return the state path
+    */
+    public State[] getStatePath()
+    {
+        if( null == m_parent )
+        {
+            return new State[]{this};
+        }
+        else
+        {
+            State[] path = m_parent.getStatePath();
+            State[] result = new State[ path.length + 1 ];
+            System.arraycopy( path, 0, result, 0, path.length );
+            result[ path.length ] = this;
+            return result;
+        }
+    }
+    
+   /**
+    * Return the substates within this state.
+    * @return the substate array
+    */
+    public State[] getStates()
+    {
+        return m_states;
+    }
+    
+   /**
+    * Return the array of transtions associated with the state.
+    * @return the transition array
+    */
+    public Transition[] getTransitions()
+    {
+        return m_transitions;
+    }
+    
+   /**
+    * Return the array of operations associated with the state.
+    * @return the operation array
+    */
+    public Operation[] getOperations()
+    {
+        return m_operations;
+    }
+    
+   /**
+    * Return the array of management interfaces associated with the state.
+    * @return the interfaces array
+    */
+    public Interface[] getInterfaces()
+    {
+        return m_interfaces;
+    }
+    
+   /**
+    * Return the terminal flag.
+    * @return true if terminal
+    */
+    public boolean getTerminal()
+    {
+        return isTerminal();
+    }
+    
+   /**
+    * Test is the state is a terminal state.
+    * @return true if terminal
+    */
+    public boolean isTerminal()
+    {
+        return m_terminal;
+    }
+    
+   /**
+    * Return a string representation of the instance.
+    * @return the string value
+    */
+    public String toString()
+    {
+        StringBuffer buffer = new StringBuffer();
+        State[] path = getStatePath();
+        for( int i=0; i<path.length; i++ )
+        {
+            State state = path[i];
+            if( i>0 )
+            {
+                buffer.append( "/" );
+            }
+            buffer.append( state.getName() );
+        }
+        return buffer.toString();
+    }
+    
+   /**
+    * Compare this object to another for equality.
+    * @param other the other object
+    * @return true if the object is equal to this object
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        else if( other instanceof DefaultState )
+        {
+            DefaultState state = (DefaultState) other;
+            if( !m_name.equals( state.getName() ) )
+            {
+                return false;
+            }
+            else if( m_terminal != state.isTerminal() )
+            {
+                return false;
+            }
+            else if( !Arrays.equals( m_triggers, state.getTriggers() ) )
+            {
+                return false;
+            }
+            else if( !Arrays.equals( m_transitions, state.getTransitions() ) )
+            {
+                return false;
+            }
+            else if( !Arrays.equals( m_operations, state.getOperations() ) )
+            {
+                return false;
+            }
+            else
+            {
+                return Arrays.equals( m_states, state.getStates() );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Compute the hashcode for this instance.
+    * @return the hashcode value
+    */
+    public int hashCode()
+    {
+        if( null == m_parent )
+        {
+            return m_name.hashCode();
+        }
+        else
+        {
+            int hash = m_parent.hashCode();
+            hash ^= m_name.hashCode();
+            return hash;
+        }
+    }
+
+    private boolean equals( Object a, Object b )
+    {
+        if( null == a )
+        {
+            return null == b;
+        }
+        else
+        {
+            return a.equals( b );
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/state/DefaultTransition.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/DefaultTransition.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/DefaultTransition.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+import java.io.Serializable;
+
+import net.dpml.state.State;
+import net.dpml.state.Transition;
+import net.dpml.state.Operation;
+
+/**
+ * Default implemention of a state transition descriptor.
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DefaultTransition implements Transition, Serializable
+{
+    private final String m_name;
+    private final String m_target;
+    private final Operation m_operation;
+    
+    private transient State m_state;
+    
+   /**
+    * Creation of a new transition.
+    * @param name the transition name
+    * @param target the transit target state name
+    */
+    public DefaultTransition( final String name, final String target )
+    {
+        this( name, target, null );
+    }
+    
+   /**
+    * Creation of a new transition.
+    * @param name the transition name
+    * @param target the transit target state name
+    * @param operation optional transition operation
+    */
+    public DefaultTransition( final String name, final String target, final Operation operation )
+    {
+        if( null == name )
+        {
+            throw new NullPointerException( "name" );
+        }
+        if( null == target )
+        {
+            throw new NullPointerException( "target" );
+        }
+        m_name = name;
+        m_target = target;
+        m_operation = operation;
+    }
+    
+   /**
+    * Set the state that this transition is a part of.
+    * @param state the owning state
+    */
+    public void setState( State state )
+    {
+        if( null == state )
+        {
+            throw new NullPointerException( "state" );
+        }
+        if( null == m_state )
+        {
+            m_state = state;
+        }
+        else
+        {
+            throw new IllegalStateException( "State already set." );
+        }
+    }
+    
+   /**
+    * Return the state that this transition is a part of.
+    * @return the owning state
+    */
+    public State getState()
+    {
+        if( null != m_state )
+        {
+            return m_state;
+        }
+        else
+        {
+            throw new IllegalStateException( "Enclosing state has not been declared." );
+        }
+    }
+    
+   /**
+    * Return the transition name
+    * @return the name
+    */
+    public String getName()
+    {
+        return m_name;
+    }
+    
+   /**
+    * Return the transition target state name
+    * @return the target state name
+    */
+    public String getTargetName()
+    {
+        return m_target;
+    }
+    
+   /**
+    * Return an operation associated with the transition.
+    * @return a possibly null operation
+    */
+    public Operation getOperation()
+    {
+        return m_operation;
+    }
+    
+   /**
+    * Compare this object to another for equality.
+    * @param other the other object
+    * @return true if the object is equal to this object
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        else if( other instanceof DefaultTransition )
+        {
+            DefaultTransition transition = (DefaultTransition) other;
+            if( !m_name.equals( transition.getName() ) )
+            {
+                return false;
+            }
+            else if( !equals( m_target, transition.getTargetName() ) )
+            {
+                return false;
+            }
+            else 
+            {
+                return equals( m_operation, transition.getOperation() );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Compute the hashcode for this instance.
+    * @return the hashcode value
+    */
+    public int hashCode()
+    {
+        int hash = m_name.hashCode();
+        hash ^= m_target.hashCode();
+        if( m_operation != null )
+        {
+            hash ^= m_operation.hashCode();
+        }
+        return hash;
+    }
+    
+    private boolean equals( Object a, Object b )
+    {
+        if( null == a )
+        {
+            return null == b;
+        }
+        else
+        {
+            return a.equals( b );
+        }
+    }
+    
+   /**
+    * Return a string representation of the instance.
+    * @return the string value
+    */
+    public String toString()
+    {
+        return "transition:" + getName() + " (target=" + m_target + ")";
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/state/DefaultTrigger.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/DefaultTrigger.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/DefaultTrigger.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+import java.io.Serializable;
+
+import net.dpml.state.Trigger;
+import net.dpml.state.TriggerPolicy;
+import net.dpml.state.Action;
+
+/**
+ * Default implementation of trigger.
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DefaultTrigger implements Trigger, Serializable
+{
+    private final TriggerPolicy m_policy;
+    private final Action m_action;
+    
+   /**
+    * Creation of a new trigger.
+    * @param event the trigger event constant
+    * @param action the action fired by the trigger
+    */
+    public DefaultTrigger( final TriggerPolicy event, final Action action )
+    {
+        if( null == event )
+        {
+            throw new NullPointerException( "event" );
+        }
+        if( null == action )
+        {
+            throw new NullPointerException( "action" );
+        }
+        m_policy = event;
+        m_action = action;
+    }
+    
+   /**
+    * Return the event enumneration that this trigger is associated with.
+    * @return the triggering event class
+    */
+    public TriggerPolicy getPolicy()
+    {
+        return m_policy;
+    }
+    
+   /**
+    * Return the actions  that this trigger initiates.
+    * @return the triggered action
+    */
+    public Action getAction()
+    {
+        return m_action;
+    }
+    
+   /**
+    * Compare this object to another for equality.
+    * @param other the other object
+    * @return true if the object is equal to this object
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        else if( other instanceof DefaultTrigger )
+        {
+            DefaultTrigger trigger = (DefaultTrigger) other;
+            if( !m_policy.equals( trigger.getPolicy() ) )
+            {
+                return false;
+            }
+            else
+            {
+                return m_action.equals( trigger.getAction() );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Compute the hashcode for this instance.
+    * @return the hashcode value
+    */
+    public int hashCode()
+    {
+        int hash = m_policy.hashCode();
+        hash ^= m_action.hashCode();
+        return hash;
+    }
+
+   /**
+    * Return a string representation of the instance.
+    * @return the string value
+    */
+    public String toString()
+    {
+        return "trigger:" + m_policy.name().toUpperCase();
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/state/NullState.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/NullState.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/NullState.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+import java.io.Serializable;
+
+import net.dpml.state.State;
+import net.dpml.state.Transition;
+import net.dpml.state.Operation;
+import net.dpml.state.Interface;
+import net.dpml.state.Trigger;
+
+/**
+ * Null state implementation.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class NullState implements State, Serializable
+{   
+   /**
+    * Return the name of the state.
+    * @return the state name
+    */
+    public String getName()
+    {
+        return "";
+    }
+    
+   /**
+    * Set the parent state. 
+    * @param state the parent state
+    */
+    public void setParent( State state )
+    {
+    }
+
+   /**
+    * Return the parent state to this state or null if this is 
+    * the root of a state graph.
+    * @return the parent state
+    */
+    public State getParent()
+    {
+        return null;
+    }
+    
+   /**
+    * Return the state path.  The path is composed of a sequence of 
+    * states from the root to this state.
+    * @return the state path
+    */
+    public State[] getStatePath()
+    {
+        return new State[0];
+    }
+    
+   /**
+    * Return the substates within this state.
+    * @return the substate array
+    */
+    public State[] getStates()
+    {
+        return new State[0];
+    }
+    
+   /**
+    * Return the array of triggers associated with the state.
+    * @return the trigger array
+    */
+    public Trigger[] getTriggers()
+    {
+        return new Trigger[0];
+    }
+    
+   /**
+    * Return the array of transtions associated with the state.
+    * @return the transition array
+    */
+    public Transition[] getTransitions()
+    {
+        return new Transition[0];
+    }
+    
+   /**
+    * Return the array of operations associated with the state.
+    * @return the operation array
+    */
+    public Operation[] getOperations()
+    {
+        return new Operation[0];
+    }
+    
+   /**
+    * Return the array of operations associated with the state.
+    * @return the operation array
+    */
+    public Interface[] getInterfaces()
+    {
+        return new Interface[0];
+    }
+    
+   /**
+    * Test is the state is a terminal state.
+    * @return true if terminal
+    */
+    public boolean isTerminal()
+    {
+        return false;
+    }
+    
+   /**
+    * Test is this state is equal to the supplied object.
+    * @param other the other object
+    * @return true if equal
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        else
+        {
+            return ( other instanceof NullState );
+        }
+    }
+    
+   /**
+    * Calcualte the hashcode for this instance.
+    * @return the hashcode value
+    */
+    public int hashCode()
+    {
+        return getClass().hashCode();
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/state/StateBuilderRuntimeException.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/StateBuilderRuntimeException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/StateBuilderRuntimeException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+/**
+ * Exception thrown when an error occurs during state graph construction.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StateBuilderRuntimeException extends RuntimeException
+{
+   /**
+    * Construct a new <code>StateBuilderRuntimeException</code> instance.
+    *
+    * @param message the exception message
+    */
+    public StateBuilderRuntimeException( String message )
+    {
+        this( message, null );
+    }
+    
+   /**
+    * Construct a new <code>StateBuilderRuntimeException</code> instance.
+    *
+    * @param message the exception message
+    * @param cause the causal exception
+    */
+    public StateBuilderRuntimeException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/state/StateDecoder.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/StateDecoder.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/StateDecoder.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2006-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+
+import javax.xml.XMLConstants;
+
+import dpml.lang.DOM3DocumentBuilder;
+
+import dpml.util.ElementHelper;
+
+import net.dpml.state.*;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import net.dpml.util.Logger;
+import dpml.util.DefaultLogger;
+
+/**
+ * Construct a state graph.
+ */
+public class StateDecoder
+{
+    private static final Logger LOGGER = new DefaultLogger( "dpml.state" );
+    
+    private static final String XML_HEADER = 
+      "<?xml version=\"1.0\"?>";
+    
+    private static final String NAMESPACE = 
+      "dpml:state";
+    
+    private static final String STATE_HEADER = 
+      "<state xmlns=\"" 
+      + NAMESPACE 
+      + "\""
+      + "\n    xmlns:xsi=\"" 
+      + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
+      + "\">";
+
+    private static final String STATE_FOOTER = "</state>";
+    
+    private static final DOM3DocumentBuilder BUILDER = new DOM3DocumentBuilder();
+    
+   /**
+    * Load a state graph.
+    * @param uri the graph uri
+    * @return the constructed state graph
+    * @exception IOException if an IO error occurs while reading the 
+    *   graph data
+    */
+    public State loadState( URI uri ) throws IOException
+    {
+        if( null == uri )
+        {
+            throw new NullPointerException( "uri" );
+        }
+        try
+        {
+            LOGGER.trace( "loading " + uri );
+            final Document document = BUILDER.parse( uri );
+            final Element root = document.getDocumentElement();
+            return buildStateGraph( root );
+        }
+        catch( Throwable e )
+        {
+            final String error =
+              "An error while attempting to load a state graph."
+              + "\nURI: " + uri;
+            IOException exception = new IOException( error );
+            exception.initCause( e );
+            throw exception;
+        }
+    }
+    
+   /**
+    * Load a state graph.
+    * @param url the graph url
+    * @return the constructed state graph
+    * @exception IOException if an IO error occurs while reading the 
+    *   graph data
+    */
+    public State loadState( URL url ) throws IOException
+    {
+        if( null == url )
+        {
+            throw new NullPointerException( "url" );
+        }
+        try
+        {
+            LOGGER.trace( "loading " + url );
+            final Document document = BUILDER.parse( url );
+            final Element root = document.getDocumentElement();
+            return buildStateGraph( root );
+        }
+        catch( Throwable e )
+        {
+            final String error =
+              "An error while attempting to load a state graph."
+              + "\nURL: " + url;
+            IOException exception = new IOException( error );
+            exception.initCause( e );
+            throw exception;
+        }
+    }
+    
+   /**
+    * Build a state graph.
+    * @param element a DOM element representing the root of the state graph
+    * @return the constructed state
+    */
+    State buildStateGraph( Element element )
+    {
+        if( null == element )
+        {
+            throw new NullPointerException( "element" );
+        }
+        
+        boolean terminal = ElementHelper.getBooleanAttribute( element, "terminal" );
+        DefaultTransition[] transitions = buildNestedTransitions( element );
+        DefaultOperation[] operations = buildNestedOperations( element );
+        DefaultInterface[] interfaces = buildNestedInterfaces( element );
+        DefaultState[] states = buildNestedStates( 1, element );
+        DefaultTrigger[] triggers = buildNestedTriggers( element );
+        return new DefaultState( 
+          "root", triggers, transitions, interfaces, operations, states, terminal );
+    }
+    
+    private DefaultTransition[] buildNestedTransitions( Element element )
+    {
+        Element[] children = ElementHelper.getChildren( element, "transition" );
+        DefaultTransition[] transitions = new DefaultTransition[ children.length ];
+        for( int i=0; i<children.length; i++ )
+        {
+            Element child = children[i];
+            transitions[i] = buildTransition( child );
+        }
+        return transitions;
+    }
+    
+    private DefaultOperation[] buildNestedOperations( Element element )
+    {
+        Element[] children = ElementHelper.getChildren( element, "operation" );
+        DefaultOperation[] operations = new DefaultOperation[ children.length ];
+        for( int i=0; i<children.length; i++ )
+        {
+            Element child = children[i];
+            operations[i] = buildOperation( child );
+        }
+        return operations;
+    }
+    
+    private DefaultInterface[] buildNestedInterfaces( Element element )
+    {
+        Element[] children = ElementHelper.getChildren( element, "interface" );
+        DefaultInterface[] interfaces = new DefaultInterface[ children.length ];
+        for( int i=0; i<children.length; i++ )
+        {
+            Element child = children[i];
+            interfaces[i] = buildInterface( child );
+        }
+        return interfaces;
+    }
+    
+    private DefaultState[] buildNestedStates( int n, Element element )
+    {
+        Element[] children = ElementHelper.getChildren( element, "state" );
+        DefaultState[] states = new DefaultState[ children.length ];
+        for( int i=0; i<children.length; i++ )
+        {
+            Element child = children[i];
+            states[i] = buildState( n, child );
+        }
+        return states;
+    }
+    
+    private DefaultTrigger[] buildNestedTriggers( Element element )
+    {
+        Element[] children = ElementHelper.getChildren( element, "trigger" );
+        DefaultTrigger[] triggers = new DefaultTrigger[ children.length ];
+        for( int i=0; i<children.length; i++ )
+        {
+            Element child = children[i];
+            triggers[i] = buildTrigger( child );
+        }
+        return triggers;
+    }
+    
+    private DefaultTransition buildTransition( Element element )
+    {
+        String name = ElementHelper.getAttribute( element, "name" );
+        String target = ElementHelper.getAttribute( element, "target" );
+        Element child = ElementHelper.getChild( element, "operation" );
+        DefaultOperation operation = buildOperation( child );
+        return new DefaultTransition( name, target, operation );
+    }
+    
+    private DefaultOperation buildOperation( Element element )
+    {
+        if( null == element )
+        {
+            return null;
+        }
+        String name = ElementHelper.getAttribute( element, "name" );
+        String method = ElementHelper.getAttribute( element, "method" );
+        return new DefaultOperation( name, method );
+    }
+    
+    private DefaultInterface buildInterface( Element element )
+    {
+        String classname = ElementHelper.getAttribute( element, "class" );
+        return new DefaultInterface( classname );
+    }
+    
+    private DefaultState buildState( int n, Element element )
+    {
+        String name = ElementHelper.getAttribute( element, "name" );
+        boolean terminal = ElementHelper.getBooleanAttribute( element, "terminal" );
+        DefaultTransition[] transitions = buildNestedTransitions( element );
+        DefaultOperation[] operations = buildNestedOperations( element );
+        DefaultInterface[] interfaces = buildNestedInterfaces( element );
+        DefaultState[] states = buildNestedStates( n+1, element );
+        DefaultTrigger[] triggers = buildNestedTriggers( element );
+        return new DefaultState( 
+          name, triggers, transitions, interfaces, operations, states, terminal );
+    }
+    
+    private DefaultTrigger buildTrigger( Element element )
+    {
+        String type = ElementHelper.getAttribute( element, "event" );
+        TriggerPolicy event = TriggerPolicy.valueOf( type.toUpperCase() );
+        Element child = getSingleNestedElement( element );
+        Action action = buildAction( child );
+        return new DefaultTrigger( event, action );
+    }
+    
+    private Action buildAction( Element element )
+    {
+        String name = element.getTagName();
+        if( name.equals( "transition" ) )
+        {
+            return buildTransition( element );
+        }
+        else if( name.equals( "operation" ) )
+        {
+            return buildOperation( element );
+        }
+        else if( name.equals( "apply" ) )
+        {
+            String id = ElementHelper.getAttribute( element, "id" );
+            return new ApplyAction( id );
+        }
+        else if( name.equals( "exec" ) )
+        {
+            String id = ElementHelper.getAttribute( element, "id" );
+            return new ExecAction( id );
+        }
+        else
+        {
+            final String error = 
+              "Illegal element name ["
+              + name
+              + "] supplied to action builder.";
+            throw new StateBuilderRuntimeException( error );
+        }
+    }
+    
+    private Element getSingleNestedElement( Element parent )
+    {
+        if( null == parent )
+        {
+            throw new NullPointerException( "parent" );
+        }
+        else
+        {
+            Element[] children = ElementHelper.getChildren( parent );
+            if( children.length == 1 )
+            {
+                return children[0];
+            }
+            else
+            {
+                final String error = 
+                  "Parent element does not contain a single child.";
+                throw new IllegalArgumentException( error );
+            }
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/dpml/state/StateEncoder.java
===================================================================
--- trunk/main/lang/part/src/main/dpml/state/StateEncoder.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/dpml/state/StateEncoder.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.state;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.io.OutputStreamWriter;
+
+import javax.xml.XMLConstants;
+
+import net.dpml.state.State;
+import net.dpml.state.Transition;
+import net.dpml.state.Operation;
+import net.dpml.state.Interface;
+import net.dpml.state.Trigger;
+import net.dpml.state.TriggerPolicy;
+import net.dpml.state.Action;
+import net.dpml.state.ExecAction;
+import net.dpml.state.ApplyAction;
+
+/**
+ * Construct a state graph.
+ */
+public class StateEncoder
+{
+    private static final String XML_HEADER = 
+      "<?xml version=\"1.0\"?>";
+    
+    private static final String STATE_SCHEMA_URN = "dpml:state";
+    
+   /**
+    * Externalize the part to XML.
+    * @param state the state graph to externalize
+    * @param output the output stream 
+    * @exception IOException if an IO error occurs
+    */
+    public void export( State state, OutputStream output ) throws IOException
+    {
+        final Writer writer = new OutputStreamWriter( output );
+
+        writer.write( XML_HEADER );
+        writer.write( "\n\n" );
+        writer.write( "<state xmlns=\"" 
+          + STATE_SCHEMA_URN 
+          + "\""
+          + "\n    xmlns:xsi=\"" 
+          + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
+          + "\"" );
+        if( state.isTerminal() )
+        {
+            writer.write( " terminal=\"true\">" );
+        }
+        else
+        {
+            writer.write( ">" );
+        }
+        writer.write( "\n" );
+        writeBody( writer, state, "" );
+        writer.write( "\n" );
+        writer.write( "\n</state>" );
+        writer.write( "\n" );
+        writer.flush();
+        output.close();
+    }
+    
+   /**
+    * Write the state.
+    * @param writer the stream writer
+    * @param state the state to externalize
+    * @param pad the pad offset
+    * @exception IOException if an IO error occurs
+    */
+    public void writeState( Writer writer, State state, String pad ) throws IOException
+    {
+        if( isEmpty( state ) )
+        {
+            return;
+        }
+        else
+        {
+            writer.write( "\n" + pad + "<state xmlns=\"" + STATE_SCHEMA_URN + "\"" );
+            if( state.isTerminal() )
+            {
+                writer.write( " terminal=\"true\"" );
+            }
+            writer.write( ">" );
+            writeBody( writer, state, pad + "  " );
+            writer.write( "\n" + pad + "</state>" );
+        }
+    }
+    
+    private void writeBody( Writer writer, State state, String pad )  throws IOException
+    {
+        Trigger[] triggers = state.getTriggers();
+        Transition[] transitions = state.getTransitions();
+        Operation[] operations = state.getOperations();
+        Interface[] interfaces = state.getInterfaces();
+        State[] states = state.getStates();
+        
+        writeTriggers( writer, triggers, pad );
+        writeTransitions( writer, transitions, pad );
+        writeOperations( writer, operations, pad );
+        writeInterfaces( writer, interfaces, pad );
+        writeStates( writer, states, pad );
+    }
+    
+    private void writeTriggers( Writer writer, Trigger[] triggers, String pad )  throws IOException
+    {
+        if( triggers.length == 0 )
+        {
+            return;
+        }
+        else
+        {
+            for( int i=0; i<triggers.length; i++ )
+            {
+                Trigger trigger = triggers[i];
+                writeTrigger( writer, trigger, pad );
+            }
+        }
+    }
+    
+    private void writeTrigger( Writer writer, Trigger trigger, String pad )  throws IOException
+    {
+        TriggerPolicy event = trigger.getPolicy();
+        writer.write( "\n" + pad + "<trigger event=\"" );
+        writer.write( event.name().toLowerCase() );
+        writer.write( "\">" );
+        Action action = trigger.getAction();
+        writeAction( writer, action, pad + "  " );
+        writer.write( "\n" + pad + "</trigger>" );
+    }
+    
+    private void writeTransitions( Writer writer, Transition[] transitions, String pad )  throws IOException
+    {
+        if( transitions.length == 0 )
+        {
+            return;
+        }
+        else
+        {
+            for( int i=0; i<transitions.length; i++ )
+            {
+                Transition transition = transitions[i];
+                writeTransition( writer, transition, pad );
+            }
+        }
+    }
+    
+    private void writeOperations( Writer writer, Operation[] operations, String pad )  throws IOException
+    {
+        if( operations.length == 0 )
+        {
+            return;
+        }
+        else
+        {
+            for( int i=0; i<operations.length; i++ )
+            {
+                Operation operation = operations[i];
+                writeOperation( writer, operation, pad );
+            }
+        }
+    }
+    
+    private void writeInterfaces( Writer writer, Interface[] interfaces, String pad )  throws IOException
+    {
+        if( interfaces.length == 0 )
+        {
+            return;
+        }
+        else
+        {
+            for( int i=0; i<interfaces.length; i++ )
+            {
+                Interface spec = interfaces[i];
+                writeInterface( writer, spec, pad );
+            }
+        }
+    }
+    
+    private void writeStates( Writer writer, State[] states, String pad )  throws IOException
+    {
+        if( states.length == 0 )
+        {
+            return;
+        }
+        else
+        {
+            for( int i=0; i<states.length; i++ )
+            {
+                State state = states[i];
+                writeNestedState( writer, state, pad );
+            }
+        }
+    }
+    
+    private void writeTransition( Writer writer, Transition transition, String pad )  throws IOException
+    {
+        String name = transition.getName();
+        String target = transition.getTargetName();
+        writer.write( "\n" + pad + "<transition name=\"" + name + "\" target=\"" + target + "\"" );
+        Operation operation = transition.getOperation();
+        if( null == operation )
+        {
+            writer.write( "/>" );
+        }
+        else
+        {
+            writer.write( ">" );
+            writeOperation( writer, operation, pad + "  " );
+            writer.write( "\n" + pad + "</transition>" );
+        }
+    }
+
+    private void writeOperation( Writer writer, Operation operation, String pad )  throws IOException
+    {
+        String name = operation.getName();
+        String method = operation.getMethodName();
+        writer.write( "\n" + pad + "<operation name=\"" + name + "\"" );
+        if( null != method )
+        {
+            writer.write( " method=\"" + method + "\"" );
+        }
+        writer.write( "/>" );
+    }
+    
+    private void writeInterface( Writer writer, Interface spec, String pad )  throws IOException
+    {
+        String classname = spec.getClassname();
+        writer.write( "\n" + pad + "<interface class=\"" + classname + "\"/>" );
+    }
+    
+    private void writeAction( Writer writer, Action action, String pad )  throws IOException
+    {
+        if( action instanceof Transition )
+        {
+            Transition transition = (Transition) action;
+            writeTransition( writer, transition, pad );
+        }
+        else if( action instanceof Operation )
+        {
+            Operation operation = (Operation) action;
+            writeOperation( writer, operation, pad );
+        }
+        else if( action instanceof Interface )
+        {
+            Interface spec = (Interface) action;
+            writeInterface( writer, spec, pad );
+        }
+        else if( action instanceof ExecAction )
+        {
+            ExecAction exec = (ExecAction) action;
+            writeExecAction( writer, exec, pad );
+        }
+        else if( action instanceof ApplyAction )
+        {
+            ApplyAction apply = (ApplyAction) action;
+            writeApplyAction( writer, apply, pad );
+        }
+        else
+        {
+            final String error = 
+              "Unrecognized action class ["
+              + action.getClass().getName()
+              + "].";
+            throw new IOException( error );
+        }
+    }
+    private void writeExecAction( Writer writer, ExecAction action, String pad )  throws IOException
+    {
+        String id = action.getID();
+        writer.write( "\n" + pad + "<exec id=\"" + id + "\"/>" );
+    }
+    
+    private void writeApplyAction( Writer writer, ApplyAction action, String pad )  throws IOException
+    {
+        String id = action.getID();
+        writer.write( "\n" + pad + "<apply id=\"" + id + "\"/>" );
+    }
+    
+    private void writeNestedState( Writer writer, State state, String pad )  throws IOException
+    {
+        String name = state.getName();
+        writer.write( "\n" + pad + "<state name=\"" + name + "\"" );
+        if( state.isTerminal() )
+        {
+            writer.write( " terminal=\"true\">" );
+        }
+        else
+        {
+            writer.write( ">" );
+        }
+        writeBody( writer, state, pad + "  " );
+        writer.write( "\n" + pad + "</state>" );
+    }
+
+    private boolean isEmpty( State state )
+    {
+        if( state.getTriggers().length > 0 )
+        {
+            return false;
+        }
+        if( state.getTransitions().length > 0 )
+        {
+            return false;
+        }
+        if( state.getOperations().length > 0 )
+        {
+            return false;
+        }
+        if( state.getInterfaces().length > 0 )
+        {
+            return false;
+        }
+        if( state.getStates().length > 0 )
+        {
+            return false;
+        }
+        return true;
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/Activation.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/Activation.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/Activation.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Component activation policy annotation.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Target( ElementType.TYPE )
+ at Retention( RetentionPolicy.RUNTIME )
+ at Documented
+public @interface Activation
+{
+   /**
+    * Returns the activation assertion status.  The default
+    * assertion status is {@link ActivationPolicy#SYSTEM}.
+    */
+    ActivationPolicy value() default ActivationPolicy.SYSTEM;
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/ActivationPolicy.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/ActivationPolicy.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/ActivationPolicy.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2005 Stephen J. McConnell
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.annotation;
+
+/**
+ * Activation policy.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public enum ActivationPolicy
+{
+   /**
+    * System managed activation policy.
+    */
+    SYSTEM,
+
+   /**
+    * Activation on startup enabled.
+    */
+    STARTUP,
+
+   /**
+    * Activation on startup disabled.
+    */
+    DEMAND;
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/CollectionPolicy.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/CollectionPolicy.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/CollectionPolicy.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.annotation;
+
+/**
+ * Collection policy.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public enum CollectionPolicy
+{
+   /**
+    * Weak collection policy.
+    */
+    WEAK,
+
+   /**
+    * Soft collection policy.
+    */
+    SOFT,
+
+   /**
+    * Hard collection policy.
+    */
+    HARD;
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/Component.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/Component.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/Component.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Component annotation dealing with lifestyle policy, lifecycle model, and collection semantics.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ @Target( ElementType.TYPE )
+ @Retention( RetentionPolicy.RUNTIME )
+public @interface Component
+{
+    String name() default "";
+    LifestylePolicy lifestyle() default LifestylePolicy.THREAD;
+    CollectionPolicy collection() default CollectionPolicy.HARD;
+    String lifecycle() default "";
+    String handlerURI() default "link:part:dpml/lang/dpml-lang-component";
+    String handlerClassname() default "net.dpml.runtime.ComponentStrategyHandler";
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/Context.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/Context.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/Context.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Assertion that an interface is expressed in terms of a context model.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Target( ElementType.TYPE )
+ at Retention( RetentionPolicy.RUNTIME )
+ at Documented
+public @interface Context
+{
+   /**
+    * Returns the context support assertion status.  The default
+    * assertion status is true.
+    */
+    boolean value() default true;
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/LifestylePolicy.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/LifestylePolicy.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/LifestylePolicy.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.annotation;
+
+/**
+ * Lifecycle policy.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public enum LifestylePolicy
+{
+   /**
+    * Declares that a single instance created from the component class
+    * shall be shared across all instance requests.  Components declaring 
+    * this policy must ensure that implementations are threadsafe.
+    */
+    SINGLETON,
+   
+   /**
+    * Declares that a new instance of the class shall be created for 
+    * each thread context.
+    */
+    THREAD,
+    
+   /**
+    * Declares that a new instance shall be created per request.
+    */
+    TRANSIENT;
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/Parts.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/Parts.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/Parts.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Assertion that an interface is expressed in terms of a parts model.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Target( ElementType.TYPE )
+ at Retention( RetentionPolicy.RUNTIME )
+ at Documented
+public @interface Parts
+{
+   /**
+    * Returns the context support assertion status.  The default
+    * assertion status is true.
+    */
+    boolean value() default true;
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/Services.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/Services.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/Services.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Assertion that a class implementation should be isolated as a 
+ * proxy using the declared set of interface classes.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Target( ElementType.TYPE )
+ at Retention( RetentionPolicy.RUNTIME )
+ at Documented
+public @interface Services
+{
+   /**
+    * Returns the array of interfaces published by an implementation.
+    */
+    Class[] value() default {};
+}

Added: trunk/main/lang/part/src/main/net/dpml/annotation/package-info.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/annotation/package-info.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/annotation/package-info.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <p>Component annotations supporting lifestyle, lifecycle, collection, 
+ * activiation, and service publication policies.</p>
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+package net.dpml.annotation;

Added: trunk/main/lang/part/src/main/net/dpml/appliance/Appliance.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/Appliance.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/Appliance.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import java.io.IOException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * Appliance interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Appliance extends Remote
+{
+    void addApplianceListener( ApplianceListener listener ) throws RemoteException;
+    
+    void removeApplianceListener( ApplianceListener listener ) throws RemoteException;
+    
+    void commission() throws IOException;
+    
+    void decommission() throws RemoteException;
+    
+   /**
+    * Return a value assignable to the supplied remote type or null if the type
+    * cannot be resolved from the underlying component.
+    * @param type the service type
+    * @return an instance of the type or null
+    * @exception IOException if an IO error occurs
+    */
+    //public <T>T getContentForClass( Class<T> type ) throws IOException;
+    
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceConnector.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceConnector.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceConnector.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2004-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import java.io.IOException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Appliance connector.
+ */
+public interface ApplianceConnector extends Remote
+{
+   /**
+    * Connect a appliance to the station.
+    * @param appliance the appliance 
+    * @exception RemoteException if a remote error occurs
+    */
+    void connect( Appliance appliance ) throws RemoteException;
+    
+    Appliance getAppliance( TimeUnit units, int timeout ) throws IOException;
+    
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceContentManager.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceContentManager.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceContentManager.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 Stephen McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import net.dpml.transit.ContentManager;
+
+import javax.management.MXBean;
+
+/**
+ * Application content manager interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ @MXBean
+public interface ApplianceContentManager extends ContentManager
+{
+    ApplianceManager[] getApplianceManagers();
+}

Added: trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceError.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceError.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceError.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2004-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+/**
+ * Application management center.
+ */
+/**
+ * Critical appliance error.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ApplianceError extends Error
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>ApplianceError</code>.
+     *
+     * @param message the error message
+     */
+    public ApplianceError( final String message )
+    {
+        super( message );
+    }
+    
+    /**
+     * Construct a new <code>ApplianceError</code>.
+     *
+     * @param message the error message
+     * @param cause the causal exception
+     */
+    public ApplianceError( final String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+    
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceEvent.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceEvent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceEvent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,71 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import java.util.EventObject;
+
+import net.dpml.runtime.Status;
+
+/**
+ * Event triggered as a result of a state change.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ApplianceEvent extends EventObject
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    private final Appliance m_appliance;
+    private final Status m_status;
+
+   /**
+    * Construct a new <code>StateEvent</code>.
+    *
+    * @param source the source component
+    */
+    public ApplianceEvent( final Appliance source, Status status )
+    {
+        super( source );
+        m_appliance = source;
+        m_status = status;
+    }
+
+   /**
+    * Return the appliance that initiated the event.
+    * @return the source appliance
+    */
+    public Appliance getAppliance()
+    {
+        return m_appliance;
+    }
+    
+   /**
+    * Return the appliance status.
+    * @return the status enumeration
+    */
+    public Status getStatus()
+    {
+        return m_status;
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2004-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import java.io.IOException;
+
+import net.dpml.lang.DecodingException;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Appliance related exception.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ApplianceException extends DecodingException
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+   /**
+    * Construct a new <code>ApplianceException</code>.
+    *
+    * @param message the error message
+    */
+    public ApplianceException( final String message )
+    {
+        super( message, null, null );
+    }
+    
+   /**
+    * Construct a new <code>ApplianceException</code>.
+    *
+    * @param message the error message
+    * @param cause the causal exception
+    */
+    public ApplianceException( final String message, Throwable cause )
+    {
+        super( message, cause, null );
+    }
+    
+   /**
+    * Construct a new <code>ApplianceException</code>.
+    *
+    * @param message the error message
+    * @param cause the causal exception
+    * @param element the element definition
+    */
+    public ApplianceException( final String message, Throwable cause, Element element )
+    {
+        super( message, cause, element );
+    }
+    
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceFactory.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceFactory.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceFactory.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,41 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import java.io.IOException;
+import java.net.URLConnection;
+
+/**
+ * Interface implementated by remote listeners to state change events.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface ApplianceFactory
+{
+   /**
+    * Create a new appliance using the supplied connection object.
+    * @param connection the URL connection
+    * @param partition an optional partition name
+    * @return the appliance
+    * @exception IOException if an IO error occurs
+    */
+    Appliance newAppliance( URLConnection connection, String partition ) throws IOException;
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceListener.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceListener.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceListener.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,42 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import java.util.EventListener;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * Interface implementated by remote listeners to state change events.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface ApplianceListener extends EventListener, Remote
+{
+   /**
+    * Notify the listener of an event within the appliance.
+    *
+    * @param event the comnponent event
+    * @exception RemoteException if a remote transport error occurs
+    */
+    void applianceChanged( final ApplianceEvent event ) throws RemoteException;
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceManager.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceManager.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/ApplianceManager.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2006 Stephen McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import javax.management.MXBean;
+
+/**
+ * Management interface for applications.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at MXBean
+public interface ApplianceManager extends Remote
+{
+   /**
+    * Returns the part URI as a string.
+    * @return the codebase uri
+    */
+    String getCodebaseURI() throws RemoteException;
+}

Added: trunk/main/lang/part/src/main/net/dpml/appliance/PlanManager.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/PlanManager.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/PlanManager.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 Stephen McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.appliance;
+
+import javax.management.MXBean;
+
+/**
+ * Management interface for applications.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at MXBean
+public interface PlanManager extends ApplianceManager
+{
+    ApplianceManager[] getApplianceManagers();
+}

Added: trunk/main/lang/part/src/main/net/dpml/appliance/package-info.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/appliance/package-info.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/appliance/package-info.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <p>Interfaces represening a managed process.</p>
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+package net.dpml.appliance;

Added: trunk/main/lang/part/src/main/net/dpml/lang/AntlibStrategy.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/AntlibStrategy.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/AntlibStrategy.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URL;
+
+import net.dpml.state.StateListener;
+
+import net.dpml.util.Logger;
+import dpml.lang.Disposable;
+
+/**
+ * Simple resource deployment strategy.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class AntlibStrategy extends Strategy
+{
+    private final String m_urn;
+    private final String m_path;
+    
+   /**
+    * Creation of resource datatype.
+    * @param classloader the classloader
+    * @param urn the resource urn
+    * @param path the resource path
+    * @exception IOException if an I/O error occurs
+    */
+    public AntlibStrategy( ClassLoader classloader, String urn, String path )
+      throws IOException
+    {
+        super( classloader );
+        if( null == urn )
+        {
+            throw new NullPointerException( "urn" );
+        }
+        if( null == path )
+        {
+            throw new NullPointerException( "path" );
+        }
+        m_urn = urn;
+        m_path = path;
+    }
+    
+    public String getName()
+    {
+        return m_urn;
+    }
+    
+    public int getPriority()
+    {
+        return 0;
+    }
+
+   /**
+    * Return the part content or null if the result type is unresolvable 
+    * relative to the supplied classes argument. Class arguments recognized
+    * over an above plugin include the URL and String classes.  If the URL
+    * class is supplied a URL referencing the resource identified by path 
+    * is returned.  If a String is requested the urn value is returned.
+    *
+    * @param c the content class
+    * @return the content
+    * @exception IOException if an IO error occurs
+    */
+    public <T>T getContentForClass( Class<T> c ) throws IOException
+    {
+        if( Strategy.class.equals( c ) )
+        {
+            return c.cast( this );
+        }
+        else if( URL.class.equals( c ) )
+        {
+            URL url = getClassLoader().getResource( m_path );
+            return c.cast( url );
+        }
+        else if( String.class.equals( c ) )
+        {
+            String urn = getURN();
+            return c.cast( urn );
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+   /**
+    * Get the resource urn.
+    * @return the urn
+    */
+    public String getURN()
+    {
+        return m_urn;
+    }
+    
+   /**
+    * Get the resource path.
+    * @return the path
+    */ 
+    public String getPath()
+    {
+        return m_path;
+    }
+    
+    public boolean isaCandidate( Class<?> type )
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void initialize( ServiceRegistry registry )
+    {
+        // not required
+    }
+
+   /**
+    * Instantiate a value.
+    * @param type the return type
+    * @return the resolved instance
+    */
+    public <T>T getInstance( Class<T> type )
+    {
+        try
+        {
+            ClassLoader classloader = getClassLoader();
+            Object resource = classloader.getResource( m_path );
+            return type.cast( resource );
+        }
+        catch( Exception e )
+        {
+            throw new PartError( e.getMessage(), e.getCause() );
+        }
+    }
+    
+   /**
+    * Encode the resource strategy to XML.
+    * @param buffer the output buffer
+    * @param key the key
+    * @exception IOException if an I/O error occurs
+    */
+    public void encode( Buffer buffer, String key ) throws IOException
+    {
+        String urn = getURN();
+        String path = getPath();
+        buffer.nl( "<resource xmlns=\"" + AntlibStrategyHandler.NAMESPACE + "\"" );
+        if( null != key )
+        {
+            buffer.write( " key=\"" + key + "\"" );
+        }
+        buffer.write( " urn=\"" + urn + "\" " );
+        buffer.write( " path=\"" + path + "\"" );
+        buffer.write( "/>" );
+    }
+    
+   /**
+    * Test if this instance is equal to the supplied instance.
+    * @param other the supplied instance
+    * @return the equality status
+    */
+    public boolean equals( Object other )
+    {
+        if( other instanceof AntlibStrategy )
+        {
+            AntlibStrategy resource = (AntlibStrategy) other;
+            if( !m_path.equals( resource.m_path ) )
+            {
+                return false;
+            }
+            else
+            {
+                return m_urn.equals( resource.m_urn );
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Get the hashcode for this instance.
+    * @return the hash value
+    */
+    public int hashCode()
+    {
+        int hash = 99875845;
+        hash ^= m_path.hashCode();
+        hash ^= m_urn.hashCode();
+        return hash;
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/AntlibStrategyHandler.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/AntlibStrategyHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/AntlibStrategyHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import dpml.util.ElementHelper;
+import dpml.util.DefaultLogger;
+import dpml.util.StandardClassLoader;
+import dpml.util.SystemClassLoader;
+import dpml.util.Category;
+
+import dpml.lang.Classpath;
+import dpml.lang.ValueDecoder;
+import dpml.lang.Value;
+
+import net.dpml.runtime.ComponentStrategyHandler;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+
+import net.dpml.util.Logger;
+import net.dpml.util.Resolver;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * Antlib strategy handler implementation.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class AntlibStrategyHandler implements StrategyHandler
+{
+    public static final String NAMESPACE = "dpml:antlib";
+    
+    public Strategy newStrategy( Class<?> c ) throws IOException
+    {
+        return newStrategy( c, null );
+    }
+    
+    public Strategy newStrategy( Class<?> c, String name ) throws IOException
+    {
+        throw new UnsupportedOperationException( "newStrategy" );
+    }
+    
+   /**
+    * Construct a strategy definition using a supplied element and value resolver.
+    * @param classloader the classloader
+    * @param element the DOM element definining the deployment strategy
+    * @param resolver symbolic property resolver
+    * @param query the query fragment (ignored)
+    * @return the strategy definition
+    * @exception IOException if an I/O error occurs
+    */
+    public Strategy build( 
+      ClassLoader classloader, Element element, Resolver resolver, String partition, String query ) throws IOException
+    {
+        String urn = ElementHelper.getAttribute( element, "urn", null, resolver );
+        String path = ElementHelper.getAttribute( element, "path", null, resolver );
+        return new AntlibStrategy( classloader, urn, path );
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/Buffer.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/Buffer.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/Buffer.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import java.io.Writer;
+import java.io.IOException;
+
+/**
+ * Utility class used as a destination during generalized object encoding.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class Buffer
+{
+    private final String m_namespace;
+    private final String m_pad;
+    private final Writer m_writer;
+    
+   /**
+    * Construct a new encoding buffer.
+    *
+    * @param writer the output stream writer
+    * @param namespace the current namespace
+    * @param pad the current offset
+    * @exception NullPointerException of the writer or namespace arguments are null
+    */
+    public Buffer( final Writer writer, final String namespace, final String pad )
+    {
+        if( null == writer )
+        {
+            throw new NullPointerException( "writer" );
+        }
+        if( null == namespace )
+        {
+            throw new NullPointerException( "namespace" );
+        }
+        if( null == pad )
+        {
+            m_pad = "";
+        }
+        else
+        {
+            m_pad = pad;
+        }
+        m_namespace = namespace;
+        m_writer = writer;
+    }
+    
+    public String getEnclosingNamespace()
+    {
+        return m_namespace;
+    }
+    
+    public String getOffset()
+    {
+        return m_pad;
+    }
+    
+    public void write( String value ) throws IOException
+    {
+        m_writer.write( value );
+    }
+    
+    public void write( int n ) throws IOException
+    {
+        m_writer.write( n );
+    }
+    
+    public void write( char[] array ) throws IOException
+    {
+        m_writer.write( array );
+    }
+    
+    public void nl( String value ) throws IOException
+    {
+        m_writer.write( "\n" + m_pad + value );
+    }
+    
+    public void nl( int n ) throws IOException
+    {
+        m_writer.write( "\n" + m_pad + n );
+    }
+    
+    public void nl( char[] array ) throws IOException
+    {
+        m_writer.write( "\n" + m_pad );
+        m_writer.write( array );
+    }
+    
+    public Buffer indent()
+    {
+        return indent( "  " );
+    }
+    
+    public Buffer indent( String indent )
+    {
+        return new Buffer( m_writer, m_namespace, m_pad + indent );
+    }
+    
+    public boolean isNamespace( String namespace )
+    {
+        return m_namespace.equals( namespace );
+    }
+    
+    public Buffer namespace( String namespace )
+    {
+        if( m_namespace.equals( namespace ) )
+        {
+            return this;
+        }
+        else
+        {
+            return new Buffer( m_writer, namespace, m_pad );
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/ClassLoaderHelper.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/ClassLoaderHelper.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/ClassLoaderHelper.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import dpml.lang.ValueDecoder;
+import dpml.util.StandardClassLoader;
+import dpml.util.SystemClassLoader;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+
+import dpml.lang.Classpath;
+import dpml.util.Category;
+
+import net.dpml.util.Logger;
+import net.dpml.util.Resolver;
+import dpml.util.ElementHelper;
+import dpml.util.DefaultLogger;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * Interace implemented by part strategy handlers.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class ClassLoaderHelper
+{
+    private static final ValueDecoder VALUE_DECODER = new ValueDecoder();
+    
+    private static final Logger LOGGER = new DefaultLogger( "dpml.lang" );
+    
+   /**
+    * Create a classloader given a classpath defintion.
+    * @param anchor the parent classloader
+    * @param classpath the classpath definition
+    * @return the new classloader
+    */
+    public static ClassLoader newClassLoader( ClassLoader anchor, URI codebase, Classpath classpath ) throws IOException
+    {
+        if( null == anchor )
+        {
+            throw new NullPointerException( "anchor" );
+        }
+        //ClassLoader anchor = getAnchorClassLoader( parent );
+        String spec = codebase.toASCIIString();
+        return newClassLoader( anchor, classpath, spec, true );
+    }
+    
+    private static ClassLoader newClassLoader( 
+      ClassLoader base, Classpath classpath, String spec, boolean expand ) throws IOException
+    {
+        if( expand )
+        {
+            Classpath cp = classpath.getBaseClasspath();
+            if( null != cp )
+            {
+                String label = spec + " (base)";
+                ClassLoader cl = newClassLoader( base, cp, label, true );
+                return newClassLoader( cl, classpath, spec, false );
+            }
+        }
+        
+        URI[] uris = classpath.getDependencies( Category.SYSTEM );
+        if( uris.length > 0 )
+        {
+            for( URI uri : uris )
+            {
+                LOGGER.warn( "Ignoring system reference: " + uri );
+            }
+            //updateSystemClassLoader( uris );
+        }
+        
+        URI[] apis = classpath.getDependencies( Category.PUBLIC );
+        ClassLoader api = 
+          StandardClassLoader.buildClassLoader( LOGGER, spec, Category.PUBLIC, base, apis );
+        URI[] spis = classpath.getDependencies( Category.PROTECTED );
+        ClassLoader spi = 
+          StandardClassLoader.buildClassLoader( LOGGER, spec, Category.PROTECTED, api, spis );
+        URI[] imps = classpath.getDependencies( Category.PRIVATE );
+        return StandardClassLoader.buildClassLoader( LOGGER, spec, Category.PRIVATE, spi, imps );
+    }
+
+    /*
+    private static void updateSystemClassLoader( URI[] uris ) throws IOException
+    {
+        ClassLoader parent = ClassLoader.getSystemClassLoader();
+        synchronized( parent )
+        {
+            if( parent instanceof SystemClassLoader )
+            {
+                SystemClassLoader loader = (SystemClassLoader) parent;
+                loader.addDelegates( uris );
+            }
+            else
+            {
+                final String message =
+                  "Cannot load [" 
+                  + uris.length 
+                  + "] system artifacts into a foreign system classloader.";
+                LOGGER.trace( message );
+            }
+        }
+    }
+    */
+    
+    /*
+    private static ClassLoader getAnchorClassLoader( ClassLoader parent )
+    {
+        if( null != parent )
+        {
+            return parent;
+        }
+        else
+        {
+            ClassLoader current = Thread.currentThread().getContextClassLoader();
+            if( null != current )
+            {
+                return current;
+            }
+            else
+            {
+                return ClassLoaderHelper.class.getClassLoader();
+            }
+        }
+    }
+    */
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/DecodingException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/DecodingException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/DecodingException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import dpml.util.ElementHelper;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+
+import net.dpml.transit.Artifact;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * Exception related to data decoding from a DOM element.
+ */
+public class DecodingException extends IOException
+{
+    private final Element m_element;
+    
+   /**
+    * Create a new decoding exception.
+    * @param element the element representing the source of the error
+    * @param message the exception message
+    */
+    public DecodingException( String message, Element element )
+    {
+        this( message, null, element );
+    }
+    
+   /**
+    * Create a new decoding exception.
+    * @param element the element representing the source of the error
+    * @param message the exception message
+    * @param cause the causal exception
+    */
+    public DecodingException( String message, Throwable cause, Element element )
+    {
+        super( message );
+        if( null != cause )
+        {
+            super.initCause( cause );
+        }
+        m_element = element;
+    }
+    
+   /**
+    * Get the element that is the subject of this exception.
+    * @return the subject element
+    */
+    public Element getElement()
+    {
+        return m_element;
+    }
+    
+   /**
+    * Return a string representation of the exception.
+    * @return the string value
+    */
+    public String getMessage()
+    {
+        try
+        {
+            String message = super.getMessage();
+            StringBuffer buffer = new StringBuffer( message );
+            Element element = getElement();
+            if( null != element )
+            {
+                Document document = element.getOwnerDocument();
+                String uri = document.getDocumentURI();
+                if( null != uri )
+                {
+                    buffer.append( "\nSource: " + uri  );
+                    String filename = getSourceFilePath( uri );
+                    if( null != filename )
+                    {
+                        buffer.append( "\nFile: " + filename );
+                    }
+                    buffer.append( "\n" );
+                }
+                String listing = list( element );
+                buffer.append( listing );
+            }
+            return buffer.toString();
+        }
+        catch( Throwable e )
+        {
+            return super.getMessage();
+        }
+    }
+    
+   /**
+    * Static utility operation that returns a string representation of a DOM element.
+    * @param element the element to stringify
+    * @return the string value
+    */
+    public static String list( Element element )
+    {
+        return list( element, "" );
+    }
+    
+   /**
+    * Static utility operation that returns a syring representation of a DOM element.
+    * @param element the element to stringify
+    * @param pad padding offset
+    * @return the string value
+    */
+    public static String list( Element element, String pad )
+    {
+        if( null == element )
+        {
+            return "";
+        }
+        StringBuffer buffer = new StringBuffer();
+        String tag = element.getTagName();
+        buffer.append( pad + "<" );
+        buffer.append( tag );
+        NamedNodeMap map = element.getAttributes();
+        for( int i=0; i<map.getLength(); i++ )
+        {
+            Node item = map.item( i );
+            buffer.append( " " + item.getNodeName() + "=\"" );
+            buffer.append( item.getNodeValue() );
+            buffer.append( "\"" );
+        }
+        
+        Element[] children = ElementHelper.getChildren( element );
+        if( children.length > 0 )
+        {
+            buffer.append( ">" );
+            for( int i=0; i<children.length; i++ )
+            {
+                Element child = children[i];
+                String listing = list( child, pad + "  " );
+                String tagName = child.getTagName();
+                buffer.append( "\n" + listing );
+            }
+            buffer.append( "\n" + pad + "</" + tag + ">" );
+        }
+        else
+        {
+            buffer.append( "/>" );
+        }
+        return buffer.toString();
+    }
+    
+    private static String getSourceFilePath( String value )
+    {
+        try
+        {
+            URI uri = URI.create( value );
+            if( Artifact.isRecognized( uri ) )
+            {
+                URL url = Artifact.toURL( uri );
+                File file = (File) url.getContent( new Class[]{ File.class } );
+                return file.getCanonicalPath();
+            }
+            return null;
+        }
+        catch( Throwable e )
+        {
+            return null;
+        }
+    }
+    
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/DuplicateKeyException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/DuplicateKeyException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/DuplicateKeyException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+/**
+ * Exception to indicate an error arrising from the use of a duplicate key.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DuplicateKeyException extends Exception
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>DuplicateKeyException</code> instance.
+     *
+     * @param key the duplicate key
+     */
+    public DuplicateKeyException( final String key )
+    {
+        super( key );
+    }
+
+   /**
+    * Return the key.
+    * @return the key
+    */
+    public String getKey()
+    {
+        return super.getMessage();
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/NamespaceError.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/NamespaceError.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/NamespaceError.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2004-2005 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+/**
+ * Error related to schmema namespace resolution.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class NamespaceError extends Error
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>PartError</code> instance.
+     *
+     * @param message The detail message for this exception.
+     */
+    public NamespaceError( final String message )
+    {
+        this( message, null );
+    }
+
+    /**
+     * Construct a new <code>PartError</code> instance.
+     *
+     * @param message The detail message for this exception.
+     * @param cause the root cause of the exception
+     */
+    public NamespaceError( final String message, final Throwable cause )
+    {
+        super( message );
+        super.initCause( cause );
+    }
+}
+
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/PartContentHandler.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/PartContentHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/PartContentHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,701 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.dpml.lang;
+
+import dpml.lang.Info;
+import dpml.lang.Classpath;
+import dpml.lang.Part;
+import dpml.lang.DOM3DocumentBuilder;
+
+import dpml.util.DefaultLogger;
+import dpml.util.SimpleResolver;
+import dpml.util.ElementHelper;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.lang.management.ManagementFactory;
+import java.lang.ref.WeakReference;
+import java.util.Map;
+import java.util.Hashtable;
+import java.util.ServiceLoader;
+import java.util.ArrayList;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.MBeanException;
+import javax.management.InstanceAlreadyExistsException;
+
+import net.dpml.annotation.Component;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceFactory;
+
+import net.dpml.lang.PartManager;
+import net.dpml.lang.PartContentManager;
+
+import net.dpml.runtime.ComponentStrategyHandler;
+
+import net.dpml.transit.Artifact;
+import net.dpml.transit.Transit;
+import net.dpml.transit.ContentHandler;
+
+import net.dpml.util.Logger;
+import net.dpml.util.Resolver;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * Content handler for the 'part' artifact type.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class PartContentHandler extends ContentHandler implements PartContentManager, ApplianceFactory
+{
+   /**
+    * Part XSD uri.
+    */
+    public static final String NAMESPACE = "dpml:part";
+
+    private static final String PART_CONTENT_TYPE = "part";
+    
+    private static final Logger LOGGER = new DefaultLogger( "dpml.part" );
+    
+    // DOES NOT WORK
+    //private static final Map<String, WeakReference<Part>> CACHE = 
+    //  new Hashtable<String, WeakReference<Part>>();
+
+    // POTENTIAL SOLUTION: map of anchor classloader (keys) to a map of part classloader and parts
+    //private static final Map<ClassLoader,Map<ClassLoader,Part>> CACHE = 
+    //  new Hashtable<ClassLoader,Map<ClassLoader,Part>>();
+    
+    private static final Map<String,Part> CACHE = new Hashtable<String,Part>();
+
+    private static final DOM3DocumentBuilder DOCUMENT_BUILDER = 
+      new DOM3DocumentBuilder();
+    
+    private static final ClassLoaderHelper CLASSLOADER_HELPER = new ClassLoaderHelper();
+
+    private static final ComponentStrategyHandler STANDARD_STRATEGY_HANDLER = 
+      new ComponentStrategyHandler();
+
+   /**
+    * Return a strategy handler based on the supplied component annotation.
+    * @param annotation the component annotation
+    * @return the strategy handler
+    * @exception Exception if an error ocurrs during handler establishment
+    */
+    public static StrategyHandler getStrategyHandler( Component annotation ) throws Exception
+    {
+        String classname = annotation.handlerClassname();
+        try
+        {
+            return getStrategyHandler( classname );
+        }
+        catch( UnknownServiceException e )
+        {
+            String urn = annotation.handlerURI();
+            URI uri = new URI( urn );
+            return getStrategyHandler( uri );
+        }
+    }
+    
+   /**
+    * Return the strategy handler supporting the supplied class.  If the class 
+    * contains the component annotation the handler is resolved relative to the 
+    * annotation properties, otherwise a default strategy handler is returned.
+    *
+    * @param subject the subject class
+    * @return the strategy handler
+    * @exception Exception if a general loading error occurs
+    */
+    public static StrategyHandler getStrategyHandler( Class<?> subject ) throws Exception
+    {   
+        if( subject.isAnnotationPresent( Component.class ) )
+        {
+            Component annotation = 
+              subject.getAnnotation( Component.class );
+            return PartContentHandler.getStrategyHandler( annotation );
+        }
+        else
+        {
+            return STANDARD_STRATEGY_HANDLER;
+        }
+    }
+    
+   /**
+    * Load a potentially foreign strategy handler.
+    * Strategy resolution is based on the following rules relative to the namespace
+    * of the supplied element:
+    * <ul>
+    *  <li>if a system property named <tt>handler:[namespace]</tt> is defined, 
+    *     it is assumed to be a handler classname and the implementation will 
+    *     load the class and instantiate the handler instance.</li>
+    *  <li>if the namespace is recognized as a standard strategy the appropriate 
+    *     strategy handler is returned</li>
+    *  <li>the implementation will evaluate the <tt<handler</tt> attribute on the
+    *     supplied element - if the attribute value is not null, then 
+    *     the values will interprited as either a classname or a uri.  If the 
+    *     value contains the ':' character the value will be interprited as a 
+    *     uri to a part definition from which a strategy handler can be established, 
+    *     otherwise, the implementation assumes the the value is a strategy handler
+    *     classname resolvable form the current context classloader</li>
+    * </ul>
+    *
+    * @param element the strategy element
+    * @exception Exception if loading error occurs
+    */
+    public static StrategyHandler getStrategyHandler( Element element ) throws Exception
+    {
+        TypeInfo info = element.getSchemaTypeInfo();
+        String namespace = info.getTypeNamespace();
+        String override = System.getProperty( "handler:" + namespace );
+        if( null != override )
+        {
+            return getStrategyHandler( override );
+        }
+        if( AntlibStrategyHandler.NAMESPACE.equals( namespace ) )
+        {
+            return new AntlibStrategyHandler();
+        }
+        else if( ComponentStrategyHandler.NAMESPACE.equals( namespace ) )
+        {
+            return new ComponentStrategyHandler();
+        }
+        else
+        {
+            String urn = ElementHelper.getAttribute( element, "handler" );
+            if( null != urn )
+            {
+                if( urn.indexOf( ":" ) > -1 )
+                {
+                    URI uri = new URI( urn );
+                    return getStrategyHandler( uri );
+                }
+                else
+                {
+                    return getStrategyHandler( urn );
+                }
+            }
+            else
+            {
+                try
+                {
+                    URI uri = getURIFromNamespaceURI( namespace );
+                    return getStrategyHandler( uri );
+                }
+                catch( Exception e )
+                {
+                    final String error = 
+                      "Cannot resolve strategy handler for element.";
+                    throw new DecodingException( error, element );
+                }
+            }
+        }
+    }
+
+   /**
+    * Load a strategy handler.  The implementation will attempt to resolve a 
+    * part defintion from the supplied uri, caching a reference to
+    * the handler, and returning the strategy handler instance.
+    *
+    * @param uri the part handler part uri
+    * @exception Exception if part loading error occurs
+    */
+    static StrategyHandler getStrategyHandler( URI uri ) throws Exception
+    {
+        ClassLoader context = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader( ClassLoader.getSystemClassLoader() ); // TODO
+        try
+        {
+            Strategy strategy = Strategy.load( null, null, uri, null );
+            StrategyHandler handler = strategy.getContentForClass( StrategyHandler.class );
+            if( null == handler )
+            {
+                final String error = 
+                  "URI does not resolve to a strategy handler ["
+                  + uri
+                  + "]";
+                throw new ServiceError( error );
+            }
+            else
+            {
+                return handler;
+            }
+        }
+        finally
+        {
+            Thread.currentThread().setContextClassLoader( context );
+        }
+    }
+    
+    static StrategyHandler getStrategyHandler( String classname ) throws Exception
+    {
+        ServiceLoader<StrategyHandler> handlers = ServiceLoader.load( StrategyHandler.class );
+        for( StrategyHandler handler : handlers )
+        {
+            if( handler.getClass().getName().equals( classname ) )
+            {
+                return handler;
+            }
+        }
+        throw new UnknownServiceException( classname );
+    }
+    
+    //--------------------------------------------------------------------------------
+    // constructor
+    //--------------------------------------------------------------------------------
+    
+    public PartContentHandler() throws Exception
+    {
+        String flag = System.getProperty( "dpml.jmx.enabled", "false" );
+        if( "true".equals( flag ) )
+        {
+            try
+            {
+                MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+                Hashtable<String,String> table = new Hashtable<String,String>();
+                table.put( "type", "Parts" );
+                ObjectName name =
+                  ObjectName.getInstance( "net.dpml.transit", table );
+                server.registerMBean( this, name );
+            }
+            catch( InstanceAlreadyExistsException e )
+            {
+                //e.printStackTrace();
+            }
+        }
+    }
+    
+    //--------------------------------------------------------------------------------
+    // ContentHandler
+    //--------------------------------------------------------------------------------
+
+   /**
+    * Returns the type tha the content handler supports.
+    * @return the content type name
+    */
+    public String getType()
+    {
+        return PART_CONTENT_TYPE;
+    }
+    
+   /**
+    * Returns the content in the form of a {@link net.dpml.lang.Strategy} datatype.
+    * @param connection the url connection
+    * @return the part datatype
+    * @exception IOException if an IO error occurs
+    */
+    public Object getContent( URLConnection connection ) throws IOException
+    {
+        Part part = getPartContent( connection );
+        return part.getStrategy();
+    }
+    
+   /**
+    * Returns the content assignable to the first recognized class in the list
+    * os supppied classes.  If the class array is empty the part datatype is returned.
+    * If none of the classes are recognized, null is returned.
+    * @param connection the url connection
+    * @param classes the selection class array
+    * @return the resolved instance
+    * @exception IOException if an IO error occurs
+    */
+    public Object getContent( URLConnection connection, Class[] classes ) throws IOException
+    {
+        Part part = getPartContent( connection );
+        return getContentForClasses( part, classes );
+    }
+    
+    //--------------------------------------------------------------------------------
+    // ApplianceFactory
+    //--------------------------------------------------------------------------------
+    
+   /**
+    * Create a new appliance using the supplied connection object.
+    * @param connection the URL connection
+    * @param partition an optional partition name
+    * @return the appliance
+    * @exception IOException if an IO error occurs
+    */
+    public Appliance newAppliance( URLConnection connection, String partition ) throws IOException
+    {
+        Part part = getPartContent( connection, partition );
+        return getContentForClass( part, Appliance.class );
+    }
+    
+    //--------------------------------------------------------------------------------
+    // ContentManager
+    //--------------------------------------------------------------------------------
+    
+    public PartManager[] getPartManagers()
+    {
+        ArrayList<PartManager> list = new ArrayList<PartManager>();
+        Part[] parts = CACHE.values().toArray( new Part[0] );
+        for( Part part : parts )
+        {
+            if( part instanceof PartManager )
+            {
+                PartManager manager = (PartManager) part;
+                list.add( manager );
+            }
+        }
+        return list.toArray( new PartManager[0] );
+    }
+    
+    //--------------------------------------------------------------------------------
+    // internals
+    //--------------------------------------------------------------------------------
+    
+    private Logger getLogger()
+    {
+        return LOGGER;
+    }
+    
+   /**
+    * Return a resolved value given a supplied part instance and class.
+    * @param part the part to resolve against
+    * @param c the return type
+    * @return the resolved value
+    * @exception IOException if an error occurs
+    */
+    private <T>T getContentForClass( Part part, Class<T> c ) throws IOException
+    {
+        if( Part.class == c )
+        {
+            return c.cast( part );
+        }
+        Strategy strategy = part.getStrategy();
+        return strategy.getContentForClass( c );
+    }
+    
+    private Object getContentForClasses( Part part, Class[] classes ) throws IOException
+    {
+        Strategy strategy = part.getStrategy();
+        for( Class<?> c : classes )
+        {
+            Object content = strategy.getContentForClass( c );
+            if( null != content )
+            {
+                return content;
+            }
+        }
+        return null;
+    }
+    
+    static Part getPartContent( URLConnection connection ) throws IOException
+    {
+        return getPartContent( connection, null, true );
+    }
+    
+    static Part getPartContent( URLConnection connection, String name ) throws IOException
+    {
+        return getPartContent( connection, name, true );
+    }
+    
+    static Part getPartContent( URLConnection connection, String name, boolean cache ) throws IOException
+    {
+        return getPartContent( null, connection, name, cache );
+    }
+    
+    static Part getPartContent( ClassLoader anchor, URLConnection connection, String name, boolean cache ) throws IOException
+    {
+        ClassLoader classloader = getAnchorClassLoader( anchor );
+        URL url = connection.getURL();
+        try
+        {
+            String key = buildKey( classloader, url );
+            if( cache )
+            {
+                //WeakReference ref = CACHE.get( key );
+                //if( null != ref )
+                //{
+                //    Part part = (Part) ref.get();
+                    //if( null != part )
+                    //{
+                    //    if( getLogger().isTraceEnabled() )
+                    //    {
+                    //        getLogger().trace( "located cached part: " + url );
+                    //    }
+                    //    return part;
+                    //}
+                    //else
+                    //{
+                    //    if( getLogger().isTraceEnabled() )
+                    //    {
+                    //        getLogger().trace( "located disgarded ref: " + key );
+                    //    }
+                    //}
+                //}
+                
+                Part part = CACHE.get( key );
+                if( null != part )
+                {
+                    return part;
+                }
+                else
+                {
+                    // otherwise we need to build it
+                    
+                    part = buildPart( classloader, connection, name );
+                    //if( part instanceof PartManager )
+                    //{
+                    //    // register it with the mbean server
+                    //}
+                    
+                    //WeakReference<Part> reference = new WeakReference<Part>( part );
+                    //CACHE.put( key, reference );
+                    CACHE.put( key, part );
+                    if( LOGGER.isTraceEnabled() )
+                    {
+                        LOGGER.trace( "caching part" 
+                          + "\n  url: " + url
+                          + "\n  key: " + key ); 
+                    }
+                    return part;
+                }
+            }
+            else
+            {
+                if( LOGGER.isTraceEnabled() )
+                {
+                    LOGGER.trace( "building new part: " + url );
+                }
+                return buildPart( classloader, connection, name );
+            }
+        }
+        catch( IOException e )
+        {
+            throw e;
+        }
+        catch( NoClassDefFoundError e )
+        {
+            LOGGER.error( 
+              e.toString() 
+              + "\n" 
+              + classloader.toString() );
+            throw e;
+        }
+        catch( Exception e )
+        {
+            final String error = "Unexpected error in part handling: " + url;
+            IOException ioe = new IOException();
+            ioe.initCause( e );
+            throw ioe;
+        }
+    }
+    
+    private static Part buildPart( ClassLoader anchor, URLConnection connection, String name ) throws Exception
+    {
+        URL url = connection.getURL();
+        if( LOGGER.isTraceEnabled() )
+        {
+            LOGGER.trace( 
+              "building part ["
+              + url
+              + "] with anchor ["
+              + System.identityHashCode( anchor )
+              + "]" );
+        }
+        
+        Document document = DOCUMENT_BUILDER.parse( connection );
+        final Element element = document.getDocumentElement();
+        TypeInfo type = element.getSchemaTypeInfo();
+        String namespace = type.getTypeNamespace();
+        if( isNamespaceRecognized( namespace ) )
+        {
+            URI uri = url.toURI();
+            Resolver resolver = new SimpleResolver();
+            Info info = getInfo( uri, element );
+            Classpath classpath = getClasspath( element );
+            ClassLoader classloader = CLASSLOADER_HELPER.newClassLoader( anchor, uri, classpath );
+            ClassLoader context = Thread.currentThread().getContextClassLoader();
+            Thread.currentThread().setContextClassLoader( classloader );
+            try
+            {
+                Element elem = getStrategyElement( element );
+                StrategyHandler handler = getStrategyHandler( elem );
+                String query = url.getQuery();
+                Strategy strategy = handler.build( classloader, elem, resolver, name, query );
+                if( LOGGER.isTraceEnabled() )
+                {
+                    LOGGER.trace( 
+                      "establised new part using [" 
+                      + strategy.getClass().getName() 
+                      + "]" );
+                }
+                return new Part( info, classpath, strategy );
+            }
+            finally
+            {
+                Thread.currentThread().setContextClassLoader( context );
+            }
+        }
+        else
+        {
+            final String error = 
+              "Part namespace not recognized."
+              + "\nFound: " + namespace
+              + "\nExpecting: " + PartContentHandler.NAMESPACE;
+            throw new DecodingException( error, element );
+        }
+    }
+    
+    private static boolean isNamespaceRecognized( String namespace )
+    {
+        if( NAMESPACE.equals( namespace ) )
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    private static Info getInfo( URI uri, Element root )
+    {
+        Element element = ElementHelper.getChild( root, "info" );
+        if( null == element )
+        {
+            return new Info( uri, null, null );
+        }
+        String title = ElementHelper.getAttribute( element, "title" );
+        Element descriptionElement = ElementHelper.getChild( element, "description" );
+        String description = ElementHelper.getValue( descriptionElement );
+        return new Info( uri, title, description );
+    }
+
+   /**
+    * Construct the classpath defintion.
+    * @param root the element containing a 'classpath' element.
+    * @return the classpath definition
+    * @exception DecodingException if an error occurs during element evaluation
+    */
+    private static Classpath getClasspath( Element root ) throws DecodingException
+    {
+        Element classpath = ElementHelper.getChild( root, "classpath" );
+        if( null == classpath )
+        {
+            return new Classpath();
+        }
+        
+        try
+        {
+            Element[] children = ElementHelper.getChildren( classpath );
+            URI[] sys = buildURIs( classpath, "system" );
+            URI[] pub = buildURIs( classpath, "public" );
+            URI[] prot = buildURIs( classpath, "protected" );
+            URI[] priv = buildURIs( classpath, "private" );
+            return new Classpath( sys, pub, prot, priv );
+        }
+        catch( Throwable e )
+        {
+            final String error = 
+              "Unable to decode classpath due to an unexpected error.";
+            throw new DecodingException( error, e, classpath );
+        }
+    }
+    
+    private static URI[] buildURIs( Element classpath, String key ) throws Exception
+    {
+        Element category = ElementHelper.getChild( classpath, key );
+        Element[] children = ElementHelper.getChildren( category, "uri" );
+        URI[] uris = new URI[ children.length ];
+        for( int i=0; i<children.length; i++ )
+        {
+            Element child = children[i];
+            String value = ElementHelper.getValue( child );
+            uris[i] = new URI( value );
+        }
+        return uris;
+    }
+    
+    // cache utils
+    
+    private static String buildKey( ClassLoader classloader, URL url ) throws IOException
+    {
+        try
+        {
+            int n = System.identityHashCode( classloader );
+            return "" + n + "#" + url.toURI().toASCIIString();
+        }
+        catch( Exception e )
+        {
+            final String error = "Internal error while resolving part key from url: " + url;
+            IOException ioe = new IOException();
+            ioe.initCause( e );
+            throw ioe;
+        }
+    }
+
+    static ClassLoader getAnchorClassLoader( ClassLoader parent )
+    {
+        if( null != parent )
+        {
+            return parent;
+        }
+        else
+        {
+            return Strategy.class.getClassLoader();
+            //ClassLoader classloader = Thread.currentThread().getContextClassLoader();
+            //if( null == classloader )
+            //{
+            //    return getClass().getClassLoader();
+            //}
+            //else
+            //{
+            //    return classloader;
+            //}
+        }
+    }
+
+    private static Element getStrategyElement( Element root ) throws DecodingException
+    {
+        Element[] children = ElementHelper.getChildren( root );
+        for( Element element : children )
+        {
+            String name = element.getLocalName();
+            if( !name.equals( "info" ) && !name.equals( "classpath" ) )
+            {
+                return element;
+            }
+        }
+        final String error = 
+          "Missing part strategy element.";
+        throw new DecodingException( error, root );
+    }
+
+   /**
+    * Resolve the part handler given an element namespace.
+    * @param urn the namespace value
+    * @return the decoder uri
+    * @exception Exception if an error occurs
+    */
+    private static URI getURIFromNamespaceURI( String urn ) throws Exception
+    {
+        URI raw = new URI( urn );
+        Artifact artifact = Artifact.createArtifact( raw );
+        String group = artifact.getGroup();
+        String name = artifact.getName();
+        String path = "link:part:" + group + "/" + name;
+        Artifact link = Artifact.createArtifact( path );
+        return link.toURI();
+    }
+}
\ No newline at end of file

Added: trunk/main/lang/part/src/main/net/dpml/lang/PartContentManager.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/PartContentManager.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/PartContentManager.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 Stephen McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import net.dpml.transit.ContentManager;
+
+import javax.management.MXBean;
+
+/**
+ * Abstract base class for artifact content handler.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ @MXBean
+public interface PartContentManager extends ContentManager
+{
+    PartManager[] getPartManagers();
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/PartError.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/PartError.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/PartError.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2004-2005 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+/**
+ * Fatal part related error.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class PartError extends Error
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>PartError</code> instance.
+     *
+     * @param message The detail message for this exception.
+     */
+    public PartError( final String message )
+    {
+        this( message, null );
+    }
+
+    /**
+     * Construct a new <code>PartError</code> instance.
+     *
+     * @param message The detail message for this exception.
+     * @param cause the root cause of the exception
+     */
+    public PartError( final String message, final Throwable cause )
+    {
+        super( message );
+        super.initCause( cause );
+    }
+}
+
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/PartException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/PartException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/PartException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2004-2005 Stephen J. McConnell.
+ * Copyright 2004 Niclas Hedhman.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import java.io.IOException;
+
+/**
+ * Exception to indicate that there was a part handler related error.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class PartException extends IOException
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>PartException</code> instance.
+     *
+     * @param message The detail message for this exception.
+     */
+    public PartException( final String message )
+    {
+        this( message, null );
+    }
+
+    /**
+     * Construct a new <code>PartException</code> instance.
+     *
+     * @param message The detail message for this exception.
+     * @param cause the root cause of the exception
+     */
+    public PartException( final String message, final Throwable cause )
+    {
+        super( message );
+        super.initCause( cause );
+    }
+}
+
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/PartManager.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/PartManager.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/PartManager.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2006 Stephen McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import javax.management.MXBean;
+
+/**
+ * Management interface to a generic part instance.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at MXBean
+public interface PartManager
+{
+   /**
+    * Returns the part URI as a string.
+    * @return the codebase uri
+    */
+    String getCodebaseURI();
+    
+   /**
+    * Returns the part title.
+    * @return the title
+    */
+    String getTitle();
+    
+   /**
+    * Returns the part description.
+    * @return the description
+    */
+    String getDescription();
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/ServiceError.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/ServiceError.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/ServiceError.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+/**
+ * Fatal service handling error.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ServiceError extends Error
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>ServiceError</code>.
+     *
+     * @param message the error message
+     */
+    public ServiceError( final String message )
+    {
+        super( message );
+    }
+    
+    /**
+     * Construct a new <code>ServiceError</code>.
+     *
+     * @param message the error message
+     * @param cause the causal exception
+     */
+    public ServiceError( final String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+    
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/ServiceRegistry.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/ServiceRegistry.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/ServiceRegistry.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+/**
+ * Component interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface ServiceRegistry
+{
+    <T>T lookup( Class<T> service );
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/SimpleServiceRegistry.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/SimpleServiceRegistry.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/SimpleServiceRegistry.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import java.util.ServiceLoader;
+
+import net.dpml.lang.ServiceRegistry;
+
+/**
+ * Simple service registry implementation that selects the first service 
+ * that is type assignable from the list of service instance supplied to 
+ * the registry constructor.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class SimpleServiceRegistry implements ServiceRegistry
+{
+    private final ServiceRegistry m_parent;
+    private final Object[] m_args;
+    
+   /**
+    * Creation of a new service registry with no parent.
+    * @param args an ordered sequence of thread-safe services
+    */
+    public SimpleServiceRegistry( Object... args )
+    {
+       this( null, args );
+    }
+    
+   /**
+    * Creation of a new service registry with no parent.
+    * @param parent an optional fallback registry
+    * @param args an ordered sequence of thread-safe services
+    */
+    public SimpleServiceRegistry( ServiceRegistry parent, Object... args )
+    {
+        if( null == args )
+        {
+            throw new NullPointerException( "args" );
+        }
+        m_parent = parent;
+        m_args = args;
+    }
+    
+   /**
+    * Matches a service in the registry with the supplied type.  If no
+    * match is found and a parent registry has been delclared, the lookup
+    * request is passed onto the parent registry, otherwise null is 
+    * returned.
+    */
+    public <T>T lookup( Class<T> type )
+    {
+        for( Object object : m_args )
+        {
+            if( null != object )
+            {
+                Class c = object.getClass();
+                if( type.isAssignableFrom( c ) )
+                {
+                    return type.cast( object );
+                }
+            }
+        }
+        if( null != m_parent )
+        {
+            return m_parent.lookup( type );
+        }
+        return null;
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/StandardServiceRegistry.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/StandardServiceRegistry.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/StandardServiceRegistry.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import java.util.ServiceLoader;
+
+/**
+ * Default service registry implementation that resolves services via 
+ * services resolvable using <tt>java.util.ServiceLoader</tt>.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StandardServiceRegistry implements ServiceRegistry
+{
+    private final ServiceRegistry m_parent;
+    
+   /**
+    * Creation of a new service registry with no parent.
+    */
+    public StandardServiceRegistry()
+    {
+        this( null );
+    }
+    
+   /**
+    * Creation of a new service registry with fallback delegation to
+    * a parent registry.
+    *
+    * @param parent an optional parent registry
+    */
+    public StandardServiceRegistry( ServiceRegistry parent )
+    {
+        m_parent = parent;
+    }
+    
+   /**
+    * Matches a service in the registry with the supplied type.  If no
+    * match is found and a parent registry has been delclared, the lookup
+    * request is passed onto the parent registry, otherwise null is 
+    * returned.
+    */
+    public <T>T lookup( Class<T> type )
+    {
+        ServiceLoader<T> loaders = ServiceLoader.load( type );
+        for( T service : loaders )
+        {
+            return service; // the first available
+        }
+        if( null != m_parent )
+        {
+            return m_parent.lookup( type );
+        }
+        return null;
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/Strategy.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/Strategy.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/Strategy.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import dpml.lang.Part;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ServiceLoader;
+
+import javax.xml.XMLConstants;
+
+import net.dpml.transit.Artifact;
+import net.dpml.transit.Transit;
+
+import net.dpml.runtime.ComponentStrategyHandler;
+import net.dpml.util.Logger;
+
+import dpml.util.DefaultLogger;
+import dpml.util.ElementHelper;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * Abstract component deployment strategy.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public abstract class Strategy implements Comparable<Strategy>
+{
+    private static final Logger LOGGER = new DefaultLogger( "dpml.lang" );
+    
+   /**
+    * Creation of a new management strategy.
+    *
+    * @param subject the implementation class to be managed
+    * @param registry the service registry
+    * @param name the path under which the strategy will be established
+    * @return the management strategy
+    * @exception Exception if a general loading error occurs
+    */
+    public static Strategy load( Class<?> subject, ServiceRegistry registry, String name ) throws Exception
+    {
+        if( null == subject )
+        {
+            throw new NullPointerException( "subject" );
+        }
+        StrategyHandler handler = PartContentHandler.getStrategyHandler( subject );
+        Strategy strategy = handler.newStrategy( subject, name );
+        if( null == registry )
+        {
+            StandardServiceRegistry standard = new StandardServiceRegistry();
+            strategy.initialize( standard );
+        }
+        else
+        {
+            strategy.initialize( registry );
+        }
+        return strategy;
+    }
+    
+   /**
+    * Load a strategy defined by the supplied uri.
+    *
+    * @param uri the source uri to a part definition
+    * @return the strategy
+    * @exception Exception if a general loading error occurs
+    * @exception NullPointerException if the uri argument is null
+    */
+    public static Strategy load( URI uri ) throws Exception, NullPointerException
+    {
+        return load( null, null, uri, null );
+    }
+    
+   /**
+    * Load a strategy defined by the supplied uri, name, classloader and service 
+    * registry, and return a value assignable to the supplied type.
+    *
+    * @param classloader the anchor classloader
+    * @param registry the service registry
+    * @param uri the source uri to a part definition
+    * @param name the path under which the strategy will be established
+    * @return an instance of the supplied type
+    * @exception Exception if a general loading error occurs
+    * @exception NullPointerException if the uri argument is null
+    */
+    public static Strategy load( 
+      ClassLoader classloader, ServiceRegistry registry, URI uri, String name ) throws Exception, NullPointerException
+    {
+        if( null == uri )
+        {
+            throw new NullPointerException( "uri" );
+        }
+        Transit transit = Transit.getInstance();
+        URL url = Artifact.toURL( uri );
+        URLConnection connection = url.openConnection();
+        Part part = PartContentHandler.getPartContent( classloader, connection, name, true );
+        Strategy strategy = part.getStrategy();
+        if( null == registry )
+        {
+            StandardServiceRegistry standard = new StandardServiceRegistry();
+            strategy.initialize( standard );
+        }
+        else
+        {
+            strategy.initialize( registry );
+        }
+        return strategy;
+    }
+    
+    //--------------------------------------------------------------------
+    // state
+    //--------------------------------------------------------------------
+
+    private ClassLoader m_classloader;
+    
+    //--------------------------------------------------------------------
+    // constructor
+    //--------------------------------------------------------------------
+    
+   /**
+    * Creation of a new deployment strategy.
+    * @param classloader the classloader
+    */
+    protected Strategy( ClassLoader classloader )
+    {
+        m_classloader = classloader;
+    }
+    
+    //--------------------------------------------------------------------
+    // public operations
+    //--------------------------------------------------------------------
+
+   /**
+    * Return the classloader establised by the strategy implementation.
+    * @return the classloader
+    */
+    public ClassLoader getClassLoader()
+    {
+        return m_classloader;
+    }
+    
+   /**
+    * Return the priority assigned to this strategy.
+    * @return the priority value
+    */
+    public abstract int getPriority();
+    
+   /**
+    * Return true if this strategy is a candidate with result to the 
+    * supply of an instance assignable to the supplied type.
+    * 
+    * @param type the requested type
+    * @return type if this strategy is a condidate
+    */
+    public abstract boolean isaCandidate( Class<?> type );
+    
+   /**
+    * Instantiate a service returning an instance assigned to the supplied type.
+    *
+    * @param type the return type
+    * @return an instance of the type
+    */
+    public abstract <T>T getInstance( Class<T> type );
+    
+   /**
+    * Write the strategy to the supplied buffer in XML format.
+    * @param buffer the output buffer
+    * @param key the optional identifying key
+    * @exception IOException if an IO error occurs
+    */
+    public abstract void encode( Buffer buffer, String key ) throws IOException;
+
+   /**
+    * Composite strategies are strategy implementations that contain subidary
+    * strategies.  During lookup operations, a subsidiary strategy may request 
+    * a service from the enclosing strategy.  To enable traversal from a subsidary
+    * to enclosing context a service registry shall be provided to all subsidiary
+    * strategies.
+    * 
+    * @param registry the service registry
+    */
+    public abstract void initialize( ServiceRegistry registry );
+    
+   /**
+    * Return the short name of this strategy.
+    * @return the name
+    */
+    public abstract String getName();
+
+   /**
+    * Compares a supplied strategy with this strategy.  If the supplied
+    * strategy has a priority greater than this strategy the returned value
+    * is 1, otherwise if the supplied strategy has a priority lower than this
+    * strategy then the return value is -1,otherwise the returned value is 0.
+    *
+    * @param strategy the strategy to evaluate relative to this strategy
+    * @return the priority comparative index
+    */
+    public int compareTo( Strategy strategy )
+    {
+        int n = getPriority();
+        int m = strategy.getPriority();
+        if( n > m )
+        {
+            return -1;
+        }
+        else if( n == m )
+        {
+            return 0;
+        }
+        else
+        {
+            return 1;
+        }
+    }
+
+    //--------------------------------------------------------------------
+    // protected operations
+    //--------------------------------------------------------------------
+    
+   /**
+    * Return a value assignable to the supplied type or null if the type
+    * cannot be resolved from this strategy.
+    * @param c the target class
+    * @return an instance of the class or null
+    * @exception IOException if an IO error occurs
+    */
+    public abstract <T>T getContentForClass( Class<T> c ) throws IOException;
+    
+    //--------------------------------------------------------------------
+    // private implementation
+    //--------------------------------------------------------------------
+    
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/StrategyHandler.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/StrategyHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/StrategyHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import dpml.lang.Classpath;
+
+import net.dpml.util.Logger;
+import net.dpml.util.Resolver;
+
+import org.w3c.dom.Element;
+
+/**
+ * Interace implemented by part strategy handlers.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface StrategyHandler
+{
+   /**
+    * Creation of a new strategy handler for the supplied implementation class.
+    * @param c the component implementation class
+    * @exception IOException if an I/O error occurs
+    */
+    Strategy newStrategy( Class<?> c ) throws IOException;
+
+   /**
+    * Creation of a new strategy handler for the supplied implementation class.
+    * @param c the component implementation class
+    * @param name the component name
+    * @exception IOException if an I/O error occurs
+    */
+    Strategy newStrategy( Class<?> c, String name ) throws IOException;
+    
+   /**
+    * Construct a new strategy using a supplied element and value resolver.
+    * @param classloader the classloader
+    * @param element the DOM element definining the deployment strategy
+    * @param resolver symbolic property resolver
+    * @param partition the assigned partition
+    * @param query the query 
+    * @return the strategy
+    * @exception IOException if an I/O error occurs
+    */
+    Strategy build( 
+      ClassLoader classloader, Element element, Resolver resolver, String partition, String query ) throws IOException;
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/TypeCastException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/TypeCastException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/TypeCastException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+import dpml.util.StandardClassLoader;
+
+/**
+ * Exception raised when class cannot be cast to a requested type.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class TypeCastException extends ClassCastException
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+    
+    private final Class m_base;
+    private final Class m_type;
+    
+    /**
+     * Construct a new <code>TypeCastException</code> instance.
+     *
+     * @param message the message
+     * @param base the base class against which a failed cast was attempted
+     * @param type the class used as the cast criteria
+     */
+    public TypeCastException( final String message, Class base, Class type )
+    {
+        super( message );
+        m_base = base;
+        m_type = type;
+    }
+    
+    public Class getBase()
+    {
+        return m_base;
+    }
+    
+    public Class getType()
+    {
+        return m_type;
+    }
+    
+    public String getReport()
+    {
+        return StandardClassLoader.toString( m_base, m_type );
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/UnknownKeyException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/UnknownKeyException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/UnknownKeyException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+/**
+ * Exception to indicate an error arrising from the use of an unknown key.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class UnknownKeyException extends Exception
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+    
+    private final String m_key;
+
+    /**
+     * Construct a new <code>UnknownKeyException</code> instance.
+     *
+     * @param key the unknown key
+     */
+    public UnknownKeyException( final String key )
+    {
+        super( "[" + key + "]" );
+        
+        m_key = key;
+    }
+
+   /**
+    * Return the key.
+    * @return the key
+    */
+    public String getKey()
+    {
+        return m_key;
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/UnknownServiceException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/UnknownServiceException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/UnknownServiceException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.lang;
+
+/**
+ * Exception  raised if a requested service cannot be found.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class UnknownServiceException extends Exception
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+    
+    /**
+     * Construct a new <code>UnknownServiceException</code> instance.
+     *
+     * @param classname the class name
+     */
+    public UnknownServiceException( final String classname )
+    {
+        super( classname );
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/lang/Version.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/Version.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/Version.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ * Copyright 1999-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.dpml.lang;
+
+import java.io.Serializable;
+
+import java.util.StringTokenizer;
+
+/**
+ * This class is used to hold version information.
+ * <p />
+ *
+ * The version number is made up of three dot-separated fields:
+ * <p />
+ * &quot;<b>major.minor.micro</b>&quot;
+ * <p />
+ * The <b>major</b>, <b>minor</b> and <b>micro</b> fields are
+ * <i>integer</i> numbers represented in decimal notation and have the
+ * following meaning:
+ * <ul>
+ *
+ * <p /><li><b>major</b> - When the major version changes (in ex. from
+ * &quot;1.5.12&quot; to &quot;2.0.0&quot;), then backward compatibility
+ * with previous releases is not granted.</li><p />
+ *
+ * <p /><li><b>minor</b> - When the minor version changes (in ex. from
+ * &quot;1.5.12&quot; to &quot;1.6.0&quot;), then backward compatibility
+ * with previous releases is granted, but something changed in the
+ * implementation of the Component. (ie it methods could have been added)</li><p />
+ *
+ * <p /><li><b>micro</b> - When the micro version changes (in ex.
+ * from &quot;1.5.12&quot; to &quot;1.5.13&quot;), then the the changes are
+ * small forward compatible bug fixes or documentation modifications etc.
+ * </li>
+ * </ul>
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class Version implements Comparable, Serializable
+{
+   /**
+    * Version -1.0.0.
+    */
+    public static final Version NULL_VERSION = new Version( -1, 0, 0 );
+    
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    private int m_major;
+    private int m_minor;
+    private int m_micro;
+
+    /**
+     * Parse a version out of a string.
+     * The version string format is <major>.<minor>.<micro> where
+     * both minor and micro are optional.
+     *
+     * @param version The input version string
+     * @return the new Version object
+     * @throws NumberFormatException if an error occurs
+     * @throws IllegalArgumentException if an error occurs
+     * @throws NullPointerException if the version argument is <code>null</code>.
+     * @since 4.1
+     */
+    public static Version parse( final String version )
+        throws NumberFormatException, IllegalArgumentException, NullPointerException
+    {
+        if( version == null )
+        {
+            throw new NullPointerException( "version" );
+        }
+
+        final StringTokenizer tokenizer = new StringTokenizer( version, "." );
+        final String[] levels = new String[ tokenizer.countTokens() ];
+        for( int i = 0; i < levels.length; i++ )
+        {
+            levels[ i ] = tokenizer.nextToken();
+        }
+
+        int major = -1;
+        if( 0 < levels.length )
+        {
+            major = Integer.parseInt( levels[ 0 ] );
+        }
+
+        int minor = 0;
+        if( 1 < levels.length )
+        {
+            minor = Integer.parseInt( levels[ 1 ] );
+        }
+
+        int micro = 0;
+        if( 2 < levels.length )
+        {
+            micro = Integer.parseInt( levels[ 2 ] );
+        }
+
+        return new Version( major, minor, micro );
+    }
+
+    /**
+     * Create a new instance of a <code>Version</code> object with the
+     * specified version numbers.
+     *
+     * @param major This <code>Version</code> major number.
+     * @param minor This <code>Version</code> minor number.
+     * @param micro This <code>Version</code> micro number.
+     */
+    public Version( final int major, final int minor, final int micro )
+    {
+        m_major = major;
+        m_minor = minor;
+        m_micro = micro;
+    }
+
+    /**
+     * Retrieve major component of version.
+     *
+     * @return the major component of version
+     * @since 4.1
+     */
+    public int getMajor()
+    {
+        return m_major;
+    }
+
+    /**
+     * Retrieve minor component of version.
+     *
+     * @return the minor component of version
+     * @since 4.1
+     */
+    public int getMinor()
+    {
+        return m_minor;
+    }
+
+    /**
+     * Retrieve micro component of version.
+     *
+     * @return the micro component of version.
+     * @since 4.1
+     */
+    public int getMicro()
+    {
+        return m_micro;
+    }
+
+    /**
+     * Check this <code>Version</code> against another for equality.
+     * <p />
+     * If this <code>Version</code> is compatible with the specified one, then
+     * <b>true</b> is returned, otherwise <b>false</b>.
+     *
+     * @param other The other <code>Version</code> object to be compared with this
+     *          for equality.
+     * @return <b>true</b> if this <code>Version</code> is compatible with the specified one
+     * @since 4.1
+     */
+    public boolean equals( final Version other )
+    {
+        if( other == null )
+        {
+            return false;
+        }
+        boolean isEqual = ( getMajor() == other.getMajor() );
+        if( isEqual )
+        {
+            isEqual = ( getMinor() == other.getMinor() );
+        }
+        if( isEqual )
+        {
+            isEqual = ( getMicro() == other.getMicro() );
+        }
+        return isEqual;
+    }
+
+    /**
+     * Indicates whether some other object is "equal to" this <code>Version</code>.
+     * Returns <b>true</b> if the other object is an instance of <code>Version</code>
+     * and has the same major, minor, and micro components.
+     *
+     * @param other an <code>Object</code> value
+     * @return <b>true</b> if the other object is equal to this <code>Version</code>
+     */
+    public boolean equals( final Object other )
+    {
+        boolean isEqual = false;
+        if( other instanceof Version )
+        {
+            isEqual = equals( (Version) other );
+        }
+        return isEqual;
+    }
+
+    /**
+     * Add a hashing function to ensure the Version object is
+     * treated as expected in hashmaps and sets.  NOTE: any
+     * time the equals() is overridden, hashCode() should also
+     * be overridden.
+     *
+     * @return the hashCode
+     */
+    public int hashCode()
+    {
+        int hash = 61486123 * getMajor();
+        hash = hash + 1273621 * getMinor();
+        hash = hash + 8912738 * getMicro();
+        return hash;
+    }
+
+    /**
+     * Check this <code>Version</code> against another for compliancy
+     * (compatibility).
+     * <p />
+     * If this <code>Version</code> is compatible with the specified one, then
+     * <b>true</b> is returned, otherwise <b>false</b>. Be careful when using
+     * this method since, in example, version 1.3.7 is compliant to version
+     * 1.3.6, while the opposite is not.
+     * <p />
+     * The following example displays the expected behaviour and results of version.
+     * <pre>
+     * final Version v1 = new Version( 1, 3, 6 );
+     * final Version v2 = new Version( 1, 3, 7 );
+     * final Version v3 = new Version( 1, 4, 0 );
+     * final Version v4 = new Version( 2, 0, 1 );
+     *
+     * assert(   v1.complies( v1 ) );
+     * assert( ! v1.complies( v2 ) );
+     * assert(   v2.complies( v1 ) );
+     * assert( ! v1.complies( v3 ) );
+     * assert(   v3.complies( v1 ) );
+     * assert( ! v1.complies( v4 ) );
+     * assert( ! v4.complies( v1 ) );
+     * </pre>
+     *
+     * @param other The other <code>Version</code> object to be compared with this
+     *              for compliancy (compatibility).
+     * @return <b>true</b> if this <code>Version</code> is compatible with the specified one
+     */
+    public boolean complies( final Version other )
+    {
+        if( other == null )
+        {
+            return false;
+        }
+        if( other.m_major == -1 )
+        {
+            return true;
+        }
+        if( m_major != other.m_major )
+        {
+            return false;
+        }
+        else if( m_minor < other.m_minor )
+        {
+            //If of major version but lower minor version then incompatible
+            return false;
+        }
+        else
+        {
+            //If same major version, same minor version but lower micro level
+            //then incompatible
+            return !( m_minor == other.m_minor && m_micro < other.m_micro );
+        }
+    }
+
+    /**
+     * Overload toString to report version correctly.
+     *
+     * @return the dot seperated version string
+     */
+    public String toString()
+    {
+        return m_major + "." + m_minor + "." + m_micro;
+    }
+
+    /**
+     * Compare two versions together according to the
+     * {@link Comparable} interface.
+     * @param o the other object
+     * @return number indicating relative value (-1, 0, 1)
+     * @throws NullPointerException if the argument is null.
+     */
+    public int compareTo( Object o )
+        throws NullPointerException 
+    {
+        if( o == null )
+        {
+            throw new NullPointerException ( "o" );
+        }
+
+        Version other = (Version) o;
+
+        if( getMajor() < other.getMajor() )
+        {
+            return -1;
+        }
+
+        if( getMajor() > other.getMajor() )
+        {
+            return 1;
+        }
+
+        if( getMinor() < other.getMinor() )
+        {
+            return -1;
+        }
+
+        if( getMinor() > other.getMinor() )
+        {
+            return 1;
+        }
+
+        if( getMicro() < other.getMicro() )
+        {
+            return -1;
+        }
+
+        if( getMicro() > other.getMicro() )
+        {
+            return 1;
+        }
+
+        return 0;
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/lang/package-info.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/lang/package-info.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/lang/package-info.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <p>Low-level services dealing with part deployment and management.</p>
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+package net.dpml.lang;

Added: trunk/main/lang/part/src/main/net/dpml/runtime/Component.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/Component.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/Component.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Component interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Component
+{
+   /**
+    * Return the component name.
+    * @return the name
+    */
+    String getName();
+    
+   /**
+    * Add a listener to the component.
+    * @param listener the component listener
+    */
+    void addComponentListener( ComponentListener listener );
+    
+   /**
+    * Remove a listener from the component.
+    * @param listener the component listener
+    */
+    void removeComponentListener( ComponentListener listener );
+    
+   /**
+    * Return a decommissioning provider.
+    * @return the provider
+    */
+    Provider getProvider();
+    
+   /**
+    * Release a provider.
+    * @param provider the provider to release
+    */
+    void release( Provider provider );
+    
+   /**
+    * Terminate the component.
+    */
+    void terminate();
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ComponentError.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ComponentError.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ComponentError.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+/**
+ * Exception to indicate an error arrising from the use of a duplicate key.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ComponentError extends Error
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    /**
+     * Construct a new <code>ComponentError</code>.
+     *
+     * @param message the error message
+     */
+    public ComponentError( final String message )
+    {
+        super( message );
+    }
+    
+    /**
+     * Construct a new <code>ComponentError</code>.
+     *
+     * @param message the error message
+     * @param cause the causal exception
+     */
+    public ComponentError( final String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+    
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ComponentEvent.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ComponentEvent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ComponentEvent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,59 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.util.EventObject;
+
+
+/**
+ * Event triggered as a result of a state change.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public abstract class ComponentEvent extends EventObject
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    private final Component m_component;
+
+   /**
+    * Construct a new <code>StateEvent</code>.
+    *
+    * @param source the source component
+    */
+    public ComponentEvent( final Component source )
+    {
+        super( source );
+        m_component = source;
+    }
+
+   /**
+    * Return the component that initiated the event.
+    * @return the source component
+    */
+    public Component getComponent()
+    {
+        return m_component;
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ComponentException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ComponentException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ComponentException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import net.dpml.lang.DecodingException;
+
+import dpml.util.ElementHelper;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * Component related exception.
+ */
+public class ComponentException extends DecodingException
+{    
+   /**
+    * Create a new decoding exception.
+    * @param message the exception message
+    */
+    public ComponentException( String message )
+    {
+        this( message, null );
+    }
+    
+   /**
+    * Create a new decoding exception.
+    * @param message the exception message
+    * @param cause the causal exception
+    */
+    public ComponentException( String message, Throwable cause )
+    {
+        this( message, cause, null );
+    }
+    
+   /**
+    * Create a new decoding exception.
+    * @param message the exception message
+    * @param cause the causal exception
+    * @param element the element representing the source definition
+    */
+    public ComponentException( String message, Throwable cause, Element element )
+    {
+        super( message, cause, element );
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ComponentInvocationHandler.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ComponentInvocationHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ComponentInvocationHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import net.dpml.annotation.Services;
+
+import dpml.lang.Disposable;
+
+/**
+* Invocation handler supporting instance isolation relative to services 
+* declared by a target implementation class.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+*/
+class ComponentInvocationHandler implements InvocationHandler
+{
+    private Object m_instance;
+    
+   /**
+    * Creation of a new component invocation handler.
+    * @param instance the instance to be isolated
+    */
+    protected ComponentInvocationHandler( Object instance )
+    {
+        m_instance = instance;
+    }
+    
+   /**
+    * Invoke the specified method on underlying object.
+    * This is called by the proxy object.
+    *
+    * @param proxy the proxy object
+    * @param method the method invoked on proxy object
+    * @param args the arguments supplied to method
+    * @return the return value of method
+    * @throws Throwable if an error occurs
+    */
+    public Object invoke( final Object proxy, final Method method, final Object[] args ) 
+      throws InvocationTargetException, IllegalAccessException
+    {
+        return method.invoke( m_instance, args );
+    }
+    
+    protected Object getInstance()
+    {
+        return m_instance;
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ComponentListener.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ComponentListener.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ComponentListener.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,39 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.util.EventListener;
+
+/**
+ * Interface implementated by remote listeners to state change events.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface ComponentListener extends EventListener
+{
+   /**
+    * Notify the listener of an event within the component.
+    *
+    * @param event the comnponent event
+    * @exception RemoteException if a remote transport error occurs
+    */
+    void componentChanged( final ComponentEvent event );
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ComponentStrategy.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ComponentStrategy.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ComponentStrategy.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,889 @@
+/*
+ * Copyright 2004-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import dpml.appliance.StandardAppliance;
+import dpml.lang.Value;
+import dpml.lang.Disposable;
+import dpml.state.StateDecoder;
+import dpml.util.DefaultLogger;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.io.File;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ServiceLoader;
+import java.util.WeakHashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
+
+import net.dpml.annotation.Activation;
+import net.dpml.annotation.CollectionPolicy;
+import net.dpml.annotation.LifestylePolicy;
+import net.dpml.annotation.ActivationPolicy;
+
+import net.dpml.appliance.Appliance;
+
+import net.dpml.lang.Buffer;
+import net.dpml.lang.ServiceRegistry;
+import net.dpml.lang.StandardServiceRegistry;
+import net.dpml.lang.Strategy;
+import net.dpml.lang.TypeCastException;
+
+import net.dpml.state.State;
+import net.dpml.state.StateMachine;
+
+import net.dpml.transit.Artifact;
+
+import net.dpml.util.Logger;
+
+import static dpml.state.DefaultState.NULL_STATE;
+
+/**
+ * Component strategy.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ComponentStrategy extends Strategy implements Component, ServiceRegistry
+{
+    private static final Logger LOGGER = new DefaultLogger( "dpml.lang.component" );
+    private static final ComponentStrategyHandler HANDLER = new ComponentStrategyHandler();
+    
+    private final String m_name;
+    private final int m_priority;
+    private final Class<?> m_class;
+    private final String m_path;
+    private final LifestylePolicy m_lifestyle;
+    private final CollectionPolicy m_collection;
+    private final State m_graph;
+    private final LifestyleHandler m_handler;
+    private final ContextModel m_context;
+    private final ActivationPolicy m_activation;
+    private final PartsDirective m_parts;
+    private final Logger m_logger;
+    private final Map<String,Object> m_map = new Hashtable<String,Object>();
+    
+    private final Set<ComponentListener> m_listeners = new CopyOnWriteArraySet<ComponentListener>();
+    private final ExecutorService m_queue = Executors.newSingleThreadExecutor();
+    
+    private ServiceRegistry m_registry;
+    
+    ComponentStrategy( 
+      final String partition, final String name, int priority, final Class type, ContextModel context, PartsDirective parts ) 
+      throws IOException
+    {
+        super( type.getClassLoader() );
+        
+        m_class = type;
+        m_priority = priority;
+        m_name = getComponentName( name, m_class );
+        m_collection = getCollectionPolicy( m_class );
+        m_lifestyle = getLifestylePolicy( m_class );
+        m_path = getComponentPath( partition, m_name, m_class );
+        m_context = context;
+        m_logger = getComponentLogger( m_path );
+        m_graph = getLifecycleGraph( m_class );
+        m_activation = getActivationPolicy( m_class );
+        m_parts = getPartsDirective( parts );
+        
+        m_parts.initialize( this );
+        
+        m_map.put( "name", m_name );
+        m_map.put( "path", m_path );
+        m_map.put( "work", new File( System.getProperty( "user.dir" ) ).getCanonicalFile() );
+        m_map.put( "temp", new File( System.getProperty( "java.io.tmpdir" ) ).getCanonicalFile() );
+        
+        try
+        {
+            m_map.put( "uri", new URI( "component:" + m_path ) );
+        }
+        catch( Exception e )
+        {
+            e.printStackTrace();
+        }
+        
+        if( m_logger.isTraceEnabled() )
+        {
+            final String message = 
+              "new "
+              + m_collection.toString().toLowerCase()
+              + " "
+              + m_lifestyle.toString().toLowerCase()
+              + " ["
+              + m_class.getName()
+              + "]";
+            m_logger.trace( message );
+        }
+        
+        m_handler = getLifestyleHandler( m_lifestyle );
+    }
+    
+    public String getName()
+    {
+        return m_name;
+    }
+    
+    public int getPriority()
+    {
+        return m_priority;
+    }
+    
+   /**
+    * Add a listener to the component.
+    * @param listener the component listener
+    */
+    public void addComponentListener( ComponentListener listener )
+    {
+        m_listeners.add( listener );
+    }
+    
+   /**
+    * Remove a listener from the component.
+    * @param listener the component listener
+    */
+    public void removeComponentListener( ComponentListener listener )
+    {
+        m_listeners.remove( listener );
+    }
+
+    void processEvent( ComponentEvent event )
+    {
+        Logger logger= getLogger();
+        for( ComponentListener listener : m_listeners )
+        {
+            m_queue.execute( new ComponentEventDistatcher( logger, listener, event ) );
+        }
+    }
+    
+    Map<String,Object> getContextMap()
+    {
+        return m_map;
+    }
+    
+    public Provider getProvider()
+    {
+        synchronized( m_handler )
+        {
+            return m_handler.getProvider();
+        }
+    }
+    
+    public void release( Provider provider )
+    {
+        synchronized( m_handler )
+        {
+            m_handler.release( provider );
+        }
+    }
+    
+    public void initialize( ServiceRegistry registry ) // TODO: parts initialization should occur here?
+    {
+        if( m_logger.isTraceEnabled() )
+        {
+            m_logger.trace( "initialization" );
+        }
+        m_registry = registry;
+    }
+
+    public boolean isaCandidate( Class<?> type )
+    {
+        return type.isAssignableFrom( m_class );
+    }
+    
+    public <T>T lookup( Class<T> service )
+    {
+        if( m_logger.isTraceEnabled() )
+        {
+            m_logger.trace( "lookup: " + service.getName() );
+        }
+        
+        for( String key : m_parts.getKeys() )
+        {
+            Strategy strategy = m_parts.getStrategy( key );
+            if( strategy.isaCandidate( service ) )
+            {
+                try
+                {
+                    return strategy.getInstance( service );
+                }
+                catch( Exception e )
+                {
+                    if( strategy instanceof ComponentStrategy )
+                    {
+                        ComponentStrategy s = (ComponentStrategy) strategy;
+                        String path = s.getComponentPath();
+                        
+                        final String error = 
+                          "Lookup aquisition in ["
+                          + getComponentPath()
+                          + "] failed while aquiring the service ["
+                          + service.getName()
+                          + "] from the provider ["
+                          + path 
+                          + "].";
+                        throw new ComponentError( error, e );
+                    }
+                    else
+                    {
+                        final String error = 
+                          "Lookup aquisition in ["
+                          + getComponentPath()
+                          + "] failed while aquiring the service ["
+                          + service.getName()
+                          + "].";
+                        throw new ComponentError( error, e );
+                    }
+                }
+            }
+        }
+        
+        if( null != m_registry )
+        {
+            return m_registry.lookup( service );
+        }
+        else
+        {
+            ServiceRegistry registry = new StandardServiceRegistry();
+            return registry.lookup( service );
+        }
+    }
+    
+    public void terminate()
+    {
+        terminate( 10, TimeUnit.SECONDS );
+    }
+    
+    void terminate( long timeout, TimeUnit units )
+    {
+        synchronized( this )
+        {
+            if( getLogger().isTraceEnabled() )
+            {
+                getLogger().trace( "termination" );
+            }
+            m_handler.terminate();
+            m_queue.shutdown();
+            try
+            {
+                boolean ok = m_queue.awaitTermination( timeout, units );
+                if( !ok )
+                {
+                    final String message = 
+                      "Component termination timeout in ["
+                      + getName()
+                      + "] (some events may not have been processed).";
+                    getLogger().warn( message );
+                }
+            }
+            catch( Exception e )
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+    
+   /**
+    * Internal support for the resolution of a context service lookup request.
+    * The service classname comes from a context entry in this component and 
+    * is resolved by the parent component.  The parent evaluates off of its 
+    * internal parts for a component implementing the service and if found, 
+    * the instance is returned.
+    */
+    <T>T getService( Class<?> clazz, Class<T> type ) throws Exception // TODO: ensure we don't evaluate the requestor
+    {
+        if( getLogger().isTraceEnabled() )
+        {
+            getLogger().trace( "invoking lookup in " + getComponentPath() + " for " + clazz.getName() );
+        }
+        if( null != m_registry )
+        {
+            try
+            {
+                Object value = m_registry.lookup( clazz );
+                return type.cast( value );
+            }
+            catch( Exception e )
+            {
+                final String error = 
+                  "Service lookup in component ["
+                  + getComponentPath()
+                  + "] failed.";
+                throw new ComponentException( error, e );
+            }
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    Class getComponentClass()
+    {
+        return m_class;
+    }
+    
+    String getComponentName()
+    {
+        return m_name;
+    }
+    
+    String getComponentPath()
+    {
+        return m_path;
+    }
+    
+    ContextModel getContextModel()
+    {
+        return m_context;
+    }
+    
+    PartsDirective getPartsDirective()
+    {
+        return m_parts;
+    }
+    
+    State getStateGraph()
+    {
+        return m_graph;
+    }
+    
+    Logger getComponentLogger()
+    {
+        return m_logger;
+    }
+    
+    Logger getLogger()
+    {
+        return m_logger;
+    }
+    
+    CollectionPolicy getCollectionPolicy()
+    {
+        return m_collection;
+    }
+    
+    LifestylePolicy getLifestylePolicy()
+    {
+        return m_lifestyle;
+    }
+    
+    ActivationPolicy getActivationPolicy()
+    {
+        return m_activation;
+    }
+    
+    private Logger getComponentLogger( String path )
+    {
+        return new DefaultLogger( path );
+    }
+    
+    public <T>T getInstance( Class<T> clazz )
+    {
+        if( clazz.equals( Component.class ) )
+        {
+            return clazz.cast( this );
+        }
+        synchronized( m_handler )
+        {
+            Provider provider = getProvider();
+            if( clazz.equals( Provider.class ) )
+            {
+                return clazz.cast( provider );
+            }
+            Object instance = provider.getInstance( clazz );
+            return clazz.cast( instance );
+        }
+    }
+    
+    public <T>T getContentForClass( Class<T> c ) throws IOException
+    {
+        if( c.isAssignableFrom( m_class ) )
+        {
+            return getInstance( c );
+        }
+        else if( c == Provider.class )
+        {
+            synchronized( m_handler )
+            {
+                Provider provider = m_handler.getProvider();
+                return c.cast( provider );
+            }
+        }
+        else if( ( c == Component.class ) || ( c == Strategy.class ) )
+        {
+            return c.cast( this );
+        }
+        else if( c == Appliance.class ) 
+        {
+            Logger logger = getComponentLogger();
+            Appliance appliance = new StandardAppliance( logger, this );
+            return c.cast( appliance );
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    public void encode(  Buffer buffer, String key ) throws IOException
+    {
+        String name = getComponentName();
+        String classname = getComponentClass().getName();
+        ContextDirective context = getContextModel().getDirective();
+        PartsDirective parts = getPartsDirective();
+        
+        boolean flag = buffer.isNamespace( NAMESPACE );
+        if( flag )
+        {
+            buffer.nl( "<component" );
+        }
+        else
+        {
+            buffer.nl( "<component xmlns=\"" + NAMESPACE + "\"" );
+            buffer.nl( "    " );
+        }
+        if( null != key )
+        {
+            buffer.write( " key=\"" + key + "\"" );
+        }
+        if( null != name )
+        {
+            buffer.write( " name=\"" + name + "\"" );
+        }
+        if( m_priority != 0 )
+        {
+            buffer.write( " priority=\"" + m_priority + "\"" );
+        }
+        buffer.write( " type=\"" + classname + "\"" );
+        if( ( context.size() == 0 ) && ( parts.size() == 0 ) )
+        {
+            buffer.write( "/>" ); 
+        }
+        else
+        {
+            buffer.write( ">" ); 
+            Buffer b = buffer.namespace( NAMESPACE );
+            context.encode( b.indent(), null );
+            parts.encode( b.indent() );
+            buffer.nl( "</component>" );
+        }
+    }
+    
+    private PartsDirective getPartsDirective( PartsDirective directive )
+    {
+        if( null == directive )
+        {
+            return new PartsDirective();
+        }
+        else
+        {
+            return directive;
+        }
+    }
+    
+    private String getComponentPath( String partition, String name, Class c )
+    {
+        if( null == partition )
+        {
+            return "/" + name;
+        }
+        else
+        {
+            return "/" + partition.replace( ".", "/" ) + "/" + name;
+        }
+    }
+    
+    private String getComponentName( String name, Class<?> c )
+    {
+        if( null != name )
+        {
+            return name;
+        }
+        else
+        {
+            return getComponentName( c );
+        }
+    }
+    
+    //-----------------------------------------------------------------------
+    // Lifestyle handlers
+    //-----------------------------------------------------------------------
+    
+    private LifestyleHandler getLifestyleHandler( LifestylePolicy policy )
+    {
+        if( policy.equals( LifestylePolicy.SINGLETON ) )
+        {
+            return new SingletonLifestyleHandler( this );
+        }
+        else if( policy.equals( LifestylePolicy.THREAD ) )
+        {
+            return new ThreadLifestyleHandler( this );
+        }
+        else
+        {
+            return new TransientLifestyleHandler( this );
+        }
+    }
+    
+   /**
+    * Singleton holder class.  The singleton holder mains a single 
+    * <tt>LifestyleHandler</tt> of a component relative to the component model 
+    * identity within the scope of the controller.  References to the 
+    * singleton instance will be shared across mutliple threads.
+    */
+    private class SingletonLifestyleHandler extends LifestyleHandler
+    {
+        private Reference<Provider> m_reference;
+        
+        SingletonLifestyleHandler( ComponentStrategy strategy )
+        {
+            super( strategy );
+            Provider provider = new StandardProvider( strategy );
+            m_reference = createReference( null );
+        }
+        
+        Provider getProvider()
+        {
+            Provider provider = m_reference.get();
+            if( null == provider )
+            {
+                ComponentStrategy strategy = getComponentStrategy();
+                provider = new StandardProvider( strategy );
+                m_reference = createReference( provider );
+            }
+            return provider;
+        }
+        
+        void release( Provider provider )
+        {
+        }
+        
+        void terminate()
+        {
+            synchronized( this )
+            {
+                Provider provider = m_reference.get();
+                if( null != provider )
+                {
+                    if( provider instanceof Disposable )
+                    {
+                        Disposable disposable = (Disposable) provider;
+                        disposable.dispose();
+                    }
+                    m_reference = createReference( null ); 
+                }
+            }
+        }
+    }
+    
+   /**
+    * Transient holder class.  The transient holder provides support for 
+    * the transient lifestyle ensuing the creation of a new <tt>LifestyleHandler</tt>
+    * per request.
+    */
+    private class TransientLifestyleHandler extends LifestyleHandler
+    {
+        private final WeakHashMap<Provider,Void> m_providers = new WeakHashMap<Provider,Void>(); // transients
+        
+        TransientLifestyleHandler( ComponentStrategy strategy )
+        {
+            super( strategy );
+        }
+        
+        Provider getProvider()
+        {
+            ComponentStrategy strategy = getComponentStrategy();
+            Provider provider = new StandardProvider( strategy );
+            m_providers.put( provider, null );
+            return provider;
+        }
+        
+        void release( Provider provider )
+        {
+            if( null == provider )
+            {
+                return;
+            }
+            if( m_providers.containsKey( provider ) )
+            {
+                m_providers.remove( provider );
+                if( provider instanceof Disposable )
+                {
+                    Disposable disposable = (Disposable) provider;
+                    disposable.dispose();
+                }
+            }
+        }
+        
+        void terminate()
+        {
+            Provider[] providers = m_providers.keySet().toArray( new Provider[0] );
+            for( Provider provider : providers )
+            {
+                release( provider );
+            }
+        }
+    }
+
+   /**
+    * The ThreadHolder class provides support for the per-thread lifestyle
+    * policy within which new <tt>LifestyleHandler</tt> creation is based on a single
+    * <tt>LifestyleHandler</tt> per thread.
+    */
+    private class ThreadLifestyleHandler extends LifestyleHandler
+    {
+        private final ThreadLocalHolder m_threadLocalHolder = new ThreadLocalHolder();
+        
+        ThreadLifestyleHandler( ComponentStrategy strategy )
+        {
+            super( strategy );
+        }
+        
+        Provider getProvider()
+        {
+            return (Provider) m_threadLocalHolder.get();
+        }
+        
+        void release( Provider provider )
+        {
+            m_threadLocalHolder.release( provider );
+        }
+
+        void terminate()
+        {
+            m_threadLocalHolder.terminate();
+        }
+        
+       /**
+        * Internal thread local holder for the per-thread lifestyle holder.
+        */
+        private class ThreadLocalHolder extends ThreadLocal
+        {
+            private final WeakHashMap<Provider,Void> m_providers = 
+              new WeakHashMap<Provider,Void>(); // per thread instances
+            
+            synchronized protected Provider initialValue()
+            {
+                ComponentStrategy strategy = getComponentStrategy();
+                Provider provider = new StandardProvider( strategy );
+                m_providers.put( provider, null );
+                return provider;
+            }
+            
+            synchronized void release( Provider provider )
+            {
+                if( m_providers.containsKey( provider ) )
+                {
+                    m_providers.remove( provider );
+                    if( provider instanceof Disposable )
+                    {
+                        Disposable disposable = (Disposable) provider;
+                        disposable.dispose();
+                    }
+                }
+            }
+            
+            synchronized void terminate()
+            {
+                Provider[] providers = m_providers.keySet().toArray( new Provider[0] );
+                for( Provider provider : providers )
+                {
+                    release( provider );
+                }
+            }
+        }
+    }
+    
+    //-----------------------------------------------------------------------
+    // utilities
+    //-----------------------------------------------------------------------
+
+    private static String getComponentName( Class<?> c )
+    {
+        if( c.isAnnotationPresent( net.dpml.annotation.Component.class ) )
+        {
+            net.dpml.annotation.Component annotation = 
+              c.getAnnotation( net.dpml.annotation.Component.class );
+            String name = annotation.name();
+            if( !"".equals( name ) )
+            {
+                return name;
+            }
+        }
+        return c.getName();
+    }
+    
+    private static String getComponentNameFromClass( Class<?> c )
+    {
+        String classname = c.getName();
+        int n = classname.lastIndexOf( "." );
+        if( n > -1 )
+        {
+            return classname.substring( n+1 );
+        }
+        else
+        {
+            return classname;
+        }
+    }
+    
+    private static CollectionPolicy getCollectionPolicy( Class<?> c )
+    {
+        if( c.isAnnotationPresent( net.dpml.annotation.Component.class ) )
+        {
+            net.dpml.annotation.Component annotation = 
+              c.getAnnotation( net.dpml.annotation.Component.class );
+            return annotation.collection();
+        }
+        return CollectionPolicy.HARD;
+    }
+    
+    private static LifestylePolicy getLifestylePolicy( Class<?> c )
+    {
+        if( c.isAnnotationPresent( net.dpml.annotation.Component.class ) )
+        {
+            net.dpml.annotation.Component annotation = 
+              c.getAnnotation( net.dpml.annotation.Component.class );
+            return annotation.lifestyle();
+        }
+        return LifestylePolicy.THREAD;
+    }
+    
+    private static ActivationPolicy getActivationPolicy( Class<?> c )
+    {
+        if( c.isAnnotationPresent( Activation.class ) )
+        {
+            Activation annotation = 
+              c.getAnnotation( Activation.class );
+            return annotation.value();
+        }
+        return ActivationPolicy.SYSTEM;
+    }
+    
+    private static State getLifecycleGraph( Class<?> c ) throws IOException
+    {
+        String name = getComponentNameFromClass( c );
+        String spec = name + ".xgraph";
+        URL url = getLifecycleURL( c, spec );
+        if( null != url )
+        {
+            StateDecoder decoder = new StateDecoder();
+            return decoder.loadState( url );
+        }
+        if( c.isAnnotationPresent( net.dpml.annotation.Component.class ) )
+        {
+            net.dpml.annotation.Component annotation = 
+              c.getAnnotation( net.dpml.annotation.Component.class );
+            String path = annotation.lifecycle();
+            return getLifecycleGraph( c, path );
+        }
+        else
+        {
+            return NULL_STATE;
+        }
+    }
+    
+    private static State getLifecycleGraph( Class<?> c, String path ) throws IOException
+    {
+        if( ( null == path ) || "".equals( path ) )
+        {
+            return NULL_STATE;
+        }
+        else
+        {
+            URL url = getLifecycleURL( c, path );
+            StateDecoder decoder = new StateDecoder();
+            return decoder.loadState( url );
+        }
+    }
+    
+    private static URL getLifecycleURL( Class<?> c, String path ) throws IOException
+    {
+        int n = path.indexOf( ":" );
+        if( n > -1 )
+        {
+            try
+            {
+                return Artifact.toURL( new URI( path ) );
+            }
+            catch( Exception e )
+            {
+                final String error = 
+                  "Bad url: " + path;
+                IOException ioe = new IOException( error );
+                ioe.initCause( e );
+                throw ioe;
+            }
+        }
+        else
+        {
+            return c.getResource( path );
+        }
+    }
+
+    private static final String NAMESPACE = ComponentStrategyHandler.NAMESPACE;
+    
+    public String toString()
+    {
+        return getComponentPath();
+    }
+
+    private static class ComponentEventDistatcher implements Runnable
+    {
+        private Logger m_logger;
+        private ComponentListener m_listener;
+        private ComponentEvent m_event;
+        
+        ComponentEventDistatcher( Logger logger, ComponentListener listener, ComponentEvent event )
+        {
+            m_logger = logger;
+            m_listener = listener;
+            m_event = event;
+        }
+        
+        public void run()
+        {
+            try
+            {
+                m_listener.componentChanged( m_event );
+            }
+            catch( Throwable e )
+            {
+                final String error = 
+                  "Event distatch error.";
+                m_logger.error( error, e );
+            }
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ComponentStrategyHandler.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ComponentStrategyHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ComponentStrategyHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import dpml.lang.Classpath;
+import dpml.lang.DOM3DocumentBuilder;
+import dpml.lang.Value;
+import dpml.util.StandardClassLoader;
+import dpml.util.ElementHelper;
+import dpml.util.DefaultLogger;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URL;
+import java.util.Map;
+import java.lang.reflect.Constructor;
+
+import net.dpml.lang.DecodingException;
+import net.dpml.lang.Strategy;
+import net.dpml.lang.StrategyHandler;
+import net.dpml.lang.Buffer;
+
+import net.dpml.util.Resolver;
+import net.dpml.util.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ComponentStrategyHandler implements StrategyHandler
+{
+    public static final String NAMESPACE = "dpml:metro";
+    
+    private static final DOM3DocumentBuilder BUILDER = new DOM3DocumentBuilder();
+    
+    public Strategy newStrategy( Class<?> c ) throws IOException
+    {
+        return newStrategy( c, null );
+    }
+    
+    public Strategy newStrategy( Class<?> c, String name ) throws IOException
+    {
+        String spec = getComponentName( c, name );
+        Profile profile = new Profile( c, spec, null );
+        ContextModel context = getContextModel( null, c, spec, profile, null, null, null );
+        PartsDirective parts = profile.getPartsDirective();
+        return new ComponentStrategy( null, spec, 0, c, context, parts );
+    }
+    
+    public Component newComponent( Class<?> c, String name ) throws IOException
+    {
+        return (Component) newStrategy( c, name );
+    }
+    
+   /**
+    * Construct a strategy definition using a supplied element and value resolver.
+    * @param classloader the operational classloader
+    * @param element the DOM element definining the deployment strategy
+    * @param resolver symbolic property resolver
+    * @param partition the enclosing partition
+    * @return the strategy definition
+    * @exception IOException if an I/O error occurs
+    */
+    public Strategy build( 
+      ClassLoader classloader, Element element, Resolver resolver, String partition, String query ) throws IOException
+    {
+        Class c = loadComponentClass( classloader, element, resolver );
+        String name = getComponentName( c, element, resolver );
+        int priority = getPriority( element, resolver );
+        String path = getComponentPath( partition, name );
+        Profile profile = new Profile( c, path, resolver );
+        
+        Query q = new Query( query );
+        Element contextElement = ElementHelper.getChild( element, "context" );
+        ContextModel context = getContextModel( classloader, c, path, profile, contextElement, resolver, q );
+        
+        //ContextDirective context = 
+        //  new ContextDirective( 
+        //    profile.getContextDirective(), 
+        //    classloader, 
+        //    contextElement,
+        //    resolver,
+        //    query );
+        
+        try
+        {
+            Element partsElement = ElementHelper.getChild( element, "parts" );
+            PartsDirective parts = 
+              new PartsDirective( 
+                profile.getPartsDirective(), 
+                classloader, 
+                partsElement, 
+                resolver, 
+                path );
+
+            ComponentStrategy strategy = new ComponentStrategy( partition, name, priority, c, context, parts );
+            return strategy;
+        }
+        catch( IOException ioe )
+        {
+            throw ioe;
+        }
+        catch( Exception e )
+        {
+            final String error = 
+              "Unable to construct component strategy for the class [" 
+              + c.getName() 
+              + "] under the partition ["
+              + partition 
+              + "]";
+            IOException ioe = new IOException( error );
+            ioe.initCause( e );
+            throw ioe;
+        }
+    }
+    
+    private int getPriority( Element element, Resolver resolver )
+    {
+        String value = ElementHelper.getAttribute( element, "priority", null, resolver );
+        if( null == value )
+        {
+            return 0;
+        }
+        else
+        {
+            return Integer.parseInt( value );
+        }
+    }
+    
+    private Class loadComponentClass( ClassLoader classloader, Element element, Resolver resolver ) throws DecodingException
+    {
+        String classname = buildComponentClassname( element, resolver );
+        try
+        {
+            return classloader.loadClass( classname );
+        }
+        catch( ClassNotFoundException e )
+        {
+            final String error =
+              "Class not found [" + classname + "].";
+            Logger logger = new DefaultLogger( "dpml.lang" );
+            String stack = StandardClassLoader.toString( classloader, null );
+            logger.error( error + stack );
+            throw new DecodingException( error, e, element );
+        }
+    }
+    
+    private String buildComponentClassname( Element element, Resolver resolver )
+    {
+        String classname = ElementHelper.getAttribute( element, "class", null, resolver );
+        if( null != classname )
+        {
+            return classname;
+        }
+        else
+        {
+            return ElementHelper.getAttribute( element, "type", null, resolver );
+        }
+    }
+
+    private static String getComponentName( Class c, Element element, Resolver resolver )
+    {
+        String name = getComponentName( element, resolver );
+        return getComponentName( c, name );
+    }
+    
+    private static String getComponentName( Element element, Resolver resolver )
+    {
+        if( null == element )
+        {
+            return null;
+        }
+        else
+        {
+            String key = ElementHelper.getAttribute( element, "key", null, resolver );
+            if( null != key )
+            {
+                return key;
+            }
+            else
+            {
+                return ElementHelper.getAttribute( element, "name", null, resolver );
+            }
+        }
+    }
+
+    private static String getComponentName( Class<?> c )
+    {
+        if( c.isAnnotationPresent( net.dpml.annotation.Component.class ) )
+        {
+            net.dpml.annotation.Component annotation = 
+              c.getAnnotation( net.dpml.annotation.Component.class );
+            String name = annotation.name();
+            if( !"".equals( name ) )
+            {
+                return name;
+            }
+        }
+        return c.getName();
+    }
+    
+    private static String getComponentNameFromClass( Class<?> c )
+    {
+        String classname = c.getName();
+        int n = classname.lastIndexOf( "." );
+        if( n > -1 )
+        {
+            return classname.substring( n+1 );
+        }
+        else
+        {
+            return classname;
+        }
+    }
+    
+    private static String getComponentPath( String partition, String name )
+    {
+        if( null == partition )
+        {
+            return name;
+        }
+        else
+        {
+            return partition + "." + name;
+        }
+    }
+    
+    private static String getComponentName( Class c, String name )
+    {
+        if( null != name )
+        {
+            return name;
+        }
+        else
+        {
+            return  getComponentName( c );
+        }
+    }
+
+    static Constructor getSingleConstructor( Class c )
+    {
+        Constructor[] constructors = c.getConstructors();
+        if( constructors.length < 1 )
+        {
+            final String error =
+              "The component class ["
+              + c.getName()
+              + "] does not declare a public constructor.";
+            throw new ComponentError( error );
+        }
+        else if( constructors.length > 1 )
+        {
+            final String error =
+              "The component class ["
+              + c.getName()
+              + "] declares more than one public constructor.";
+            throw new ComponentError( error );
+        }
+        else
+        {
+            return constructors[0];
+        }
+    }
+
+    private static Class getContextClass( Constructor constructor, boolean policy )
+    {
+        final Class<?>[] types = constructor.getParameterTypes();
+        for( Class c : types )
+        {
+            if( ContextInvocationHandler.isaContext( c, policy ) )
+            {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    private static ContextModel getContextModel( 
+      ClassLoader classloader, Class clazz, String path, 
+      Profile profile, Element element, Resolver resolver, Query query  ) throws IOException
+    {
+        boolean policy = getContextHandlingPolicy( clazz );
+        Constructor constructor = getSingleConstructor( clazz );
+        Class subject = getContextClass( constructor, policy );
+        ContextDirective bundled = profile.getContextDirective();
+        ContextDirective declared = new ContextDirective( classloader, element, resolver );
+        return new ContextModel( clazz, path, subject, policy, bundled, declared, query );
+    }
+    
+    private static boolean getContextHandlingPolicy( Class c )
+    {
+        // TODO: update to get policy as a class annotation
+        return false; // return classic evaluation policy
+    }
+
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ContextDirective.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ContextDirective.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ContextDirective.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2005-2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+import java.util.Hashtable;
+
+import dpml.lang.Construct;
+import dpml.lang.ValueDecoder;
+
+import dpml.lang.Value;
+import net.dpml.lang.DecodingException;
+import net.dpml.lang.Buffer;
+
+import net.dpml.runtime.Directive.Resolvable;
+import net.dpml.runtime.Directive.Encodable;
+
+import dpml.util.ElementHelper;
+import net.dpml.util.Resolver;
+
+import org.w3c.dom.Element;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class ContextDirective extends Directive implements Encodable 
+{
+    private static final ValueDecoder VALUE_DECODER = new ValueDecoder();
+    
+    private final Element m_element;
+    
+    private final Map<String,Encodable> m_entries = new Hashtable<String,Encodable>();
+    
+   /**
+    * Creation of a new top-level context argument.
+    */
+    ContextDirective()
+    {
+        m_element = null;
+    }
+    
+   /**
+    * Creation of a new context argument resolved from a packaged context definition.
+    */
+    ContextDirective( ClassLoader classloader, Element element, Resolver resolver ) throws DecodingException
+    {
+        m_element = element;
+        
+        if( null != element )
+        {
+            Element[] elements = ElementHelper.getChildren( element );
+            for( Element child : elements )
+            {
+                String key = ElementHelper.getAttribute( child, "key" );
+                if( null == key )
+                {
+                    final String error = 
+                      "Context entry does not declare a key.";
+                    throw new DecodingException( error, null, child );
+                }
+                
+                if( "context".equals( child.getLocalName() ) )
+                {
+                    ContextDirective directive = new ContextDirective( classloader, child, resolver );
+                    m_entries.put( key, directive );
+                }
+                else if( "entry".equals( child.getLocalName() ) )
+                {
+                    String service = ElementHelper.getAttribute( child, "lookup" );
+                    if( null == service )
+                    {
+                        Value value = VALUE_DECODER.decodeValue( child, resolver );
+                        ValueWrapper wrapper = new ValueWrapper( child, value );
+                        m_entries.put( key, wrapper );
+                    }
+                    else
+                    {
+                        Lookup loookup = new Lookup( classloader, child, service );
+                        m_entries.put( key, loookup );
+                    }
+                }
+                else
+                {
+                    final String error = 
+                      "Context entry element not recognized.";
+                    throw new ComponentException( error, null, child );
+                }
+            }
+        }
+        
+        /*
+        // override context with query arguments if present
+        if( null != query )
+        {
+            Map<String,String> map = new Hashtable<String,String>();
+            String[] segments = query.split( "," );
+            for( String segment : segments )
+            {
+                String[] args = segment.split( "=" );
+                if( args.length != 2 )
+                {
+                    throw new IllegalArgumentException( "Invalid query [" + segment + "]" );
+                }
+                String key = args[0];
+                String param = args[1];
+                Value value = new Construct( param );
+                m_entries.put( key, new ValueWrapper( null, value ) );
+            }
+        }
+        */
+    }
+    
+    int size()
+    {
+        return m_entries.size();
+    }
+    
+    //String[] getKeys()
+    //{
+    //    return m_entries.keySet().toArray( new String[0] );
+    //}
+    
+    public Element getElement()
+    {
+        return m_element;
+    }
+    
+    public void encode( Buffer buffer, String key ) throws IOException
+    {
+        if( null != m_element )
+        {
+            buffer.nl( "<context" );
+            if( null != key )
+            {
+                buffer.write( " key=\"" + key + "\"" );
+            }
+            buffer.write( ">" );
+            Buffer b2 = buffer.indent();
+            for( String k : m_entries.keySet().toArray( new String[0] ) )
+            {
+                Encodable entry = m_entries.get( k );
+                entry.encode( b2, k );
+            }
+            buffer.nl( "</context>" );
+        }
+    }
+
+    Resolvable getEntry( String key )
+    {
+        Encodable entry = m_entries.get( key );
+        if( null != entry )
+        {
+            if( entry instanceof Resolvable )
+            {
+                return (Resolvable) entry;
+            }
+        }
+        return null;
+    }
+    
+    ContextDirective getContextDirective( String key )
+    {
+        Encodable entry = m_entries.get( key );
+        if( null != entry )
+        {
+            if( entry instanceof ContextDirective )
+            {
+                return (ContextDirective) entry;
+            }
+        }
+        return null;
+    }
+
+    private static abstract class AbstractResolvable implements Resolvable, Encodable
+    {
+        private final Element m_element;
+        
+        AbstractResolvable( Element element )
+        {
+            m_element = element;
+        }
+        
+        public Element getElement()
+        {
+            return m_element;
+        }
+    }
+    
+    static class ValueWrapper extends AbstractResolvable
+    {
+        private final Value m_value;
+        
+        ValueWrapper( Value value )
+        {
+            this( null, value );
+        }
+        
+        ValueWrapper( Element element, Value value )
+        {
+            super( element );
+            m_value = value;
+        }
+        
+        public <T>T resolve( ComponentStrategy parent, Class<T> type ) throws Exception
+        {
+            Object value = m_value.resolve( type, parent.getContextMap() );
+            return type.cast( value );
+        }
+        
+        public void encode( Buffer buffer, String key ) throws IOException
+        {
+            m_value.encode( buffer, "entry", key );
+        }
+    }
+    
+    static class Lookup extends AbstractResolvable
+    {
+        private final Class m_class;
+        
+        Lookup( ClassLoader classloader, Element element, String classname ) throws ComponentException
+        {
+            super( element );
+            try
+            {
+                m_class = classloader.loadClass( classname );
+            }
+            catch( ClassNotFoundException cnfe )
+            {
+                final String error = 
+                  "Class not found: ["
+                  + classname 
+                  + "].";
+                throw new ComponentException( error, cnfe, element );
+            }
+        }
+        
+        public <T>T resolve( ComponentStrategy strategy, Class<T> type ) throws Exception
+        {
+            T value = strategy.getService( m_class, type );
+            if( null != value )
+            {
+                return value;
+            }
+            else
+            {
+                Element element = getElement();
+                final String error = 
+                  "Service not found [" 
+                  + m_class.getName() 
+                  + "].";
+                throw new ComponentException( error, null, element );
+            }
+        }
+        
+        public void encode( Buffer buffer, String key ) throws IOException
+        {
+            buffer.nl( "<entry key=\"" + key + "\" lookup=\"" + m_class.getName() + "\"/>" );
+        }
+    }
+}
\ No newline at end of file

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ContextInvocationHandler.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ContextInvocationHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ContextInvocationHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.util.Map;
+import java.beans.Introspector;
+import java.beans.Expression;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import net.dpml.annotation.Context;
+import net.dpml.runtime.Directive.Resolvable;
+import dpml.lang.Value;
+
+import org.w3c.dom.Element;
+
+/**
+ * Invocation handler utility for a Context class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+final class ContextInvocationHandler implements InvocationHandler
+{
+    //-------------------------------------------------------------------
+    // static
+    //-------------------------------------------------------------------
+    
+    private static final String GET = "get";
+
+   /**
+    * Test if the supplied class is recognized as a context class. If
+    * the supplied policy is true then evaluation is based on the presence
+    * of the <tt>net.dpml.lang.Context</tt> annotation and resulting 
+    * value of annotation evaluation.  If no context annnotation is present
+    * and strict processing is disabled then evaluation will return true if 
+    * the classname ends with the string <tt>$Context</tt>.
+    *
+    * @param c the candidate class
+    * @param policy the strict evaluation policy
+    * @return true if this class is recognized as a context class
+    */
+    public static boolean isaContext( final Class<?> c, final boolean policy )
+    {
+        boolean flag = c.isAnnotationPresent( Context.class );
+        if( flag )
+        {
+            return c.getAnnotation( Context.class ).value();
+        }
+        else if( policy )
+        {
+            return false;
+        }
+        else
+        {
+            return c.getName().endsWith( "$Context" );
+        }
+    }
+    
+   /**
+    * Validate that the supplied map properly fulfills the required  
+    * context entry.  Specifically, for all non-optional methods declared
+    * by the context class, the validation process checks the the supplied
+    * map has a corresponding key and associated non-null value.
+    *
+    * @param clazz the context class
+    * @param map a map of context entry values
+    * @exception IllegalArgumentException if validation fails
+    */
+    public static void validate( Class clazz, Map<String,Object> map ) 
+      throws IllegalArgumentException
+    {
+        for( Method method : clazz.getMethods() )
+        {
+            String key = getKeyForMethod( method );
+            boolean optional = isOptionalEntry( method );
+            if( !optional )
+            {
+                if( !map.containsKey( key ) )
+                {
+                    final String error = 
+                      "Missing required key ["
+                      + key
+                      + "]";
+                    throw new IllegalArgumentException( error );
+                }
+                else if( null == map.get( key ) )
+                {
+                    final String error = 
+                      "Missing value for the required key ["
+                      + key
+                      + "]";
+                    throw new IllegalArgumentException( error );
+                }
+            }
+        }
+    }
+    
+   /**
+    * Construct a new context instance implementing the supplied class
+    * backed by entries in the supplied map.
+    *
+    * @param clazz the context class
+    * @param map a map of context entry keys and values
+    * @return the constructed context instance
+    */
+    public static <T>T getProxiedInstance( 
+      final Class<T> clazz, final ComponentStrategy strategy, final ContextModel model )
+    {
+        ClassLoader classloader = clazz.getClassLoader();
+        ContextInvocationHandler handler = 
+          new ContextInvocationHandler( strategy, model );
+        final Object instance = 
+          Proxy.newProxyInstance( classloader, new Class[]{clazz}, handler );
+        return clazz.cast( instance );
+    }
+    
+    //-------------------------------------------------------------------
+    // state
+    //-------------------------------------------------------------------
+
+   /**
+    * Context datatype.
+    */
+    private final ContextModel m_model;
+    
+   /**
+    * Component strategy handler.
+    */
+    private final ComponentStrategy m_strategy;
+
+    //-------------------------------------------------------------------
+    // constructor
+    //-------------------------------------------------------------------
+
+   /**
+    * Create a context invocation handler.
+    *
+    * @param map a map containing context key/value pairs.
+    */
+    private ContextInvocationHandler( final ComponentStrategy strategy, final ContextModel model )
+    {
+        m_model = model;
+        m_strategy = strategy;
+    }
+
+    //-------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------
+
+   /**
+    * Invoke the specified method on underlying object.
+    * This is called by the proxy object.
+    *
+    * @param proxy the proxy object
+    * @param method the method invoked on proxy object
+    * @param args the arguments supplied to method
+    * @return the return value of method
+    * @throws Throwable if an error occurs
+    */
+    @SuppressWarnings( "unchecked" )
+    public Object invoke( final Object proxy, final Method method, final Object[] args ) throws Throwable
+    {
+        Class source = method.getDeclaringClass();
+        if( Object.class == source )
+        {
+            return method.invoke( this, args );
+        }
+        else
+        {
+            String name = method.getName();
+            if( name.startsWith( "get" ) )
+            {
+                Class<?> clazz = method.getReturnType();
+                String key = Introspector.decapitalize( name.substring( 3 ) );
+                Resolvable entry = m_model.getResolvable( key );
+                if( null != entry )
+                {
+                    Class nc = normalize( clazz );
+                    Object v = resolve( entry, key, nc );
+                    if( nc.isAssignableFrom( v.getClass() ) )
+                    {
+                        return v;
+                    }
+                    else
+                    {
+                        final String error = 
+                          "Cannot cast [" 
+                          + v.getClass().getName()
+                          + "] to the return type ["
+                          + clazz.getName()
+                          + "] on the context entry ["
+                          + key
+                          + "]";
+                        Element element = entry.getElement();
+                        throw new ComponentException( error, null, element );
+                    }
+                }
+                if( ( null != args ) && ( args.length > 0 ) )
+                {
+                    return args[0];
+                }
+                else
+                {
+                    // should not happen
+                    
+                    final String error = 
+                      "Unresolvable context entry [" 
+                      + key
+                      + "] in the component model ["
+                      + m_strategy.getComponentPath()
+                      + "].";
+                    throw new ComponentError( error );
+                }
+            }
+            else
+            {
+                throw new UnsupportedOperationException( name );
+            }
+        }
+    }
+    
+    private Object resolve( Resolvable entry, String key, Class<?> c ) throws ComponentException
+    {
+        try
+        {
+            return entry.resolve( m_strategy, c );
+        }
+        catch( ClassCastException e )
+        {
+            final String error = 
+              "Failed to resolve the value for the context entry ["
+              + key
+              + "] in the component ["
+              + m_strategy.getComponentPath()
+              + "] for the return type ["
+              + c.getName()
+              + "]";
+            throw new ComponentException( error, e, entry.getElement() );
+        }
+        catch( Exception e )
+        {
+            final String error = 
+              "Failed to resolve the value for the context entry ["
+              + key
+              + "] in the component ["
+              + m_strategy.getComponentPath()
+              + "]";
+            throw new ComponentException( error, e, entry.getElement() );
+        }
+    }
+    
+    private static boolean isAssignableFrom( Class<?> clazz, Class<?> c )
+    {
+        Class<?> normalized = normalize( clazz );
+        return normalized.isAssignableFrom( c );
+    }
+    
+    private static Class<?> normalize( Class<?> clazz )
+    {
+        if( clazz.isPrimitive() )
+        {
+            if( Integer.TYPE == clazz )
+            {
+                return Integer.class;
+            }
+            else if( Boolean.TYPE == clazz )
+            {
+                return Boolean.class;
+            }
+            else if( Byte.TYPE == clazz )
+            {
+                return Byte.class;
+            }
+            else if( Short.TYPE == clazz )
+            {
+                return Short.class;
+            }
+            else if( Long.TYPE == clazz )
+            {
+                return Long.class;
+            }
+            else if( Float.TYPE == clazz )
+            {
+                return Float.class;
+            }
+            else if( Character.TYPE == clazz )
+            {
+                return Character.class;
+            }
+            else if( Double.TYPE == clazz )
+            {
+                return Double.class;
+            }
+            else
+            {
+                final String error =
+                  "Primitive type ["
+                  + clazz.getName()
+                  + "] not supported.";
+                throw new RuntimeException( error );
+            }
+        }
+        else
+        {
+            return clazz;
+        }
+    }
+    
+    private static boolean isOptionalEntry( Method method )
+    {
+        return method.getParameterTypes().length == 1;
+    }
+    
+    static String getKeyForMethod( Method method )
+    {
+        String name = method.getName();
+        if( name.startsWith( GET ) )
+        {
+            String remainder = name.substring( GET.length() );
+            return Introspector.decapitalize( remainder );
+        }
+        else
+        {
+            final String error = 
+              "Method name is not a recognized pattern: " 
+              + name;
+            throw new IllegalArgumentException( error );
+        }
+    }
+    
+    private static final String STRICT_PROCESSING_KEY = "dpml.lang.context.policy";
+    private static final String STRICT_PROCESSING_KEYWORD = "strict";
+    private static final boolean STRICT_PROCESSING = getStrictProcessingPolicy();
+    
+    private static boolean getStrictProcessingPolicy()
+    {
+        return STRICT_PROCESSING_KEYWORD.equalsIgnoreCase( 
+          System.getProperty( 
+            STRICT_PROCESSING_KEY, 
+            STRICT_PROCESSING_KEYWORD ) );
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ContextModel.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ContextModel.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ContextModel.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Hashtable;
+import java.lang.reflect.Method;
+
+import net.dpml.lang.Buffer;
+
+import net.dpml.runtime.Directive.Resolvable;
+
+import org.w3c.dom.Element;
+
+/**
+ * Context model interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class ContextModel implements Resolvable
+{
+    private ContextDirective m_directive;
+    
+    private final Map<String,Resolvable> m_map = new Hashtable<String,Resolvable>();
+    
+    ContextModel( 
+      Class clazz, String path, Class subject, boolean policy,
+      ContextDirective bundled, ContextDirective directive, Query query ) throws IOException
+    {
+        this( clazz, path, subject, policy, null, bundled, directive, query );
+    }
+    
+    private ContextModel( 
+      Class clazz, String path, Class subject, boolean policy, String keyPath,
+      ContextDirective bundled, ContextDirective directive, Query query ) throws IOException
+    {
+        m_directive = directive;
+        
+        if( null != subject )
+        {
+            for( Method method : subject.getMethods() )
+            {
+                Class c = method.getReturnType();
+                String key = ContextInvocationHandler.getKeyForMethod( method );
+                boolean optional = isOptionalEntry( method );
+                boolean composite = ContextInvocationHandler.isaContext( c, policy );
+                
+                Resolvable value = null;
+                if( composite )
+                {
+                    ContextDirective parent = getContextDirective( bundled, key );
+                    ContextDirective nested = getContextDirective( directive, key );
+                    value = new ContextModel( clazz, path, c, policy, key, parent, nested, query );
+                }
+                else
+                {
+                    if( null != query )
+                    {
+                        String scopedKey = getScopedKey( keyPath, key );
+                        value = query.getEntry( scopedKey );
+                    }
+                    if( ( null == value ) && null != directive )
+                    {
+                        value = directive.getEntry( key );
+                    }
+                    if( ( null == value ) && null != bundled )
+                    {
+                        value = bundled.getEntry( key );
+                    }
+                }
+                if( null != value )
+                {
+                    m_map.put( key, value );
+                }
+                else if( !optional )
+                {
+                    final String error = 
+                      "No solution declared for the context entry ["
+                      + key
+                      + "] within the context definition ["
+                      + subject.getName()
+                      + "] as a constructor argument to the component class ["
+                      + clazz.getName()
+                      + "] within the component model ["
+                      + path
+                      + "].";
+                    throw new ComponentException( error );
+                }
+            }
+        }
+    }
+    
+    private String getScopedKey( String base, String key )
+    {
+        if( null == base )
+        {
+            return key;
+        }
+        else
+        {
+            return base + "." + key;
+        }
+    }
+    
+    public Element getElement()
+    {
+        if( null != m_directive )
+        {
+            return m_directive.getElement();
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    public void encode( Buffer buffer, String key ) throws IOException
+    {
+        if( null != m_directive )
+        {
+            m_directive.encode( buffer, key );
+        }
+    }
+
+    private boolean isOptionalEntry( Method method )
+    {
+        return ( method.getParameterTypes().length > 0 );
+    }
+    
+    public <T>T resolve( ComponentStrategy strategy, Class<T> type ) throws Exception
+    {
+        return ContextInvocationHandler.getProxiedInstance( type, strategy, this );
+    }
+    
+    Resolvable getResolvable( String key )
+    {
+        return m_map.get( key );
+    }
+    
+    ContextDirective getDirective()
+    {
+        return m_directive;
+    }
+
+    private ContextDirective getContextDirective( ContextDirective directive, String key )
+    {
+        if( null == directive )
+        {
+            return null;
+        }
+        else
+        {
+            return directive.getContextDirective( key );
+        }
+    }
+    
+    /*
+    private static class Entry
+    {
+        private final String m_key;
+        private final boolean m_optional;
+        private final boolean m_composite;
+        
+        Entry( String key, boolean optional, boolean composite )
+        {
+            m_key = key;
+            m_optional = optional;
+            m_composite = composite;
+        }
+    }
+    */
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/DefaultStateMachine.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/DefaultStateMachine.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/DefaultStateMachine.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,1037 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.beans.Expression;
+import java.beans.Statement;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.WeakHashMap;
+import java.util.EventObject;
+import java.util.EventListener;
+
+import net.dpml.state.State;
+import net.dpml.state.Transition;
+import net.dpml.state.Operation;
+import net.dpml.state.Interface;
+import net.dpml.state.Trigger;
+import net.dpml.state.TriggerPolicy;
+import net.dpml.state.Action;
+import net.dpml.state.StateMachine;
+import net.dpml.state.UnknownOperationException;
+import net.dpml.state.UnknownTransitionException;
+import net.dpml.state.IntegrityRuntimeException;
+import net.dpml.state.StateListener;
+import net.dpml.state.StateEvent;
+import net.dpml.state.ExecAction;
+import net.dpml.state.ApplyAction;
+
+import net.dpml.util.Logger;
+
+/**
+ * Default state-machine implementation.
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class DefaultStateMachine implements StateMachine, EventQueue.EventHandler
+{
+   /**
+    * Constant name used to reference a state change in a property event.
+    */
+    public static final String PROPERTY_NAME = "state";
+    
+   /**
+    * Validate the state integrity.
+    * @param state the state to validate
+    */
+    public static void validate( State state )
+    {
+        validateState( state );
+    }
+
+    //-------------------------------------------------------------------------------
+    // state
+    //-------------------------------------------------------------------------------
+    
+    private State m_state;
+    private boolean m_active = false;
+    private boolean m_disposed = false;
+    
+    private final Object m_lock = new Object();
+
+    private final EventQueue m_queue;
+    
+    private final WeakHashMap<StateListener,Void> m_listeners = new WeakHashMap<StateListener,Void>();
+
+    private final Logger m_logger;
+    
+    //-------------------------------------------------------------------------------
+    // constructor
+    //-------------------------------------------------------------------------------
+
+   /**
+    * Creation of a new state machine using a state graph.
+    * @param queue the event queue
+    * @param logger the logging channel
+    * @param state the state graph
+    */
+    public DefaultStateMachine( EventQueue queue, Logger logger, State state )
+    {
+        m_queue = queue;
+        m_logger = logger;
+        m_state = state;
+    }
+
+    //-------------------------------------------------------------------------------
+    // StateMachine
+    //-------------------------------------------------------------------------------
+
+   /**
+    * Add a state change listener to the state machine.
+    * @param listener the state listener
+    */
+    public void addStateListener( final StateListener listener )
+    {
+        if( null == listener )
+        {
+            throw new NullPointerException( "listener" );
+        }
+        checkDisposed();
+        synchronized( m_lock ) 
+        {
+            m_listeners.put( listener, null );
+        }
+    }
+    
+   /**
+    * Remove a state listener from the state machine.
+    * @param listener the state listener
+    */
+    public void removeStateListener( final StateListener listener )
+    {
+        if( null == listener )
+        {
+            throw new NullPointerException( "listener" );
+        }
+        checkDisposed();
+        synchronized( m_lock )
+        {
+            m_listeners.remove( listener );
+        }
+    }
+    
+   /**
+    * Return the assigned state event listeners.
+    * @return the event listeners
+    */
+    public EventListener[] getEventListeners()
+    {
+        return getStateListeners();
+    }
+    
+    private StateListener[] getStateListeners()
+    {
+        synchronized( m_lock )
+        {
+            return (StateListener[]) m_listeners.keySet().toArray( new StateListener[0] );
+        }
+    }
+    
+   /**
+    * Process the supplied event.
+    * @param event the event to process
+    */
+    public void processEvent( EventObject event )
+    {
+        StateListener[] listeners = getStateListeners();
+        for( int i=0; i < listeners.length; i++ )
+        {
+            StateListener listener = listeners[i];
+            if( event instanceof StateEvent )
+            {
+                try
+                {
+                    StateEvent e = (StateEvent) event;
+                    listener.stateChanged( e );
+                }
+                catch( Throwable e )
+                {
+                    final String error =
+                      "StateListener notification error.";
+                    getLogger().error( error, e );
+                }
+            }
+        }
+    }
+
+   /**
+    * Return the current state.
+    * @return the current state
+    */
+    public State getState()
+    {
+        checkDisposed();
+        synchronized( m_state )
+        {
+            return m_state;
+        }
+    }
+    
+   /**
+    * Locate and return the most immediate initialization action defined relative to 
+    * the current state.  If an action is located within the current state it will be 
+    * return otherwise the search will continue up the state graph until either an 
+    * action is located or no further parent state is available in which case a null 
+    * value is returned.
+    * 
+    * @return the initialization action or null if no action declared
+    */
+    public Action getInitializationAction()
+    {
+        checkDisposed();
+        try
+        {
+            return getAction( m_state, TriggerPolicy.INITIALIZATION );
+        }
+        catch( Throwable e )
+        {
+            final String error = 
+              "Unexpected error during resolution of initialization actions.";
+            throw new IntegrityRuntimeException( error, e );
+        }
+    }
+    
+   /**
+    * Locate and return the most immediate termination action defined relative to 
+    * the current state.  If an action is located within the current state it will be 
+    * return otherwise the search will continue up the state graph until either an 
+    * action is located or no further parent state is available in which case a null 
+    * value is returned.
+    * 
+    * @return the termination action or null if no action declared
+    */
+    public Action getTerminationAction()
+    {
+        checkDisposed();
+        try
+        {
+            return getAction( m_state, TriggerPolicy.TERMINATION );
+        }
+        catch( Throwable e )
+        {
+            final String error = 
+              "Unexpected error during resolution of termination actions.";
+            throw new IntegrityRuntimeException( error, e );
+        }
+    }
+    
+   /**
+    * Invoke initialization of the supplied object using the initialization action
+    * declared under the current state path.
+    * 
+    * @param object the object to initialize
+    * @return the state established as a sidee effect of the initialization
+    * @exception InvocationTargetException if an invocation error occurs as a 
+    *   result of initialization
+    */
+    public State initialize( Object object ) throws InvocationTargetException
+    {
+        checkDisposed();
+        ArrayList<Action> visited = new ArrayList<Action>();
+        try
+        {
+            State result = initialize( visited, object );
+            m_active = true;
+            return result;
+        }
+        catch( UnknownTransitionException e )
+        {
+            final String error = 
+              "Internal state machine error raised due to an unresolved transition.";
+            throw new IntegrityRuntimeException( error, e );
+        }
+        catch( UnknownOperationException e )
+        {
+            final String error = 
+              "Internal state machine error raised due to an unresolved operation.";
+            throw new IntegrityRuntimeException( error, e );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e;
+        }
+        catch( Throwable e )
+        {
+            final String error = 
+              "Unexpected error during state-machine initialization.";
+            throw new IntegrityRuntimeException( error, e );
+        }
+    }
+    
+   /**
+    * Execute a named operation on the supplied object.
+    * @param name an operation name
+    * @param object the target object
+    * @param args operation arguments
+    * @return the result of operation invocation
+    * @exception UnknownOperationException if the operation is unknown
+    * @exception InvocationTargetException if an invocation error occurs as a 
+    *   result of operation execution
+    */
+    public Object execute( String name, Object object, Object[] args ) 
+      throws UnknownOperationException, InvocationTargetException
+    {
+        checkDisposed();
+        Operation operation = getOperation( getState(), name );
+        return execute( operation, object, args );
+    }
+    
+   /**
+    * Invoke a management method on the supplied object.
+    * @param object the target object
+    * @param method the method name
+    * @param args method parameter arguments
+    * @return the return value
+    * @exception IllegalStateException if the method is recognized but not available
+    * @exception UnknownOperationException if the operation is unknown
+    * @exception InvocationTargetException if an invocation error occurs as a 
+    *   result of operation execution
+    */
+    public Object invoke( Object object, String method, Object[] args ) 
+      throws UnknownOperationException, InvocationTargetException, IllegalStateException
+    {
+        checkDisposed();
+        
+        // TODO: validate exposure of declaring interface
+        
+        try
+        {
+            Expression expression = new Expression( object, method, args );
+            return expression.getValue();
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e;
+        }
+        catch( Exception e )
+        {
+            throw new InvocationTargetException( e );
+        }
+    }
+    
+   /**
+    * Apply a named transition to the target object.
+    * @param name the transition name
+    * @param object the object against which any transition handler action are to be applied
+    * @return the state established by the application of the transition
+    * @exception UnknownTransitionException if the transition is unknown
+    * @exception InvocationTargetException if an invocation error occurs as a 
+    *   result of transition invocation
+    */
+    public State apply( String name, Object object ) 
+      throws UnknownTransitionException, InvocationTargetException
+    {
+        checkDisposed();
+        synchronized( m_state )
+        {
+            Transition transition = getTransition( m_state, name );
+            return apply( transition, object );
+        }
+    }
+    
+   /**
+    * Return all of the available transitions relative to the current state.
+    * @return the available transitions
+    */
+    public Transition[] getTransitions()
+    {
+        checkDisposed();
+        Hashtable<String,Transition> table = new Hashtable<String,Transition>();
+        State[] states = m_state.getStatePath();
+        for( int i=( states.length-1 ); i>-1; i-- )
+        {
+            State state = states[i];
+            Transition[] transitions = state.getTransitions();
+            for( int j=0; j<transitions.length; j++ )
+            {
+                Transition transition = transitions[j];
+                String name = transition.getName();
+                if( null == table.get( name ) )
+                {
+                    table.put( name, transition );
+                }
+            }
+        }
+        return (Transition[]) table.values().toArray( new Transition[0] );
+    }
+    
+   /**
+    * Return all of the available operations relative to the current state.
+    * @return the available operations
+    */
+    public Operation[] getOperations() 
+    {
+        checkDisposed();
+        Hashtable<String,Operation> table = new Hashtable<String,Operation>();
+        State[] states = m_state.getStatePath();
+        for( int i=( states.length-1 ); i>-1; i-- )
+        {
+            State state = states[i];
+            Operation[] operations = state.getOperations();
+            for( int j=0; j<operations.length; j++ )
+            {
+                Operation operation = operations[j];
+                String name = operation.getName();
+                if( null == table.get( name ) )
+                {
+                    table.put( name, operation );
+                }
+            }
+        }
+        return table.values().toArray( new Operation[0] );
+    }
+    
+   /**
+    * Return all of the available interfaces relative to the current state.
+    * @return the available interface declarations
+    */
+    public Interface[] getInterfaces()
+    {
+        checkDisposed();
+        Hashtable<String,Interface> table = new Hashtable<String,Interface>();
+        State[] states = m_state.getStatePath();
+        for( int i=( states.length-1 ); i>-1; i-- )
+        {
+            State state = states[i];
+            Interface[] interfaces = state.getInterfaces();
+            for( int j=0; j<interfaces.length; j++ )
+            {
+                Interface data = interfaces[j];
+                String name = data.getName();
+                if( null == table.get( name ) )
+                {
+                    table.put( name, data );
+                }
+            }
+        }
+        return table.values().toArray( new Interface[0] );
+    }
+    
+   /**
+    * Invoke termination of the supplied object using the termination action
+    * declared under the current state path.
+    * 
+    * @param object the object to terminate
+    * @return the state established as a side-effect of the termination
+    */
+    public State terminate( Object object )
+    {
+        checkDisposed();
+        ArrayList visited = new ArrayList();
+        try
+        {
+            State result = terminate( visited, object );
+            m_active = false;
+            return result;
+        }
+        catch( Throwable e )
+        {
+            e.printStackTrace();
+            return getState();
+        }
+    }
+    
+   /**
+    * Returns the active status of the state machine.
+    * @return TRUE if the state machine has invoked initialization and 
+    * termination has not been performed otherwise FALSE
+    */
+    public boolean isActive()
+    {
+        return m_active;
+    }
+    
+   /**
+    * Dispose of the state machine.
+    */
+    public void dispose()
+    {
+        synchronized( m_lock )
+        {
+            StateListener[] listeners = getStateListeners();
+            for( int i=0; i<listeners.length; i++ )
+            {
+                StateListener listener = listeners[i];
+                removeStateListener( listener );
+            }
+        }
+        m_disposed = true;
+        m_state = null;
+    }
+    
+    //-------------------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------------------
+    
+    //private String getTag( final Object object )
+    //{
+    //    return DefaultProvider.createTag( object );
+    //}
+    
+    private State initialize( List<Action> list, Object object ) throws Exception
+    {
+        Action action = getInitializationAction();
+        if( null == action )
+        {
+            return m_state;
+        }
+        else if( list.contains( action ) )
+        {
+            return m_state;
+        }
+        else
+        {
+            list.add( action );
+            if( action instanceof Operation )
+            {
+                Operation operation = (Operation) action;
+                execute( operation, object, new Object[0] );
+                return m_state;
+            }
+            else if( action instanceof Transition )
+            {
+                Transition transition = (Transition) action;
+                State current = getState();
+                State result = apply( transition, object );
+                if( !current.equals( result ) )
+                {
+                    return initialize( list, object );
+                }
+                else
+                {
+                    return getState();
+                }
+            }
+            else
+            {
+                final String error = "Unrecognized action: " + action;
+                throw new IllegalStateException( error );
+            }
+        }
+    }
+    
+    private Object execute( Operation operation, Object object, Object[] args ) throws InvocationTargetException
+    {
+        if( null == object )
+        {
+            return null;
+        }
+        
+        String method = getMethodName( operation );
+        
+        try
+        {
+            Expression expression = new Expression( object, method, args );
+            return expression.getValue();
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e;
+        }
+        catch( Exception e )
+        {
+            throw new InvocationTargetException( e );
+        }
+    }
+    
+    private State terminate( List list, Object object ) throws Exception
+    {
+        Action action = getTerminationAction();
+        if( null == action )
+        {
+            return m_state;
+        }
+        else if( list.contains( action ) )
+        {
+            return m_state;
+        }
+        else
+        {
+            if( action instanceof Operation )
+            {
+                Operation operation = (Operation) action;
+                execute( operation, object, new Object[0] );
+                return m_state;
+            }
+            else if( action instanceof Transition )
+            {
+                Transition transition = (Transition) action;
+                State current = getState();
+                State result = apply( transition, object );
+                if( !current.equals( result ) )
+                {
+                    return terminate( list, object );
+                }
+                else
+                {
+                    return getState();
+                }
+            }
+            else
+            {
+                final String error = "Unrecognized action: " + action;
+                throw new IllegalStateException( error );
+            }
+        }
+    }
+    
+    private State apply( Transition transition, Object object ) throws InvocationTargetException
+    {
+        synchronized( m_state )
+        {
+            State context = transition.getState();
+            String target = transition.getTargetName();
+            State state = getState( context, target );
+            Operation operation = transition.getOperation();
+            if( getLogger().isTraceEnabled() )
+            {
+                String name = transition.getName();
+                getLogger().trace( 
+                  "applying transition [" 
+                  + name 
+                  + "]." );
+            }
+            if( null != operation )
+            {
+                execute( operation, object, new Object[0] ); // TODO: add resolved values as args
+            }
+            setState( object, state );
+            return state;
+        }
+    }
+    
+    private void execute( URI handler, Object object ) throws InvocationTargetException
+    {
+        if( null == object )
+        {
+            return;
+        }
+        String scheme = handler.getScheme();
+        if( "method".equals( scheme ) )
+        {
+            String methodName = handler.getSchemeSpecificPart();
+            if( getLogger().isTraceEnabled() )
+            {
+                getLogger().trace( 
+                  "executing operation [" 
+                  + methodName 
+                  + "]" );
+            }
+            Statement statement = new Statement( object, methodName, new Object[0] );
+            try
+            {
+                statement.execute();
+            }
+            catch( InvocationTargetException e )
+            {
+                throw e;
+            }
+            catch( Exception e )
+            {
+                throw new InvocationTargetException( e );
+            }
+        }
+        else
+        {
+            final String error = 
+              "Operation scheme not recognized."
+              + "\nScheme: " + scheme
+              + "\nURI: " + handler;
+            throw new IllegalArgumentException( error );
+        }
+    }
+    
+    private void setState( final Object object, final State state )
+    {
+        synchronized( m_state )
+        {
+            if( m_state != state )
+            {
+                final State oldState = m_state;
+                m_state = state;
+                
+                if( getLogger().isTraceEnabled() )
+                {
+                    getLogger().trace( 
+                      "transitioning from [" 
+                      + oldState 
+                      + "] to [" 
+                      + state
+                      + "]" );
+                }
+                
+                final StateEvent event = new StateEvent( this, oldState, state );
+                m_queue.enqueueEvent( event );
+            }
+        }
+    }
+    
+    private Action getAction( State state, TriggerPolicy category )
+      throws UnknownTransitionException, UnknownOperationException
+    {
+        Trigger[] triggers = state.getTriggers();
+        for( int i=0; i<triggers.length; i++ )
+        {
+            Trigger trigger = triggers[i];
+            if( trigger.getPolicy().equals( category ) )
+            {
+                Action action = trigger.getAction();
+                if( action instanceof ApplyAction )
+                {
+                    ApplyAction apply = (ApplyAction) action;
+                    String id = apply.getID();
+                    return getTransition( state, id );
+                }
+                else if( action instanceof ExecAction )
+                {
+                    ExecAction exec = (ExecAction) action;
+                    String id = exec.getID();
+                    return getOperation( state, id );
+                }
+                else
+                {
+                    return action;
+                }
+            }
+        }
+        State parent = state.getParent();
+        if( null != parent )
+        {
+            return getAction( parent, category );
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    private Transition getTransition( State state, String name ) throws UnknownTransitionException
+    {
+        Transition[] transitions = state.getTransitions();
+        for( int i=0; i<transitions.length; i++ )
+        {
+            Transition transition = transitions[i];
+            if( name.equals( transition.getName() ) )
+            {
+                return transition;
+            }
+        }
+        State parent = state.getParent();
+        if( null == parent )
+        {
+            final String error = 
+              "Unable to resolve a transition named [" 
+              + name
+              + "] relative to the state [" 
+              + state.getName()
+              + "].";
+            throw new UnknownTransitionException( error );
+        }
+        else
+        {
+            try
+            {
+                return getTransition( parent, name );
+            }
+            catch( UnknownTransitionException e )
+            {
+                final String error = 
+                  "Unable to resolve a transition named [" 
+                  + name
+                  + "] relative to the current state [" 
+                  + state
+                  + "].";
+                throw new UnknownTransitionException( error );
+            }
+        }
+    }
+
+    private Operation getOperation( State state, String name ) throws UnknownOperationException
+    {
+        Operation[] operations = state.getOperations();
+        for( int i=0; i<operations.length; i++ )
+        {
+            Operation operation = operations[i];
+            if( name.equals( operation.getName() ) )
+            {
+                return operation;
+            }
+        }
+        State parent = state.getParent();
+        if( null == parent )
+        {
+            throw new UnknownOperationException( name );
+        }
+        else
+        {
+            return getOperation( parent, name );
+        }
+    }
+
+    //-------------------------------------------------------------------------------
+    // static internals used to validate the integrity of a state graph
+    //-------------------------------------------------------------------------------
+    
+    private static void validateState( State state )
+    {
+        Trigger[] triggers = state.getTriggers();
+        validateTriggers( state, triggers );
+        Transition[] transitions = state.getTransitions();
+        validateTransitions( state, transitions );
+        Operation[] operations = state.getOperations();
+        validateOperations( state, operations );
+        State[] states = state.getStates();
+        validateStates( state, states );
+    }
+
+    private static void validateTransitions( State state, Transition[] transitions )
+    {
+        for( int i=0; i<transitions.length; i++ )
+        {
+            Transition transition = transitions[i];
+            validateTransition( state, transition );
+        }
+    }
+
+    private static void validateOperations( State state, Operation[] operations )
+    {
+        for( int i=0; i<operations.length; i++ )
+        {
+            Operation operation = operations[i];
+            validateOperation( state, operation );
+        }
+    }
+
+    private static void validateTriggers( State state, Trigger[] triggers )
+    {
+        for( int i=0; i<triggers.length; i++ )
+        {
+            Trigger trigger = triggers[i];
+            validateTrigger( state, trigger );
+        }
+    }
+    
+    private static void validateStates( State state, State[] states )
+    {
+        for( int i=0; i<states.length; i++ )
+        {
+            State s = states[i];
+            validateState( s );
+        }
+    }
+    
+    private static void validateTrigger( State state, Trigger trigger )
+    {
+        TriggerPolicy event = trigger.getPolicy();
+        Action action = trigger.getAction();
+        if( action instanceof Transition )
+        {
+            Transition transition = (Transition) action;
+            validateTransition( state, transition );
+        }
+        else if( action instanceof Operation )
+        {
+            Operation operation = (Operation) action;
+            validateOperation( state, operation );
+        }
+        else if( action instanceof ApplyAction )
+        {
+            ApplyAction apply = (ApplyAction) action;
+            String id = apply.getID();
+            validateTransition( state, id );
+        }
+        else if( action instanceof ExecAction )
+        {
+            ExecAction exec = (ExecAction) action;
+            String id = exec.getID();
+            validateOperation( state, id );
+        }
+    }
+    
+    private static void validateTransition( State state, String id )
+    {
+        //System.out.println( "# v/transition: " + id );
+    }
+    
+    private static void validateTransition( State state, Transition transition )
+    {
+        String target = transition.getTargetName();
+        State s = getState( state, target );
+        if( null == state )
+        {
+            final String error = 
+              "Transition target [" 
+              + target 
+              + "] does not exist relative to state ["
+              + state;
+            throw new IllegalStateException( error );
+        }
+    }
+    
+    private static void validateOperation( State state, String id )
+    {
+        //System.out.println( "# v/operation: " + operation );
+    }
+    
+    private static void validateOperation( State state, Operation operation )
+    {
+        //System.out.println( "# v/operation: " + operation );
+    }
+
+    private static State getState( State state, String target )
+    {
+        if( target.startsWith( "/" ) )
+        {
+            //
+            // its an absolute target 
+            //
+            
+            String spec = target.substring( 1 );
+            State root = state.getStatePath()[0];
+            return getState( root, spec );
+        }
+        else if( target.startsWith( "../" ) )
+        {
+            //
+            // its relative to the state's parent
+            //
+            
+            String spec = target.substring( 3 );
+            State parent = state.getParent();
+            if( null != parent )
+            {
+                return getState( parent, spec );
+            }
+            else
+            {
+                final String error = 
+                "Invalid relative reference [" 
+                + spec
+                + "] passed to root state.";
+                throw new IllegalArgumentException( error );
+            }
+        }
+        else if( target.indexOf( "/" ) > -1 )
+        {
+            //
+            // its a composition address
+            //
+            
+            int index = target.indexOf( "/" );
+            String base = target.substring( 0, index );
+            String remainder = target.substring( index + 1 );
+            State s = getState( state, base );
+            return getState( s, remainder );
+        }
+        else
+        {
+            //
+            // its a name relative to the supplied state
+            //
+            
+            State[] states = state.getStates();
+            for( int i=0; i<states.length; i++ )
+            {
+                State s = states[i];
+                if( target.equals( s.getName() ) )
+                {
+                    return s;
+                }
+            }
+            final String error = 
+              "Requested target state [" 
+              + target
+              + "] does not exist within the state ["
+              + state.getName()
+              + "].";
+            throw new IllegalArgumentException( error );
+        }
+    }
+    
+    private void checkDisposed() throws IllegalStateException
+    {
+        if( m_disposed )
+        {
+            final String error = 
+              "Instance has been disposed.";
+            throw new IllegalStateException( error );
+        }
+    }
+
+    private String getMethodName( Operation operation )
+    {
+        if( null != operation.getMethodName() )
+        {
+            return operation.getMethodName();
+        }
+        
+        //
+        // otherwise resolve it using java beans style getXxxx
+        //
+        
+        String name = operation.getName();
+        int n = name.length();
+        if( n == 0 )
+        {
+            throw new IllegalArgumentException( "Operation name is empty." );
+        }
+        else if( n == 1 )
+        {
+            return "get" + name.toUpperCase();
+        }
+        else
+        {
+            return "get" 
+              + name.substring( 0, 1 ).toUpperCase()
+              + name.substring( 1 );
+        }
+    }
+    
+    private static URI createURI( String path ) throws Exception
+    {
+        if( null == path )
+        {
+            return null;
+        }
+        else
+        {
+            return new URI( path );
+        }
+    }
+
+    private Logger getLogger()
+    {
+        return m_logger;
+    }
+    
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/Directive.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/Directive.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/Directive.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import net.dpml.lang.Buffer;
+
+import org.w3c.dom.Element;
+
+/**
+ * Exception to indicate an error arrising from the use of a duplicate key.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+abstract class Directive
+{
+    public interface Encodable
+    {
+        Element getElement();
+        
+        void encode( Buffer buffer, String key ) throws IOException;
+    }
+    
+    public interface Resolvable extends Encodable
+    {
+        <T>T resolve( ComponentStrategy parent, Class<T> clazz ) throws Exception;
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/EventQueue.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/EventQueue.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/EventQueue.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.util.EventObject;
+import java.util.EventListener;
+import java.util.List;
+import java.util.LinkedList;
+
+import net.dpml.util.Logger;
+import dpml.util.DefaultLogger;
+
+/**
+ * A abstract base class that established an event queue and handles event dispatch 
+ * operations for listeners declared in classes extending this base class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class EventQueue
+{
+    /**
+     * Interface implemented by objects that maintain a collection of event listeners
+     * and support for operational event propergation.
+     *
+     * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+     * @version @PROJECT-VERSION@
+     */
+    public interface EventHandler
+    {
+       /**
+        * Return the associated event listeners.
+        * @return the event listeners
+        */
+        EventListener[] getEventListeners();
+        
+       /**
+        * Process the supplied event.
+        * @param event the event to be processed
+        */
+        void processEvent( EventObject event );
+    }
+
+    // ------------------------------------------------------------------------
+    // state
+    // ------------------------------------------------------------------------
+    
+    private final EventDispatchThread m_thread;
+    
+    private final Logger m_logger;
+    
+    private final List<EventObject> m_queue = new LinkedList<EventObject>();
+    
+    // ------------------------------------------------------------------------
+    // constructor
+    // ------------------------------------------------------------------------
+
+   /**
+    * Creation of a new event queue.
+    * @param category the name used to construct a logging channel
+    * @deprecated Use new EventQueue( logger, "Thread name" ) instead.
+    */
+    public EventQueue( String category ) 
+    {
+        this( category, "Event Dispatch Thread" );
+    }
+
+   /**
+    * Creation of a new model.
+    * @param logger the assigned logging channel
+    * @exception NullPointerException if the supplied logging channel is null
+    * @deprecated Use new EventQueue( logger, "Thread name" ) instead.
+    */
+    public EventQueue( Logger logger ) 
+      throws NullPointerException
+    {
+        this( logger, "Event Dispatch Thread" );
+    }
+    
+   /**
+    * Creation of a new event queue.
+    * @param category the name used to construct a logging channel
+    * @param name the name to assign to the thread
+    */
+    public EventQueue( String category, String name ) 
+    {
+        this( getLoggerForCategory( category ), name );
+    }
+
+   /**
+    * Creation of a new model.
+    * @param logger the assigned logging channel
+    * @param name the name to assign to the thread
+    * @exception NullPointerException if the supplied logging channel or 
+    *   thread name is null
+    */
+    public EventQueue( Logger logger, String name ) 
+      throws NullPointerException
+    {
+        if( null == logger )
+        {
+            throw new NullPointerException( "logger" );
+        }
+        if( null == name )
+        {
+            throw new NullPointerException( "name" );
+        }
+        m_logger = logger;
+        m_thread = new EventDispatchThread();
+        m_thread.setName( name );
+        m_thread.setDaemon( true );
+        m_thread.start();
+    }
+
+    // ------------------------------------------------------------------------
+    // EventQueue
+    // ------------------------------------------------------------------------
+
+   /**
+    * Terminate the dispatch thread.
+    */
+    public synchronized void terminateDispatchThread()
+    {
+        if( null != m_thread )
+        {
+            m_thread.dispose();
+        }
+    }
+
+   /**
+    * Return the assigned logging channel.
+    * @return the logging channel
+    */
+    private Logger getLogger()
+    {
+        return m_logger;
+    }
+    
+    /**
+     * A single background thread ("the event notification thread") monitors
+     * the event queue and delivers events that are placed on the queue.
+     */
+    private class EventDispatchThread extends Thread 
+    {
+        private boolean m_continue = true;
+
+        void dispose()
+        {
+            synchronized( m_queue )
+            {
+                m_continue = false;
+                m_queue.notify();
+            }
+        }
+        
+        public void run() 
+        {
+            while( m_continue ) 
+            {
+                // Wait on m_queue till an event is present
+                EventObject event = null;
+                synchronized( m_queue ) 
+                {
+                    try 
+                    {
+                        while( m_continue && m_queue.isEmpty() )
+                        { 
+                            m_queue.wait();
+                        }
+                        if ( !m_continue )
+                        {
+                            break;
+                        }
+                        Object object = m_queue.remove( 0 );
+                        try
+                        {
+                            event = (EventObject) object;
+                        }
+                        catch( ClassCastException cce )
+                        {
+                            final String error = 
+                              "Unexpected class cast exception while processing an event." 
+                              + "\nEvent: " + object;
+                            throw new IllegalStateException( error );
+                        }
+                    }
+                    catch( InterruptedException e )
+                    {
+                        return;
+                    }
+                }
+
+                Object source = event.getSource();
+                if( source instanceof EventHandler )
+                {
+                    EventHandler handler = (EventHandler) source;
+                    try
+                    {
+                        handler.processEvent( event );
+                    }
+                    catch( Throwable e )
+                    {
+                        final String error = 
+                          "Unexpected error while processing event."
+                          + "\nEvent: " + event
+                          + "\nSource: " + this;
+                        getLogger().error( error, e );
+                    }
+                }
+                else
+                {
+                    final String error = 
+                      "Event source is not an instance of " 
+                      + EventHandler.class.getName();
+                    getLogger().error( error );
+                }
+            }
+        }
+    }
+
+    /**
+     * Enqueue an event for delivery to registered
+     * listeners unless there are no registered
+     * listeners.
+     *
+     * @param event the event object to add to the queue
+     */
+    public void enqueueEvent( EventObject event )
+    {
+        enqueueEvent( event, false );
+    }
+
+    /**
+     * Enqueue an event for delivery to registered
+     * listeners unless there are no registered
+     * listeners.
+     *
+     * @param event the event object to add to the queue
+     * @param waitForCompletion if TRUE the implementation will apply
+     *   the event to the event source event handler and return on 
+     *   copmpletion of evetn delivery
+     */
+    public void enqueueEvent( EventObject event, boolean waitForCompletion )
+    {
+        if( !waitForCompletion )
+        {    
+            synchronized( m_queue ) 
+            {
+                m_queue.add( event );
+                m_queue.notify();
+            }
+        }
+        else
+        {
+            Object source = event.getSource();
+            if( source instanceof EventHandler )
+            {
+                EventHandler handler = (EventHandler) source;
+                try
+                {
+                    handler.processEvent( event );
+                }
+                catch( Throwable e )
+                {
+                    final String error = 
+                      "Unexpected error while processing event."
+                      + "\nEvent: " + event
+                      + "\nSource: " + source;
+                    getLogger().error( error );
+                }
+            }
+            else
+            {
+                final String error = 
+                  "Event source is not an instance of " 
+                  + EventHandler.class.getName()
+                  + "\nSource: " + source.getClass().getName();
+                throw new IllegalStateException( error );
+            }
+        }
+    }
+
+   /**
+    * Return a logging channel for the supplied name.
+    * @param name the name to use in construction of the logging channel
+    * @return the logging channel
+    */
+    static Logger getLoggerForCategory( String name )
+    {
+        if( null == name )
+        {
+            return new DefaultLogger( "" );
+        }
+        else
+        {
+            return new DefaultLogger( name );
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/LifestyleHandler.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/LifestyleHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/LifestyleHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ServiceLoader;
+
+import net.dpml.annotation.CollectionPolicy;
+
+import net.dpml.state.State;
+import net.dpml.state.StateMachine;
+
+import net.dpml.util.Logger;
+import dpml.util.DefaultLogger;
+
+/**
+ * Abstract lifestyle handler.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+abstract class LifestyleHandler
+{
+    private static final EventQueue QUEUE = 
+      new EventQueue( 
+        new DefaultLogger( "dpml.metro" ), 
+        "DPML Component Event Queue" );
+
+    private final ComponentStrategy m_strategy;
+    
+    LifestyleHandler( ComponentStrategy strategy )
+    {
+        m_strategy = strategy;
+    }
+    
+   /**
+    * Return the component strategy.
+    * @return a component strategy
+    */
+    protected ComponentStrategy getComponentStrategy()
+    {
+        return m_strategy;
+    }
+    
+   /**
+    * Return a component provider.
+    * @return a provider instance
+    * @exception Exception if an error occurs
+    */
+    abstract void release( Provider provider );
+    
+   /**
+    * Return an instance of the component taking into account the lifestyle policy.
+    * @return a component instance
+    * @exception Exception if an error occurs
+    */
+    abstract Provider getProvider();
+    
+    abstract void terminate();
+    
+    protected <T> Reference<T> createReference( T referent )
+    {
+        CollectionPolicy policy = getComponentStrategy().getCollectionPolicy();
+        if( policy.equals( CollectionPolicy.SOFT ) )
+        {
+            return new SoftReference<T>( referent );
+        }
+        else if( policy.equals( CollectionPolicy.WEAK ) )
+        {
+            return new WeakReference<T>( referent );
+        }
+        else
+        {
+            return new HardReference<T>( referent );
+        }
+    }
+
+   /**
+    * A reference class that implements hard reference semantics.
+    */
+    private static class HardReference<T> extends SoftReference<T>
+    {
+        private final T m_referent; // hard reference
+        
+       /**
+        * Creation of a new hard reference.
+        * @param referent the referenced object
+        */
+        public HardReference( T referent )
+        {
+            super( referent );
+            m_referent = referent;
+        }
+        
+       /**
+        * Return the referent.
+        * @return the referent object
+        */
+        public T get()
+        {
+            return m_referent;
+        }
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/PartsDirective.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/PartsDirective.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/PartsDirective.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import dpml.util.ElementHelper;
+import dpml.util.DefaultLogger;
+
+import java.io.Writer;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Hashtable;
+import java.lang.reflect.Array;
+
+import net.dpml.lang.Buffer;
+import net.dpml.lang.DecodingException;
+import net.dpml.lang.ServiceRegistry;
+import net.dpml.lang.Strategy;
+import net.dpml.lang.StrategyHandler;
+import net.dpml.lang.PartContentHandler;
+
+import net.dpml.util.Resolver;
+import net.dpml.util.Logger;
+
+import org.w3c.dom.Element;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class PartsDirective
+{
+    private final PartsDirective m_parent;
+    private final Map<String,Strategy> m_parts = new Hashtable<String,Strategy>();
+    
+   /**
+    * Creation of parts datastructure.
+    */
+    PartsDirective()
+    {
+        m_parent = null;
+    }
+    
+    PartsDirective( 
+      ClassLoader classloader, 
+      Element element, Resolver resolver, String partition ) throws DecodingException
+    {
+        this( null, classloader, element, resolver, partition );
+    }
+    
+    PartsDirective( 
+      PartsDirective parent, ClassLoader classloader, 
+      Element element, Resolver resolver, String partition ) throws DecodingException
+    {
+        m_parent = parent;
+        if( null != element )
+        {
+            Element[] elements = ElementHelper.getChildren( element );
+            for( Element child : elements ) 
+            {
+                boolean implicit = false;
+                String key = ElementHelper.getAttribute( child, "key" );
+                Strategy strategy = buildStrategy( classloader, child, resolver, partition );
+                if( null == key )
+                {
+                    implicit = true;
+                    key = strategy.getName();
+                }
+                if( m_parts.containsKey( key ) )
+                {
+                    if( implicit )
+                    {
+                        final String error = 
+                          "Strategy declaration resolving to the implicit key ["
+                          + key
+                          + "] cannot be added because the key has already been assigned.";
+                        throw new DecodingException( error, null, child );
+                    }
+                    else
+                    {
+                        final String error = 
+                          "Strategy declaration references a duplicate key ["
+                          + key
+                          + "].";
+                        throw new DecodingException( error, null, child );
+                    }
+                }
+                else
+                {
+                    m_parts.put( key, strategy );
+                }
+            }
+        }
+    }
+    
+    private Strategy buildStrategy( ClassLoader classloader, 
+      Element element, Resolver resolver, String partition ) throws DecodingException
+    {
+        try
+        {
+            StrategyHandler handler = PartContentHandler.getStrategyHandler( element );
+            return handler.build( classloader, element, resolver, partition, null );
+        }
+        catch( DecodingException e )
+        {
+            throw e;
+        }
+        catch( Exception e )
+        {
+            if( null != partition )
+            {
+                final String error = 
+                  "Error building part strategy in partition [" 
+                  + partition
+                  + "]";
+                throw new DecodingException( error, e, element );
+            }
+            else
+            {
+                final String error = 
+                  "Error building part strategy.";
+                throw new DecodingException( error, e, element );
+            }
+        }
+    }
+    
+    void initialize( ServiceRegistry registry )
+    {
+        if( null != m_parent )
+        {
+            m_parent.initialize( registry );
+        }
+        for( Strategy strategy : m_parts.values() )
+        {
+            strategy.initialize( registry );
+        }
+    }
+    
+    int size()
+    {
+        return m_parts.size();
+    }
+    
+    String[] getKeys()
+    {
+        return m_parts.keySet().toArray( new String[0] );
+    }
+    
+    Strategy getStrategy( String key )
+    {
+        Strategy strategy = m_parts.get( key );
+        if( null != strategy )
+        {
+            return strategy;
+        }
+        else if( null != m_parent )
+        {
+            return m_parent.getStrategy( key );
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    String[] getAllKeys()
+    {
+        ArrayList<String> list = new ArrayList<String>();
+        if( null != m_parent )
+        {
+            String[] keys = m_parent.getAllKeys();
+            for( String key : keys )
+            {
+                if( !list.contains( key ) )
+                {
+                    list.add( key );
+                }
+            }
+        }
+        for( String key : getKeys() )
+        {
+            if( !list.contains( key ) )
+            {
+                list.add( key );
+            }
+        }
+        return list.toArray( new String[0] );
+    }
+    
+   /**
+    * Returns an array of type T where the contents of the array 
+    * will be composed of all parts returning a non-null value
+    * from getContentForClass( T ).
+    * @param type the component type of the returned array
+    * @return an array of values matching the type selection criteria
+    * @exception IOException if a content resolution error occurs
+    */
+    @SuppressWarnings( "unchecked" )
+    <T>T[] select( Class<T> type ) throws IOException
+    {
+        return select( type, null );
+    }
+    
+   /**
+    * Returns an array of type T where the contents of the array 
+    * will be composed of all parts returning a non-null value
+    * from getContentForClass( c ).
+    * @param type the component type of the returned array
+    * @param criteria the content type selection constraint
+    * @return an array of values matching the type selection criteria
+    * @exception IOException if a content resolution error occurs
+    */
+    @SuppressWarnings( "unchecked" )
+    <T>T[] select( Class<T> type, Class criteria ) throws IOException
+    {
+        Strategy[] strategies = getAllStrategies();
+        
+        ArrayList<T> list = new ArrayList<T>();
+        for( Strategy strategy : strategies )
+        {
+            if( null != criteria )
+            {
+                if( strategy.isaCandidate( criteria ) )
+                {
+                    T value = strategy.getInstance( type );
+                    list.add( value );
+                }
+            }
+            else
+            {
+                T value = strategy.getContentForClass( type );
+                if( null != value )
+                {
+                    list.add( value );
+                }
+            }
+        }
+        T[] result = (T[]) Array.newInstance( type, list.size() );
+        int n = list.size();
+        for( int i=0; i<n; i++ )
+        {
+            result[i] = list.get( i );
+        }
+        return result;
+    }
+    
+    Strategy[] getAllStrategies()
+    {
+        return getAllStrategies( true );
+    }
+    
+    Strategy[] getAllStrategies( boolean sort )
+    {
+        ArrayList<Strategy> list = new ArrayList<Strategy>();
+        if( null != m_parent )
+        {
+            Strategy[] values = m_parent.getAllStrategies( sort );
+            for( Strategy strategy : values )
+            {
+                list.add( strategy );
+            }
+        }
+        Collection<Strategy> collection = m_parts.values();
+        for( Strategy strategy : collection )
+        {
+            list.add( strategy );
+        }
+        Strategy[] result = list.toArray( new Strategy[0] );
+        if( sort )
+        {
+            Arrays.sort( result );
+        }
+        return result;
+    }
+    
+    public void encode( Buffer buffer ) throws IOException
+    {
+        if( size() > 0 )
+        {
+            buffer.nl( "<parts>" );
+            Buffer b2 = buffer.indent();
+            for( String key : getKeys() )
+            {
+                Strategy strategy = getStrategy( key );
+                strategy.encode( b2, key );
+            }
+            buffer.nl( "</parts>" );
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/PartsInvocationHandler.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/PartsInvocationHandler.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/PartsInvocationHandler.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.util.Map;
+import java.beans.Introspector;
+import java.beans.Expression;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.TypeVariable;
+
+import net.dpml.annotation.Parts;
+
+import net.dpml.lang.Strategy;
+
+/**
+ * Invocation handler utility for a Context class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+final class PartsInvocationHandler implements InvocationHandler
+{
+    //-------------------------------------------------------------------
+    // static
+    //-------------------------------------------------------------------
+    
+    private static final String GET = "get";
+
+   /**
+    * Test if the supplied class is recognized as a context class. If
+    * the supplied policy is true then evaluation is based on the presence
+    * of the <tt>net.dpml.lang.Context</tt> annotation and resulting 
+    * value of annotation evaluation.  If no context annnotation is present
+    * and strict processing is disabled then evaluation will return true if 
+    * the classname ends with the string <tt>$Context</tt>.
+    *
+    * @param c the candidate class
+    * @param policy the strict evaluation policy
+    * @return true if this class is recognized as a context class
+    */
+    public static boolean isaParts( final Class<?> c, final boolean policy )
+    {
+        boolean flag = c.isAnnotationPresent( Parts.class );
+        if( flag )
+        {
+            return c.getAnnotation( Parts.class ).value();
+        }
+        else if( policy )
+        {
+            return false;
+        }
+        else
+        {
+            return c.getName().endsWith( "$Parts" );
+        }
+    }
+    
+   /**
+    * Construct a new context instance implementing the supplied class
+    * backed by entries in the supplied map.
+    *
+    * @param clazz the context class
+    * @param map a map of context entry keys and values
+    * @return the constructed context instance
+    */
+    public static <T>T getProxiedInstance( 
+      final Class<T> clazz, final PartsDirective directive )
+    {
+        ClassLoader classloader = clazz.getClassLoader();
+        PartsInvocationHandler handler = 
+          new PartsInvocationHandler( directive );
+        final Object instance = 
+          Proxy.newProxyInstance( classloader, new Class[]{clazz}, handler );
+        return clazz.cast( instance );
+    }
+    
+    //-------------------------------------------------------------------
+    // state
+    //-------------------------------------------------------------------
+
+   /**
+    * A map containing key values.
+    */
+    private final PartsDirective m_directive;
+    
+    //-------------------------------------------------------------------
+    // constructor
+    //-------------------------------------------------------------------
+
+   /**
+    * Create a parts invocation handler.
+    *
+    * @param directive the parts directive
+    */
+    private PartsInvocationHandler( final PartsDirective directive )
+    {
+        m_directive = directive;
+    }
+    
+    //-------------------------------------------------------------------
+    // implementation
+    //-------------------------------------------------------------------
+
+   /**
+    * Invoke the specified method on underlying object.
+    * This is called by the proxy object.
+    *
+    * @param proxy the proxy object
+    * @param method the method invoked on proxy object
+    * @param args the arguments supplied to method
+    * @return the return value of method
+    * @throws Throwable if an error occurs
+    */
+    @SuppressWarnings( "unchecked" )
+    public Object invoke( final Object proxy, final Method method, final Object[] args ) throws Throwable
+    {
+        String name = method.getName();
+        if( name.startsWith( "get" ) )
+        {
+            Class<?> clazz = method.getReturnType();
+            if( clazz.isArray() )
+            {
+                // build an array of all parts matching the array type
+                Class<?> type = clazz.getComponentType();
+                if( null == args )
+                {
+                    return m_directive.select( type );
+                }
+                else
+                {
+                    Class<?> c = getClassArgument( args );
+                    return m_directive.select( type, c );
+                }
+            }
+            else
+            {
+                String key = Introspector.decapitalize( name.substring( 3 ) );
+                Strategy strategy = m_directive.getStrategy( key );
+                if( null != strategy )
+                {
+                    if( ( null != args ) && ( args.length > 0 ) && ( args[0].getClass() == Class.class ) )
+                    {
+                        return strategy.getInstance( (Class) args[0] );
+                    }
+                    else
+                    {
+                        return strategy.getInstance( clazz );
+                    }
+                }
+                if( ( null != args ) && ( args.length > 0 ) )
+                {
+                    return args[0];
+                }
+                else
+                {
+                    final String error = 
+                      "Unable to resolve a parts entry value for the key [" 
+                      + key
+                      + "]";
+                    throw new IllegalStateException( error );
+                }
+            }
+        }
+        else
+        {
+            throw new UnsupportedOperationException( name );
+        }
+    }
+    
+    private static final String STRICT_PROCESSING_KEY = "dpml.lang.parts.policy";
+    private static final String STRICT_PROCESSING_KEYWORD = "strict";
+    private static final boolean STRICT_PROCESSING = getStrictProcessingPolicy();
+    
+    private static boolean getStrictProcessingPolicy()
+    {
+        return STRICT_PROCESSING_KEYWORD.equalsIgnoreCase( 
+          System.getProperty( 
+            STRICT_PROCESSING_KEY, 
+            STRICT_PROCESSING_KEYWORD ) );
+    }
+    
+    private Class<?> getClassArgument( Object[] args )
+    {
+        if( null == args )
+        {
+            throw new NullPointerException( "args" ); // will not happen
+        }
+        else if( args.length == 0 )
+        {
+            throw new IllegalArgumentException( "args" ); // will not happen
+        }
+        else
+        {
+            Object arg = args[0];
+            if( arg.getClass() == Class.class )
+            {
+                return (Class) arg;
+            }
+            else
+            {   
+                String classname = arg.getClass().getName();
+                final String error = 
+                  "Expacting a class parameter but found an integer of [" 
+                  + classname
+                  + "].";
+                throw new IllegalArgumentException( error );
+            }
+        }
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/Profile.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/Profile.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/Profile.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+
+import dpml.lang.DOM3DocumentBuilder;
+
+import net.dpml.util.Resolver;
+import dpml.util.ElementHelper;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Component interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class Profile
+{
+    private static final DOM3DocumentBuilder BUILDER = new DOM3DocumentBuilder();
+
+    private Class m_clazz;
+    private Element m_element;
+    private ContextDirective m_context;
+    private PartsDirective m_parts;
+    
+    Profile( Class<?> c, String path, Resolver resolver ) throws IOException
+    {
+        m_element = getProfileElement( c );
+        ClassLoader classloader = c.getClassLoader();
+        m_context = getContextProfile( classloader, m_element, resolver );
+        m_parts = getPartsProfile( classloader, m_element, resolver, path );
+    }
+    
+    ContextDirective getContextDirective()
+    {
+        return m_context;
+    }
+
+    PartsDirective getPartsDirective()
+    {
+        return m_parts;
+    }
+
+    private static Element getProfileElement( Class<?> c ) throws IOException
+    {
+        ClassLoader classloader = c.getClassLoader();
+        String path = c.getName().replace( ".", "/" );
+        String profile = path + ".xprofile";
+        URL url = classloader.getResource( profile );
+        if( null != url )
+        {
+            try
+            {
+                URI uri = url.toURI();
+                final Document document = BUILDER.parse( uri );
+                return document.getDocumentElement();
+            }
+            catch( Exception e )
+            {
+                final String error = 
+                  "Bad url: " + url;
+                IOException ioe = new IOException( error );
+                ioe.initCause( e );
+                throw ioe;
+            }
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    private static ContextDirective getContextProfile( 
+      ClassLoader classloader, Element profile, Resolver resolver ) throws IOException
+    {
+        if( null == profile )
+        {
+            return null;
+        }
+        Element context = ElementHelper.getChild( profile, "context" );
+        return new ContextDirective( classloader, context, resolver );
+    }
+    
+    private static PartsDirective getPartsProfile( 
+      ClassLoader classloader, Element profile, Resolver resolver, String path ) throws IOException
+    {
+        if( null == profile )
+        {
+            return null;
+        }
+        Element partsElement = ElementHelper.getChild( profile, "parts" );
+        return new PartsDirective( classloader, partsElement, resolver, path );
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/Provider.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/Provider.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/Provider.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import net.dpml.state.StateListener;
+
+/**
+ * Component interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Provider
+{
+   /**
+    * Add a state change listener to the state machine.
+    * @param listener the state listener
+    */
+    void addStateListener( final StateListener listener );
+    
+   /**
+    * Remove a state listener from the state machine.
+    * @param listener the state listener
+    */
+    void removeStateListener( final StateListener listener );
+
+   /**
+    * Return a fully commissioned instance.
+    * @return the instance
+    */
+    <T>T getInstance( Class<T> type );
+    
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/ProviderEvent.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/ProviderEvent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/ProviderEvent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,63 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+/**
+ * Event triggered as a result of a state change.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ProviderEvent extends ComponentEvent
+{
+    private final Provider m_provider;
+    private final Status m_action;
+    
+   /**
+    * Construct a new <code>StateEvent</code>.
+    *
+    * @param source the source component 
+    * @param provider the provider instance initiating the event
+    * @param action the modified Status enumeration
+    */
+    public ProviderEvent( final Component source, Provider provider, Status action )
+    {
+        super( source );
+        
+        m_provider = provider;
+        m_action = action;
+    }
+    
+    public Provider getProvider()
+    {
+        return m_provider;
+    }
+    
+    public Status getStatus()
+    {
+        return m_action;
+    }
+    
+    public String toString()
+    {
+        String id = super.toString();
+        return id + "#" + getStatus();
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/Query.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/Query.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/Query.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import dpml.lang.Value;
+import dpml.lang.Construct;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import net.dpml.runtime.Directive.Resolvable;
+import net.dpml.runtime.ContextDirective.ValueWrapper;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class Query
+{
+    private final Map<String,Resolvable> m_entries = new Hashtable<String,Resolvable>();
+    
+    Query( String query )
+    {
+        this( expand( query ) );
+    }
+    
+    Query( List<Binding> values )
+    {
+        for( Binding binding : values )
+        {
+            String key = binding.getKey();
+            Resolvable value = binding.getValue();
+            m_entries.put( key, value );
+        }
+    }
+    
+    public Resolvable getEntry( String key )
+    {
+        return m_entries.get( key );
+    }
+    
+    private static List<Binding> expand( String query )
+    {
+        final List<Binding> list = new ArrayList<Binding>();
+        if( null == query )
+        {
+            return list;
+        }
+        String[] segments = query.split( "," );
+        for( String segment : segments )
+        {
+            String[] args = segment.split( "=" );
+            if( args.length != 2 )
+            {
+                throw new IllegalArgumentException( 
+                  "Invalid query [" + segment + "]" );
+            }
+            String address = args[0];
+            String param = args[1];
+            String decoded = decode( param );
+            Value value = new Construct( decoded );
+            Resolvable entry = new ValueWrapper( value );
+            Binding binding = new Binding( address, entry );
+            list.add( binding );
+        }
+        return list;
+    }
+    
+    private static String decode( String param )
+    {
+        try
+        {
+            return URLDecoder.decode( param, "UTF8"  );
+        }
+        catch( UnsupportedEncodingException uee )
+        {
+            // will not happen
+            uee.printStackTrace();
+            return param;
+        }
+    }
+    
+    private static class Binding
+    {
+        private final String m_key;
+        private final Resolvable m_value;
+        
+        Binding( String key, Resolvable value )
+        {
+            m_key = key;
+            m_value = value;
+        }
+        
+        String getKey()
+        {
+            return m_key;
+        }
+        
+        Resolvable getValue()
+        {
+            return m_value;
+        }
+    }
+        
+    //public <T>T resolve( ComponentStrategy parent, Class<T> clazz ) throws Exception
+    //{
+    //    return null;
+    //}
+    
+    /*
+    private final List<Binding> m_list = new ArrayList<Binding>();
+    
+    Query( String query )
+    {
+        if( null != query )
+        {
+            String[] segments = query.split( "," );
+            for( String segment : segments )
+            {
+                String[] args = segment.split( "=" );
+                if( args.length != 2 )
+                {
+                    throw new IllegalArgumentException( 
+                      "Invalid query [" + segment + "]" );
+                }
+                String address = args[0];
+                String param = args[1];
+                String[] keys = address.split( "." );
+                Binding binding = new Binding( keys, param );
+                m_list.add( binding );
+            }
+        }
+    }
+    
+    Binding getBinding( String key )
+    {
+        for( Binding binding : m_list )
+        {
+            if( key.equals( binding.getKey() ) )
+            {
+                return binding;
+            }
+        }
+        return null;
+    }
+    
+    static class Binding
+    {
+        private final String m_key;
+        private final Object m_value;
+        
+        Binding( String[] keys, String value )
+        {
+            int n = keys.length;
+            if( n == 0 )
+            {
+                throw new IllegalArgumentException( 
+                  "Invalid query expression." );
+            }
+            else if( n == 1 )
+            {
+                m_key = keys[0];
+                m_value = value;
+            }
+            else
+            {
+                int m = n-1;
+                m_key = keys[0];
+                String[] newKeys = new String[ m ];
+                System.arrayCopy( keys, 1, newKeys, 0, m );
+                m_value = new Binding( newKeys, value );
+            }
+        }
+        
+        String getKey()
+        {
+            return m_key;
+        }
+        
+        Object getValue()
+        {
+            return m_value;
+        }
+    }
+    */
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/StandardProvider.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/StandardProvider.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/StandardProvider.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,434 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import dpml.util.DefaultLogger;
+import dpml.util.StandardClassLoader;
+import dpml.lang.Disposable;
+
+import dpml.lang.LoggingInvocationHandler;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ServiceLoader;
+
+import net.dpml.annotation.Services;
+import net.dpml.annotation.LifestylePolicy;
+import net.dpml.annotation.ActivationPolicy;
+
+import net.dpml.lang.ServiceRegistry;
+import net.dpml.lang.StandardServiceRegistry;
+import net.dpml.lang.TypeCastException;
+
+import net.dpml.state.State;
+import net.dpml.state.StateListener;
+import net.dpml.state.StateMachine;
+
+import net.dpml.util.Logger;
+
+import static net.dpml.runtime.Status.CREATION;
+import static net.dpml.runtime.Status.INCARNATION;
+import static net.dpml.runtime.Status.ETHERIALIZATION;
+import static net.dpml.runtime.Status.TERMINATION;
+
+import static net.dpml.annotation.ActivationPolicy.STARTUP;
+
+
+/**
+ * Abstract lifestyle handler.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class StandardProvider implements Provider, Disposable
+{
+    private static final EventQueue QUEUE = 
+      new EventQueue( 
+        new DefaultLogger( "dpml.metro" ), 
+        "DPML Provider Event Queue" );
+
+    private static final ServiceRegistry REGISTRY = 
+      new StandardServiceRegistry();
+
+    private final ComponentStrategy m_strategy;
+    private final StateMachine m_machine;
+    private final Class<?> m_class;
+    private final String m_category;
+    private final Logger m_logger;
+    
+    private Object m_instance = null;
+    
+    StandardProvider( ComponentStrategy strategy )
+    {
+        m_strategy = strategy;
+        m_class = m_strategy.getComponentClass();
+        final Logger logger = strategy.getComponentLogger();
+        final State graph = strategy.getStateGraph();
+        LifestylePolicy lifestyle = m_strategy.getLifestylePolicy();
+        m_category = getLoggingCategory( lifestyle );
+        m_logger = new DefaultLogger( m_category );
+        m_machine = getStateMachine( m_logger, graph );
+        
+        ComponentEvent event = new ProviderEvent( m_strategy, this, CREATION );
+        strategy.processEvent( event );
+
+        ActivationPolicy activation = m_strategy.getActivationPolicy();
+        if( STARTUP.equals( activation ) )
+        {
+            m_instance = newInstance();
+        }
+    }
+
+   /**
+    * Add a state change listener to the state machine.
+    * @param listener the state listener
+    */
+    public void addStateListener( final StateListener listener )
+    {
+        if( m_logger.isTraceEnabled() )
+        {
+            m_logger.trace( "adding state listener" );
+        }
+        m_machine.addStateListener( listener );
+    }
+    
+   /**
+    * Remove a state listener from the state machine.
+    * @param listener the state listener
+    */
+    public void removeStateListener( final StateListener listener )
+    {
+        if( m_logger.isTraceEnabled() )
+        {
+            m_logger.trace( "removing state listener" );
+        }
+        m_machine.removeStateListener( listener );
+    }
+    
+    public <T>T getInstance( Class<T> type )
+    {
+        synchronized( this )
+        {
+            Object instance = getCachedInstance();
+            if( type.isInterface() )
+            {
+                if( m_class.isAnnotationPresent( Services.class ) )
+                {
+                    InvocationHandler handler = new ComponentInvocationHandler( instance );
+                    ClassLoader classloader = m_class.getClassLoader();
+                    Services annotation = m_class.getAnnotation( Services.class );
+                    Class[] services = annotation.value();
+                    Object proxy = Proxy.newProxyInstance( classloader, services, handler );
+                    try
+                    {
+                        return type.cast( proxy );
+                    }
+                    catch( ClassCastException cce )
+                    {
+                        StringBuffer buffer = new StringBuffer();
+                        buffer.append( "Cannot assign component class [" );
+                        buffer.append( instance.getClass().getName() + "]" );
+                        buffer.append( " to the return type [" );
+                        buffer.append( type.getName() + "] " );
+                        buffer.append( "because the requested service type is not " );
+                        buffer.append( "included in the public services published by the component." );
+                        String error = buffer.toString();
+                        throw new TypeCastException( error, m_class, type );
+                    }
+                }
+                else
+                {
+                    try
+                    {
+                        return type.cast( instance );
+                    }
+                    catch( ClassCastException cce )
+                    {
+                        StringBuffer buffer = new StringBuffer();
+                        buffer.append( "Cannot assign component class [" );
+                        buffer.append( instance.getClass().getName() + "]" );
+                        buffer.append( " to the return type [" );
+                        buffer.append( type.getName() + "]" );
+                        String error = buffer.toString();
+                        throw new TypeCastException( error, m_class, type );
+                    }
+                }
+            }
+            else if( type.isAssignableFrom( m_class ) )
+            {
+                return type.cast( instance );
+            }
+            else
+            {
+                StringBuffer buffer = new StringBuffer();
+                buffer.append( "Cannot assign component class [" );
+                buffer.append( instance.getClass().getName() + "]" );
+                buffer.append( " to the return type [" );
+                buffer.append( type.getName() + "]" );
+                String error = buffer.toString();
+                throw new TypeCastException( error, m_class, type );
+            }
+        }
+    }
+    
+    private Object getCachedInstance()
+    {
+        if( null == m_instance )
+        {
+            m_instance = newInstance();
+        }
+        return m_instance;
+    }
+    
+    private Object newInstance()
+    {
+        if( m_logger.isTraceEnabled() )
+        {
+            m_logger.trace( "incarnation [" + m_class + "]" );
+        }
+        
+        ComponentEvent event = new ProviderEvent( m_strategy, this, INCARNATION );
+        m_strategy.processEvent( event );
+        
+        final String path = m_strategy.getComponentPath();
+        final Constructor<?> constructor = getConstructor( m_class );
+        final Class<?>[] types = constructor.getParameterTypes();
+        final Object[] args = new Object[ types.length ];
+        
+        for( int i=0; i<types.length; i++ )
+        {
+            Class<?> type = types[i];
+            if( java.util.logging.Logger.class.isAssignableFrom( type ) )
+            {
+                String category = getLoggingCategory();
+                java.util.logging.Logger logger = 
+                  java.util.logging.Logger.getLogger( category );
+                args[i] = logger;
+            }
+            else if( Logger.class.isAssignableFrom( type ) )
+            {
+                args[i] = getTargetLogger();
+            }
+            else if( ContextInvocationHandler.isaContext( type, false ) )
+            {
+                ContextModel context = m_strategy.getContextModel();
+                args[i] = ContextInvocationHandler.getProxiedInstance( type, m_strategy, context );
+            }
+            else if( PartsInvocationHandler.isaParts( type, false ) )
+            {
+                PartsDirective directive = m_strategy.getPartsDirective();
+                args[i] = PartsInvocationHandler.getProxiedInstance( type, directive );
+            }
+            else if( "net.dpml.logging.Logger".equals( type.getName() ) ) // legacy
+            {
+                Logger logger = getTargetLogger();
+                args[i] = LoggingInvocationHandler.getProxiedInstance( type, logger );
+            }
+            else
+            {
+                Object service = m_strategy.lookup( type );
+                if( null != service )
+                {
+                    args[i] = service;
+                }
+                else
+                {
+                    service = REGISTRY.lookup( type );
+                    if( null != service )
+                    {
+                        args[i] = service;
+                    }
+                    else if( type.isArray() )
+                    {
+                        args[i] = Array.newInstance( type.getComponentType(), 0 );
+                    }
+                    else
+                    {
+                        String stack = StandardClassLoader.toString( getClass(), m_class );
+                        System.out.println( stack );
+                        final String error = 
+                          "No solution for the constructor parameter ["
+                          + type.getName()
+                          + "] at position " + i 
+                          + " for the component ["
+                          + path
+                          + "] ("
+                          + m_class.getName() 
+                          + ").";
+                        throw new ComponentError( error );
+                    }
+                }
+            }
+        }
+        
+        try
+        {
+            Object instance = constructor.newInstance( args );
+            m_machine.initialize( instance );
+            return instance;
+        }
+        catch( Throwable e )
+        {
+            ComponentError error = getComponentError( path, e );
+            throw error;
+        }
+    }
+    
+    private Logger getTargetLogger()
+    {
+        String category = getLoggingCategory();
+        return new DefaultLogger( category );
+    }
+    
+    public void dispose()
+    {
+        if( null != m_instance )
+        {
+            ComponentEvent etherialization = new ProviderEvent( m_strategy, this, ETHERIALIZATION );
+            m_strategy.processEvent( etherialization );
+            if( m_logger.isTraceEnabled() )
+            {
+                m_logger.trace( "etherialization" );
+            }
+            Object instance = getUnwrappedInstance( m_instance );
+            m_machine.terminate( instance );
+            m_instance = null;
+        }
+        ComponentEvent termination = new ProviderEvent( m_strategy, this, TERMINATION );
+        m_strategy.processEvent( termination );
+    }
+    
+    private ComponentError getComponentError( String path, Throwable e )
+    {
+        if( e instanceof ComponentError )
+        {
+            return (ComponentError) e;
+        }
+        if( e instanceof UndeclaredThrowableException )
+        {
+            Throwable cause = e.getCause();
+            if( null != cause )
+            {
+                return getComponentError( path, cause );
+            }
+        }
+        if( e instanceof InvocationTargetException )
+        {
+            Throwable cause = e.getCause();
+            if( null != cause )
+            {
+                return getComponentError( path, cause );
+            }
+        }
+        final String error = 
+          "Component '" 
+          + path 
+          + "' could not be instantiated ["
+          + m_class.getName()
+          + "]";
+        return new ComponentError( error, e );
+    }
+    
+   /**
+    * Loacate and return the single public constructor declared by the component class.
+    * @return the constructor
+    * @exception ControlException if the class does not declare a unique public constructor
+    */
+    private Constructor getConstructor( Class c )
+    {
+        return ComponentStrategyHandler.getSingleConstructor( c );
+    }
+    
+    private StateMachine getStateMachine( Logger logger, State graph )
+    {
+        return new DefaultStateMachine( QUEUE, logger, graph );
+    }
+    
+    private Object getUnwrappedInstance( Object instance )
+    {
+        Class c = instance.getClass();
+        if( Proxy.isProxyClass( c ) )
+        {
+            InvocationHandler handler = Proxy.getInvocationHandler( instance );
+            if( handler instanceof ComponentInvocationHandler )
+            {
+                ComponentInvocationHandler h = (ComponentInvocationHandler) handler;
+                return h.getInstance();
+            }
+            else
+            {
+                final String error = 
+                  "Invocation handler class ["
+                  + handler.getClass().getName() 
+                  + "] is not recognized.";
+                throw new IllegalArgumentException( error );
+            }
+        }
+        else
+        {
+            return instance;
+        }
+    }
+    
+    private String getLoggingCategory()
+    {
+        return m_category;
+    }
+    
+    private String getLoggingCategory( LifestylePolicy lifestyle )
+    {
+        String category = getBaseLoggingCategory();
+        if( LifestylePolicy.SINGLETON.equals( lifestyle ) )
+        {
+            return category;
+        }
+        else
+        {
+            int id = System.identityHashCode( this );
+            return category + "." + id;
+        }
+    }
+    
+    private String getBaseLoggingCategory()
+    {
+        String path = m_strategy.getComponentPath();
+        if( path.startsWith( "/" ) )
+        {
+            return path.substring( 1 );
+        }
+        else
+        {
+            return path;
+        }
+    }
+    
+    public String toString()
+    {
+        String lifestyle = m_strategy.getLifestylePolicy().toString().toLowerCase();
+        String path = m_strategy.getComponentPath();
+        int id = System.identityHashCode( this );
+        return lifestyle + ":" + path + "#" + id;
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/runtime/Status.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/Status.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/Status.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+/**
+ * Provider status enumeration.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public enum Status
+{
+    CREATION,
+    INCARNATION,
+    ETHERIALIZATION,
+    TERMINATION,
+}

Added: trunk/main/lang/part/src/main/net/dpml/runtime/package-info.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/runtime/package-info.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/runtime/package-info.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Component strategy runtime implementation.
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+package net.dpml.runtime;

Added: trunk/main/lang/part/src/main/net/dpml/state/Action.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/Action.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/Action.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * Interface marking a a direct or implict actionable instance.
+ * 
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Action
+{
+   /**
+    * Return the action name.
+    * @return the name
+    */
+    String getName();
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/ApplyAction.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/ApplyAction.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/ApplyAction.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+import java.io.Serializable;
+
+/**
+ * Default implementation of delegating action.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ApplyAction implements Action, Serializable
+{
+    private final String m_id;
+    
+   /**
+    * Creation of a new apply action.
+    * @param id transition name
+    */
+    public ApplyAction( final String id )
+    {
+        if( null == id )
+        {
+            throw new NullPointerException( "id" );
+        }
+        m_id = id;
+    }
+    
+   /**
+    * Return the action name.
+    * @return the name
+    */
+    public String getName()
+    {
+        return "apply:"+ m_id;
+    }
+    
+   /**
+    * Return the id of the transition to apply.
+    * @return the transition id
+    */
+    public String getID()
+    {
+        return m_id;
+    }
+    
+   /**
+    * Compare this object to another for equality.
+    * @param other the other object
+    * @return true if the object is equal to this object
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        else if( other instanceof ApplyAction )
+        {
+            ApplyAction action = (ApplyAction) other;
+            return m_id.equals( action.getID() );
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Compute the hashcode for this instance.
+    * @return the hashcode value
+    */
+    public int hashCode()
+    {
+        return m_id.hashCode();
+    }
+
+   /**
+    * Return a string representation of the instance.
+    * @return the string value
+    */
+    public String toString()
+    {
+        return "apply:" + m_id;
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/ExecAction.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/ExecAction.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/ExecAction.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+import java.io.Serializable;
+
+/**
+ * Default implementation of delegating action.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ExecAction implements Action, Serializable
+{
+    private final String m_id;
+    
+   /**
+    * Creation of a new exec action.
+    * @param id operation name
+    */
+    public ExecAction( final String id )
+    {
+        if( null == id )
+        {
+            throw new NullPointerException( "id" );
+        }
+        m_id = id;
+    }
+    
+   /**
+    * Return the action name.
+    * @return the name
+    */
+    public String getName()
+    {
+        return "exec:" + m_id;
+    }
+    
+   /**
+    * Return the id of the transition to apply.
+    * @return the transition id
+    */
+    public String getID()
+    {
+        return m_id;
+    }
+    
+   /**
+    * Compare this object to another for equality.
+    * @param other the other object
+    * @return true if the object is equal to this object
+    */
+    public boolean equals( Object other )
+    {
+        if( null == other )
+        {
+            return false;
+        }
+        else if( other instanceof ExecAction )
+        {
+            ExecAction action = (ExecAction) other;
+            return m_id.equals( action.getID() );
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+   /**
+    * Compute the hashcode for this instance.
+    * @return the hashcode value
+    */
+    public int hashCode()
+    {
+        return m_id.hashCode();
+    }
+
+   /**
+    * Return a string representation of the instance.
+    * @return the string value
+    */
+    public String toString()
+    {
+        return "exec:" + m_id;
+    }
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/IntegrityRuntimeException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/IntegrityRuntimeException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/IntegrityRuntimeException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,55 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * Runtime exception thrown when an inconsitent state is encounted within a state-machine.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class IntegrityRuntimeException extends RuntimeException
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+   /**
+    * Construct a new <code>IntegrityRuntimeException</code> instance.
+    *
+    * @param message the exception message
+    */
+    public IntegrityRuntimeException( final String message )
+    {
+        this( message, null );
+    }
+
+   /**
+    * Construct a new <code>IntegrityRuntimeException</code> instance.
+    *
+    * @param message the exception message
+    * @param cause the causal exception
+    */
+    public IntegrityRuntimeException( final String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/state/Interface.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/Interface.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/Interface.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * An Interface action declares the classname of an interface 
+ * implemented by a component class that may be dynamically
+ * exposed by a component through the assocation of the interface 
+ * with an active state.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Interface extends Action
+{
+   /**
+    * Return the classname of a management interface implemented and
+    * potentially exposed by a component.
+    * @return the interface classname
+    */
+    String getClassname();
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/Operation.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/Operation.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/Operation.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * An operation defines the name of a bean style accessor that 
+ * may be invoked by a management application while the operation
+ * is exposed within the active path.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Operation extends Action
+{
+   /**
+    * Return the optional overriding method name.  If the 
+    * value returned is null the method shall be assumed to be the 
+    * equivalent of "get[Name]().
+    * @return the operation method name
+    */
+    String getMethodName();
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/State.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/State.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/State.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * Interface describing an application state.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface State
+{   
+   /**
+    * Constant artifact type for a state graph.
+    */
+    static final String TYPE = "state";
+     
+   /**
+    * Return the name of the state.
+    * @return the state name
+    */
+    String getName();
+    
+   /**
+    * Set the parent state. 
+    * @param state the parent state
+    */
+    void setParent( State state );
+
+   /**
+    * Return the parent state to this state or null if this is 
+    * the root of a state graph.
+    * @return the parent state
+    */
+    State getParent();
+    
+   /**
+    * Return the state path.  The path is composed of a sequence of 
+    * states from the root to this state.
+    * @return the state path
+    */
+    State[] getStatePath();
+    
+   /**
+    * Return the substates within this state.
+    * @return the substate array
+    */
+    State[] getStates();
+    
+   /**
+    * Return the array of triggers associated with the state.
+    * @return the trigger array
+    */
+    Trigger[] getTriggers();
+    
+   /**
+    * Return the array of transtions associated with the state.
+    * @return the transition array
+    */
+    Transition[] getTransitions();
+    
+   /**
+    * Return the array of operations associated with the state.
+    * @return the operation array
+    */
+    Operation[] getOperations();
+    
+   /**
+    * Return the array of management interfaces associated with 
+    * the state.
+    * @return the interfaces array
+    */
+    Interface[] getInterfaces();
+    
+   /**
+    * Test is the state is a terminal state.
+    * @return true if terminal
+    */
+    boolean isTerminal();
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/StateEvent.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/StateEvent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/StateEvent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,73 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+import java.util.EventObject;
+
+
+/**
+ * Event triggered as a result of a state change.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StateEvent extends EventObject
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    private final State m_from;
+    private final State m_to;
+
+   /**
+    * Construct a new <code>StateEvent</code>.
+    *
+    * @param source the source compoent model
+    * @param from the originating state
+    * @param to the new current state
+    */
+    public StateEvent( final Object source, State from, State to )
+    {
+        super( source );
+        m_from = from;
+        m_to = to;
+    }
+
+   /**
+    * Return the state that existed prior to the transition.
+    * @return the original state
+    */
+    public State getFromState()
+    {
+        return m_from;
+    }
+
+   /**
+    * Return the state that was established by a transition.
+    * @return the new current state
+    */
+    public State getToState()
+    {
+        return m_to;
+    }
+
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/state/StateListener.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/StateListener.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/StateListener.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,41 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.EventListener;
+
+/**
+ * Interface implementated by remote listeners to state change events.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface StateListener extends EventListener, Remote
+{
+   /**
+    * Notify the listener of a state change.
+    *
+    * @param event the state change event
+    * @exception RemoteException if a remote transport error occurs
+    */
+    void stateChanged( final StateEvent event ) throws RemoteException;
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/state/StateMachine.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/StateMachine.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/StateMachine.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * <p>Defintion of the state machine.  The state machine handles the maintenance 
+ * of a single current state and supports the invocation of transition and operations
+ * relative to the current state.  Invocation of transiton and operations are handled
+ * via two mechansims:</p>
+ *
+ * <ol>
+ *  <li>triggers</li>
+ *  <li>explicit invocation of the 'appply' and 'execute' operations</li>
+ * </ol>
+ *
+ * <p>Triggers, Transitions, and Operations may be declared within any state and enter
+ * active scope when when the enclosing state is within the current state path
+ * (where the current state path is the sequence of state's from the current state to  
+ * the root state).</p>
+ *
+ * <p>Transitions and operations available at any given time are a function of 
+ * all uniquely named transitions and operations exposed within the current state path.
+ * If multiple instances of a transition or operation share the same name, the instance
+ * closest to the current state takes precedence and the duplicate instance will not be 
+ * exposed (equivalent to overriding the characteristics of a super-state).
+ *
+ * <p>Triggers are structures that hold a single action (transition or operation) and 
+ * are invoked automatically by a state machine implementation as a part of initialization
+ * and termination requests. If a trigger contains a transition resulting that results in 
+ * a change to the current state a state-machine will recursively evaluate triggers in the 
+ * new current state path.  The process of recursive evaluation of triggers will continue
+ * until a state is reached where no further trigger invocation is possible.</p>
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface StateMachine
+{
+   /**
+    * Add a property change listener to the state machine.
+    * @param listener the property change listener
+    */
+    //void addPropertyChangeListener( final PropertyChangeListener listener );
+    
+   /**
+    * Remove a property change listener from the state machine.
+    * @param listener the property change listener
+    */
+    //void removePropertyChangeListener( final PropertyChangeListener listener );
+    
+   /**
+    * Add a state change listener to the state machine.
+    * @param listener the state listener
+    */
+    void addStateListener( final StateListener listener );
+    
+   /**
+    * Remove a state listener from the state machine.
+    * @param listener the state listener
+    */
+    void removeStateListener( final StateListener listener );
+
+   /**
+    * Return the current state.
+    * @return the current state
+    */
+    State getState();
+    
+   /**
+    * Invoke initialization of the supplied object using the initialization action
+    * declared under the current state path.
+    * 
+    * @param object the object to initialize
+    * @return the state established as a side-effect of initialization
+    * @exception InvocationTargetException if an invocation error occurs as a 
+    *   result of initialization
+    */
+    State initialize( Object object ) throws InvocationTargetException;
+    
+   /**
+    * Execute a named operation on the supplied object.
+    * @param name an operation name
+    * @param object the target object
+    * @param args operation argument array
+    * @return the return value
+    * @exception UnknownOperationException if the operation is unknown
+    * @exception InvocationTargetException if an invocation error occurs as a 
+    *   result of operation execution
+    */
+    Object execute( String name, Object object, Object[] args ) 
+      throws UnknownOperationException, InvocationTargetException;
+    
+   /**
+    * Invoke a management method on the supplied object.
+    * @param object the target object
+    * @param method the method name
+    * @param args method parameter arguments
+    * @return the return value
+    * @exception IllegalStateException if the method is recognized but not available
+    * @exception UnknownOperationException if the operation is unknown
+    * @exception InvocationTargetException if an invocation error occurs as a 
+    *   result of operation execution
+    */
+    Object invoke( Object object, String method, Object[] args ) 
+      throws UnknownOperationException, InvocationTargetException, IllegalStateException;
+    
+   /**
+    * Apply a named state transition.
+    * @param name the transition name
+    * @param object the object against which any transition handler action are to be applied
+    * @return the state established by the application of the transition
+    * @exception UnknownTransitionException if the transition is unknown
+    * @exception InvocationTargetException if an invocation error occurs as a 
+    *   result of transition invocation
+    */
+    State apply( String name, Object object ) 
+      throws UnknownTransitionException, InvocationTargetException;
+    
+   /**
+    * Return all of the available transitions relative to the current state.
+    * @return the available transitions
+    */
+    Transition[] getTransitions();
+    
+   /**
+    * Return all of the available operations relative to the current state.
+    * @return the available operations
+    */
+    Operation[] getOperations();
+    
+   /**
+    * Return all of the available interfaces relative to the current state.
+    * @return the available interface declarations
+    */
+    Interface[] getInterfaces();
+    
+   /**
+    * Invoke termination of the supplied object using the termination action
+    * declared under the current state path.
+    * 
+    * @param object the object to terminate
+    * @return the state established as a side-effect of the termination
+    */
+    State terminate( Object object );
+
+   /**
+    * Returns the active status of the state machine.
+    * @return TRUE if the state machine has invoked initialization and 
+    * termination has not been performed otherwise FALSE
+    */
+    boolean isActive();
+    
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/Transition.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/Transition.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/Transition.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * Interface describing a transition that may be performed under an activate 
+ * state.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Transition extends Action
+{  
+   /**
+    * Set the state that this transition is a part of.
+    * @param state the owning state
+    */
+    void setState( State state );
+    
+   /**
+    * Return the state that this transition is a part of.
+    * @return the owning state
+    */
+    State getState();
+    
+   /**
+    * Return the transition target state name
+    * @return the target state name
+    */
+    String getTargetName();
+    
+   /**
+    * Return an operation associated with the transition.
+    * @return a possibly null operation
+    */
+    Operation getOperation();
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/Trigger.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/Trigger.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/Trigger.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * Interface describing a condition within which an action may be invoked.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Trigger
+{
+   /**
+    * Return the event enumneration that this trigger is associated with.
+    * @return the triggering event class
+    */
+    TriggerPolicy getPolicy();
+    
+   /**
+    * Return the actions  that this trigger initiates.
+    * @return the triggered action
+    */
+    Action getAction();
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/TriggerPolicy.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/TriggerPolicy.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/TriggerPolicy.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * Interface describing a condition within which an action may be invoked.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public enum TriggerPolicy
+{
+   /**
+    * Initialization event emumeration.
+    */
+    INITIALIZATION,
+
+   /**
+    * Termination event emumeration.
+    */
+    TERMINATION;
+}

Added: trunk/main/lang/part/src/main/net/dpml/state/UnknownOperationException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/UnknownOperationException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/UnknownOperationException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,46 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * Exception thrown when a request is made for retrival of an operation 
+ * via an operation key and the key is unresolvable.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class UnknownOperationException extends Exception
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+   /**
+    * Construct a new <code>UnknownOperationException</code> instance.
+    *
+    * @param key the operation key
+    */
+    public UnknownOperationException( final String key )
+    {
+        super( key );
+    }
+
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/state/UnknownTransitionException.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/UnknownTransitionException.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/UnknownTransitionException.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,48 @@
+/* 
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * Exception thrown when a request is made to apply a transition that is unknown
+ * relative to the target state.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class UnknownTransitionException extends Exception
+{
+   /**
+    * Serial version identifier.
+    */
+    static final long serialVersionUID = 1L;
+
+    private String m_transition;
+
+   /**
+    * Construct a new <code>UnknownTransitionException</code> instance.
+    *
+    * @param transition the transition name
+    */
+    public UnknownTransitionException( final String transition )
+    {
+        super( transition );
+    }
+
+}
+

Added: trunk/main/lang/part/src/main/net/dpml/state/package-info.java
===================================================================
--- trunk/main/lang/part/src/main/net/dpml/state/package-info.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/main/net/dpml/state/package-info.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * States, transitons, operations and triggers and a state machine supporting 
+ * orderly management of state transitions and dynamic operations.
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+package net.dpml.state;

Added: trunk/main/lang/part/src/test/META-INF/services/org.acme.Gizmo
===================================================================
--- trunk/main/lang/part/src/test/META-INF/services/org.acme.Gizmo	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/META-INF/services/org.acme.Gizmo	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1 @@
+org.acme.GizmoAdapter

Added: trunk/main/lang/part/src/test/META-INF/services/org.acme.Widget
===================================================================
--- trunk/main/lang/part/src/test/META-INF/services/org.acme.Widget	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/META-INF/services/org.acme.Widget	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1 @@
+org.acme.StandaloneWidgetAdapter

Added: trunk/main/lang/part/src/test/Widget.java
===================================================================
--- trunk/main/lang/part/src/test/Widget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/Widget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Sample object used in test case. 
+ */
+public class Widget
+{
+}
\ No newline at end of file

Added: trunk/main/lang/part/src/test/dpml/lang/AbstractTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/dpml/lang/AbstractTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/dpml/lang/AbstractTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2005-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * AbstractEncodingTestCase.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public abstract class AbstractTestCase extends TestCase
+{
+   /**
+    * Utility operation to encode and decode an supplied object using an intermidiate file.
+    * @param object the object to enciode
+    * @return the result of decoding the encoded structure
+    * @exception Exception if an error occurs
+    */
+    public Object executeEncodingTest( Object object ) throws Exception
+    {
+        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
+        ObjectOutputStream output = new ObjectOutputStream( byteOutputStream );
+        output.writeObject( object );
+        output.close();
+
+        ByteArrayInputStream byteInputStream = new ByteArrayInputStream( byteOutputStream.toByteArray() );
+        ObjectInputStream input = new ObjectInputStream( byteInputStream );
+        Object serialized = input.readObject();
+        input.close();
+
+        assertTrue( "!=", object != serialized ); // Ensure this is not the same instance
+        assertEquals( "equals", object, serialized );
+        assertEquals( "hash", object.hashCode(), serialized.hashCode() );
+        
+        return serialized;
+    }
+
+}

Added: trunk/main/lang/part/src/test/dpml/lang/ConstructTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/dpml/lang/ConstructTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/dpml/lang/ConstructTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.awt.Color;
+import java.io.File;
+import java.util.Date;
+import java.util.Map;
+import java.util.Hashtable;
+import java.util.Arrays;
+
+import dpml.lang.Value;
+
+/**
+ * Construct testcase.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ConstructTestCase extends AbstractTestCase
+{
+    public void setUp()
+    {
+        ClassLoader loader = ConstructTestCase.class.getClassLoader();
+        Thread.currentThread().setContextClassLoader( loader );
+    }
+    
+   /**
+    * Test creation of a simple construct.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testSimpleConstruct() throws Exception
+    {
+        Construct construct = new Construct( "fred" );
+        Object value = construct.resolve();
+        if( null == value )
+        {
+            throw new NullPointerException( "value" );
+        }
+        assertEquals( "isa-string", value.getClass(), String.class );
+        assertEquals( "simple construct value", value, "fred" );
+    }
+
+   /**
+    * Test creation of a construct using a null value.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testNullArgConstruct() throws Exception
+    {
+        Construct construct = new Construct( Date.class.getName(), (String) null );
+        Object value = construct.resolve();
+        assertEquals( "isa-data", value.getClass(), Date.class );
+    }
+
+   /**
+    * Test creation of a construct using a primitive type.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testPrimitiveConstruct() throws Exception
+    {
+        Construct construct = new Construct( "int", "10" );
+        ClassLoader cl = ConstructTestCase.class.getClassLoader();
+        Object value = construct.resolve();
+        assertEquals( "isa-Integer", Integer.class, value.getClass() );
+    }
+
+   /**
+    * Test creation of a construct using a single typed argument.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testSingleArgConstruct() throws Exception
+    {
+        Construct construct = new Construct( File.class.getName(), "abc" );
+        Object value = construct.resolve();
+        assertEquals( "isa-file", value.getClass(), File.class );
+        assertEquals( "file", value, new File( "abc" ) );
+    }
+
+   /**
+    * Test creation of a construct using a multiple primitate arguments.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testPrimitiveMultiArgConstruct() throws Exception
+    {
+        Value a = new Construct( "int", "100" );
+        Value b = new Construct( "boolean", "true" );
+        Value c = new Construct( Context2.class.getName(), new Value[]{a, b} );
+        Object value = c.resolve();
+        assertEquals( "isa-context", value.getClass(), Context2.class );
+        Context2 context = (Context2) value;
+        if( !( context.getNumber() == 100 ) )
+        {
+            System.out.println( "# number: " + context.getNumber() );
+            fail( "context2 number return value is not 100" );
+        }
+        if( !context.getLogical() )
+        {
+            System.out.println( "# logical: " + context.getLogical() );
+            fail( "context2 logical return value is not 'true'" );
+        }
+    }
+    
+   /**
+    * Test creation of a construct using a static method operator.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testStaticMethod() throws Exception
+    {
+        Value v = new Construct( Context2.class.getName(), "create", new Value[0] );
+        Object value = v.resolve();
+        assertEquals( "isa-context", value.getClass(), Context2.class );
+        Context2 context = (Context2) value;
+        if( !( context.getNumber() == 100 ) )
+        {
+            System.out.println( "# number: " + context.getNumber() );
+            fail( "context2 number return value is not 100" );
+        }
+        if( !context.getLogical() )
+        {
+            System.out.println( "# logical: " + context.getLogical() );
+            fail( "context2 logical return value is not 'true'" );
+        }
+    }
+    
+   /**
+    * Test creation of a construct using a static field operator.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testStaticField() throws Exception
+    {
+        Value v = new Construct( Color.class.getName(), "RED", (String) null );
+        Object value = v.resolve();
+        assertEquals( "color", Color.RED, value );
+    }
+
+   /**
+    * Test creation of a composite construct using a static field operator.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testStaticFieldInComposite() throws Exception
+    {
+        Value v = new Construct( Color.class.getName(), "RED", new Value[0] );
+        Object value = v.resolve();
+        assertEquals( "color", Color.RED, value );
+    }
+
+   /**
+    * Test creation of a construct using a symbolic reference.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testSymbolicReference() throws Exception
+    {
+        Map<String, Object> map = new Hashtable<String, Object>();
+        File file = new File( "somewhere" );
+        map.put( "test", file );
+        Value construct = new Construct( "${test}" );
+        Object value = construct.resolve( map );
+        assertEquals( "value", file, value );
+    }
+    
+   /**
+    * Test creation of a construct using a typed symbolic reference.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testTypedSymbolicReference() throws Exception
+    {
+        Map<String, Object> map = new Hashtable<String, Object>();
+        map.put( "number", new Integer( 100 ) );
+        map.put( "logical", new Boolean( true ) );
+        
+        Value number = new Construct( "int", "${number}" );
+        Value logical = new Construct( "boolean", "${logical}" );
+        Value construct = new Construct( Context2.class.getName(), new Value[]{number, logical} );
+        Object value = construct.resolve( map );
+        
+        assertEquals( "isa-context", value.getClass(), Context2.class );
+        Context2 context = (Context2) value;
+        if( !( context.getNumber() == 100 ) )
+        {
+            System.out.println( "# number: " + context.getNumber() );
+            fail( "context2 number return value is not 100" );
+        }
+        if( !context.getLogical() )
+        {
+            System.out.println( "# logical: " + context.getLogical() );
+            fail( "context2 logical return value is not true" );
+        }
+    }
+    
+   /**
+    * Test array return type.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testSimpleArray() throws Exception
+    {
+        String[] args = new String[]{"aaa", "bbb"};
+        Value s1 = new Construct( "aaa" );
+        Value s2 = new Construct( "bbb" );
+        Value construct = new Construct( args.getClass().getName(), new Value[]{s1, s2} );
+        String[] result = (String[]) construct.resolve();
+        boolean equal = Arrays.equals( args, result );
+        assertTrue( "simple-array", equal );
+    }
+    
+   /**
+    * Test array with zero entries.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testZeroLengthArray() throws Exception
+    {
+        String[] args = new String[0];
+        Value construct = new Construct( args.getClass().getName(), new Value[0] );
+        String[] result = (String[]) construct.resolve();
+        boolean equal = Arrays.equals( args, result );
+        assertTrue( "zero-length-array", equal );
+    }
+    
+   /**
+    * Test creation of a simple construct.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testArrayAsCompositeArgument() throws Exception
+    {
+        Construct a = new Construct( "Hello " );
+        Construct b = new Construct( "World!" );
+        Construct array = new Construct( String[].class.getName(), new Value[]{a, b} );
+        Construct construct = new Construct( Demo.class.getName(), new Value[]{array} );
+        Demo demo = (Demo) construct.resolve();
+        assertNotNull( "demo", demo );
+    }
+    
+   /**
+    * Test creation of a simple construct.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testPrimitiveArray() throws Exception
+    {
+        int[] args = new int[]{1, 2, 3};
+        Value p1 = new Construct( "int", "1" );
+        Value p2 = new Construct( "int", "2" );
+        Value p3 = new Construct( "int", "3" );
+        Value construct = new Construct( "int[]", new Value[]{p1, p2, p3} );
+        Object result = construct.resolve();
+        int[] array = (int[]) construct.resolve();
+        boolean equal = Arrays.equals( args, array );
+        assertTrue( "primitive-array", equal );
+    }
+
+   /**
+    * Test construct encoding.
+    * @exception Exception if an unexpected error occurs.
+    */
+    public void testEncoding() throws Exception
+    {
+        Value number = new Construct( "int", "${number}" );
+        Value logical = new Construct( "boolean", "${logical}" );
+        Value construct = new Construct( Context2.class.getName(), new Value[]{number, logical} );
+        Value result = (Value) executeEncodingTest( construct );
+        assertEquals( "encoding", construct, result );
+    }
+
+   /**
+    * Test class.
+    */
+    public static class Demo
+    {
+       /**
+        * Create a new demo class.
+        * @param args the args
+        */
+        public Demo( String[] args )
+        {
+            for( int i=0; i<args.length; i++ )
+            {
+                System.out.print( args[i] );
+            }
+            System.out.println( "" );
+        }
+    }
+    
+   /**
+    * Mock class.
+    */
+    public static class Context 
+    {
+        private File m_a;
+        private File m_b;
+
+       /**
+        * Creation of a mock composite argument object.
+        * @param a the primary argument
+        * @param b the secondary argument
+        */
+        public Context( File a, File b )
+        {
+            m_a = a;
+            m_b = b;
+        }
+
+       /**
+        * Return the primary argument.
+        * @return the primary argument value
+        */
+        public File getA()
+        {
+            return m_a;
+        }
+
+       /**
+        * Return the secondary argument.
+        * @return the secondary argument value
+        */
+        public File getB()
+        {
+            return m_b;
+        }
+    }
+
+   /**
+    * Another mock class.
+    */
+    public static class Context2 
+    {
+        private int m_number;
+        private boolean m_logical;
+        
+       /**
+        * Static constructor method.
+        * @return an instance
+        */
+        public static Context2 create()
+        {
+            return new Context2( 100, true );
+        }
+
+       /**
+        * Creation of a mock object using primiative arguments.
+        * @param number a primitive number
+        * @param logical a boolean value
+        */
+        public Context2( int number, boolean logical )
+        {
+            m_number = number;
+            m_logical = logical;
+        }
+
+       /**
+        * Return the number.
+        * @return the number
+        */
+        public int getNumber()
+        {
+            return m_number;
+        }
+
+       /**
+        * Return the boolean.
+        * @return the boolean
+        */
+        public boolean getLogical()
+        {
+            return m_logical;
+        }
+    }
+}

Added: trunk/main/lang/part/src/test/dpml/lang/ContextTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/dpml/lang/ContextTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/dpml/lang/ContextTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dpml.lang;
+
+import java.awt.Color;
+import java.net.URI;
+import java.util.Hashtable;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+//import net.dpml.lang.Plugin;
+import net.dpml.lang.ServiceRegistry;
+import net.dpml.lang.SimpleServiceRegistry;
+
+import org.acme.Sample;
+import org.acme.Sample.Context;
+import org.acme.Sample.AnotherContext;
+import org.acme.Sample.Negation;
+
+/**
+ * Context test case.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ContextTestCase extends TestCase
+{
+   /**
+    * Test the isaContext implementation for strict evaluation
+    * of the org.acme.Sample.Context class.
+    * @exception Exception if a test error occurs
+    */
+    public void testIsaContextUsingStrictAssessment() throws Exception
+    {
+        boolean foo = ContextInvocationHandler.isaContext( Context.class, true );
+        assertEquals( "isa-context", false, foo );
+    }
+
+   /**
+    * Test the isaContext implementation for non-strict evaluation
+    * of the org.acme.Sample.Context class.
+    * @exception Exception if a test error occurs
+    */
+    public void testIsaContextUsingLegacyAssessment() throws Exception
+    {
+        boolean foo = ContextInvocationHandler.isaContext( Context.class, false );
+        assertEquals( "isa-context", true, foo );
+    }
+
+   /**
+    * Test the isaContext implementation for negation using the 
+    * org.acme.Sample.Negation.Context class.
+    * @exception Exception if a test error occurs
+    */
+    public void testIsaContextNegation() throws Exception
+    {
+        boolean foo = ContextInvocationHandler.isaContext( Negation.Context.class, true );
+        assertEquals( "isa-context-negation", false, foo );
+    }
+
+   /**
+    * Test missing context entry detection.
+    * @exception Exception if a test error occurs
+    */
+    public void testMissingRequiredEntry() throws Exception
+    {
+        try
+        {
+            Hashtable<String,Object > map = new Hashtable<String,Object>();
+            ContextInvocationHandler.validate( Context.class, map );
+            fail( "Did not throw IllegalArgumentException for missing key 'message'." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // success
+        }
+    }
+
+   /**
+    * Test null value for an entry detection.
+    * @exception Exception if a test error occurs
+    */
+    public void testNullEntryValue() throws Exception
+    {
+        try
+        {
+            HashMap<String,Object> map = new HashMap< String,Object>();
+            map.put( "message", null );
+            ContextInvocationHandler.validate( Context.class, map );
+            fail( "Did not throw IllegalArgumentException for null value" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // success
+        }
+    }
+
+   /**
+    * Test missing required entry detection.
+    * @exception Exception if a test error occurs
+    */
+    public void testSimpleRequiredEntry() throws Exception
+    {
+        Hashtable<String,Object> map = new Hashtable<String,Object>();
+        map.put( "message", MESSAGE );
+        Context context = 
+          ContextInvocationHandler.getProxiedInstance( Context.class, map );
+        assertEquals( "message", MESSAGE, context.getMessage() );
+    }
+
+   /**
+    * Test optional entry processing.
+    * @exception Exception if a test error occurs
+    */
+    public void testSimpleOptionalEntry() throws Exception
+    {
+        Hashtable<String,Object> map = new Hashtable<String,Object>();
+        map.put( "message", MESSAGE );
+        map.put( "resourceURI", RESOURCE );
+        Context context = 
+          ContextInvocationHandler.getProxiedInstance( Context.class, map );
+        assertEquals( "resourceURI", RESOURCE, context.getResourceURI( null ) );
+    }
+    
+   /**
+    * Test compound optional entry processing.
+    * @exception Exception if a test error occurs
+    */
+    public void testCompoundOptionalEntry() throws Exception
+    {
+        Hashtable<String,Object> external = new Hashtable<String,Object>();
+        external.put( "color", Color.RED );
+        Hashtable<String,Object> map = new Hashtable<String,Object>();
+        map.put( "message", MESSAGE );
+        map.put( "external", external );
+        Context context = 
+          ContextInvocationHandler.getProxiedInstance( Context.class, map );
+        AnotherContext ext = context.getExternal( null );
+        assertEquals( "color", Color.RED, ext.getColor( null ) );
+    }
+    
+   /**
+    * Test instantiation of a class referencing a context parameter.
+    * @exception Exception if a test error occurs
+    */
+    //public void testPluginInstantiation() throws Exception
+    //{
+    //    Hashtable<String,Object> external = new Hashtable<String,Object>();
+    //    external.put( "color", Color.RED );
+    //    Hashtable<String,Object> map = new Hashtable<String,Object>();
+    //    map.put( "message", MESSAGE );
+    //    map.put( "resourceURI", RESOURCE );
+    //    map.put( "external", external );
+    //    Context context = 
+    //      ContextInvocationHandler.getProxiedInstance( Context.class, map );
+    //    ServiceRegistry registry = new SimpleServiceRegistry( context );
+    //    Plugin plugin = new Plugin( Sample.class );
+    //    plugin.initialize( registry );
+    //    Sample sample = plugin.getInstance( Sample.class );
+    //}
+    
+    private static final String MESSAGE = "Hello.";
+    private static final URI RESOURCE = setupURI();
+    
+    private static URI setupURI()
+    {
+        try
+        {
+            return ContextTestCase.class.getProtectionDomain().getCodeSource().getLocation().toURI();
+        }
+        catch( Throwable e )
+        {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/AbstractTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/AbstractTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/AbstractTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2007 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import net.dpml.lang.Strategy;
+import net.dpml.lang.TypeCastException;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class AbstractTestCase extends TestCase
+{
+    static
+    {
+        System.setProperty( 
+          "handler:dpml:metro", 
+          "net.dpml.runtime.ComponentStrategyHandler" );
+    }
+    
+    protected <T>T load( Class<T> type, String path ) throws Exception
+    {
+        return load( type, path, null );
+    }
+    
+    protected <T>T load( Class<T> type, String path, String name ) throws Exception
+    {
+        ClassLoader classloader = getClass().getClassLoader();
+        File dir = new File( System.getProperty( "project.test.dir" ) );
+        File file = new File( dir, path );
+        try
+        {
+            Strategy strategy = Strategy.load( classloader, null, file.toURI(), name );
+            return strategy.getContentForClass( type );
+        }
+        catch( TypeCastException e )
+        {
+            String report = e.getReport();
+            System.out.println( report );
+            throw e;
+        }
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/composition/CompositeTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/composition/CompositeTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/composition/CompositeTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.composition;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import org.acme.CompositeComponent;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class CompositeTestCase extends AbstractTestCase
+{
+    public void testComponent() throws Exception
+    {
+        CompositeComponent component = 
+          load( CompositeComponent.class, "composite.xml", "composite" );
+        assertNotNull( "widget", component.getParts().getWidget() );
+        assertNotNull( "gizmo", component.getParts().getGizmo() );
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/composition/ControllerTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/composition/ControllerTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/composition/ControllerTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.composition;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import org.acme.ControllerComponent;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ControllerTestCase extends AbstractTestCase
+{
+    public void testComponent() throws Exception
+    {
+        ControllerComponent component = 
+          load( ControllerComponent.class, "controller.xml", "controller" );
+          
+        assertNotNull( "widget", component.getParts().getWidget() );
+        assertNotNull( "gizmo", component.getParts().getGizmo() );
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/composition/GenericTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/composition/GenericTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/composition/GenericTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.composition;
+
+import java.awt.Color;
+import java.io.File;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import net.dpml.runtime.Provider;
+import net.dpml.runtime.Component;
+
+import org.acme.Widget;
+import org.acme.Gizmo;
+import org.acme.GenericComponent;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class GenericTestCase extends AbstractTestCase
+{
+    public void testComponent() throws Exception
+    {
+        GenericComponent component = 
+          load( GenericComponent.class, "generics.xml", "generic" );
+          
+        assertNotNull( "widget", component.getParts().getWidget( Provider.class ) );
+        assertNotNull( "gizmo", component.getParts().getGizmo( Component.class ) );
+        Component c = component.getParts().getWidget( Component.class );
+        Provider provider = c.getProvider();
+        Widget w1 = provider.getInstance( Widget.class );
+        Widget w2 = component.getParts().getWidget( Widget.class );
+        assertEquals( "equality", w1, w2 );
+        Gizmo gizmo = component.getParts().getGizmo( Gizmo.class );
+        int number = gizmo.getNumber();
+        assertEquals( "gizmo", 42, number );
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/composition/LookupTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/composition/LookupTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/composition/LookupTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.composition;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import org.acme.CompositeComponent;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class LookupTestCase extends AbstractTestCase
+{
+    public void testComponent() throws Exception
+    {
+        CompositeComponent component = 
+          load( CompositeComponent.class, "lookup.xml", "lookup" );
+        
+        assertNotNull( "widget", component.getParts().getWidget() );
+        assertNotNull( "gizmo", component.getParts().getGizmo() );
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/composition/SelectTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/composition/SelectTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/composition/SelectTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.composition;
+
+import net.dpml.runtime.Provider;
+import net.dpml.runtime.Component;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import org.acme.SelectComponent;
+import org.acme.Widget;
+import org.acme.Gizmo;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class SelectTestCase extends AbstractTestCase
+{
+    public void testSelectionByServiceReturnType() throws Exception
+    {
+        SelectComponent.Parts parts = getParts();
+        Widget[] widgets = parts.getWidgets();
+        assertEquals( "size-widget", 2, widgets.length );
+    }
+    
+    public void testSelectionByServiceCriteria() throws Exception
+    {
+        SelectComponent.Parts parts = getParts();
+        Provider[] providers = parts.getProviders( Widget.class );
+        assertEquals( "size-providers", 2, providers.length );
+        Component[] components = parts.getComponents( Widget.class );
+        assertEquals( "size-providers", 2, components.length );
+        Component[] gizmos = parts.getComponents( Gizmo.class );
+        assertEquals( "gizmos", 1, gizmos.length );
+        Provider[] gizmoProviders = parts.getProviders( Gizmo.class );
+        assertEquals( "gizmo-providers", 1, gizmoProviders.length );
+    }
+    
+    public void testAllSelectionCriteria() throws Exception
+    {
+        SelectComponent.Parts parts = getParts();
+        Component[] all = parts.getAllComponents();
+        assertEquals( "size-all", 3, all.length );
+    }
+    
+    private SelectComponent.Parts getParts() throws Exception
+    {
+        SelectComponent component = 
+          load( SelectComponent.class, "select.xml", "select" );
+        return component.getParts();
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/context/ArrayTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/context/ArrayTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/context/ArrayTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.context;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import org.acme.ArrayWidget;
+import org.acme.Widget;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ArrayTestCase extends AbstractTestCase
+{
+    public void testEquality() throws Exception
+    {
+        ArrayWidget widget = 
+          load( ArrayWidget.class, "array.xml", "array" );
+        
+        char[] chars = new char[]{ 'h','e','l','l','o'};
+        char[] result = widget.getContext().getMessage();
+        assertEquals( "length", chars.length, result.length );
+        for( int i=0; i<chars.length; i++ )
+        {
+            String assertion = "character-" + i;
+            assertEquals( assertion, chars[i], result[i] );
+        }
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/context/ContextualTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/context/ContextualTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/context/ContextualTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.context;
+
+import java.awt.Color;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import org.acme.ContextualWidget;
+import org.acme.Widget;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ContextualTestCase extends AbstractTestCase
+{
+    public void testEquality() throws Exception
+    {
+        ContextualWidget widget = 
+          load( ContextualWidget.class, "contextual.xml", "contextual" );
+    
+        assertEquals( "message", "Batman", widget.getMessage() );
+        assertEquals( "primary", Color.RED, widget.getPrimary() );
+        assertEquals( "secondary", Color.BLUE, widget.getSecondary() );
+        assertEquals( "numbers.length", 3, widget.getNumbers().length );
+        assertEquals( "numbers[0]", 1, widget.getNumbers()[0] );
+        assertEquals( "numbers[1]", 2, widget.getNumbers()[1] );
+        assertEquals( "numbers[2]", 3, widget.getNumbers()[2] );
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/isolation/SampleTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/isolation/SampleTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/isolation/SampleTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.isolation;
+
+import java.lang.reflect.Proxy;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import org.acme.DefaultWidget;
+import org.acme.Widget;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class SampleTestCase extends AbstractTestCase
+{
+    public void testNormalUsage() throws Exception
+    {
+        Widget widget = 
+          load( Widget.class, "component.xml", "normal" );
+
+        String message = widget.getMessage();
+        assertEquals( "message", "Hello", message );
+    }
+    
+    public void testNoIsolation() throws Exception
+    {
+        Widget widget = 
+          load( DefaultWidget.class, "component.xml", "isolation" );
+        assertFalse( "isa-proxy", Proxy.isProxyClass( widget.getClass() ) );
+    }
+
+    public void testWithIsolation() throws Exception
+    {
+        Widget widget = 
+          load( Widget.class, "component.xml", "no-isolation" );
+        assertTrue( "isa-proxy", Proxy.isProxyClass( widget.getClass() ) );
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/lifecycle/StateTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/lifecycle/StateTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/lifecycle/StateTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+package net.dpml.runtime.lifecycle;
+
+import java.util.concurrent.TimeUnit;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import net.dpml.runtime.Component;
+import net.dpml.runtime.Provider;
+
+import org.acme.StateWidget;
+import org.acme.Widget;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StateTestCase extends AbstractTestCase
+{
+    public void testLifecycle() throws Exception
+    {
+        Component component = load( Component.class, "state.xml", "state" );
+        Provider provider = component.getProvider();
+        StateWidget widget = provider.getInstance( StateWidget.class );
+        assertEquals( "started", 1, widget.getState() );
+        component.release( provider );
+        component.terminate();
+        assertEquals( "stopped", 2, widget.getState() );
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/SingletonTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/SingletonTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/SingletonTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.lifestyle;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import net.dpml.runtime.Component;
+
+import org.acme.SingletonWidget;
+import org.acme.Widget;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class SingletonTestCase extends AbstractTestCase
+{
+    public void testEquality() throws Exception
+    {
+        Component component = load( Component.class, "singleton.xml", "singleton" );
+        Widget w1 = component.getProvider().getInstance( SingletonWidget.class );
+        Widget w2 = component.getProvider().getInstance( SingletonWidget.class );
+        assertEquals( "equality", w1, w2 );
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/TransientTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/TransientTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/lifestyle/TransientTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.lifestyle;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import net.dpml.runtime.Component;
+
+import org.acme.DefaultWidget;
+import org.acme.Widget;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class TransientTestCase extends AbstractTestCase
+{
+    public void testEquality() throws Exception
+    {
+        Component component = load( Component.class, "transient.xml", "transient" );
+        Widget w1 = component.getProvider().getInstance( DefaultWidget.class );
+        Widget w2 = component.getProvider().getInstance( DefaultWidget.class );
+        if( w1 == w2 )
+        {
+            fail( "transients" );
+        }
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/profile/ProfileTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/profile/ProfileTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/profile/ProfileTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.profile;
+
+import java.util.ServiceLoader;
+
+import junit.framework.TestCase;
+
+import org.acme.Widget;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ProfileTestCase extends TestCase
+{
+    public void testServiceLoading() throws Exception
+    {
+        Widget widget = getWidget();
+        assertNotNull( "widget", widget );
+        String message = widget.getMessage();
+        assertEquals( "message", "Batman", message );
+    }
+    
+    public Widget getWidget() throws Exception
+    {
+        ServiceLoader<Widget> loaders = ServiceLoader.load( Widget.class );
+        for( Widget widget : loaders )
+        {
+            return widget;
+        }
+        return null;
+    }
+}

Added: trunk/main/lang/part/src/test/net/dpml/runtime/service/ForeignTestCase.java
===================================================================
--- trunk/main/lang/part/src/test/net/dpml/runtime/service/ForeignTestCase.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/net/dpml/runtime/service/ForeignTestCase.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.runtime.service;
+
+import net.dpml.runtime.AbstractTestCase;
+
+import net.dpml.lang.Strategy;
+
+import org.acme.Widget;
+import org.acme.ForeignWidget;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ForeignTestCase extends AbstractTestCase
+{
+    public void testComponentViaPart() throws Exception
+    {
+        Widget widget = load( Widget.class, "foreign.xml", "foreign" );
+        assertEquals( "message", "42", widget.getMessage() );
+    }
+    
+    public void testComponentViaClass() throws Exception
+    {
+        Strategy strategy = Strategy.load( ForeignWidget.class, null, "foreign" );
+        Widget widget = strategy.getContentForClass( Widget.class );
+        assertEquals( "message", "42", widget.getMessage() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/ArrayWidget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/ArrayWidget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/ArrayWidget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.annotation.Services;
+
+import net.dpml.util.Logger;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ArrayWidget implements Widget
+{
+    public interface Context
+    {
+        char[] getMessage();
+    }
+    
+    private Context m_context;
+    
+    public ArrayWidget( Logger logger, Context context )
+    {
+        m_context = context;
+        logger.info( getMessage() );
+    }
+    
+    public String getMessage()
+    {
+        return new String( m_context.getMessage() );
+    }
+    
+    public Context getContext()
+    {
+        return m_context;
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/CompositeComponent.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/CompositeComponent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/CompositeComponent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.util.Logger;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class CompositeComponent
+{
+    public interface Parts
+    {
+        Widget getWidget();
+        Gizmo getGizmo();
+    }
+    
+    private final Parts m_parts;
+    
+    public CompositeComponent( Logger logger, Parts parts )
+    {
+        logger.info( "instantiated" );
+        m_parts = parts;
+    }
+    
+    public Parts getParts()
+    {
+        return m_parts;
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/ContextualWidget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/ContextualWidget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/ContextualWidget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.awt.Color;
+
+import static net.dpml.annotation.LifestylePolicy.TRANSIENT;
+
+import net.dpml.annotation.Component;
+import net.dpml.annotation.Services;
+
+import net.dpml.util.Logger;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Component
+ at Services( Widget.class )
+public class ContextualWidget implements Widget
+{
+    public interface Context
+    {
+        String getMessage( String value );
+        ColorManager getColors();
+        int[] getNumbers();
+    }
+    
+    private final Context m_context;
+    
+    public ContextualWidget( Logger logger, Context context )
+    {
+        logger.info( "instantiated" );
+        m_context = context;
+    }
+    
+    public String getMessage()
+    {
+        return m_context.getMessage( "Hello" );
+    }
+    
+    public Color getPrimary()
+    {
+        return m_context.getColors().getPrimary();
+    }
+    
+    public Color getSecondary()
+    {
+        return m_context.getColors().getSecondary();
+    }
+    
+    public int[] getNumbers()
+    {
+        return m_context.getNumbers();
+    }
+    
+    @net.dpml.annotation.Context
+    public interface ColorManager
+    {
+        Color getPrimary();
+        Color getSecondary();
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/ControllerComponent.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/ControllerComponent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/ControllerComponent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.annotation.Parts;
+
+import net.dpml.runtime.Component;
+import net.dpml.runtime.Provider;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ControllerComponent
+{
+    @Parts
+    public interface ControllerParts
+    {
+        Component getWidget();
+        Provider getGizmo();
+    }
+    
+    private final ControllerParts m_parts;
+    
+    public ControllerComponent( ControllerParts parts )
+    {
+        m_parts = parts;
+    }
+    
+    public ControllerParts getParts() // for testcase
+    {
+        return m_parts;
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/DefaultGizmo.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/DefaultGizmo.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/DefaultGizmo.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.util.Logger;
+
+/**
+ * Sample plugin-based implementation of a gizmo.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DefaultGizmo implements Gizmo
+{
+    private final Logger m_logger;
+    
+    public DefaultGizmo( Logger logger )
+    {
+        m_logger = logger;
+        m_logger.info( "instantiated" );
+    }
+    
+    public int getNumber()
+    {
+        return 42;
+    }
+
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/DefaultWidget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/DefaultWidget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/DefaultWidget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.annotation.Services;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Services( Widget.class )
+public class DefaultWidget implements Widget
+{
+    public String getMessage()
+    {
+        return "Hello";
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/ForeignWidget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/ForeignWidget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/ForeignWidget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.awt.Color;
+
+import net.dpml.annotation.Component;
+import net.dpml.annotation.Services;
+
+import net.dpml.util.Logger;
+
+import static net.dpml.annotation.LifestylePolicy.TRANSIENT;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Component( name="foreign" )
+ at Services( Widget.class )
+public class ForeignWidget implements Widget
+{
+    private final Gizmo m_gizmo;
+    
+    public ForeignWidget( final Logger logger, final Gizmo gizmo )
+    {
+        logger.info( "instantiated" );
+        m_gizmo = gizmo;
+        logger.info( getMessage() );
+    }
+    
+    public String getMessage()
+    {
+        return "" + m_gizmo.getNumber();
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/GenericComponent.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/GenericComponent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/GenericComponent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.annotation.Parts;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class GenericComponent
+{
+    @Parts
+    public interface GenericParts
+    {
+        <T>T getWidget( Class<T> type );
+        <T>T getGizmo( Class<T> type );
+    }
+    
+    private final GenericParts m_parts;
+    
+    public GenericComponent( GenericParts parts )
+    {
+        m_parts = parts;
+    }
+    
+    public GenericParts getParts()
+    {
+        return m_parts;
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/Gizmo.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/Gizmo.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/Gizmo.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Gizmo
+{
+    int getNumber();
+}

Added: trunk/main/lang/part/src/test/org/acme/GizmoAdapter.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/GizmoAdapter.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/GizmoAdapter.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.lang.Strategy;
+
+import net.dpml.runtime.ComponentError;
+import net.dpml.runtime.ComponentStrategyHandler;
+
+/**
+ * Example of a component that is declared as a service (via META=INF/services)
+ * while actual deployment is handled via net.dpml.runtime.ComponentStrategy.
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class GizmoAdapter implements Gizmo
+{
+    private Gizmo m_delegate;
+    
+    public int getNumber()
+    {
+        return getDelegate().getNumber();
+    }
+    
+    private Gizmo getDelegate()
+    {
+        if( null == m_delegate )
+        {
+            m_delegate = createDelegate();
+        }
+        return m_delegate;
+    }
+    
+    private Gizmo createDelegate()
+    {
+        try
+        {
+            Strategy strategy = Strategy.load( DefaultGizmo.class, null, "gizmo" );
+            return strategy.getInstance( Gizmo.class );
+        }
+        catch( Exception e )
+        {
+            final String error = 
+              "Error in gizmo adapter delegate establishment.";
+            throw new ComponentError( error, e );
+        }
+    }
+
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/Parameterizable.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/Parameterizable.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/Parameterizable.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.net.URI;
+import java.awt.Color;
+
+/**
+ * Sample object used in test case.  Contains a number of inner context classes
+ * used to evaluate strict and non-strict context evaluation strategies and 
+ * general part instantiation.
+ */
+public class Parameterizable
+{
+    private String m_name;
+    private int m_id;
+    
+    public Parameterizable( String name, int id )
+    {
+        m_name = name;
+        m_id = id;
+    }
+    
+    public String getName()
+    {
+        return m_name;
+    }
+    
+    public int getID()
+    {
+        return m_id;
+    }
+}
\ No newline at end of file

Added: trunk/main/lang/part/src/test/org/acme/Sample.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/Sample.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/Sample.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.net.URI;
+import java.awt.Color;
+
+/**
+ * Sample object used in test case.  Contains a number of inner context classes
+ * used to evaluate strict and non-strict context evaluation strategies and 
+ * general part instantiation.
+ */
+public class Sample
+{
+   /**
+    * Traditional context interface definition with a nested context
+    * interface as a return type and parameter to one of the entries.
+    */
+    public interface Context
+    {
+       /**
+        * @return a message
+        */
+        String getMessage();
+        
+       /**
+        * @param uri the default value
+        * @return a uri
+        */
+        URI getResourceURI( URI uri );
+        
+       /**
+        * @param value the default value
+        * @return a nested context object
+        */
+        AnotherContext getExternal( AnotherContext value );
+    }
+    
+   /**
+    * A context defintion declared as a context using the <tt>ContextDef</tt>
+    * annotation.
+    */
+    @net.dpml.annotation.Context
+    public interface AnotherContext
+    {
+       /**
+        * @param color the default value
+        * @return a color
+        */
+        Color getColor( Color color );
+    }
+    
+   /**
+    * Constructor that takes a single context argument as the initial state.
+    * @param context a classic context instance
+    */
+    public Sample( Context context )
+    {
+        System.out.println( "  message: " + context.getMessage() );
+        System.out.println( "  resourceURI: " + context.getResourceURI( null ) );
+        AnotherContext external = context.getExternal( null );
+        if( null != external )
+        {
+            System.out.println( "  external.color: " + external.getColor( null ) );
+        }
+    }
+    
+   /**
+    * Internal class used to validate that a inner context interface 
+    * marked as non-a-context using the <tt>ContextDef</tt> annotion is 
+    * correctly recognized as such.
+    */
+    public static class Negation
+    {
+       /**
+        * A non-context interface that happens to be named Context.
+        */
+        @net.dpml.annotation.Context( false )
+        public interface Context
+        {
+        }
+    }
+}
\ No newline at end of file

Added: trunk/main/lang/part/src/test/org/acme/SelectComponent.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/SelectComponent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/SelectComponent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.util.List;
+
+import net.dpml.util.Logger;
+
+import net.dpml.runtime.Component;
+import net.dpml.runtime.Provider;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class SelectComponent
+{
+    public interface Parts
+    {
+        Widget[] getWidgets();
+        Provider[] getProviders( Class type );
+        Component[] getComponents( Class type );
+        Component[] getAllComponents();
+    }
+    
+    private final Parts m_parts;
+    
+    public SelectComponent( Logger logger, Parts parts )
+    {
+        logger.info( "instantiated" );
+        m_parts = parts;
+    }
+    
+    public Parts getParts()
+    {
+        return m_parts;
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/SingletonWidget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/SingletonWidget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/SingletonWidget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.annotation.Component;
+import net.dpml.annotation.Services;
+
+import static net.dpml.annotation.LifestylePolicy.SINGLETON;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Services( Widget.class )
+ at Component( name="widget", lifestyle=SINGLETON )
+public class SingletonWidget extends DefaultWidget
+{
+}

Added: trunk/main/lang/part/src/test/org/acme/StandaloneWidget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/StandaloneWidget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/StandaloneWidget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.awt.Color;
+
+import static net.dpml.annotation.LifestylePolicy.TRANSIENT;
+
+import net.dpml.annotation.Component;
+import net.dpml.annotation.Services;
+
+import net.dpml.util.Logger;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Component
+ at Services( Widget.class )
+public class StandaloneWidget implements Widget
+{
+    public interface Context
+    {
+        String getMessage( String value );
+        ColorManager getColors();
+        int[] getNumbers();
+    }
+    
+    private final Context m_context;
+    
+    public StandaloneWidget( Logger logger, Context context )
+    {
+        logger.info( "instantiated" );
+        logger.info( "message: " + context.getMessage( null ) );
+        logger.info( "colors: " + context.getColors() );
+        for( int n : context.getNumbers() )
+        {
+            logger.info( "  " + n );
+        }
+        m_context = context;
+    }
+    
+    public String getMessage()
+    {
+        return m_context.getMessage( "Hello" );
+    }
+    
+    public Color getPrimary()
+    {
+        return m_context.getColors().getPrimary();
+    }
+    
+    public Color getSecondary()
+    {
+        return m_context.getColors().getSecondary();
+    }
+    
+    public int[] getNumbers()
+    {
+        return m_context.getNumbers();
+    }
+    
+    @net.dpml.annotation.Context
+    public interface ColorManager
+    {
+        Color getPrimary();
+        Color getSecondary();
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/StandaloneWidget.xprofile
===================================================================
--- trunk/main/lang/part/src/test/org/acme/StandaloneWidget.xprofile	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/StandaloneWidget.xprofile	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+
+<profile xmlns="dpml:metro">
+  <context>
+    <entry key="message" value="Batman"/>
+    <context key="colors">
+      <entry key="primary" method="RED"/>
+      <entry key="secondary" method="BLUE"/>
+    </context>
+    <entry key="numbers">
+      <param value="1"/>
+      <param value="2"/>
+      <param value="3"/>
+    </entry>
+  </context>
+</profile>

Added: trunk/main/lang/part/src/test/org/acme/StandaloneWidgetAdapter.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/StandaloneWidgetAdapter.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/StandaloneWidgetAdapter.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.lang.Strategy;
+
+import dpml.util.DefaultLogger;
+import net.dpml.util.Logger;
+
+import net.dpml.runtime.ComponentError;
+import net.dpml.runtime.ComponentStrategyHandler;
+
+/**
+ * Example of a component that is declared as a service (via META=INF/services)
+ * while actual deployment is handled via net.dpml.runtime.ComponentStrategy.
+ * 
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StandaloneWidgetAdapter implements Widget
+{
+    private Widget m_delegate;
+    private Logger m_logger = new DefaultLogger( "adapter" );
+    
+    public StandaloneWidgetAdapter()
+    {
+        m_logger.info( "instantiated" ); 
+    }
+    
+    public String getMessage()
+    {
+        return getDelegate().getMessage();
+    }
+    
+    private Widget getDelegate()
+    {
+        if( null == m_delegate )
+        {
+            m_delegate = createDelegate();
+        }
+        return m_delegate;
+    }
+    
+    private Widget createDelegate()
+    {
+        m_logger.info( "creating delegate" );
+        try
+        {
+            Strategy strategy = Strategy.load( StandaloneWidget.class, null, "adapter.standalone" );
+            return strategy.getInstance( Widget.class );
+        }
+        catch( Exception e )
+        {
+            final String error = 
+              "Error in widget adapter delegate establishment.";
+            throw new ComponentError( error, e );
+        }
+    }
+
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/StateWidget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/StateWidget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/StateWidget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.awt.Color;
+
+import net.dpml.annotation.Component;
+import net.dpml.annotation.Services;
+
+import static net.dpml.annotation.LifestylePolicy.TRANSIENT;
+
+import net.dpml.util.Logger;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Component
+ at Services( Widget.class )
+public class StateWidget implements Widget
+{
+    private final Logger m_logger;
+    
+    private int m_state = 0;
+    
+    public StateWidget( Logger logger )
+    {
+        m_logger = logger;
+        if( m_logger.isInfoEnabled() )
+        {
+            m_logger.info( "instantiated" );
+        }
+    }
+    
+    public void start() throws Exception
+    {
+        m_state = 1;
+        if( m_logger.isInfoEnabled() )
+        {
+            m_logger.info( "starting" );
+        }
+    }
+    
+    public String getMessage()
+    {
+        if( m_state == 0 )
+        {
+            return "constructed";
+        }
+        else if( m_state == 1 )
+        {
+            return "started";
+        }
+        else if( m_state == 2 )
+        {
+            return "stopped";
+        }
+        else
+        {
+            return "unknown";
+        }
+    }
+
+    public int getState()
+    {
+        return m_state;
+    }
+    
+    public void stop() throws Exception
+    {
+        m_state = 2;
+        if( m_logger.isInfoEnabled() )
+        {
+            m_logger.info( "stopping" );
+        }
+    }
+
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/part/src/test/org/acme/StateWidget.xgraph
===================================================================
--- trunk/main/lang/part/src/test/org/acme/StateWidget.xgraph	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/StateWidget.xgraph	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+
+<state xmlns="dpml:state"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+  <trigger event="initialization">
+    <transition name="start" target="started">
+      <operation name="startup" method="start"/>
+    </transition>
+  </trigger>
+  <state name="started">
+    <trigger event="termination">
+      <apply id="stop"/>
+    </trigger>
+    <transition name="stop" target="../stopped">
+      <operation name="stop" method="stop"/>
+    </transition>
+  </state>
+  <state name="stopped">
+    <transition name="start" target="../started">
+      <operation name="start" method="start"/>
+    </transition>
+  </state>
+
+</state>

Added: trunk/main/lang/part/src/test/org/acme/TransientWidget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/TransientWidget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/TransientWidget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.annotation.Component;
+import net.dpml.annotation.Services;
+
+import static net.dpml.annotation.LifestylePolicy.TRANSIENT;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Services( Widget.class )
+ at Component( name="widget", lifestyle=TRANSIENT )
+public class TransientWidget extends DefaultWidget
+{
+}

Added: trunk/main/lang/part/src/test/org/acme/Widget.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/Widget.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/Widget.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.lang.Strategy;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Widget
+{
+    String getMessage();
+}

Added: trunk/main/lang/part/src/test/org/acme/WidgetUsingGizmo.java
===================================================================
--- trunk/main/lang/part/src/test/org/acme/WidgetUsingGizmo.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/part/src/test/org/acme/WidgetUsingGizmo.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2004-2006 Stephen J. McConnell.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.awt.Color;
+
+import net.dpml.annotation.Context;
+import net.dpml.annotation.Component;
+import net.dpml.annotation.Services;
+
+import net.dpml.util.Logger;
+
+import static net.dpml.annotation.LifestylePolicy.TRANSIENT;
+
+/**
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Component( name="foreign" )
+ at Services( Widget.class )
+public class WidgetUsingGizmo implements Widget
+{
+    @Context
+    public interface WidgetContext
+    {
+        Gizmo getGizmo();
+    }
+    
+    private final Gizmo m_gizmo;
+    
+    public WidgetUsingGizmo( final Logger logger, final WidgetContext context )
+    {
+        logger.info( "instantiated" );
+        m_gizmo = context.getGizmo();
+        logger.info( getMessage() );
+    }
+    
+    public String getMessage()
+    {
+        return "" + m_gizmo.getNumber();
+    }
+    
+    public boolean equals( Object other )
+    {
+        return ( hashCode() == other.hashCode() );
+    }
+}

Added: trunk/main/lang/sample/etc/component.xml
===================================================================
--- trunk/main/lang/sample/etc/component.xml	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/sample/etc/component.xml	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<component xmlns="dpml:metro" name="hello" type="org.acme.HelloComponent"/>

Added: trunk/main/lang/sample/project.xml
===================================================================
--- trunk/main/lang/sample/project.xml	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/sample/project.xml	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<project xmlns="dpml:library" name="dpml-lang-sample">
+
+  <info title="DPML Component Example"/>
+  
+  <types>
+    <type id="jar"/>
+    <type id="part" source="etc/component.xml" alias="true"/>
+  </types>
+  
+  <dependencies>
+    <runtime>
+      <include ref="dpml/lang/dpml-lang-part"/>
+    </runtime>
+  </dependencies>
+  
+</project>
+

Added: trunk/main/lang/sample/src/main/org/acme/AnotherContext.java
===================================================================
--- trunk/main/lang/sample/src/main/org/acme/AnotherContext.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/sample/src/main/org/acme/AnotherContext.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2005 Stephen McConnell
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import java.net.URI;
+
+import net.dpml.annotation.Context;
+
+
+/**
+ * A context interface referenced by an enclosing context.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Context
+public interface AnotherContext
+{
+    URI getUri( URI value );
+}

Added: trunk/main/lang/sample/src/main/org/acme/Hello.java
===================================================================
--- trunk/main/lang/sample/src/main/org/acme/Hello.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/sample/src/main/org/acme/Hello.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2005 Stephen McConnell
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+/**
+ * Sample service interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Hello
+{
+    String getMessage();
+}

Added: trunk/main/lang/sample/src/main/org/acme/HelloComponent.java
===================================================================
--- trunk/main/lang/sample/src/main/org/acme/HelloComponent.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/sample/src/main/org/acme/HelloComponent.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2005 Stephen McConnell
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import dpml.util.PID;
+
+import java.net.URI;
+
+import net.dpml.annotation.Component;
+import net.dpml.annotation.Services;
+
+import static net.dpml.annotation.LifestylePolicy.SINGLETON;
+
+import net.dpml.util.Logger;
+
+/**
+ * Sample component used in testing.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Component( lifestyle=SINGLETON )
+ at Services( Hello.class )
+public class HelloComponent implements Hello
+{
+    private static final PID ID = new PID();
+    private static final String MESSAGE = "Hello";
+    
+    private final Logger m_logger;
+    private final HelloConfiguration m_context;
+    
+    public HelloComponent( Logger logger, HelloConfiguration context ) throws Exception
+    {
+        m_logger = logger;
+        m_context = context;
+
+        URI codebase = 
+          getClass().getProtectionDomain().getCodeSource().getLocation().toURI();
+        
+        m_logger.info( "pid: " + ID );
+        m_logger.info( "message: " + context.getMessage( MESSAGE ) );
+        m_logger.info( "port: " + context.getPort( 0 ) );
+        m_logger.info( "target: " + context.getTarget().getUri( codebase ) );
+    }
+    
+    public String getMessage()
+    {
+        return m_context.getMessage( "Hello" );
+    }
+    
+    public void start()
+    {
+        m_logger.info( "starting" );
+        m_logger.info( "started" );
+    }
+    
+    public void stop()
+    {
+        m_logger.info( "stopping" );
+        m_logger.info( "stopped" );
+    }
+}

Added: trunk/main/lang/sample/src/main/org/acme/HelloComponent.xgraph
===================================================================
--- trunk/main/lang/sample/src/main/org/acme/HelloComponent.xgraph	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/sample/src/main/org/acme/HelloComponent.xgraph	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+
+<state xmlns="dpml:state">
+
+  <trigger event="initialization">
+    <transition name="start" target="started">
+      <operation name="startup" method="start"/>
+    </transition>
+  </trigger>
+
+  <state name="started">
+    <trigger event="termination">
+      <apply id="stop"/>
+    </trigger>
+    <transition name="stop" target="../stopped">
+      <operation name="stop" method="stop"/>
+    </transition>
+  </state>
+
+  <state name="stopped">
+    <transition name="start" target="../started">
+      <operation name="start" method="start"/>
+    </transition>
+  </state>
+
+</state>

Added: trunk/main/lang/sample/src/main/org/acme/HelloConfiguration.java
===================================================================
--- trunk/main/lang/sample/src/main/org/acme/HelloConfiguration.java	2007-02-09 01:28:27 UTC (rev 1858)
+++ trunk/main/lang/sample/src/main/org/acme/HelloConfiguration.java	2007-02-09 01:29:45 UTC (rev 1859)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2005 Stephen McConnell
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.acme;
+
+import net.dpml.annotation.Context;
+
+/**
+ * Sample context iterface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+ at Context
+public interface HelloConfiguration
+{
+    String getMessage( String value );
+    int getPort( int port );
+    AnotherContext getTarget();
+}




More information about the notify-dpml mailing list