
org.objectweb.jonas.ws.axis.JAxisServiceFactory Maven / Gradle / Ivy
The newest version!
/**
* JOnAS: Java(TM) Open Application Server
* Copyright (C) 1999-2005 Bull S.A.
* Contact: [email protected]
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id: JAxisServiceFactory.java 10513 2007-06-04 13:38:32Z sauthieg $
* --------------------------------------------------------------------------
*/
package org.objectweb.jonas.ws.axis;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.naming.BinaryRefAddr;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.client.AxisClient;
import org.apache.axis.configuration.XMLStringProvider;
import org.apache.axis.deployment.wsdd.WSDDConstants;
import org.apache.axis.deployment.wsdd.WSDDProvider;
import org.apache.axis.utils.XMLUtils;
import org.apache.axis.wsdl.toJava.Utils;
import org.objectweb.jonas_lib.xml.XMLSerializer;
import org.objectweb.jonas_ws.deployment.api.MappingFile;
import org.objectweb.jonas_ws.deployment.api.PortComponentDesc;
import org.objectweb.jonas_ws.deployment.api.PortComponentRefDesc;
import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc;
import org.objectweb.jonas_ws.deployment.api.IServiceRefDesc;
import org.objectweb.jonas.common.I18n;
import org.objectweb.jonas.common.JNDIUtils;
import org.objectweb.jonas.common.Log;
import org.objectweb.jonas.ws.JServiceFactory;
import org.objectweb.jonas.ws.WSServiceException;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
/**
* Axis specific JServiceFactory. Create an Axis Service Reference. Used to
* recreate Axis Service bound in JNDI (ObjectFactory)
* @author Guillaume Sauthier
* @author Xavier Delplanque
*/
public class JAxisServiceFactory implements JServiceFactory {
/** logger */
private static Logger logger = Log.getLogger(Log.JONAS_WS_PREFIX);
/** i18n instance */
private static I18n i18n = I18n.getInstance(JAxisServiceFactory.class);
/** The jonas-init-param name for client configuration file */
private static final String AXIS_CLIENT_CONFIG_PARAM = "axis.clientConfigFile";
/** default client configuration file to be filled */
private static final String CLIENT_CONFIG_WSDD = "org/objectweb/jonas/ws/axis/client-config.wsdd";
/** Service Implementation in JOnAS */
private static final String JONAS_SERVICE_CLASSNAME = "org.objectweb.jonas.ws.axis.JService";
// ======================================================================
/**
* Ref name for client-config wsdd
*/
public static final String REF_CLIENT_CONFIG = "client.config.wsdd";
/**
* Ref name for the service WSDL URL
*/
public static final String REF_SERVICE_WSDL = "service.wsdl.url";
/**
* Ref name for the service QName
*/
public static final String REF_SERVICE_QNAME = "service.qname";
/**
* Ref name for a Map linking service-endpoint-interface (from port-component) to wsdl:port
*/
public static final String REF_SERVICE_PORT2WSDL = "port.2.wsdl.map";
/**
* Ref name for the service call properties
*/
public static final String REF_SERVICE_CALL_PROPS = "service.call.properties";
/**
* Ref name for the service call properties
*/
public static final String REF_SERVICE_STUB_PROPS = "service.stub.properties";
/**
* Ref name for the service port list
*/
public static final String REF_SERVICE_WSDL_PORT_LIST = "service.port.list";
/**
* setEndpointAddress method signature
*/
private static final Class[] SETENDPOINTADDRESS_SIG = new Class[] {java.lang.String.class, java.lang.String.class };
// ======================================================================
/**
* Construct a new JAxisServiceFactory.
*/
public JAxisServiceFactory() {
QName javaURI = new QName(WSDDConstants.URI_WSDD_JAVA, WSDDNoopProvider.PROVIDER_NAME);
WSDDProvider.registerProvider(javaURI, new WSDDNoopProvider());
}
/**
* Create a Reference on a Service from an Axis Service object.
* @param sr the service-ref instance where informations are extracted
* @param cl the classloader where config files can be loaded
* @return a Reference on a Service from an Axis Service object.
* @throws WSServiceException if wsdd cannot be load or merged
*/
public Reference getServiceReference(IServiceRefDesc sr, ClassLoader cl) throws WSServiceException {
// TODO remove this ugly cast
String classname = createServiceClassname((ServiceRefDesc) sr);
logger.log(BasicLevel.DEBUG, "Service classname: '" + classname + "'");
// Create a reference on the Service class (generated or not)
Reference ref = new Reference(classname, getClass().getName(), null);
Document base = loadAxisDeployment(CLIENT_CONFIG_WSDD, cl);
// get the WSDD configuration
String clientConfig = sr.getParam(AXIS_CLIENT_CONFIG_PARAM);
// If ServiceRef has a specified ConfigFile
if (clientConfig != null) {
// load wsdd
Document doc = loadAxisDeployment(clientConfig, cl);
// merge
mergeAxisDeployment(base, doc);
}
// 1. client.wsdd
String str = null;
try {
str = serializeDOM(base);
if (logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "Client Descriptor file : \n" + str);
}
} catch (IOException ioe) {
throw new WSServiceException("Cannot serialize Document", ioe);
}
ref.add(new StringRefAddr(REF_CLIENT_CONFIG, str));
//2. manage port-component-link
for (Iterator i = sr.getPortComponentRefs().iterator(); i.hasNext();) {
PortComponentRefDesc pcr = (PortComponentRefDesc) i.next();
PortComponentDesc referencedPortComponent = pcr.getPortComponentDesc();
// port has a link on a local port
if (referencedPortComponent != null) {
logger.log(BasicLevel.DEBUG, "Find a port-component-link in port-component-ref" + pcr.getSEI());
// Get the Service WSDL URL !!!
URL url = referencedPortComponent.getEndpointURL();
if (url == null) {
// Component outside JOnAS server
// lookup endpoint URL value
try {
Context ic = new InitialContext();
url = (URL) ic.lookup(referencedPortComponent.getName());
} catch (NamingException ne) {
throw new WSServiceException("Cannot find updated endpoint for port-component '"
+ referencedPortComponent.getName() + "'", ne);
}
}
logger.log(BasicLevel.DEBUG, "Uptodate URL : '" + url + "?JWSDL' ");
ref.add(new StringRefAddr(REF_SERVICE_WSDL, url.toExternalForm() + "?JWSDL"));
}
}
// 3. service wsdl URL
if (sr.getAlternateWsdlURL() != null) {
logger.log(BasicLevel.DEBUG, "Using alternate WSDL URL : '" + sr.getAlternateWsdlURL() + "'");
ref.add(new StringRefAddr(REF_SERVICE_WSDL, sr.getAlternateWsdlURL().toString()));
} else if (sr.getLocalWSDLURL() != null) {
logger.log(BasicLevel.DEBUG, "Using WSDL URL : '" + sr.getLocalWSDLURL() + "'");
ref.add(new StringRefAddr(REF_SERVICE_WSDL, sr.getLocalWSDLURL().toExternalForm()));
}
// 4. Service QName
if (sr.getServiceQName() != null) {
ref.add(new BinaryRefAddr(REF_SERVICE_QNAME, JNDIUtils.getBytesFromObject(sr.getServiceQName())));
}
// 5. classname -> wsdl:port map
List ports = sr.getPortComponentRefs();
if (!ports.isEmpty()) {
Map map = new Hashtable();
for (Iterator i = ports.iterator(); i.hasNext();) {
PortComponentRefDesc pcrd = (PortComponentRefDesc) i.next();
QName wsdlPort = pcrd.getWsdlPort();
if (wsdlPort != null) {
map.put(pcrd.getSEI().getName(), wsdlPort);
}
}
if (!map.isEmpty()) {
ref.add(new BinaryRefAddr(REF_SERVICE_PORT2WSDL, JNDIUtils.getBytesFromObject(map)));
}
}
// 6. store call & stubs properties
String portNames = null;
for (Iterator i = sr.getPortComponentRefs().iterator(); i.hasNext();) {
PortComponentRefDesc pcr = (PortComponentRefDesc) i.next();
Properties cProps = pcr.getCallProperties();
Properties sProps = pcr.getStubProperties();
if (pcr.getWsdlPort() != null) {
// use call & stub property only if there is a wsdl:port for applying to
// TODO must be something to add into documentation for this
String name = pcr.getWsdlPort().getLocalPart();
if (!cProps.isEmpty()) {
ref.add(new BinaryRefAddr(REF_SERVICE_CALL_PROPS + "_" + name, JNDIUtils
.getBytesFromObject(cProps)));
}
if (!sProps.isEmpty()) {
ref.add(new BinaryRefAddr(REF_SERVICE_STUB_PROPS + "_" + name, JNDIUtils
.getBytesFromObject(sProps)));
}
if (!sProps.isEmpty() || !cProps.isEmpty()) {
if (portNames != null) {
// only the first addition does not need a comma
portNames += "," + name;
} else {
portNames = name;
}
}
}
}
if (portNames != null) {
ref.add(new StringRefAddr(REF_SERVICE_WSDL_PORT_LIST, portNames));
}
return ref;
}
/**
* @param base the Document to serialize
* @return Returns a String representation of the given XML Document
* @throws IOException when Serializer cannot proceed
*/
private String serializeDOM(Document base) throws IOException {
StringWriter sw = new StringWriter();
XMLSerializer ser = new XMLSerializer(base);
ser.serialize(sw);
return sw.getBuffer().toString();
}
/**
* @param base father Document
* @param doc Document that will be incorpored inside base Document
*/
private void mergeAxisDeployment(Document base, Document doc) {
Element importedDeploymentElement = (Element) base.importNode(doc.getDocumentElement(), true);
NodeList list = importedDeploymentElement.getChildNodes();
// append each Element childnodes
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i) instanceof Element) {
base.getDocumentElement().appendChild(list.item(i));
}
}
}
/**
* Create the Axis Service Implementation class name from the QName (if
* generated interface found).
* TODO Use jaxrpc mapping information if available !
* @param sr the service-ref storing service informations
* @return the fully qualified Service implementation classname.
*/
private String createServiceClassname(ServiceRefDesc sr) {
String intfName = sr.getServiceInterface().getName();
if (intfName.equals("javax.xml.rpc.Service")) {
// no generated class
return JONAS_SERVICE_CLASSNAME;
} else {
// generated class
QName qn = sr.getServiceQName();
MappingFile mf = sr.getMappingFile();
String p = (String) mf.getMappings().get(qn.getNamespaceURI());
String classname = "";
if (p != null) {
classname = p + "." + Utils.xmlNameToJavaClass(qn.getLocalPart()) + "Locator";
} else {
classname = Utils.xmlNameToJavaClass(qn.getLocalPart()) + "Locator";
}
return classname;
}
}
/**
* Load the Axis Deployment Descriptor from the ClassLoader.
* @param filename the resource name to load
* @param cl The ClassLoader used to load the WSDD
* @return the Document Axis Deployment Descriptor from the ClassLoader.
* @throws WSServiceException if resource could not be found or if XML
* Document cannot be created
*/
private Document loadAxisDeployment(String filename, ClassLoader cl) throws WSServiceException {
InputStream is = cl.getResourceAsStream(filename);
//logger.log(BasicLevel.DEBUG, "classloader : " + cl);
if (is == null) {
// exception !
String err = i18n.getMessage("JAxisServiceFactory.loadAxisDeployment.configNotFound", filename);
logger.log(BasicLevel.ERROR, err);
throw new WSServiceException(err);
}
Document doc = null;
try {
doc = XMLUtils.newDocument(is);
} catch (Exception e) {
String err = i18n.getMessage("JAxisServiceFactory.loadAxisDeployment.docCreation", filename);
logger.log(BasicLevel.DEBUG, err);
throw new WSServiceException(err, e);
}
return doc;
}
/**
* Create a new instance of Axis Service (or sub classes) from a Reference
* object.
* @param refObject the Reference to create an instance from
* @param name Object Name
* @param nameCtx Context
* @param env the environnment
* @return A Service instance configured
* @throws Exception when instanciation fail (check if this is a correct
* behavior !!!)
*/
public Object getObjectInstance(Object refObject, Name name, Context nameCtx, Hashtable env) throws Exception {
JService instance = null;
Object proxy = null;
if (refObject instanceof Reference) {
Reference ref = (Reference) refObject;
// get ClassLoader
ClassLoader cl = Thread.currentThread().getContextClassLoader();
logger.log(BasicLevel.DEBUG, "Context ClassLoader : " + cl);
// get Class
Class serviceClass = cl.loadClass(ref.getClassName());
// new Service
BinaryRefAddr bRefQname = (BinaryRefAddr) ref.get(REF_SERVICE_QNAME);
QName serviceQname = null;
if (bRefQname != null) {
serviceQname = (QName) JNDIUtils.getObjectFromBytes((byte[]) bRefQname.getContent());
}
RefAddr refServiceWSDL = ref.get(REF_SERVICE_WSDL);
String serviceWsdl = null;
if (refServiceWSDL != null) {
serviceWsdl = (String) refServiceWSDL.getContent();
}
// Prefill as much as we can
if (JONAS_SERVICE_CLASSNAME.equals(serviceClass.getName())) {
// default service class
logger.log(BasicLevel.DEBUG, "default service class");
if ((serviceQname == null) && (serviceWsdl == null)) {
logger.log(BasicLevel.DEBUG, "Create a new Service instance without params");
// no param instance
instance = new JService();
} else if ((serviceQname != null) && (serviceWsdl == null)) {
logger.log(BasicLevel.DEBUG, "Create a new Service instance with only a QName " + serviceQname);
// serviceQname only
instance = new JService(serviceQname);
} else if ((serviceQname != null) && (serviceWsdl != null)) {
logger.log(BasicLevel.DEBUG, "Create a new Service instance with QName " + serviceQname
+ "and WSDL " + serviceWsdl);
// serviceQname + wsdl
instance = new JService(serviceWsdl, serviceQname);
} else {
logger.log(BasicLevel.DEBUG, "Create a new Service instance with WSDL " + serviceWsdl);
logger.log(BasicLevel.DEBUG, "Should not occurs !!!");
// wsdl
// serviceWsdl, updatedURLs, serviceQname);
instance = new JService();
}
} else {
logger.log(BasicLevel.DEBUG, "Create a new Generated Service instance");
logger.log(BasicLevel.DEBUG, "serviceWSDL:" + serviceWsdl + " serviceQName:" + serviceQname);
// generated class
Constructor ctr = serviceClass.getConstructor(new Class[] {String.class, QName.class});
instance = (JService) ctr.newInstance(new Object[] {serviceWsdl, serviceQname});
// we have to update ports endpoints
// we should have Service WSDL
// otherwise, no Generated WSDL !
if (serviceWsdl != null) {
WSDLFactory factory = WSDLFactory.newInstance();
WSDLReader reader = factory.newWSDLReader();
reader.setFeature("javax.wsdl.importDocuments", true);
Definition def = reader.readWSDL(serviceWsdl);
Service service = def.getService(serviceQname);
Map ports = service.getPorts();
java.lang.reflect.Method m = serviceClass.getMethod("setEndpointAddress", SETENDPOINTADDRESS_SIG);
for (Iterator i = ports.keySet().iterator(); i.hasNext();) {
String portName = (String) i.next();
Port port = service.getPort(portName);
String endpoint = getSOAPLocation(port);
m.invoke(instance, new Object[] {port.getName(), endpoint });
}
}
}
// get port2wsdl map
BinaryRefAddr bRefp2w = (BinaryRefAddr) ref.get(REF_SERVICE_PORT2WSDL);
if (bRefp2w != null) {
Map map = (Map) JNDIUtils.getObjectFromBytes((byte[]) bRefp2w.getContent());
instance.assignSEIClassnameToWSDLPort(map);
}
// get WSDL_PORT_NAMES
RefAddr portsRef = ref.get(REF_SERVICE_WSDL_PORT_LIST);
String listPorts = null;
if (portsRef != null) {
listPorts = (String) portsRef.getContent();
if (listPorts != null) {
// get call properties
StringTokenizer strPort = new StringTokenizer(listPorts, ",");
while (strPort.hasMoreTokens()) {
String port = strPort.nextToken();
// call properties
BinaryRefAddr bRefcp = (BinaryRefAddr) ref.get(REF_SERVICE_CALL_PROPS + "_" + port);
if (bRefcp != null) {
Properties callProperties = (Properties) JNDIUtils.getObjectFromBytes((byte[]) bRefcp.getContent());
instance.assignCallProperties(port, callProperties);
}
// stub properties
BinaryRefAddr bRefsp = (BinaryRefAddr) ref.get(REF_SERVICE_STUB_PROPS + "_" + port);
if (bRefsp != null) {
Properties stubProperties = (Properties) JNDIUtils.getObjectFromBytes((byte[]) bRefsp.getContent());
instance.assignStubProperties(port, stubProperties);
}
}
}
}
EngineConfiguration ec = getConfiguration(ref);
// configure the instance
instance.setEngine(new AxisClient(ec));
JServiceProxy handler = new JServiceProxy(instance);
Class[] serviceInterfaces = serviceClass.getInterfaces();
Class[] interfaces = new Class[serviceInterfaces.length + 1];
for (int i = 0; i < serviceInterfaces.length; i++) {
interfaces[i] = serviceInterfaces[i];
}
interfaces[serviceInterfaces.length] = javax.xml.rpc.Service.class;
proxy = Proxy.newProxyInstance(cl, interfaces, handler);
}
return proxy;
}
/**
* @param port analyzed port
* @return Returns the endpoint URL of the given Port
*/
private String getSOAPLocation(Port port) {
String endpoint = null;
List extensions = port.getExtensibilityElements();
for (Iterator i = extensions.iterator(); i.hasNext();) {
ExtensibilityElement ext = (ExtensibilityElement) i.next();
if (ext instanceof SOAPAddress) {
SOAPAddress addr = (SOAPAddress) ext;
endpoint = addr.getLocationURI();
}
}
return endpoint;
}
/**
* Return the EngineConfiguration object found in the Reference
* @param ref The reference to an Axis Service instance
* @return the EngineConfiguration object found in the Reference
* @throws Exception when content of reference is not a valid WSDD
*/
private EngineConfiguration getConfiguration(Reference ref) throws Exception {
// create a Configuration Object
String conf = (String) ref.get(REF_CLIENT_CONFIG).getContent();
logger.log(BasicLevel.DEBUG, "loaded configuration : " + conf);
return new XMLStringProvider(conf);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy