00001
00025 package org.objectweb.jonas.ws.axis;
00026
00027 import java.io.File;
00028 import java.io.IOException;
00029 import java.io.InputStream;
00030 import java.io.PrintWriter;
00031 import java.net.HttpURLConnection;
00032 import java.net.URL;
00033 import java.util.Iterator;
00034 import java.util.List;
00035
00036 import javax.naming.InitialContext;
00037 import javax.naming.NamingException;
00038 import javax.servlet.http.HttpServletRequest;
00039 import javax.servlet.http.HttpServletResponse;
00040 import javax.wsdl.Definition;
00041 import javax.wsdl.Port;
00042 import javax.wsdl.Service;
00043 import javax.wsdl.WSDLException;
00044 import javax.wsdl.extensions.ExtensibilityElement;
00045 import javax.wsdl.extensions.soap.SOAPAddress;
00046 import javax.wsdl.factory.WSDLFactory;
00047 import javax.wsdl.xml.WSDLReader;
00048 import javax.wsdl.xml.WSDLWriter;
00049 import javax.xml.namespace.QName;
00050 import javax.xml.parsers.DocumentBuilder;
00051 import javax.xml.parsers.DocumentBuilderFactory;
00052 import javax.xml.parsers.ParserConfigurationException;
00053
00054 import org.w3c.dom.Attr;
00055 import org.w3c.dom.Document;
00056 import org.w3c.dom.Element;
00057 import org.w3c.dom.NodeList;
00058 import org.xml.sax.SAXException;
00059
00060 import org.apache.axis.AxisFault;
00061 import org.apache.axis.Constants;
00062 import org.apache.axis.MessageContext;
00063 import org.apache.axis.i18n.Messages;
00064 import org.apache.axis.server.AxisServer;
00065 import org.apache.axis.transport.http.AbstractQueryStringHandler;
00066 import org.apache.axis.transport.http.HTTPConstants;
00067 import org.apache.axis.utils.XMLUtils;
00068
00069 import org.objectweb.jonas_ws.deployment.api.PortComponentDesc;
00070 import org.objectweb.jonas_ws.deployment.api.ServiceDesc;
00071
00072 import org.objectweb.jonas.ws.WSServiceException;
00073
00079 public class QSUpdateServiceWSDLHandler extends AbstractQueryStringHandler {
00080
00084 private static final String NS_URI_SOAP = "http://schemas.xmlsoap.org/wsdl/soap/";
00085
00089 private static final QName QNAME_SOAP_ADDRESS = new QName(NS_URI_SOAP, "address");
00090
00094 private static final String NS_URI_WSDL = "http://schemas.xmlsoap.org/wsdl/";
00095
00099 private static final String NS_URI_XSD = "http://www.w3.org/2001/XMLSchema";
00100
00104 private static final String PARAM_FILENAME = "filename";
00105
00109 private static final String PARAM_CONTEXT = "context";
00110
00114 private static final String PARAM_JWSDL = "JWSDL";
00115
00119 private static final QName WSDL_DEFINITIONS_QNAME = new QName(NS_URI_WSDL, "definitions");
00120
00124 private ServiceDesc sd = null;
00125
00132 public void invoke(MessageContext msgContext) throws AxisFault {
00133
00134
00135 configureFromContext(msgContext);
00136
00137 AxisServer engine = (AxisServer) msgContext.getProperty(HTTPConstants.PLUGIN_ENGINE);
00138 PrintWriter writer = (PrintWriter) msgContext.getProperty(HTTPConstants.PLUGIN_WRITER);
00139 HttpServletResponse response = (HttpServletResponse) msgContext
00140 .getProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE);
00141 HttpServletRequest request = (HttpServletRequest) msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
00142
00143 InitialContext ctx;
00144 try {
00145 ctx = new InitialContext();
00146 sd = (ServiceDesc) ctx.lookup("java:comp/jonas/" + engine.getName() + "/dd");
00147 } catch (NamingException e) {
00148 throw new AxisFault("Servlet name not found : " + engine.getName(), e);
00149 }
00150
00151 String wsdlFilename = request.getParameter(PARAM_FILENAME);
00152 String context = request.getParameter(PARAM_CONTEXT);
00153 try {
00154 Document doc = null;
00155 if (wsdlFilename == null) {
00156
00157 doc = getDefinitionAsDocument(sd.getWSDL().getDefinition());
00158 wsdlFilename = sd.getWSDL().getName();
00159 String[] pathElements = wsdlFilename.split("/");
00160 if (pathElements.length <= 2) {
00161 throw new WSServiceException("invalid filename");
00162 }
00163
00164 StringBuffer buf = new StringBuffer();
00165 for (int i = 2; i < pathElements.length; i++) {
00166 buf.append(pathElements[i]);
00167 if (i != (pathElements.length - 1)) {
00168
00169 buf.append("/");
00170 }
00171 }
00172
00173
00174 wsdlFilename = buf.toString();
00175 context = ".";
00176 msgContext.setProperty("WSDL", doc);
00177 } else {
00178
00179 doc = (Document) msgContext.getProperty("WSDL_" + wsdlFilename);
00180
00181 if (doc == null) {
00182
00183 doc = getDocument(wsdlFilename, context);
00184 }
00185
00186 msgContext.setProperty("WSDL_" + wsdlFilename, doc);
00187 }
00188
00189 if (doc != null) {
00190
00191 modifyImports(doc, request, new File(context, wsdlFilename).getParent());
00192 Document up2date = updateWSDLPortLocations(doc);
00193 response.setContentType("text/xml; charset=" + XMLUtils.getEncoding().toLowerCase());
00194 reportWSDL(up2date, writer);
00195 } else {
00196
00197 if (log.isDebugEnabled()) {
00198 log.debug("processWsdlRequest: failed to create WSDL");
00199 }
00200 reportNoWSDL(response, writer, "noWSDL02", null);
00201 }
00202 } catch (AxisFault axisFault) {
00203
00204 if (axisFault.getFaultCode().equals(Constants.QNAME_NO_SERVICE_FAULT_CODE)) {
00205
00206 processAxisFault(axisFault);
00207
00208
00209 response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
00210 reportNoWSDL(response, writer, "noWSDL01", axisFault);
00211 } else {
00212
00213 throw axisFault;
00214 }
00215 }
00216 }
00217
00223 private Document getDefinitionAsDocument(Definition definition) throws AxisFault {
00224
00225 try {
00226 WSDLWriter writer = getWSDLWriter();
00227 return writer.getDocument(definition);
00228 } catch (WSDLException e) {
00229 throw new AxisFault(e.getMessage(), e);
00230 }
00231
00232 }
00233
00240 private void modifyImports(Document doc, HttpServletRequest request, String context) {
00241
00242
00243
00244
00245 Element de = doc.getDocumentElement();
00246
00247 NodeList imports = de.getElementsByTagNameNS(NS_URI_WSDL, "import");
00248
00249
00250 for (int i = 0; i < imports.getLength(); i++) {
00251 Element imp = (Element) imports.item(i);
00252 Attr location = imp.getAttributeNode("location");
00253 if (!location.getValue().startsWith("http://")) {
00254
00255 String req = computeUpdatedURL(request, context, location);
00256
00257 log.debug("Replacing wsdl:location '" + location.getValue() + "' with '" + req.toString() + "'");
00258 location.setValue(req.toString());
00259 }
00260 }
00261
00262
00263 updateSchema(de, "include", request, context);
00264
00265 updateSchema(de, "import", request, context);
00266
00267
00268 NodeList types = de.getElementsByTagNameNS(NS_URI_WSDL, "types");
00269
00270 if (types.getLength() != 0) {
00271
00272
00273 Element typesElement = (Element) types.item(0);
00274
00275
00276 NodeList schemasList = typesElement.getElementsByTagNameNS(NS_URI_XSD, "schema");
00277 for (int i = 0; i < schemasList.getLength(); i++) {
00278 Element schema = (Element) schemasList.item(i);
00279 updateSchema(schema, "include", request, context);
00280 updateSchema(schema, "import", request, context);
00281 }
00282 }
00283 }
00284
00291 private String computeUpdatedURL(HttpServletRequest request, String context, Attr location) {
00292 StringBuffer req = request.getRequestURL();
00293 req.append("?" + PARAM_JWSDL);
00294 req.append("&" + PARAM_FILENAME + "=" + location.getValue());
00295 req.append("&" + PARAM_CONTEXT + "=" + context);
00296 return req.toString();
00297 }
00298
00305 private void updateSchema(Element schema, String elementName, HttpServletRequest request, String context) {
00306
00307 NodeList elements = schema.getElementsByTagNameNS(NS_URI_XSD, elementName);
00308
00309
00310 for (int i = 0; i < elements.getLength(); i++) {
00311 Element e = (Element) elements.item(i);
00312 Attr location = e.getAttributeNode("schemaLocation");
00313 if ((location != null) && (!location.getValue().startsWith("http://"))) {
00314
00315 String req = computeUpdatedURL(request, context, location);
00316
00317 log.debug("Replacing xsd:schemaLocation '" + location.getValue() + "' with '" + req.toString() + "'");
00318 location.setValue(req.toString());
00319 }
00320 }
00321 }
00322
00330 private Document getDocument(String wsdlFilename, String context) throws AxisFault {
00331
00332
00333
00334
00335
00336 ClassLoader cl = Thread.currentThread().getContextClassLoader();
00337 URL res = cl.getResource(context + "/" + wsdlFilename);
00338
00339 Document doc = null;
00340 if (res != null) {
00341 try {
00342 doc = createDocument(res.openStream());
00343 } catch (IOException ioe) {
00344 throw new AxisFault("Cannot open requested URL : " + res);
00345 }
00346 } else {
00347 throw new AxisFault("Cannot find requested document : " + wsdlFilename);
00348 }
00349
00350 return doc;
00351 }
00352
00358 private Document createDocument(InputStream stream) throws AxisFault {
00359 try {
00360 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
00361 factory.setNamespaceAware(true);
00362 factory.setValidating(false);
00363 DocumentBuilder builder = factory.newDocumentBuilder();
00364 return builder.parse(stream);
00365 } catch (ParserConfigurationException pce) {
00366 throw new AxisFault(pce.getMessage(), pce);
00367 } catch (SAXException se) {
00368 throw new AxisFault(se.getMessage(), se);
00369 } catch (IOException ioe) {
00370 throw new AxisFault(ioe.getMessage(), ioe);
00371 }
00372 }
00373
00380 private Document updateWSDLPortLocations(Document doc) throws AxisFault {
00381 log.debug("Entering updateWSDL");
00382
00383 QName docQname = new QName(doc.getDocumentElement().getNamespaceURI(), doc.getDocumentElement().getLocalName());
00384
00385
00386 if (WSDL_DEFINITIONS_QNAME.equals(docQname)) {
00387 try {
00388 WSDLReader reader = getWSDLReader();
00389
00390 Definition def = reader.readWSDL(null, doc);
00391
00396 QName sQName = sd.getWSDL().getServiceQname();
00397 Service s = def.getService(sQName);
00398 if (s != null) {
00399
00400 List portsComp = sd.getPortComponents();
00401 for (Iterator i = portsComp.iterator(); i.hasNext();) {
00402 PortComponentDesc pcd = (PortComponentDesc) i.next();
00403 URL endpoint = pcd.getEndpointURL();
00404 QName portQName = pcd.getQName();
00405
00406 Port port = s.getPort(portQName.getLocalPart());
00407
00408 if (port != null) {
00409
00410 List ext = port.getExtensibilityElements();
00411 for (Iterator it = ext.iterator(); it.hasNext();) {
00412 ExtensibilityElement element = (ExtensibilityElement) it.next();
00413 if (element.getElementType().equals(QNAME_SOAP_ADDRESS)) {
00414 SOAPAddress sa = (SOAPAddress) element;
00415 sa.setLocationURI(endpoint.toExternalForm());
00416 log.debug("Update port soap:location with " + endpoint);
00417 }
00418 }
00419 } else {
00420 log.warn("Cannot find wsdl:port '" + portQName.getLocalPart() + "' in wsdl:service "
00421 + s.getQName());
00422 }
00423 }
00424 }
00425
00426 return WSDLFactory.newInstance().newWSDLWriter().getDocument(def);
00427 } catch (WSDLException wsdle) {
00428 throw new AxisFault("Cannot read WSDL Document", wsdle);
00429 }
00430 } else {
00431
00432
00433 return doc;
00434 }
00435
00436 }
00437
00442 private WSDLReader getWSDLReader() throws WSDLException {
00443 WSDLFactory factory = WSDLFactory.newInstance();
00444 WSDLReader reader = factory.newWSDLReader();
00445 reader.setFeature("javax.wsdl.importDocuments", false);
00446 return reader;
00447 }
00448
00453 private WSDLWriter getWSDLWriter() throws WSDLException {
00454 WSDLFactory factory = WSDLFactory.newInstance();
00455 return factory.newWSDLWriter();
00456 }
00457
00463 public void reportWSDL(Document doc, PrintWriter writer) {
00464 XMLUtils.PrettyDocumentToWriter(doc, writer);
00465 }
00466
00474 public void reportNoWSDL(HttpServletResponse res, PrintWriter writer, String moreDetailCode, AxisFault axisFault) {
00475 res.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
00476 res.setContentType("text/html");
00477
00478 writer.println("<h2>" + Messages.getMessage("error00") + "</h2>");
00479 writer.println("<p>" + Messages.getMessage("noWSDL00") + "</p>");
00480
00481 if (moreDetailCode != null) {
00482 writer.println("<p>" + Messages.getMessage(moreDetailCode) + "</p>");
00483 }
00484
00485 if (axisFault != null && isDevelopment()) {
00486
00487 writeFault(writer, axisFault);
00488 }
00489 }
00490
00491 }