Skip to Content.
Sympa Menu

notify-dpml - r1821 - in trunk/main/metro: . appliance appliance/etc appliance/etc/data appliance/etc/main appliance/etc/main/META-INF appliance/etc/main/META-INF/services appliance/etc/xsds appliance/src appliance/src/main appliance/src/main/dpml appliance/src/main/dpml/station appliance/src/main/dpml/station/info appliance/src/main/dpml/station/util appliance/src/main/net appliance/src/main/net/dpml appliance/src/main/net/dpml/station appliance/src/test appliance/src/test/net appliance/src/test/net/dpml appliance/src/test/net/dpml/appliance connector connector/etc connector/src connector/src/main connector/src/main/dpml connector/src/main/dpml/station connector/src/main/dpml/station/connector main main/etc main/etc/bin main/src main/src/main main/src/main/dpml main/src/main/dpml/metro main/src/main/dpml/metro/console station station/etc station/etc/bin station/etc/bin/scm station/etc/bin/scm/conf station/etc/bin/scm/lib station/etc/prefs station/etc/prefs/plans station/etc/pref! s/propertiess station/src station/src/main station/src/main/dpml station/src/main/dpml/station station/src/main/dpml/station/console test test/etc/data test/src test/src/test/net/dpml/test

notify-dpml AT lists.ibiblio.org

Subject: DPML Notify

List archive

Chronological Thread  
  • From: mcconnell at BerliOS <mcconnell AT mail.berlios.de>
  • To: notify-dpml AT lists.ibiblio.org
  • Subject: r1821 - in trunk/main/metro: . appliance appliance/etc appliance/etc/data appliance/etc/main appliance/etc/main/META-INF appliance/etc/main/META-INF/services appliance/etc/xsds appliance/src appliance/src/main appliance/src/main/dpml appliance/src/main/dpml/station appliance/src/main/dpml/station/info appliance/src/main/dpml/station/util appliance/src/main/net appliance/src/main/net/dpml appliance/src/main/net/dpml/station appliance/src/test appliance/src/test/net appliance/src/test/net/dpml appliance/src/test/net/dpml/appliance connector connector/etc connector/src connector/src/main connector/src/main/dpml connector/src/main/dpml/station connector/src/main/dpml/station/connector main main/etc main/etc/bin main/src main/src/main main/src/main/dpml main/src/main/dpml/metro main/src/main/dpml/metro/console station station/etc station/etc/bin station/etc/bin/scm station/etc/bin/scm/conf station/etc/bin/scm/lib station/etc/prefs station/etc/prefs/plans station/etc/pref! s/propertiess station/src station/src/main station/src/main/dpml station/src/main/dpml/station station/src/main/dpml/station/console test test/etc/data test/src test/src/test/net/dpml/test
  • Date: Fri, 9 Feb 2007 00:33:52 +0100

Author: mcconnell
Date: 2007-02-09 00:33:09 +0100 (Fri, 09 Feb 2007)
New Revision: 1821

Added:
trunk/main/metro/appliance/
trunk/main/metro/appliance/build.xml
trunk/main/metro/appliance/etc/
trunk/main/metro/appliance/etc/data/
trunk/main/metro/appliance/etc/data/appliance.xml
trunk/main/metro/appliance/etc/data/bar.xml
trunk/main/metro/appliance/etc/data/empty.xml
trunk/main/metro/appliance/etc/data/foo.xml
trunk/main/metro/appliance/etc/data/logging.properties
trunk/main/metro/appliance/etc/data/plan.xml
trunk/main/metro/appliance/etc/data/security.policy
trunk/main/metro/appliance/etc/main/
trunk/main/metro/appliance/etc/main/META-INF/
trunk/main/metro/appliance/etc/main/META-INF/services/

trunk/main/metro/appliance/etc/main/META-INF/services/net.dpml.transit.ContentHandler

trunk/main/metro/appliance/etc/main/META-INF/services/org.w3c.dom.ls.LSResourceResolver
trunk/main/metro/appliance/etc/xsds/
trunk/main/metro/appliance/etc/xsds/appliance.xsd
trunk/main/metro/appliance/etc/xsds/plan.xsd
trunk/main/metro/appliance/project.xml
trunk/main/metro/appliance/src/
trunk/main/metro/appliance/src/main/
trunk/main/metro/appliance/src/main/dpml/
trunk/main/metro/appliance/src/main/dpml/station/
trunk/main/metro/appliance/src/main/dpml/station/info/

trunk/main/metro/appliance/src/main/dpml/station/info/ApplianceDescriptor.java
trunk/main/metro/appliance/src/main/dpml/station/info/EntryDescriptor.java
trunk/main/metro/appliance/src/main/dpml/station/info/InfoDescriptor.java
trunk/main/metro/appliance/src/main/dpml/station/info/PlanDescriptor.java

trunk/main/metro/appliance/src/main/dpml/station/info/ProcessDescriptor.java
trunk/main/metro/appliance/src/main/dpml/station/info/package-info.java
trunk/main/metro/appliance/src/main/dpml/station/util/
trunk/main/metro/appliance/src/main/dpml/station/util/LoggingServer.java

trunk/main/metro/appliance/src/main/dpml/station/util/OutputStreamReader.java
trunk/main/metro/appliance/src/main/dpml/station/util/StreamReader.java
trunk/main/metro/appliance/src/main/net/
trunk/main/metro/appliance/src/main/net/dpml/
trunk/main/metro/appliance/src/main/net/dpml/station/

trunk/main/metro/appliance/src/main/net/dpml/station/ApplianceContentHandler.java

trunk/main/metro/appliance/src/main/net/dpml/station/ApplianceNamespaceResolver.java
trunk/main/metro/appliance/src/main/net/dpml/station/Application.java

trunk/main/metro/appliance/src/main/net/dpml/station/CompositeAppliance.java

trunk/main/metro/appliance/src/main/net/dpml/station/PlanContentHandler.java

trunk/main/metro/appliance/src/main/net/dpml/station/PlanNamespaceResolver.java
trunk/main/metro/appliance/src/main/net/dpml/station/Station.java
trunk/main/metro/appliance/src/main/net/dpml/station/StationException.java
trunk/main/metro/appliance/src/main/net/dpml/station/package-info.java
trunk/main/metro/appliance/src/test/
trunk/main/metro/appliance/src/test/net/
trunk/main/metro/appliance/src/test/net/dpml/
trunk/main/metro/appliance/src/test/net/dpml/appliance/

trunk/main/metro/appliance/src/test/net/dpml/appliance/AbstractTestCase.java

trunk/main/metro/appliance/src/test/net/dpml/appliance/ApplianceDescriptorTestCase.java

trunk/main/metro/appliance/src/test/net/dpml/appliance/PlanDescriptorTestCase.java
trunk/main/metro/connector/
trunk/main/metro/connector/build.xml
trunk/main/metro/connector/etc/
trunk/main/metro/connector/etc/component.xml
trunk/main/metro/connector/etc/local.xml
trunk/main/metro/connector/project.xml
trunk/main/metro/connector/src/
trunk/main/metro/connector/src/main/
trunk/main/metro/connector/src/main/dpml/
trunk/main/metro/connector/src/main/dpml/station/
trunk/main/metro/connector/src/main/dpml/station/connector/

trunk/main/metro/connector/src/main/dpml/station/connector/LocalConnector.java
trunk/main/metro/main/
trunk/main/metro/main/build.xml
trunk/main/metro/main/etc/
trunk/main/metro/main/etc/bin/
trunk/main/metro/main/etc/bin/metro
trunk/main/metro/main/etc/bin/metro.exe
trunk/main/metro/main/etc/bin/metro.lap
trunk/main/metro/main/etc/bin/metro.policy
trunk/main/metro/main/etc/component.xml
trunk/main/metro/main/project.xml
trunk/main/metro/main/src/
trunk/main/metro/main/src/main/
trunk/main/metro/main/src/main/dpml/
trunk/main/metro/main/src/main/dpml/metro/
trunk/main/metro/main/src/main/dpml/metro/console/
trunk/main/metro/main/src/main/dpml/metro/console/Main.java
trunk/main/metro/station/
trunk/main/metro/station/build.xml
trunk/main/metro/station/etc/
trunk/main/metro/station/etc/bin/
trunk/main/metro/station/etc/bin/scm/
trunk/main/metro/station/etc/bin/scm/WRAPPER_LICENSE.txt
trunk/main/metro/station/etc/bin/scm/conf/
trunk/main/metro/station/etc/bin/scm/conf/wrapper.conf
trunk/main/metro/station/etc/bin/scm/install-DPML-SCM.bat
trunk/main/metro/station/etc/bin/scm/lib/
trunk/main/metro/station/etc/bin/scm/lib/wrapper.dll
trunk/main/metro/station/etc/bin/scm/lib/wrapper.jar
trunk/main/metro/station/etc/bin/scm/uninstall-DPML-SCM.bat
trunk/main/metro/station/etc/bin/scm/wrapper.exe
trunk/main/metro/station/etc/bin/station
trunk/main/metro/station/etc/bin/station.exe
trunk/main/metro/station/etc/bin/station.lap
trunk/main/metro/station/etc/bin/station.policy
trunk/main/metro/station/etc/component.xml
trunk/main/metro/station/etc/prefs/
trunk/main/metro/station/etc/prefs/plans/
trunk/main/metro/station/etc/prefs/plans/default.plan
trunk/main/metro/station/etc/prefs/propertiess/
trunk/main/metro/station/etc/prefs/propertiess/process.properties
trunk/main/metro/station/etc/prefs/propertiess/station.properties
trunk/main/metro/station/project.xml
trunk/main/metro/station/src/
trunk/main/metro/station/src/main/
trunk/main/metro/station/src/main/dpml/
trunk/main/metro/station/src/main/dpml/station/
trunk/main/metro/station/src/main/dpml/station/console/
trunk/main/metro/station/src/main/dpml/station/console/Main.java

trunk/main/metro/station/src/main/dpml/station/console/StationNotBoundException.java
trunk/main/metro/test/etc/data/application.xml
trunk/main/metro/test/etc/data/security.policy
trunk/main/metro/test/etc/data/test.properties
trunk/main/metro/test/project.xml
trunk/main/metro/test/src/test/net/dpml/test/LocalTestCase.java
trunk/main/metro/test/src/test/net/dpml/test/PlanTestCase.java
Removed:
trunk/main/metro/build.xml
trunk/main/metro/component/
trunk/main/metro/model/
trunk/main/metro/runtime/
trunk/main/metro/state/
trunk/main/metro/test/src/main/
trunk/main/metro/test/src/test/net/dpml/test/part/
trunk/main/metro/test/src/test/net/dpml/test/runtime/
trunk/main/metro/tools/
Modified:
trunk/main/metro/module.xml
trunk/main/metro/test/build.xml
trunk/main/metro/test/etc/data/logging.properties
Log:
SDK 2.X staged commit.

Added: trunk/main/metro/appliance/build.xml
===================================================================
--- trunk/main/metro/appliance/build.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/appliance/build.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<project name="dpml-component" default="install" basedir="."
+ xmlns:x="antlib:dpml.tools">
+
+ <x:import uri="local:template:dpml/tools/standard"/>
+
+ <target name="build" depends="standard.build">
+ <x:rmic>
+ <include name="**/StandardAppliance.class"/>
+ <include name="**/CompositeAppliance.class"/>
+ </x:rmic>
+ </target>
+
+</project>

Added: trunk/main/metro/appliance/etc/data/appliance.xml
===================================================================
--- trunk/main/metro/appliance/etc/data/appliance.xml 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/appliance/etc/data/appliance.xml 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+
+<appliance xmlns="dpml:appliance">
+
+ <info name="hello"/>
+
+ <process startup="0" shutdown="0">
+ <environment>
+ <variable name="FOO" value="BAR"/>
+ </environment>
+ <properties>
+ <property name="foo" value="bar"/>
+ </properties>
+ </process>
+
+ <codebase
uri="link:part:dpml/lang/dpml-lang-sample?message=Hello%20World,port=1024"/>
+
+</appliance>

Added: trunk/main/metro/appliance/etc/data/bar.xml
===================================================================
--- trunk/main/metro/appliance/etc/data/bar.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/appliance/etc/data/bar.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+
+<appliance xmlns="dpml:appliance">
+
+ <info name="bar"/>
+
+ <process startup="0" shutdown="0">
+ <environment>
+ <variable name="FOO" value="BAR"/>
+ </environment>
+ <properties>
+ <property name="foo" value="bar"/>
+ </properties>
+ </process>
+
+ <codebase uri="link:part:dpml/lang/dpml-lang-sample?message=Bar"/>
+
+</appliance>

Added: trunk/main/metro/appliance/etc/data/empty.xml
===================================================================
--- trunk/main/metro/appliance/etc/data/empty.xml 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/appliance/etc/data/empty.xml 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+
+<plan xmlns="dpml:plan" name="demo" title="Plan Demo">
+
+</plan>

Added: trunk/main/metro/appliance/etc/data/foo.xml
===================================================================
--- trunk/main/metro/appliance/etc/data/foo.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/appliance/etc/data/foo.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+
+<appliance xmlns="dpml:appliance">
+
+ <info name="foo"/>
+
+ <process startup="0" shutdown="0">
+ <environment>
+ <variable name="FOO" value="BAR"/>
+ </environment>
+ <properties>
+ <property name="foo" value="bar"/>
+ </properties>
+ </process>
+
+ <codebase uri="link:part:dpml/lang/dpml-lang-sample?message=Foo,port=7"/>
+
+</appliance>

Added: trunk/main/metro/appliance/etc/data/logging.properties
===================================================================
--- trunk/main/metro/appliance/etc/data/logging.properties 2007-02-08
23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/etc/data/logging.properties 2007-02-08
23:33:09 UTC (rev 1821)
@@ -0,0 +1,3 @@
+.level=INFO
+sun.rmi.level=INFO
+#dpml.transit.level=INFO

Added: trunk/main/metro/appliance/etc/data/plan.xml
===================================================================
--- trunk/main/metro/appliance/etc/data/plan.xml 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/appliance/etc/data/plan.xml 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+
+<plan xmlns="dpml:plan" name="demo" title="Plan Demo">
+
+ <entry key="foo" uri="link:appliance:dpml/metro/demo-foo"/>
+ <entry key="bar" uri="link:appliance:dpml/metro/demo-bar"/>
+ <entry key="toto"
uri="link:part:dpml/lang/dpml-lang-sample?message=Hello%20World,port=1024"/>
+
+</plan>

Added: trunk/main/metro/appliance/etc/data/security.policy
===================================================================
--- trunk/main/metro/appliance/etc/data/security.policy 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/appliance/etc/data/security.policy 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,4 @@
+grant {
+ permission java.security.AllPermission;
+};
+

Added:
trunk/main/metro/appliance/etc/main/META-INF/services/net.dpml.transit.ContentHandler
===================================================================
---
trunk/main/metro/appliance/etc/main/META-INF/services/net.dpml.transit.ContentHandler
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/etc/main/META-INF/services/net.dpml.transit.ContentHandler
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,6 @@
+#
+# List of available Transit content handlers.
+#
+
+net.dpml.station.ApplianceContentHandler
+net.dpml.station.PlanContentHandler
\ No newline at end of file

Added:
trunk/main/metro/appliance/etc/main/META-INF/services/org.w3c.dom.ls.LSResourceResolver
===================================================================
---
trunk/main/metro/appliance/etc/main/META-INF/services/org.w3c.dom.ls.LSResourceResolver
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/etc/main/META-INF/services/org.w3c.dom.ls.LSResourceResolver
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,6 @@
+#
+# List of namespace resolvers within the dpml-lang-part artifact.
+#
+
+net.dpml.station.ApplianceNamespaceResolver
+net.dpml.station.PlanNamespaceResolver

Added: trunk/main/metro/appliance/etc/xsds/appliance.xsd
===================================================================
--- trunk/main/metro/appliance/etc/xsds/appliance.xsd 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/appliance/etc/xsds/appliance.xsd 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+
+<!--
+Defintion of an application.
+
+Example:
+
+ <application title="Sample Application" policy="automatic">
+
+ <process startup="60" shutdown="60">
+ <properties>
+ <property name="foo" value="bar"/>
+ </properties>
+ </process>
+
+ <codebase uri="link:part:acme/widget">
+ <param class="java.awt.Color" method="RED"/>
+ </codebase>
+
+ </application>
+
+-->
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema";
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+ xmlns:part="dpml:part"
+ xmlns:this="dpml:appliance"
+ targetNamespace="dpml:appliance"
+ elementFormDefault="qualified">
+
+ <import namespace="dpml:part"
schemaLocation="link:xsd:dpml/lang/dpml-lang-part"/>
+
+ <element name="appliance" type="this:ApplianceType"/>
+ <element name="codebase" type="this:CodebaseType"/>
+
+ <complexType name="ApplianceType">
+ <sequence>
+ <element name="info" type="this:InfoType" minOccurs="0"
maxOccurs="1"/>
+ <element name="process" type="this:ProcessType" minOccurs="0"
maxOccurs="1"/>
+ <element name="codebase" type="this:CodebaseType" minOccurs="1"
maxOccurs="1"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="ProcessType">
+ <sequence>
+ <element name="environment" type="this:EnvironmentType"
minOccurs="0" maxOccurs="1"/>
+ <element name="properties" type="this:PropertiesType" minOccurs="0"
maxOccurs="1"/>
+ <element name="arguments" type="this:ArgumentsType" minOccurs="0"
maxOccurs="1"/>
+ </sequence>
+ <attribute name="startup" type="integer" default="0"/>
+ <attribute name="shutdown" type="integer" default="0"/>
+ <attribute name="path" type="string"/>
+ <attribute name="executable" type="string" default="metro"/>
+ </complexType>
+
+ <complexType name="PropertiesType">
+ <sequence>
+ <element name="property" type="this:PropertyType" minOccurs="0"
maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="EnvironmentType">
+ <sequence>
+ <element name="variable" type="this:PropertyType" minOccurs="0"
maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="ArgumentsType">
+ <sequence>
+ <element name="arg" type="this:ArgumentsType" minOccurs="0"
maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="ArgumentType">
+ <attribute name="value" type="string"/>
+ </complexType>
+
+ <complexType name="PropertyType">
+ <attribute name="name" type="string"/>
+ <attribute name="value" type="string"/>
+ </complexType>
+
+ <complexType name="CodebaseType">
+ <attribute name="uri" type="anyURI"/>
+ </complexType>
+
+ <complexType name="InfoType">
+ <sequence>
+ <element name="description" type="string" minOccurs="0"
maxOccurs="1"/>
+ </sequence>
+ <attribute name="name" type="string"/>
+ <attribute name="title" type="string"/>
+ </complexType>
+
+</schema>

Added: trunk/main/metro/appliance/etc/xsds/plan.xsd
===================================================================
--- trunk/main/metro/appliance/etc/xsds/plan.xsd 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/appliance/etc/xsds/plan.xsd 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+
+<!--
+Defintion of an multi-application deployment plan.
+
+Example:
+
+ <plan title="Scenario Demo">
+ <entry name="foo" uri="link:appliance:dpml/metro/demo"/>
+ <entry name="bar" uri="link:part:dpml/lang/dpml-lang-sample"/>
+ <entry name="toto"
uri="link:part:dpml/lang/dpml-lang-sample?message=My%20Scenario,port=999"/>
+ </plan>
+
+-->
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema";
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+ xmlns:this="dpml:plan"
+ targetNamespace="dpml:plan"
+ elementFormDefault="qualified">
+
+ <element name="plan" type="this:PlanType"/>
+
+ <complexType name="PlanType">
+ <sequence>
+ <element name="entry" type="this:EntryType" minOccurs="0"
maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="name" type="string" default="root"/>
+ <attribute name="title" type="string"/>
+ </complexType>
+
+ <complexType name="EntryType">
+ <attribute name="uri" type="anyURI" use="required"/>
+ <attribute name="key" type="string" use="required"/>
+ </complexType>
+
+</schema>

Added: trunk/main/metro/appliance/project.xml
===================================================================
--- trunk/main/metro/appliance/project.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/appliance/project.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<project xmlns="dpml:library" name="dpml-metro-appliance">
+
+ <info title="DPML Application Content Handler">
+ <description>Content handler for the application datatype.</description>
+ </info>
+
+ <types>
+ <type id="xsd" alias="true" source="etc/xsds/appliance.xsd">
+ <property name="project.package.include-in-classes" value="true"/>
+ </type>
+ <type id="xsd" name="dpml-metro-plan" alias="true"
source="etc/xsds/plan.xsd">
+ <property name="project.package.include-in-classes" value="true"/>
+ </type>
+ <type id="jar"/>
+ <type id="appliance" name="demo" source="etc/data/appliance.xml"
alias="true"/>
+ <type id="appliance" name="demo-foo" source="etc/data/foo.xml"
alias="true"/>
+ <type id="appliance" name="demo-bar" source="etc/data/bar.xml"
alias="true"/>
+ <type id="plan" name="demo" source="etc/data/plan.xml" alias="true"/>
+ <type id="plan" name="empty" source="etc/data/empty.xml" alias="true"/>
+ </types>
+
+ <dependencies>
+ <build>
+ <include ref="dpml/lang/dpml-lang-sample"/>
+ </build>
+ <runtime>
+ <include ref="dpml/lang/dpml-lang-part"/>
+ <include ref="dpml/metro/dpml-metro-connector"/>
+ </runtime>
+ <test>
+ <include ref="org/apache/ant/ant-junit"/>
+ </test>
+ </dependencies>
+
+</project>
+

