JAxisServiceFactory.java

00001 
00026 package org.objectweb.jonas.ws.axis;
00027 
00028 import java.io.IOException;
00029 import java.io.InputStream;
00030 import java.io.StringWriter;
00031 import java.lang.reflect.Constructor;
00032 import java.lang.reflect.Proxy;
00033 import java.net.URL;
00034 import java.util.Hashtable;
00035 import java.util.Iterator;
00036 import java.util.List;
00037 import java.util.Map;
00038 import java.util.Properties;
00039 import java.util.StringTokenizer;
00040 
00041 import javax.naming.BinaryRefAddr;
00042 import javax.naming.Context;
00043 import javax.naming.InitialContext;
00044 import javax.naming.Name;
00045 import javax.naming.NamingException;
00046 import javax.naming.RefAddr;
00047 import javax.naming.Reference;
00048 import javax.naming.StringRefAddr;
00049 import javax.wsdl.Definition;
00050 import javax.wsdl.Port;
00051 import javax.wsdl.Service;
00052 import javax.wsdl.extensions.ExtensibilityElement;
00053 import javax.wsdl.extensions.soap.SOAPAddress;
00054 import javax.wsdl.factory.WSDLFactory;
00055 import javax.wsdl.xml.WSDLReader;
00056 import javax.xml.namespace.QName;
00057 
00058 import org.w3c.dom.Document;
00059 import org.w3c.dom.Element;
00060 import org.w3c.dom.NodeList;
00061 
00062 import org.apache.axis.EngineConfiguration;
00063 import org.apache.axis.client.AxisClient;
00064 import org.apache.axis.configuration.XMLStringProvider;
00065 import org.apache.axis.deployment.wsdd.WSDDConstants;
00066 import org.apache.axis.deployment.wsdd.WSDDProvider;
00067 import org.apache.axis.utils.XMLUtils;
00068 import org.apache.axis.wsdl.toJava.Utils;
00069 
00070 import org.objectweb.jonas_lib.I18n;
00071 import org.objectweb.jonas_lib.xml.XMLSerializer;
00072 
00073 import org.objectweb.jonas_ws.deployment.api.MappingFile;
00074 import org.objectweb.jonas_ws.deployment.api.PortComponentDesc;
00075 import org.objectweb.jonas_ws.deployment.api.PortComponentRefDesc;
00076 import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc;
00077 
00078 import org.objectweb.jonas.common.JNDIUtils;
00079 import org.objectweb.jonas.common.Log;
00080 import org.objectweb.jonas.ws.JServiceFactory;
00081 import org.objectweb.jonas.ws.WSServiceException;
00082 
00083 import org.objectweb.util.monolog.api.BasicLevel;
00084 import org.objectweb.util.monolog.api.Logger;
00085 
00092 public class JAxisServiceFactory implements JServiceFactory {
00093 
00094 
00096     private static Logger logger = Log.getLogger(Log.JONAS_WS_PREFIX);
00097 
00099     private static I18n i18n = I18n.getInstance(JAxisServiceFactory.class);
00100 
00102     private static final String AXIS_CLIENT_CONFIG_PARAM = "axis.clientConfigFile";
00103 
00105     private static final String CLIENT_CONFIG_WSDD = "org/objectweb/jonas/ws/axis/client-config.wsdd";
00106 
00108     private static final String JONAS_SERVICE_CLASSNAME = "org.objectweb.jonas.ws.axis.JService";
00109 
00110     // ======================================================================
00111 
00115     public static final String REF_CLIENT_CONFIG = "client.config.wsdd";
00116 
00120     public static final String REF_SERVICE_WSDL = "service.wsdl.url";
00121 
00125     public static final String REF_SERVICE_QNAME = "service.qname";
00126 
00130     public static final String REF_SERVICE_PORT2WSDL = "port.2.wsdl.map";
00131 
00135     public static final String REF_SERVICE_CALL_PROPS = "service.call.properties";
00136 
00140     public static final String REF_SERVICE_STUB_PROPS = "service.stub.properties";
00141 
00145     private static final String REF_SERVICE_WSDL_PORT_LIST = "service.port.list";
00146 
00150     private static final Class[] SETENDPOINTADDRESS_SIG = new Class[] {java.lang.String.class, java.lang.String.class };
00151 
00152     // ======================================================================
00153 
00157     public JAxisServiceFactory() {
00158         QName javaURI = new QName(WSDDConstants.URI_WSDD_JAVA, WSDDNoopProvider.PROVIDER_NAME);
00159         WSDDProvider.registerProvider(javaURI, new WSDDNoopProvider());
00160     }
00161 
00169     public Reference getServiceReference(ServiceRefDesc sr, ClassLoader cl) throws WSServiceException {
00170 
00171         String classname = createServiceClassname(sr);
00172 
00173         logger.log(BasicLevel.DEBUG, "Service classname: '" + classname + "'");
00174 
00175         // Create a reference on the Service class (generated or not)
00176         Reference ref = new Reference(classname, getClass().getName(), null);
00177 
00178         Document base = loadAxisDeployment(CLIENT_CONFIG_WSDD, cl);
00179 
00180         // get the WSDD configuration
00181         String clientConfig = sr.getParam(AXIS_CLIENT_CONFIG_PARAM);
00182 
00183         // If ServiceRef has a specified ConfigFile
00184         if (clientConfig != null) {
00185             // load wsdd
00186             Document doc = loadAxisDeployment(clientConfig, cl);
00187 
00188             // merge
00189             mergeAxisDeployment(base, doc);
00190         }
00191 
00192         // 1. client.wsdd
00193         String str = null;
00194         try {
00195             str = serializeDOM(base);
00196             if (logger.isLoggable(BasicLevel.DEBUG)) {
00197                 logger.log(BasicLevel.DEBUG, "Client Descriptor file : \n" + str);
00198             }
00199         } catch (IOException ioe) {
00200             throw new WSServiceException("Cannot serialize Document", ioe);
00201         }
00202         ref.add(new StringRefAddr(REF_CLIENT_CONFIG, str));
00203 
00204         //2. manage port-component-link
00205         for (Iterator i = sr.getPortComponentRefs().iterator(); i.hasNext();) {
00206             PortComponentRefDesc pcr = (PortComponentRefDesc) i.next();
00207             PortComponentDesc referencedPortComponent = pcr.getPortComponentDesc();
00208 
00209             // port has a link on a local port
00210             if (referencedPortComponent != null) {
00211 
00212                 logger.log(BasicLevel.DEBUG, "Find a port-component-link in port-component-ref" + pcr.getSEI());
00213                 // Get the Service WSDL URL !!!
00214                 URL url = referencedPortComponent.getEndpointURL();
00215                 if (url == null) {
00216                     // Component outside JOnAS server
00217                     // lookup endpoint URL value
00218                     try {
00219                         Context ic = new InitialContext();
00220                         url = (URL) ic.lookup(referencedPortComponent.getName());
00221                     } catch (NamingException ne) {
00222                         throw new WSServiceException("Cannot find updated endpoint for port-component '"
00223                                 + referencedPortComponent.getName() + "'", ne);
00224                     }
00225                 }
00226 
00227                 logger.log(BasicLevel.DEBUG, "Uptodate URL : '" + url + "?JWSDL' ");
00228                 ref.add(new StringRefAddr(REF_SERVICE_WSDL, url.toExternalForm() + "?JWSDL"));
00229             }
00230         }
00231 
00232         // 3. service wsdl URL
00233         if (sr.getAlternateWsdlURL() != null) {
00234             logger.log(BasicLevel.DEBUG, "Using alternate WSDL URL : '" + sr.getAlternateWsdlURL() + "'");
00235             ref.add(new StringRefAddr(REF_SERVICE_WSDL, sr.getAlternateWsdlURL().toString()));
00236         } else if (sr.getLocalWSDLURL() != null) {
00237             logger.log(BasicLevel.DEBUG, "Using WSDL URL : '" + sr.getLocalWSDLURL() + "'");
00238             ref.add(new StringRefAddr(REF_SERVICE_WSDL, sr.getLocalWSDLURL().toExternalForm()));
00239         }
00240 
00241         // 4. Service QName
00242         if (sr.getServiceQName() != null) {
00243             ref.add(new BinaryRefAddr(REF_SERVICE_QNAME, JNDIUtils.getBytesFromObject(sr.getServiceQName())));
00244         }
00245 
00246         // 5. classname -> wsdl:port map
00247         List ports = sr.getPortComponentRefs();
00248         if (!ports.isEmpty()) {
00249             Map map = new Hashtable();
00250             for (Iterator i = ports.iterator(); i.hasNext();) {
00251                 PortComponentRefDesc pcrd = (PortComponentRefDesc) i.next();
00252                 QName wsdlPort = pcrd.getWsdlPort();
00253                 if (wsdlPort != null) {
00254                     map.put(pcrd.getSEI().getName(), wsdlPort);
00255                 }
00256             }
00257             if (!map.isEmpty()) {
00258                 ref.add(new BinaryRefAddr(REF_SERVICE_PORT2WSDL, JNDIUtils.getBytesFromObject(map)));
00259             }
00260         }
00261 
00262         // 6. store call & stubs properties
00263         String portNames = "";
00264         for (Iterator i = sr.getPortComponentRefs().iterator(); i.hasNext();) {
00265             PortComponentRefDesc pcr = (PortComponentRefDesc) i.next();
00266             Properties cProps = pcr.getCallProperties();
00267             Properties sProps = pcr.getStubProperties();
00268 
00269             if (pcr.getWsdlPort() != null) {
00270                 // use call & stub property only if there is a wsdl:port for applying to
00271                 // TODO must be something to add into documentation for this
00272                 String name = pcr.getWsdlPort().getLocalPart();
00273                 if (!cProps.isEmpty()) {
00274                     ref.add(new BinaryRefAddr(REF_SERVICE_CALL_PROPS + "_" + name, JNDIUtils
00275                                     .getBytesFromObject(cProps)));
00276                 }
00277                 if (!sProps.isEmpty()) {
00278                     ref.add(new BinaryRefAddr(REF_SERVICE_STUB_PROPS + "_" + name, JNDIUtils
00279                                     .getBytesFromObject(sProps)));
00280                 }
00281                 if (!sProps.isEmpty() || !cProps.isEmpty()) {
00282                     portNames += name + ",";
00283                 }
00284             }
00285 
00286         }
00287         // delete the last ,
00288         if (portNames.endsWith(",")) {
00289             portNames = portNames.substring(0, portNames.length() - 1);
00290         }
00291         ref.add(new StringRefAddr(REF_SERVICE_WSDL_PORT_LIST, portNames));
00292 
00293         return ref;
00294     }
00295 
00301     private String serializeDOM(Document base) throws IOException {
00302         StringWriter sw = new StringWriter();
00303         XMLSerializer ser = new XMLSerializer(base);
00304         ser.serialize(sw);
00305         return sw.getBuffer().toString();
00306     }
00307 
00312     private void mergeAxisDeployment(Document base, Document doc) {
00313         Element importedDeploymentElement = (Element) base.importNode(doc.getDocumentElement(), true);
00314         NodeList list = importedDeploymentElement.getChildNodes();
00315         // append each Element childnodes
00316         for (int i = 0;  i < list.getLength(); i++) {
00317             if (list.item(i) instanceof Element) {
00318                 base.getDocumentElement().appendChild(list.item(i));
00319             }
00320         }
00321     }
00322 
00330     private String createServiceClassname(ServiceRefDesc sr) {
00331 
00332         String intfName = sr.getServiceInterface().getName();
00333 
00334         if (intfName.equals("javax.xml.rpc.Service")) {
00335             // no generated class
00336             return JONAS_SERVICE_CLASSNAME;
00337         } else {
00338             // generated class
00339             QName qn = sr.getServiceQName();
00340             MappingFile mf = sr.getMappingFile();
00341 
00342             String p = (String) mf.getMappings().get(qn.getNamespaceURI());
00343 
00344             String classname = "";
00345             if (p != null) {
00346                 classname = p + "." + Utils.xmlNameToJavaClass(qn.getLocalPart()) + "Locator";
00347             } else {
00348                 classname = Utils.xmlNameToJavaClass(qn.getLocalPart()) + "Locator";
00349             }
00350 
00351             return classname;
00352         }
00353 
00354     }
00355 
00364     private Document loadAxisDeployment(String filename, ClassLoader cl) throws WSServiceException {
00365 
00366         InputStream is = cl.getResourceAsStream(filename);
00367 
00368         //logger.log(BasicLevel.DEBUG, "classloader : " + cl);
00369 
00370         if (is == null) {
00371             // exception !
00372             String err = i18n.getMessage("JAxisServiceFactory.loadAxisDeployment.configNotFound", filename);
00373             logger.log(BasicLevel.ERROR, err);
00374             throw new WSServiceException(err);
00375         }
00376 
00377         Document doc = null;
00378         try {
00379             doc = XMLUtils.newDocument(is);
00380         } catch (Exception e) {
00381             String err = i18n.getMessage("JAxisServiceFactory.loadAxisDeployment.docCreation", filename);
00382             logger.log(BasicLevel.DEBUG, err);
00383 
00384             throw new WSServiceException(err, e);
00385         }
00386 
00387         return doc;
00388     }
00389 
00401     public Object getObjectInstance(Object refObject, Name name, Context nameCtx, Hashtable env) throws Exception {
00402 
00403         JService instance = null;
00404         Object proxy = null;
00405 
00406         if (refObject instanceof Reference) {
00407             Reference ref = (Reference) refObject;
00408 
00409             // get ClassLoader
00410             ClassLoader cl = Thread.currentThread().getContextClassLoader();
00411             logger.log(BasicLevel.DEBUG, "Context ClassLoader : " + cl);
00412 
00413             // get Class
00414             Class serviceClass = cl.loadClass(ref.getClassName());
00415 
00416             // new Service
00417             BinaryRefAddr bRefQname = (BinaryRefAddr) ref.get(REF_SERVICE_QNAME);
00418 
00419             QName serviceQname = null;
00420             if (bRefQname != null) {
00421                 serviceQname = (QName) JNDIUtils.getObjectFromBytes((byte[]) bRefQname.getContent());
00422             }
00423 
00424             RefAddr refServiceWSDL = ref.get(REF_SERVICE_WSDL);
00425 
00426             String serviceWsdl = null;
00427             if (refServiceWSDL != null) {
00428                 serviceWsdl = (String) refServiceWSDL.getContent();
00429             }
00430 
00431             // Prefill as much as we can
00432             if (JONAS_SERVICE_CLASSNAME.equals(serviceClass.getName())) {
00433 
00434                 // default service class
00435                 logger.log(BasicLevel.DEBUG, "default service class");
00436 
00437                 if ((serviceQname == null) && (serviceWsdl == null)) {
00438                     logger.log(BasicLevel.DEBUG, "Create a new Service instance without params");
00439                     // no param instance
00440                     instance = new JService();
00441 
00442                 } else if ((serviceQname != null) && (serviceWsdl == null)) {
00443                     logger.log(BasicLevel.DEBUG, "Create a new Service instance with only a QName " + serviceQname);
00444                     // serviceQname only
00445                     instance = new JService(serviceQname);
00446 
00447                 } else if ((serviceQname != null) && (serviceWsdl != null)) {
00448                     logger.log(BasicLevel.DEBUG, "Create a new Service instance with QName " + serviceQname
00449                             + "and WSDL " + serviceWsdl);
00450                     // serviceQname + wsdl
00451                     instance = new JService(serviceWsdl, serviceQname);
00452 
00453                 } else {
00454                     logger.log(BasicLevel.DEBUG, "Create a new Service instance with WSDL " + serviceWsdl);
00455                     logger.log(BasicLevel.DEBUG, "Should not occurs !!!");
00456                     // wsdl
00457                     // serviceWsdl, updatedURLs, serviceQname);
00458                     instance = new JService();
00459                 }
00460 
00461             } else {
00462                 logger.log(BasicLevel.DEBUG, "Create a new Generated Service instance");
00463                 logger.log(BasicLevel.DEBUG, "serviceWSDL:" + serviceWsdl + " serviceQName:" + serviceQname);
00464 
00465                 // generated class
00466                 Constructor ctr = serviceClass.getConstructor(new Class[] {String.class, QName.class});
00467                 instance = (JService) ctr.newInstance(new Object[] {serviceWsdl, serviceQname});
00468 
00469                 // we have to update ports endpoints
00470                 // we should have Service WSDL
00471                 // otherwise, no Generated WSDL !
00472                 if (serviceWsdl != null) {
00473                     WSDLFactory factory = WSDLFactory.newInstance();
00474                     WSDLReader reader = factory.newWSDLReader();
00475                     reader.setFeature("javax.wsdl.importDocuments", true);
00476                     Definition def = reader.readWSDL(serviceWsdl);
00477 
00478                     Service service = def.getService(serviceQname);
00479                     Map ports = service.getPorts();
00480                     java.lang.reflect.Method m = serviceClass.getMethod("setEndpointAddress", SETENDPOINTADDRESS_SIG);
00481                     for (Iterator i = ports.keySet().iterator(); i.hasNext();) {
00482                         String portName = (String) i.next();
00483                         Port port = service.getPort(portName);
00484                         String endpoint = getSOAPLocation(port);
00485                         m.invoke(instance, new Object[] {port.getName(), endpoint });
00486                     }
00487                 }
00488             }
00489 
00490             // get port2wsdl map
00491             BinaryRefAddr bRefp2w = (BinaryRefAddr) ref.get(REF_SERVICE_PORT2WSDL);
00492 
00493             if (bRefp2w != null) {
00494                 Map map = (Map) JNDIUtils.getObjectFromBytes((byte[]) bRefp2w.getContent());
00495                 instance.assignSEIClassnameToWSDLPort(map);
00496             }
00497 
00498             // get WSDL_PORT_NAMES
00499             RefAddr portsRef = ref.get(REF_SERVICE_WSDL_PORT_LIST);
00500             String listPorts = null;
00501             if (portsRef != null) {
00502                 listPorts = (String)  portsRef.getContent();
00503 
00504                 if (listPorts != null) {
00505                     // get call properties
00506                     StringTokenizer  strPort = new StringTokenizer(listPorts, ",");
00507                     while (strPort.hasMoreTokens()) {
00508                         String port = strPort.nextToken();
00509 
00510                         // call properties
00511                         BinaryRefAddr bRefcp = (BinaryRefAddr) ref.get(REF_SERVICE_CALL_PROPS + "_" + port);
00512 
00513                         if (bRefcp != null) {
00514                             Properties callProperties = (Properties) JNDIUtils.getObjectFromBytes((byte[]) bRefcp.getContent());
00515                             instance.assignCallProperties(port, callProperties);
00516                         }
00517 
00518                         // stub properties
00519                         BinaryRefAddr bRefsp = (BinaryRefAddr) ref.get(REF_SERVICE_STUB_PROPS + "_" + port);
00520 
00521                         if (bRefsp != null) {
00522                             Properties stubProperties = (Properties) JNDIUtils.getObjectFromBytes((byte[]) bRefsp.getContent());
00523                             instance.assignStubProperties(port, stubProperties);
00524                         }
00525                     }
00526                 }
00527             }
00528             EngineConfiguration ec = getConfiguration(ref);
00529 
00530             // configure the instance
00531             instance.setEngine(new AxisClient(ec));
00532 
00533             JServiceProxy handler = new JServiceProxy(instance);
00534             Class[] serviceInterfaces = serviceClass.getInterfaces();
00535             Class[] interfaces = new Class[serviceInterfaces.length + 1];
00536             for (int i = 0; i < serviceInterfaces.length; i++) {
00537                 interfaces[i] = serviceInterfaces[i];
00538             }
00539             interfaces[serviceInterfaces.length] = javax.xml.rpc.Service.class;
00540             proxy = Proxy.newProxyInstance(cl, interfaces, handler);
00541 
00542         }
00543 
00544         return proxy;
00545     }
00546 
00551     private String getSOAPLocation(Port port) {
00552         String endpoint = null;
00553         List extensions = port.getExtensibilityElements();
00554         for (Iterator i = extensions.iterator(); i.hasNext();) {
00555             ExtensibilityElement ext = (ExtensibilityElement) i.next();
00556             if (ext instanceof SOAPAddress) {
00557                 SOAPAddress addr = (SOAPAddress) ext;
00558                 endpoint = addr.getLocationURI();
00559             }
00560         }
00561         return endpoint;
00562     }
00563 
00570     private EngineConfiguration getConfiguration(Reference ref) throws Exception {
00571         // create a Configuration Object
00572         String conf = (String) ref.get(REF_CLIENT_CONFIG).getContent();
00573         logger.log(BasicLevel.DEBUG, "loaded configuration : " + conf);
00574         return new XMLStringProvider(conf);
00575     }
00576 
00577 }

Generated on Tue Feb 15 15:05:35 2005 for JOnAS by  doxygen 1.3.9.1