001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.geronimo.axis2.pojo;
019    
020    import java.io.PrintWriter;
021    import java.net.HttpURLConnection;
022    import java.net.URL;
023    
024    import javax.naming.Context;
025    import javax.xml.ws.WebServiceException;
026    
027    import org.apache.axis2.context.ConfigurationContext;
028    import org.apache.axis2.context.MessageContext;
029    import org.apache.axis2.context.ServiceContext;
030    import org.apache.axis2.description.AxisService;
031    import org.apache.axis2.engine.Handler.InvocationResponse;
032    import org.apache.axis2.jaxws.registry.FactoryRegistry;
033    import org.apache.axis2.jaxws.server.endpoint.lifecycle.factory.EndpointLifecycleManagerFactory;
034    import org.apache.axis2.transport.http.HTTPConstants;
035    import org.apache.axis2.transport.http.HTTPTransportReceiver;
036    import org.apache.axis2.transport.http.HTTPTransportUtils;
037    import org.apache.axis2.transport.http.util.RESTUtil;
038    import org.apache.commons.logging.Log;
039    import org.apache.commons.logging.LogFactory;
040    import org.apache.geronimo.axis2.Axis2WebServiceContainer;
041    import org.apache.geronimo.jaxws.JAXWSAnnotationProcessor;
042    import org.apache.geronimo.jaxws.PortInfo;
043    import org.apache.geronimo.jaxws.annotations.AnnotationHolder;
044    
045    /**
046     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
047     */
048    public class POJOWebServiceContainer extends Axis2WebServiceContainer {
049    
050        private static final Log LOG = LogFactory.getLog(POJOWebServiceContainer.class);
051        
052        private Object endpointInstance;
053        private String contextRoot;
054        private AnnotationHolder holder;
055        
056        public POJOWebServiceContainer(PortInfo portInfo,
057                                       String endpointClassName,
058                                       ClassLoader classLoader,
059                                       Context context,
060                                       URL configurationBaseUrl,
061                                       AnnotationHolder holder,
062                                       String contextRoot) {
063            super(portInfo, endpointClassName, classLoader, context, configurationBaseUrl);
064            this.holder = holder;
065            this.contextRoot = contextRoot;
066        }
067        
068        @Override
069        public void init() throws Exception { 
070            super.init();
071            
072            /*
073             * This replaces EndpointLifecycleManagerFactory for all web services.
074             * This should be ok as we do our own endpoint instance management and injection.       
075             */
076            FactoryRegistry.setFactory(EndpointLifecycleManagerFactory.class, 
077                                       new POJOEndpointLifecycleManagerFactory());
078                                          
079            String servicePath = trimContext(getServicePath(this.contextRoot));
080            this.configurationContext.setServicePath(servicePath);
081            //need to setContextRoot after servicePath as cachedServicePath is only built 
082            //when setContextRoot is called.
083            String rootContext = trimContext(this.contextRoot);
084            this.configurationContext.setContextRoot(rootContext); 
085            
086            // instantiate and inject resources into service
087            try {
088                this.endpointInstance = this.holder.newInstance(this.endpointClass.getName(), 
089                                                                this.endpointClass.getClassLoader(), 
090                                                                this.context);
091            } catch (Exception e) {
092                throw new WebServiceException("Service resource injection failed", e);
093            }
094            
095            this.annotationProcessor = 
096                new JAXWSAnnotationProcessor(this.jndiResolver, new POJOWebServiceContext());
097    
098            // configure and inject handlers
099            try {
100                configureHandlers();
101                injectHandlers();
102            } catch (Exception e) {
103                throw new WebServiceException("Error configuring handlers", e);
104            }
105            
106        }
107        
108        @Override
109        protected void processXMLRequest(Request request, 
110                                         Response response, 
111                                         AxisService service, 
112                                         MessageContext msgContext) throws Exception {
113            String contentType = request.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
114            String soapAction = request.getHeader(HTTPConstants.HEADER_SOAP_ACTION);
115            if (soapAction == null) {
116                soapAction = "\"\"";
117            }
118    
119            ConfigurationContext configurationContext = msgContext.getConfigurationContext();
120            configurationContext.fillServiceContextAndServiceGroupContext(msgContext);
121            
122            setMsgContextProperties(request, response, service, msgContext);
123    
124            ServiceContext serviceContext = msgContext.getServiceContext();
125            serviceContext.setProperty(ServiceContext.SERVICE_OBJECT, this.endpointInstance);
126                    
127            try {
128                if (!HTTPTransportUtils.isRESTRequest(contentType)) {
129                    HTTPTransportUtils.processHTTPPostRequest(msgContext,
130                                                              request.getInputStream(),
131                                                              response.getOutputStream(),
132                                                              contentType,
133                                                              soapAction,
134                                                              request.getURI().getPath());
135                } else {
136                    RESTUtil.processXMLRequest(msgContext, 
137                                               request.getInputStream(),
138                                               response.getOutputStream(), 
139                                               contentType);
140                }
141            } finally {                        
142                // de-associate JAX-WS MessageContext with the thread
143                // (association happens in POJOEndpointLifecycleManager.createService() call)
144                POJOWebServiceContext.clear();
145            } 
146        }
147            
148        @Override
149        protected void processURLRequest(Request request,
150                                         Response response,
151                                         AxisService service,
152                                         MessageContext msgContext) throws Exception {
153            String contentType = request.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
154            
155            ConfigurationContext configurationContext = msgContext.getConfigurationContext();
156            configurationContext.fillServiceContextAndServiceGroupContext(msgContext);
157            
158            setMsgContextProperties(request, response, service, msgContext);
159            
160            ServiceContext serviceContext = msgContext.getServiceContext();
161            serviceContext.setProperty(ServiceContext.SERVICE_OBJECT, this.endpointInstance);
162                    
163            InvocationResponse processed = null;
164            try {
165                processed = RESTUtil.processURLRequest(msgContext, 
166                                                       response.getOutputStream(),
167                                                       contentType);
168            } finally {                        
169                // de-associate JAX-WS MessageContext with the thread
170                // (association happens in POJOEndpointLifecycleManager.createService() call)
171                POJOWebServiceContext.clear();
172            }
173                
174            if (!processed.equals(InvocationResponse.CONTINUE)) {
175                response.setStatusCode(HttpURLConnection.HTTP_OK);
176                String s = HTTPTransportReceiver.getServicesHTML(configurationContext);
177                PrintWriter pw = new PrintWriter(response.getOutputStream());
178                pw.write(s);
179                pw.flush();
180            }
181        }
182        
183        @Override
184        public void destroy() {
185            // call handler preDestroy
186            destroyHandlers();
187            
188            // call service preDestroy
189            if (this.endpointInstance != null) {
190                try {
191                    this.holder.destroyInstance(this.endpointInstance);
192                } catch (Exception e) {
193                    LOG.warn("Error calling @PreDestroy method", e); 
194                }
195            }
196            
197            super.destroy();
198        }
199    }