Added:
trunk/main/metro/appliance/src/main/dpml/station/info/ApplianceDescriptor.java
===================================================================
---
trunk/main/metro/appliance/src/main/dpml/station/info/ApplianceDescriptor.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/dpml/station/info/ApplianceDescriptor.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,255 @@
+/*
+ * 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.station.info;
+
+import dpml.util.ElementHelper;
+
+import java.util.Map;
+import java.util.Properties;
+import java.net.URI;
+
+import net.dpml.util.Resolver;
+import net.dpml.lang.DecodingException;
+
+import org.w3c.dom.Element;
+
+/**
+ * The ApplianceDescriptor is immutable datastructure used to
+ * describe an application.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class ApplianceDescriptor
+{
+ private final Element m_element;
+ private final InfoDescriptor m_info;
+ private final ProcessDescriptor m_profile;
+ private final URI m_codebase;
+ private final URI m_uri;
+
+ public ApplianceDescriptor( Element element, Resolver resolver, URI uri
) throws DecodingException
+ {
+ m_uri = uri;
+ m_element = element;
+
+ Element codebase = ElementHelper.getChild( element, "codebase" );
+ m_codebase = getCodebase( codebase, resolver );
+
+ Element info = ElementHelper.getChild( element, "info" );
+ m_info = new InfoDescriptor( info, resolver );
+
+ Element process = ElementHelper.getChild( element, "process" );
+ m_profile = new ProcessDescriptor( process, resolver );
+ }
+
+ /*
+ public ApplianceDescriptor( InfoDescriptor info, ProcessDescriptor
profile, URI codebase )
+ {
+ m_info = info;
+ m_profile = profile;
+ m_codebase = codebase;
+ m_element = null;
+ }
+ */
+
+ /**
+ * Return the element defining the scenario descriptor.
+ * @return the defining element
+ */
+ public Element getElement()
+ {
+ return m_element;
+ }
+
+ /**
+ * Get the application name.
+ *
+ * @return the name
+ */
+ public String getName()
+ {
+ return m_info.getName();
+ }
+
+ /**
+ * Get the application title.
+ *
+ * @return the title
+ */
+ public String getTitle()
+ {
+ return m_info.getTitle();
+ }
+
+ /**
+ * Get the application description.
+ *
+ * @return the description
+ */
+ public String getDescription()
+ {
+ return m_info.getDescription();
+ }
+
+ /**
+ * Returns the executable name.
+ *
+ * @return the name of the target executable
+ */
+ public String getExecutable()
+ {
+ return m_profile.getExecutable();
+ }
+
+ /**
+ * Returns the relative path for establishment of the working directory.
+ *
+ * @return the working directory path
+ */
+ public String getPath()
+ {
+ return m_profile.getPath();
+ }
+
+ /**
+ * Get the duration in seconds to wait for startup
+ * of the application before considering deployment as a timeout failure.
+ *
+ * @return the startup timeout value
+ */
+ public int getStartupTimeout()
+ {
+ return m_profile.getStartupTimeout();
+ }
+
+ /**
+ * Get the duration in seconds to wait for the shutdown
+ * of the application before considering the process as non-responsive.
+ *
+ * @return the shutdown timeout value
+ */
+ public int getShutdownTimeout()
+ {
+ return m_profile.getStartupTimeout();
+ }
+
+ /**
+ * Get the environment variable declarations.
+ *
+ * @return the environment variable map
+ */
+ public Map<String,String> getEnvironmentMap()
+ {
+ return m_profile.getEnvironmentMap();
+ }
+
+ /**
+ * Get the system properties.
+ *
+ * @return the system properties
+ */
+ public Properties getSystemProperties()
+ {
+ return m_profile.getSystemProperties();
+ }
+
+ /**
+ * Get the target uri.
+ *
+ * @return the target uri
+ */
+ public URI getTargetURI()
+ {
+ return m_codebase;
+ }
+
+
+ /**
+ * Get the codebase uri.
+ *
+ * @return the codebase uri
+ */
+ public URI getCodebaseURI()
+ {
+ return m_uri;
+ }
+
+ /**
+ * Compare this object with another for equality.
+ * @param other the object to compare this object with
+ * @return TRUE if the supplied object equivalent
+ */
+ public boolean equals( Object other )
+ {
+ if( null == other )
+ {
+ return false;
+ }
+ else if( getClass() != other.getClass() )
+ {
+ return false;
+ }
+ else
+ {
+ ApplianceDescriptor application = (ApplianceDescriptor) other;
+ if( !m_info.equals( application.m_info ) )
+ {
+ return false;
+ }
+ if( !m_profile.equals( application.m_profile ) )
+ {
+ return false;
+ }
+ if( !m_codebase.equals( application.m_codebase ) )
+ {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Return the hashcode for the object.
+ * @return the hashcode value
+ */
+ public int hashCode()
+ {
+ int hash = getClass().hashCode();
+ hash ^= m_info.hashCode();
+ hash ^= m_profile.hashCode();
+ hash ^= m_codebase.hashCode();
+ return hash;
+ }
+
+ private static URI getCodebase( Element element, Resolver resolver )
throws DecodingException
+ {
+ String spec = ElementHelper.getAttribute( element, "uri", null,
resolver );
+ if( null == spec )
+ {
+ final String error =
+ "Mising uri attribute.";
+ throw new DecodingException( error, element );
+ }
+ else
+ {
+ return URI.create( spec );
+ }
+ }
+}

Added:
trunk/main/metro/appliance/src/main/dpml/station/info/EntryDescriptor.java
===================================================================
---
trunk/main/metro/appliance/src/main/dpml/station/info/EntryDescriptor.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/dpml/station/info/EntryDescriptor.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,135 @@
+/*
+ * 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.station.info;
+
+import dpml.util.ElementHelper;
+
+import java.net.URI;
+
+import net.dpml.lang.DecodingException;
+import net.dpml.util.Resolver;
+
+import org.w3c.dom.Element;
+
+/**
+ * Immutable datastructure used to describe an deployment scenario.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class EntryDescriptor
+{
+ private final Element m_element;
+ private final String m_key;
+ private final URI m_uri;
+
+ public EntryDescriptor( Element element, Resolver resolver ) throws
DecodingException
+ {
+ m_element = element;
+ m_key = ElementHelper.getAttribute( element, "key", null, resolver );
+ if( null == m_key )
+ {
+ final String error =
+ "Missing 'key' attribute in entry descriptor.";
+ throw new DecodingException( error, element );
+ }
+ String spec = ElementHelper.getAttribute( element, "uri", null,
resolver );
+ m_uri = URI.create( spec );
+ if( null == m_uri )
+ {
+ final String error =
+ "Missing 'uri' attribute in entry descriptor.";
+ throw new DecodingException( error, element );
+ }
+ }
+
+ /**
+ * Return the element defining the entry descriptor.
+ * @return the defining element
+ */
+ public Element getElement()
+ {
+ return m_element;
+ }
+
+ /**
+ * Get the uri.
+ *
+ * @return the uri
+ */
+ public URI getURI()
+ {
+ return m_uri;
+ }
+
+ /**
+ * Get the entry key.
+ *
+ * @return the key
+ */
+ public String getKey()
+ {
+ return m_key;
+ }
+
+ /**
+ * Compare this object with another for equality.
+ * @param other the object to compare this object with
+ * @return TRUE if the supplied object is equivalent
+ */
+ public boolean equals( Object other )
+ {
+ if( null == other )
+ {
+ return false;
+ }
+ else if( getClass() != other.getClass() )
+ {
+ return false;
+ }
+ else
+ {
+ EntryDescriptor entry = (EntryDescriptor) other;
+ if( !m_key.equals( entry.m_key ) )
+ {
+ return false;
+ }
+ else if( !m_uri.equals( entry.m_uri ) )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Return the hashcode for the object.
+ * @return the hashcode value
+ */
+ public int hashCode()
+ {
+ int hash = getClass().hashCode();
+ hash ^= m_uri.hashCode();
+ hash ^= m_key.hashCode();
+ return hash;
+ }
+}

Added:
trunk/main/metro/appliance/src/main/dpml/station/info/InfoDescriptor.java
===================================================================
--- trunk/main/metro/appliance/src/main/dpml/station/info/InfoDescriptor.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/src/main/dpml/station/info/InfoDescriptor.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,162 @@
+/*
+ * 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.station.info;
+
+import dpml.util.ElementHelper;
+import dpml.util.ObjectUtils;
+
+import net.dpml.util.Resolver;
+import net.dpml.lang.DecodingException;
+
+import org.w3c.dom.Element;
+
+/**
+ * Application info description.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class InfoDescriptor
+{
+ private final Element m_element;
+ private final String m_title;
+ private final String m_description;
+ private final String m_name;
+
+ /**
+ * Creation of a new application info descriptor.
+ * @param name the application name
+ * @param title the title of the application
+ * @param description the application description
+ */
+ public InfoDescriptor( Element element, Resolver resolver ) throws
DecodingException
+ {
+ m_element = element;
+ if( null == element )
+ {
+ m_name = null;
+ m_description = null;
+ m_title = null;
+ }
+ else
+ {
+ m_name = ElementHelper.getAttribute( element, "name", null,
resolver );
+ m_title = ElementHelper.getAttribute( element, "title", null,
resolver );
+ Element elem = ElementHelper.getChild( element, "description" );
+ if( null != elem )
+ {
+ m_description = ElementHelper.getValue( elem );
+ }
+ else
+ {
+ m_description = null;
+ }
+ }
+ }
+
+ public InfoDescriptor( String name, String title, String description )
+ {
+ m_name = name;
+ m_title = title;
+ m_description = description;
+ m_element = null;
+ }
+
+ /**
+ * Return the element defining the scenario descriptor.
+ * @return the defining element
+ */
+ public Element getElement()
+ {
+ return m_element;
+ }
+
+ /**
+ * Get the application name.
+ *
+ * @return the name
+ */
+ public String getName()
+ {
+ return m_name;
+ }
+
+ /**
+ * Get the application title.
+ *
+ * @return the title
+ */
+ public String getTitle()
+ {
+ return m_title;
+ }
+
+ /**
+ * Get the application 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( null == other )
+ {
+ return false;
+ }
+ if( getClass() != other.getClass() )
+ {
+ return false;
+ }
+ InfoDescriptor info = (InfoDescriptor) other;
+ if( !ObjectUtils.equals( m_name, info.m_name ) )
+ {
+ return false;
+ }
+ else if( !ObjectUtils.equals( m_title, info.m_title ) )
+ {
+ return false;
+ }
+ else
+ {
+ return ObjectUtils.equals( m_description, info.m_description );
+ }
+ }
+
+ /**
+ * Get the hashcode for this instance.
+ * @return the hash value
+ */
+ public int hashCode()
+ {
+ int hash = getClass().hashCode();
+ hash ^= ObjectUtils.hashValue( m_name );
+ hash ^= ObjectUtils.hashValue( m_title );
+ hash ^= ObjectUtils.hashValue( m_description );
+ return hash;
+ }
+}

Added:
trunk/main/metro/appliance/src/main/dpml/station/info/PlanDescriptor.java
===================================================================
--- trunk/main/metro/appliance/src/main/dpml/station/info/PlanDescriptor.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/src/main/dpml/station/info/PlanDescriptor.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,158 @@
+/*
+ * 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.station.info;
+
+import dpml.util.ElementHelper;
+
+import java.io.IOException;
+import java.net.URI;
+
+import net.dpml.util.Resolver;
+
+import org.w3c.dom.Element;
+
+/**
+ * Immutable datastructure used to describe an deployment scenario.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class PlanDescriptor
+{
+ private final Element m_element;
+ private final String m_name;
+ private final String m_title;
+ private final EntryDescriptor[] m_entries;
+ private final URI m_codebase;
+
+ public PlanDescriptor( Element element, Resolver resolver, URI codebase
) throws IOException
+ {
+ m_element = element;
+ m_codebase = codebase;
+ m_name = ElementHelper.getAttribute( element, "name", null, resolver
);
+ m_title = ElementHelper.getAttribute( element, "title", null,
resolver );
+ Element[] elements = ElementHelper.getChildren( element, "entry" );
+ m_entries = new EntryDescriptor[ elements.length ];
+ for( int i=0; i<elements.length; i++ )
+ {
+ Element elem = elements[i];
+ m_entries[i] = new EntryDescriptor( elem, resolver );
+ }
+ }
+
+ /**
+ * Return the element defining the scenario descriptor.
+ * @return the defining element
+ */
+ public Element getElement()
+ {
+ return m_element;
+ }
+
+ /**
+ * Get the codebase uri.
+ *
+ * @return the uri
+ */
+ public URI getCodebaseURI()
+ {
+ return m_codebase;
+ }
+
+ /**
+ * Get the scenario name.
+ *
+ * @return the name
+ */
+ public String getName()
+ {
+ return m_name;
+ }
+
+ /**
+ * Get the scenario title.
+ *
+ * @return the title
+ */
+ public String getTitle()
+ {
+ return m_title;
+ }
+
+ /**
+ * Get the deployment uris.
+ *
+ * @return the deployment uris
+ */
+ public EntryDescriptor[] getEntryDescriptors()
+ {
+ return m_entries;
+ }
+
+ /**
+ * Compare this object with another for equality.
+ * @param other the object to compare this object with
+ * @return TRUE if the supplied object is equivalent
+ */
+ public boolean equals( Object other )
+ {
+ if( null == other )
+ {
+ return false;
+ }
+ else if( getClass() != other.getClass() )
+ {
+ return false;
+ }
+ else
+ {
+ PlanDescriptor scenario = (PlanDescriptor) other;
+ int n = m_entries.length;
+ int m = scenario.m_entries.length;
+ if( n != m )
+ {
+ return false;
+ }
+ for( int i=0; i<m_entries.length; i++ )
+ {
+ EntryDescriptor local = m_entries[i];
+ EntryDescriptor external = scenario.m_entries[i];
+ if( !local.equals( external ) )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Return the hashcode for the object.
+ * @return the hashcode value
+ */
+ public int hashCode()
+ {
+ int hash = getClass().hashCode();
+ for( EntryDescriptor entry : m_entries )
+ {
+ hash ^= entry.hashCode();
+ }
+ return hash;
+ }
+}

Added:
trunk/main/metro/appliance/src/main/dpml/station/info/ProcessDescriptor.java
===================================================================
---
trunk/main/metro/appliance/src/main/dpml/station/info/ProcessDescriptor.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/dpml/station/info/ProcessDescriptor.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,274 @@
+/*
+ * 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.station.info;
+
+import dpml.util.ElementHelper;
+import dpml.util.ObjectUtils;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.ArrayList;
+
+import net.dpml.lang.DecodingException;
+import net.dpml.util.Resolver;
+
+import org.w3c.dom.Element;
+
+/**
+ * Application info description.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class ProcessDescriptor
+{
+ private final Element m_element;
+ private final String m_executable;
+ private final Map<String,String> m_environment = new
Hashtable<String,String>();
+ private final Properties m_properties = new Properties();
+ private final List<String> m_arguments = new ArrayList<String>();
+ private final String m_path;
+ private final int m_startup;
+ private final int m_shutdown;
+
+ /**
+ * Creation of a new process descriptor.
+ * @param executable the java executable name (optional)
+ * @param environment a map of overriding environment variables
+ * @param properties supplimentary system properties
+ * @param path the deployment base directory path
+ * @param startup startup timeout in seconds
+ * @param shutdown startup timeout in seconds
+ */
+ public ProcessDescriptor( Element element, Resolver resolver ) throws
DecodingException
+ {
+ m_element = element;
+ if( null == element )
+ {
+ m_executable = "metro";
+ m_path = null;
+ m_startup = 0;
+ m_shutdown = 0;
+ }
+ else
+ {
+ m_executable = ElementHelper.getAttribute( element,
"executable", null, resolver );
+ m_path = ElementHelper.getAttribute( element, "path", null,
resolver );
+ Element environment = ElementHelper.getChild( element,
"environment" );
+ if( null != environment )
+ {
+ Element[] variables = ElementHelper.getChildren(
environment, "variable" );
+ for( Element variable : variables )
+ {
+ String name = ElementHelper.getAttribute( variable,
"name", null, resolver );
+ String value = ElementHelper.getAttribute( variable,
"value", null, resolver );
+ m_environment.put( name, value );
+ }
+ }
+
+ Element properties = ElementHelper.getChild( element,
"properties" );
+ if( null != properties )
+ {
+ Element[] props = ElementHelper.getChildren( properties,
"property" );
+ for( Element elem : props )
+ {
+ String name = ElementHelper.getAttribute( elem, "name",
null, resolver );
+ String value = ElementHelper.getAttribute( elem,
"value", null, resolver );
+ m_properties.setProperty( name, value );
+ }
+ }
+
+ Element arguments = ElementHelper.getChild( element, "arguments"
);
+ if( null != arguments )
+ {
+ Element[] args = ElementHelper.getChildren( properties,
"arg" );
+ for( Element arg : args )
+ {
+ String value = ElementHelper.getAttribute( arg, "value",
null, resolver );
+ m_arguments.add( value );
+ }
+ }
+
+ String start = ElementHelper.getAttribute( element, "startup",
"0", resolver );
+ m_startup = Integer.parseInt( start );
+ String stop = ElementHelper.getAttribute( element, "shutdown",
"0", resolver );
+ m_shutdown = Integer.parseInt( stop );
+ }
+ }
+
+ public ProcessDescriptor(
+ String executable, Map<String,String> environment, Properties
properties,
+ List<String> arguments, String path, int startup, int shutdown )
+ {
+ m_element = null;
+ m_executable = executable;
+ if( null != environment )
+ {
+ m_environment.putAll( environment );
+ }
+ if( null != properties )
+ {
+ m_properties.putAll( properties );
+ }
+ if( null != arguments )
+ {
+ m_arguments.addAll( arguments );
+ }
+ m_path = path;
+ m_startup = startup;
+ m_shutdown = shutdown;
+ }
+
+ /**
+ * Return the element defining the scenario descriptor.
+ * @return the defining element
+ */
+ public Element getElement()
+ {
+ return m_element;
+ }
+
+ /**
+ * Return the executable name (defaults to metro).
+ *
+ * @return the executable name
+ */
+ public String getExecutable()
+ {
+ return m_executable;
+ }
+
+ /**
+ * Return the executable arguments.
+ *
+ * @return the executable arguments
+ */
+ public String[] getArguments()
+ {
+ return m_arguments.toArray( new String[0] );
+ }
+
+ /**
+ * Get the relative deployment path.
+ *
+ * @return the path
+ */
+ public String getPath()
+ {
+ return m_path;
+ }
+
+ /**
+ * Get the duration in seconds to wait for startup
+ * of the application before considering deployment as a timeout failure.
+ *
+ * @return the startup timeout value
+ */
+ public int getStartupTimeout()
+ {
+ return m_startup;
+ }
+
+ /**
+ * Get the duration in seconds to wait for the shutdown
+ * of the application before considering the process as non-responsive.
+ *
+ * @return the shutdown timeout value
+ */
+ public int getShutdownTimeout()
+ {
+ return m_shutdown;
+ }
+
+ /**
+ * Get the system properties.
+ *
+ * @return the system properties
+ */
+ public Properties getSystemProperties()
+ {
+ return m_properties;
+ }
+
+ /**
+ * Get the environment variable declarations.
+ *
+ * @return the environment variable map
+ */
+ public Map<String,String> getEnvironmentMap()
+ {
+ return m_environment;
+ }
+
+ /**
+ * 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( null == other )
+ {
+ return false;
+ }
+ if( getClass() != other.getClass() )
+ {
+ return false;
+ }
+ ProcessDescriptor profile = (ProcessDescriptor) other;
+ if( !ObjectUtils.equals( m_path, profile.m_path ) )
+ {
+ return false;
+ }
+ if( !ObjectUtils.equals( m_executable, profile.m_executable ) )
+ {
+ return false;
+ }
+ if( !ObjectUtils.equals( m_properties, profile.m_properties ) )
+ {
+ return false;
+ }
+ if( m_startup != profile.m_startup )
+ {
+ return false;
+ }
+ if( m_shutdown != profile.m_shutdown )
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get the hashcode for this instance.
+ * @return the hash value
+ */
+ public int hashCode()
+ {
+ int hash = getClass().hashCode();
+ hash ^= ObjectUtils.hashValue( m_executable );
+ hash ^= ObjectUtils.hashValue( m_path );
+ hash ^= ObjectUtils.hashValue( m_properties );
+ hash ^= m_startup;
+ hash ^= m_shutdown;
+ return hash;
+ }
+}

Added: trunk/main/metro/appliance/src/main/dpml/station/info/package-info.java
===================================================================
--- trunk/main/metro/appliance/src/main/dpml/station/info/package-info.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/src/main/dpml/station/info/package-info.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -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>Internal datastructures describing an appliance.</p>
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+package dpml.station.info;

Added:
trunk/main/metro/appliance/src/main/dpml/station/util/LoggingServer.java
===================================================================
--- trunk/main/metro/appliance/src/main/dpml/station/util/LoggingServer.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/src/main/dpml/station/util/LoggingServer.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2005-2007 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.station.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.BufferedInputStream;
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.net.SocketException;
+import java.util.logging.Logger;
+import java.util.logging.LogRecord;
+
+import dpml.util.LogStatement;
+
+import dpml.util.PID;
+
+/**
+ * The LoggingServer is a remote service that handles the aggregation of
+ * log records from multiple jvm processes.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class LoggingServer extends Thread
+{
+ private static final PID PROCESS = new PID();
+ private static final String LOG_SERVER_PORT_KEY =
"dpml.station.logging.port";
+ private static final int DEFAULT_LOG_SERVER_PORT = 2020;
+
+ //public static final Thread SERVER = createLoggingServerThread();
+
+ /*
+ private static Thread createLoggingServerThread()
+ {
+ System.out.println( "## CREATING LOG SERVER THREAD IN " + PROCESS );
+ int port = getLogServerPort();
+ try
+ {
+ LoggingServer server = new LoggingServer( port );
+ Thread thread = new Thread( server, "DPML Station Aggregator" );
+ thread.setDaemon( true );
+ thread.start();
+ return thread;
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unexpected error while attempting to start the logging server
on port [" + port + "].";
+ throw new Error( error, e );
+ }
+ }
+ */
+
+ private static LoggingServer SERVER;
+
+ public static void init()
+ {
+ if( null == SERVER )
+ {
+ try
+ {
+ SERVER = new LoggingServer();
+ SERVER.setDaemon( true );
+ SERVER.setName( "DPML Logging Server" );
+ SERVER.start();
+ }
+ catch( Throwable e )
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static int getLogServerPort()
+ {
+ String port = System.getProperty( LOG_SERVER_PORT_KEY, null );
+ if( null == port )
+ {
+ return DEFAULT_LOG_SERVER_PORT;
+ }
+ else
+ {
+ return Integer.parseInt( port );
+ }
+ }
+
+ private final ServerSocket m_server;
+
+ private int m_count = 0;
+
+ /**
+ * Creation of a new logging service instance.
+ * @param port the log server port
+ * @exception IOException if an IO exception occurs
+ */
+ public LoggingServer() throws IOException
+ {
+ this( getLogServerPort() );
+ }
+
+ /**
+ * Creation of a new logging service instance.
+ * @param port the log server port
+ * @exception IOException if an IO exception occurs
+ */
+ public LoggingServer( int port ) throws IOException
+ {
+ m_server = new ServerSocket( port );
+ }
+
+ /**
+ * Runnable implementation.
+ */
+ public void run()
+ {
+ while( true )
+ {
+ try
+ {
+ Socket socket = m_server.accept();
+ RequestHandler handler = new RequestHandler( socket );
+ Thread thread = new Thread( handler );
+ thread.start();
+ }
+ catch( Throwable e )
+ {
+ e.printStackTrace();
+ m_count++;
+ }
+ }
+ }
+
+ int getErrorCount()
+ {
+ return m_count;
+ }
+
+ /**
+ * Internal utility class to handle a client connection.
+ */
+ final class RequestHandler implements Runnable
+ {
+ private final Socket m_socket;
+
+ /**
+ * Creation of a new request handler.
+ * @param socket the socket
+ */
+ private RequestHandler( Socket socket )
+ {
+ m_socket = socket;
+ }
+
+ /**
+ * Run the process.
+ */
+ public void run()
+ {
+ try
+ {
+ InputStream input = m_socket.getInputStream();
+ BufferedInputStream buffer = new BufferedInputStream( input
);
+ ObjectInputStream ois = new ObjectInputStream( buffer );
+ while( true )
+ {
+ Object object = ois.readObject();
+ if( object instanceof LogStatement )
+ {
+ LogStatement statement = (LogStatement) object;
+ PID pid = statement.getPID();
+ if( !PROCESS.equals( pid ) )
+ {
+ int id = pid.getValue();
+ LogRecord record = statement.getLogRecord();
+ String raw = record.getMessage();
+ String message = "$[" + id + "] " + raw;
+ record.setMessage( message );
+ Logger logger = getNamedLogger( record );
+ logger.log( record );
+ }
+ }
+ }
+ }
+ catch( ClassNotFoundException e )
+ {
+ e.printStackTrace();
+ }
+ catch( SocketException ioe )
+ {
+ // ignore
+ }
+ catch( IOException ioe )
+ {
+ //ioe.printStackTrace();
+ }
+ }
+
+ private Logger getNamedLogger( LogRecord record )
+ {
+ String name = record.getLoggerName();
+ if( null != name )
+ {
+ return Logger.getLogger( name );
+ }
+ else
+ {
+ return Logger.getAnonymousLogger();
+ }
+ }
+ }
+}
+

Added:
trunk/main/metro/appliance/src/main/dpml/station/util/OutputStreamReader.java
===================================================================
---
trunk/main/metro/appliance/src/main/dpml/station/util/OutputStreamReader.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/dpml/station/util/OutputStreamReader.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,67 @@
+/*
+ * 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.station.util;
+
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import net.dpml.util.Logger;
+
+/**
+ * Stream reader utility class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class OutputStreamReader extends StreamReader
+{
+ /**
+ * Creation of a process output reader.
+ * @param logger the assigned logging channel
+ * @param input the subprocess input stream
+ */
+ public OutputStreamReader( Logger logger, InputStream input )
+ {
+ super( logger, input );
+ }
+
+ /**
+ * Start the stream reader.
+ */
+ public void run()
+ {
+ try
+ {
+ InputStreamReader isr = new InputStreamReader( getInputStream()
);
+ BufferedReader reader = new BufferedReader( isr );
+ String line = null;
+ while( ( line = reader.readLine() ) != null )
+ {
+ System.out.println( line );
+ getLogger().debug( "$ " + line );
+ }
+ }
+ catch( IOException e )
+ {
+ getLogger().error( "Process read error.", e );
+ }
+ }
+}

Added: trunk/main/metro/appliance/src/main/dpml/station/util/StreamReader.java
===================================================================
--- trunk/main/metro/appliance/src/main/dpml/station/util/StreamReader.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/src/main/dpml/station/util/StreamReader.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,64 @@
+/*
+ * 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.station.util;
+
+import java.io.InputStream;
+
+import net.dpml.util.Logger;
+
+/**
+ * Stream reader utility class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public abstract class StreamReader extends Thread
+{
+ private final Logger m_logger;
+ private final InputStream m_input;
+
+ /**
+ * Creation of a new reader.
+ * @param logger the assigned logging channel
+ * @param input the subprocess input stream
+ */
+ public StreamReader( Logger logger, InputStream input )
+ {
+ m_input = input;
+ m_logger = logger;
+ }
+
+ /**
+ * Return the input stream.
+ * @return the subprocess input stream
+ */
+ protected InputStream getInputStream()
+ {
+ return m_input;
+ }
+
+ /**
+ * Return the assigned logging channel.
+ * @return the logging channel
+ */
+ protected Logger getLogger()
+ {
+ return m_logger;
+ }
+}

Added:
trunk/main/metro/appliance/src/main/net/dpml/station/ApplianceContentHandler.java
===================================================================
---
trunk/main/metro/appliance/src/main/net/dpml/station/ApplianceContentHandler.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/net/dpml/station/ApplianceContentHandler.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,341 @@
+/*
+ * 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.station;
+
+import dpml.lang.DOM3DocumentBuilder;
+import dpml.util.SimpleResolver;
+import dpml.util.ElementHelper;
+import dpml.util.DefaultLogger;
+import dpml.station.util.LoggingServer;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+import java.rmi.Remote;
+import java.util.Properties;
+import java.util.Map;
+import java.util.Hashtable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.MBeanException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+
+import net.dpml.transit.Artifact;
+import net.dpml.transit.ContentHandler;
+import net.dpml.transit.ContentManager;
+import net.dpml.lang.DecodingException;
+import net.dpml.util.Logger;
+import net.dpml.util.Resolver;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceException;
+import net.dpml.appliance.ApplianceManager;
+import net.dpml.appliance.ApplianceContentManager;
+import net.dpml.appliance.ApplianceFactory;
+import dpml.station.info.ApplianceDescriptor;
+import dpml.station.info.InfoDescriptor;
+import dpml.station.info.ProcessDescriptor;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * Content handler for the <tt>appliance</tt> artifact type.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ApplianceContentHandler extends ContentHandler implements
ApplianceContentManager, ApplianceFactory
+{
+ static final String NAMESPACE = "dpml:appliance";
+ static final String TYPE = "appliance";
+
+ private static final Logger LOGGER = new DefaultLogger(
"dpml.metro.appliance" );
+ private static final DOM3DocumentBuilder DOCUMENT_BUILDER =
+ new DOM3DocumentBuilder();
+
+ private static final List<ApplianceManager> MANAGERS =
+ new ArrayList<ApplianceManager>();
+
+ private static final ApplianceContentHandler SINGLETON =
newApplianceContentHandler();
+
+ private static ApplianceContentHandler newApplianceContentHandler()
+ {
+ ApplianceContentHandler handler = new ApplianceContentHandler();
+ 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", "Appliances" );
+ ObjectName name =
+ ObjectName.getInstance( "net.dpml.transit", table );
+ server.registerMBean( handler, name );
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ }
+ return handler;
+ }
+
+ public ApplianceContentHandler()
+ {
+ this( LOGGER );
+ }
+
+ protected ApplianceContentHandler( Logger logger )
+ {
+ logger.debug( "instantiating" );
+ }
+
+ /*
+ protected MBeanServerConnection getMBeanServerConnection() throws
MalformedURLException, IOException
+ {
+ String spec = System.getProperty( Station.STATION_JMX_URI_KEY );
+ if( null != spec )
+ {
+ JMXServiceURL url = new JMXServiceURL( spec );
+ JMXConnector connector = JMXConnectorFactory.connect( url, null
);
+ return connector.getMBeanServerConnection();
+ }
+ else
+ {
+ return ManagementFactory.getPlatformMBeanServer();
+ }
+ }
+ */
+
+ public ApplianceManager[] getApplianceManagers()
+ {
+ return MANAGERS.toArray( new ApplianceManager[0] );
+ }
+
+ /**
+ * Returns the type thar the content handler supports.
+ * @return the content type name
+ */
+ public String getType()
+ {
+ return TYPE;
+ }
+
+ /**
+ * Returns the content in the form of a {@link
net.dpml.appliance.Appliance}.
+ * @param connection the url connection
+ * @return the application handler
+ * @exception IOException if an IO error occurs
+ */
+ public Object getContent( URLConnection connection ) throws IOException
+ {
+ return newAppliance( connection, null );
+ }
+
+ /**
+ * Returns the content assignable to the first recognized class in the
list
+ * of suppied classes. If the class array is empty the application
handler 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
+ {
+ ApplianceDescriptor descriptor = getApplianceDescriptor( connection
);
+ return getContentForClasses( descriptor, classes );
+ }
+
+ /**
+ * 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
+ {
+ ApplianceDescriptor descriptor = getApplianceDescriptor( connection
);
+ return newAppliance( partition, descriptor );
+ }
+
+ static <T>T getContentForClass( URLConnection connection, Class<T> type
) throws IOException
+ {
+ ApplianceDescriptor descriptor = getApplianceDescriptor( connection
);
+ return getContentForClass( descriptor, type );
+ }
+
+ private static Object getContentForClasses( ApplianceDescriptor
descriptor, Class<?>[] classes ) throws IOException
+ {
+ for( Class<?> c : classes )
+ {
+ Object value = getContentForClass( descriptor, c );
+ if( null != value )
+ {
+ return value;
+ }
+ }
+ return null;
+ }
+
+ private static <T>T getContentForClass( ApplianceDescriptor descriptor,
Class<T> type ) throws IOException
+ {
+ if( ApplianceDescriptor.class == type )
+ {
+ return type.cast( descriptor );
+ }
+ else if( Appliance.class == type )
+ {
+ String key = "" + System.identityHashCode( descriptor );
+ Appliance appliance = newAppliance( key, descriptor );
+ return type.cast( appliance );
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private static final Appliance newAppliance( String key,
ApplianceDescriptor descriptor ) throws IOException
+ {
+ if( null == key )
+ {
+ throw new NullPointerException( "key" );
+ }
+ Logger logger = getLogger();
+ Application application = new Application( logger, key, descriptor );
+ Appliance appliance = application.getAppliance();
+ register( key, appliance );
+ return appliance;
+ }
+
+ static void register( String id, Appliance appliance )
+ {
+ if( appliance instanceof ApplianceManager )
+ {
+ if( null == id )
+ {
+ throw new NullPointerException( "id" );
+ }
+ ApplianceManager manager = (ApplianceManager) appliance;
+ if( !MANAGERS.contains( manager ) )
+ {
+ try
+ {
+ MBeanServer server =
ManagementFactory.getPlatformMBeanServer();
+ Hashtable<String, String> table = new Hashtable<String,
String>();
+ table.put( "type", "Appliances" );
+ table.put( "name", id );
+ ObjectName name =
+ ObjectName.getInstance( "net.dpml.transit", table );
+ server.registerMBean( manager, name );
+ MANAGERS.add( manager );
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ static void deregister( Appliance appliance )
+ {
+ if( appliance instanceof ApplianceManager )
+ {
+ ApplianceManager manager = (ApplianceManager) appliance;
+ if( MANAGERS.contains( manager ) )
+ {
+ MANAGERS.remove( manager );
+ }
+ }
+ }
+
+ static Appliance newAppliance( String key, URI uri ) throws IOException
+ {
+ URL url = Artifact.toURL( uri );
+ URLConnection connection = url.openConnection();
+ ApplianceDescriptor descriptor = getApplianceDescriptor( connection
);
+ return newAppliance( key, descriptor );
+ }
+
+ //static final Appliance newLocalAppliance( String partition, URI
codebase ) throws IOException
+ //{
+ // return new StandardAppliance( LOGGER, partition, codebase );
+ //}
+
+ private static ApplianceDescriptor getApplianceDescriptor( URLConnection
connection ) throws IOException
+ {
+ URL url = connection.getURL();
+ try
+ {
+ Document document = DOCUMENT_BUILDER.parse( url );
+ final Element element = document.getDocumentElement();
+ TypeInfo type = element.getSchemaTypeInfo();
+ String namespace = type.getTypeNamespace();
+ if( NAMESPACE.equals( namespace ) )
+ {
+ URI uri = URI.create( url.toExternalForm() );
+ Resolver resolver = new SimpleResolver();
+ return new ApplianceDescriptor( element, resolver, uri );
+ }
+ else
+ {
+ final String error =
+ "ApplianceDescriptor namespace not recognized."
+ + "\nFound: " + namespace
+ + "\nExpecting: " + NAMESPACE;
+ throw new DecodingException( error, element );
+ }
+ }
+ catch( IOException e )
+ {
+ throw e;
+ }
+ catch( Exception e )
+ {
+ final String error = "Unexpected error while constructing
application profile: " + url;
+ IOException ioe = new IOException();
+ ioe.initCause( e );
+ throw ioe;
+ }
+ }
+
+ private static Logger getLogger()
+ {
+ return LOGGER;
+ }
+}

Added:
trunk/main/metro/appliance/src/main/net/dpml/station/ApplianceNamespaceResolver.java
===================================================================
---
trunk/main/metro/appliance/src/main/net/dpml/station/ApplianceNamespaceResolver.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/net/dpml/station/ApplianceNamespaceResolver.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,92 @@
+/*
+ * 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.station;
+
+import dpml.lang.DOMInput;
+
+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 ApplianceNamespaceResolver implements LSResourceResolver
+{
+ /**
+ * Return the schema definition for a <tt>dpml:appliance</tt> namespace.
+ *
+ * @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( ApplianceContentHandler.NAMESPACE.equals( namespace ) )
+ {
+ return classloader.getResource(
"dpml/metro/dpml-metro-appliance.xsd" );
+ }
+ else
+ {
+ return null;
+ }
+ }
+}

Added: trunk/main/metro/appliance/src/main/net/dpml/station/Application.java
===================================================================
--- trunk/main/metro/appliance/src/main/net/dpml/station/Application.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/src/main/net/dpml/station/Application.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,404 @@
+/*
+ * 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.station;
+
+import dpml.util.PID;
+
+import dpml.station.connector.LocalConnector;
+import dpml.station.info.ApplianceDescriptor;
+import dpml.station.util.OutputStreamReader;
+import dpml.station.util.StreamReader;
+import dpml.station.util.LoggingServer;
+
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.net.URL;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Date;
+import java.util.Set;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
+import java.rmi.ConnectException;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.server.UnicastRemoteObject;
+
+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.ApplianceException;
+import net.dpml.appliance.ApplianceListener;
+import net.dpml.appliance.ApplianceEvent;
+
+import net.dpml.util.Logger;
+
+import net.dpml.lang.DuplicateKeyException;
+import net.dpml.lang.Strategy;
+import net.dpml.runtime.Status;
+
+/**
+ * Process configuration and management support class.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+final class Application
+{
+ static
+ {
+ LoggingServer.init();
+ }
+
+ private static final PID PROCESS_ID = new PID();
+
+ private final ApplianceDescriptor m_descriptor;
+ private final Logger m_logger;
+ private final ProcessBuilder m_builder;
+ private final LocalConnector m_connector;
+ private final String m_address;
+ private final String m_key;
+
+ Application( Logger logger, String key, ApplianceDescriptor descriptor )
throws IOException
+ {
+ m_logger = logger;
+ m_descriptor = descriptor;
+ m_key = key;
+
+ int port = getConnectorPort();
+ try
+ {
+ m_connector = new LocalConnector();
+ Registry registry = resolveRegistry( port );
+ m_address =
+ "dpml/station/"
+ + PROCESS_ID.getValue()
+ + "/"
+ + System.identityHashCode( this );
+ registry.bind( m_address, m_connector );
+ }
+ catch( ApplianceException e )
+ {
+ throw e;
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unable to bind local station callback to RMI registry.";
+ throw new ApplianceException( error, e );
+ }
+
+ m_builder = newProcessBuilder();
+ }
+
+ private Registry resolveRegistry( int port )throws ApplianceException
+ {
+ try
+ {
+ Registry registry = LocateRegistry.createRegistry( port );
+ getLogger().debug( "created local registry on port " + port );
+ return registry;
+ }
+ catch( RemoteException re )
+ {
+ try
+ {
+ Registry registry = LocateRegistry.getRegistry( port );
+ getLogger().debug( "using local registry on port " + port );
+ return registry;
+ }
+ catch( RemoteException e )
+ {
+ final String error =
+ "Unable to locate or create RMI registry to due a remote
exeception.";
+ throw new ApplianceException( error, e );
+ }
+ }
+ }
+
+ private int getConnectorPort()
+ {
+ String port = System.getProperty( "dpml.appliance.connector.port",
null );
+ if( null == port )
+ {
+ return Registry.REGISTRY_PORT;
+ }
+ else
+ {
+ return Integer.parseInt( port );
+ }
+ }
+
+ /**
+ * Returns the part URI as a string.
+ * @return the codebase uri
+ */
+ //public String getCodebaseURI()
+ //{
+ // return m_descriptor.getURI().toASCIIString();
+ //}
+
+ /**
+ * Returns the part title.
+ * @return the title
+ */
+ public String getTitle()
+ {
+ return m_descriptor.getTitle();
+ }
+
+ /**
+ * Returns the part description.
+ * @return the description
+ */
+ public String getDescription()
+ {
+ return m_descriptor.getDescription();
+ }
+
+ public Appliance getAppliance() throws IOException
+ {
+ int timeout = m_descriptor.getStartupTimeout();
+ if( 0 == timeout )
+ {
+ return getAppliance( TimeUnit.SECONDS, 60 );
+ }
+ else
+ {
+ return getAppliance( TimeUnit.SECONDS, timeout );
+ }
+ }
+
+ public Appliance getAppliance( TimeUnit unit, int timeout ) throws
IOException
+ {
+ final Process process = newProcess();
+ long now = new Date().getTime();
+ Appliance appliance = m_connector.getAppliance( unit, timeout );
+ long then = new Date().getTime();
+ long diff = then - now;
+ getLogger().info( "process established in " + diff + " ms" );
+ return appliance;
+ }
+
+ Logger getLogger()
+ {
+ return m_logger;
+ }
+
+ ApplianceDescriptor getApplianceDescriptor()
+ {
+ return m_descriptor;
+ }
+
+ Process newProcess() throws IOException
+ {
+ Process process = m_builder.start();
+ setShutdownHook( process );
+ OutputStreamReader output =
+ new OutputStreamReader( m_logger, process.getInputStream() );
+ output.setDaemon( true );
+ output.start();
+ return process;
+ }
+
+ private ProcessBuilder newProcessBuilder() throws IOException
+ {
+ List<String> commands = getProcessCommands();
+ ProcessBuilder builder = new ProcessBuilder( commands );
+ builder.redirectErrorStream( true );
+ File dir = getValidatedProcessDirectory();
+ builder.directory( dir );
+ Map<String,String> environment = builder.environment();
+ Map<String,String> env = m_descriptor.getEnvironmentMap();
+ environment.putAll( env );
+ return builder;
+ }
+
+ private File getValidatedProcessDirectory() throws IOException
+ {
+ File file = getProcessDirectory();
+ if( null == file )
+ {
+ return file;
+ }
+ if( !file.exists() )
+ {
+ final String error =
+ "Process basedir not found: "
+ + file.getCanonicalPath();
+ throw new ApplianceException( error, null,
m_descriptor.getElement() );
+ //throw new FileNotFoundException( error );
+ }
+ if( !file.isDirectory() )
+ {
+ final String error =
+ "Process basedir is not a directory: "
+ + file.getCanonicalPath();
+ throw new ApplianceException( error, null,
m_descriptor.getElement() );
+ //throw new IllegalArgumentException( error );
+ }
+ return file;
+ }
+
+ private File getProcessDirectory()
+ {
+ String path = m_descriptor.getPath();
+ if( null == path )
+ {
+ return null;
+ }
+ else
+ {
+ File file = new File( path );
+ if( file.isAbsolute() )
+ {
+ return file;
+ }
+ else
+ {
+ File base = new File( System.getProperty( "user.dir" ) );
+ return new File( base, path );
+ }
+ }
+ }
+
+ private List<String> getProcessCommands() throws IOException
+ {
+ List<String> list = new ArrayList<String>();
+
+ //
+ // add the metro command
+ //
+
+ String executable = m_descriptor.getExecutable();
+ list.add( executable );
+
+ //
+ // add partition
+ //
+
+ if( null != m_key )
+ {
+ list.add( "-Ddpml.station.partition=" + m_key );
+ }
+
+ //
+ // add connection key
+ //
+
+ list.add( "-Ddpml.appliance.connector.key=" + m_address );
+
+ //
+ // add codebase uri
+ //
+
+ URI codebase = m_descriptor.getCodebaseURI();
+ if( null != codebase )
+ {
+ String spec = codebase.toASCIIString();
+ list.add( "-Ddpml.appliance.codebase.uri=" + spec );
+ }
+
+ //
+ // add decommissioning timeout
+ //
+
+ list.add( "-Ddpml.decommmission.timeout=" +
m_descriptor.getShutdownTimeout() );
+
+ //
+ // add default system properties
+ //
+
+ list.add(
"-Djava.util.logging.config.class=dpml.util.DepotLoggingConfiguration" );
+ //list.add(
"-Ddpml.logging.config=local:properties:dpml/station/application" );
+
+ //
+ // add declared system properties
+ //
+
+ Properties properties = m_descriptor.getSystemProperties();
+ Set<String> names = properties.stringPropertyNames();
+ for( String name : names )
+ {
+ String value = properties.getProperty( name ); // expand symbols?
+ list.add( "-D" + name + "=" + value );
+ }
+
+ //
+ // add the codebase uri
+ //
+
+ URI uri = m_descriptor.getTargetURI();
+ String spec = uri.toASCIIString();
+ list.add( spec );
+
+ return list;
+ }
+
+ private static void setShutdownHook( final ApplianceListener listener )
+ {
+ Runtime.getRuntime().addShutdownHook(
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ UnicastRemoteObject.unexportObject( listener, false );
+ }
+ catch( RemoteException e )
+ {
+ }
+ }
+ }
+ );
+ }
+
+ private static void setShutdownHook( final Process process )
+ {
+ Runtime.getRuntime().addShutdownHook(
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ process.destroy();
+ }
+ catch( Throwable e )
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ );
+ }
+}

Added:
trunk/main/metro/appliance/src/main/net/dpml/station/CompositeAppliance.java
===================================================================
---
trunk/main/metro/appliance/src/main/net/dpml/station/CompositeAppliance.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/net/dpml/station/CompositeAppliance.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,171 @@
+/*
+ * 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.station;
+
+import dpml.station.info.PlanDescriptor;
+import dpml.station.info.EntryDescriptor;
+
+import dpml.appliance.ApplianceHelper;
+import dpml.appliance.AbstractAppliance;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceException;
+import net.dpml.appliance.ApplianceListener;
+import net.dpml.appliance.ApplianceEvent;
+import net.dpml.appliance.ApplianceManager;
+
+import net.dpml.runtime.Status;
+
+import net.dpml.transit.Artifact;
+import net.dpml.util.Logger;
+
+/**
+ * Appliance implementation that aggregates a collection of ordered
appliance instances.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+class CompositeAppliance extends AbstractAppliance implements Appliance,
ApplianceManager
+{
+ private PlanDescriptor m_descriptor;
+ private ArrayList<Appliance> m_list = new ArrayList<Appliance>();
+
+ CompositeAppliance( final Logger logger, final PlanDescriptor descriptor
) throws IOException
+ {
+ this( logger, null, descriptor );
+ }
+
+ CompositeAppliance( final Logger logger, final String partition, final
PlanDescriptor descriptor ) throws IOException
+ {
+ super( logger, descriptor.getCodebaseURI() );
+
+ m_descriptor = descriptor;
+
+ for( EntryDescriptor entry : m_descriptor.getEntryDescriptors() )
+ {
+ URI codebase = descriptor.getCodebaseURI();
+ String name = getQualifiedName( partition, entry.getKey() );
+ logger.info( "loading " + name );
+ Appliance appliance = getApplianceForType( partition, entry );
+ if( null == appliance )
+ {
+ final String error =
+ "Failed to resolve an appliance for the uri [ "
+ + codebase
+ + "]."
+ throw new ApplianceException( error );
+ }
+ else
+ {
+ m_list.add( appliance );
+ ApplianceContentHandler.register( name, appliance );
+ }
+ }
+
+ ApplianceEvent ae = new ApplianceEvent( this, Status.CREATION );
+ processEvent( ae );
+ }
+
+ /**
+ * Returns the plan URI as a string.
+ * @return the codebase uri
+ */
+ public String getCodebaseURI()
+ {
+ return m_descriptor.getCodebaseURI().toASCIIString();
+ }
+
+ private String getQualifiedName( String partition, String key )
+ {
+ if( null == partition )
+ {
+ return key;
+ }
+ else
+ {
+ return partition + "." + key;
+ }
+ }
+
+ private Appliance getApplianceForType( String partition, EntryDescriptor
entry ) throws IOException
+ {
+ String key = entry.getKey();
+ String address = getQualifiedName( partition, key );
+ URI uri = entry.getURI();
+ return ApplianceHelper.newAppliance( address, uri );
+ }
+
+ public void commission() throws IOException
+ {
+ getLogger().info( "commissioning plan" );
+ synchronized( this )
+ {
+ ApplianceEvent ae = new ApplianceEvent( this, Status.INCARNATION
);
+ processEvent( ae );
+ super.commission();
+ for( Appliance appliance : m_list )
+ {
+ appliance.commission();
+ }
+ }
+ getLogger().info( "plan commissioning complete" );
+ }
+
+ protected void decommission( long timeout, TimeUnit units ) throws
RemoteException
+ {
+ getLogger().info( "decommissioning plan" );
+ synchronized( this )
+ {
+ ApplianceEvent ee = new ApplianceEvent( this,
Status.ETHERIALIZATION );
+ processEvent( ee );
+ Appliance[] appliances = m_list.toArray( new Appliance[0] );
+ for( int i = appliances.length; i>0; i-- )
+ {
+ Appliance appliance = appliances[i-1];
+ appliance.decommission();
+ }
+ ApplianceEvent te = new ApplianceEvent( this, Status.TERMINATION
);
+ processEvent( te );
+ super.decommission( timeout, units );
+ }
+ getLogger().info( "plan decommissioning complete" );
+ }
+
+ /**
+ * 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
+ {
+ return null;
+ }
+}
+

Added:
trunk/main/metro/appliance/src/main/net/dpml/station/PlanContentHandler.java
===================================================================
---
trunk/main/metro/appliance/src/main/net/dpml/station/PlanContentHandler.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/net/dpml/station/PlanContentHandler.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2007 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.station;
+
+import dpml.lang.DOM3DocumentBuilder;
+import dpml.util.SimpleResolver;
+import dpml.util.ElementHelper;
+import dpml.util.DefaultLogger;
+
+import dpml.station.info.EntryDescriptor;
+import dpml.station.info.PlanDescriptor;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.lang.management.ManagementFactory;
+import java.util.Hashtable;
+
+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.ApplianceFactory;
+
+import net.dpml.lang.DecodingException;
+
+import net.dpml.transit.Artifact;
+import net.dpml.transit.ContentHandler;
+
+import net.dpml.util.Resolver;
+import net.dpml.util.Logger;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * Content handler for the <tt>plan</tt> artifact type.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class PlanContentHandler extends ApplianceContentHandler //implements
ApplianceFactory
+{
+ private static final Logger LOGGER = new DefaultLogger(
"dpml.station.plan" );
+ static final String NAMESPACE = "dpml:plan";
+ static final String TYPE = "plan";
+
+ private static final DOM3DocumentBuilder DOCUMENT_BUILDER =
+ new DOM3DocumentBuilder();
+
+ public PlanContentHandler()
+ {
+ super( LOGGER );
+ }
+
+ /**
+ * Returns the type thar the content handler supports.
+ * @return the content type name
+ */
+ public String getType()
+ {
+ return TYPE;
+ }
+
+ /**
+ * Returns the content in the form of a {@link
net.dpml.appliance.Appliance}.
+ * @param connection the url connection
+ * @return the application handler
+ * @exception IOException if an IO error occurs
+ */
+ public Object getContent( URLConnection connection ) throws IOException
+ {
+ return getContentForClass( connection, Appliance.class );
+ }
+
+ /**
+ * Returns the content assignable to the first recognized class in the
list
+ * of suppied classes. If the class array is empty the application
handler 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
+ {
+ PlanDescriptor descriptor = getPlanDescriptor( connection );
+ return getContentForClasses( descriptor, classes );
+ }
+
+ /**
+ * 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
+ {
+ PlanDescriptor descriptor = getPlanDescriptor( connection );
+ String name = descriptor.getName();
+ String path = getQualifiedName( partition, name );
+ Appliance appliance = new CompositeAppliance( LOGGER, path,
descriptor );
+ register( path, appliance );
+ return appliance;
+ }
+
+ private static String getQualifiedName( String partition, String name )
+ {
+ if( null == partition )
+ {
+ return name;
+ }
+ else
+ {
+ return partition + "." + name;
+ }
+ }
+
+ static <T>T getContentForClass( URLConnection connection, Class<T> type
) throws IOException
+ {
+ PlanDescriptor descriptor = getPlanDescriptor( connection );
+ return getContentForClass( descriptor, type );
+ }
+
+ private static Object getContentForClasses(
+ PlanDescriptor descriptor, Class<?>[] classes ) throws IOException
+ {
+ for( Class<?> c : classes )
+ {
+ Object value = getContentForClass( descriptor, c );
+ if( null != value )
+ {
+ return value;
+ }
+ }
+ return null;
+ }
+
+ private static <T>T getContentForClass(
+ PlanDescriptor descriptor, Class<T> type ) throws IOException
+ {
+ if( PlanDescriptor.class == type )
+ {
+ return type.cast( descriptor );
+ }
+ else if( Appliance.class == type )
+ {
+ String name = descriptor.getName();
+ CompositeAppliance appliance = new CompositeAppliance( LOGGER,
name, descriptor );
+ register( name, appliance );
+ return type.cast( appliance );
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public static Appliance newAppliance( String key, URI uri ) throws
IOException
+ {
+ URL url = Artifact.toURL( uri );
+ URLConnection connection = url.openConnection();
+ PlanDescriptor descriptor = getPlanDescriptor( connection );
+ Appliance appliance = new CompositeAppliance( LOGGER, key,
descriptor );
+ register( key, appliance );
+ return appliance;
+ }
+
+ private static PlanDescriptor getPlanDescriptor( URLConnection
connection ) throws IOException
+ {
+ URL url = connection.getURL();
+ try
+ {
+ Document document = DOCUMENT_BUILDER.parse( url );
+ final Element element = document.getDocumentElement();
+ TypeInfo type = element.getSchemaTypeInfo();
+ String namespace = type.getTypeNamespace();
+ if( NAMESPACE.equals( namespace ) )
+ {
+ URI codebase = url.toURI();
+ Resolver resolver = new SimpleResolver();
+ return new PlanDescriptor( element, resolver, codebase );
+ }
+ else
+ {
+ final String error =
+ "Document namespace not recognized."
+ + "\nFound: " + namespace
+ + "\nExpecting: " + NAMESPACE;
+ throw new DecodingException( error, element );
+ }
+ }
+ catch( IOException e )
+ {
+ throw e;
+ }
+ catch( Exception e )
+ {
+ final String error = "Unexpected error while constructing
scenario: " + url;
+ IOException ioe = new IOException();
+ ioe.initCause( e );
+ throw ioe;
+ }
+ }
+}

Added:
trunk/main/metro/appliance/src/main/net/dpml/station/PlanNamespaceResolver.java
===================================================================
---
trunk/main/metro/appliance/src/main/net/dpml/station/PlanNamespaceResolver.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/net/dpml/station/PlanNamespaceResolver.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,92 @@
+/*
+ * 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.station;
+
+import dpml.lang.DOMInput;
+
+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 for the <tt>dpml:plan</tt> namespace.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public final class PlanNamespaceResolver implements LSResourceResolver
+{
+ /**
+ * Return the schema definition for a <tt>dpml:plan</tt> namespace.
+ *
+ * @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( PlanContentHandler.NAMESPACE.equals( namespace ) )
+ {
+ return classloader.getResource( "dpml/metro/dpml-metro-plan.xsd"
);
+ }
+ else
+ {
+ return null;
+ }
+ }
+}

Added: trunk/main/metro/appliance/src/main/net/dpml/station/Station.java
===================================================================
--- trunk/main/metro/appliance/src/main/net/dpml/station/Station.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/src/main/net/dpml/station/Station.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,38 @@
+/*
+ * 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.station;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * Station interface.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public interface Station extends Remote
+{
+ static final String STATION_CONNECTOR_KEY = "dpml.station.key";
+ static final String STATION_JMX_URI_KEY = "dpml.station.jmx.uri";
+ //static final String STATION_RMI_PORT = "dpml.station.rmi.port";
+
+ void shutdown() throws RemoteException;
+}
+

Added:
trunk/main/metro/appliance/src/main/net/dpml/station/StationException.java
===================================================================
---
trunk/main/metro/appliance/src/main/net/dpml/station/StationException.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/main/net/dpml/station/StationException.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,73 @@
+/*
+ * 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.station;
+
+import net.dpml.appliance.ApplianceException;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Station related exception.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StationException extends ApplianceException
+{
+ /**
+ * Serial version identifier.
+ */
+ static final long serialVersionUID = 1L;
+
+ /**
+ * Construct a new <code>StationException</code>.
+ *
+ * @param message the error message
+ */
+ public StationException( final String message )
+ {
+ super( message, null, null );
+ }
+
+ /**
+ * Construct a new <code>StationException</code>.
+ *
+ * @param message the error message
+ * @param cause the causal exception
+ */
+ public StationException( 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 StationException( final String message, Throwable cause, Element
element )
+ {
+ super( message, cause, element );
+ }
+
+}
+

