summaryrefslogtreecommitdiffstats
path: root/sandbox/ant/container.python
diff options
context:
space:
mode:
authordims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
committerdims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
commitbdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch)
tree38a92061c0793434c4be189f1d70c3458b6bc41d /sandbox/ant/container.python
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sandbox/ant/container.python')
-rw-r--r--sandbox/ant/container.python/NOTICE.txt14
-rw-r--r--sandbox/ant/container.python/pom.xml78
-rw-r--r--sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponent.java113
-rw-r--r--sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentBuilder.java74
-rw-r--r--sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentType.java61
-rw-r--r--sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentTypeLoader.java76
-rw-r--r--sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonImplementation.java37
-rw-r--r--sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonImplementationLoader.java123
-rw-r--r--sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonInvoker.java54
-rw-r--r--sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonScript.java116
-rw-r--r--sandbox/ant/container.python/src/main/resources/META-INF/sca/py.system.scdl40
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/HelloWorldService.java25
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentBuilderTestCase.java23
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTestCase.java94
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTypeLoaderTestCase.java87
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTypeTestCase.java36
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonImplementationLoaderTestCase.java110
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonImplementationTestCase.java33
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonInvokerTestCase.java62
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonScriptTestCase.java82
-rw-r--r--sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/function/HelloWorldTestCase.java46
-rw-r--r--sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/PythonScriptTestCase.py6
-rw-r--r--sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/HelloWorld.componentType9
-rw-r--r--sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/helloworld.py6
-rw-r--r--sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/helloworld.scdl29
25 files changed, 1434 insertions, 0 deletions
diff --git a/sandbox/ant/container.python/NOTICE.txt b/sandbox/ant/container.python/NOTICE.txt
new file mode 100644
index 0000000000..d83ebbe236
--- /dev/null
+++ b/sandbox/ant/container.python/NOTICE.txt
@@ -0,0 +1,14 @@
+${pom.name}
+Copyright (c) 2005 - 2006 The Apache Software Foundation
+
+Apache Tuscany is an effort undergoing incubation at The Apache Software
+Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is
+required of all newly accepted projects until a further review indicates that
+the infrastructure, communications, and decision making process have stabilized
+in a manner consistent with other successful ASF projects. While incubation
+status is not necessarily a reflection of the completeness or stability of the
+code, it does indicate that the project has yet to be fully endorsed by the ASF.
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/sandbox/ant/container.python/pom.xml b/sandbox/ant/container.python/pom.xml
new file mode 100644
index 0000000000..1b31cab18b
--- /dev/null
+++ b/sandbox/ant/container.python/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<project>
+
+ <parent>
+ <groupId>org.apache.tuscany.containers</groupId>
+ <artifactId>containers</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>tuscany-python</artifactId>
+ <name>Apache Tuscany Python Container</name>
+ <description>Apache Tuscany Python Container</description>
+
+ <repositories>
+ <repository>
+ <id>ant</id>
+ <url>http://people.apache.org/~antelder/maven2</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.tuscany</groupId>
+ <artifactId>core</artifactId>
+ <version>${sca.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jython</groupId>
+ <artifactId>jython</artifactId>
+ <version>2.2a1</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany</groupId>
+ <artifactId>test</artifactId>
+ <version>${sca.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ </dependency>
+
+ </dependencies>
+
+</project>
diff --git a/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponent.java b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponent.java
new file mode 100644
index 0000000000..4376c48b82
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponent.java
@@ -0,0 +1,113 @@
+/*
+ * 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.container.python;
+
+import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.TargetException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.extension.AtomicComponentExtension;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.WireService;
+
+/**
+ * A component implementation for the Python language.
+ */
+public class PythonComponent extends AtomicComponentExtension {
+
+ private final List<Class<?>> services;
+
+ private final Map<String, Object> properties;
+
+ private PythonScript rhinoScript;
+
+ public PythonComponent(String name, PythonScript rhinoScript, List<Class<?>> services, CompositeComponent parent, ScopeContainer scopeContainer,
+ WireService wireService, WorkContext workContext) {
+
+ super(name, parent, scopeContainer, wireService, workContext, null, 0);
+
+ this.rhinoScript = rhinoScript;
+ this.services = services;
+ this.scope = scopeContainer.getScope();
+ this.properties = new HashMap<String, Object>();
+ }
+
+ public Object createInstance() throws ObjectCreationException {
+
+ Map<String, Object> context = new HashMap<String, Object>(getProperties());
+
+ for (List<OutboundWire> referenceWires : getOutboundWires().values()) {
+ for (OutboundWire wire : referenceWires) {
+ Object wireProxy = wireService.createProxy(wire);
+ context.put(wire.getReferenceName(), wireProxy);
+ }
+ }
+
+ Object instance = rhinoScript.createInstance(context);
+
+ return instance;
+ }
+
+ public TargetInvoker createTargetInvoker(String serviceName, Operation operation) {
+ Method[] methods = operation.getServiceContract().getInterfaceClass().getMethods();
+ Method method = findMethod(operation, methods);
+ return new PythonInvoker(method, this);
+ }
+
+ // TODO: move all the following up to AtomicComponentExtension?
+
+ public List<Class<?>> getServiceInterfaces() {
+ return services;
+ }
+
+ public Map<String, Object> getProperties() {
+ return properties;
+ }
+
+ public Object getTargetInstance() throws TargetException {
+ return scopeContainer.getInstance(this);
+ }
+
+ public Object getServiceInstance() throws TargetException {
+ return getServiceInstance(null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getServiceInstance(String service) throws TargetException {
+ InboundWire wire = getInboundWire(service);
+ if (wire == null) {
+ TargetException e = new TargetException("ServiceDefinition not found"); // TODO better error message
+ e.setIdentifier(service);
+ throw e;
+ }
+ return wireService.createProxy(wire);
+ }
+
+}
diff --git a/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentBuilder.java b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentBuilder.java
new file mode 100644
index 0000000000..d460f77bc6
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentBuilder.java
@@ -0,0 +1,74 @@
+/*
+ * 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.container.python;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.tuscany.spi.builder.BuilderConfigException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentBuilderExtension;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+/**
+ * Extension point for creating {@link PythonComponent}s from an assembly configuration
+ */
+public class PythonComponentBuilder extends ComponentBuilderExtension<PythonImplementation> {
+
+ public PythonComponentBuilder() {
+ }
+
+ protected Class<PythonImplementation> getImplementationType() {
+ return PythonImplementation.class;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Component build(CompositeComponent parent, ComponentDefinition<PythonImplementation> componentDefinition,
+ DeploymentContext deploymentContext) throws BuilderConfigException {
+
+ String name = componentDefinition.getName();
+ PythonImplementation implementation = componentDefinition.getImplementation();
+ PythonComponentType componentType = implementation.getComponentType();
+
+ // get list of services provided by this component
+ Collection<ServiceDefinition> collection = componentType.getServices().values();
+ List<Class<?>> services = new ArrayList<Class<?>>(collection.size());
+ for (ServiceDefinition serviceDefinition : collection) {
+ services.add(serviceDefinition.getServiceContract().getInterfaceClass());
+ }
+
+ // TODO: have ComponentBuilderExtension pass ScopeContainer in on build method?
+ ScopeContainer scopeContainer;
+ Scope scope = componentType.getLifecycleScope();
+ if (Scope.MODULE == scope) {
+ scopeContainer = deploymentContext.getModuleScope();
+ } else {
+ scopeContainer = scopeRegistry.getScopeContainer(scope);
+ }
+
+ return new PythonComponent(name, implementation.getJythonScript(), services, parent, scopeContainer, wireService, workContext);
+ }
+
+}
diff --git a/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentType.java b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentType.java
new file mode 100644
index 0000000000..640ff297c5
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentType.java
@@ -0,0 +1,61 @@
+/*
+ * 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.container.python;
+
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+/**
+ * A componentType for Python components
+ * TODO: really need a generic componentType that supports scope and lifecycle
+ */
+public class PythonComponentType extends ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> {
+
+ private Scope lifecycleScope = Scope.MODULE;
+
+ public PythonComponentType() {
+ }
+
+ @SuppressWarnings("unchecked")
+ public PythonComponentType(ComponentType ct) {
+ // TODO: A bit hacky but this is so the non-python .componentType XML side file can be used for now
+ setInitLevel(ct.getInitLevel());
+ for (Object property : ct.getProperties().values()) {
+ add((Property) property);
+ }
+ for (Object reference : ct.getReferences().values()) {
+ add((ReferenceDefinition) reference);
+ }
+ for (Object service : ct.getServices().values()) {
+ add((ServiceDefinition) service);
+ }
+ }
+
+ public Scope getLifecycleScope() {
+ return lifecycleScope;
+ }
+
+ public void setLifecycleScope(Scope lifecycleScope) {
+ this.lifecycleScope = lifecycleScope;
+ }
+
+}
diff --git a/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentTypeLoader.java b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentTypeLoader.java
new file mode 100644
index 0000000000..1f1456594e
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonComponentTypeLoader.java
@@ -0,0 +1,76 @@
+/*
+ * 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.container.python;
+
+import java.net.URL;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.model.ComponentType;
+
+/**
+ * ComponentType loader for Python components
+ */
+public class PythonComponentTypeLoader extends ComponentTypeLoaderExtension<PythonImplementation> {
+
+ public PythonComponentTypeLoader() {
+ }
+
+ @Override
+ protected Class<PythonImplementation> getImplementationClass() {
+ return PythonImplementation.class;
+ }
+
+ protected String getResourceName(PythonImplementation implementation) {
+ return implementation.getJythonScript().getModuleName();
+ }
+
+ // TODO: must be possible to move all the following up in to ComponentTypeLoaderExtension
+
+ public void load(CompositeComponent parent, PythonImplementation implementation, DeploymentContext deploymentContext) throws LoaderException {
+ String sideFile = getSideFileName(implementation);
+ URL resource = implementation.getJythonScript().getClassLoader().getResource(sideFile);
+ PythonComponentType componentType;
+ if (resource == null) {
+ throw new IllegalArgumentException("missing .componentType side file: " + sideFile);
+ // TODO: or else implement intospection
+ } else {
+ componentType = loadFromSidefile(resource, deploymentContext);
+ }
+ implementation.setComponentType(componentType);
+ }
+
+ protected PythonComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext) throws LoaderException {
+ ComponentType ct = loaderRegistry.load(null, url, ComponentType.class, deploymentContext);
+ PythonComponentType pythonComponentType = new PythonComponentType(ct);
+ return pythonComponentType;
+ }
+
+ protected String getSideFileName(PythonImplementation implementation) {
+ String baseName = getResourceName(implementation);
+ int lastDot = baseName.lastIndexOf('.');
+ if (lastDot != -1) {
+ baseName = baseName.substring(0, lastDot);
+ }
+ return baseName + ".componentType";
+ }
+
+}
diff --git a/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonImplementation.java b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonImplementation.java
new file mode 100644
index 0000000000..df35801e88
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonImplementation.java
@@ -0,0 +1,37 @@
+/*
+ * 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.container.python;
+
+import org.apache.tuscany.spi.model.AtomicImplementation;
+
+/**
+ * Model object for a Python implementation.
+ */
+public class PythonImplementation extends AtomicImplementation<PythonComponentType> {
+
+ private PythonScript pythonScript;
+
+ public PythonScript getJythonScript() {
+ return pythonScript;
+ }
+
+ public void setPythonScript(PythonScript pythonScript) {
+ this.pythonScript = pythonScript;
+ }
+}
diff --git a/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonImplementationLoader.java b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonImplementationLoader.java
new file mode 100644
index 0000000000..61a6cbd4b6
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonImplementationLoader.java
@@ -0,0 +1,123 @@
+/*
+ * 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.container.python;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.loader.MissingResourceException;
+import org.osoa.sca.annotations.Constructor;
+
+/**
+ * Loader for handling python elements.
+ *
+ * <py:implementation.python module="path/foo.py" class="myclass">
+ *
+ */
+public class PythonImplementationLoader extends LoaderExtension<PythonImplementation> {
+
+ private static final QName IMPLEMENTATION_PYTHON = new QName("http://tuscany.apache.org/xmlns/python/1.0", "implementation.python");
+
+ @Constructor( { "registry" })
+ public PythonImplementationLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return IMPLEMENTATION_PYTHON;
+ }
+
+ public PythonImplementation load(CompositeComponent parent, XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+
+ String moduleName = reader.getAttributeValue(null, "module");
+ if (moduleName == null) {
+ throw new MissingResourceException("implementation element has no module attribute");
+ }
+
+ String className = reader.getAttributeValue(null, "class");
+
+ LoaderUtil.skipToEndElement(reader);
+
+ PythonImplementation implementation = new PythonImplementation();
+
+ ClassLoader cl = deploymentContext.getClassLoader();
+ String pythonSource = loadSource(cl, moduleName);
+
+ PythonScript pythonScript = new PythonScript(moduleName, className, pythonSource, cl);
+ implementation.setPythonScript(pythonScript);
+
+ registry.loadComponentType(parent, implementation, deploymentContext);
+
+ Class iface = implementation.getComponentType().getServices().values().iterator().next().getServiceContract().getInterfaceClass();
+ // TODO: service interfaces should be on PythonScript constructor but loadComponentType requires the script name to work out the sidefile name
+ pythonScript.setServiceInterface(iface);
+
+ return implementation;
+ }
+
+ protected String loadSource(ClassLoader cl, String resource) throws LoaderException {
+ URL url = cl.getResource(resource);
+ if (url == null) {
+ throw new MissingResourceException(resource);
+ }
+ InputStream is;
+ try {
+ is = url.openStream();
+ } catch (IOException e) {
+ MissingResourceException mre = new MissingResourceException(resource, e);
+ mre.setIdentifier(resource);
+ throw mre;
+ }
+ try {
+ Reader reader = new InputStreamReader(is, "UTF-8");
+ char[] buffer = new char[1024];
+ StringBuilder source = new StringBuilder();
+ int count;
+ while ((count = reader.read(buffer)) > 0) {
+ source.append(buffer, 0, count);
+ }
+ return source.toString();
+ } catch (IOException e) {
+ LoaderException le = new LoaderException(e);
+ le.setIdentifier(resource);
+ throw le;
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+}
diff --git a/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonInvoker.java b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonInvoker.java
new file mode 100644
index 0000000000..62f7a6c847
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonInvoker.java
@@ -0,0 +1,54 @@
+/*
+ * 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.container.python;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.spi.extension.TargetInvokerExtension;
+
+/**
+ * Dispatches to a PythonScript implementation instance
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class PythonInvoker extends TargetInvokerExtension {
+
+ private PythonComponent context;
+
+ private Method method;
+
+ public PythonInvoker(Method method, PythonComponent context) {
+ this.method = method;
+ this.context = context;
+ }
+
+ /**
+ * Invokes a function on a script instance
+ */
+ public Object invokeTarget(final Object payload) throws InvocationTargetException {
+ Object target = context.getTargetInstance();
+ try {
+ return method.invoke(target, (Object[]) payload);
+ } catch (Exception e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+
+}
diff --git a/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonScript.java b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonScript.java
new file mode 100644
index 0000000000..1eab532582
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/java/org/apache/tuscany/container/python/PythonScript.java
@@ -0,0 +1,116 @@
+/*
+ * 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.container.python;
+
+import java.util.Map;
+
+import org.python.core.Py;
+import org.python.core.PyObject;
+import org.python.core.PySystemState;
+import org.python.util.PythonInterpreter;
+
+/**
+ * JythonScript represents a compiled Jython script
+ */
+public class PythonScript {
+
+ protected String moduleName;
+
+ protected String className;
+
+ protected String script;
+
+ protected Class iface;
+
+ protected ClassLoader classLoader;
+
+ private PyObject pythonClass;
+
+ /**
+ * Create a new RhinoInvoker.
+ *
+ * @param scriptName
+ * the name of the script. Can be anything, only used in messages to identify the script
+ * @param script
+ * the complete script
+ * @param context
+ * name-value pairs that are added in to the scope where the script is compiled. May be null. The value objects are made available to
+ * the script by using a variable with the name.
+ * @param classLoader
+ * the ClassLoader Rhino should use to locate any user Java classes used in the script
+ */
+ public PythonScript(String moduleName, String className, String script, ClassLoader classLoader) {
+ this.moduleName = moduleName;
+ this.className = className;
+ this.script = script;
+ this.classLoader = classLoader;
+
+ }
+
+ private void initScript(String moduleName, String className, String script) {
+ PythonInterpreter interpreter = new PythonInterpreter();
+ PySystemState sys = Py.getSystemState();
+ PySystemState.add_package(iface.getPackage().getName(), null);
+ sys.setClassLoader(classLoader);
+ interpreter.exec(script);
+
+ pythonClass = interpreter.get(className);
+ if (pythonClass == null) {
+ throw new RuntimeException("No callable (class or function) " + "named " + className + " in " + moduleName);
+ }
+ }
+
+ /**
+ * Create a new invokeable instance of the script
+ *
+ * @param context
+ * objects to add to scope of the script instance
+ * @return a RhinoScriptInstance
+ */
+ public Object createInstance(Map<String, Object> context) {
+ initScript(moduleName, className, script);
+
+ PyObject instance = pythonClass.__call__();
+ Object o = instance.__tojava__(iface);
+ if (o == Py.NoConversion) {
+ throw new RuntimeException("The value from " + className + " must extend " + iface.getName());
+ }
+ return o;
+ }
+
+ public String getModuleName() {
+ return moduleName;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getScript() {
+ return script;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public void setServiceInterface(Class iface) {
+ this.iface = iface;
+ }
+}
diff --git a/sandbox/ant/container.python/src/main/resources/META-INF/sca/py.system.scdl b/sandbox/ant/container.python/src/main/resources/META-INF/sca/py.system.scdl
new file mode 100644
index 0000000000..e124d8677d
--- /dev/null
+++ b/sandbox/ant/container.python/src/main/resources/META-INF/sca/py.system.scdl
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<!--
+ JavaScript configuration for the launcher environment.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ xmlns:system="http://tuscany.apache.org/xmlns/system/1.0-SNAPSHOT"
+
+ name="org.apache.tuscany.launcher.PythonImplementation">
+
+ <component name="python.implementationLoader">
+ <system:implementation.system class="org.apache.tuscany.container.python.PythonImplementationLoader"/>
+ </component>
+
+ <component name="python.componentTypeLoader">
+ <system:implementation.system class="org.apache.tuscany.container.python.PythonComponentTypeLoader"/>
+ </component>
+
+ <component name="python.componentBuilder">
+ <system:implementation.system class="org.apache.tuscany.container.python.PythonComponentBuilder"/>
+ </component>
+
+</composite>
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/HelloWorldService.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/HelloWorldService.java
new file mode 100644
index 0000000000..50ba1c3695
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/HelloWorldService.java
@@ -0,0 +1,25 @@
+/*
+ * 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.container.python;
+
+public interface HelloWorldService {
+
+ String sayHello(String s);
+
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentBuilderTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentBuilderTestCase.java
new file mode 100644
index 0000000000..86e77920dc
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentBuilderTestCase.java
@@ -0,0 +1,23 @@
+package org.apache.tuscany.container.python;
+
+import junit.framework.TestCase;
+
+public class PythonComponentBuilderTestCase extends TestCase {
+
+ public void testGetImplementationType() {
+ PythonComponentBuilder builder = new PythonComponentBuilder();
+ assertEquals(PythonImplementation.class, builder.getImplementationType());
+ }
+
+ public void testBuild() {
+// PythonComponentBuilder builder = new PythonComponentBuilder();
+// CompositeComponent parent = createMock(CompositeComponent.class);
+// Component component = builder.build(parent, componentDefinition, deploymentContext);
+// assertNotNull(component);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTestCase.java
new file mode 100644
index 0000000000..3a1f6081ba
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTestCase.java
@@ -0,0 +1,94 @@
+package org.apache.tuscany.container.python;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.TargetException;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.easymock.IAnswer;
+
+public class PythonComponentTestCase extends TestCase {
+
+ private ScopeContainer scopeContainer;
+
+ @SuppressWarnings("unchecked")
+ public void testCreateTargetInvoker() {
+ PythonComponent pc = new PythonComponent(null,null,null, null, scopeContainer, null, null);
+
+ Operation operation = new Operation("hashCode", null,null,null,false,null);
+ ServiceContract contract = new ServiceContract(List.class){};
+ operation.setServiceContract(contract);
+ TargetInvoker invoker = pc.createTargetInvoker("hashCode", operation);
+
+ assertNotNull(invoker);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testCreateInstance() throws IOException {
+ PythonComponent pc = new PythonComponent(null,createPythonScript(),null, null, scopeContainer, null, null);
+ Object o = pc.createInstance();
+ assertNotNull(o);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testGetServiceInstance() {
+ PythonComponent pc = new PythonComponent(null,null,null, null, scopeContainer, null, null);
+ try {
+ pc.getServiceInstance();
+ fail();
+ } catch (TargetException e) {
+ // expected
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testGetproperties() {
+ PythonComponent pc = new PythonComponent(null,null,null, null, scopeContainer, null, null);
+ assertNotNull(pc.getProperties());
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testGetServiceInterfaces() {
+ List services = new ArrayList();
+ PythonComponent pc = new PythonComponent(null,null,services, null, scopeContainer, null,null);
+ assertEquals(services, pc.getServiceInterfaces());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void setUp() {
+ this.scopeContainer = createMock(ScopeContainer.class);
+ expect(scopeContainer.getScope()).andStubAnswer(new IAnswer() {
+ public Object answer() throws Throwable {
+ return Scope.MODULE;
+ }
+ });
+ }
+
+ public PythonScript createPythonScript() throws IOException {
+ URL scriptURL = getClass().getResource("PythonScriptTestCase.py");
+ InputStream is = scriptURL.openStream();
+ StringBuilder sb = new StringBuilder();
+ int i = 0;
+ while ((i = is.read()) != -1) {
+ sb.append((char) i);
+ }
+ is.close();
+ String script = sb.toString();
+ PythonScript pythonScript = new PythonScript("PythonScriptTestCase", "hello", script, null);
+ pythonScript.setServiceInterface(HelloWorldService.class);
+ return pythonScript;
+ }
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTypeLoaderTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTypeLoaderTestCase.java
new file mode 100644
index 0000000000..73a6e9b849
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTypeLoaderTestCase.java
@@ -0,0 +1,87 @@
+/*
+ * 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.container.python;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.xml.stream.XMLStreamException;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.spi.loader.LoaderException;
+
+/**
+ *
+ */
+public class PythonComponentTypeLoaderTestCase extends TestCase {
+
+ private String script;
+
+ public void testGetSideFileName() {
+ PythonScript pythonScript = new PythonScript("PythonScriptTestCase", "hello", script, null);
+ PythonComponentTypeLoader loader = new PythonComponentTypeLoader();
+ PythonImplementation implementation = new PythonImplementation();
+ implementation.setPythonScript(pythonScript);
+ assertEquals("PythonScriptTestCase.componentType", loader.getSideFileName(implementation));
+ }
+
+ public void testLoadFromSideFile() throws MalformedURLException, LoaderException, XMLStreamException {
+// PythonComponentTypeLoader loader = new PythonComponentTypeLoader();
+// LoaderRegistry loaderRegistry = createMock(LoaderRegistry.class);
+// expect(loaderRegistry.load(isA(CompositeComponent.class),isA(URL.class),isA(Class.class),isA(DeploymentContext.class))).andStubAnswer(new IAnswer() {
+// public Object answer() throws Throwable {
+// return new ComponentType();
+// }
+// });
+// loader.setLoaderRegistry(loaderRegistry);
+//
+// URL url = new URL("http://foo");
+// DeploymentContext deploymentContext = createMock(DeploymentContext.class);
+// loader.loadFromSidefile(url, deploymentContext);
+ }
+
+ public void testGetImplementationClass() {
+ PythonComponentTypeLoader loader = new PythonComponentTypeLoader();
+ assertEquals(PythonImplementation.class, loader.getImplementationClass());
+ }
+
+ public void testGetResourceName() {
+ PythonComponentTypeLoader loader = new PythonComponentTypeLoader();
+ PythonImplementation implementation = new PythonImplementation();
+ PythonScript pythonScript = new PythonScript("PythonScriptTestCase", "hello", script, null);
+ implementation.setPythonScript(pythonScript);
+ assertEquals("PythonScriptTestCase", loader.getResourceName(implementation));
+ }
+
+ @Override
+ public void setUp() throws IOException {
+ URL scriptURL = getClass().getResource("PythonScriptTestCase.py");
+ InputStream is = scriptURL.openStream();
+ StringBuilder sb = new StringBuilder();
+ int i = 0;
+ while ((i = is.read()) != -1) {
+ sb.append((char) i);
+ }
+ is.close();
+ script = sb.toString();
+ }
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTypeTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTypeTestCase.java
new file mode 100644
index 0000000000..3ae4b73e60
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonComponentTypeTestCase.java
@@ -0,0 +1,36 @@
+package org.apache.tuscany.container.python;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+public class PythonComponentTypeTestCase extends TestCase {
+
+ public void testLifecycleScope() {
+ PythonComponentType ct = new PythonComponentType();
+ assertEquals(Scope.MODULE, ct.getLifecycleScope());
+ ct.setLifecycleScope(Scope.COMPOSITE);
+ assertEquals(Scope.COMPOSITE, ct.getLifecycleScope());
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testComponentTypeConstructor() {
+ ComponentType ct = new ComponentType();
+ Property property = new Property();
+ ct.add(property);
+ ReferenceDefinition reference = new ReferenceDefinition();
+ ct.add(reference);
+ ServiceDefinition service = new ServiceDefinition();
+ ct.add(service);
+
+ PythonComponentType pct = new PythonComponentType(ct);
+
+ assertEquals(property, pct.getProperties().values().iterator().next());
+ assertEquals(reference, pct.getReferences().values().iterator().next());
+ assertEquals(service, pct.getServices().values().iterator().next());
+ }
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonImplementationLoaderTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonImplementationLoaderTestCase.java
new file mode 100644
index 0000000000..f84d217334
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonImplementationLoaderTestCase.java
@@ -0,0 +1,110 @@
+/*
+ * 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.container.python;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.createMock;
+import static org.easymock.classextension.EasyMock.replay;
+import static org.easymock.classextension.EasyMock.verify;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.MissingResourceException;
+
+/**
+ *
+ */
+public class PythonImplementationLoaderTestCase extends TestCase {
+ private CompositeComponent parent;
+
+ private XMLStreamReader reader;
+
+ private DeploymentContext deploymentContext;
+
+ private ClassLoader classLoader;
+
+ private LoaderRegistry registry;
+
+ private PythonImplementationLoader loader;
+
+ public void testNoModuleAttribute() throws LoaderException, XMLStreamException {
+ expect(reader.getAttributeValue(null, "module")).andReturn(null);
+ replay(reader);
+ replay(deploymentContext);
+
+ try {
+ loader.load(parent, reader, deploymentContext);
+ fail();
+ } catch (MissingResourceException e) {
+ // ok
+ }
+ verify(reader);
+ verify(deploymentContext);
+ }
+
+ public void testNoScriptPresent() throws LoaderException, XMLStreamException {
+ expect(reader.getAttributeValue(null, "module")).andReturn("foo.py");
+ expect(reader.getAttributeValue(null, "class")).andReturn(null);
+ expect(reader.next()).andReturn(XMLStreamConstants.END_ELEMENT);
+ expect(deploymentContext.getClassLoader()).andReturn(classLoader);
+
+ replay(reader);
+ replay(deploymentContext);
+
+ PythonImplementationLoader mockLoader = new PythonImplementationLoader(registry) {
+ protected String loadSource(ClassLoader cl, String resource) throws LoaderException {
+ assertSame(classLoader, cl);
+ assertEquals("foo.py", resource);
+ throw new MissingResourceException(resource);
+ }
+ };
+ try {
+ mockLoader.load(parent, reader, deploymentContext);
+ fail();
+ } catch (MissingResourceException e) {
+ assertEquals("foo.py", e.getMessage());
+ }
+ verify(reader);
+ verify(deploymentContext);
+ }
+
+ public void testLoadScript() throws LoaderException {
+ String script = loader.loadSource(getClass().getClassLoader(), "org/apache/tuscany/container/python/PythonScriptTestCase.py");
+ assertTrue(script.startsWith("from org.apache.tuscany.container.python"));
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ registry = createMock(LoaderRegistry.class);
+ loader = new PythonImplementationLoader(registry);
+
+ parent = createMock(CompositeComponent.class);
+ reader = createMock(XMLStreamReader.class);
+ deploymentContext = createMock(DeploymentContext.class);
+ classLoader = createMock(ClassLoader.class);
+ }
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonImplementationTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonImplementationTestCase.java
new file mode 100644
index 0000000000..a2af619795
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonImplementationTestCase.java
@@ -0,0 +1,33 @@
+package org.apache.tuscany.container.python;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+public class PythonImplementationTestCase extends TestCase {
+
+ private PythonScript pythonScript;
+
+ public void testGetPythonScript() {
+ PythonImplementation impl = new PythonImplementation();
+ impl.setPythonScript(pythonScript);
+ assertEquals(pythonScript, impl.getJythonScript());
+ }
+
+ public void setUp() throws IOException {
+ URL scriptURL = getClass().getResource("PythonScriptTestCase.py");
+ assert scriptURL != null;
+ InputStream is = scriptURL.openStream();
+ StringBuilder sb = new StringBuilder();
+ int i = 0;
+ while ((i = is.read()) != -1) {
+ sb.append((char) i);
+ }
+ is.close();
+ String script = sb.toString();
+ pythonScript = new PythonScript("PythonScriptTestCase", "hello", script, null);
+ }
+
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonInvokerTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonInvokerTestCase.java
new file mode 100644
index 0000000000..03a9151a47
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonInvokerTestCase.java
@@ -0,0 +1,62 @@
+package org.apache.tuscany.container.python;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.model.Scope;
+import org.easymock.IAnswer;
+
+public class PythonInvokerTestCase extends TestCase {
+
+ private PythonComponent context;
+
+ private Method method;
+
+ private ScopeContainer scopeContainer;
+
+ public void testInvokeTarget() throws InvocationTargetException {
+ PythonInvoker invoker = new PythonInvoker(method, context);
+ Object o = invoker.invokeTarget(new Object[] { "petra" });
+ assertEquals("hello petra", o);
+ }
+
+ public void testInvokeTargetException() throws InvocationTargetException, SecurityException, NoSuchMethodException {
+ PythonInvoker invoker = new PythonInvoker(method, context);
+ try {
+ invoker.invokeTarget(null);
+ fail();
+ } catch (InvocationTargetException e) {
+ // expected
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ scopeContainer = createMock(ScopeContainer.class);
+ expect(scopeContainer.getInstance(isA(AtomicComponent.class))).andStubAnswer(new IAnswer() {
+ public Object answer() throws Throwable {
+ return "hello ";
+ }
+ });
+ expect(scopeContainer.getScope()).andStubAnswer(new IAnswer() {
+ public Object answer() throws Throwable {
+ return Scope.MODULE;
+ }
+ });
+ replay(scopeContainer);
+
+ context = new PythonComponent(null, null, null, null, scopeContainer, null, null);
+ method = String.class.getDeclaredMethod("concat", new Class[] { String.class });
+ }
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonScriptTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonScriptTestCase.java
new file mode 100644
index 0000000000..560b623e9a
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/PythonScriptTestCase.java
@@ -0,0 +1,82 @@
+/*
+ * 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.container.python;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+public class PythonScriptTestCase extends TestCase {
+
+ protected String script;
+
+ public void testCreateInstance() {
+ PythonScript pythonScript = new PythonScript("PythonScriptTestCase", "hello", script, null);
+ pythonScript.setServiceInterface(HelloWorldService.class);
+ HelloWorldService helloworld = (HelloWorldService) pythonScript.createInstance(null);
+
+ assertEquals("Hello petra", helloworld.sayHello("petra"));
+ }
+
+ public void testCreateInstanceBadIface() {
+ PythonScript pythonScript = new PythonScript("PythonScriptTestCase", "hello", script, null);
+ pythonScript.setServiceInterface(String.class);
+ try {
+ pythonScript.createInstance(null);
+ fail();
+ } catch (RuntimeException e) {
+ // expected
+ }
+ }
+
+ public void testCreateInstanceBadClassName() {
+ PythonScript pythonScript = new PythonScript("PythonScriptTestCase", "badClass", script, null);
+ pythonScript.setServiceInterface(String.class);
+ try {
+ pythonScript.createInstance(null);
+ assertTrue("expecting bad class exception", false);
+ } catch (RuntimeException e) {
+ // expected
+ }
+ }
+
+ public void testGetters() {
+ PythonScript pythonScript = new PythonScript("PythonScriptTestCase", "hello", script, null);
+ assertEquals(null, pythonScript.getClassLoader());
+ assertEquals("hello", pythonScript.getClassName());
+ assertEquals(script, pythonScript.getScript());
+ }
+
+ @Override
+ public void setUp() throws IOException {
+ URL scriptURL = getClass().getResource("PythonScriptTestCase.py");
+ InputStream is = scriptURL.openStream();
+ StringBuilder sb = new StringBuilder();
+ int i = 0;
+ while ((i = is.read()) != -1) {
+ sb.append((char) i);
+ }
+ is.close();
+ script = sb.toString();
+
+ }
+
+}
diff --git a/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/function/HelloWorldTestCase.java b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/function/HelloWorldTestCase.java
new file mode 100644
index 0000000000..38f15adafd
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/java/org/apache/tuscany/container/python/function/HelloWorldTestCase.java
@@ -0,0 +1,46 @@
+/*
+ * 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.container.python.function;
+
+
+import org.apache.tuscany.container.python.HelloWorldService;
+import org.apache.tuscany.test.SCATestCase;
+import org.osoa.sca.CompositeContext;
+import org.osoa.sca.CurrentCompositeContext;
+
+/**
+ * This shows how to test the HelloWorld service component.
+ */
+public class HelloWorldTestCase extends SCATestCase {
+
+ private HelloWorldService helloWorldService;
+
+ protected void setUp() throws Exception {
+ addExtension("PythonContainer", getClass().getClassLoader().getResource("META-INF/sca/py.system.scdl"));
+ setApplicationSCDL("org/apache/tuscany/container/python/function/helloworld.scdl");
+ super.setUp();
+
+ CompositeContext context = CurrentCompositeContext.getContext();
+ helloWorldService = context.locateService(HelloWorldService.class, "HelloWorldComponent");
+ }
+
+ public void testHelloWorld() throws Exception {
+ assertEquals(helloWorldService.sayHello("petra"), "Hello petra");
+ }
+}
diff --git a/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/PythonScriptTestCase.py b/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/PythonScriptTestCase.py
new file mode 100644
index 0000000000..5ce69aca61
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/PythonScriptTestCase.py
@@ -0,0 +1,6 @@
+from org.apache.tuscany.container.python import HelloWorldService
+
+class hello(HelloWorldService):
+
+ def sayHello(self, val1):
+ return "Hello " + val1
diff --git a/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/HelloWorld.componentType b/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/HelloWorld.componentType
new file mode 100644
index 0000000000..432c9badc0
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/HelloWorld.componentType
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="ASCII"?>
+
+<componentType xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <service name="HelloWorldService">
+ <interface.java interface="org.apache.tuscany.container.python.HelloWorldService"/>
+ </service>
+
+</componentType>
diff --git a/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/helloworld.py b/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/helloworld.py
new file mode 100644
index 0000000000..5ce69aca61
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/helloworld.py
@@ -0,0 +1,6 @@
+from org.apache.tuscany.container.python import HelloWorldService
+
+class hello(HelloWorldService):
+
+ def sayHello(self, val1):
+ return "Hello " + val1
diff --git a/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/helloworld.scdl b/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/helloworld.scdl
new file mode 100644
index 0000000000..97461b3ae3
--- /dev/null
+++ b/sandbox/ant/container.python/src/test/resources/org/apache/tuscany/container/python/function/helloworld.scdl
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ xmlns:py="http://tuscany.apache.org/xmlns/python/1.0"
+
+ name="HelloWorldComposite">
+
+ <component name="HelloWorldComponent">
+ <py:implementation.python module="org/apache/tuscany/container/python/function/HelloWorld.py" class="hello" />
+ </component>
+
+</composite>