You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by rf...@apache.org on 2007/02/13 03:30:40 UTC

svn commit: r506820 - in /incubator/tuscany/branches/sca-java-integration: sca/kernel/api/src/main/java/org/apache/tuscany/api/ sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/ sca/test/src/main/java/org/apache/tuscany/test/ spec/sca-ap...

Author: rfeng
Date: Mon Feb 12 18:30:40 2007
New Revision: 506820

URL: http://svn.apache.org/viewvc?view=rev&rev=506820
Log:
[sca-integration-branch] Add the TuscanyContainer as the entry point to start/stop Tuscany runtime and retrieve ComponentContext

Added:
    incubator/tuscany/branches/sca-java-integration/sca/kernel/api/src/main/java/org/apache/tuscany/api/TuscanyContainer.java   (with props)
    incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultTuscanyContainer.java   (with props)
Modified:
    incubator/tuscany/branches/sca-java-integration/sca/test/src/main/java/org/apache/tuscany/test/SCATestCase.java
    incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CompositeContext.java
    incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CurrentCompositeContext.java

Added: incubator/tuscany/branches/sca-java-integration/sca/kernel/api/src/main/java/org/apache/tuscany/api/TuscanyContainer.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/sca/kernel/api/src/main/java/org/apache/tuscany/api/TuscanyContainer.java?view=auto&rev=506820
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/sca/kernel/api/src/main/java/org/apache/tuscany/api/TuscanyContainer.java (added)
+++ incubator/tuscany/branches/sca-java-integration/sca/kernel/api/src/main/java/org/apache/tuscany/api/TuscanyContainer.java Mon Feb 12 18:30:40 2007
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+package org.apache.tuscany.api;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.osoa.sca.ComponentContext;
+
+/**
+ * The Tuscany container
+ */
+public abstract class TuscanyContainer {
+    public static final String SYSTEM_SCDL = "META-INF/tuscany/system.scdl";
+    public static final String EXTENSION_SCDL = "META-INF/sca/extension.scdl";
+    public static final String APPLICATION_SCDL = "META-INF/sca/application.composite";
+
+    private static TuscanyContainer instance;
+
+    /**
+     * Read the service name from a configuration file
+     * @param classLoader
+     * @param name
+     * @return
+     * @throws IOException
+     */
+    private static String getServiceName(ClassLoader classLoader, String name) throws IOException {
+        InputStream is = classLoader.getResourceAsStream("META-INF/services/" + name);
+        if (is == null) {
+            return null;
+        }
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new InputStreamReader(is));
+            while (true) {
+                String line = reader.readLine();
+                if (line == null) {
+                    break;
+                } else if (!line.startsWith("#")) {
+                    return line.trim();
+                }
+            }
+        } finally {
+            if (reader != null) {
+                reader.close();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a TuscanyContainer instance. If the system property
+     * "org.apache.tuscany.api.TuscanyContainer" is set, its value is used as
+     * the name of the implementation class. Otherwise, if the resource
+     * "META-INF/services/org.apache.tuscany.api.TuscanyContainer" can be loaded
+     * from the supplied classloader. Otherwise, it will use
+     * "org.apache.tuscany.core.bootstrap.DefaultTuscanyContainer" as the default.
+     * The named class is loaded from the supplied classloader and instantiated
+     * using its default (no-arg) constructor.
+     * 
+     * @return
+     */
+    private synchronized static TuscanyContainer newInstance(final ClassLoader classLoader) {
+
+        try {
+            final String name = TuscanyContainer.class.getName();
+            String className = AccessController.doPrivileged(new PrivilegedAction<String>() {
+                public String run() {
+                    return System.getProperty(name);
+                }
+            });
+
+            if (className == null) {
+                className = getServiceName(classLoader, name);
+            }
+            if (className == null) {
+                className = "org.apache.tuscany.core.bootstrap.DefaultTuscanyContainer";
+            }
+            Class cls = Class.forName(className, true, classLoader);
+            return (TuscanyContainer)cls.newInstance();
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Get an instance of Tuscany container
+     * 
+     * @return The instance
+     */
+    private static TuscanyContainer getInstance() {
+        if (instance != null) {
+            return instance;
+        }
+        ClassLoader classLoader = TuscanyContainer.class.getClassLoader();
+        instance = newInstance(classLoader);
+        return instance;
+    }
+
+    /**
+     * Start the Tuscany runtime using default SCDLs
+     */
+    public static void start() {
+        try {
+            getInstance().startup(null, null, null);
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Start the Tuscany container with the given SCDLs
+     * 
+     * @param system The URL for the system SCDL
+     * @param extensions An array of URLs for extensions
+     * @param application The URL for the application SCDL
+     */
+    public static void start(URL system, URL[] extensions, URL application) {
+        try {
+            getInstance().startup(system, extensions, application);
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Get the ComponentContext by name
+     * 
+     * @param componentName
+     * @return
+     */
+    public static ComponentContext getComponentContext(String componentName) {
+        return getInstance().getContext(componentName);
+    }
+
+    /**
+     * Stop the Tuscany container
+     */
+    public static void stop() {
+        try {
+            getInstance().shutdown();
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Look up the ComponentContext by name
+     * @param componentName
+     * @return
+     */
+    protected abstract ComponentContext getContext(String componentName);
+
+    /**
+     * Start up the container
+     * @param system
+     * @param extensions
+     * @param application
+     * @throws Exception
+     */
+    protected abstract void startup(URL system, URL[] extensions, URL application) throws Exception;
+
+    /**
+     * Shutdown the container
+     * @throws Exception
+     */
+    protected abstract void shutdown() throws Exception;
+}

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/api/src/main/java/org/apache/tuscany/api/TuscanyContainer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/api/src/main/java/org/apache/tuscany/api/TuscanyContainer.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultTuscanyContainer.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultTuscanyContainer.java?view=auto&rev=506820
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultTuscanyContainer.java (added)
+++ incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultTuscanyContainer.java Mon Feb 12 18:30:40 2007
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.tuscany.core.bootstrap;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collections;
+import java.util.Enumeration;
+
+import org.apache.tuscany.api.TuscanyContainer;
+import org.apache.tuscany.api.TuscanyException;
+import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
+import org.apache.tuscany.core.launcher.CompositeContextImpl;
+import org.apache.tuscany.core.launcher.LauncherImpl;
+import org.apache.tuscany.core.monitor.JavaLoggingMonitorFactory;
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.host.runtime.InitializationException;
+import org.apache.tuscany.spi.bootstrap.ComponentNames;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.ComponentException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.deployer.DeploymentMonitor;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.wire.WireService;
+import org.osoa.sca.ComponentContext;
+import org.osoa.sca.CurrentCompositeContext;
+
+/**
+ * Base class for JUnit tests that want to run in an SCA client environment.
+ * 
+ * @version $Rev$ $Date$
+ */
+@SuppressWarnings("deprecation")
+public class DefaultTuscanyContainer extends TuscanyContainer {
+    protected CompositeComponent component;
+    private CompositeContextImpl context;
+    private LauncherImpl launcher;
+    private MonitorFactory monitorFactory;
+
+    protected void startup(URL system, URL[] exts, URL applicationSCDL) throws Exception {
+        if (monitorFactory == null) {
+            monitorFactory = new JavaLoggingMonitorFactory();
+        }
+        ClassLoader cl = getClass().getClassLoader();
+        launcher = new LauncherImpl();
+        launcher.setApplicationLoader(cl);
+
+        if (system == null) {
+            system = cl.getResource(TuscanyContainer.SYSTEM_SCDL);
+        }
+
+        try {
+            CompositeComponent composite = launcher.bootRuntime(system, monitorFactory);
+            if (exts == null) {
+                Enumeration<URL> urls = cl.getResources(TuscanyContainer.EXTENSION_SCDL);
+                exts = Collections.list(urls).toArray(new URL[0]);
+            }
+            for (int i=0;i<exts.length;i++) {
+                deployExtension(composite, "tuscany.extension." + (i++), exts[i]);
+            }
+
+            SCAObject wireServiceComponent = composite.getSystemChild(ComponentNames.TUSCANY_WIRE_SERVICE);
+            if (!(wireServiceComponent instanceof AtomicComponent)) {
+                throw new InitializationException("WireService must be an atomic component");
+            }
+
+            WireService wireService = (WireService)((AtomicComponent)wireServiceComponent).getTargetInstance();
+
+            if (applicationSCDL == null) {
+                applicationSCDL = cl.getResource(TuscanyContainer.APPLICATION_SCDL);
+                throw new RuntimeException("application SCDL not found: " + applicationSCDL);
+            }
+            component = launcher.bootApplication("application", applicationSCDL);
+            component.start();
+            context = new CompositeContextImpl(component, wireService);
+            CurrentCompositeContext.setContext(context);
+        } catch (TuscanyException e) {
+            DeploymentMonitor monitor = monitorFactory.getMonitor(DeploymentMonitor.class);
+            monitor.deploymentError(e);
+            throw e;
+        }
+
+    }
+
+    /**
+     * Sets the monitor factory to use
+     * 
+     * @param monitorFactory the monitor factory to use
+     */
+    protected void setMonitorFactory(MonitorFactory monitorFactory) {
+        this.monitorFactory = monitorFactory;
+    }
+
+    protected void deployExtension(CompositeComponent composite, String extensionName, URL scdlURL)
+        throws LoaderException, BuilderException, ComponentException, InitializationException {
+        SystemCompositeImplementation implementation = new SystemCompositeImplementation();
+        implementation.setScdlLocation(scdlURL);
+        implementation.setClassLoader(new URLClassLoader(new URL[] {scdlURL}, getClass().getClassLoader()));
+
+        ComponentDefinition<SystemCompositeImplementation> definition =
+            new ComponentDefinition<SystemCompositeImplementation>(extensionName, implementation);
+
+        SCAObject child = composite.getSystemChild(ComponentNames.TUSCANY_DEPLOYER);
+        if (!(child instanceof AtomicComponent)) {
+            throw new InitializationException("Deployer must be an atomic component");
+        }
+        Deployer deployer = (Deployer)((AtomicComponent)child).getTargetInstance();
+        Component component = deployer.deploy(composite, definition);
+        component.start();
+    }
+
+    protected void shutdown() throws Exception {
+        CurrentCompositeContext.setContext(null);
+        component.stop();
+        launcher.shutdownRuntime();
+    }
+
+    @Override
+    protected ComponentContext getContext(String componentName) {
+        // TODO
+        return null;
+    }
+}

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultTuscanyContainer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultTuscanyContainer.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: incubator/tuscany/branches/sca-java-integration/sca/test/src/main/java/org/apache/tuscany/test/SCATestCase.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/sca/test/src/main/java/org/apache/tuscany/test/SCATestCase.java?view=diff&rev=506820&r1=506819&r2=506820
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/sca/test/src/main/java/org/apache/tuscany/test/SCATestCase.java (original)
+++ incubator/tuscany/branches/sca-java-integration/sca/test/src/main/java/org/apache/tuscany/test/SCATestCase.java Mon Feb 12 18:30:40 2007
@@ -20,98 +20,42 @@
 
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.URLClassLoader;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.tuscany.spi.bootstrap.ComponentNames;
-import org.apache.tuscany.spi.builder.BuilderException;
-import org.apache.tuscany.spi.component.AtomicComponent;
-import org.apache.tuscany.spi.component.Component;
-import org.apache.tuscany.spi.component.ComponentException;
-import org.apache.tuscany.spi.component.CompositeComponent;
-import org.apache.tuscany.spi.component.SCAObject;
-import org.apache.tuscany.spi.deployer.Deployer;
-import org.apache.tuscany.spi.deployer.DeploymentMonitor;
-import org.apache.tuscany.spi.loader.LoaderException;
-import org.apache.tuscany.spi.model.ComponentDefinition;
-import org.apache.tuscany.spi.wire.WireService;
-
 import junit.framework.TestCase;
-import org.apache.tuscany.api.TuscanyException;
-import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
-import org.apache.tuscany.core.launcher.CompositeContextImpl;
-import org.apache.tuscany.core.launcher.LauncherImpl;
-import org.apache.tuscany.core.monitor.JavaLoggingMonitorFactory;
-import org.apache.tuscany.host.MonitorFactory;
-import org.apache.tuscany.host.runtime.InitializationException;
 
-import org.osoa.sca.CurrentCompositeContext;
+import org.apache.tuscany.api.TuscanyContainer;
 
 /**
  * Base class for JUnit tests that want to run in an SCA client environment.
- *
+ * 
  * @version $Rev$ $Date$
  */
 public abstract class SCATestCase extends TestCase {
-    protected CompositeComponent component;
-    private CompositeContextImpl context;
     private Map<String, URL> extensions = new HashMap<String, URL>();
     private URL applicationSCDL;
-    private LauncherImpl launcher;
-    private MonitorFactory monitorFactory;
 
     protected void setUp() throws Exception {
         super.setUp();
-        if (monitorFactory == null) {
-            monitorFactory = new JavaLoggingMonitorFactory();
-        }
-        ClassLoader cl = getClass().getClassLoader();
-        launcher = new LauncherImpl();
-        launcher.setApplicationLoader(cl);
-        URL scdl = cl.getResource(LauncherImpl.METAINF_SYSTEM_SCDL_PATH);
-
-        try {
-            CompositeComponent composite = launcher.bootRuntime(scdl, monitorFactory);
-            for (String extensionName : extensions.keySet()) {
-                deployExtension(composite, extensionName, extensions.get(extensionName));
-            }
-
-            SCAObject wireServiceComponent = composite.getSystemChild(ComponentNames.TUSCANY_WIRE_SERVICE);
-            if (!(wireServiceComponent instanceof AtomicComponent)) {
-                throw new InitializationException("WireService must be an atomic component");
-            }
-
-            WireService wireService = (WireService) ((AtomicComponent) wireServiceComponent).getTargetInstance();
-
-            if (applicationSCDL == null) {
-                throw new RuntimeException("application SCDL not found: " + applicationSCDL);
-            }
-            component = launcher.bootApplication("application", applicationSCDL);
-            component.start();
-            context = new CompositeContextImpl(component, wireService);
-            CurrentCompositeContext.setContext(context);
-        } catch (TuscanyException e) {
-            DeploymentMonitor monitor = monitorFactory.getMonitor(DeploymentMonitor.class);
-            monitor.deploymentError(e);
-            throw e;
-        }
-
+        TuscanyContainer.start(null, extensions.values().toArray(new URL[0]), applicationSCDL);
     }
 
     /**
-     * A TestCase can use this to overide the default SCDL location of "META-INF/sca/default.scdl"
+     * A TestCase can use this to overide the default SCDL location of
+     * "META-INF/sca/default.scdl"
      */
     protected void setApplicationSCDL(URL applicationSCDL) {
         this.applicationSCDL = applicationSCDL;
     }
 
     /**
-     * Set the application scdl based on the classpath entry for a class. Normally this will be a class in the
-     * production code associated with this test case.
-     *
+     * Set the application scdl based on the classpath entry for a class.
+     * Normally this will be a class in the production code associated with this
+     * test case.
+     * 
      * @param aClass a Class from which to determine the resource base url
-     * @param path   location of the application SCDL relative to the base class
+     * @param path location of the application SCDL relative to the base class
      * @throws MalformedURLException if the path is malformed
      */
     protected void setApplicationSCDL(Class<?> aClass, String path) throws MalformedURLException {
@@ -120,42 +64,13 @@
     }
 
     /**
-     * A TestCase can use this to add the SCDL location of an extention to be deployed to the runtime
+     * A TestCase can use this to add the SCDL location of an extention to be
+     * deployed to the runtime
      */
     protected void addExtension(String extensionName, URL extentionSCDL) {
         extensions.put(extensionName, extentionSCDL);
     }
 
-
-    /**
-     * Sets the monitor factory to use
-     *
-     * @param monitorFactory the monitor factory to use
-     */
-    protected void setMonitorFactory(MonitorFactory monitorFactory) {
-        this.monitorFactory = monitorFactory;
-    }
-
-    protected void deployExtension(CompositeComponent composite, String extensionName, URL scdlURL)
-        throws LoaderException, BuilderException, ComponentException, InitializationException {
-        SystemCompositeImplementation implementation = new SystemCompositeImplementation();
-        implementation.setScdlLocation(scdlURL);
-        implementation.setClassLoader(new URLClassLoader(new URL[]{scdlURL}, getClass().getClassLoader()));
-
-        ComponentDefinition<SystemCompositeImplementation> definition =
-            new ComponentDefinition<SystemCompositeImplementation>(extensionName, implementation);
-
-
-        SCAObject child = composite.getSystemChild(ComponentNames.TUSCANY_DEPLOYER);
-        if (!(child instanceof AtomicComponent)) {
-            throw new InitializationException("Deployer must be an atomic component");
-        }
-        Deployer deployer = (Deployer) ((AtomicComponent) child).getTargetInstance();
-        Component component = deployer.deploy(composite, definition);
-        component.start();
-    }
-
-
     protected static URL getRoot(Class<?> aClass) {
         String name = aClass.getName();
         String classPath = "/" + name.replace('.', '/') + ".class";
@@ -175,9 +90,7 @@
     }
 
     protected void tearDown() throws Exception {
-        CurrentCompositeContext.setContext(null);
-        component.stop();
-        launcher.shutdownRuntime();
+        TuscanyContainer.stop();
         super.tearDown();
     }
 }

Modified: incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CompositeContext.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CompositeContext.java?view=diff&rev=506820&r1=506819&r2=506820
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CompositeContext.java (original)
+++ incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CompositeContext.java Mon Feb 12 18:30:40 2007
@@ -20,6 +20,8 @@
 
 
 /**
+ * @deprecated
+ * 
  * Interface used by SCA Components to access their context
  *
  * @version $Rev$ $Date$

Modified: incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CurrentCompositeContext.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CurrentCompositeContext.java?view=diff&rev=506820&r1=506819&r2=506820
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CurrentCompositeContext.java (original)
+++ incubator/tuscany/branches/sca-java-integration/spec/sca-api-r1.0/src/main/java/org/osoa/sca/CurrentCompositeContext.java Mon Feb 12 18:30:40 2007
@@ -19,6 +19,8 @@
 package org.osoa.sca;
 
 /**
+ * @deprecated
+ * 
  * Class providing access to the current CompositeComponent.
  *
  * @version $Rev$ $Date$



---------------------------------------------------------------------
To unsubscribe, e-mail: tuscany-commits-unsubscribe@ws.apache.org
For additional commands, e-mail: tuscany-commits-help@ws.apache.org