diff options
Diffstat (limited to 'sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org')
18 files changed, 2458 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2AsyncBindingInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2AsyncBindingInvoker.java new file mode 100644 index 0000000000..e2517e02d8 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2AsyncBindingInvoker.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.binding.axis2; + +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.CountDownLatch; + +import javax.xml.namespace.QName; + +import org.apache.axiom.soap.SOAPFactory; +import org.apache.axis2.AxisFault; +import org.apache.axis2.client.OperationClient; +import org.apache.axis2.client.Options; +import org.apache.axis2.client.ServiceClient; + +public class Axis2AsyncBindingInvoker extends Axis2BindingInvoker { + + private Axis2ReferenceCallbackTargetInvoker callbackInvoker; + + public Axis2AsyncBindingInvoker(ServiceClient serviceClient, + QName wsdlOperationName, + Options options, + SOAPFactory soapFactory) { + super(serviceClient, wsdlOperationName, options, soapFactory); + } + + private Object invokeTarget(final Object payload, String conversationId) + throws InvocationTargetException { + try { + Object[] args = (Object[]) payload; + OperationClient operationClient = createOperationClient(args, conversationId); + Axis2ReferenceCallback callback = new Axis2ReferenceCallback(callbackInvoker); + operationClient.setCallback(callback); + + // FIXME Synchronize with callback thread to get return value + CountDownLatch doneSignal = new CountDownLatch(1); + callbackInvoker.setSignal(doneSignal); + + operationClient.execute(false); + + try { + doneSignal.await(); + } catch(InterruptedException e) { + e.printStackTrace(); + } + + // FIXME returning value from callback thread + Object response = callbackInvoker.getReturnPayload(); + return response; + } catch (AxisFault e) { + throw new InvocationTargetException(e); + } + } + + public void setCallbackTargetInvoker(Axis2ReferenceCallbackTargetInvoker callbackInvoker) { + this.callbackInvoker = callbackInvoker; + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2BindingInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2BindingInvoker.java new file mode 100644 index 0000000000..fe33416f8b --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2BindingInvoker.java @@ -0,0 +1,146 @@ +/* + * 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.sca.binding.axis2; + +import java.lang.reflect.InvocationTargetException; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.soap.SOAPBody; +import org.apache.axiom.soap.SOAPEnvelope; +import org.apache.axiom.soap.SOAPFactory; +import org.apache.axiom.soap.SOAPHeader; +import org.apache.axis2.AxisFault; +import org.apache.axis2.addressing.AddressingConstants; +import org.apache.axis2.addressing.EndpointReference; +import org.apache.axis2.client.OperationClient; +import org.apache.axis2.client.Options; +import org.apache.axis2.client.ServiceClient; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.transport.http.HTTPConstants; +import org.apache.axis2.wsdl.WSDLConstants; +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.osoa.sca.Constants; + +/** + * Axis2BindingInvoker uses an Axis2 OperationClient to invoke a remote web service + */ +public class Axis2BindingInvoker implements Invoker { + + private ServiceClient serviceClient; + private QName wsdlOperationName; + private Options options; + private SOAPFactory soapFactory; + + public static final QName CONVERSATION_ID_REFPARM_QN = new QName(Constants.SCA_NS,"conversationID"); + + public Axis2BindingInvoker(ServiceClient serviceClient, QName wsdlOperationName, + Options options, SOAPFactory soapFactory) { + this.serviceClient = serviceClient; + this.wsdlOperationName = wsdlOperationName; + this.options = options; + this.soapFactory = soapFactory; + } + + public Message invoke(Message msg) { + try { + // getCallbackUris() has been removed from the Message interface + // LinkedList<URI> callbackRoutingChain = msg.getCallbackUris(); + // if (callbackRoutingChain != null) { + // workContext.setCallbackUris(callbackRoutingChain); + // } + Object resp = invokeTarget(msg.getBody(), msg.getConversationSequence(), msg.getConversationID()); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setFaultBody(e.getCause()); + } catch (Throwable e) { + msg.setFaultBody(e); + } + return msg; + } + + protected Object invokeTarget(final Object payload, final ConversationSequence sequence, String conversationId) throws InvocationTargetException { + try { + + Object[] args = (Object[]) payload; + OperationClient operationClient = createOperationClient(args, conversationId); + + // ensure connections are tracked so that they can be closed by the reference binding + MessageContext requestMC = operationClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE); + requestMC.getOptions().setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Boolean.TRUE); + requestMC.getOptions().setTimeOutInMilliSeconds(120000L); + + operationClient.execute(true); + + MessageContext responseMC = operationClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE); + + operationClient.complete(requestMC); + + return responseMC.getEnvelope().getBody().getFirstElement(); + + } catch (AxisFault e) { + throw new InvocationTargetException(e); + } + } + + @SuppressWarnings("deprecation") + protected OperationClient createOperationClient(Object[] args, String conversationId) throws AxisFault { + SOAPEnvelope env = soapFactory.getDefaultEnvelope(); + if (args != null && args.length > 0) { + SOAPBody body = env.getBody(); + for (Object bc : args) { + if (bc instanceof OMElement) { + body.addChild((OMElement) bc); + } else { + throw new IllegalArgumentException( + "Can't handle mixed payloads betweem OMElements and other types."); + } + } + } + MessageContext requestMC = new MessageContext(); + requestMC.setEnvelope(env); + + // Axis2 operationClients can not be shared so create a new one for each request + OperationClient operationClient = serviceClient.createClient(wsdlOperationName); + + if (conversationId != null && conversationId.length() != 0) { + EndpointReference fromEPR = new EndpointReference(AddressingConstants.Final.WSA_ANONYMOUS_URL); + fromEPR.addReferenceParameter(CONVERSATION_ID_REFPARM_QN, conversationId); + options.setFrom(fromEPR); + requestMC.setFrom(fromEPR); //who knows why two ways ? + + //For now do this the brute force method. Need to figure out how to do axis addressing .. configure mar in flow. + SOAPEnvelope sev = requestMC.getEnvelope(); + SOAPHeader sh = sev.getHeader(); + OMElement el = fromEPR.toOM(AddressingConstants.Final.WSA_NAMESPACE, + AddressingConstants.WSA_FROM, + AddressingConstants.WSA_DEFAULT_PREFIX); + sh.addChild(el); + } + + operationClient.setOptions(options); + operationClient.addMessageContext(requestMC); + + return operationClient; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2BindingProviderFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2BindingProviderFactory.java new file mode 100644 index 0000000000..f6631d7e1f --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2BindingProviderFactory.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.sca.binding.axis2; + +import org.apache.tuscany.sca.binding.ws.WebServiceBinding; +import org.apache.tuscany.sca.http.ServletHost; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Axis2BindingProviderFactory + * + * @version $Rev$ $Date$ + */ + +public class Axis2BindingProviderFactory implements BindingProviderFactory<WebServiceBinding> { + + private MessageFactory messageFactory; + private ServletHost servletHost; + + public Axis2BindingProviderFactory(ServletHost servletHost, MessageFactory messageFactory) { + this.servletHost = servletHost; + this.messageFactory = messageFactory; + } + + public ReferenceBindingProvider createReferenceBindingProvider(RuntimeComponent component, RuntimeComponentReference reference, WebServiceBinding binding) { + return new Axis2ReferenceBindingProvider(component, reference, binding, messageFactory); + } + + public ServiceBindingProvider createServiceBindingProvider(RuntimeComponent component, RuntimeComponentService service, WebServiceBinding binding) { + return new Axis2ServiceBindingProvider(component, service, binding, servletHost, messageFactory); + } + + public Class<WebServiceBinding> getModelType() { + return WebServiceBinding.class; + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2CallbackInvocationHandler.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2CallbackInvocationHandler.java new file mode 100644 index 0000000000..91d0f05bde --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2CallbackInvocationHandler.java @@ -0,0 +1,53 @@ +/* + * 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.sca.binding.axis2; + +import java.net.URI; +import java.util.LinkedList; + +import org.apache.tuscany.sca.core.invocation.AbstractInvocationHandler; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; + +public class Axis2CallbackInvocationHandler extends AbstractInvocationHandler { + + private RuntimeWire wire; + + public Axis2CallbackInvocationHandler(MessageFactory messageFactory, RuntimeWire wire) { + super(messageFactory, false); + this.wire = wire; + } + + public Object invoke(Operation operation, Object[] args, LinkedList<URI> callbackRoutingChain) throws Throwable { +// Object targetAddress = callbackRoutingChain.removeFirst(); +// if (targetAddress == null) { +// throw new AssertionError("Popped a null from address from stack"); +// } + +// //TODO optimize as this is slow in local invocations +// Map<Operation, InvocationChain> sourceCallbackInvocationChains = +// wire.getCallbackInvocationChains(); +// InvocationChain chain = sourceCallbackInvocationChains.get(operation); +// chain.g +// TargetInvoker invoker = chain.getTargetInvoker(); +// return invoke(chain, invoker, args, null, callbackRoutingChain, null); + throw new UnsupportedOperationException("not yet implemented"); + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ModuleActivator.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ModuleActivator.java new file mode 100644 index 0000000000..50e916c084 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ModuleActivator.java @@ -0,0 +1,70 @@ +/* + * 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.sca.binding.axis2; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.binding.ws.DefaultWebServiceBindingFactory; +import org.apache.tuscany.sca.binding.ws.WebServiceBindingFactory; +import org.apache.tuscany.sca.binding.ws.xml.WebServiceBindingProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.http.ServletHost; +import org.apache.tuscany.sca.interfacedef.wsdl.DefaultWSDLFactory; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory; +import org.apache.tuscany.sca.interfacedef.wsdl.introspect.DefaultWSDLInterfaceIntrospector; +import org.apache.tuscany.sca.interfacedef.wsdl.introspect.WSDLInterfaceIntrospector; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; + +public class Axis2ModuleActivator implements ModuleActivator { + + public void start(ExtensionPointRegistry registry) { + + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = factories.getFactory(AssemblyFactory.class); + PolicyFactory policyFactory = factories.getFactory(PolicyFactory.class); + MessageFactory messageFactory = factories.getFactory(MessageFactory.class); + + WebServiceBindingFactory wsFactory = new DefaultWebServiceBindingFactory(); + WSDLFactory wsdlFactory = new DefaultWSDLFactory(); + + StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + WSDLInterfaceIntrospector introspector = new DefaultWSDLInterfaceIntrospector(wsdlFactory); + WebServiceBindingProcessor processor = + new WebServiceBindingProcessor(assemblyFactory, policyFactory, wsFactory, wsdlFactory, introspector); + processors.addArtifactProcessor(processor); + + ProviderFactoryExtensionPoint providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + ServletHost servletHost = registry.getExtensionPoint(ServletHost.class); + Axis2BindingProviderFactory providerFactory = new Axis2BindingProviderFactory(servletHost, messageFactory); + providerFactories.addProviderFactory(providerFactory); + } + + public void stop(ExtensionPointRegistry registry) { + } + + public Object[] getExtensionPoints() { + return null; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2OneWayBindingInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2OneWayBindingInvoker.java new file mode 100644 index 0000000000..fb95022c6b --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2OneWayBindingInvoker.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.sca.binding.axis2; + +import java.lang.reflect.InvocationTargetException; + +import javax.xml.namespace.QName; + +import org.apache.axiom.soap.SOAPFactory; +import org.apache.axis2.AxisFault; +import org.apache.axis2.client.OperationClient; +import org.apache.axis2.client.Options; +import org.apache.axis2.client.ServiceClient; + +public class Axis2OneWayBindingInvoker extends Axis2BindingInvoker { + + public Axis2OneWayBindingInvoker(ServiceClient serviceClient, + QName wsdlOperationName, + Options options, + SOAPFactory soapFactory) { + + super(serviceClient, wsdlOperationName, options, soapFactory); + } + + protected Object invokeTarget(final Object payload, final short sequence, String conversationId) throws InvocationTargetException { + try { + Object[] args = (Object[]) payload; + + OperationClient operationClient = createOperationClient(args, conversationId); + operationClient.execute(false); + + // REVIEW it seems ok to return null + return null; + + } catch (AxisFault e) { + throw new InvocationTargetException(e); + } catch (Throwable t) { + throw new InvocationTargetException(t); + } + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceBindingProvider.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceBindingProvider.java new file mode 100644 index 0000000000..98994aa917 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceBindingProvider.java @@ -0,0 +1,267 @@ +/** + * + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tuscany.sca.binding.axis2; + +import java.util.List; + +import javax.wsdl.Binding; +import javax.wsdl.BindingOperation; +import javax.wsdl.Definition; +import javax.wsdl.extensions.soap.SOAPAddress; +import javax.wsdl.extensions.soap.SOAPOperation; +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.soap.SOAPFactory; +import org.apache.axis2.AxisFault; +import org.apache.axis2.addressing.EndpointReference; +import org.apache.axis2.client.Options; +import org.apache.axis2.client.ServiceClient; +import org.apache.axis2.context.ConfigurationContext; +import org.apache.axis2.description.AxisService; +import org.apache.axis2.transport.http.HTTPConstants; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.tuscany.sca.binding.ws.WebServiceBinding; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; + +public class Axis2ReferenceBindingProvider implements ReferenceBindingProvider { + + private MessageFactory messageFactory; + private RuntimeComponent component; + private RuntimeComponentReference reference; + private WebServiceBinding wsBinding; + private ConfigurationContext configContext; + private ServiceClient serviceClient; + + public Axis2ReferenceBindingProvider(RuntimeComponent component, + RuntimeComponentReference reference, + WebServiceBinding wsBinding, + MessageFactory messageFactory) { + + this.component = component; + this.reference = reference; + this.wsBinding = wsBinding; + this.messageFactory = messageFactory; + + try { + TuscanyAxisConfigurator tuscanyAxisConfigurator = new TuscanyAxisConfigurator(); + configContext = tuscanyAxisConfigurator.getConfigurationContext(); + } catch (AxisFault e) { + throw new RuntimeException(e); // TODO: better exception + } + initServiceClient(); + } + + // methods for ReferenceBindingActivator + + public void initServiceClient() { + InterfaceContract contract = wsBinding.getBindingInterfaceContract(); + if (contract == null) { + contract = reference.getInterfaceContract(); + wsBinding.setBindingInterfaceContract(contract); + } + + // Set to use the Axiom data binding + contract.getInterface().setDefaultDataBinding(OMElement.class.getName()); + + // ??? following line was in Axis2BindingBuilder before the SPI changes + // and code reorg + // + // URI targetURI = wsBinding.getURI() != null ? + // URI.create(wsBinding.getURI()) : URI.create("foo"); + // + // targetURI was passed to the ReferenceBindingExtension constructor and + // apparently was unused + // Do we still need a targetURI? + + // wsBinding.setURI(component.getURI() + "#" + reference.getName()); + + // create an Axis2 ServiceClient + serviceClient = createServiceClient(); + } + + public void start() { + } + + public void stop() { + + // close all connections that we have initiated, so that the jetty + // server + // can be restarted without seeing ConnectExceptions + HttpClient httpClient = (HttpClient)serviceClient.getServiceContext().getConfigurationContext() + .getProperty(HTTPConstants.CACHED_HTTP_CLIENT); + if (httpClient != null) + ((MultiThreadedHttpConnectionManager)httpClient.getHttpConnectionManager()).shutdown(); + } + + /** + * Create an Axis2 ServiceClient + */ + protected ServiceClient createServiceClient() { + try { + QName serviceQName = wsBinding.getServiceName(); + String portName = wsBinding.getPortName(); + Definition wsdlDefinition = wsBinding.getWSDLDefinition().getDefinition(); + AxisService axisService = AxisService.createClientSideAxisService(wsdlDefinition, + serviceQName, + portName, + new Options()); + + return new ServiceClient(configContext, axisService); + } catch (AxisFault e) { + throw new RuntimeException(e); // TODO: better exception + } + } + + // methods for ReferenceBindingProvider + + public InterfaceContract getBindingInterfaceContract() { + return wsBinding.getBindingInterfaceContract(); + } + + public Invoker createInvoker(Operation operation, boolean isCallback) { + + Axis2BindingInvoker invoker; + + InterfaceContract contract = wsBinding.getBindingInterfaceContract(); + if (contract == null) { + contract = reference.getInterfaceContract(); + wsBinding.setBindingInterfaceContract(contract); + } + + if (wsBinding.getBindingInterfaceContract().getCallbackInterface() == null) { + invoker = createOperationInvoker(serviceClient, operation, false, operation.isNonBlocking()); + } else { + // FIXME: SDODataBinding needs to pass in TypeHelper and classLoader + // as parameters. + + // FIXME: This makes the (BIG) assumption that there is only one + // callback method + // Relaxing this assumption, however, does not seem to be trivial, + // it may depend on knowledge + // of what actual callback method was invoked by the service at the + // other end + + RuntimeWire wire = reference.getRuntimeWire(wsBinding); + Operation callbackOperation = findCallbackOperation(wire); + Axis2CallbackInvocationHandler invocationHandler = new Axis2CallbackInvocationHandler(messageFactory, wire); + Axis2ReferenceCallbackTargetInvoker callbackInvoker = new Axis2ReferenceCallbackTargetInvoker( + callbackOperation, + wire, + invocationHandler); + + Axis2AsyncBindingInvoker asyncInvoker = (Axis2AsyncBindingInvoker)createOperationInvoker(serviceClient, + operation, + true, + false); + asyncInvoker.setCallbackTargetInvoker(callbackInvoker); + invoker = asyncInvoker; + } + + return invoker; + } + + private Operation findCallbackOperation(RuntimeWire wire) { + InterfaceContract contract = wire.getTarget().getInterfaceContract(); // TODO: + // which + // end? + List callbackOperations = contract.getCallbackInterface().getOperations(); + if (callbackOperations.size() != 1) { + throw new RuntimeException("Can only handle one callback operation"); + } + Operation callbackOperation = (Operation)callbackOperations.get(0); + return callbackOperation; + } + + /** + * Create and configure an Axis2BindingInvoker for each operation + */ + private Axis2BindingInvoker createOperationInvoker(ServiceClient serviceClient, + Operation operation, + boolean hasCallback, + boolean isOneWay) { + + Options options = new Options(); + options.setTo(getPortLocationEPR()); + options.setProperty(HTTPConstants.CHUNKED, Boolean.FALSE); + + String operationName = operation.getName(); + + String soapAction = getSOAPAction(operationName); + if (soapAction != null && soapAction.length() > 1) { + options.setAction(soapAction); + } + + options.setTimeOutInMilliSeconds(30 * 1000); // 30 seconds + + SOAPFactory soapFactory = OMAbstractFactory.getSOAP11Factory(); + QName wsdlOperationQName = new QName(operationName); + + Axis2BindingInvoker invoker; + if (hasCallback) { + invoker = new Axis2AsyncBindingInvoker(serviceClient, wsdlOperationQName, options, soapFactory); + } else if (isOneWay) { + invoker = new Axis2OneWayBindingInvoker(serviceClient, wsdlOperationQName, options, soapFactory); + } else { + invoker = new Axis2BindingInvoker(serviceClient, wsdlOperationQName, options, soapFactory); + } + + return invoker; + } + + protected EndpointReference getPortLocationEPR() { + String ep = wsBinding.getURI(); + if (ep == null && wsBinding.getPort() != null) { + List wsdlPortExtensions = wsBinding.getPort().getExtensibilityElements(); + for (final Object extension : wsdlPortExtensions) { + if (extension instanceof SOAPAddress) { + ep = ((SOAPAddress)extension).getLocationURI(); + break; + } + } + } + return new EndpointReference(ep); + } + + protected String getSOAPAction(String operationName) { + Binding binding = wsBinding.getBinding(); + if (binding != null) { + for (Object o : binding.getBindingOperations()) { + BindingOperation bop = (BindingOperation)o; + if (bop.getName().equalsIgnoreCase(operationName)) { + for (Object o2 : bop.getExtensibilityElements()) { + if (o2 instanceof SOAPOperation) { + return ((SOAPOperation)o2).getSoapActionURI(); + } + } + } + } + } + return null; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceCallback.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceCallback.java new file mode 100644 index 0000000000..cbc82f9c68 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceCallback.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.sca.binding.axis2; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.axiom.om.OMElement; +import org.apache.axis2.client.async.AsyncResult; +import org.apache.axis2.client.async.Callback; +import org.apache.axis2.context.MessageContext; + +public class Axis2ReferenceCallback extends Callback { + + private Axis2ReferenceCallbackTargetInvoker targetInvoker; + + public Axis2ReferenceCallback(Axis2ReferenceCallbackTargetInvoker targetInvoker) { + this.targetInvoker = targetInvoker; + } + + public void onComplete(AsyncResult result) { + MessageContext responseMC = result.getResponseMessageContext(); + OMElement responseOM = responseMC.getEnvelope().getBody().getFirstElement(); + try { + targetInvoker.invokeTarget(new Object[] {responseOM}, null); + } catch (InvocationTargetException e) { + // FIXME what is the appropriate exception here? + throw new RuntimeException(e); + } + } + + public void setComplete(boolean complete) { + super.setComplete(complete); + } + + public void onError(Exception e) { + throw new RuntimeException(e); + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceCallbackTargetInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceCallbackTargetInvoker.java new file mode 100644 index 0000000000..dce9bf8cf1 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ReferenceCallbackTargetInvoker.java @@ -0,0 +1,108 @@ +/* + * 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.sca.binding.axis2; + +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.CountDownLatch; + +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeWire; + +public class Axis2ReferenceCallbackTargetInvoker { + + private Operation operation; + private RuntimeWire inboundWire; + private boolean cacheable; + Axis2CallbackInvocationHandler invocationHandler; + private CountDownLatch signal; + private Object returnPayload; + + public Axis2ReferenceCallbackTargetInvoker(Operation operation, + RuntimeWire inboundWire, + Axis2CallbackInvocationHandler invocationHandler) { + + this.operation = operation; + this.inboundWire = inboundWire; + this.invocationHandler = invocationHandler; + } + + public Object invokeTarget(final Object payload, final ConversationSequence sequence) throws InvocationTargetException { + Object[] args; + if (payload != null && !payload.getClass().isArray()) { + args = new Object[]{payload}; + returnPayload = payload; + } else { + args = (Object[]) payload; + returnPayload = args[0]; + } + // FIXME synchronize with forward thread to return value + signal.countDown(); + try { +// return invocationHandler.invoke(operation, args, callbackRoutingChain); + return null; // TODO ??? + } catch (Throwable t) { + t.printStackTrace(); + throw new InvocationTargetException(t); + } + } + + public Message invoke(Message msg) { + try { + Object resp = invokeTarget(msg.getBody(), null); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setFaultBody(e.getCause()); + } catch (Throwable e) { + msg.setFaultBody(e); + } + return msg; + } + + public boolean isCacheable() { + return cacheable; + } + + public void setCacheable(boolean cacheable) { + this.cacheable = cacheable; + } + + public boolean isOptimizable() { + return isCacheable(); // we only need to check if the scopes are correct + } + + public Axis2ReferenceCallbackTargetInvoker clone() throws CloneNotSupportedException { + Axis2ReferenceCallbackTargetInvoker invoker = (Axis2ReferenceCallbackTargetInvoker) super.clone(); + invoker.operation = this.operation; + invoker.inboundWire = this.inboundWire; + invoker.cacheable = this.cacheable; + invoker.invocationHandler = this.invocationHandler; + return invoker; + } + + public void setSignal(CountDownLatch signal) { + this.signal = signal; + } + + public Object getReturnPayload() { + return returnPayload; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceBindingProvider.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceBindingProvider.java new file mode 100644 index 0000000000..b5a8e6552b --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceBindingProvider.java @@ -0,0 +1,418 @@ +/** + * + * Copyright 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tuscany.sca.binding.axis2; + +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +import javax.wsdl.Definition; +import javax.wsdl.Port; +import javax.wsdl.extensions.soap.SOAPAddress; +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.soap.SOAPFactory; +import org.apache.axis2.AxisFault; +import org.apache.axis2.context.ConfigurationContext; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.description.AxisOperation; +import org.apache.axis2.description.AxisService; +import org.apache.axis2.description.Parameter; +import org.apache.axis2.description.WSDL11ToAxisServiceBuilder; +import org.apache.axis2.description.WSDL2Constants; +import org.apache.axis2.description.WSDLToAxisServiceBuilder; +import org.apache.axis2.engine.MessageReceiver; +import org.apache.axis2.wsdl.WSDLConstants; +import org.apache.tuscany.sca.binding.ws.WebServiceBinding; +import org.apache.tuscany.sca.core.invocation.ThreadMessageContext; +import org.apache.tuscany.sca.http.ServletHost; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +public class Axis2ServiceBindingProvider implements ServiceBindingProvider { + + private RuntimeComponent component; + private RuntimeComponentService service; + private WebServiceBinding wsBinding; + private ServletHost servletHost; + private ConfigurationContext configContext; + private MessageFactory messageFactory; + + // TODO: what to do about the base URI? + private static final String BASE_URI = "http://localhost:8080/"; + + public Axis2ServiceBindingProvider(RuntimeComponent component, + RuntimeComponentService service, + WebServiceBinding wsBinding, + ServletHost servletHost, + MessageFactory messageFactory) { + + this.component = component; + this.service = service; + this.wsBinding = wsBinding; + this.servletHost = servletHost; + this.messageFactory = messageFactory; + + try { + TuscanyAxisConfigurator tuscanyAxisConfigurator = new TuscanyAxisConfigurator(); + configContext = tuscanyAxisConfigurator.getConfigurationContext(); + } catch (AxisFault e) { + throw new RuntimeException(e); // TODO: better exception + } + } + + // methods for ServiceBindingActivator + + public void start() { + + // TODO: add back in from duplicate code in getBindingInterfaceContract + // to temporarily bypass NPE + InterfaceContract contract = wsBinding.getBindingInterfaceContract(); + if (contract == null) { + contract = service.getInterfaceContract(); + wsBinding.setBindingInterfaceContract(contract); + } + + // Set to use the Axiom data binding + contract.getInterface().setDefaultDataBinding(OMElement.class.getName()); + + String uri = computeActualURI(BASE_URI, component, service).normalize().toString(); + if (uri.endsWith("/")) { + uri = uri.substring(0, uri.length() - 1); + } + wsBinding.setURI(uri.toString()); + + // TODO: if <binding.ws> specifies the wsdl service then should create a + // service for every port + + try { + configContext.getAxisConfiguration().addService(createAxisService()); + } catch (AxisFault e) { + throw new RuntimeException(e); + } + + Axis2ServiceServlet servlet = new Axis2ServiceServlet(); + servlet.init(configContext); + String servletURI = wsBinding.getURI(); + configContext.setContextRoot(servletURI); + servletHost.addServletMapping(servletURI, servlet); + } + + public void stop() { + servletHost.removeServletMapping(wsBinding.getURI()); + try { + configContext.getAxisConfiguration().removeService(wsBinding.getURI()); + } catch (AxisFault e) { + throw new RuntimeException(e); + } + } + + /** + * Compute the endpoint URI based on section 2.1.1 of the WS binding spec 1. + * The URIs in the endpoint(s) of the referenced WSDL, which may be relative + * 2. The URI specified by the wsa:Address element of the + * wsa:EndpointReference, which may be relative 3. The explicitly stated URI + * in the "uri" attribute of the binding.ws element, which may be relative, + * 4. The implicit URI as defined by in section 1.7 in the SCA Assembly spec + * If the <binding.ws> has no wsdlElement but does have a uri attribute then + * the uri takes precidence over any implicitly used WSDL. + * + * @param parent + */ + protected URI computeActualURI(String baseURI, RuntimeComponent component, RuntimeComponentService service) { + + // TODO: support wsa:Address + + URI wsdlURI = null; + if (wsBinding.getServiceName() != null && wsBinding.getBindingName() == null) { + // <binding.ws> explicitly points at a wsdl port, may be a relative + // URI + wsdlURI = getEndpoint(wsBinding.getPort()); + } + if (wsdlURI != null && wsdlURI.isAbsolute()) { + if (wsBinding.getURI() != null && (wsBinding.getServiceName() != null && wsBinding.getBindingName() == null)) { + throw new IllegalArgumentException("binding URI cannot be used with absolute WSDL endpoint URI"); + } + return URI.create(wsdlURI.toString()); + } + + // either there is no wsdl port endpoint URI or that URI is relative + + URI bindingURI = null; + if (wsBinding.getURI() != null) { + bindingURI = URI.create(wsBinding.getURI()); + } + if (bindingURI != null && bindingURI.isAbsolute()) { + // there is an absoulte uri specified on the binding: <binding.ws + // uri="xxx" + if (wsdlURI != null) { + // there is a relative URI in the wsdl port + return URI.create(bindingURI + "/" + wsdlURI); + } else { + return bindingURI; + } + } + + // both the WSDL endpoint and binding uri are either unspecified or + // relative so + // the endpoint is based on the component name and service binding URI + + URI componentURI = URI.create(component.getName()); + + String actualURI; + if (componentURI.isAbsolute()) { + actualURI = componentURI.toString(); + } else { + actualURI = baseURI + "/" + componentURI; + } + + // with multiple services the default binding URI is the binding name + if (bindingURI == null && component.getServices().size() > 1) { + // if the binding doesn't have a name use the name of the service + // (assumption, not in spec) + if (wsBinding.getName() != null) { + bindingURI = URI.create(wsBinding.getName()); + } else { + bindingURI = URI.create(service.getName()); + } + } + + // add any relative binding URI + if (bindingURI != null) { + actualURI += "/" + bindingURI; + } + + // add any relative WSDL port URI + if (wsdlURI != null) { + actualURI += "/" + wsdlURI.toString(); + } + + return URI.create(actualURI); + } + + /** + * Returns the endpoint of a given port. + */ + protected URI getEndpoint(Port wsdlPort) { + if (wsdlPort != null) { + List wsdlPortExtensions = wsdlPort.getExtensibilityElements(); + for (Object extension : wsdlPortExtensions) { + if (extension instanceof SOAPAddress) { + return URI.create(((SOAPAddress)extension).getLocationURI()); + } + } + } + return null; + } + + private AxisService createAxisService() throws AxisFault { + Definition definition = wsBinding.getWSDLDefinition().getDefinition(); + + // WSDLToAxisServiceBuilder only uses the service and port to find the + // wsdl4J Binding + // An SCA service with binding.ws does not require a service or port so + // we may not have these + // but + + WSDLToAxisServiceBuilder builder = new WSDL11ToAxisServiceBuilder(definition, wsBinding.getServiceName(), + wsBinding.getPortName()); + builder.setServerSide(true); + AxisService axisService = builder.populateService(); + + String path = URI.create(wsBinding.getURI()).getPath(); + axisService.setName(path); + axisService.setServiceDescription("Tuscany configured AxisService for service: " + wsBinding.getURI()); + + // Use the existing WSDL + Parameter wsdlParam = new Parameter(WSDLConstants.WSDL_4_J_DEFINITION, null); + wsdlParam.setValue(definition); + axisService.addParameter(wsdlParam); + Parameter userWSDL = new Parameter("useOriginalwsdl", "true"); + axisService.addParameter(userWSDL); + + for (Iterator i = axisService.getOperations(); i.hasNext();) { + AxisOperation axisOp = (AxisOperation)i.next(); + Operation op = getOperation(axisOp); + if (op != null) { + + if (op.isNonBlocking()) { + axisOp.setMessageExchangePattern(WSDL2Constants.MEP_URI_IN_ONLY); + } else { + axisOp.setMessageExchangePattern(WSDL2Constants.MEP_URI_IN_OUT); + } + + MessageReceiver msgrec = null; + if (wsBinding.getBindingInterfaceContract().getCallbackInterface() != null) { + msgrec = new Axis2ServiceInOutAsyncMessageReceiver(this, op); + } else if (op.isNonBlocking()) { + msgrec = new Axis2ServiceInMessageReceiver(this, op); + } else { + msgrec = new Axis2ServiceInOutSyncMessageReceiver(this, op); + } + axisOp.setMessageReceiver(msgrec); + } + } + + return axisService; + } + + protected Operation getOperation(AxisOperation axisOp) { + String operationName = axisOp.getName().getLocalPart(); + for (Operation op : wsBinding.getBindingInterfaceContract().getInterface().getOperations()) { + if (op.getName().equalsIgnoreCase(operationName)) { + return op; + } + } + return null; + } + + // methods for ServiceBindingProvider + + public InterfaceContract getBindingInterfaceContract() { + InterfaceContract contract = wsBinding.getBindingInterfaceContract(); + if (contract == null) { + contract = service.getInterfaceContract(); + wsBinding.setBindingInterfaceContract(contract); + } + + // Set to use the Axiom data binding + contract.getInterface().setDefaultDataBinding(OMElement.class.getName()); + return contract; + } + + // other methods that were previously in Axis2ServiceBinding + // TODO: are these still needed? + + private Map<Object, InvocationContext> invCtxMap = new HashMap<Object, InvocationContext>(); + + public Invoker createTargetInvoker(InterfaceContract contract, Operation operation) { + // if (!operation.isCallback()) { TODO: no isCallback methjod yet? + // throw new UnsupportedOperationException(); + // } else { + return new Axis2ServiceCallbackTargetInvoker(this); + // } + } + + public void addMapping(Object msgId, InvocationContext invCtx) { + this.invCtxMap.put(msgId, invCtx); + } + + public InvocationContext retrieveMapping(Object msgId) { + return this.invCtxMap.get(msgId); + } + + public void removeMapping(Object msgId) { + this.invCtxMap.remove(msgId); + } + + /** + * @param inMC + * @return + */ + protected static String getConversationID(MessageContext inMC) { + String conversationID = null; + Iterator i = inMC.getEnvelope().getHeader() + .getChildrenWithName(new QName("http://www.w3.org/2005/08/addressing", "From")); + for (; i.hasNext();) { + Object a = i.next(); + if (a instanceof OMElement) { + OMElement ao = (OMElement)a; + for (Iterator rpI = ao.getChildrenWithName(new QName("http://www.w3.org/2005/08/addressing", + "ReferenceParameters")); rpI.hasNext();) { + OMElement rpE = (OMElement)rpI.next(); + for (Iterator cidI = rpE.getChildrenWithName(Axis2BindingInvoker.CONVERSATION_ID_REFPARM_QN); cidI + .hasNext();) { + OMElement cidE = (OMElement)cidI.next(); + conversationID = cidE.getText(); + } + } + + } + + } + return conversationID; + } + + public Object invokeTarget(Operation op, Object[] args, Object messageId, String conversationID) + throws InvocationTargetException { + + Message requestMsg = messageFactory.createMessage(); + + if (messageId != null) { + requestMsg.setMessageID(messageId); + } + requestMsg.setBody(args); + + Message workContext = ThreadMessageContext.getMessageContext(); + + ThreadMessageContext.setMessageContext(requestMsg); + try { + if (isConversational() && conversationID != null) { + requestMsg.setConversationID(conversationID); + } else { + requestMsg.setConversationID(null); + } + + Message responseMsg = service.getInvoker(wsBinding, op).invoke(requestMsg); + + if (responseMsg.isFault()) { + throw new InvocationTargetException((Throwable)responseMsg.getBody()); + } + return responseMsg.getBody(); + + } finally { + ThreadMessageContext.setMessageContext(workContext); + } + } + + protected class InvocationContext { + public MessageContext inMessageContext; + + public Operation operation; + + public SOAPFactory soapFactory; + + public CountDownLatch doneSignal; + + public InvocationContext(MessageContext messageCtx, + Operation operation, + SOAPFactory soapFactory, + CountDownLatch doneSignal) { + this.inMessageContext = messageCtx; + this.operation = operation; + this.soapFactory = soapFactory; + this.doneSignal = doneSignal; + } + } + + public boolean isConversational() { + return wsBinding.getBindingInterfaceContract().getInterface().isConversational(); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceCallbackTargetInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceCallbackTargetInvoker.java new file mode 100644 index 0000000000..29eb24bc61 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceCallbackTargetInvoker.java @@ -0,0 +1,105 @@ +/* + * 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.sca.binding.axis2; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.soap.SOAPEnvelope; +import org.apache.axis2.AxisFault; +import org.apache.axis2.Constants; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.engine.AxisEngine; +import org.apache.axis2.util.Utils; +import org.apache.tuscany.sca.binding.axis2.Axis2ServiceBindingProvider.InvocationContext; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; + +public class Axis2ServiceCallbackTargetInvoker implements Invoker { + + private Axis2ServiceBindingProvider service; + + protected static final OMElement RESPONSE = null; + + public Axis2ServiceCallbackTargetInvoker(Axis2ServiceBindingProvider service) { + this.service = service; + } + + private Object invokeTarget(final Object payload, Object correlationId) throws InvocationTargetException { + try { + // Use current correlation id as index to retrieve inv context + InvocationContext invCtx = service.retrieveMapping(correlationId); + + MessageContext outMC = Utils.createOutMessageContext(invCtx.inMessageContext); + outMC.getOperationContext().addMessageContext(outMC); + + OMElement responseOM; + if (payload != null && !payload.getClass().isArray()) { + responseOM = (OMElement) payload; + } else { + responseOM = (OMElement) ((Object[]) payload)[0]; + } + SOAPEnvelope soapEnvelope = invCtx.soapFactory.getDefaultEnvelope(); + soapEnvelope.getBody().addChild(responseOM); + outMC.setEnvelope(soapEnvelope); + outMC.getOperationContext().setProperty(Constants.RESPONSE_WRITTEN, Constants.VALUE_TRUE); + + AxisEngine engine = + new AxisEngine( + invCtx.inMessageContext.getOperationContext().getServiceContext().getConfigurationContext()); + engine.send(outMC); + + invCtx.doneSignal.countDown(); + + service.removeMapping(correlationId); + } catch (AxisFault e) { + throw new InvocationTargetException(e); + } catch (Throwable t) { + throw new InvocationTargetException(t); + } + + return RESPONSE; + } + + public Message invoke(Message msg) { + try { + Object correlationId = msg.getCorrelationID(); + if (correlationId == null) { + throw new RuntimeException("Missing correlation id"); + } + Object resp = invokeTarget(msg.getBody(), correlationId); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setFaultBody(e.getCause()); + } catch (Throwable e) { + msg.setFaultBody(e); + } + return msg; + } + + public Axis2ServiceCallbackTargetInvoker clone() throws CloneNotSupportedException { + try { + return (Axis2ServiceCallbackTargetInvoker) super.clone(); + } catch (CloneNotSupportedException e) { + // will not happen + return null; + } + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInMessageReceiver.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInMessageReceiver.java new file mode 100644 index 0000000000..85871c7924 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInMessageReceiver.java @@ -0,0 +1,65 @@ +/* + * 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.sca.binding.axis2; + +import org.apache.axiom.om.OMElement; +import org.apache.axis2.AxisFault; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.receivers.AbstractInMessageReceiver; +import org.apache.tuscany.sca.interfacedef.Operation; + +public class Axis2ServiceInMessageReceiver extends AbstractInMessageReceiver { + + protected Operation operation; + + private Axis2ServiceBindingProvider provider; + + public Axis2ServiceInMessageReceiver(Axis2ServiceBindingProvider provider, Operation operation) { + this.provider = provider; + this.operation = operation; + } + + public Axis2ServiceInMessageReceiver() { + + } + + @Override + public void invokeBusinessLogic(MessageContext inMC) throws AxisFault { + try { + OMElement requestOM = inMC.getEnvelope().getBody().getFirstElement(); + Object[] args = new Object[] {requestOM}; + String conversationID = provider.isConversational() ? Axis2ServiceBindingProvider.getConversationID(inMC) : null; + +// axis2Service.invokeTarget(operation, args, null, conversationID); + +// } catch (InvocationTargetException e) { +// Throwable t = e.getCause(); +// if (t instanceof Exception) { +// throw AxisFault.makeFault((Exception)t); +// } +// throw new InvocationRuntimeException(e); + } catch (Throwable t) { + if (t instanceof Exception) { + throw AxisFault.makeFault((Exception)t); + } + throw new RuntimeException(t); + } + + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInOutAsyncMessageReceiver.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInOutAsyncMessageReceiver.java new file mode 100644 index 0000000000..70d705c7b8 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInOutAsyncMessageReceiver.java @@ -0,0 +1,128 @@ +/* + * 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.sca.binding.axis2; + +import java.util.concurrent.CountDownLatch; + +import org.apache.axiom.om.OMElement; +import org.apache.axis2.AxisFault; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.receivers.AbstractMessageReceiver; +import org.apache.tuscany.sca.interfacedef.Operation; + +public class Axis2ServiceInOutAsyncMessageReceiver extends AbstractMessageReceiver { + + private Operation operation; + + private Axis2ServiceBindingProvider provider; + + public Axis2ServiceInOutAsyncMessageReceiver(Axis2ServiceBindingProvider provider, + Operation operation) { + this.provider = provider; + this.operation = operation; + } + + public Axis2ServiceInOutAsyncMessageReceiver() { + } + + public final void receive(final MessageContext messageCtx) { + try { + Object messageId = messageCtx.getMessageID(); + if (messageId == null) { + messageId = new MessageId(); + } + + // Now use message id as index to context to be used by callback + // target invoker + CountDownLatch doneSignal = new CountDownLatch(1); +// InvocationContext invCtx = +// service.new InvocationContext(messageCtx, operation, getSOAPFactory(messageCtx), doneSignal); +// service.addMapping(messageId, invCtx); + + invokeBusinessLogic(messageCtx, messageId); + + try { + doneSignal.await(); + } catch(InterruptedException e) { + e.printStackTrace(); + } + } catch (AxisFault e) { + // log.error(e); + } + } + + private void invokeBusinessLogic(MessageContext inMC, Object messageId) throws AxisFault { + try { + OMElement requestOM = inMC.getEnvelope().getBody().getFirstElement(); + Object[] args = new Object[] {requestOM}; + String conversationID = provider.isConversational() ? Axis2ServiceBindingProvider.getConversationID(inMC) : null; +// service.invokeTarget(operation, args, messageId, conversationID); +// } catch (InvocationTargetException e) { +// Throwable t = e.getCause(); +// if (t instanceof Exception) { +// throw AxisFault.makeFault((Exception)t); +// } +// throw new InvocationRuntimeException(e); + } catch (Exception e) { + throw AxisFault.makeFault(e); + } + + } + + /** + * A unique identifier for a message flowing on a wire, potentially end-to-end (ie, through more than one SCAObject to + * SCAObject hop). + * + * This used to be in the org.apache.tuscany.spi.wire package + */ + public class MessageId { + + private long timestamp; + + public MessageId() { + this.timestamp = System.currentTimeMillis(); + } + + public long getTimestamp() { + return timestamp; + } + + public String toString() { + return "MsgId[" + timestamp + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + final MessageId messageId = (MessageId) o; + return timestamp == messageId.timestamp; + } + + public int hashCode() { + return (int) (timestamp ^ (timestamp >>> 32)); + } + + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInOutSyncMessageReceiver.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInOutSyncMessageReceiver.java new file mode 100644 index 0000000000..ea5bb9f2e6 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceInOutSyncMessageReceiver.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.sca.binding.axis2; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.soap.SOAPEnvelope; +import org.apache.axis2.AxisFault; +import org.apache.axis2.Constants; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver; +import org.apache.tuscany.sca.interfacedef.Operation; + +public class Axis2ServiceInOutSyncMessageReceiver extends AbstractInOutSyncMessageReceiver { + + protected Operation operation; + + private Axis2ServiceBindingProvider provider; + + public Axis2ServiceInOutSyncMessageReceiver() { + } + + public Axis2ServiceInOutSyncMessageReceiver(Axis2ServiceBindingProvider provider, Operation operation) { + this.provider = provider; + this.operation = operation; + } + + @Override + public void invokeBusinessLogic(MessageContext inMC, MessageContext outMC) throws AxisFault { + try { + OMElement requestOM = inMC.getEnvelope().getBody().getFirstElement(); + Object[] args = new Object[] {requestOM}; + + String conversationID = provider.isConversational() ? Axis2ServiceBindingProvider.getConversationID(inMC) : null; + + OMElement responseOM = (OMElement) provider.invokeTarget(operation, args, null, conversationID); + + SOAPEnvelope soapEnvelope = getSOAPFactory(inMC).getDefaultEnvelope(); + if(null != responseOM ){ + soapEnvelope.getBody().addChild(responseOM); + } + outMC.setEnvelope(soapEnvelope); + outMC.getOperationContext().setProperty(Constants.RESPONSE_WRITTEN, Constants.VALUE_TRUE); + + } catch (InvocationTargetException e) { + e.printStackTrace(); + Throwable t = e.getCause(); + if (t instanceof Exception) { + throw AxisFault.makeFault((Exception)t); + } + throw new RuntimeException(e); + } catch (Exception e) { + e.printStackTrace(); + throw AxisFault.makeFault(e); + } + + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceServlet.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceServlet.java new file mode 100644 index 0000000000..b313ff1b4e --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/Axis2ServiceServlet.java @@ -0,0 +1,300 @@ +/* + * 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.sca.binding.axis2; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.SocketException; +import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Set; +import java.util.Vector; + +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.axis2.AxisFault; +import org.apache.axis2.addressing.EndpointReference; +import org.apache.axis2.context.ConfigurationContext; +import org.apache.axis2.transport.http.AxisServlet; +import org.apache.axis2.transport.http.ListingAgent; +import org.apache.axis2.transport.http.server.HttpUtils; + +/** + * This overrides the servlet init of the AxisServlet so Tuscany can use + * a single Axis2 ConfigurationContext instance shared between AxisServlet + * instances for each SCA service with a ws binding. + * TODO: need to review if thats really what we want to be doing + */ +public class Axis2ServiceServlet extends AxisServlet { + + protected TuscanyListingAgent agent; + protected boolean inited; + + private static final long serialVersionUID = 1L; + private static final ServletConfig DUMMY_CONFIG = createDummyServletConfig(); + + public void init(ConfigurationContext configContext) { + this.configContext = configContext; + try { + super.init(DUMMY_CONFIG); + } catch (ServletException e) { + throw new RuntimeException(e); + } + agent = new TuscanyListingAgent(configContext); + } + + /** + * Override Axis2 servlet method to avoid loop when init + * is called after servletConfig already initialized by + * this classes init(ConfigurationContext) method. + */ + @Override + public void init() throws ServletException { + } + + /** + * We've setup the Servlet by passing in a ConfigurationContext on our init method + * override this method to just return that + */ + @Override + protected ConfigurationContext initConfigContext(ServletConfig config) throws ServletException { + return this.configContext; + } + + @Override + public ServletConfig getServletConfig() { + return DUMMY_CONFIG; + } + + @Override + public String getServletName() { + return "TuscanyAxis2Servlet"; + } + + /** + * The AxisServlet gets NPE during init without a ServletConfig so this is a mocked up one to prevent that. + */ + private static ServletConfig createDummyServletConfig() { + ServletConfig sc = new ServletConfig() { + + public String getServletName() { + return "TuscanyAxis2DummyServlet"; + } + + public ServletContext getServletContext() { + return new ServletContext() { + + public ServletContext getContext(String uripath) { + return null; + } + + public String getContextPath() { + return null; + } + + public int getMajorVersion() { + return 0; + } + + public int getMinorVersion() { + return 0; + } + + public String getMimeType(String file) { + return null; + } + + public Set getResourcePaths(String path) { + return Collections.emptySet(); + } + + public URL getResource(String path) throws MalformedURLException { + if("/".equals(path)) { + // HACK: To avoid NPE + return new URL("/axis2"); + } + return null; + } + + public InputStream getResourceAsStream(String path) { + return null; + } + + public RequestDispatcher getRequestDispatcher(String path) { + return null; + } + + public RequestDispatcher getNamedDispatcher(String arg0) { + return null; + } + + public Servlet getServlet(String arg0) throws ServletException { + return null; + } + + public Enumeration getServlets() { + return null; + } + + public Enumeration getServletNames() { + return null; + } + + public void log(String arg0) { + } + + public void log(Exception arg0, String arg1) { + } + + public void log(String arg0, Throwable arg1) { + } + + public String getRealPath(String arg0) { + return null; + } + + public String getServerInfo() { + return null; + } + + public String getInitParameter(String arg0) { + return null; + } + + public Enumeration getInitParameterNames() { + return null; + } + + public Object getAttribute(String arg0) { + return null; + } + + public Enumeration getAttributeNames() { + return null; + } + + public void setAttribute(String arg0, Object arg1) { + } + + public void removeAttribute(String arg0) { + } + + public String getServletContextName() { + return null; + } + }; + } + + public String getInitParameter(String arg0) { + return null; + } + + public Enumeration getInitParameterNames() { + return new Vector().elements(); + } + }; + return sc; + } + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // HACK: Get the correct context root which is not available during init() call + if (!inited) { + synchronized (configContext) { + configContext.setContextRoot(request.getContextPath()); + inited = true; + } + } + + super.service(request, response); + } + + @Override + public void destroy() { + try { + super.destroy(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Override the AxisServlet doGet to use the TuscanyListingAgent for ?wsdl + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + initContextRoot(request); + + String query = request.getQueryString(); + if ((query != null) && (query.indexOf("wsdl2") >= 0 || + query.indexOf("wsdl") >= 0 || query.indexOf("xsd") >= 0 || + query.indexOf("policy") >= 0)) { + agent.processListService(request, response); + } else { + super.doGet(request, response); + } + } + + /** + + /** + * Override the AxisServlet method so as to not add "/services" into the url + */ + @Override + public EndpointReference[] getEPRsForService(String serviceName, String ip) throws AxisFault { + //RUNNING_PORT + String port = (String) configContext.getProperty(ListingAgent.RUNNING_PORT); + if (port == null) { + port = "8080"; + } + if (ip == null) { + try { + ip = HttpUtils.getIpAddress(); + if (ip == null) { + ip = "localhost"; + } + } catch (SocketException e) { + throw new AxisFault(e); + } + } + + + StringBuilder eprString = new StringBuilder("http://"); + eprString.append(ip).append(":").append(port); + if (!serviceName.startsWith("/")) { + eprString.append('/'); + } + eprString.append(serviceName); + EndpointReference endpoint = new EndpointReference(eprString.toString()); + + return new EndpointReference[]{endpoint}; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyAxisConfigurator.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyAxisConfigurator.java new file mode 100755 index 0000000000..370ed6e0a4 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyAxisConfigurator.java @@ -0,0 +1,44 @@ +/* + * 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.sca.binding.axis2; + +import org.apache.axis2.AxisFault; +import org.apache.axis2.context.ConfigurationContext; +import org.apache.axis2.context.ConfigurationContextFactory; +import org.apache.axis2.deployment.URLBasedAxisConfigurator; +import org.apache.axis2.engine.AxisConfigurator; + +/** + * Helps configure Axis2 from a resource in binding.axis2 instead of Axis2.xml + * <p/> TODO: Review: should there be a single global Axis + * ConfigurationContext + */ +public class TuscanyAxisConfigurator extends URLBasedAxisConfigurator implements AxisConfigurator { + + public TuscanyAxisConfigurator() throws AxisFault { + super(TuscanyAxisConfigurator.class.getResource("/org/apache/tuscany/sca/binding/axis2/engine/config/axis2.xml"), null); + } + + public ConfigurationContext getConfigurationContext() throws AxisFault { + if (configContext == null) + configContext = ConfigurationContextFactory.createConfigurationContext(this); + return configContext; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyDispatcher.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyDispatcher.java new file mode 100644 index 0000000000..8988c74445 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyDispatcher.java @@ -0,0 +1,101 @@ +/* + * 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.sca.binding.axis2; + +import java.net.URI; +import java.util.HashMap; + +import org.apache.axis2.AxisFault; +import org.apache.axis2.addressing.EndpointReference; +import org.apache.axis2.context.ConfigurationContext; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.description.AxisService; +import org.apache.axis2.description.HandlerDescription; +import org.apache.axis2.engine.AxisConfiguration; +import org.apache.axis2.engine.RequestURIBasedDispatcher; +import org.apache.axis2.util.JavaUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A Tuscany specific Axis2 Dispatcher that enables using services + * exposed at the SCA defined service URI instead of /services/<serviceName> + */ +public class TuscanyDispatcher extends RequestURIBasedDispatcher { + + public static final String NAME = "TuscanyDispatcher"; + private static final Log log = LogFactory.getLog(RequestURIBasedDispatcher.class); + private static final boolean isDebugEnabled = log.isDebugEnabled(); + + /* + * (non-Javadoc) + * + * @see org.apache.axis2.engine.AbstractDispatcher#findService(org.apache.axis2.context.MessageContext) + */ + public AxisService findService(MessageContext messageContext) throws AxisFault { + EndpointReference toEPR = messageContext.getTo(); + + if (toEPR != null) { + if(isDebugEnabled){ + log.debug("Checking for Service using target endpoint address : " + toEPR.getAddress()); + } + + String path = URI.create(toEPR.getAddress()).getPath(); + + ConfigurationContext configurationContext = messageContext.getConfigurationContext(); + AxisConfiguration registry = configurationContext.getAxisConfiguration(); + + String serviceName = findAxisServiceName(registry, path); + return registry.getService(serviceName); + + } else { + if(isDebugEnabled){ + log.debug("Attempted to check for Service using null target endpoint URI"); + } + return null; + } + } + + public void initDispatcher() { + init(new HandlerDescription(NAME)); + } + + protected String findAxisServiceName(AxisConfiguration registry, String path) { + HashMap services = registry.getServices(); + if (services == null) { + return null; + } + String[] parts = JavaUtils.split(path, '/'); + String serviceName = ""; + for (int i=parts.length-1; i>=0; i--) { + serviceName = parts[i] + serviceName; + if (services.containsKey(serviceName)) { + return serviceName; + } + serviceName = "/" + serviceName; + if (services.containsKey(serviceName)) { + return serviceName; + } + } + + return null; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyListingAgent.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyListingAgent.java new file mode 100644 index 0000000000..87338ceb27 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ws-axis2/src/main/java/org/apache/tuscany/sca/binding/axis2/TuscanyListingAgent.java @@ -0,0 +1,334 @@ +/* + * 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.sca.binding.axis2; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.axiom.attachments.utils.IOUtils; +import org.apache.axis2.Constants; +import org.apache.axis2.context.ConfigurationContext; +import org.apache.axis2.deployment.DeploymentConstants; +import org.apache.axis2.description.AxisDescription; +import org.apache.axis2.description.AxisService; +import org.apache.axis2.description.PolicyInclude; +import org.apache.axis2.transport.http.ListingAgent; +import org.apache.axis2.util.ExternalPolicySerializer; +import org.apache.axis2.util.JavaUtils; +import org.apache.neethi.Policy; +import org.apache.neethi.PolicyRegistry; +import org.apache.ws.commons.schema.XmlSchema; + +/** + * A Tuscany specific Axis2 ListingAgent as the Axis2 one does not work + * with the Tuscany sevice names which include slash ('/') characters. + * Unfortunately it ends up having to copy a fair amount of Axis2 code to do this. + */ +public class TuscanyListingAgent extends ListingAgent { + + private static final String LIST_SINGLE_SERVICE_JSP_NAME = + "listSingleService.jsp"; + + public TuscanyListingAgent(ConfigurationContext aConfigContext) { + super(aConfigContext); + } + + protected String findAxisServiceName(String path) { + HashMap services = configContext.getAxisConfiguration().getServices(); + if (services == null) { + return null; + } + String[] parts = JavaUtils.split(path, '/'); + String serviceName = ""; + for (int i=parts.length-1; i>=0; i--) { + serviceName = parts[i] + serviceName; + if (services.containsKey(serviceName)) { + return serviceName; + } + serviceName = "/" + serviceName; + if (services.containsKey(serviceName)) { + return serviceName; + } + } + + return null; + } + + @Override + public void processListService(HttpServletRequest req, + HttpServletResponse res) + throws IOException, ServletException { + + + String filePart = req.getRequestURL().toString(); +// String serviceName = filePart.substring(filePart.lastIndexOf("/") + 1, +// filePart.length()); +// Change the Axis2 code so as to use the complete ServletPath as the service name +// this line is the only change to to Axis2 code + + String serviceName = findAxisServiceName(filePart); + + String query = req.getQueryString(); + int wsdl2 = query.indexOf("wsdl2"); + int wsdl = query.indexOf("wsdl"); + int xsd = query.indexOf("xsd"); + int policy = query.indexOf("policy"); + + HashMap services = configContext.getAxisConfiguration().getServices(); + if ((services != null) && !services.isEmpty()) { + Object serviceObj = services.get(serviceName); + if (serviceObj != null) { + boolean isHttp = "http".equals(req.getScheme()); + if (wsdl2 >= 0) { + OutputStream out = res.getOutputStream(); + res.setContentType("text/xml"); + String ip = extractHostAndPort(filePart, isHttp); + ((AxisService) serviceObj) + .printWSDL2(out, ip, configContext.getServiceContextPath()); + out.flush(); + out.close(); + return; + } else if (wsdl >= 0) { + OutputStream out = res.getOutputStream(); + res.setContentType("text/xml"); + String ip = extractHostAndPort(filePart, isHttp); + ((AxisService) serviceObj).printWSDL(out, ip, configContext.getServicePath()); + out.flush(); + out.close(); + return; + } else if (xsd >= 0) { + OutputStream out = res.getOutputStream(); + res.setContentType("text/xml"); + AxisService axisService = (AxisService) serviceObj; + //call the populator + axisService.populateSchemaMappings(); + Map schemaMappingtable = + axisService.getSchemaMappingTable(); + ArrayList schemas = axisService.getSchema(); + + //a name is present - try to pump the requested schema + String xsds = req.getParameter("xsd"); + if (!"".equals(xsds)) { + XmlSchema schema = + (XmlSchema) schemaMappingtable.get(xsds); + if (schema != null) { + //schema is there - pump it outs + schema.write(new OutputStreamWriter(out, "UTF8")); + out.flush(); + out.close(); + } else { + InputStream in = axisService.getClassLoader() + .getResourceAsStream(DeploymentConstants.META_INF + "/" + xsds); + if (in != null) { + out.write(IOUtils.getStreamAsByteArray(in)); + out.flush(); + out.close(); + } else { + res.sendError(HttpServletResponse.SC_NOT_FOUND); + } + } + + //multiple schemas are present and the user specified + //no name - in this case we cannot possibly pump a schema + //so redirect to the service root + } else if (schemas.size() > 1) { + res.sendRedirect(""); + //user specified no name and there is only one schema + //so pump that out + } else { + XmlSchema schema = axisService.getSchema(0); + if (schema != null) { + schema.write(new OutputStreamWriter(out, "UTF8")); + out.flush(); + out.close(); + } + } + return; + } else if (policy >= 0) { + + OutputStream out = res.getOutputStream(); + + ExternalPolicySerializer serializer = new ExternalPolicySerializer(); + serializer.setAssertionsToFilter(configContext + .getAxisConfiguration().getLocalPolicyAssertions()); + + // check whether Id is set + String idParam = req.getParameter("id"); + + if (idParam != null) { + // Id is set + + Policy targetPolicy = findPolicy(idParam, (AxisService) serviceObj); + + if (targetPolicy != null) { + XMLStreamWriter writer; + + try { + writer = XMLOutputFactory.newInstance() + .createXMLStreamWriter(out); + + res.setContentType("text/xml"); + targetPolicy.serialize(writer); + writer.flush(); + + } catch (XMLStreamException e) { + throw new ServletException( + "Error occured when serializing the Policy", + e); + + } catch (FactoryConfigurationError e) { + throw new ServletException( + "Error occured when serializing the Policy", + e); + } + + } else { + + res.setContentType("text/html"); + String outStr = "<b>No policy found for id=" + + idParam + "</b>"; + out.write(outStr.getBytes()); + } + + } else { + + PolicyInclude policyInclude = ((AxisService) serviceObj).getPolicyInclude(); + Policy effecPolicy = policyInclude.getEffectivePolicy(); + + if (effecPolicy != null) { + XMLStreamWriter writer; + + try { + writer = XMLOutputFactory.newInstance() + .createXMLStreamWriter(out); + + res.setContentType("text/xml"); + effecPolicy.serialize(writer); + writer.flush(); + + } catch (XMLStreamException e) { + throw new ServletException( + "Error occured when serializing the Policy", + e); + + } catch (FactoryConfigurationError e) { + throw new ServletException( + "Error occured when serializing the Policy", + e); + } + } else { + + res.setContentType("text/html"); + String outStr = "<b>No effective policy for " + + serviceName + " servcie</b>"; + out.write(outStr.getBytes()); + } + } + + return; + } else { + req.getSession().setAttribute(Constants.SINGLE_SERVICE, + serviceObj); + } + } else { + req.getSession().setAttribute(Constants.SINGLE_SERVICE, null); + } + } + + renderView(LIST_SINGLE_SERVICE_JSP_NAME, req, res); + } + + private String extractHostAndPort(String filePart, boolean isHttp) { + int ipindex = filePart.indexOf("//"); + String ip = null; + if (ipindex >= 0) { + ip = filePart.substring(ipindex + 2, filePart.length()); + int seperatorIndex = ip.indexOf(":"); + int slashIndex = ip.indexOf("/"); + String port; + if (seperatorIndex >= 0) { + port = ip.substring(seperatorIndex + 1, slashIndex); + ip = ip.substring(0, seperatorIndex); + } else { + ip = ip.substring(0, slashIndex); + port = "80"; + } + if (isHttp) { + configContext.setProperty(RUNNING_PORT, port); + } + } + return ip; + } + + private Policy findPolicy(String id, AxisDescription des) { + + List policyElements = des.getPolicyInclude().getPolicyElements(); + PolicyRegistry registry = des.getPolicyInclude().getPolicyRegistry(); + + Object policyComponent; + + Policy policy = registry.lookup(id); + + if (policy != null) { + return policy; + } + + for (Iterator iterator = policyElements.iterator(); iterator.hasNext();) { + policyComponent = iterator.next(); + + if (policyComponent instanceof Policy) { + // policy found for the id + + if (id.equals(((Policy) policyComponent).getId())) { + return (Policy) policyComponent; + } + } + } + + AxisDescription child; + + for (Iterator iterator = des.getChildren(); iterator.hasNext();) { + child = (AxisDescription) iterator.next(); + policy = findPolicy(id, child); + + if (policy != null) { + return policy; + } + } + + return null; + } + +} |