Added: trunk/main/metro/appliance/src/main/net/dpml/station/package-info.java
===================================================================
--- trunk/main/metro/appliance/src/main/net/dpml/station/package-info.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/appliance/src/main/net/dpml/station/package-info.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -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>Application profile and process execution support.</p>
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+package net.dpml.station;

Added:
trunk/main/metro/appliance/src/test/net/dpml/appliance/AbstractTestCase.java
===================================================================
---
trunk/main/metro/appliance/src/test/net/dpml/appliance/AbstractTestCase.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/test/net/dpml/appliance/AbstractTestCase.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,66 @@
+/*
+ * 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.appliance;
+
+import dpml.station.info.ApplianceDescriptor;
+import dpml.station.info.PlanDescriptor;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLConnection;
+
+import junit.framework.TestCase;
+
+import net.dpml.lang.Strategy;
+import net.dpml.lang.TypeCastException;
+
+import net.dpml.station.ApplianceContentHandler;
+import net.dpml.station.PlanContentHandler;
+
+/**
+ * Test dealing with the appliance descriptor.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public abstract class AbstractTestCase extends TestCase
+{
+ static final ApplianceContentHandler HANDLER = new
ApplianceContentHandler();
+
+ ApplianceDescriptor loadApplianceDescriptor( String path ) throws
Exception
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ File dir = new File( System.getProperty( "project.test.dir" ) );
+ File file = new File( dir, path );
+ URL url = file.toURI().toURL();
+ URLConnection connection = url.openConnection();
+ ApplianceContentHandler handler = new ApplianceContentHandler();
+ return (ApplianceDescriptor) handler.getContent( connection, new
Class[]{ ApplianceDescriptor.class } );
+ }
+
+ PlanDescriptor loadPlanDescriptor( String path ) throws Exception
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ File dir = new File( System.getProperty( "project.test.dir" ) );
+ File file = new File( dir, path );
+ URL url = file.toURI().toURL();
+ URLConnection connection = url.openConnection();
+ PlanContentHandler handler = new PlanContentHandler();
+ return (PlanDescriptor) handler.getContent( connection, new Class[]{
PlanDescriptor.class } );
+ }
+}

Added:
trunk/main/metro/appliance/src/test/net/dpml/appliance/ApplianceDescriptorTestCase.java
===================================================================
---
trunk/main/metro/appliance/src/test/net/dpml/appliance/ApplianceDescriptorTestCase.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/test/net/dpml/appliance/ApplianceDescriptorTestCase.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -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.appliance;
+
+import java.net.URI;
+import java.util.Properties;
+import java.util.Map;
+
+import dpml.station.info.ApplianceDescriptor;
+
+/**
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ApplianceDescriptorTestCase extends AbstractTestCase
+{
+ public void testApplianceDescriptor() throws Exception
+ {
+ ApplianceDescriptor application = loadApplianceDescriptor(
"appliance.xml" );
+ String path = application.getPath();
+ int startup = application.getStartupTimeout();
+ int shutdown = application.getShutdownTimeout();
+ Properties properties = application.getSystemProperties();
+ Map environment = application.getEnvironmentMap();
+ assertEquals( "startup", 0, startup );
+ assertEquals( "shutdown", 0, shutdown );
+ assertEquals( "path", null, path );
+ assertEquals( "system", "bar", properties.getProperty( "foo" ) );
+ assertEquals( "environment", "BAR", environment.get( "FOO" ) );
+ URI uri = new URI(
"link:part:dpml/lang/dpml-lang-sample?message=Hello%20World,port=1024" );
+ URI target = application.getTargetURI();
+ assertEquals( "uri", uri, target );
+ }
+}

Added:
trunk/main/metro/appliance/src/test/net/dpml/appliance/PlanDescriptorTestCase.java
===================================================================
---
trunk/main/metro/appliance/src/test/net/dpml/appliance/PlanDescriptorTestCase.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/appliance/src/test/net/dpml/appliance/PlanDescriptorTestCase.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,48 @@
+/*
+ * 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.appliance;
+
+import dpml.station.info.PlanDescriptor;
+import dpml.station.info.EntryDescriptor;
+
+import java.net.URI;
+import java.util.Properties;
+import java.util.Map;
+
+/**
+ * Scenario descriptor testcase.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class PlanDescriptorTestCase extends AbstractTestCase
+{
+ public void testScenarioTitle() throws Exception
+ {
+ PlanDescriptor scenario = loadPlanDescriptor( "plan.xml" );
+ String title = scenario.getTitle();
+ assertEquals( "title", "Plan Demo", title );
+ }
+
+ public void testPlanURIs() throws Exception
+ {
+ PlanDescriptor scenario = loadPlanDescriptor( "plan.xml" );
+ EntryDescriptor[] entries = scenario.getEntryDescriptors();
+ assertEquals( "uri", 3, entries.length );
+ }
+}

Deleted: trunk/main/metro/build.xml
===================================================================
--- trunk/main/metro/build.xml 2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/build.xml 2007-02-08 23:33:09 UTC (rev 1821)
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
- 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.
--->
-
-<project name="dpml-metro" default="install" basedir="."
- xmlns:transit="antlib:net.dpml.transit" >
-
- <transit:import uri="local:template:dpml/tools/standard"/>
-
-</project>

Added: trunk/main/metro/connector/build.xml
===================================================================
--- trunk/main/metro/connector/build.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/connector/build.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<project name="dpml-lang-remote" default="install" basedir="."
+ xmlns:x="antlib:dpml.tools">
+
+ <x:import uri="local:template:dpml/tools/standard"/>
+
+ <target name="build" depends="standard.build">
+ <x:rmic>
+ <include name="**/LocalConnector.class"/>
+ </x:rmic>
+ </target>
+
+</project>

Added: trunk/main/metro/connector/etc/component.xml
===================================================================
--- trunk/main/metro/connector/etc/component.xml 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/connector/etc/component.xml 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<component xmlns="dpml:metro" name="station"
type="dpml.station.DefaultStation"/>

Added: trunk/main/metro/connector/etc/local.xml
===================================================================
--- trunk/main/metro/connector/etc/local.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/connector/etc/local.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<component xmlns="dpml:metro" name="local" type="dpml.station.LocalStation"/>

Added: trunk/main/metro/connector/project.xml
===================================================================
--- trunk/main/metro/connector/project.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/connector/project.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<project xmlns="dpml:library" name="dpml-metro-connector">
+
+ <info title="DPML Metro Station"/>
+
+ <types>
+ <type id="jar"/>
+ <!--
+ <type id="part" source="etc/component.xml" alias="true"/>
+ <type id="part" source="etc/local.xml" alias="true"
name="dpml-metro-local"/>
+ -->
+ </types>
+
+ <dependencies>
+ <runtime>
+ <include ref="dpml/lang/dpml-lang-part"/>
+ </runtime>
+ </dependencies>
+
+</project>
+

