Return-Path: Delivered-To: apmail-incubator-cxf-commits-archive@locus.apache.org Received: (qmail 52707 invoked from network); 20 Sep 2006 02:16:49 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 20 Sep 2006 02:16:49 -0000 Received: (qmail 14746 invoked by uid 500); 20 Sep 2006 02:16:48 -0000 Delivered-To: apmail-incubator-cxf-commits-archive@incubator.apache.org Received: (qmail 14635 invoked by uid 500); 20 Sep 2006 02:16:48 -0000 Mailing-List: contact cxf-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: cxf-dev@incubator.apache.org Delivered-To: mailing list cxf-commits@incubator.apache.org Received: (qmail 14626 invoked by uid 99); 20 Sep 2006 02:16:47 -0000 Received: from idunn.apache.osuosl.org (HELO idunn.apache.osuosl.org) (140.211.166.84) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 19 Sep 2006 19:16:47 -0700 X-ASF-Spam-Status: No, hits=-9.8 required=5.0 tests=ALL_TRUSTED,NO_REAL_NAME Received: from ([140.211.166.113:60997] helo=eris.apache.org) by idunn.apache.osuosl.org (ecelerity 2.1 r(10620)) with ESMTP id E1/82-00639-A84A0154 for ; Tue, 19 Sep 2006 19:16:42 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id A42C41A981A; Tue, 19 Sep 2006 19:16:40 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r448031 - in /incubator/cxf/trunk/rt/frontend/jaxws/src/main: java/org/apache/cxf/jaxws/servlet/ resources/META-INF/ Date: Wed, 20 Sep 2006 02:16:40 -0000 To: cxf-commits@incubator.apache.org From: ffang@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20060920021640.A42C41A981A@eris.apache.org> X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: ffang Date: Tue Sep 19 19:16:39 2006 New Revision: 448031 URL: http://svn.apache.org/viewvc?view=rev&rev=448031 Log: [JIRA CXF-68] get servlet working - phase 1 Added: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractCachedOutputStream.java (with props) incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractWrappedOutputStream.java (with props) incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/CXFServlet.java (with props) incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletDestination.java (with props) incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletTransportFactory.java (with props) incubator/cxf/trunk/rt/frontend/jaxws/src/main/resources/META-INF/bus-extensions.xml (with props) Added: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractCachedOutputStream.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractCachedOutputStream.java?view=auto&rev=448031 ============================================================================== --- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractCachedOutputStream.java (added) +++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractCachedOutputStream.java Tue Sep 19 19:16:39 2006 @@ -0,0 +1,196 @@ +/** + * 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.cxf.jaxws.servlet; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; + +public abstract class AbstractCachedOutputStream extends OutputStream { + + protected OutputStream currentStream; + + private long threshold = 8 * 1024; + + private int totalLength; + + private boolean inmem; + + private File tempFile; + + private File outputDir; + + public AbstractCachedOutputStream(PipedInputStream stream) throws IOException { + currentStream = new PipedOutputStream(stream); + inmem = true; + } + + public AbstractCachedOutputStream() { + currentStream = new ByteArrayOutputStream(); + inmem = true; + } + + /** + * Perform any actions required on stream flush (freeze headers, reset + * output stream ... etc.) + */ + protected abstract void doFlush() throws IOException; + + public void flush() throws IOException { + currentStream.flush(); + doFlush(); + } + + /** + * Perform any actions required on stream closure (handle response etc.) + */ + protected abstract void doClose() throws IOException; + + public void close() throws IOException { + currentStream.close(); + doClose(); + } + + public boolean equals(Object obj) { + return currentStream.equals(obj); + } + + /** + * Replace the original stream with the new one, when with Attachment, needs + * to replace the xml writer stream with the stream used by + * AttachmentSerializer Or Copy the cached output stream to the "real" + * output stream, i.e. onto the wire. + * + * @param realOS + * the real output stream + * @throws IOException + */ + public void resetOut(OutputStream out, boolean copyOldContent) throws IOException { + ByteArrayOutputStream bout = (ByteArrayOutputStream) currentStream; + if (copyOldContent && bout.size() > 0) { + bout.writeTo(out); + } + currentStream = out; + } + + /** + * @return the underlying output stream + */ + public OutputStream getOut() { + return currentStream; + } + + public int hashCode() { + return currentStream.hashCode(); + } + + public String toString() { + return currentStream.toString(); + } + + protected abstract void onWrite() throws IOException; + + public void write(byte[] b, int off, int len) throws IOException { + onWrite(); + this.totalLength += len; + if (inmem && totalLength > threshold) { + createFileOutputStream(); + } + currentStream.write(b, off, len); + } + + public void write(byte[] b) throws IOException { + onWrite(); + this.totalLength += b.length; + if (inmem && totalLength > threshold) { + createFileOutputStream(); + } + currentStream.write(b); + } + + public void write(int b) throws IOException { + onWrite(); + this.totalLength++; + if (inmem && totalLength > threshold) { + createFileOutputStream(); + } + currentStream.write(b); + } + + private void createFileOutputStream() throws IOException { + byte[] bytes = ((ByteArrayOutputStream) currentStream).toByteArray(); + if (outputDir == null) { + tempFile = File.createTempFile("att", "tmp"); + } else { + tempFile = File.createTempFile("att", "tmp", outputDir); + } + currentStream = new BufferedOutputStream(new FileOutputStream(tempFile)); + currentStream.write(bytes); + inmem = false; + } + + public File getTempFile() { + return tempFile; + } + + public InputStream getInputStream() throws IOException { + if (inmem) { + if (currentStream instanceof ByteArrayOutputStream) { + return new ByteArrayInputStream(((ByteArrayOutputStream)currentStream).toByteArray()); + } else if (currentStream instanceof PipedOutputStream) { + return new PipedInputStream((PipedOutputStream)currentStream); + } else { + return null; + } + } else { + try { + return new FileInputStream(tempFile); + } catch (FileNotFoundException e) { + throw new IOException("Cached file was deleted, " + e.toString()); + } + } + } + + public void dispose() { + if (!inmem) { + tempFile.delete(); + } + } + + public void setOutputDir(File outputDir) throws IOException { + this.outputDir = outputDir; + createFileOutputStream(); + } + + public void setThreshold(long threshold) { + this.threshold = threshold; + } + +} Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractCachedOutputStream.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractCachedOutputStream.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Added: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractWrappedOutputStream.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractWrappedOutputStream.java?view=auto&rev=448031 ============================================================================== --- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractWrappedOutputStream.java (added) +++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractWrappedOutputStream.java Tue Sep 19 19:16:39 2006 @@ -0,0 +1,45 @@ +/** + * 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.cxf.jaxws.servlet; + + +import org.apache.cxf.message.Message; + +public abstract class AbstractWrappedOutputStream extends AbstractCachedOutputStream { + + protected Message outMessage; + private boolean flushed; + + AbstractWrappedOutputStream(Message m) { + super(); + outMessage = m; + } + + /** + * @return true if already flushed + */ + protected boolean alreadyFlushed() { + boolean ret = flushed; + flushed = true; + return ret; + } + +} Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractWrappedOutputStream.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/AbstractWrappedOutputStream.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Added: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/CXFServlet.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/CXFServlet.java?view=auto&rev=448031 ============================================================================== --- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/CXFServlet.java (added) +++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/CXFServlet.java Tue Sep 19 19:16:39 2006 @@ -0,0 +1,288 @@ +/** + * 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.cxf.jaxws.servlet; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import org.apache.cxf.Bus; + +import org.apache.cxf.bus.CXFBusFactory; +import org.apache.cxf.jaxws.EndpointImpl; +import org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean; +import org.apache.cxf.jaxws.support.JaxwsImplementorInfo; +import org.apache.cxf.service.Service; +import org.apache.cxf.service.model.EndpointInfo; +import org.apache.cxf.transport.DestinationFactory; +import org.apache.cxf.transport.DestinationFactoryManager; +import org.apache.cxf.ws.addressing.EndpointReferenceType; +import org.apache.cxf.wsdl.EndpointReferenceUtils; + + + + +public class CXFServlet extends HttpServlet { + static final String HTTP_REQUEST = + CXFServlet.class.getName() + ".REQUEST"; + static final String HTTP_RESPONSE = + CXFServlet.class.getName() + ".RESPONSE"; + + static final Map> BUS_MAP = new Hashtable>(); + + protected Bus bus; + protected Map servantMap + = new HashMap(); + + + EndpointReferenceType reference; + ServletTransportFactory servletTransportFactory; + EndpointImpl ep; + EndpointInfo ei; + + public void init(ServletConfig servletConfig) throws ServletException { + super.init(servletConfig); + + List list = new ArrayList(); + String busid = servletConfig.getInitParameter("bus.id"); + if (null != busid) { + list.add("-BUSid"); + list.add(busid); + WeakReference ref = BUS_MAP.get(busid); + if (null != ref) { + bus = ref.get(); + } + } + if (null == bus) { + //bus = Bus.init(list.toArray(new String[list.size()])); + bus = new CXFBusFactory().createBus(); + + } + if (null != busid) { + BUS_MAP.put(busid, new WeakReference(bus)); + } + + InputStream ins = servletConfig.getServletContext() + .getResourceAsStream("/WEB-INF/cxf-servlet.xml"); + if (ins != null) { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + builderFactory.setNamespaceAware(true); + builderFactory.setValidating(false); + + + try { + Document doc = builderFactory.newDocumentBuilder().parse(ins); + Node nd = doc.getDocumentElement().getFirstChild(); + while (nd != null) { + if ("endpoint".equals(nd.getLocalName())) { + loadEndpoint(servletConfig, nd); + } + nd = nd.getNextSibling(); + } + } catch (SAXException ex) { + // TODO Auto-generated catch block + ex.printStackTrace(); + } catch (IOException ex) { + // TODO Auto-generated catch block + ex.printStackTrace(); + } catch (ParserConfigurationException ex) { + // TODO Auto-generated catch block + ex.printStackTrace(); + } + } + } + + private void deregisterTransport(String transportId) { + bus.getExtension(DestinationFactoryManager.class).deregisterDestinationFactory(transportId); + } + + /** + * @return + */ + protected DestinationFactory createServletTransportFactory() { + if (servletTransportFactory == null) { + servletTransportFactory = new ServletTransportFactory(bus, reference); + } + return servletTransportFactory; + } + + private void registerTransport(DestinationFactory factory, String namespace) { + bus.getExtension(DestinationFactoryManager.class).registerDestinationFactory( + namespace, + factory); + } + + public void loadEndpoint(String implName, + String serviceName, + String wsdlName, + String portName, + String urlPat) { + + try { + + URL url = null; + if (wsdlName != null) { + try { + url = getServletConfig().getServletContext().getResource(wsdlName); + } catch (MalformedURLException ex) { + try { + url = new URL(wsdlName); + } catch (MalformedURLException ex2) { + try { + url = getServletConfig().getServletContext().getResource("/" + wsdlName); + } catch (MalformedURLException ex3) { + url = null; + } + } + } + } + Class cls = Class.forName(implName, false, Thread.currentThread().getContextClassLoader()); + Object impl = cls.newInstance(); + reference = EndpointReferenceUtils + .getEndpointReference(url, + QName.valueOf(serviceName), + portName); + + + + ep = new EndpointImpl(bus, impl, url.toString()); + replaceDestionFactory(); +// doesn't really matter what URL is used here + ep.publish("http://localhost" + (urlPat.charAt(0) == '/' ? "" : "/") + urlPat); + JaxwsImplementorInfo implInfo = new JaxwsImplementorInfo(impl.getClass()); + // build up the Service model + JaxWsServiceFactoryBean serviceFactory = new JaxWsServiceFactoryBean(implInfo); + serviceFactory.setBus(bus); + serviceFactory.setServiceClass(impl.getClass()); + Service service = serviceFactory.create(); + + // create the endpoint + QName endpointName = implInfo.getEndpointName(); + ei = service.getServiceInfo().getEndpoint(endpointName); + + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + } catch (InstantiationException ex) { + ex.printStackTrace(); + } catch (IllegalAccessException ex) { + ex.printStackTrace(); + } + } + + private void replaceDestionFactory() { + DestinationFactory factory = createServletTransportFactory(); + deregisterTransport("http://schemas.xmlsoap.org/wsdl/soap/"); + deregisterTransport("http://schemas.xmlsoap.org/wsdl/soap/http"); + deregisterTransport("http://schemas.xmlsoap.org/wsdl/http/"); + deregisterTransport("http://celtix.objectweb.org/bindings/xmlformat"); + deregisterTransport("http://celtix.objectweb.org/transports/http/configuration"); + registerTransport(factory, "http://schemas.xmlsoap.org/wsdl/soap/"); + registerTransport(factory, "http://schemas.xmlsoap.org/wsdl/soap/http"); + registerTransport(factory, "http://schemas.xmlsoap.org/wsdl/http/"); + registerTransport(factory, "http://celtix.objectweb.org/bindings/xmlformat"); + registerTransport(factory, "http://celtix.objectweb.org/transports/http/configuration"); + } + + public void loadEndpoint(ServletConfig servletConfig, Node node) { + Element el = (Element)node; + String implName = el.getAttribute("implementation"); + String serviceName = el.getAttribute("service"); + String wsdlName = el.getAttribute("wsdl"); + String portName = el.getAttribute("port"); + String urlPat = el.getAttribute("url-pattern"); + + loadEndpoint(implName, serviceName, wsdlName, portName, urlPat); + } + + public void destroy() { + String s = bus.getId(); + BUS_MAP.remove(s); + + bus.shutdown(true); + } + + void addServant(URL url, ServletDestination servant) { + servantMap.put(url.getPath(), servant); + } + void removeServant(URL url, ServletDestination servant) { + servantMap.remove(url.getPath()); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { + System.out.println("do post is invoked"); + try { + ((ServletDestination)ep.getServer().getDestination()).doService(request, response); + } catch (IOException e) { + e.printStackTrace(); + } + /*ServletServerTransport tp = servantMap.get(request.getPathInfo()); + if (tp == null) { + throw new ServletException("Unknown servlet mapping " + request.getPathInfo()); + } + try { + tp.doPost(request, response); + } catch (IOException ex) { + throw new ServletException(ex.getMessage()); + }*/ + } + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { + System.out.println("do get is invoked"); + try { + ((ServletDestination)servletTransportFactory. + getDestination(ei)).doService(request, response); + } catch (IOException e) { + e.printStackTrace(); + } + /*ServletServerTransport tp = servantMap.get(request.getPathInfo()); + if (tp == null) { + throw new ServletException("Unknown servlet mapping " + request.getPathInfo()); + } + try { + tp.doGet(request, response); + } catch (IOException ex) { + throw new ServletException(ex.getMessage()); + }*/ + } + +} Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/CXFServlet.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/CXFServlet.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Added: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletDestination.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletDestination.java?view=auto&rev=448031 ============================================================================== --- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletDestination.java (added) +++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletDestination.java Tue Sep 19 19:16:39 2006 @@ -0,0 +1,471 @@ +/** + * 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.cxf.jaxws.servlet; + + + + + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.wsdl.Definition; +import javax.wsdl.Port; +import javax.wsdl.extensions.ExtensibilityElement; +import javax.wsdl.extensions.soap.SOAPAddress; +import javax.wsdl.factory.WSDLFactory; +import javax.wsdl.xml.WSDLWriter; + +import org.apache.cxf.Bus; +import org.apache.cxf.common.util.Base64Exception; +import org.apache.cxf.common.util.Base64Utility; +import org.apache.cxf.configuration.security.AuthorizationPolicy; +import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageImpl; +import org.apache.cxf.service.model.EndpointInfo; +import org.apache.cxf.transport.Conduit; +import org.apache.cxf.transport.ConduitInitiator; +import org.apache.cxf.transport.Destination; +import org.apache.cxf.transport.MessageObserver; +import org.apache.cxf.ws.addressing.EndpointReferenceType; + + +import org.apache.cxf.wsdl11.ServiceWSDLBuilder; +import org.xmlsoap.schemas.wsdl.http.AddressType; + + +public class ServletDestination implements Destination { + + public static final String HTTP_REQUEST = + ServletDestination.class.getName() + ".REQUEST"; + public static final String HTTP_RESPONSE = + ServletDestination.class.getName() + ".RESPONSE"; + + static final Logger LOG = Logger.getLogger(ServletDestination.class.getName()); + + private static final long serialVersionUID = 1L; + + protected final Bus bus; + protected final ConduitInitiator conduitInitiator; + //protected final HTTPDestinationConfiguration config; + protected final EndpointInfo endpointInfo; + protected final EndpointReferenceType reference; + protected String name; + protected URL nurl; + protected MessageObserver incomingObserver; + + + /** + * Constructor, allowing subsititution of configuration. + * + * @param b the associated Bus + * @param ci the associated conduit initiator + * @param ei the endpoint info of the destination + * @param cfg the configuration + * @throws IOException + */ + public ServletDestination(Bus b, + ConduitInitiator ci, + EndpointInfo ei, + EndpointReferenceType ref) + throws IOException { + bus = b; + conduitInitiator = ci; + endpointInfo = ei; + + reference = ref; + + // get url (publish address) from endpoint reference + /*nurl = new URL(EndpointReferenceUtils.getAddress(ref)); + + + name = nurl.getPath();*/ + + + } + + /** + * @return the reference associated with this Destination + */ + public EndpointReferenceType getAddress() { + return reference; + } + + /** + * Cache HTTP headers in message. + * + * @param message the current message + */ + protected void setHeaders(Message message) { + Map> requestHeaders = new HashMap>(); + copyRequestHeaders(message, requestHeaders); + message.put(Message.PROTOCOL_HEADERS, requestHeaders); + + if (requestHeaders.containsKey("Authorization")) { + List authorizationLines = requestHeaders.get("Authorization"); + String credentials = authorizationLines.get(0); + String authType = credentials.split(" ")[0]; + if ("Basic".equals(authType)) { + String authEncoded = credentials.split(" ")[1]; + try { + String authDecoded = new String(Base64Utility.decode(authEncoded)); + String authInfo[] = authDecoded.split(":"); + String username = authInfo[0]; + String password = authInfo[1]; + + AuthorizationPolicy policy = new AuthorizationPolicy(); + policy.setUserName(username); + policy.setPassword(password); + + message.put(AuthorizationPolicy.class, policy); + } catch (Base64Exception ex) { + //ignore, we'll leave things alone. They can try decoding it themselves + } + } + } + + } + + @SuppressWarnings("unchecked") + protected void updateResponseHeaders(Message message) { + Map> responseHeaders = + (Map>)message.get(Message.PROTOCOL_HEADERS); + if (responseHeaders == null) { + responseHeaders = new HashMap>(); + message.put(Message.PROTOCOL_HEADERS, responseHeaders); + } + } + + + + /** + * Register a message observer for incoming messages. + * + * @param observer the observer to notify on receipt of incoming + */ + public synchronized void setMessageObserver(MessageObserver observer) { + incomingObserver = observer; + } + + /** + * Retreive a back-channel Conduit, which must be policy-compatible + * with the current Message and associated Destination. For example + * compatible Quality of Protection must be asserted on the back-channel. + * This would generally only be an issue if the back-channel is decoupled. + * + * @param inMessage the current inbound message (null to indicate a + * disassociated back-channel) + * @param partialResponse in the decoupled case, this is expected to be the + * outbound Message to be sent over the in-built back-channel. + * @param address the backchannel address (null to indicate anonymous) + * @return a suitable Conduit + */ + public Conduit getBackChannel(Message inMessage, + Message partialResponse, + EndpointReferenceType address) throws IOException { + HttpServletResponse response = (HttpServletResponse)inMessage.get(HTTP_RESPONSE); + Conduit backChannel = null; + if (address == null) { + backChannel = new BackChannelConduit(address, response); + } else { + if (partialResponse != null) { + // setup the outbound message to for 202 Accepted + partialResponse.put(Message.RESPONSE_CODE, + HttpURLConnection.HTTP_ACCEPTED); + backChannel = new BackChannelConduit(address, response); + } else { + backChannel = conduitInitiator.getConduit(endpointInfo, address); + // ensure decoupled back channel input stream is closed + backChannel.setMessageObserver(new MessageObserver() { + public void onMessage(Message m) { + if (m.getContentFormats().contains(InputStream.class)) { + InputStream is = m.getContent(InputStream.class); + try { + is.close(); + } catch (Exception e) { + // ignore + } + } + } + }); + } + } + return backChannel; + } + + /** + * Shutdown the Destination, i.e. stop accepting incoming messages. + */ + public void shutdown() { + } + + /** + * Copy the request headers into the message. + * + * @param message the current message + * @param headers the current set of headers + */ + protected void copyRequestHeaders(Message message, + Map> headers) { + + } + + /** + * Copy the response headers into the response. + * + * @param message the current message + * @param headers the current set of headers + */ + protected void copyResponseHeaders(Message message, HttpServletResponse response) { + } + + protected void doService(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + + + if ("GET".equals(req.getMethod())) { + doGet(req, resp); + } else { + doPost(req, resp); + } + + + // REVISIT: service on executor if associated with endpoint + //serviceRequest(req, resp); + } + + private void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + try { + if (LOG.isLoggable(Level.INFO)) { + LOG.info("Service http request on thread: " + Thread.currentThread()); + } + + MessageImpl inMessage = new MessageImpl(); + inMessage.setContent(InputStream.class, req.getInputStream()); + inMessage.put(HTTP_REQUEST, req); + inMessage.put(HTTP_RESPONSE, resp); + inMessage.put(Message.HTTP_REQUEST_METHOD, req.getMethod()); + inMessage.put(Message.PATH_INFO, req.getPathInfo()); + inMessage.put(Message.QUERY_STRING, req.getQueryString()); + + setHeaders(inMessage); + + inMessage.setDestination(this); + + + incomingObserver.onMessage(inMessage); + + } finally { + if (LOG.isLoggable(Level.INFO)) { + LOG.info("Finished servicing http request on thread: " + Thread.currentThread()); + } + } + + } + + private void doGet(HttpServletRequest req, HttpServletResponse resp) { + try { + + + resp.setHeader("Content-Type", "text/xml"); + + OutputStream os = resp.getOutputStream(); + + WSDLWriter wsdlWriter = WSDLFactory.newInstance().newWSDLWriter(); + Definition def = + ServiceWSDLBuilder.getServiceWSDLBuilder().buildDefinition(endpointInfo.getService()); + Port port = def.getService( + endpointInfo.getService().getName()).getPort( + endpointInfo.getName().getLocalPart()); + List exts = port.getExtensibilityElements(); + if (exts.size() > 0) { + ExtensibilityElement el = (ExtensibilityElement)exts.get(0); + if (el instanceof SOAPAddress) { + SOAPAddress add = (SOAPAddress)el; + add.setLocationURI(req.getRequestURL().toString()); + } + if (el instanceof AddressType) { + AddressType add = (AddressType)el; + add.setLocation(req.getRequestURL().toString()); + } + } + + wsdlWriter.writeWSDL(def, os); + resp.getOutputStream().flush(); + return; + } catch (Exception ex) { + + ex.printStackTrace(); + } + } + + protected class BackChannelConduit implements Conduit { + + protected HttpServletResponse response; + protected EndpointReferenceType target; + + BackChannelConduit(EndpointReferenceType ref, HttpServletResponse resp) { + response = resp; + target = ref; + } + public void close(Message msg) throws IOException { + msg.getContent(OutputStream.class).close(); + } + + /** + * Register a message observer for incoming messages. + * + * @param observer the observer to notify on receipt of incoming + */ + public void setMessageObserver(MessageObserver observer) { + // shouldn't be called for a back channel conduit + } + + /** + * Send an outbound message, assumed to contain all the name-value + * mappings of the corresponding input message (if any). + * + * @param message the message to be sent. + */ + public void send(Message message) throws IOException { + message.put(HTTP_RESPONSE, response); + message.setContent(OutputStream.class, + new WrappedOutputStream(message, response)); + } + + /** + * @return the reference associated with the target Destination + */ + public EndpointReferenceType getTarget() { + return target; + } + + /** + * Retreive the back-channel Destination. + * + * @return the backchannel Destination (or null if the backchannel is + * built-in) + */ + public Destination getBackChannel() { + return null; + } + + /** + * Close the conduit + */ + public void close() { + } + } + + private class WrappedOutputStream extends AbstractWrappedOutputStream { + + protected HttpServletResponse response; + + WrappedOutputStream(Message m, HttpServletResponse resp) { + super(m); + response = resp; + } + + /** + * Perform any actions required on stream flush (freeze headers, + * reset output stream ... etc.) + */ + protected void doFlush() throws IOException { + OutputStream responseStream = flushHeaders(outMessage); + if (null != responseStream && !alreadyFlushed()) { + resetOut(responseStream, true); + } + } + + /** + * Perform any actions required on stream closure (handle response etc.) + */ + protected void doClose() { + commitResponse(); + } + + protected void onWrite() throws IOException { + } + + private void commitResponse() { + try { + response.flushBuffer(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + protected OutputStream flushHeaders(Message outMessage) throws IOException { + updateResponseHeaders(outMessage); + Object responseObj = outMessage.get(HTTP_RESPONSE); + OutputStream responseStream = null; + if (responseObj instanceof HttpServletResponse) { + HttpServletResponse response = (HttpServletResponse)responseObj; + + Integer i = (Integer)outMessage.get(Message.RESPONSE_CODE); + if (i != null) { + int status = i.intValue(); + if (status == HttpURLConnection.HTTP_INTERNAL_ERROR) { + response.setStatus(status, "Fault Occurred"); + } else if (status == HttpURLConnection.HTTP_ACCEPTED) { + response.setStatus(status, "Accepted"); + } else { + response.setStatus(status); + } + } else { + response.setStatus(HttpURLConnection.HTTP_OK); + } + + copyResponseHeaders(outMessage, response); + responseStream = response.getOutputStream(); + + if (isOneWay(outMessage)) { + response.flushBuffer(); + } + } else { + LOG.log(Level.WARNING, "UNEXPECTED_RESPONSE_TYPE_MSG", responseObj.getClass()); + throw new IOException("UNEXPECTED_RESPONSE_TYPE_MSG" + responseObj.getClass()); + } + + if (isOneWay(outMessage)) { + outMessage.remove(HTTP_RESPONSE); + } + return responseStream; + } + + protected boolean isOneWay(Message message) { + Boolean oneway = (Boolean)message.get(org.apache.cxf.message.Message.ONEWAY_MESSAGE); + return oneway != null && oneway.booleanValue(); + } + +} Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletDestination.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletDestination.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Added: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletTransportFactory.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletTransportFactory.java?view=auto&rev=448031 ============================================================================== --- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletTransportFactory.java (added) +++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletTransportFactory.java Tue Sep 19 19:16:39 2006 @@ -0,0 +1,93 @@ +/** + * 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.cxf.jaxws.servlet; + +import java.io.IOException; +import java.util.Collection; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; + +import org.apache.cxf.Bus; +import org.apache.cxf.service.model.EndpointInfo; +import org.apache.cxf.transport.Conduit; +import org.apache.cxf.transport.ConduitInitiator; +import org.apache.cxf.transport.ConduitInitiatorManager; +import org.apache.cxf.transport.Destination; +import org.apache.cxf.transport.DestinationFactory; +import org.apache.cxf.transport.DestinationFactoryManager; +import org.apache.cxf.ws.addressing.EndpointReferenceType; + +public class ServletTransportFactory implements ConduitInitiator, DestinationFactory { + + Bus bus; + EndpointReferenceType reference; + @Resource + Collection activationNamespaces; + + + public ServletTransportFactory(Bus b, EndpointReferenceType ref) { + bus = b; + + reference = ref; + } + + public ServletTransportFactory() { + // TODO Auto-generated constructor stub + } + + @PostConstruct + void registerWithBindingManager() { + ConduitInitiatorManager cim = bus.getExtension(ConduitInitiatorManager.class); + for (String ns : activationNamespaces) { + cim.registerConduitInitiator(ns, this); + } + DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class); + for (String ns : activationNamespaces) { + dfm.registerDestinationFactory(ns, this); + } + } + + public Conduit getConduit(EndpointInfo endpointInfo) + throws IOException { + return null; + } + + public Conduit getConduit(EndpointInfo endpointInfo, EndpointReferenceType target) + throws IOException { + return null; + } + + public Destination getDestination(EndpointInfo endpointInfo) + throws IOException { + return new ServletDestination(bus, null, endpointInfo, reference); + } + + public Bus getBus() { + return bus; + } + + @Resource + public void setBus(Bus bus) { + this.bus = bus; + } + +} Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletTransportFactory.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/servlet/ServletTransportFactory.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Added: incubator/cxf/trunk/rt/frontend/jaxws/src/main/resources/META-INF/bus-extensions.xml URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/resources/META-INF/bus-extensions.xml?view=auto&rev=448031 ============================================================================== --- incubator/cxf/trunk/rt/frontend/jaxws/src/main/resources/META-INF/bus-extensions.xml (added) +++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/resources/META-INF/bus-extensions.xml Tue Sep 19 19:16:39 2006 @@ -0,0 +1,25 @@ + + + + + + http://schemas.xmlsoap.org/wsdl/servlet + + Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/resources/META-INF/bus-extensions.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/resources/META-INF/bus-extensions.xml ------------------------------------------------------------------------------ svn:keywords = Rev Date Propchange: incubator/cxf/trunk/rt/frontend/jaxws/src/main/resources/META-INF/bus-extensions.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml