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    package org.apache.geronimo.jetty6;
018    
019    import java.io.IOException;
020    import java.util.Map;
021    import java.util.Set;
022    
023    import javax.security.auth.Subject;
024    import javax.security.jacc.PolicyContext;
025    import javax.servlet.ServletContext;
026    import javax.servlet.ServletException;
027    import javax.servlet.ServletRequest;
028    import javax.servlet.ServletResponse;
029    import javax.servlet.UnavailableException;
030    import javax.servlet.http.HttpServletRequest;
031    
032    import org.apache.geronimo.gbean.GBeanInfo;
033    import org.apache.geronimo.gbean.GBeanInfoBuilder;
034    import org.apache.geronimo.gbean.GBeanLifecycle;
035    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
036    import org.apache.geronimo.webservices.POJOWebServiceServlet;
037    import org.apache.geronimo.webservices.WebServiceContainer;
038    import org.apache.geronimo.webservices.WebServiceContainerInvoker;
039    import org.apache.geronimo.webservices.WebServiceContainerFactory;
040    import org.mortbay.jetty.Request;
041    import org.mortbay.jetty.servlet.ServletHolder;
042    
043    
044    /**
045     * This is intended to hold the web service stack for an axis POJO web service.
046     * It is starting life as a copy of JettyServletHolder.
047     *
048     * @version $Rev: 549859 $ $Date: 2007-06-22 12:05:13 -0400 (Fri, 22 Jun 2007) $
049     */
050    public class JettyPOJOWebServiceHolder implements GBeanLifecycle {
051        private final ServletHolder servletHolder;
052        private final WebServiceContainer webServiceContainer;
053        private final Set servletMappings;
054        private final JettyServletRegistration context;
055        private final String pojoClassName;
056    
057        //todo consider interface instead of this constructor for endpoint use.
058        public JettyPOJOWebServiceHolder() {
059            servletHolder = null;
060            webServiceContainer = null;
061            servletMappings = null;
062            context = null;
063            pojoClassName = null;
064        }
065    
066        public JettyPOJOWebServiceHolder(String pojoClassName,
067                                         String servletName,
068                                         Map initParams,
069                                         Integer loadOnStartup,
070                                         Set servletMappings,
071                                         String runAsRole, 
072                                         WebServiceContainerFactory webServiceContainerFactory,
073                                         JettyServletRegistration context) throws Exception {
074            Subject runAsSubject = context == null? null: context.getSubjectForRole(runAsRole);
075            servletHolder = new InternalJettyServletHolder(context == null? null: context.getLifecycleChain(), runAsSubject, context);
076            //context will be null only for use as "default servlet info holder" in deployer.
077    
078            this.pojoClassName = pojoClassName;
079            this.context = context;
080            this.webServiceContainer = webServiceContainerFactory == null? null: webServiceContainerFactory.getWebServiceContainer();
081            this.servletMappings = servletMappings;
082            if (context != null) {            
083                servletHolder.setName(servletName);
084                servletHolder.setClassName(POJOWebServiceServlet.class.getName());
085                servletHolder.setInitParameters(initParams);
086                if (loadOnStartup != null) {
087                    servletHolder.setInitOrder(loadOnStartup.intValue());
088                }
089            }
090        }
091    
092        //todo how do we stop/destroy the servlet?
093        //todo is start called twice???
094    
095        public String getServletName() {
096            return servletHolder.getName();
097        }
098    
099        /**
100         * TODO THIS IS NOT CALLED!!! only the ServletHolder is!!
101         * Service a request with this servlet.  Set the ThreadLocal to hold the
102         * current JettyServletHolder.
103         */
104        public void handle(ServletRequest request, ServletResponse response)
105                throws ServletException, UnavailableException, IOException {
106    
107            //  TODO There has to be some way to get this in on the Servlet's init method.
108    //        request.setAttribute(POJOWebServiceServlet.WEBSERVICE_CONTAINER, webServiceContainer);
109    
110            InternalJettyServletHolder.setCurrentServletName(getServletName());
111            PolicyContext.setHandlerData(Request.getRequest((HttpServletRequest) request));
112    
113            servletHolder.handle(request, response);
114        }
115    
116        public void doStart() throws Exception {
117            if (context != null) {
118                Class pojoClass = context.getWebClassLoader().loadClass(pojoClassName);
119    
120                /* DMB: Hack! I really just want to override initServlet and give a reference of the WebServiceContainer to the servlet before we call init on it.
121                 * But this will have to do instead....
122                 */
123                ServletContext servletContext = this.context.getServletHandler().getServletContext();
124    
125                // Make up an ID for the WebServiceContainer
126                // put a reference the ID in the init-params
127                // put the WebServiceContainer in the webapp context keyed by its ID
128                String webServicecontainerID = getServletName() + WebServiceContainerInvoker.WEBSERVICE_CONTAINER + webServiceContainer.hashCode();
129                servletHolder.setInitParameter(WebServiceContainerInvoker.WEBSERVICE_CONTAINER, webServicecontainerID);
130                servletContext.setAttribute(webServicecontainerID, webServiceContainer);
131    
132                // Same for the POJO Class
133                String pojoClassID = getServletName() + POJOWebServiceServlet.POJO_CLASS + pojoClass.hashCode();
134                servletHolder.setInitParameter(POJOWebServiceServlet.POJO_CLASS, pojoClassID);
135                servletContext.setAttribute(pojoClassID, pojoClass);
136    
137                //this now starts the servlet in the appropriate context
138                //TODO check that we should not call this a servlet for jsr-77 benefit.
139                context.registerServletHolder(servletHolder, getServletName(), this.servletMappings, null);
140                servletHolder.start();
141            }
142        }
143    
144        public void doStop() throws Exception {
145            servletHolder.stop();
146        }
147    
148        public void doFail() {
149            try {
150                servletHolder.stop();
151            } catch (Exception e) {
152                //ignore ??
153            }
154        }
155    
156        public static final GBeanInfo GBEAN_INFO;
157    
158        static {
159            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JettyPOJOWebServiceHolder.class, NameFactory.SERVLET_WEB_SERVICE_TEMPLATE);
160            //todo replace with interface
161    //        infoBuilder.addInterface(ServletHolder.class);
162    
163            infoBuilder.addAttribute("pojoClassName", String.class, true);
164            infoBuilder.addAttribute("servletName", String.class, true);
165            infoBuilder.addAttribute("initParams", Map.class, true);
166            infoBuilder.addAttribute("loadOnStartup", Integer.class, true);
167            infoBuilder.addAttribute("servletMappings", Set.class, true);
168            infoBuilder.addAttribute("runAsRole", String.class, true);
169            infoBuilder.addReference("WebServiceContainerFactory", WebServiceContainerFactory.class);
170            infoBuilder.addReference("JettyServletRegistration", JettyServletRegistration.class);
171    
172            infoBuilder.setConstructor(new String[]{"pojoClassName",
173                    "servletName",
174                    "initParams",
175                    "loadOnStartup",
176                    "servletMappings",
177                    "runAsRole",
178                    "WebServiceContainerFactory",
179                    "JettyServletRegistration"});
180    
181            GBEAN_INFO = infoBuilder.getBeanInfo();
182        }
183    
184        public static GBeanInfo getGBeanInfo() {
185            return GBEAN_INFO;
186        }
187    
188    
189    }