summaryrefslogtreecommitdiffstats
path: root/sandbox/ant/container.python/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/ant/container.python/src/main')
-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
9 files changed, 694 insertions, 0 deletions
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>