Added:
trunk/main/metro/connector/src/main/dpml/station/connector/LocalConnector.java
===================================================================
---
trunk/main/metro/connector/src/main/dpml/station/connector/LocalConnector.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/connector/src/main/dpml/station/connector/LocalConnector.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,126 @@
+/*
+ * 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.station.connector;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceConnector;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Utility class used to handler the establishment of a connection between
+ * a spawned sub-process and a parent process.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class LocalConnector extends UnicastRemoteObject implements
ApplianceConnector
+{
+ private final Object m_lock = new Object();
+ private Appliance m_appliance;
+ private Monitor m_monitor;
+
+ public LocalConnector() throws RemoteException
+ {
+ super();
+ }
+
+ /**
+ * Connect an appliance to the station.
+ * @param appliance the appliance
+ * @exception RemoteException if a remote error occurs
+ */
+ public void connect( Appliance appliance ) throws RemoteException
+ {
+ synchronized( m_lock )
+ {
+ m_appliance = appliance;
+ if( null != m_monitor )
+ {
+ m_monitor.interrupt();
+ }
+ }
+ }
+
+ public Appliance getAppliance( TimeUnit units, int timeout ) throws
IOException
+ {
+ synchronized( m_lock )
+ {
+ if( null != m_appliance )
+ {
+ return m_appliance;
+ }
+ else
+ {
+ m_monitor = new Monitor( units, timeout );
+ m_monitor.setName( "DPML Connection Monitor "
+ + System.identityHashCode( this ) );
+ m_monitor.start();
+ }
+ }
+
+ try
+ {
+ m_monitor.join();
+ }
+ catch( InterruptedException e )
+ {
+ }
+
+ synchronized( m_lock )
+ {
+ m_monitor = null;
+ if( null != m_appliance )
+ {
+ return m_appliance;
+ }
+ else
+ {
+ throw new IOException( "Appliance connection timeout (" +
timeout + ")." );
+ }
+ }
+ }
+
+ private class Monitor extends Thread
+ {
+ private int m_timeout;
+ private TimeUnit m_units;
+
+ public Monitor( TimeUnit units, int timeout )
+ {
+ m_timeout = timeout;
+ m_units = units;
+ }
+
+ public void run()
+ {
+ try
+ {
+ m_units.sleep( m_timeout );
+ //Thread.currentThread().sleep( m_timeout );
+ }
+ catch( InterruptedException e )
+ {
+ }
+ }
+ }
+}

Added: trunk/main/metro/main/build.xml
===================================================================
--- trunk/main/metro/main/build.xml 2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/main/build.xml 2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<project name="dpml-metro-main" default="install" basedir="."
+ xmlns:x="antlib:dpml.tools">
+
+ <x:import uri="local:template:dpml/tools/standard"/>
+
+ <available property="metro.exe.available"
file="${dpml.system}/bin/metro.exe"/>
+
+ <target name="build" depends="standard.build">
+ <!--
+ <x:rmic>
+ <include name="**/StandardAppliance.class"/>
+ </x:rmic>
+ -->
+ </target>
+
+ <target name="install" depends="bin,standard.install">
+ <copy todir="${dpml.system}" preservelastmodified="true"
overwrite="true">
+ <fileset dir="target">
+ <include name="bin/metro.lap"/>
+ <include name="bin/metro.policy"/>
+ <include name="bin/metro"/>
+ </fileset>
+ </copy>
+ <chmod perm="755">
+ <fileset dir="${dpml.system}/bin">
+ <include name="metro"/>
+ </fileset>
+ </chmod>
+ </target>
+
+ <target name="bin" depends="standard.install" unless="metro.exe.available">
+ <mkdir dir="${dpml.system}/bin"/>
+ <copy todir="${dpml.system}" preservelastmodified="true">
+ <fileset dir="target">
+ <include name="bin/metro.exe"/>
+ </fileset>
+ </copy>
+ </target>
+
+</project>

Added: trunk/main/metro/main/etc/bin/metro
===================================================================
--- trunk/main/metro/main/etc/bin/metro 2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/main/etc/bin/metro 2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+
+METRO_JVM_OPTS="-Ddpml.depot.application=link:part:dpml/metro/dpml-metro-main"
+
+if [ "$DEPOT_JVM_OPTS" = "" ] ; then
+ DEPOT_JVM_OPTS=$METRO_JVM_OPTS
+else
+ DEPOT_JVM_OPTS="$METRO_JVM_OPTS $DEPOT_JVM_OPTS"
+fi
+export DEPOT_JVM_OPTS
+
+depot $*

Added: trunk/main/metro/main/etc/bin/metro.exe
===================================================================
(Binary files differ)


Property changes on: trunk/main/metro/main/etc/bin/metro.exe
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream

Added: trunk/main/metro/main/etc/bin/metro.lap
===================================================================
--- trunk/main/metro/main/etc/bin/metro.lap 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/main/etc/bin/metro.lap 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,17 @@
+#
+# This file contains the runtime configuration of the Janel java launcher
application.
+#
+
+-Djava.ext.dirs=${env.DPML_HOME}\share\lib\ext
+-Djava.endorsed.dirs=${env.DPML_HOME}\share\lib\endorsed
+-Djava.system.class.loader=dpml.util.SystemClassLoader
+-Djava.security.policy=${env.DPML_HOME}\share\bin\metro.policy
+-Djava.protocol.handler.pkgs=dpml.transit
+-Djava.rmi.server.RMIClassLoaderSpi=dpml.util.FederatingClassLoader
+-Dcom.sun.management.jmxremote
+-Ddpml.class.path=link:jar:dpml/lang/dpml-lang-part
+-Ddpml.depot.application=link:part:dpml/metro/dpml-metro-main
+-Ddpml.jmx.enabled=true
+janel.main.class=dpml.util.Main
+janel.min.java.version=1.4.0
+janel.sysprop.process.id=true

Added: trunk/main/metro/main/etc/bin/metro.policy
===================================================================
--- trunk/main/metro/main/etc/bin/metro.policy 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/main/etc/bin/metro.policy 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,4 @@
+grant {
+ permission java.security.AllPermission;
+};
+

Added: trunk/main/metro/main/etc/component.xml
===================================================================
--- trunk/main/metro/main/etc/component.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/main/etc/component.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<component xmlns="dpml:metro" name="dpml.metro"
type="dpml.metro.console.Main"/>

Added: trunk/main/metro/main/project.xml
===================================================================
--- trunk/main/metro/main/project.xml 2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/main/project.xml 2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<project xmlns="dpml:library" name="dpml-metro-main">
+
+ <info title="DPML Metro Commandline handler"/>
+
+ <types>
+ <type id="jar"/>
+ <type id="part" source="etc/component.xml" alias="true"/>
+ </types>
+
+ <dependencies>
+ <runtime>
+ <include ref="dpml/lang/dpml-lang-part"/>
+ <include ref="dpml/metro/dpml-metro-connector"/>
+ <include ref="dpml/metro/dpml-metro-appliance"/>
+ <include ref="dpml/util/dpml-util-cli"/>
+ </runtime>
+ <test>
+ <include ref="org/apache/ant/ant-junit"/>
+ </test>
+ </dependencies>
+
+</project>
+

Added: trunk/main/metro/main/src/main/dpml/metro/console/Main.java
===================================================================
--- trunk/main/metro/main/src/main/dpml/metro/console/Main.java 2007-02-08
23:32:32 UTC (rev 1820)
+++ trunk/main/metro/main/src/main/dpml/metro/console/Main.java 2007-02-08
23:33:09 UTC (rev 1821)
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2005-2007 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.metro.console;
+
+import dpml.appliance.ApplianceHelper;
+
+import dpml.cli.Option;
+import dpml.cli.Group;
+import dpml.cli.CommandLine;
+import dpml.cli.OptionException;
+import dpml.cli.TooManyArgumentsException;
+import dpml.cli.commandline.Parser;
+import dpml.cli.util.HelpFormatter;
+import dpml.cli.DisplaySetting;
+import dpml.cli.builder.ArgumentBuilder;
+import dpml.cli.builder.GroupBuilder;
+import dpml.cli.builder.DefaultOptionBuilder;
+import dpml.cli.builder.CommandBuilder;
+import dpml.cli.option.PropertyOption;
+import dpml.cli.validation.URIValidator;
+import dpml.cli.validation.NumberValidator;
+
+import dpml.util.PropertyResolver;
+import dpml.util.DefaultLogger;
+import dpml.util.PID;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.NotBoundException;
+import java.rmi.server.UnicastRemoteObject;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.util.Properties;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+import javax.tools.Tool;
+import javax.lang.model.SourceVersion;
+
+import net.dpml.annotation.Context;
+import net.dpml.annotation.Component;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceError;
+import net.dpml.appliance.ApplianceException;
+import net.dpml.appliance.ApplianceListener;
+import net.dpml.appliance.ApplianceEvent;
+import net.dpml.appliance.ApplianceConnector;
+
+import net.dpml.lang.Strategy;
+import net.dpml.lang.ServiceRegistry;
+import net.dpml.lang.SimpleServiceRegistry;
+import net.dpml.lang.DuplicateKeyException;
+
+import net.dpml.runtime.ComponentListener;
+import net.dpml.runtime.ComponentEvent;
+import net.dpml.runtime.ProviderEvent;
+import net.dpml.runtime.Status;
+
+import net.dpml.transit.Artifact;
+import net.dpml.transit.InvalidArtifactException;
+import net.dpml.transit.ContentHandler;
+import net.dpml.transit.Transit;
+
+import net.dpml.util.Logger;
+
+import static net.dpml.annotation.LifestylePolicy.SINGLETON;
+
+/**
+ * Generic application handler that establishes a dedicated handler based
+ * on the type of resource exposed by a codebase uri.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+@Component( lifestyle=SINGLETON )
+public class Main implements Tool
+{
+
//------------------------------------------------------------------------------
+ // static
+
//------------------------------------------------------------------------------
+
+ private static final PID PROCESS_ID = new PID();
+
+
//------------------------------------------------------------------------------
+ // state
+
//------------------------------------------------------------------------------
+
+ private final Logger m_logger;
+
+ /**
+ * The application handler class is a generic component handler that
delegates
+ * application deployment processes to dedicated handlers based on the
codebase
+ * type of the target application. Normally this plugin is activated as
a
+ * consequence of invoking the <tt>metro</tt> commandline handler (which
is
+ * the default haviour of the <tt>station</tt> when deployment local
processes).
+ * The following command list help about the <tt>metro</tt> commandline
handler:
+ * <pre>$ metro help
+Usage:
+metro <uri> [-server] | -help
+options
+ <uri> Application codebase part uri.
+ -command Enables command mode.
+ -help Prints command help and exits.
+ -version Prints version info and exits.
+ * </pre>
+ * An example commandline and resulting log of an application launch
+ * using <tt>metro</tt> is show below:
+ * <pre>
+$ metro -command link:part:dpml/lang/dpml-lang-sample
+
+[2756 ] [INFO ] (dpml.metro): commissioning hello
+[2756 ] [INFO ] (hello): pid: [2756]
+[2756 ] [INFO ] (hello): message: Hello
+[2756 ] [INFO ] (hello): port: 0
+[2756 ] [INFO ] (hello): target:
artifact:jar:dpml/lang/dpml-lang-sample#SNAPSHOT
+[2756 ] [INFO ] (hello): starting
+[2756 ] [INFO ] (hello): started
+[2756 ] [INFO ] (dpml.metro): decommissioning hello
+[2756 ] [INFO ] (hello): stopping
+[2756 ] [INFO ] (hello): stopped
+ * </pre>
+ *
+ * @param logger the assigned logging channel
+ * @exception Exception if an error occurs
+ */
+ public Main( Logger logger ) throws Exception
+ {
+ m_logger = logger;
+ Thread.currentThread().setContextClassLoader(
+ Appliance.class.getClassLoader() );
+ }
+
+ public Set<SourceVersion> getSourceVersions()
+ {
+ return Collections.unmodifiableSet(
+ EnumSet.range(
+ SourceVersion.RELEASE_4,
+ SourceVersion.latest() ) );
+ }
+
+ /**
+ * Run the Metro tool.
+ */
+ public int run( InputStream in, OutputStream out, OutputStream err,
String... arguments )
+ {
+ for( int i=0; i<arguments.length; i++ )
+ {
+ String arg = arguments[i];
+ if( m_logger.isTraceEnabled() )
+ {
+ m_logger.trace( " arg: " + ( i + 1 ) + ": " + arg );
+ }
+ if( "-help".equals( arg ) )
+ {
+ printHelpMessage();
+ return 0;
+ }
+ if( "-version".equals( arg ) )
+ {
+ printVersionMessage();
+ return 0;
+ }
+ }
+
+ try
+ {
+ return execute( arguments );
+ }
+ catch( Throwable e )
+ {
+ m_logger.error( "Execution error.", e );
+ return -1;
+ }
+ }
+
+ private int execute( String... args ) throws Exception
+ {
+ CommandLine line = getCommandLine( args );
+ if( ( null == line ) || !line.hasOption( CODEBASE ) )
+ {
+ printHelpMessage();
+ return -1;
+ }
+
+ URI uri = getURI( line );
+ ClassLoader current = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(
getClass().getClassLoader() );
+ try
+ {
+ Appliance appliance = ApplianceHelper.newAppliance( uri );
+ boolean flag = line.hasOption( COMMAND_EXECUTION_OPTION );
+ return execute( appliance, flag );
+ }
+ catch( InvalidArtifactException e )
+ {
+ String error =
+ "Invalid artifact: "
+ + uri
+ + "\n" + e.getMessage()
+ + " (expected format:
'scheme:type:[group[/group[/...]]/name[#<version>]).";
+ m_logger.error( error );
+ return -1;
+ }
+ catch( MalformedURLException e )
+ {
+ String error =
+ "Invalid uri: ["
+ + uri
+ + "] (" + e.getMessage() +
+ "), expected format:
'scheme:type:[group[/group[/...]]/name[#<version>].";
+ m_logger.error( error );
+ return -1;
+ }
+ catch( TooManyArgumentsException e )
+ {
+ m_logger.error( "Error: " + e.getMessage() );
+ return -1;
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader( current );
+ }
+ }
+
+ private String getType( URI uri )
+ {
+ if( Artifact.isRecognized( uri ) )
+ {
+ Artifact artifact = Artifact.createArtifact( uri );
+ return artifact.getType();
+ }
+ return null;
+ }
+
+ /**
+ * Execute the appliance.
+ * @param appliance the appliance
+ * @param flag if true we are executing in command mode
+ */
+ private int execute( Appliance appliance, boolean flag ) throws Exception
+ {
+ if( flag )
+ {
+ return executeAsCommand( appliance );
+ }
+ else
+ {
+ //
+ // we are running in server mode - just need to check if we are
+ // running as a top-level server, or if we are running as a
+ // child of a parent process
+ //
+
+ String key = System.getProperty( "dpml.appliance.connector.key",
null );
+ if( null == key )
+ {
+ //
+ // just go ahead and commission (decommissioning will be
handled
+ // by the shutdown hook)
+ //
+
+ try
+ {
+ appliance.commission();
+ return 1;
+ }
+ catch( Exception e )
+ {
+ getLogger().error( "error commissioning appliance", e );
+ return -1;
+ }
+ }
+ else
+ {
+ //
+ // we need to bind the appliance to a connector so that the
+ // parent process can get a handle to the appliance - any
+ // commissioning/decommissioning activity is the
responsibity
+ // of the application that established the callback connector
+ //
+
+ appliance.addApplianceListener( new LocalApplianceListener()
);
+ ApplianceConnector connector = getApplianceConnector( key );
+ connector.connect( appliance );
+ return 1;
+ }
+ }
+ }
+
+ /**
+ * Execute the appliance.
+ * @param appliance the appliance
+ * @param flag if true we are executing in command mode
+ */
+ private int executeAsCommand( Appliance appliance ) throws Exception
+ {
+ try
+ {
+ appliance.commission();
+ }
+ catch( Exception e )
+ {
+ getLogger().error( "error commissioning appliance", e );
+ return -1;
+ }
+ finally
+ {
+ try
+ {
+ appliance.decommission();
+ return 0;
+ }
+ catch( Exception re )
+ {
+ getLogger().error( "error decommissioning appliance", re );
+ return -1;
+ }
+ }
+ }
+
+ private static int getStationPort()
+ {
+ String port = System.getProperty( "dpml.appliance.connector.port",
null );
+ if( null == port )
+ {
+ return Registry.REGISTRY_PORT;
+ }
+ else
+ {
+ return Integer.parseInt( port );
+ }
+ }
+
+ private static long getDecommissionTimeout()
+ {
+ String value = System.getProperty( "dpml.decommmission.timeout",
null );
+ if( null == value )
+ {
+ return 10;
+ }
+ else
+ {
+ try
+ {
+ return Long.parseLong( value );
+ }
+ catch( Throwable e )
+ {
+ return 10;
+ }
+ }
+ }
+
+ private URI getURI( CommandLine line )
+ {
+ URI uri = (URI) line.getValue( CODEBASE, null );
+ if( null == uri )
+ {
+ throw new NullPointerException( "uri" ); // will not happen
+ }
+ return uri;
+ }
+
+ private CommandLine getCommandLine( String[] args ) throws Exception
+ {
+ try
+ {
+ Parser parser = new Parser();
+ parser.setGroup( COMMAND_GROUP );
+ return parser.parse( args );
+ }
+ catch( TooManyArgumentsException e )
+ {
+ String message = e.getMessage();
+ m_logger.error( message );
+ return null;
+ }
+ catch( OptionException oe )
+ {
+ String message = oe.getMessage();
+ m_logger.error( message );
+ return null;
+ }
+ }
+
+ /**
+ * Return a properties instance composed of the
<tt>-C&lt;key&gt;=&lt;value&gt;</tt>
+ * commandline arguments.
+ * @param line the commandline
+ * @return the resolved properties
+ */
+ private Properties getCommandLineProperties( CommandLine line )
+ {
+ Properties properties = new Properties();
+ Set propertyValue = line.getProperties();
+ Iterator iterator = propertyValue.iterator();
+ while( iterator.hasNext() )
+ {
+ String name = (String) iterator.next();
+ String value = line.getProperty( name );
+ properties.setProperty( name, value );
+ }
+ return properties;
+ }
+
+ private class InternalComponentMonitor implements ComponentListener
+ {
+ /**
+ * Notify the listener of a state change.
+ *
+ * @param event the state change event
+ * @exception RemoteException if a remote transport error occurs
+ */
+ public void componentChanged( final ComponentEvent event )
+ {
+ if( event instanceof ProviderEvent )
+ {
+ ProviderEvent e = (ProviderEvent) event;
+ String action = e.getStatus().name().toLowerCase();
+ if( m_logger.isDebugEnabled() )
+ {
+ m_logger.debug( action );
+ }
+ }
+ else
+ {
+ m_logger.warn(
+ "Event not recognized: "
+ + event.toString() );
+ }
+ }
+ }
+
+ private void printVersionMessage()
+ {
+ StringBuffer buffer = new StringBuffer( "version" );
+ buffer.append( "\n" );
+ buffer.append( "\n DPML Metro" );
+ buffer.append( "\n Version @PROJECT-VERSION@" );
+ buffer.append( "\n Copyright 2005-2007 Stephen J. McConnell" );
+ buffer.append( "\n Digital Product Management Laboratory" );
+ String message = buffer.toString();
+ m_logger.info( message );
+ }
+
+ private void printHelpMessage()
+ {
+ StringBuffer buffer = new StringBuffer( "help" );
+ buffer.append( "\n" );
+ buffer.append( "\n Description:" );
+ buffer.append( "\n" );
+ buffer.append( "\n Deploys a component referenced by a part uri."
);
+ buffer.append( "\n" );
+ buffer.append( "\n Usage: metro [-command] <uri> | -help |
-version" );
+ buffer.append( "\n" );
+ buffer.append( "\n Arguments:" );
+ buffer.append( "\n <uri> uri referencing a part
datatype" );
+ buffer.append( "\n" );
+ buffer.append( "\n Options:" );
+ buffer.append( "\n -command enables command execution
mode" );
+ buffer.append( "\n -help list command help and exit"
);
+ buffer.append( "\n -version list version info and exit"
);
+ buffer.append( "\n" );
+ String message = buffer.toString();
+ m_logger.info( message );
+ }
+
+
//------------------------------------------------------------------------------
+ // internals
+
//------------------------------------------------------------------------------
+
+ private Logger getLogger()
+ {
+ return m_logger;
+ }
+
+ private ApplianceConnector getApplianceConnector( String key ) throws
Exception
+ {
+ if( null == key )
+ {
+ throw new NullPointerException( "key " );
+ }
+ else
+ {
+ int port = getStationPort();
+ Registry registry = LocateRegistry.getRegistry( port );
+ try
+ {
+ return (ApplianceConnector) registry.lookup( key );
+ }
+ catch( NotBoundException e )
+ {
+ final String error =
+ "Connector key [" + key + "] is not bound in registry ["
+ + registry
+ + "].";
+ throw new ApplianceError( error, e );
+ }
+ }
+ }
+
+ private class LocalApplianceListener implements ApplianceListener
+ {
+ public void applianceChanged( final ApplianceEvent event )
+ {
+ Status status = event.getStatus();
+ String name = status.name().toLowerCase();
+ getLogger().getChildLogger( "event" ).info( name );
+ if( Status.TERMINATION.equals( status ) )
+ {
+ try
+ {
+ event.getAppliance().removeApplianceListener( this );
+ }
+ catch( IOException ioe )
+ {
+ final String warning =
+ "Ignoring error on listener removal.";
+ getLogger().warn( warning, ioe );
+ }
+ }
+ }
+ }
+
+
//-----------------------------------------------------------------------------
+ // CLI
+
//-----------------------------------------------------------------------------
+
+ /**
+ * List general command help to the console.
+ * @exception IOException if an I/O error occurs
+ */
+ @SuppressWarnings( "unchecked" )
+ private void processHelp() throws IOException
+ {
+ HelpFormatter formatter = new HelpFormatter(
+ HelpFormatter.DEFAULT_GUTTER_LEFT,
+ HelpFormatter.DEFAULT_GUTTER_CENTER,
+ HelpFormatter.DEFAULT_GUTTER_RIGHT,
+ 100 );
+
+ formatter.getDisplaySettings().add(
DisplaySetting.DISPLAY_GROUP_OUTER );
+ formatter.getDisplaySettings().add(
DisplaySetting.DISPLAY_PROPERTY_OPTION );
+ formatter.getDisplaySettings().add(
DisplaySetting.DISPLAY_ARGUMENT_BRACKETED );
+
+ formatter.getFullUsageSettings().add(
DisplaySetting.DISPLAY_OPTIONAL );
+ formatter.getFullUsageSettings().add(
DisplaySetting.DISPLAY_GROUP_OUTER );
+ formatter.getFullUsageSettings().add(
DisplaySetting.DISPLAY_PROPERTY_OPTION );
+ formatter.getFullUsageSettings().add(
DisplaySetting.DISPLAY_OPTIONAL );
+ formatter.getFullUsageSettings().add(
DisplaySetting.DISPLAY_ARGUMENT_BRACKETED );
+ formatter.getFullUsageSettings().remove(
DisplaySetting.DISPLAY_PARENT_CHILDREN );
+
+ formatter.getLineUsageSettings().add(
DisplaySetting.DISPLAY_PROPERTY_OPTION );
+ formatter.getLineUsageSettings().add(
DisplaySetting.DISPLAY_ARGUMENT_BRACKETED );
+ formatter.getLineUsageSettings().remove(
DisplaySetting.DISPLAY_PARENT_CHILDREN );
+ formatter.getLineUsageSettings().remove(
DisplaySetting.DISPLAY_GROUP_EXPANDED );
+
+ formatter.setGroup( CODEBASE_GROUP );
+ formatter.setShellCommand( "metro" );
+ formatter.print();
+ }
+
+ private static final DefaultOptionBuilder OPTION_BUILDER = new
DefaultOptionBuilder();
+ private static final ArgumentBuilder ARGUMENT_BUILDER = new
ArgumentBuilder();
+ private static final GroupBuilder GROUP_BUILDER = new GroupBuilder();
+ private static final CommandBuilder COMMAND_BUILDER = new
CommandBuilder();
+
+ private static final PropertyOption CONTEXT_OPTION =
+ new PropertyOption( "-C", "Set a context entry value.", 'C' );
+ private static final NumberValidator PORT_VALIDATOR =
NumberValidator.getIntegerInstance();
+ private static final URIValidator URI_VALIDATOR = new URIValidator();
+
+ private static final Option HELP_COMMAND =
+ OPTION_BUILDER
+ .withShortName( "help" )
+ .withShortName( "h" )
+ .withDescription( "Prints command help." )
+ .create();
+
+ private static final Option COMMAND_EXECUTION_OPTION =
+ OPTION_BUILDER
+ .withShortName( "command" )
+ .withShortName( "c" )
+ .withDescription( "Enables command execution mode." )
+ .create();
+
+ private static final Option CODEBASE =
+ ARGUMENT_BUILDER
+ .withName( "codebase" )
+ .withDescription( "URI referencing a part datastructure." )
+ .withValidator( new URIValidator() )
+ .create();
+
+ private static final Group CODEBASE_GROUP =
+ GROUP_BUILDER
+ .withOption( CODEBASE )
+ .withOption( CONTEXT_OPTION )
+ .create();
+
+ private static final Group COMMAND_GROUP =
+ GROUP_BUILDER
+ .withMinimum( 0 )
+ .withMaximum( 1 )
+ .withOption( CODEBASE )
+ .withOption( CONTEXT_OPTION )
+ .withOption( COMMAND_EXECUTION_OPTION )
+ .create();
+}

Modified: trunk/main/metro/module.xml
===================================================================
--- trunk/main/metro/module.xml 2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/module.xml 2007-02-08 23:33:09 UTC (rev 1821)
@@ -1,179 +1,19 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<module name="metro"
- xmlns="link:xsd:dpml/lang/dpml-module#1.0"
+ xmlns="dpml:library"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
- xmlns:part="link:xsd:dpml/lang/dpml-part#1.0">
+ xmlns:part="dpml:part">

- <properties>
- <property name="project.minor.version" value="2"/>
- <property name="project.micro.version" value="0"/>
- </properties>
+ <dependencies>
+ <build>
+ <include ref="dpml/depot"/>
+ </build>
+ </dependencies>

- <project name="dpml-metro-state" basedir="state">
- <info title="DPML State Management Model">
- <description>State/transition model for lifecycle
manaement.</description>
- </info>
- <types>
- <type id="jar"/>
- </types>
- <dependencies>
- <build>
- <include ref="dpml/lang/dpml-state"/>
- </build>
- <runtime>
- <include ref="dpml/transit/dpml-transit-main"/>
- </runtime>
- <test>
- <include ref="ant/ant-junit"/>
- </test>
- </dependencies>
- <filters>
- <feature token="STATE-XSD-URI" id="uri" type="xsd"
ref="dpml/lang/dpml-state" alias="true"/>
- </filters>
- </project>
-
- <project name="dpml-metro-component" basedir="component">
- <info title="DPML Metro Component API">
- <description>Interfaces defining the Metro component
model.</description>
- </info>
- <types>
- <type id="jar"/>
- </types>
- <dependencies>
- <build>
- <include ref="dpml/lang/dpml-part"/>
- </build>
- <runtime>
- <include key="dpml-metro-state" tag="public"/>
- <include ref="dpml/transit/dpml-transit-main" tag="private"/>
- </runtime>
- <test>
- <include ref="ant/ant-junit"/>
- </test>
- </dependencies>
- <filters>
- <feature token="NAME" id="name"/>
- <feature token="VERSION" id="version"/>
- <feature token="GROUP" id="group"/>
- <feature token="PART-HANDLER-URI" id="uri" type="part"
ref="dpml/metro/dpml-metro-runtime"/>
- </filters>
- </project>
-
- <project name="dpml-metro-model" basedir="model">
- <info title="DPML Metro Component SPI">
- <description>Interfaces defining the Metro
datastructures.</description>
- </info>
- <types>
- <type id="jar"/>
- </types>
- <dependencies>
- <build>
- <include ref="dpml/lang/dpml-part"/>
- <include ref="dpml/lang/dpml-state"/>
- <include ref="dpml/lang/dpml-type"/>
- <include ref="dpml/lang/dpml-component"/>
- </build>
- <runtime>
- <include key="dpml-metro-state"/>
- <include key="dpml-metro-component"/>
- </runtime>
- <test>
- <include ref="ant/ant-junit"/>
- </test>
- </dependencies>
- <filters>
- <feature token="NAME" id="name"/>
- <feature token="VERSION" id="version"/>
- <feature token="GROUP" id="group"/>
- <feature token="PART-HANDLER-URI" id="uri"
ref="dpml/metro/dpml-metro-runtime" type="part"/>
- <feature token="STATE-XSD-URI" id="uri" type="xsd"
ref="dpml/lang/dpml-state" alias="true"/>
- <feature token="PART-XSD-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="COMPONENT-XSD-URI" id="uri" type="xsd"
ref="dpml/lang/dpml-component" alias="true"/>
- </filters>
- </project>
-
- <project name="dpml-metro-runtime" basedir="runtime">
- <info title="DPML Metro Runtime">
- <description>
- Metro component management platform runtime container.
- </description>
- </info>
- <types>
- <type id="jar"/>
- <part:plugin alias="true"
class="net.dpml.metro.runtime.CompositionController">
- <part:param class="net.dpml.component.InitialContext"/>
- </part:plugin>
- </types>
- <dependencies>
- <build>
- <include ref="dpml/lang/dpml-part"/>
- <include ref="dpml/lang/dpml-state"/>
- <include ref="dpml/lang/dpml-type"/>
- <include ref="dpml/lang/dpml-component"/>
- </build>
- <runtime>
- <include ref="dpml/util/dpml-logging-api" tag="public"/>
- <include ref="dpml/metro/dpml-metro-component" tag="protected"/>
- <include ref="dpml/metro/dpml-metro-model" tag="protected"/>
- </runtime>
- <test>
- <include ref="ant/ant-junit"/>
- </test>
- </dependencies>
- <filters>
- <feature token="PART-HANDLER-URI" id="uri" type="part"/>
- <feature token="STATE-XSD-URI" id="uri" type="xsd"
ref="dpml/lang/dpml-state" alias="true"/>
- <feature token="PART-XSD-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="COMPONENT-XSD-URI" id="uri" type="xsd"
ref="dpml/lang/dpml-component" alias="true"/>
- </filters>
- </project>
-
- <project name="dpml-metro-tools" basedir="tools">
- <info title="DPML Metro Tools">
- <description>
- DPML extensions supporting the Ant build system for component
- type and deployment data management.
- </description>
- </info>
- <types>
- <type id="jar"/>
- <part:resource alias="true" urn="dpml:metro"
- path="net/dpml/metro/tools/antlib.xml"/>
- </types>
- <dependencies>
- <build>
- <include ref="dpml/lang/dpml-component"/>
- </build>
- <runtime>
- <include ref="dpml/depot/dpml-tools-builder"/>
- <include ref="dpml/transit/dpml-transit-tools"/>
- <include ref="dpml/metro/dpml-metro-runtime"/>
- </runtime>
- </dependencies>
- <filters>
- <feature token="PART-BUILDER-URI" id="uri" type="part"/>
- <feature token="PART-HANDLER-URI" id="uri" type="part"
ref="dpml/metro/dpml-metro-runtime"/>
- <feature token="COMPONENT-XSD-URI" id="uri" type="xsd"
ref="dpml/lang/dpml-component" alias="true"/>
- <feature token="STRATEGY-BUILDER-URI" id="uri" type="part"
ref="dpml/metro/dpml-metro-runtime"/>
- </filters>
- </project>
+ <project file="appliance/project.xml"/>
+ <project file="main/project.xml"/>
+ <project file="connector/project.xml"/>
+ <project file="test/project.xml"/>
+ <project file="station/project.xml"/>

- <project name="dpml-metro-test" basedir="test">
- <info title="Internal Test Package"/>
- <types>
- <type id="jar"/>
- </types>
- <dependencies>
- <runtime>
- <include ref="dpml/util/dpml-logging-api"/>
- <include ref="dpml/metro/dpml-metro-model"/>
- </runtime>
- <test>
- <include key="dpml-metro-tools"/>
- </test>
- </dependencies>
- </project>
-
</module>

Added: trunk/main/metro/station/build.xml
===================================================================
--- trunk/main/metro/station/build.xml 2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/build.xml 2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<project name="dpml-metro-station" default="install" basedir="."
+ xmlns:x="antlib:dpml.tools">
+
+ <x:import uri="local:template:dpml/tools/standard"/>
+
+ <available property="station.exe.available"
file="${dpml.system}/bin/station.exe"/>
+
+ <target name="install" depends="bin,standard.install">
+ <mkdir dir="${dpml.prefs}/${project.group}"/>
+ <copy toDir="${dpml.prefs}/${project.group}">
+ <fileset dir="etc/prefs">
+ <include name="**/*"/>
+ </fileset>
+ </copy>
+
+ <!--
+ <mkdir dir="${dpml.prefs}/${project.group}/plans"/>
+ <copy file="${basedir}/target/prefs/default.xml"
toFile="${dpml.prefs}/${project.group}/plans/default.plan"
+ preservelastmodified="true" overwrite="true"/>
+ -->
+
+ <copy todir="${dpml.system}" preservelastmodified="true"
overwrite="true">
+ <fileset dir="target">
+ <include name="bin/station.lap"/>
+ <include name="bin/station.policy"/>
+ <include name="bin/station"/>
+ <include name="bin/scm/**"/>
+ </fileset>
+ </copy>
+ <chmod perm="755">
+ <fileset dir="${dpml.system}/bin">
+ <include name="station"/>
+ </fileset>
+ </chmod>
+ </target>
+
+ <target name="bin" depends="standard.install"
unless="station.exe.available">
+ <mkdir dir="${dpml.system}/bin"/>
+ <copy todir="${dpml.system}" preservelastmodified="true">
+ <fileset dir="target">
+ <include name="bin/station.exe"/>
+ </fileset>
+ </copy>
+ </target>
+
+</project>

Added: trunk/main/metro/station/etc/bin/scm/WRAPPER_LICENSE.txt
===================================================================
--- trunk/main/metro/station/etc/bin/scm/WRAPPER_LICENSE.txt 2007-02-08
23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/etc/bin/scm/WRAPPER_LICENSE.txt 2007-02-08
23:33:09 UTC (rev 1821)
@@ -0,0 +1,41 @@
+Copyright (c) 1999, 2004 Tanuki Software
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of the Java Service Wrapper and associated
+documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sub-license,
+and/or sell copies of the Software, and to permit persons to
+whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+Portions of the Software have been derived from source code
+developed by Silver Egg Technology under the following license:
+
+Copyright (c) 2001 Silver Egg Technology
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sub-license, and/or
+sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+

Added: trunk/main/metro/station/etc/bin/scm/conf/wrapper.conf
===================================================================
--- trunk/main/metro/station/etc/bin/scm/conf/wrapper.conf 2007-02-08
23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/etc/bin/scm/conf/wrapper.conf 2007-02-08
23:33:09 UTC (rev 1821)
@@ -0,0 +1,115 @@
+#********************************************************************
+# TestWrapper Properties
+#
+# NOTE - Please use src/conf/wrapper.conf.in as a template for your
+# own application rather than the values used for the
+# TestWrapper sample.
+#********************************************************************
+# Java Application
+wrapper.java.command=java
+
+# Working directory.
+wrapper.working.dir=../../../data/work
+
+# Java Main class. This class must implement the WrapperListener interface
+# or guarantee that the WrapperManager class is initialized. Helper
+# classes are provided to do this for you. See the Integration section
+# of the documentation for details.
+#wrapper.java.mainclass=net.dpml.depot.Main
+wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
+
+
+# Java Classpath (include wrapper.jar) Add class path elements as
+# needed starting from 1
+wrapper.java.classpath.1=../../share/bin/scm/lib/wrapper.jar
+wrapper.java.classpath.2=../../share/lib/dpml-transit-main.jar
+
+# Java Library Path (location of Wrapper.DLL or libwrapper.so)
+wrapper.java.library.path.1=../../share/bin/scm/lib
+
+# Java Additional Parameters
+wrapper.java.additional.1=-Djava.ext.dirs=..\..\share\lib\ext
+wrapper.java.additional.2=-Djava.endorsed.dirs=..\..\share\lib\endorsed
+wrapper.java.additional.3=-Djava.system.class.loader=dpml.util.SystemClassLoader
+wrapper.java.additional.4=-Djava.security.policy=..\..\share\bin\station.policy
+wrapper.java.additional.5=-Djava.protocol.handler.pkgs=dpml.transit
+wrapper.java.additional.6=-Djava.rmi.server.RMIClassLoaderSpi=dpml.util.FederatingClassLoader
+wrapper.java.additional.7=-Dcom.sun.management.jmxremote
+wrapper.java.additional.8=-Ddpml.class.path=link:jar:dpml/lang/dpml-lang-part
+wrapper.java.additional.9=-Ddpml.depot.application=link:part:dpml/metro/dpml-metro-station
+wrapper.java.additional.10=-Ddpml.jmx.enabled=true
+wrapper.java.additional.11=-Ddpml.logging.config=local:properties:dpml/metro/station
+
+# Initial Java Heap Size (in MB)
+#wrapper.java.initmemory=3
+
+# Maximum Java Heap Size (in MB)
+#wrapper.java.maxmemory=64
+
+# Application parameters. Add parameters as needed starting from 1
+wrapper.app.parameter.1=dpml.util.Main
+wrapper.app.parameter.2=server
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console. (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output. (See docs for log levels)
+wrapper.console.loglevel=INFO
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=../../data/logs/service.log
+
+# Format of output for the log file. (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output. (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+# the log is rolled. Size is specified in bytes. The default value
+# of 0, disables log rolling. May abbreviate with the 'k' (kb) or
+# 'm' (mb) suffix. For example: 10m = 10 megabytes.
+wrapper.logfile.maxsize=0
+
+# Maximum number of rolled log files which will be allowed before old
+# files are deleted. The default value of 0 implies no limit.
+wrapper.logfile.maxfiles=0
+
+# Log Level for sys/event log output. (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=DPML Station Server
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+# using this configuration file has been installed as a service.
+# Please uninstall the service before modifying this section. The
+# service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=DPML
+
+# Display name of the service
+wrapper.ntservice.displayname=DPML Station Server
+
+# Description of the service
+wrapper.ntservice.description=Multi-application management station.
+
+# Service dependencies. Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed. AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=DEMAND_START
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false
+

Added: trunk/main/metro/station/etc/bin/scm/install-DPML-SCM.bat
===================================================================
--- trunk/main/metro/station/etc/bin/scm/install-DPML-SCM.bat 2007-02-08
23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/etc/bin/scm/install-DPML-SCM.bat 2007-02-08
23:33:09 UTC (rev 1821)
@@ -0,0 +1,35 @@
+@echo off
+setlocal
+
+rem
+rem Java Service Wrapper general NT service install script
+rem
+
+if "%OS%"=="Windows_NT" goto nt
+echo This script only works with NT-based versions of Windows.
+goto :eof
+
+:nt
+rem
+rem Find the application home.
+rem
+rem %~dp0 is location of current script under NT
+set _REALPATH=%~dp0
+set _WRAPPER_EXE=%_REALPATH%Wrapper.exe
+
+rem
+rem Find the wrapper.conf
+rem
+:conf
+set _WRAPPER_CONF="%~f1"
+if not %_WRAPPER_CONF%=="" goto startup
+set _WRAPPER_CONF="%_REALPATH%conf\wrapper.conf"
+
+rem
+rem Install the Wrapper as an NT service.
+rem
+:startup
+"%_WRAPPER_EXE%" -i %_WRAPPER_CONF%
+if not errorlevel 1 goto :eof
+pause
+

Added: trunk/main/metro/station/etc/bin/scm/lib/wrapper.dll
===================================================================
(Binary files differ)


Property changes on: trunk/main/metro/station/etc/bin/scm/lib/wrapper.dll
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream

Added: trunk/main/metro/station/etc/bin/scm/lib/wrapper.jar
===================================================================
(Binary files differ)


Property changes on: trunk/main/metro/station/etc/bin/scm/lib/wrapper.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream

Added: trunk/main/metro/station/etc/bin/scm/uninstall-DPML-SCM.bat
===================================================================
--- trunk/main/metro/station/etc/bin/scm/uninstall-DPML-SCM.bat 2007-02-08
23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/etc/bin/scm/uninstall-DPML-SCM.bat 2007-02-08
23:33:09 UTC (rev 1821)
@@ -0,0 +1,35 @@
+@echo off
+setlocal
+
+rem
+rem Java Service Wrapper general NT service uninstall script
+rem
+
+if "%OS%"=="Windows_NT" goto nt
+echo This script only works with NT-based versions of Windows.
+goto :eof
+
+:nt
+rem
+rem Find the application home.
+rem
+rem %~dp0 is location of current script under NT
+set _REALPATH=%~dp0
+set _WRAPPER_EXE=%_REALPATH%Wrapper.exe
+
+rem
+rem Find the wrapper.conf
+rem
+:conf
+set _WRAPPER_CONF="%~f1"
+if not %_WRAPPER_CONF%=="" goto startup
+set _WRAPPER_CONF="%_REALPATH%conf\wrapper.conf"
+
+rem
+rem Uninstall the Wrapper as an NT service.
+rem
+:startup
+"%_WRAPPER_EXE%" -r %_WRAPPER_CONF%
+if not errorlevel 1 goto :eof
+pause
+

Added: trunk/main/metro/station/etc/bin/scm/wrapper.exe
===================================================================
(Binary files differ)


Property changes on: trunk/main/metro/station/etc/bin/scm/wrapper.exe
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream

Added: trunk/main/metro/station/etc/bin/station
===================================================================
--- trunk/main/metro/station/etc/bin/station 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/station/etc/bin/station 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+
+STATION_JVM_OPTS="-Ddpml.depot.application=link:part:dpml/metro/dpml-metro-station"
+
+if [ "$DEPOT_JVM_OPTS" = "" ] ; then
+ DEPOT_JVM_OPTS=$STATION_JVM_OPTS
+else
+ DEPOT_JVM_OPTS="$STATION_JVM_OPTS $DEPOT_JVM_OPTS"
+fi
+export DEPOT_JVM_OPTS
+
+depot $*

Added: trunk/main/metro/station/etc/bin/station.exe
===================================================================
(Binary files differ)


Property changes on: trunk/main/metro/station/etc/bin/station.exe
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream

Added: trunk/main/metro/station/etc/bin/station.lap
===================================================================
--- trunk/main/metro/station/etc/bin/station.lap 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/station/etc/bin/station.lap 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,17 @@
+#
+# This file contains the runtime configuration of the Janel java launcher
application.
+#
+
+-Djava.ext.dirs=${env.DPML_HOME}\share\lib\ext
+-Djava.endorsed.dirs=${env.DPML_HOME}\share\lib\endorsed
+-Djava.system.class.loader=dpml.util.SystemClassLoader
+-Djava.security.policy=${env.DPML_HOME}\share\bin\station.policy
+-Djava.protocol.handler.pkgs=dpml.transit
+-Djava.rmi.server.RMIClassLoaderSpi=dpml.util.FederatingClassLoader
+-Dcom.sun.management.jmxremote
+-Ddpml.class.path=link:jar:dpml/lang/dpml-lang-part
+-Ddpml.depot.application=link:part:dpml/metro/dpml-metro-station
+-Ddpml.jmx.enabled=true
+janel.main.class=dpml.util.Main
+janel.min.java.version=1.6.0
+janel.sysprop.process.id=true

Added: trunk/main/metro/station/etc/bin/station.policy
===================================================================
--- trunk/main/metro/station/etc/bin/station.policy 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/station/etc/bin/station.policy 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,4 @@
+grant {
+ permission java.security.AllPermission;
+};
+

Added: trunk/main/metro/station/etc/component.xml
===================================================================
--- trunk/main/metro/station/etc/component.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/station/etc/component.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<component xmlns="dpml:metro" name="dpml.station"
type="dpml.station.console.Main"/>

Added: trunk/main/metro/station/etc/prefs/plans/default.plan
===================================================================
--- trunk/main/metro/station/etc/prefs/plans/default.plan 2007-02-08
23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/etc/prefs/plans/default.plan 2007-02-08
23:33:09 UTC (rev 1821)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+
+<plan xmlns="dpml:plan" name="station" title="DPML Station Default
Deployment Plan">
+
+</plan>

Added: trunk/main/metro/station/etc/prefs/propertiess/process.properties
===================================================================
--- trunk/main/metro/station/etc/prefs/propertiess/process.properties
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/etc/prefs/propertiess/process.properties
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,13 @@
+#
+# Logging configuration template for an application (jvm) established
+# by the Station server. The template assumes that a system property
+# 'dpml.station.key' and ${dpml.station.logging.dir} are declared.
+#
+
+handlers=java.util.logging.FileHandler
+java.util.logging.FileHandler.count=10
+java.util.logging.FileHandler.limit=100000
+java.util.logging.FileHandler.pattern=${dpml.station.logging.dir}/${dpml.station.key}/${dpml.station.key}-%g.log
+java.util.logging.FileHandler.formatter=dpml.util.StandardFormatter
+sun.rmi.level=INFO
+

Added: trunk/main/metro/station/etc/prefs/propertiess/station.properties
===================================================================
--- trunk/main/metro/station/etc/prefs/propertiess/station.properties
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/etc/prefs/propertiess/station.properties
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,11 @@
+#
+# Logging configuration for the Station server.
+#
+
+handlers=java.util.logging.FileHandler
+java.util.logging.FileHandler.pattern=${dpml.data}/logs/station/dpml-station-server-%u.log
+java.util.logging.FileHandler.limit=50000
+java.util.logging.FileHandler.count=1
+java.util.logging.FileHandler.formatter=dpml.util.StandardFormatter
+sun.rmi.level=INFO
+

Added: trunk/main/metro/station/project.xml
===================================================================
--- trunk/main/metro/station/project.xml 2007-02-08 23:32:32 UTC (rev
1820)
+++ trunk/main/metro/station/project.xml 2007-02-08 23:33:09 UTC (rev
1821)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<project xmlns="dpml:library" name="dpml-metro-station">
+
+ <info title="DPML Station Commandline handler"/>
+
+ <types>
+ <type id="jar"/>
+ <type id="part" source="etc/component.xml" alias="true"/>
+ </types>
+
+ <dependencies>
+ <runtime>
+ <include ref="dpml/lang/dpml-lang-part"/>
+ <include ref="dpml/metro/dpml-metro-connector"/>
+ <include ref="dpml/metro/dpml-metro-appliance"/>
+ <include ref="dpml/util/dpml-util-cli"/>
+ </runtime>
+ <test>
+ <include ref="org/apache/ant/ant-junit"/>
+ </test>
+ </dependencies>
+
+</project>
+

Added: trunk/main/metro/station/src/main/dpml/station/console/Main.java
===================================================================
--- trunk/main/metro/station/src/main/dpml/station/console/Main.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/station/src/main/dpml/station/console/Main.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,872 @@
+/*
+ * Copyright 2005-2007 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.station.console;
+
+import dpml.appliance.ApplianceHelper;
+import dpml.station.connector.LocalConnector;
+import dpml.station.info.InfoDescriptor;
+import dpml.station.info.ProcessDescriptor;
+import dpml.station.info.ApplianceDescriptor;
+import dpml.station.util.OutputStreamReader;
+import dpml.station.util.StreamReader;
+import dpml.station.util.LoggingServer;
+
+import dpml.cli.Option;
+import dpml.cli.Group;
+import dpml.cli.CommandLine;
+import dpml.cli.OptionException;
+import dpml.cli.TooManyArgumentsException;
+import dpml.cli.commandline.Parser;
+import dpml.cli.util.HelpFormatter;
+import dpml.cli.DisplaySetting;
+import dpml.cli.builder.ArgumentBuilder;
+import dpml.cli.builder.GroupBuilder;
+import dpml.cli.builder.DefaultOptionBuilder;
+import dpml.cli.builder.CommandBuilder;
+import dpml.cli.option.PropertyOption;
+import dpml.cli.validation.URIValidator;
+import dpml.cli.validation.NumberValidator;
+
+import dpml.util.PropertyResolver;
+import dpml.util.DefaultLogger;
+import dpml.util.PID;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.NotBoundException;
+import java.rmi.ConnectException;
+import java.rmi.server.UnicastRemoteObject;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.util.Properties;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+import javax.tools.Tool;
+import javax.lang.model.SourceVersion;
+
+import javax.management.MBeanServer;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import net.dpml.annotation.Context;
+import net.dpml.annotation.Component;
+
+import net.dpml.appliance.Appliance;
+import net.dpml.appliance.ApplianceError;
+import net.dpml.appliance.ApplianceException;
+import net.dpml.appliance.ApplianceListener;
+import net.dpml.appliance.ApplianceEvent;
+import net.dpml.appliance.ApplianceConnector;
+
+import net.dpml.lang.Strategy;
+import net.dpml.lang.ServiceRegistry;
+import net.dpml.lang.SimpleServiceRegistry;
+import net.dpml.lang.DuplicateKeyException;
+
+import net.dpml.runtime.ComponentListener;
+import net.dpml.runtime.ComponentEvent;
+import net.dpml.runtime.ProviderEvent;
+import net.dpml.runtime.Status;
+
+import net.dpml.station.Station;
+
+import net.dpml.transit.Artifact;
+import net.dpml.transit.InvalidArtifactException;
+import net.dpml.transit.ContentHandler;
+import net.dpml.transit.Transit;
+
+import net.dpml.util.Logger;
+
+import static net.dpml.annotation.LifestylePolicy.SINGLETON;
+
+/**
+ * Generic application handler that establishes a dedicated handler based
+ * on the type of resource exposed by a codebase uri.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+@Component( lifestyle=SINGLETON )
+public class Main extends UnicastRemoteObject implements Tool, Station
+{
+
//------------------------------------------------------------------------------
+ // static
+
//------------------------------------------------------------------------------
+
+ private static final String DEFAULT_PLAN_URI_VALUE =
"local:plan:dpml/metro/default";
+ private static final String STATION_CONNECTOR_VALUE = "dpml/station";
+
+
//------------------------------------------------------------------------------
+ // state
+
//------------------------------------------------------------------------------
+
+ private final Logger m_logger;
+ private Appliance m_plan;
+ private Thread m_thread;
+ //private JMXServiceURL m_jmx;
+ //private JMXConnectorServer m_server;
+
+ /**
+ * The application handler class is a generic component handler that
delegates
+ * application deployment processes to dedicated handlers based on the
codebase
+ * type of the target application. Normally this plugin is activated as
a
+ * consequence of invoking the <tt>metro</tt> commandline handler (which
is
+ * the default haviour of the <tt>station</tt> when deployment local
processes).
+ * The following command list help about the <tt>metro</tt> commandline
handler:
+ * <pre>$ metro help
+Usage:
+metro <uri> [-server] | -help
+options
+ <uri> Application codebase part uri.
+ -command Enables command mode.
+ -help Prints command help and exits.
+ -version Prints version info and exits.
+ * </pre>
+ * An example commandline and resulting log of an application launch
+ * using <tt>metro</tt> is show below:
+ * <pre>
+$ metro -command link:part:dpml/lang/dpml-lang-sample
+
+[2756 ] [INFO ] (dpml.metro): commissioning hello
+[2756 ] [INFO ] (hello): pid: [2756]
+[2756 ] [INFO ] (hello): message: Hello
+[2756 ] [INFO ] (hello): port: 0
+[2756 ] [INFO ] (hello): target:
artifact:jar:dpml/lang/dpml-lang-sample#SNAPSHOT
+[2756 ] [INFO ] (hello): starting
+[2756 ] [INFO ] (hello): started
+[2756 ] [INFO ] (dpml.metro): decommissioning hello
+[2756 ] [INFO ] (hello): stopping
+[2756 ] [INFO ] (hello): stopped
+ * </pre>
+ *
+ * @param logger the assigned logging channel
+ * @exception Exception if an error occurs
+ */
+ public Main( Logger logger ) throws Exception
+ {
+ super();
+
+ m_logger = logger;
+ }
+
+ public Set<SourceVersion> getSourceVersions()
+ {
+ return Collections.unmodifiableSet(
+ EnumSet.range(
+ SourceVersion.RELEASE_4,
+ SourceVersion.latest() ) );
+ }
+
+ /**
+ * Run the Metro tool.
+ */
+ public int run( InputStream in, OutputStream out, OutputStream err,
String... arguments )
+ {
+ Thread.currentThread().setContextClassLoader(
+ getClass().getClassLoader() );
+
+ for( int i=0; i<arguments.length; i++ )
+ {
+ String arg = arguments[i];
+ if( m_logger.isTraceEnabled() )
+ {
+ m_logger.trace( " arg: " + ( i + 1 ) + ": " + arg );
+ }
+ if( "-help".equals( arg ) )
+ {
+ printHelpMessage();
+ return 0;
+ }
+ if( "-version".equals( arg ) )
+ {
+ printVersionMessage();
+ return 0;
+ }
+ }
+
+ try
+ {
+ return execute( arguments );
+ }
+ catch( Throwable e )
+ {
+ m_logger.error( "Execution error.", e );
+ return -1;
+ }
+ }
+
+ private int execute( String... args ) throws Exception
+ {
+ String name = System.getProperty( STATION_CONNECTOR_KEY,
STATION_CONNECTOR_VALUE );
+ CommandLine line = getCommandLine( args );
+ if( null == line )
+ {
+ return -1;
+ }
+
+ int port = getPortValue( line, Registry.REGISTRY_PORT );
+ if( line.hasOption( SERVER_COMMAND ) )
+ {
+ Registry registry = resolveRegistry( port );
+
+ LoggingServer.init();
+
+ //m_jmx = getJMXServiceURL( port );
+ //m_server = getJMXConnectorServer( m_jmx );
+ //m_server.start();
+
+ URI uri = getURI( line );
+ m_thread = Thread.currentThread();
+
+ URL url = Artifact.toURL( uri );
+ ClassLoader current =
Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(
getClass().getClassLoader() );
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "resolving plan [" + url + "]" );
+ }
+ try
+ {
+ m_plan = (Appliance) url.getContent( new Class[]{
Appliance.class } );
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader( current );
+ }
+ if( null == m_plan )
+ {
+ if( getLogger().isErrorEnabled() )
+ {
+ final String error =
+ "Unable to resolve ["
+ + url
+ + "] to an appliance.";
+ getLogger().error( error );
+ }
+ return -1;
+ }
+
+ registry.bind( name, this );
+
+ try
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "commissioning plan" );
+ }
+ m_plan.commission();
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "plan commissioning complete" );
+ }
+ return 1;
+ }
+ catch( Exception e )
+ {
+ final String error =
+ "Plan deployment error.";
+ if( getLogger().isErrorEnabled() )
+ {
+ getLogger().error( error, e );
+ }
+ m_plan.decommission();
+ return -1;
+ }
+ }
+ else if( line.hasOption( STARTUP_COMMAND ) )
+ {
+ URI uri = getURI( line );
+ if( getLogger().isInfoEnabled() )
+ {
+ getLogger().info( "station startup" );
+ }
+
+ //
+ // otherwise we are creating a sub-process with a sticky
connector
+ // and we locate the appliance from the connector, initiate
appliance
+ // commissioning, and given a successfull startup we exit
without
+ // disrupting the launched sub-process
+ //
+
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "creating station subprocess" );
+ }
+ List<String> commands = new ArrayList<String>();
+ commands.add( "station" );
+ commands.add(
+ "-D"
+ + STATION_CONNECTOR_KEY
+ + "="
+ + STATION_CONNECTOR_VALUE );
+ //commands.add(
+ // "-D"
+ // + STATION_JMX_URI_KEY
+ // + "="
+ // + m_jmx.toString() );
+ commands.add( "server" );
+ commands.add( "-port" );
+ commands.add( "" + port );
+ commands.add( uri.toASCIIString() );
+
+ ProcessBuilder builder = new ProcessBuilder( commands );
+ builder.redirectErrorStream( true );
+
+ if( getLogger().isTraceEnabled() )
+ {
+ StringBuffer buffer = new StringBuffer( "station command: "
);
+ for( String command : commands )
+ {
+ buffer.append( command );
+ buffer.append( " " );
+ }
+ getLogger().trace( buffer.toString() );
+ }
+
+ // execute the process
+
+ Process process = builder.start();
+ //setShutdownHook( process ); // <-- need to enable this, but
add removeShutdownHook before we return
+ OutputStreamReader output =
+ new OutputStreamReader( m_logger, process.getInputStream() );
+ output.setDaemon( true );
+ output.start();
+
+ waitForThis( port, name );
+
+ if( getLogger().isInfoEnabled() )
+ {
+ getLogger().info( "startup complete" );
+ }
+
+ return 0;
+ }
+ else if( line.hasOption( SHUTDOWN_COMMAND ) )
+ {
+ try
+ {
+ Station station = getStation( port );
+ if( getLogger().isInfoEnabled() )
+ {
+ getLogger().info( "initiating remote shutdown" );
+ }
+ station.shutdown();
+ if( getLogger().isInfoEnabled() )
+ {
+ getLogger().info( "remote shutdown request completed" );
+ }
+ return 0;
+ }
+ catch( ConnectException e )
+ {
+ if( getLogger().isWarnEnabled() )
+ {
+ getLogger().warn( "Station not running" );
+ }
+ return -1;
+ }
+ catch( Exception e )
+ {
+ final String error = "Shutdown error.";
+ if( getLogger().isErrorEnabled() )
+ {
+ getLogger().error( error, e );
+ }
+ return -1;
+ }
+ }
+ else if( line.hasOption( INFO_COMMAND ) )
+ {
+ try
+ {
+ Station station = getStation( port );
+ if( getLogger().isInfoEnabled() )
+ {
+ getLogger().info( "Station running on port [" + port +
"]" );
+ }
+ }
+ catch( StationNotBoundException e )
+ {
+ if( getLogger().isInfoEnabled() )
+ {
+ getLogger().info( "Station not bound on port [" + port +
"]" );
+ }
+ }
+ catch( ConnectException e )
+ {
+ if( getLogger().isInfoEnabled() )
+ {
+ getLogger().info( "Station not running" );
+ }
+ }
+ return 0;
+ }
+ else
+ {
+ final String error =
+ "Invalid command state.";
+ if( getLogger().isErrorEnabled() )
+ {
+ getLogger().error( error );
+ }
+ return -1;
+ }
+ }
+
+ private JMXServiceURL getJMXServiceURL( int port ) throws
MalformedURLException
+ {
+ return new JMXServiceURL(
+ "service:jmx:rmi:///jndi/rmi://localhost:"
+ + port
+ + "/dpml-station-jmx");
+ }
+
+ private JMXConnectorServer getJMXConnectorServer( JMXServiceURL url )
throws IOException
+ {
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+ return JMXConnectorServerFactory.newJMXConnectorServer( url, null,
server );
+ }
+
+ private void waitForThis( int port, String name ) // TODO: add timeout
support
+ {
+ Station station = null;
+ while( null == station )
+ {
+ try
+ {
+ Registry registry = LocateRegistry.getRegistry( port );
+ station = (Station) registry.lookup( name );
+ }
+ catch( Exception ie )
+ {
+ try
+ {
+ Thread.currentThread().sleep( 100 );
+ }
+ catch( InterruptedException e )
+ {
+ }
+ }
+ }
+ }
+
+ public void shutdown() throws RemoteException
+ {
+ if( null != m_plan )
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "initiating station process shutdown" );
+ }
+ m_plan.decommission();
+ Terminator terminator = new Terminator( m_thread, this );
+ terminator.setName( "DPML Station Terminator" );
+ terminator.start();
+ /*
+ if( null != m_server )
+ {
+ try
+ {
+ m_server.stop();
+ }
+ catch( IOException e )
+ {
+ if( getLogger().isWarnEnabled() )
+ {
+ getLogger().warn( "JMX connector server shutdown
error.", e );
+ }
+ }
+ }
+ */
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "station process shutdown complete" );
+ }
+ }
+ }
+
+ private class Terminator extends Thread
+ {
+ private Thread m_thread;
+ private Station m_station;
+
+ Terminator( Thread thread, Station station )
+ {
+ m_thread = thread;
+ m_station = station;
+ }
+
+ public void run()
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "executing terminator" );
+ }
+ try
+ {
+ UnicastRemoteObject.unexportObject( m_station, false );
+ }
+ catch( Throwable e )
+ {
+ if( getLogger().isWarnEnabled() )
+ {
+ final String error =
+ "Ignoring unexpected error while unexporting the
station.";
+ getLogger().warn( error, e );
+ }
+ }
+ try
+ {
+ UnicastRemoteObject.unexportObject( m_plan, false );
+ }
+ catch( Throwable e )
+ {
+ if( getLogger().isWarnEnabled() )
+ {
+ final String error =
+ "Ignoring unexpected error while unexporting the
plan.";
+ getLogger().warn( error, e );
+ }
+ }
+ try
+ {
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "interrupting " + m_thread );
+ }
+ m_thread.interrupt();
+ }
+ catch( Throwable e )
+ {
+ if( getLogger().isWarnEnabled() )
+ {
+ final String error = "interupted";
+ getLogger().warn( error, e );
+ }
+ }
+ if( getLogger().isTraceEnabled() )
+ {
+ getLogger().trace( "termination completed" );
+ }
+ }
+ }
+
+ private Station getStation( int port ) throws Exception
+ {
+ Registry registry = LocateRegistry.getRegistry( port );
+ try
+ {
+ return (Station) registry.lookup( STATION_CONNECTOR_VALUE );
+ }
+ catch( NotBoundException nbe )
+ {
+ final String error =
+ "Station not bound on ["
+ + port
+ + "] under ["
+ + STATION_CONNECTOR_VALUE
+ + "] on registry ["
+ + registry
+ + "]";
+ throw new StationNotBoundException( error );
+ }
+ }
+
+ private Registry resolveRegistry( int port )throws ApplianceException
+ {
+ try
+ {
+ Registry registry = LocateRegistry.createRegistry( port );
+ getLogger().info( "created local registry on port " + port );
+ return registry;
+ }
+ catch( RemoteException re )
+ {
+ try
+ {
+ Registry registry = LocateRegistry.getRegistry( port );
+ getLogger().info( "using local registry on port " + port );
+ return registry;
+ }
+ catch( RemoteException e )
+ {
+ final String error =
+ "Unable to locate or create RMI registry to due a remote
exeception.";
+ throw new ApplianceException( error, e );
+ }
+ }
+ }
+
+ private URI getURI( CommandLine line )
+ {
+ URI uri = (URI) line.getValue( CODEBASE, null );
+ if( null == uri )
+ {
+ return URI.create( DEFAULT_PLAN_URI_VALUE );
+ }
+ else
+ {
+ return uri;
+ }
+ }
+
+ private int getPortValue( CommandLine line, int defaultPort )
+ {
+ if( line.hasOption( PORT_OPTION ) )
+ {
+ Number number = (Number) line.getValue( PORT_OPTION, null );
+ if( null != number )
+ {
+ return number.intValue();
+ }
+ }
+ return defaultPort;
+ }
+
+ private CommandLine getCommandLine( String[] args ) throws Exception
+ {
+ try
+ {
+ Parser parser = new Parser();
+ parser.setGroup( COMMAND_GROUP );
+ return parser.parse( args );
+ }
+ catch( TooManyArgumentsException e )
+ {
+ String message = e.getMessage();
+ m_logger.error( message );
+ return null;
+ }
+ catch( OptionException oe )
+ {
+ String message = oe.getMessage();
+ m_logger.error( message );
+ return null;
+ }
+ }
+
+ private void printVersionMessage()
+ {
+ StringBuffer buffer = new StringBuffer( "version" );
+ buffer.append( "\n" );
+ buffer.append( "\n DPML Station" );
+ buffer.append( "\n Version @PROJECT-VERSION@" );
+ buffer.append( "\n Copyright 2005-2007 Stephen J. McConnell" );
+ buffer.append( "\n Digital Product Management Laboratory" );
+ String message = buffer.toString();
+ m_logger.info( message );
+ }
+
+ private void printHelpMessage()
+ {
+ StringBuffer buffer = new StringBuffer( "help" );
+ buffer.append( "\n" );
+ buffer.append( "\n Description:" );
+ buffer.append( "\n" );
+ buffer.append( "\n Process management controller." );
+ buffer.append( "\n" );
+ buffer.append( "\n Usage: $ station startup [<uri>] | info |
shutdown | -help | -version" );
+ buffer.append( "\n" );
+ buffer.append( "\n Common Options:" );
+ buffer.append( "\n" );
+ buffer.append( "\n -help list command help and exit"
);
+ buffer.append( "\n -version list version info and exit"
);
+ buffer.append( "\n -port override the RMI Registry
port value" );
+ buffer.append( "\n" );
+ buffer.append( "\n Commands:" );
+ buffer.append( "\n" );
+ buffer.append( "\n startup [<uri>] startup the station" );
+ buffer.append( "\n" );
+ buffer.append( "\n <uri> uri referencing a plan
datatype" );
+ buffer.append( "\n if not supplied the default
station deployment" );
+ buffer.append( "\n plan
(local:plan:dpml/station/default) will" );
+ buffer.append( "\n be selected" );
+ buffer.append( "\n" );
+ buffer.append( "\n -server enables server execution
mode" );
+ buffer.append( "\n" );
+ buffer.append( "\n info list station operational
status and exit" );
+ buffer.append( "\n" );
+ buffer.append( "\n shutdown shutdown the station" );
+ buffer.append( "\n" );
+ buffer.append( "\n" );
+ String message = buffer.toString();
+ m_logger.info( message );
+ }
+
+
//------------------------------------------------------------------------------
+ // internals
+
//------------------------------------------------------------------------------
+
+ private Logger getLogger()
+ {
+ return m_logger;
+ }
+
+
//-----------------------------------------------------------------------------
+ // CLI
+
//-----------------------------------------------------------------------------
+
+ private static final DefaultOptionBuilder OPTION_BUILDER = new
DefaultOptionBuilder();
+ private static final ArgumentBuilder ARGUMENT_BUILDER = new
ArgumentBuilder();
+ private static final GroupBuilder GROUP_BUILDER = new GroupBuilder();
+ private static final CommandBuilder COMMAND_BUILDER = new
CommandBuilder();
+
+ private static final NumberValidator PORT_VALIDATOR =
NumberValidator.getIntegerInstance();
+ private static final URIValidator URI_VALIDATOR = new URIValidator();
+
+ private static final Option PORT_OPTION =
+ OPTION_BUILDER
+ .withShortName( "port" )
+ .withDescription( "RMI Registry port." )
+ .withRequired( false )
+ .withArgument(
+ ARGUMENT_BUILDER
+ .withDescription( "Registry port." )
+ .withName( "port" )
+ .withMinimum( 0 )
+ .withMaximum( 1 )
+ .withValidator( PORT_VALIDATOR )
+ .create() )
+ .create();
+
+ private static final Option SERVER_OPTION =
+ OPTION_BUILDER
+ .withShortName( "server" )
+ .withDescription( "Enables server execution mode." )
+ .create();
+
+ private static final Option SHUTDOWN_OPTION =
+ OPTION_BUILDER
+ .withShortName( "shutdown" )
+ .withShortName( "s" )
+ .withDescription( "Shutdown the station." )
+ .create();
+
+ private static final Option CODEBASE =
+ ARGUMENT_BUILDER
+ .withName( "codebase" )
+ .withDescription( "URI referencing a plan datastructure." )
+ .withValidator( new URIValidator() )
+ .create();
+
+ private static final Group SERVER_GROUP =
+ GROUP_BUILDER
+ .withMinimum( 0 )
+ .withMaximum( 2 )
+ .withOption( PORT_OPTION )
+ .withOption( CODEBASE )
+ .create();
+
+ private static final Option SERVER_COMMAND =
+ COMMAND_BUILDER
+ .withName( "server" )
+ .withDescription( "Server mode." )
+ .withChildren( SERVER_GROUP )
+ .create();
+
+ private static final Group INFO_GROUP =
+ GROUP_BUILDER
+ .withMinimum( 0 )
+ .withMaximum( 1 )
+ .withOption( PORT_OPTION )
+ .create();
+
+ private static final Option INFO_COMMAND =
+ COMMAND_BUILDER
+ .withName( "info" )
+ .withDescription( "Station status report." )
+ .withChildren( INFO_GROUP )
+ .create();
+
+ private static final Group STARTUP_GROUP =
+ GROUP_BUILDER
+ .withMinimum( 0 )
+ .withMaximum( 2 )
+ .withOption( PORT_OPTION )
+ //.withOption( SERVER_OPTION )
+ .withOption( CODEBASE )
+ .create();
+
+ private static final Option STARTUP_COMMAND =
+ COMMAND_BUILDER
+ .withName( "startup" )
+ .withDescription( "Startup the station." )
+ .withChildren( STARTUP_GROUP )
+ .create();
+
+ private static final Group SHUTDOWN_GROUP =
+ GROUP_BUILDER
+ .withMinimum( 0 )
+ .withMaximum( 1 )
+ .withOption( PORT_OPTION )
+ .create();
+
+ private static final Option SHUTDOWN_COMMAND =
+ COMMAND_BUILDER
+ .withName( "shutdown" )
+ .withDescription( "Shutdown the station." )
+ .withChildren( SHUTDOWN_GROUP )
+ .create();
+
+ private static final Group COMMAND_GROUP =
+ GROUP_BUILDER
+ .withMinimum( 0 )
+ .withMaximum( 1 )
+ .withOption( INFO_COMMAND )
+ .withOption( STARTUP_COMMAND )
+ .withOption( SHUTDOWN_COMMAND )
+ .withOption( SERVER_COMMAND )
+ .create();
+
+ private static void setShutdownHook( final Process process )
+ {
+ Runtime.getRuntime().addShutdownHook(
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ process.destroy();
+ }
+ catch( Throwable e )
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ );
+ }
+}

Added:
trunk/main/metro/station/src/main/dpml/station/console/StationNotBoundException.java
===================================================================
---
trunk/main/metro/station/src/main/dpml/station/console/StationNotBoundException.java
2007-02-08 23:32:32 UTC (rev 1820)
+++
trunk/main/metro/station/src/main/dpml/station/console/StationNotBoundException.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,50 @@
+/*
+ * 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 dpml.station.console;
+
+import net.dpml.station.StationException;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Exception thrown when an attempt is made to reference an unbound station.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class StationNotBoundException extends StationException
+{
+ /**
+ * Serial version identifier.
+ */
+ static final long serialVersionUID = 1L;
+
+ /**
+ * Construct a new <code>StationException</code>.
+ *
+ * @param message the error message
+ */
+ public StationNotBoundException( final String message )
+ {
+ super( message, null, null );
+ }
+
+}
+

Modified: trunk/main/metro/test/build.xml
===================================================================
--- trunk/main/metro/test/build.xml 2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/test/build.xml 2007-02-08 23:33:09 UTC (rev 1821)
@@ -17,244 +17,12 @@
limitations under the License.
-->

-<project name="dpml-metro-test" default="install"
- xmlns:transit="antlib:net.dpml.transit"
- xmlns:x="dpml:depot"
- xmlns:c="dpml:metro" >
+<project default="install" xmlns:x="antlib:dpml.tools" >

- <transit:import uri="local:template:dpml/tools/standard"/>
+ <x:import uri="local:template:dpml/tools/standard"/>

- <target name="build" depends="standard.build">
-
- <rmic base="${project.target.classes.main.dir}"
- classpathref="project.compile.path">
- <include name="**/ManagedComponent#DefaultMonitor.class"/>
- </rmic>
-
- <x:plugin uri="link:part:dpml/metro/dpml-metro-tools"/>
-
- <!-- create the test component types -->
-
- <c:type class="net.dpml.test.ExampleComponent" name="example">
- <state>
- <trigger event="initialization">
- <transition name="init" target="available"/>
- </trigger>
- <state name="available">
- <trigger event="termination">
- <transition name="terminate" target="../terminated"/>
- </trigger>
- </state>
- <state name="terminated" terminal="true"/>
- </state>
- </c:type>
- <c:type class="net.dpml.test.SingletonComponent" name="example"
threadsafe="true"/>
- <c:type class="net.dpml.test.ContextTestComponent" name="context"
threadsafe="true"/>
-
- <!-- create test components -->
-
- <c:component dest="target/test/example.part" test="true"
- type="net.dpml.test.ExampleComponent" name="example">
- <context>
- <entry key="color" method="RED"/>
- </context>
- </c:component>
-
- <c:component dest="target/test/example-2.part" test="true"
- type="net.dpml.test.ExampleComponent" name="transient"
collection="SOFT" lifestyle="transient">
- <context>
- <entry key="color">
- <value class="int" value="100"/>
- <value class="int" value="200"/>
- <value class="int" value="0"/>
- </entry>
- </context>
- </c:component>
-
- <c:component dest="target/test/example-3.part" test="true" name="weak"
- type="net.dpml.test.SingletonComponent" lifestyle="SINGLETON"
collection="WEAK">
- <context>
- <entry key="color" method="RED"/>
- </context>
- </c:component>
-
- <c:component dest="target/test/example-4.part" test="true"
- type="net.dpml.test.SingletonComponent" name="singleton"
collection="HARD">
- <context>
- <entry key="color" method="RED"/>
- </context>
- </c:component>
-
- <c:component dest="target/test/context.part" test="true"
- type="net.dpml.test.ContextTestComponent" name="context"
collection="SOFT">
- <context>
- <entry key="color" method="RED"/>
- <entry key="integer" value="0"/>
- <entry key="short" value="0"/>
- <entry key="long" value="0"/>
- <entry key="byte" value="0"/>
- <entry key="double" value="0"/>
- <entry key="float" value="0.5"/>
- <entry key="char" value="x"/>
- <entry key="boolean" value="true"/>
- <entry key="file" value="$${work}"/>
- <entry key="tempFile" value="$${temp}"/>
- <entry key="URI" value="$${uri}"/>
- <entry key="name" value="$${name}"/>
- <entry key="path" value="$${path}"/>
- </context>
- </c:component>
-
- <!-- create the composite component -->
-
- <types xmlns="dpml:metro">
- <type class="net.dpml.test.composite.ChildComponent" name="child"/>
- <type class="net.dpml.test.composite.CompositeComponent"
name="parent"/>
- <type class="net.dpml.test.composite.PartsComponent" name="parent"/>
- </types>
-
- <c:component dest="target/test/composite.part" test="true"
- type="net.dpml.test.composite.CompositeComponent" collection="HARD">
- <context>
- <entry key="color" method="RED"/>
- </context>
- <parts>
- <component type="net.dpml.test.composite.ChildComponent" key="child">
- <context>
- <entry key="color" method="BLUE"/>
- </context>
- </component>
- </parts>
- </c:component>
-
- <c:component dest="target/test/parts.part" test="true"
- type="net.dpml.test.composite.PartsComponent" collection="HARD">
- <context>
- <entry key="color" method="RED"/>
- </context>
- <parts>
- <component type="net.dpml.test.composite.ChildComponent" key="child">
- <context>
- <entry key="color" method="BLUE"/>
- </context>
- </component>
- </parts>
- </c:component>
-
- <!-- create the lifecycle managed component -->
-
- <c:type class="net.dpml.test.lifecycle.StartableComponent"
name="lifecycle">
- <state>
- <trigger event="initialization">
- <transition name="init" target="started">
- <operation name="startup" method="start"/>
- </transition>
- </trigger>
- <state name="started">
- <transition name="stop" target="../stopped">
- <operation name="stop" method="stop"/>
- </transition>
- <trigger event="termination">
- <apply id="stop"/>
- </trigger>
- </state>
- <state name="stopped">
- <transition name="start" target="../started">
- <operation name="start" method="start"/>
- </transition>
- </state>
- </state>
- </c:type>
-
- <c:component dest="target/test/lifecycle.part" test="true"
- type="net.dpml.test.lifecycle.StartableComponent" collection="HARD"/>
-
- <!-- categories component -->
-
- <c:type class="net.dpml.test.categories.CategoriesComponent"
name="categories" lifestyle="thread">
- <categories>
- <category name="alpha"/>
- <category name="beta"/>
- </categories>
- </c:type>
-
- <c:component dest="target/test/categories.part" test="true"
activation="STARTUP"
- type="net.dpml.test.categories.CategoriesComponent"
collection="hard">
- <categories>
- <category name="alpha" priority="warn"/>
- <category name="beta" priority="error"/>
- </categories>
- </c:component>
-
- <!-- part test component -->
-
- <c:type class="net.dpml.test.part.ExampleComponent" name="test"/>
- <c:component dest="target/test/test.part" test="true"
- type="net.dpml.test.part.ExampleComponent">
- <context>
- <entry key="color" method="RED"/>
- </context>
- </c:component>
-
- <!-- composite app-->
-
- <c:types>
- <type name="server" class="net.dpml.test.app.DefaultServer"
lifestyle="singleton"/>
- <type name="listener" class="net.dpml.test.app.DefaultListener"
lifestyle="singleton"/>
- <type name="demo" class="net.dpml.test.app.Demo"
lifestyle="singleton"/>
- </c:types>
-
- <c:component type="net.dpml.test.app.Demo"
- dest="target/test/application.part" test="true" collection="hard">
- <parts>
- <component key="server" type="net.dpml.test.app.DefaultServer" >
- <context>
- <entry key="port" value="1010"/>
- </context>
- </component>
- <component key="listener" type="net.dpml.test.app.DefaultListener" >
- <context>
- <entry key="server" lookup="net.dpml.test.app.Server"/>
- </context>
- </component>
- </parts>
- </c:component>
-
- <!-- operations test -->
-
- <c:type class="net.dpml.test.state.ManagedComponent" name="demo"
lifestyle="thread">
- <state>
- <operation name="ping" method="ping"/>
- <operation name="monitor"/>
- </state>
- </c:type>
-
- <c:component dest="target/test/state.part" test="true"
activation="STARTUP"
- type="net.dpml.test.state.ManagedComponent" collection="hard"/>
-
- <!-- array test -->
-
- <c:type class="net.dpml.test.array.ArrayTestComponent" name="array"/>
- <c:component dest="target/test/array.part" test="true"
- type="net.dpml.test.array.ArrayTestComponent">
- <context>
- <entry key="values">
- <value value="Hello"/>
- <value value="World"/>
- </entry>
- </context>
- </c:component>
-
- </target>
-
- <target name="install" depends="standard.install">
- <c:catalog title="Test Catalog">
- <fileset dir="${basedir}">
- <include name="**/target/classes/main/**/*.type"/>
- </fileset>
- </c:catalog>
- </target>
-
+ <target name="javadoc"/>
+
</project>



Added: trunk/main/metro/test/etc/data/application.xml
===================================================================
--- trunk/main/metro/test/etc/data/application.xml 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/test/etc/data/application.xml 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+
+<application xmlns="dpml:application">
+
+ <info name="hello"/>
+
+ <process startup="0" shutdown="0" path="target/test">
+ <environment>
+ <variable name="FOO" value="BAR"/>
+ </environment>
+ <properties>
+ <property name="foo" value="bar"/>
+ </properties>
+ </process>
+
+ <codebase
uri="link:part:dpml/lang/dpml-lang-sample?message=Hello%20World,port=1024"/>
+
+</application>

Modified: trunk/main/metro/test/etc/data/logging.properties
===================================================================
--- trunk/main/metro/test/etc/data/logging.properties 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/test/etc/data/logging.properties 2007-02-08 23:33:09
UTC (rev 1821)
@@ -1,4 +1,7 @@
.level=INFO
sun.rmi.level=INFO
sun.rmi.transport.tcp.level=INFO
-weak.level=FINE
\ No newline at end of file
+weak.level=FINE
+dpml.transit.level=WARNING
+dpml.lang.level=WARNING
+dpml.part.level=WARNING

Added: trunk/main/metro/test/etc/data/security.policy
===================================================================
--- trunk/main/metro/test/etc/data/security.policy 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/test/etc/data/security.policy 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,4 @@
+grant {
+ permission java.security.AllPermission;
+};
+

Added: trunk/main/metro/test/etc/data/test.properties
===================================================================
--- trunk/main/metro/test/etc/data/test.properties 2007-02-08 23:32:32
UTC (rev 1820)
+++ trunk/main/metro/test/etc/data/test.properties 2007-02-08 23:33:09
UTC (rev 1821)
@@ -0,0 +1,6 @@
+java.ext.dirs=${env.DPML_HOME}\share\lib\ext
+java.endorsed.dirs=${env.DPML_HOME}\share\lib\endorsed
+java.system.class.loader=dpml.util.SystemClassLoader
+java.protocol.handler.pkgs=dpml.transit
+java.rmi.server.RMIClassLoaderSpi=dpml.util.FederatingClassLoader
+dpml.class.path=link:jar:dpml/lang/dpml-lang-part

Added: trunk/main/metro/test/project.xml
===================================================================
--- trunk/main/metro/test/project.xml 2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/test/project.xml 2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<project xmlns="dpml:library" name="dpml-metro-test">
+
+ <info title="DPML Metro Test Suite"/>
+
+ <dependencies>
+ <runtime>
+ <include ref="dpml/metro/dpml-metro-appliance"/>
+ </runtime>
+ <test>
+ <include ref="org/apache/ant/ant-junit"/>
+ </test>
+ </dependencies>
+
+</project>
+

Added: trunk/main/metro/test/src/test/net/dpml/test/LocalTestCase.java
===================================================================
--- trunk/main/metro/test/src/test/net/dpml/test/LocalTestCase.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/test/src/test/net/dpml/test/LocalTestCase.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -0,0 +1,65 @@
+/*
+ * 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.test;
+
+import dpml.util.DefaultLogger;
+import dpml.util.ExceptionHelper;
+
+import java.net.URI;
+import java.net.URL;
+import java.rmi.RMISecurityManager;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.TestCase;
+
+import net.dpml.appliance.Appliance;
+
+import net.dpml.transit.Artifact;
+
+import net.dpml.util.Logger;
+
+/**
+ * Appliance testcase.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class LocalTestCase extends TestCase
+{
+ private Logger m_logger = new DefaultLogger( "test" );
+
+ public void testClassicAppliance() throws Exception
+ {
+ URI uri = URI.create( "link:appliance:dpml/metro/demo" );
+ URL url = Artifact.toURL( uri );
+ Appliance appliance = (Appliance) url.getContent( new Class[]{
Appliance.class } );
+ try
+ {
+ appliance.commission();
+ }
+ finally
+ {
+ appliance.decommission();
+ }
+ }
+
+ static
+ {
+ System.setSecurityManager( new RMISecurityManager() );
+ }
+}

Added: trunk/main/metro/test/src/test/net/dpml/test/PlanTestCase.java
===================================================================
--- trunk/main/metro/test/src/test/net/dpml/test/PlanTestCase.java
2007-02-08 23:32:32 UTC (rev 1820)
+++ trunk/main/metro/test/src/test/net/dpml/test/PlanTestCase.java
2007-02-08 23:33:09 UTC (rev 1821)
@@ -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.test;
+
+import dpml.util.DefaultLogger;
+import dpml.util.ExceptionHelper;
+
+import java.net.URI;
+import java.net.URL;
+import java.rmi.RMISecurityManager;
+
+import junit.framework.TestCase;
+
+import net.dpml.appliance.Appliance;
+
+import net.dpml.transit.Artifact;
+
+import net.dpml.util.Logger;
+
+/**
+ * Plan testcase.
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class PlanTestCase extends TestCase
+{
+ private Logger m_logger = new DefaultLogger( "test" );
+
+ public void testPlanDeployment() throws Exception
+ {
+ URI uri = URI.create( "link:plan:dpml/metro/demo" );
+ URL url = Artifact.toURL( uri );
+ Appliance appliance = (Appliance) url.getContent( new Class[]{
Appliance.class } );
+ try
+ {
+ appliance.commission();
+ }
+ finally
+ {
+ appliance.decommission();
+ }
+ }
+
+ static
+ {
+ System.setSecurityManager( new RMISecurityManager() );
+ }
+}




  • r1821 - in trunk/main/metro: . appliance appliance/etc appliance/etc/data appliance/etc/main appliance/etc/main/META-INF appliance/etc/main/META-INF/services appliance/etc/xsds appliance/src appliance/src/main appliance/src/main/dpml appliance/src/main/dpml/station appliance/src/main/dpml/station/info appliance/src/main/dpml/station/util appliance/src/main/net appliance/src/main/net/dpml appliance/src/main/net/dpml/station appliance/src/test appliance/src/test/net appliance/src/test/net/dpml appliance/src/test/net/dpml/appliance connector connector/etc connector/src connector/src/main connector/src/main/dpml connector/src/main/dpml/station connector/src/main/dpml/station/connector main main/etc main/etc/bin main/src main/src/main main/src/main/dpml main/src/main/dpml/metro main/src/main/dpml/metro/console station station/etc station/etc/bin station/etc/bin/scm station/etc/bin/scm/conf station/etc/bin/scm/lib station/etc/prefs station/etc/prefs/plans station/etc/pref! s/propertiess station/src station/src/main station/src/main/dpml station/src/main/dpml/station station/src/main/dpml/station/console test test/etc/data test/src test/src/test/net/dpml/test, mcconnell at BerliOS, 02/08/2007

Archive powered by MHonArc 2.6.24.

Top of Page