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
00176 Reference ref = new Reference(classname, getClass().getName(), null);
00177
00178 Document base = loadAxisDeployment(CLIENT_CONFIG_WSDD, cl);
00179
00180
00181 String clientConfig = sr.getParam(AXIS_CLIENT_CONFIG_PARAM);
00182
00183
00184 if (clientConfig != null) {
00185
00186 Document doc = loadAxisDeployment(clientConfig, cl);
00187
00188
00189 mergeAxisDeployment(base, doc);
00190 }
00191
00192
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
00205 for (Iterator i = sr.getPortComponentRefs().iterator(); i.hasNext();) {
00206 PortComponentRefDesc pcr = (PortComponentRefDesc) i.next();
00207 PortComponentDesc referencedPortComponent = pcr.getPortComponentDesc();
00208
00209
00210 if (referencedPortComponent != null) {
00211
00212 logger.log(BasicLevel.DEBUG, "Find a port-component-link in port-component-ref" + pcr.getSEI());
00213
00214 URL url = referencedPortComponent.getEndpointURL();
00215 if (url == null) {
00216
00217
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
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
00242 if (sr.getServiceQName() != null) {
00243 ref.add(new BinaryRefAddr(REF_SERVICE_QNAME, JNDIUtils.getBytesFromObject(sr.getServiceQName())));
00244 }
00245
00246
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
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
00271
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
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
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
00336 return JONAS_SERVICE_CLASSNAME;
00337 } else {
00338
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
00369
00370 if (is == null) {
00371
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
00410 ClassLoader cl = Thread.currentThread().getContextClassLoader();
00411 logger.log(BasicLevel.DEBUG, "Context ClassLoader : " + cl);
00412
00413
00414 Class serviceClass = cl.loadClass(ref.getClassName());
00415
00416
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
00432 if (JONAS_SERVICE_CLASSNAME.equals(serviceClass.getName())) {
00433
00434
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
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
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
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
00457
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
00466 Constructor ctr = serviceClass.getConstructor(new Class[] {String.class, QName.class});
00467 instance = (JService) ctr.newInstance(new Object[] {serviceWsdl, serviceQname});
00468
00469
00470
00471
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
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
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
00506 StringTokenizer strPort = new StringTokenizer(listPorts, ",");
00507 while (strPort.hasMoreTokens()) {
00508 String port = strPort.nextToken();
00509
00510
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
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
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
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 }