blob: de33a5b1405a60104e282cfb00235ec3197cd496 [file] [log] [blame]
/*
* 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.core.context.impl;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.StringWriter;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Binding;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.assembly.Service;
import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
import org.apache.tuscany.sca.assembly.builder.BuilderContext;
import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
import org.apache.tuscany.sca.context.CompositeContext;
import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory;
import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl;
import org.apache.tuscany.sca.core.context.ServiceReferenceExt;
import org.apache.tuscany.sca.core.factory.ObjectCreationException;
import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory;
import org.apache.tuscany.sca.core.invocation.ProxyFactory;
import org.apache.tuscany.sca.core.invocation.impl.AsyncJDKInvocationHandler;
import org.apache.tuscany.sca.core.invocation.impl.DOMInvokerImpl;
import org.apache.tuscany.sca.interfacedef.Interface;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
import org.apache.tuscany.sca.invocation.MessageFactory;
import org.apache.tuscany.sca.runtime.DOMInvoker;
import org.apache.tuscany.sca.runtime.Invocable;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
import org.oasisopen.sca.ServiceRuntimeException;
import org.w3c.dom.Node;
/**
* Default implementation of a ServiceReference.
*
* @version $Rev$ $Date$
* @param <B> the type of the business interface
*/
public class ServiceReferenceImpl<B> implements ServiceReferenceExt<B> {
private static final long serialVersionUID = 6763709434194361540L;
protected transient ProxyFactory proxyFactory;
protected transient Class<B> businessInterface;
protected transient B proxy;
protected Object callbackID; // The callbackID should be serializable
protected transient RuntimeEndpointReference endpointReference;
// protected String scdl;
//
// private transient XMLStreamReader xmlReader;
protected transient CompositeContext compositeContext;
protected ExtensionPointRegistry registry;
protected FactoryExtensionPoint modelFactories;
protected RuntimeAssemblyFactory assemblyFactory;
protected StAXArtifactProcessorExtensionPoint staxProcessors;
protected StAXArtifactProcessor<EndpointReference> staxProcessor;
protected XMLInputFactory xmlInputFactory;
protected XMLOutputFactory xmlOutputFactory;
protected BuilderExtensionPoint builders;
private MessageFactory messageFactory;
/*
* Public constructor for Externalizable serialization/deserialization
*/
public ServiceReferenceImpl() {
super();
}
public ServiceReferenceImpl(Class<B> businessInterface,
Invocable endpointReference,
CompositeContext compositeContext) {
this.businessInterface = businessInterface;
this.endpointReference = (RuntimeEndpointReference) endpointReference;
if (compositeContext == null) {
compositeContext = endpointReference.getCompositeContext();
}
bind(compositeContext);
}
public ServiceReferenceImpl(Class<B> businessInterface,
Invocable endpointReference) {
this(businessInterface, endpointReference, null);
}
protected void bind(CompositeContext context) {
this.compositeContext = context;
this.registry = compositeContext.getExtensionPointRegistry();
this.modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
this.assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class);
this.xmlInputFactory = modelFactories.getFactory(XMLInputFactory.class);
this.xmlOutputFactory = modelFactories.getFactory(XMLOutputFactory.class);
this.staxProcessors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
this.staxProcessor = staxProcessors.getProcessor(EndpointReference.class);
this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
this.proxyFactory = ExtensibleProxyFactory.getInstance(registry);
FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
this.messageFactory = modelFactories.getFactory(MessageFactory.class);
}
public RuntimeEndpointReference getEndpointReference() {
return endpointReference;
}
public B getProxy() throws ObjectCreationException {
try {
if (proxy == null) {
proxy = createProxy();
}
return proxy;
} catch (Exception e) {
throw new ObjectCreationException(e);
}
}
public void setProxy(B proxy) {
this.proxy = proxy;
}
protected B createProxy() throws Exception {
return proxyFactory.createProxy(this);
}
public B getService() {
try {
resolve();
return getProxy();
} catch (Exception e) {
throw new ServiceRuntimeException(e);
}
}
public Class<B> getBusinessInterface() {
try {
resolve();
return businessInterface;
} catch (Exception e) {
throw new ServiceRuntimeException(e);
}
}
/**
* Follow a service promotion chain down to the inner most (non composite)
* component service.
*
* @param topCompositeService
* @return
*/
private ComponentService getPromotedComponentService(CompositeService compositeService) {
ComponentService componentService = compositeService.getPromotedService();
if (componentService != null) {
Service service = componentService.getService();
if (componentService.getName() != null && service instanceof CompositeService) {
// Continue to follow the service promotion chain
return getPromotedComponentService((CompositeService)service);
} else {
// Found a non-composite service
return componentService;
}
} else {
// No promoted service
return null;
}
}
// ============ WRITE AND READ THE REFERENCE TO EXTERNAL XML ========================
/**
* write the reference to a stream
*
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(endpointReference);
/*
try {
String xml = null;
if (scdl == null) {
xml = toXMLString();
} else {
xml = scdl;
}
if (xml == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeUTF(xml);
}
} catch (Exception e) {
// e.printStackTrace();
throw new IOException(e.toString());
}
*/
}
/**
* write the endpoint reference into an xml string
*/
public String toXMLString() throws IOException, XMLStreamException, ContributionWriteException {
StringWriter writer = new StringWriter();
XMLStreamWriter streamWriter = xmlOutputFactory.createXMLStreamWriter(writer);
staxProcessor.write(endpointReference, streamWriter, new ProcessorContext(registry));
return writer.toString();
}
/**
* Read the reference from a stream
*
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.endpointReference = (RuntimeEndpointReference) in.readObject();
// Force resolve
endpointReference.getComponent();
bind(endpointReference.getCompositeContext());
RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference();
reference.setComponent((RuntimeComponent)endpointReference.getComponent());
Interface i = reference.getInterfaceContract().getInterface();
if (i instanceof JavaInterface) {
JavaInterface javaInterface = (JavaInterface)i;
if (javaInterface.isUnresolved()) {
// Allow privileged access to get ClassLoader. Requires RuntimePermission in
// security policy.
ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
javaInterface.setJavaClass(classLoader.loadClass(javaInterface.getName()));
JavaInterfaceFactory javaInterfaceFactory = getJavaInterfaceFactory(compositeContext);
try {
javaInterfaceFactory.createJavaInterface(javaInterface, javaInterface.getJavaClass());
} catch (InvalidInterfaceException e) {
throw new ServiceRuntimeException(e);
}
//FIXME: If the interface needs XSDs to be loaded (e.g., for static SDO),
// this needs to be done here. We usually search for XSDs in the current
// contribution at resolve time. Is it possible to locate the current
// contribution at runtime?
}
this.businessInterface = (Class<B>)javaInterface.getJavaClass();
}
Binding binding = endpointReference.getBinding();
if (binding != null) {
BindingBuilder bindingBuilder = builders.getBindingBuilder(binding.getType());
if (bindingBuilder != null) {
org.apache.tuscany.sca.assembly.builder.BuilderContext context = new BuilderContext(registry);
bindingBuilder.build(endpointReference.getComponent(), reference, endpointReference.getBinding(), context, false);
}
}
this.proxyFactory = getProxyFactory(this.compositeContext);
/*
endpointReference.bind(CompositeContext.getCurrentCompositeContext());
endpointReference.rebuild();
*/
/*
final boolean hasSCDL = in.readBoolean();
if (hasSCDL) {
this.scdl = in.readUTF();
} else {
this.scdl = null;
}
*/
}
/**
* Read xml string into the endpoint reference
*/
/*
public void fromXMLString() throws IOException, XMLStreamException, ContributionReadException {
XMLStreamReader streamReader = xmlReader;
if (scdl != null) {
Reader reader = new StringReader(scdl);
if (xmlInputFactory == null) {
// this is a reference being read from a external stream
// so set up enough of the reference in order to resolved the
// xml being read
bind(CompositeContext.getCurrentCompositeContext());
}
streamReader = xmlInputFactory.createXMLStreamReader(reader);
}
endpointReference = (RuntimeEndpointReference) staxProcessor.read(streamReader, new ProcessorContext(registry));
// ok to GC
xmlReader = null;
scdl = null;
}
*/
/**
* @throws IOException
*/
private synchronized void resolve() throws Exception {
/*
if ((scdl != null || xmlReader != null) && endpointReference == null) {
fromXMLString();
compositeContext.bindComponent((RuntimeComponent) endpointReference.getComponent());
RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference();
reference.setComponent((RuntimeComponent)endpointReference.getComponent());
ReferenceParameters parameters = null;
for (Object ext : reference.getExtensions()) {
if (ext instanceof ReferenceParameters) {
parameters = (ReferenceParameters)ext;
break;
}
}
if (parameters != null) {
this.callbackID = parameters.getCallbackID();
}
Interface i = reference.getInterfaceContract().getInterface();
if (i instanceof JavaInterface) {
JavaInterface javaInterface = (JavaInterface)i;
if (javaInterface.isUnresolved()) {
// Allow privileged access to get ClassLoader. Requires RuntimePermission in
// security policy.
ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
javaInterface.setJavaClass(classLoader.loadClass(javaInterface.getName()));
JavaInterfaceFactory javaInterfaceFactory = getJavaInterfaceFactory(compositeContext);
javaInterfaceFactory.createJavaInterface(javaInterface, javaInterface.getJavaClass());
//FIXME: If the interface needs XSDs to be loaded (e.g., for static SDO),
// this needs to be done here. We usually search for XSDs in the current
// contribution at resolve time. Is it possible to locate the current
// contribution at runtime?
}
this.businessInterface = (Class<B>)javaInterface.getJavaClass();
}
Binding binding = endpointReference.getBinding();
if (binding != null) {
BindingBuilder bindingBuilder = builders.getBindingBuilder(binding.getType());
if (bindingBuilder != null) {
BuilderContext context = new BuilderContext(registry);
bindingBuilder.build(endpointReference.getComponent(), reference, endpointReference.getBinding(), context);
}
}
this.proxyFactory = getProxyFactory(this.compositeContext);
} else if (compositeContext == null) {
this.compositeContext = CompositeContext.getCurrentCompositeContext();
if (this.compositeContext != null) {
this.proxyFactory = getProxyFactory(this.compositeContext);
}
}
*/
}
private JavaInterfaceFactory getJavaInterfaceFactory(CompositeContext compositeContext) {
ExtensionPointRegistry extensionPointRegistry = compositeContext.getExtensionPointRegistry();
FactoryExtensionPoint factories = extensionPointRegistry.getExtensionPoint(FactoryExtensionPoint.class);
JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class);
return javaInterfaceFactory;
}
private ProxyFactory getProxyFactory(CompositeContext compositeContext) {
ExtensionPointRegistry extensionPointRegistry = compositeContext.getExtensionPointRegistry();
return ExtensibleProxyFactory.getInstance(extensionPointRegistry);
}
// ==================================================================================
/*
public XMLStreamReader getXMLReader() {
return xmlReader;
}
*/
public void setBindingURI(String uri) {
((RuntimeEndpointReferenceImpl)endpointReference).setBindingURI(uri);
}
public DOMInvoker getDOMInvoker() {
RuntimeEndpointReference epr = getEndpointReference();
InterfaceContract ic;
try {
ic = (InterfaceContract)epr.getGeneratedWSDLContract(epr.getBindingInterfaceContract()).clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
ic.getInterface().resetDataBinding(Node.class.getName());
((RuntimeEndpointReferenceImpl)epr).setreferenceInterfaceContract(ic);
epr.rebuild();
AsyncJDKInvocationHandler handler = new AsyncJDKInvocationHandler(registry, messageFactory, this);
return new DOMInvokerImpl(handler);
}
}