From 6d0e93c68d3aeaeb4bb6d96ac0460eec40ef786e Mon Sep 17 00:00:00 2001 From: lresende Date: Wed, 11 Nov 2009 23:13:23 +0000 Subject: Moving 1.x branches git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835143 13f79535-47bb-0310-9956-ffa450edef68 --- .../tuscany/container/ruby/RubyComponent.java | 134 +++++++++++++++ .../container/ruby/RubyComponentBuilder.java | 94 +++++++++++ .../tuscany/container/ruby/RubyComponentType.java | 58 +++++++ .../container/ruby/RubyComponentTypeLoader.java | 118 +++++++++++++ .../tuscany/container/ruby/RubyImplementation.java | 48 ++++++ .../container/ruby/RubyImplementationLoader.java | 123 ++++++++++++++ .../tuscany/container/ruby/RubyIntrospector.java | 173 +++++++++++++++++++ .../apache/tuscany/container/ruby/RubyInvoker.java | 55 ++++++ .../container/ruby/RubyRefInvocInterceptor.java | 92 ++++++++++ .../tuscany/container/ruby/RubyReferenceProxy.java | 127 ++++++++++++++ .../container/ruby/rubyscript/RubySCAConfig.java | 159 ++++++++++++++++++ .../container/ruby/rubyscript/RubyScript.java | 160 ++++++++++++++++++ .../ruby/rubyscript/RubyScriptInstance.java | 61 +++++++ .../container/ruby/rubyscript/RubyUtils.java | 71 ++++++++ .../src/main/resources/META-INF/sca/default.scdl | 46 +++++ .../main/resources/META-INF/sca/ruby.system.scdl | 40 +++++ .../test/java/helloworld/HelloWorldService.java | 24 +++ .../java/helloworld/HelloWorldServiceImpl.java | 42 +++++ .../ruby/RubyImplementationLoaderTestCase.java | 109 ++++++++++++ .../ruby/RubyScriptIntrospectorTestCase.java | 130 ++++++++++++++ .../container/ruby/ScriptInvokeTestCase.java | 54 ++++++ .../tuscany/container/ruby/WireTestCase.java | 186 +++++++++++++++++++++ .../ruby/function/HelloWorldTestCase.java | 75 +++++++++ .../tuscany/container/ruby/mock/Greeting.java | 26 +++ .../ruby/function/HelloWorld.componentType | 28 ++++ .../tuscany/container/ruby/function/HelloWorld.rb | 33 ++++ .../ruby/function/IntrospectableHelloWorld.rb | 30 ++++ .../container/ruby/function/helloworld.scdl | 44 +++++ .../ruby/function/propertyTest.componentType | 26 +++ .../container/ruby/function/propertyTest.rb | 24 +++ .../tuscany/container/ruby/jruby/helloworld.wsdl | 78 +++++++++ .../org/apache/tuscany/container/ruby/mock/test.rb | 1 + 32 files changed, 2469 insertions(+) create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponent.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentBuilder.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentType.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentTypeLoader.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyImplementation.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyImplementationLoader.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyIntrospector.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyInvoker.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyRefInvocInterceptor.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyReferenceProxy.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubySCAConfig.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyScript.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyScriptInstance.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyUtils.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/resources/META-INF/sca/default.scdl create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/resources/META-INF/sca/ruby.system.scdl create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/helloworld/HelloWorldService.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/helloworld/HelloWorldServiceImpl.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/RubyImplementationLoaderTestCase.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/RubyScriptIntrospectorTestCase.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/ScriptInvokeTestCase.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/WireTestCase.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/function/HelloWorldTestCase.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/mock/Greeting.java create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/HelloWorld.componentType create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/HelloWorld.rb create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/IntrospectableHelloWorld.rb create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/helloworld.scdl create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/propertyTest.componentType create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/propertyTest.rb create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/jruby/helloworld.wsdl create mode 100644 sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/mock/test.rb (limited to 'sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src') diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponent.java new file mode 100644 index 0000000000..7a244b828c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponent.java @@ -0,0 +1,134 @@ +/* + * 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.ruby; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.container.ruby.rubyscript.RubyScript; +import org.apache.tuscany.container.ruby.rubyscript.RubyScriptInstance; +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; + +/** + * The Ruby component implementation. + */ +public class RubyComponent extends AtomicComponentExtension { + + private final List> services; + + private final Map properties; + + private RubyScript rubyScript; + + private String rubyClassName; + + public RubyComponent(String name, + RubyScript rubyScript, + String rubyClassName, + List> services, + Map propValues, + CompositeComponent parent, + ScopeContainer scopeContainer, + WireService wireService, + WorkContext workContext) { + super(name, parent, scopeContainer, wireService, workContext, null, 0); + + this.rubyScript = rubyScript; + this.rubyClassName = rubyClassName; + this.services = services; + this.scope = scopeContainer.getScope(); + //this.properties = new HashMap(); + this.properties = propValues; + } + + public Object createInstance() throws ObjectCreationException { + + Map context = new HashMap(getProperties()); + + for (List referenceWires : getOutboundWires().values()) { + for (OutboundWire wire : referenceWires) { + Object wireProxy = wireService.createProxy(wire); + //since all types that may be used in the reference interface may not be known to Rhino + //using the wireProxy as is will fail result in type conversion exceptions in cases where + //Rhino does not know enough of the tpypes used. Hence introduce a interceptor proxy, + //with weak typing (java.lang.Object) so that Rhino's call to the proxy succeeds. Then + //within this interceptor proxy perform data mediations required to correctly call the + //referenced service. + Class businessInterface = wire.getServiceContract().getInterfaceClass(); + RubyReferenceProxy interceptingProxy = new RubyReferenceProxy(businessInterface, + wireProxy, + rubyScript.getRubyEngine()); + context.put(wire.getReferenceName(), interceptingProxy.createProxy()); + } + } + + Object instance = rubyScript.createScriptInstance(context, rubyClassName); + + return instance; + } + + public TargetInvoker createTargetInvoker(String targetName, Operation operation) { + /*Method[] methods = operation.getServiceContract().getInterfaceClass().getMethods(); + Method method = findMethod(operation, + methods);*/ + return new RubyInvoker(operation.getName(), this, operation.getOutputType().getPhysical().getClass()); + } + + // TODO: move all the following up to AtomicComponentExtension? + + public List> getServiceInterfaces() { + return services; + } + + public Map getProperties() { + return properties; + } + + public RubyScriptInstance getTargetInstance() throws TargetException { + return (RubyScriptInstance) 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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentBuilder.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentBuilder.java new file mode 100644 index 0000000000..bdbbd1871c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentBuilder.java @@ -0,0 +1,94 @@ +/* + * 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.ruby; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.container.ruby.rubyscript.RubyScript; +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.Property; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceDefinition; + +/** + * Extension point for creating {@link RubyComponent}s from an assembly configuration + */ +public class RubyComponentBuilder extends ComponentBuilderExtension { + + protected Class getImplementationType() { + return RubyImplementation.class; + } + + @SuppressWarnings("unchecked") + public Component build(CompositeComponent parent, + ComponentDefinition componentDefinition, + DeploymentContext deploymentContext) throws BuilderConfigException { + + String name = componentDefinition.getName(); + RubyImplementation implementation = componentDefinition.getImplementation(); + RubyComponentType componentType = implementation.getComponentType(); + + // get list of services provided by this component + Collection collection = componentType.getServices().values(); + List> services = new ArrayList>(collection.size()); + for (ServiceDefinition serviceDefinition : collection) { + services.add(serviceDefinition.getServiceContract().getInterfaceClass()); + } + + Map propertyValues = new Hashtable(); + Collection> propValueSettings = componentDefinition.getPropertyValues().values(); + for (PropertyValue propertyValue : propValueSettings) { + propertyValues.put(propertyValue.getName(), + propertyValue.getValueFactory().getInstance()); + } + + RubyScript rubyScript = implementation.getRubyScript(); + + // 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 RubyComponent(name, + rubyScript, + implementation.getRubyClassName(), + services, + propertyValues, + parent, + scopeContainer, + wireService, + workContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentType.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentType.java new file mode 100644 index 0000000000..1b98cf86d6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentType.java @@ -0,0 +1,58 @@ +/* + * 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.ruby; + +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 RubyComponentType extends + ComponentType> { + + private Scope lifecycleScope = Scope.MODULE; + + public RubyComponentType() { + } + + @SuppressWarnings("unchecked") + public RubyComponentType(ComponentType ct) { + // TODO: A bit hacky but this is so the non-Ruby .componentType 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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentTypeLoader.java new file mode 100644 index 0000000000..6fc5f87c68 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyComponentTypeLoader.java @@ -0,0 +1,118 @@ +/* + * 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.ruby; + +import java.net.URL; + +import org.apache.tuscany.container.ruby.rubyscript.RubySCAConfig; +import org.apache.tuscany.container.ruby.rubyscript.RubyScript; +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.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.model.ComponentType; + +/** + * @version $Rev$ $Date$ + */ +public class RubyComponentTypeLoader extends ComponentTypeLoaderExtension { + + private JavaInterfaceProcessorRegistry processorRegistry; + + public RubyComponentTypeLoader(@Autowire + JavaInterfaceProcessorRegistry processorRegistry) { + this.processorRegistry = processorRegistry; + } + + @Override + protected Class getImplementationClass() { + return RubyImplementation.class; + } + + protected RubyComponentType loadByIntrospection(CompositeComponent parent, + RubyImplementation implementation, + DeploymentContext deploymentContext) throws + MissingResourceException, + InvalidServiceContractException { + + RubyScript rubyScript = implementation.getRubyScript(); + RubySCAConfig scaConfig = rubyScript.getSCAConfig(); + if (!scaConfig.hasSCAConfig()) { + throw new IllegalArgumentException( + "must use either .componentType side file or Ruby Global variable $SCA definition"); + } + + // FIXME this should be a system service, not instantiated here + RubyComponentType componentType = new RubyIntrospector(null, processorRegistry) + .introspectScript(scaConfig, rubyScript.getClassLoader()); + + return componentType; + } + + protected String getResourceName(RubyImplementation implementation) { + return implementation.getRubyScript().getScriptName(); + } + + // TODO: must be possible to move all the following up in to ComponentTypeLoaderExtension + + public void load(CompositeComponent parent, + RubyImplementation implementation, + DeploymentContext deploymentContext) throws LoaderException { + + URL resource = implementation.getRubyScript().getClassLoader().getResource(getSideFileName(implementation)); + RubyComponentType componentType; + if (resource == null) { + try { + componentType = loadByIntrospection(parent, implementation, deploymentContext); + } catch (InvalidServiceContractException e) { + throw new LoaderException("Invalid service contract", e); + } + } else { + componentType = loadFromSidefile(resource, deploymentContext); + } + + implementation.setComponentType(componentType); + + + } + + protected RubyComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext) throws LoaderException { + ComponentType ct = loaderRegistry.load(null, + url, + ComponentType.class, + deploymentContext); + RubyComponentType jsct = new RubyComponentType(ct); + return jsct; + } + + private String getSideFileName(RubyImplementation implementation) { + String baseName = getResourceName(implementation); + int lastDot = baseName.lastIndexOf('.'); + if (lastDot != -1) { + baseName = baseName.substring(0, + lastDot); + } + return baseName + ".componentType"; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyImplementation.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyImplementation.java new file mode 100644 index 0000000000..6f07399d0a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyImplementation.java @@ -0,0 +1,48 @@ +/* + * 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.ruby; + +import org.apache.tuscany.container.ruby.rubyscript.RubyScript; +import org.apache.tuscany.spi.model.AtomicImplementation; + +/** + * Model object for a JavaScript implementation. + */ +public class RubyImplementation extends AtomicImplementation { + + private RubyScript rubyScript; + + private String rubyClassName; + + public String getRubyClassName() { + return rubyClassName; + } + + public void setRubyClassName(String rubyClassName) { + this.rubyClassName = rubyClassName; + } + + public RubyScript getRubyScript() { + return rubyScript; + } + + public void setRubyScript(RubyScript rubyScript) { + this.rubyScript = rubyScript; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyImplementationLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyImplementationLoader.java new file mode 100644 index 0000000000..322e3d84e8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyImplementationLoader.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.ruby; + +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.container.ruby.rubyscript.RubyScript; +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 JavaScript elements. + */ +public class RubyImplementationLoader extends LoaderExtension { + private static final QName IMPLEMENTATION_RUBY = new QName( + "http://incubator.apache.org/tuscany/xmlns/container/rb/1.0-incubator-M2", "implementation.rb"); + + @Constructor({"registry"}) + public RubyImplementationLoader(@Autowire + LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return IMPLEMENTATION_RUBY; + } + + public RubyImplementation load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, + LoaderException { + + String script = reader.getAttributeValue(null, + "script"); + String rubyClassName = reader.getAttributeValue(null,"class"); + + if ( script == null ) { + throw new MissingResourceException("No script supplied"); + } + + ClassLoader cl = deploymentContext.getClassLoader(); + String source = loadSource(cl, + script); + + LoaderUtil.skipToEndElement(reader); + + RubyImplementation implementation = new RubyImplementation(); + RubyScript rubyScript = new RubyScript(script, source, null, cl); + implementation.setRubyScript(rubyScript); + implementation.setRubyClassName(rubyClassName); + registry.loadComponentType(parent, + implementation, + deploymentContext); + 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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyIntrospector.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyIntrospector.java new file mode 100644 index 0000000000..d5ef41d835 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyIntrospector.java @@ -0,0 +1,173 @@ +/* + * 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.ruby; + +import java.util.Iterator; +import java.util.Map; + +import javax.wsdl.Definition; +import javax.wsdl.PortType; +import javax.wsdl.WSDLException; +import javax.wsdl.factory.WSDLFactory; +import javax.wsdl.xml.WSDLReader; +import javax.xml.namespace.QName; + +import org.apache.tuscany.container.ruby.rubyscript.RubySCAConfig; +import org.apache.tuscany.idl.wsdl.WSDLDefinitionRegistry; +import org.apache.tuscany.idl.wsdl.WSDLServiceContract; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; + +/** + * Introspects JavaScript files for SCA configuration + */ +public class RubyIntrospector { + + private WSDLDefinitionRegistry wsdlRegistry; + private JavaInterfaceProcessorRegistry processorRegistry; + + public RubyIntrospector(@Autowire WSDLDefinitionRegistry wsdlRegistry, + @Autowire JavaInterfaceProcessorRegistry processorRegistry) { + this.wsdlRegistry = wsdlRegistry; + this.processorRegistry = processorRegistry; + } + + public RubyComponentType introspectScript(RubySCAConfig scaConfig, ClassLoader cl) + throws MissingResourceException, InvalidServiceContractException { + RubyComponentType componentType = new RubyComponentType(); + introspectJavaInterface(componentType, cl, scaConfig.getJavaInterface()); + introspectWSDLInterface(componentType, cl, scaConfig.getWSDLNamespace(), scaConfig.getWSDLPortType(), + scaConfig.getWSDLLocation()); + introspectReferences(componentType, cl, scaConfig.getReferences()); + introspectProperties(componentType, cl, scaConfig.getProperties()); + introspectScope(componentType, scaConfig.getScope()); + return componentType; + } + + private void introspectScope(RubyComponentType componentType, Scope scope) { + if (scope != null) { + componentType.setLifecycleScope(scope); + } + } + + @SuppressWarnings("unchecked") + private void introspectJavaInterface(ComponentType componentType, ClassLoader cl, String serviceClass) + throws MissingResourceException, InvalidServiceContractException { + if (serviceClass != null) { + ServiceDefinition service = new ServiceDefinition(); + try { + ServiceContract sc = processorRegistry.introspect(Class.forName(serviceClass)); + service.setServiceContract(sc); + componentType.add(service); + } catch (ClassNotFoundException e) { + throw new MissingResourceException("Interface not found", e); + } + } + } + + @SuppressWarnings("unchecked") + private void introspectWSDLInterface(ComponentType componentType, ClassLoader cl, String wsdlNamespace, + String wsdlPortType, String wsdlLocation) { + if (wsdlNamespace == null && wsdlPortType == null && wsdlLocation == null) { + return; + } + + PortType portType = null; + if (wsdlLocation != null) { + portType = readWSDLPortType(wsdlNamespace, wsdlPortType, wsdlLocation, portType); + } else { + portType = getPortType(wsdlNamespace, wsdlPortType); + } + + ServiceDefinition service = new ServiceDefinition(); + WSDLServiceContract wsdlSC = new WSDLServiceContract(); + wsdlSC.setPortType(portType); + service.setServiceContract(wsdlSC); + componentType.add(service); + } + + private PortType readWSDLPortType(String wsdlNamespace, String wsdlPortType, String wsdlLocation, + PortType portType) { + Definition wsdlDefinition; + try { + WSDLReader reader = WSDLFactory.newInstance().newWSDLReader(); + reader.setFeature("javax.wsdl.verbose", false); + wsdlDefinition = reader.readWSDL(wsdlLocation.toString()); + } catch (WSDLException e) { + throw new RuntimeException(e); + + } + Map portTypes = wsdlDefinition.getPortTypes(); + for (Iterator i = portTypes.keySet().iterator(); i.hasNext();) { + QName portTypeQN = (QName) i.next(); + if (wsdlNamespace != null) { + if (!portTypeQN.getNamespaceURI().equals(wsdlNamespace)) { + continue; + } + } + if (wsdlPortType != null) { + if (!portTypeQN.getLocalPart().equals(wsdlPortType)) { + continue; + } + } + if (portType != null) { + throw new RuntimeException("multiple matching portTypes in wsdl: " + wsdlLocation); + } + portType = (PortType) portTypes.get(portTypeQN); + } + if (portType == null) { + throw new RuntimeException("portType not found in wsdl: " + wsdlLocation); + } + return portType; + } + + private PortType getPortType(String wsdlNamespace, String wsdlPortType) { + if (wsdlPortType == null) { + throw new IllegalArgumentException("must specify the wsdlPortType in script SCA config"); + } + PortType portType = null; + if (wsdlNamespace != null) { + QName portTypeQN = new QName(wsdlNamespace.toString(), wsdlPortType.toString()); + portType = wsdlRegistry.getPortType(portTypeQN); + if (portType == null) { + throw new IllegalArgumentException("no WSDL registered for portType: " + portTypeQN); + } + } else { + // wsdlRegistry.getPortType(wsdlPortType.toString()); + if (portType == null) { + throw new IllegalArgumentException("no WSDL registered for portType:" + wsdlPortType); + } + } + return portType; + } + + + private void introspectProperties(ComponentType componentType, ClassLoader cl, Map properties) { + } + + private void introspectReferences(ComponentType componentType, ClassLoader cl, Map references) { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyInvoker.java new file mode 100644 index 0000000000..a40f04612e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyInvoker.java @@ -0,0 +1,55 @@ +/* + * 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.ruby; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.container.ruby.rubyscript.RubyScriptInstance; +import org.apache.tuscany.spi.extension.TargetInvokerExtension; + +/** + * Dispatches to a JavaScript implementation instance + * + * @version $$Rev$$ $$Date$$ + */ +public class RubyInvoker extends TargetInvokerExtension { + + private RubyComponent context; + + private String functionName; + + private Class returnType; + + public RubyInvoker(String functionName, RubyComponent context, Class returnType) { + this.functionName = functionName; + this.context = context; + this.returnType = returnType; + } + + /** + * Invokes a function on a script instance + */ + public Object invokeTarget(final Object payload) throws InvocationTargetException { + RubyScriptInstance target = context.getTargetInstance(); + return target.invokeFunction(functionName, + (Object[]) payload, + returnType); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyRefInvocInterceptor.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyRefInvocInterceptor.java new file mode 100644 index 0000000000..bf62d1fcab --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyRefInvocInterceptor.java @@ -0,0 +1,92 @@ +/* + * 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.ruby; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +import org.jruby.IRuby; +import org.jruby.RubyObject; +import org.jruby.javasupport.JavaUtil; + +/** + * This Interceptor encasulates the data mediation required by the JavaScriptReferenceProxy. The + * invocation handler of this class traps the javascript reference calls, performs data mediation + * and calls then calls the actual referred service. This classes implementation is subject to + * review and change when the DataMediation infrastructure of Tuscany is ready. + * + */ +public class RubyRefInvocInterceptor implements InvocationHandler { + private Object actualProxy; + + private Class wireInterface; + + private IRuby rubyEngine; + + RubyRefInvocInterceptor(Object wireProxy, Class wireIfc, IRuby rubyEng) { + this.actualProxy = wireProxy; + this.wireInterface = wireIfc; + this.rubyEngine = rubyEng; + } + + public Object invoke(Object arg0, Method method, Object[] args) throws Throwable { + if ( method.getName().equals("hashCode")) + return new Integer(1); + + Method invokedMethod = getInvokedMethod(method.getName()); + Object[] tranformedArgs = new Object[args.length]; + for (int count = 0; count < args.length; ++count) { + tranformedArgs[count] = fromRubyToJava(invokedMethod.getParameterTypes()[count], args[count]); + } + + Object response = invokedMethod.invoke(actualProxy, tranformedArgs); + response = fromJavaToRuby(response); + return response; + } + + private Method getInvokedMethod(String methodName) { + Method[] methods = wireInterface.getMethods(); + + for (int count = 0; count < methods.length; ++count) { + if (methods[count].getName().equals(methodName)) { + return methods[count]; + } + } + throw new RuntimeException("Unable to find invocation method"); + } + + protected Object fromRubyToJava(Class reqArgType, Object rubyArg) throws Exception { + Object javaArg = null; + + //for known cases the JRuby runtime handles the conversion before calling the Java objects + //so nothing to do. When it cannot convert it simply passed the instance of RubyObject + if ( rubyArg instanceof RubyObject ) { + //need to deal with this + } else { + javaArg = rubyArg; + } + + return javaArg; + } + + protected Object fromJavaToRuby(Object retVal) throws RuntimeException { + Object rubyRetVal = JavaUtil.convertJavaToRuby(rubyEngine, retVal, retVal.getClass()); + return rubyRetVal; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyReferenceProxy.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyReferenceProxy.java new file mode 100644 index 0000000000..4d91194484 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/RubyReferenceProxy.java @@ -0,0 +1,127 @@ +/* + * 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.ruby; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.jruby.IRuby; +import org.jruby.RubyException; + +import net.sf.cglib.asm.ClassWriter; +import net.sf.cglib.asm.CodeVisitor; +import net.sf.cglib.asm.Constants; +import net.sf.cglib.asm.Type; + +/** + * This is a proxy that will mediate reference calls from the JavaScript. The mediation code here will be reviewed when the DataMediation + * infrastructure is ready. This proxy assmes that there is no verloading of service methods on the reference interface i.e. there are no two service + * methods that have the same method name or operation name. + */ +public class RubyReferenceProxy { + + private Class interfaze; + + private Object wireProxy; + + private IRuby rubyEngine; + + public RubyReferenceProxy(Class interfaze, Object wireProxy, IRuby rubyEng) { + this.interfaze = interfaze; + this.wireProxy = wireProxy; + this.rubyEngine = rubyEng; + } + + public Object createProxy() { + try { + GenericProxyClassLoader classloader = new GenericProxyClassLoader(); + final byte[] byteCode = generateGenericInterface(interfaze); + + Class genericInterface = classloader.defineClass(byteCode); + InvocationHandler proxyHandler = new RubyRefInvocInterceptor(wireProxy, interfaze, rubyEngine); + // return genericInterface.cast(Proxy.newProxyInstance(classloader, new Class[]{genericInterface}, proxyHandler)); + return Proxy.newProxyInstance(classloader, + new Class[]{genericInterface}, + proxyHandler); + } catch (Exception e) { + return null; + } + } + + private static byte[] generateGenericInterface(Class serviceInterface) { + String interfazeName = serviceInterface.getCanonicalName(); + ClassWriter cw = new ClassWriter(false); + + cw.visit(Constants.V1_5, + Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT + Constants.ACC_INTERFACE, + interfazeName.replace('.', + '/'), + "java/lang/Object", + null, + serviceInterface.getSimpleName() + ".java"); + + StringBuffer argsAndReturn = new StringBuffer("("); + Method[] methods = serviceInterface.getMethods(); + for (int count = 0; count < methods.length; ++count) { + argsAndReturn = new StringBuffer("("); + Class[] paramTypes = methods[count].getParameterTypes(); + Class returnType = methods[count].getReturnType(); + + for (int paramCount = 0; paramCount < paramTypes.length; ++paramCount) { + argsAndReturn.append(Type.getType(Object.class)); + } + argsAndReturn.append(")"); + argsAndReturn.append(Type.getType(Object.class)); + + Class[] exceptionTypes = methods[count].getExceptionTypes(); + String[] exceptions = new String[exceptionTypes.length]; + for (int excCount = 0; excCount < exceptionTypes.length; ++excCount) { + exceptions[excCount] = exceptionTypes[excCount].getName(); + exceptions[excCount] = exceptions[excCount].replace('.', + '/'); + } + + CodeVisitor cv = cw.visitMethod(Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT, + methods[count].getName(), + argsAndReturn.toString(), + exceptions, + null); + cw.visitEnd(); + } + + cw.visitEnd(); + + return cw.toByteArray(); + } + + private class GenericProxyClassLoader extends ClassLoader { + public Class defineClass(byte[] byteArray) { + try { + return defineClass(null, + byteArray, + 0, + byteArray.length); + } catch (Throwable e) { + return null; + } + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubySCAConfig.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubySCAConfig.java new file mode 100644 index 0000000000..4d14d8a56a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubySCAConfig.java @@ -0,0 +1,159 @@ +/* + * 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.ruby.rubyscript; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.model.Scope; +import org.jruby.RubyHash; +import org.jruby.RubyObject; +import org.jruby.internal.runtime.GlobalVariables; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * Represents the variable defining the SCA aspects of the script + * + * SCA = { + * javaInterface : "my.pkg.ClassName", + * wsdlPortType : "wsdlPortTypeName", + * wsdlNameSpace : "http://my.namespace.com", + * wsdlLocation : "\wsdl\mywsdl.txt", + * properties : { "foo" : ["java.lang.String", "defaultValue"],}, + * references : {}, + * scope : 'stateless'|'request'|'conversational'|'composite', + * } + * + * The config must define the service with either javaInterface or wsdl. When + * using wsdl the three parameters are optional. If wsdlLocation is used that is the + * WSDL document used, and the namespace and portType parameters are only required if + * the WSDL definition defines multiple portTypes. + */ +public class RubySCAConfig { + + private boolean hasSCAConfig; + + private String javaInterface; + + private String wsdlLocation; + + private String wsdlNamespace; + + private String wsdlPortType; + + private Map properties; + + private Map references; + + private Scope scope; + + public RubySCAConfig(GlobalVariables globalVariables) { + IRubyObject rubyObject = globalVariables.get("$SCA"); + if (rubyObject != null && !rubyObject.isNil()) { + hasSCAConfig = true; + RubyHash scaVar = (RubyHash) rubyObject; + Object o = scaVar.get("javaInterface"); + if ( o != null ) { + this.javaInterface = o.toString(); + } + o = scaVar.get("wsdlLocation"); + if (o != null ) { + this.wsdlLocation = o.toString(); + } + o = scaVar.get("wsdlPortType"); + if (o != null ) { + this.wsdlPortType = o.toString(); + } + o = scaVar.get("wsdlNamespace"); + if (o != null ) { + this.wsdlNamespace = o.toString(); + } + if (javaInterface != null) { + if (wsdlLocation != null || wsdlPortType != null || wsdlNamespace != null) { + throw new IllegalArgumentException("script SCA config defines both Java and WSDL service interface"); + } + } else { + if (wsdlLocation == null && wsdlPortType == null && wsdlNamespace == null) { + throw new IllegalArgumentException("script SCA config must define either Java or WSDL service interface"); + } + } + + this.properties = new HashMap(); + o = scaVar.get("properties"); + if (o != null ) { + // TODO parse properties + } + + this.references = new HashMap(); + o = scaVar.get("references"); + if (o != null ) { + // TODO parse references + } + + o = scaVar.get("scope"); + if (o != null ) { + if ("stateless".equalsIgnoreCase(String.valueOf(o))) { + this.scope = Scope.STATELESS; + } else if ("request".equalsIgnoreCase(String.valueOf(o))) { + this.scope = Scope.REQUEST; + } else if ("conversational".equalsIgnoreCase(String.valueOf(o))) { + this.scope = Scope.SESSION; // TODO: where's CONVERSATIONAL? + } else if ("composite".equalsIgnoreCase(String.valueOf(o))) { + this.scope = Scope.MODULE; // TODO: composite = MODULE for now? + } else { + throw new IllegalArgumentException("invalid scope value: " + o); + } + } + + } + } + + public boolean hasSCAConfig() { + return hasSCAConfig; + } + + public String getJavaInterface() { + return javaInterface; + } + + public Map getProperties() { + return properties; + } + + public Map getReferences() { + return references; + } + + public String getWSDLLocation() { + return wsdlLocation; + } + + public String getWSDLNamespace() { + return wsdlNamespace; + } + + public String getWSDLPortType() { + return wsdlPortType; + } + + public Scope getScope() { + return scope; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyScript.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyScript.java new file mode 100644 index 0000000000..87d995eabd --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyScript.java @@ -0,0 +1,160 @@ +/* + * 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.ruby.rubyscript; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; + +import org.jruby.IRuby; +import org.jruby.RubyString; +import org.jruby.javasupport.JavaEmbedUtils; +import org.jruby.javasupport.JavaUtil; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * A RhinoScript represents a compiled JavaScript script + */ +public class RubyScript { + protected final String NEW = ".new"; + protected final String EQUAL = "="; + + protected String scriptName; + + protected String script; + + protected Map responseClasses; + + protected ClassLoader classLoader; + + private IRuby rubyEngine = JavaEmbedUtils.initialize(new Vector()); + + /** + * Create a new RubyScript. + * + * @param scriptName + * the name of the script. Can be anything, only used in messages to identify the script + * @param script + * the complete script + */ + public RubyScript(String scriptName, String script) { + this(scriptName, script, (Map) null, null); + } + + /** + * Create a new RubyScript. + * + * @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 to be used to locate any user Java classes used in the script + */ + public RubyScript(String scriptName, String script, Map context, ClassLoader classLoader) { + this.scriptName = scriptName; + this.script = script; + this.responseClasses = new HashMap(); + this.classLoader = classLoader; + rubyEngine.loadScript((RubyString) JavaUtil.convertJavaToRuby(rubyEngine, + "MyScript.rb", + String.class), + (RubyString) JavaUtil.convertJavaToRuby(rubyEngine, + this.script, + String.class), + false); + } + + /** + * Create a new invokeable instance of the script + * + * @return a IRubyObject + */ +public RubyScriptInstance createScriptInstance(Map context, String rubyClassName) { + if ( rubyClassName == null ) { + return new RubyScriptInstance(rubyEngine.evalScript(script), responseClasses); + } + else { + IRubyObject rubyObject = rubyEngine.evalScript(rubyClassName + NEW); + + Iterator keyIterator = context.keySet().iterator(); + String key = null; + Object value = null; + while ( keyIterator.hasNext()) { + key = keyIterator.next(); + value = JavaUtil.convertJavaToRuby(rubyEngine, + context.get(key), + context.get(key).getClass()); + + JavaEmbedUtils.invokeMethod(rubyEngine, + rubyObject, + key + EQUAL, + new Object[]{value}, null); + } + + return new RubyScriptInstance(rubyObject, responseClasses); + } + } + public String getScript() { + return script; + } + + public String getScriptName() { + return scriptName; + } + + public Map getResponseClasses() { + return responseClasses; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + /** + * Set the Java type of a response value. JavaScript is dynamically typed so Rhino cannot always work out what the intended Java type of a + * response should be, for example should the statement "return 42" be a Java int, or Integer or Double etc. When Rhino can't determine the type + * it will default to returning a String, using this method enables overriding the Rhino default to use a specific Java type. + */ + public void setResponseClass(String functionName, Class responseClasses) { + this.responseClasses.put(functionName, + responseClasses); + } + + public RubySCAConfig getSCAConfig() { + return new RubySCAConfig(rubyEngine.getGlobalVariables()); + } + + public void setScript(String script) { + this.script = script; + } + + public IRuby getRubyEngine() { + return rubyEngine; + } + + public void setRubyEngine(IRuby rubyEngine) { + this.rubyEngine = rubyEngine; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyScriptInstance.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyScriptInstance.java new file mode 100644 index 0000000000..2d93c57fc9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyScriptInstance.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.ruby.rubyscript; + +import java.util.HashMap; +import java.util.Map; + +import org.jruby.javasupport.JavaEmbedUtils; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * An invokeable instance of a JavaScript script. + */ +public class RubyScriptInstance { + + private IRubyObject rubyInstance; + + private Map responseClasses; + + public RubyScriptInstance(IRubyObject rubyInstance, Map responseClasses) { + this.rubyInstance = rubyInstance; + this.responseClasses = responseClasses; + if (this.responseClasses == null) { + this.responseClasses = new HashMap(); + } + } + + public Object invokeFunction(String functionName, Object[] args, Class returnType) { + Object[] rubyArgs = RubyUtils.fromJavaToRuby(rubyInstance.getRuntime(), args); + + Object rubyResponse = JavaEmbedUtils.invokeMethod(rubyInstance.getRuntime(), + rubyInstance, + functionName, + rubyArgs, + returnType); + Object response = RubyUtils.fromRubyToJava(rubyInstance.getRuntime(), + returnType, + rubyResponse); + return response; + } + + + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyUtils.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyUtils.java new file mode 100644 index 0000000000..c19f233b94 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/java/org/apache/tuscany/container/ruby/rubyscript/RubyUtils.java @@ -0,0 +1,71 @@ +/* + * 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.ruby.rubyscript; + +import java.io.ByteArrayInputStream; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; +import org.apache.axiom.om.util.StAXUtils; +import org.jruby.IRuby; +import org.jruby.RubyObject; +import org.jruby.javasupport.JavaUtil; + +/** + * @author administrator + * + */ +public class RubyUtils { + public static Object fromRubyToJava(IRuby rubyEngine, Class reqArgType, Object rubyArg) { + Object javaArg = null; + + //for known cases the JRuby runtime handles the conversion before calling the Java objects + //so nothing to do. When it cannot convert it simply passed the instance of RubyObject + if ( rubyArg instanceof RubyObject ) { + //need to deal with this + } else { + javaArg = rubyArg; + } + + return javaArg; + } + + public static Object[] fromJavaToRuby(IRuby rubyEngine, Object[] arg) { + Object[] jsArgs; + if (arg == null) { + jsArgs = new Object[0]; + } else { + jsArgs = new Object[arg.length]; + for (int i = 0; i < jsArgs.length; i++) { + jsArgs[i] = fromJavaToRuby(rubyEngine, arg[i]); + } + } + + return jsArgs; + } + + public static Object fromJavaToRuby(IRuby rubyEngine, Object javaObj) { + Object rubyObj = JavaUtil.convertJavaToRuby(rubyEngine, javaObj, javaObj.getClass()); + return rubyObj; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/resources/META-INF/sca/default.scdl b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/resources/META-INF/sca/default.scdl new file mode 100644 index 0000000000..7a329afb7a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/resources/META-INF/sca/default.scdl @@ -0,0 +1,46 @@ + + + + + + + org.apache.tuscany.sca.services.containers + ruby + 1.0-incubator-M2-SNAPSHOT + + + + + + + + + + + + + + + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/resources/META-INF/sca/ruby.system.scdl b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/resources/META-INF/sca/ruby.system.scdl new file mode 100644 index 0000000000..686e1ea308 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/main/resources/META-INF/sca/ruby.system.scdl @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/helloworld/HelloWorldService.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/helloworld/HelloWorldService.java new file mode 100644 index 0000000000..7e99f6f720 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/helloworld/HelloWorldService.java @@ -0,0 +1,24 @@ +/* + * 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 helloworld; + + +public interface HelloWorldService { + String sayHello(String s); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/helloworld/HelloWorldServiceImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/helloworld/HelloWorldServiceImpl.java new file mode 100644 index 0000000000..be804d3540 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/helloworld/HelloWorldServiceImpl.java @@ -0,0 +1,42 @@ +/* + * 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 helloworld; + +import org.osoa.sca.annotations.Property; + + +public class HelloWorldServiceImpl implements HelloWorldService { + + @Property + public String greeting = "Default hello"; + + public String getGreeting() { + return greeting; + } + + + public void setGreeting(String greeting) { + this.greeting = greeting; + } + + public String sayHello(String s) { + //return greeting + s + " from the JavaWorld!"; + return greeting + " from Java Reference " + s ; //+ " from " + helloSayer.firstName + " " + helloSayer.lastName; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/RubyImplementationLoaderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/RubyImplementationLoaderTestCase.java new file mode 100644 index 0000000000..289a187461 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/RubyImplementationLoaderTestCase.java @@ -0,0 +1,109 @@ +/* + * 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.ruby; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +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; + +import junit.framework.TestCase; +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; + +/** + * Tests for RubyImplementationLoader + */ +public class RubyImplementationLoaderTestCase extends TestCase { + private CompositeComponent parent; + + private XMLStreamReader reader; + + private DeploymentContext deploymentContext; + + private ClassLoader classLoader; + + private LoaderRegistry registry; + + private RubyImplementationLoader loader; + + public void testNoScriptAttribute() throws LoaderException, XMLStreamException { + expect(reader.getAttributeValue(null, "script")).andReturn(null); + expect(reader.getAttributeValue(null, "class")).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, "script")).andReturn("foo.groovy"); + expect(reader.getAttributeValue(null, "class")).andReturn(null); + expect(deploymentContext.getClassLoader()).andReturn(classLoader); + + replay(reader); + replay(deploymentContext); + + RubyImplementationLoader mockLoader = new RubyImplementationLoader(registry) { + protected String loadSource(ClassLoader cl, String resource) throws LoaderException { + assertSame(classLoader, cl); + assertEquals("foo.groovy", resource); + throw new MissingResourceException(resource); + } + }; + try { + mockLoader.load(parent, reader, deploymentContext); + fail(); + } catch (MissingResourceException e) { + assertEquals("foo.groovy", e.getMessage()); + } + verify(reader); + verify(deploymentContext); + } + + public void testLoadScript() throws LoaderException { + String script = + loader.loadSource(getClass().getClassLoader(), "org/apache/tuscany/container/ruby/mock/test.rb"); + assertEquals("//Test Script", script); + } + + protected void setUp() throws Exception { + super.setUp(); + registry = createMock(LoaderRegistry.class); + loader = new RubyImplementationLoader(registry); + + parent = createMock(CompositeComponent.class); + reader = createMock(XMLStreamReader.class); + deploymentContext = createMock(DeploymentContext.class); + classLoader = createMock(ClassLoader.class); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/RubyScriptIntrospectorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/RubyScriptIntrospectorTestCase.java new file mode 100644 index 0000000000..4f4869355d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/RubyScriptIntrospectorTestCase.java @@ -0,0 +1,130 @@ +/* + * 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.ruby; + +import helloworld.HelloWorldService; + +import java.io.IOException; +import java.net.URL; +import java.util.Map; + +import javax.wsdl.WSDLException; +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.container.ruby.rubyscript.RubySCAConfig; +import org.apache.tuscany.container.ruby.rubyscript.RubyScript; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.idl.wsdl.WSDLDefinitionRegistryImpl; +import org.apache.tuscany.idl.wsdl.WSDLServiceContract; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; + +public class RubyScriptIntrospectorTestCase extends TestCase { + + private static final WSDLDefinitionRegistryImpl.Monitor NULL_MONITOR = new WSDLDefinitionRegistryImpl.Monitor() { + public void readingWSDL(String namespace, URL location) { + } + + public void cachingDefinition(String namespace, URL location) { + } + }; + + public void testJavaInterface() throws MissingResourceException, + InvalidServiceContractException { + RubyScript rs = new RubyScript("javaInterfaceTest", + "$SCA = { 'javaInterface' => 'helloworld.HelloWorldService'}", + null, + getClass().getClassLoader()); + RubySCAConfig scaConfig = new RubySCAConfig(rs.getRubyEngine().getGlobalVariables()); + RubyIntrospector introspector = new RubyIntrospector(null, + new JavaInterfaceProcessorRegistryImpl()); + ComponentType comonentType = introspector.introspectScript(scaConfig, + rs.getClassLoader()); + assertNotNull(comonentType); + Map services = comonentType.getServices(); + assertEquals(1, + services.size()); + ServiceDefinition serviceDefinition = (ServiceDefinition) services.values() + .iterator() + .next(); + ServiceContract serviceContract = serviceDefinition.getServiceContract(); + assertTrue(serviceContract instanceof JavaServiceContract); + JavaServiceContract javaServiceContract = (JavaServiceContract) serviceContract; + assertEquals(HelloWorldService.class, + javaServiceContract.getInterfaceClass()); + } + + public void testWSDLLocation() throws WSDLException { + // RhinoScript rs = new RhinoScript("wsdlLocation", + // "SCA = { wsdlLocation : 'src/test/resources/org/apache/tuscany/container/javascript/rhino/helloworld.wsdl',};", null, getClass() + // .getClassLoader()); + // RhinoSCAConfig scaConfig = new RhinoSCAConfig(rs.getScriptScope()); + // JavaScriptIntrospector introspector = new JavaScriptIntrospector(null); + // ComponentType comonentType = introspector.introspectScript(scaConfig, rs.getClassLoader()); + // assertNotNull(comonentType); + // Map services = comonentType.getServices(); + // assertEquals(1, services.size()); + // ServiceDefinition serviceDefinition = (ServiceDefinition) services.values().iterator().next(); + // ServiceContract serviceContract = serviceDefinition.getServiceContract(); + // assertTrue(serviceContract instanceof WSDLServiceContract); + // WSDLServiceContract wsdlServiceContract = (WSDLServiceContract) serviceContract; + // assertEquals(new QName("http://helloworld", "HelloWorld"), wsdlServiceContract.getPortType().getQName()); + } + + public void testWSDLPortType() throws WSDLException, + IOException, + MissingResourceException, + InvalidServiceContractException { + RubyScript rs = new RubyScript("wsdlPortType", + "$SCA = { 'wsdlPortType' => 'HelloWorld', 'wsdlNamespace' => 'http://helloworld'}", + null, + getClass().getClassLoader()); + RubySCAConfig scaConfig = new RubySCAConfig(rs.getRubyEngine().getGlobalVariables()); + + WSDLDefinitionRegistryImpl wsdlReg = new WSDLDefinitionRegistryImpl(); + wsdlReg.setMonitor(NULL_MONITOR); + URL wsdlURL = getClass().getClassLoader() + .getResource("org/apache/tuscany/container/ruby/jruby/helloworld.wsdl"); + wsdlReg.loadDefinition("http://helloworld", + wsdlURL); + + RubyIntrospector introspector = new RubyIntrospector(wsdlReg, + new JavaInterfaceProcessorRegistryImpl()); + ComponentType comonentType = introspector.introspectScript(scaConfig, + rs.getClassLoader()); + assertNotNull(comonentType); + Map services = comonentType.getServices(); + assertEquals(1, + services.size()); + ServiceDefinition serviceDefinition = (ServiceDefinition) services.values() + .iterator() + .next(); + ServiceContract serviceContract = serviceDefinition.getServiceContract(); + assertTrue(serviceContract instanceof WSDLServiceContract); + WSDLServiceContract wsdlServiceContract = (WSDLServiceContract) serviceContract; + assertEquals(new QName("http://helloworld", "HelloWorld"), + wsdlServiceContract.getPortType().getQName()); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/ScriptInvokeTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/ScriptInvokeTestCase.java new file mode 100644 index 0000000000..c83605eecb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/ScriptInvokeTestCase.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.ruby; + +import junit.framework.TestCase; + +import org.apache.tuscany.container.ruby.rubyscript.RubyScript; + +/** + * Tests for invoker JavaScriptComponents + */ +public class ScriptInvokeTestCase extends TestCase { + + private static final String SCRIPT = "def greet(name) \n return name \n end \n"; + + private RubyScript rubyScript; + + /** + * Tests the invocation of a Groovy "script" as opposed to a class + */ + public void testBasicScriptInvocation() throws Exception { +// ModuleScopeContainer scope = new ModuleScopeContainer(null); +// scope.start(); +// List> services = new ArrayList>(); +// services.add(Greeting.class); +// RubyComponent context = new RubyComponent("source", rhinoScript, services, new HashMap(), +// null, scope, ArtifactFactory.createWireService(), null); +// scope.register(context); +// Greeting object = (Greeting) context.getServiceInstance(); +// assertEquals("foo", object.greet("foo")); +// scope.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + rubyScript = new RubyScript("test", SCRIPT); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/WireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/WireTestCase.java new file mode 100644 index 0000000000..3794eb82f7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/WireTestCase.java @@ -0,0 +1,186 @@ +/* + * 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.ruby; + +import static org.easymock.EasyMock.reportMatcher; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.tuscany.container.ruby.mock.Greeting; +import org.apache.tuscany.container.ruby.rubyscript.RubyScript; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.test.ArtifactFactory; +import org.easymock.IArgumentMatcher; + +/** + * Tests for JavaScript component wiring + */ +public class WireTestCase extends TestCase { + + private static final String SCRIPT = " def setWire(ref)\n" + " wire = ref\n" + + "end \n" + " def greet(name)\n" + " return wire.greet(name) \n" + + " end\n"; + + private static final String SCRIPT2 = " def greet(name)\n" + " return name \n" + + "end \n"; + + private RubyScript implClass1; + + private RubyScript implClass2; + + /** + * Tests a basic invocation down a source wire + */ + public void testReferenceWireInvocation() throws Exception { + // ModuleScopeContainer scope = new ModuleScopeContainer(null); + // scope.start(); + // + // List> services = new ArrayList>(); + // services.add(Greeting.class); + // JavaScriptComponent context = new JavaScriptComponent("source", implClass1, services, properties, null, scope, + // ArtifactFactory.createWireService(), null); + // OutboundWire wire = ArtifactFactory.createOutboundWire("wire", Greeting.class); + // ArtifactFactory.terminateWire(wire); + // + // TargetInvoker invoker = createMock(TargetInvoker.class); + // expect(invoker.isCacheable()).andReturn(false); + // Message response = new MessageImpl(); + // response.setBody("foo"); + // expect(invoker.invoke(eqMessage())).andReturn(response); + // replay(invoker); + // + // for (OutboundInvocationChain chain : wire.getInvocationChains().values()) { + // chain.setTargetInvoker(invoker); + // } + // scope.register(context); + // context.addOutboundWire(wire); + // Greeting greeting = context.getServiceInstance(); + // assertEquals("foo", greeting.greet("foo")); + // verify(invoker); + // + // scope.stop(); + } + + // todo this could be generalized and moved to test module + public static Message eqMessage() { + reportMatcher(new IArgumentMatcher() { + public boolean matches(Object object) { + if (!(object instanceof Message)) { + return false; + } + final Message msg = (Message) object; + Object[] body = (Object[]) msg.getBody(); + return "foo".equals(body[0]); + } + + public void appendTo(StringBuffer stringBuffer) { + } + }); + return null; + } + + /** + * Tests a basic invocation to a target + */ + public void testTargetInvocation() throws Exception { + ModuleScopeContainer scope = new ModuleScopeContainer(null); + scope.start(); + List> services = new ArrayList>(); + services.add(Greeting.class); + Map properties = new Hashtable(); + properties.put("greeting","HeyThere"); + + RubyComponent context = new RubyComponent("source", + implClass2, + null, + services, + properties, + null, + scope, + ArtifactFactory.createWireService(), + null); + scope.register(context); + DataType returnDataType = new DataType(String.class, String.class.getName()); +// Operation operation = new Operation("greet", +// returnDataType, +// null, +// null, +// false, +// null); +// +// TargetInvoker invoker = context.createTargetInvoker(null, +// operation); +// assertEquals("foo", +// invoker.invokeTarget(new String[]{"foo"})); + scope.stop(); + } + + /** + * Tests a basic invocation down a target wire + */ + public void testTargetWireInvocation() throws Exception { + ModuleScopeContainer scope = new ModuleScopeContainer(null); + scope.start(); + List> services = new ArrayList>(); + services.add(Greeting.class); + Map properties = new Hashtable(); + properties.put("greeting","HeyThere"); + RubyComponent context = new RubyComponent("source", + implClass2, + null, + services, + properties, + null, + scope, + ArtifactFactory.createWireService(), + null); + scope.register(context); + + InboundWire wire = ArtifactFactory.createInboundWire("Greeting", + Greeting.class); + ArtifactFactory.terminateWire(wire); + for (InboundInvocationChain chain : wire.getInvocationChains().values()) { + chain.setTargetInvoker(context.createTargetInvoker(null, + chain.getOperation())); + } + context.addInboundWire(wire); + Greeting greeting = (Greeting) context.getServiceInstance("Greeting"); + assertEquals("foo", + greeting.greet("foo")); + scope.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + implClass1 = new RubyScript("script1", SCRIPT); + implClass2 = new RubyScript("script2", SCRIPT2); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/function/HelloWorldTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/function/HelloWorldTestCase.java new file mode 100644 index 0000000000..c2af5b9b10 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/function/HelloWorldTestCase.java @@ -0,0 +1,75 @@ +/* + * 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.ruby.function; + +import java.net.URL; + +import helloworld.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; + private CompositeContext context = null; + + + protected void setUp() throws Exception { + URL base = getClass().getResource("/META-INF/sca/ruby.system.scdl"); + addExtension("RubyContainer", new URL(base, "default.scdl")); + setApplicationSCDL(getClass().getResource("helloworld.scdl")); + super.setUp(); + + context = CurrentCompositeContext.getContext(); + helloWorldService = context.locateService(HelloWorldService.class, "HelloWorldRubyComponent"); + + //helloWorldService = context.locateService(HelloWorldService.class, "HelloWorldJavaReference"); + } + + public void testHelloWorldWithClass() throws Exception { + assertEquals(helloWorldService.sayHello("petra"), "Hey Howdy from Java Reference petra"); + //System.out.println(helloWorldService.sayHello("petra")); + } + + public void testHelloWorldGlobal() throws Exception { + assertEquals(helloWorldService.sayHello("artep"), "Hey Howdy from Java Reference artep"); + //System.out.println(helloWorldService.sayHello("artep")); + } + + public void testHelloWorldProperty() throws Exception { + HelloWorldService helloWorldService = context.locateService(HelloWorldService.class, "HelloWorldProperty"); + assertEquals(helloWorldService.sayHello("petra"), "Namaskaar petra"); + //System.out.println(helloWorldService.sayHello("petra")); + } + + public void testHelloWorldPropertyDefault() throws Exception { + HelloWorldService helloWorldService = context.locateService(HelloWorldService.class, "HelloWorldPropertyDefault"); + assertEquals(helloWorldService.sayHello("petra"), "Bow Wow petra"); + //System.out.println(helloWorldService.sayHello("petra")); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/mock/Greeting.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/mock/Greeting.java new file mode 100644 index 0000000000..acf71f152b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/java/org/apache/tuscany/container/ruby/mock/Greeting.java @@ -0,0 +1,26 @@ +/* + * 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.ruby.mock; + +public interface Greeting { + + String setWire(Greeting ref); + + String greet(String name); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/HelloWorld.componentType b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/HelloWorld.componentType new file mode 100644 index 0000000000..d52b63226c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/HelloWorld.componentType @@ -0,0 +1,28 @@ + + + + + + + + + + Hullow + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/HelloWorld.rb b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/HelloWorld.rb new file mode 100644 index 0000000000..3f1a053b15 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/HelloWorld.rb @@ -0,0 +1,33 @@ + # 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. + +class Helloworld + + def sayHello(s) + return "Hello to " + s + " from the Ruby World!" + end + +end + +class HelloWorldServiceRubyImpl + attr_writer :extHelloWorld + attr_writer :greeting + + def sayHello(s) + return @greeting + " " + @extHelloWorld.sayHello(s); + end +end diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/IntrospectableHelloWorld.rb b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/IntrospectableHelloWorld.rb new file mode 100644 index 0000000000..d4edb7a100 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/IntrospectableHelloWorld.rb @@ -0,0 +1,30 @@ + # 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. + +$SCA = { + 'javaInterface' => 'helloworld.HelloWorldService' +} + +def sayHello(s) + return "Hello to " + s + " from the Ruby World!" +end + +class HelloWorldServiceRubyImpl + def sayHello(s) + return "Hello to " + s + " from the Ruby World!" + end +end diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/helloworld.scdl b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/helloworld.scdl new file mode 100644 index 0000000000..222beac543 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/helloworld.scdl @@ -0,0 +1,44 @@ + + + + + + + HelloWorldJavaReference + Hey + + + + + Howdy + + + + + Namaskaar + + + + + + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/propertyTest.componentType b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/propertyTest.componentType new file mode 100644 index 0000000000..6b37990b8b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/propertyTest.componentType @@ -0,0 +1,26 @@ + + + + + + + + Bow Wow + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/propertyTest.rb b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/propertyTest.rb new file mode 100644 index 0000000000..7aa0f3e8ea --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/function/propertyTest.rb @@ -0,0 +1,24 @@ + # 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. + +class HelloWorldPropertyTest + attr_writer :GREETING + + def sayHello(s) + return @GREETING + " " + s; + end +end \ No newline at end of file diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/jruby/helloworld.wsdl b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/jruby/helloworld.wsdl new file mode 100644 index 0000000000..67067f044a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/jruby/helloworld.wsdl @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/mock/test.rb b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/mock/test.rb new file mode 100644 index 0000000000..ef2694b475 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.ruby/src/test/resources/org/apache/tuscany/container/ruby/mock/test.rb @@ -0,0 +1 @@ +//Test Script \ No newline at end of file -- cgit v1.2.3