001    /*
002     * Copyright (c) 2001-2004 Caucho Technology, Inc.  All rights reserved.
003     *
004     * The Apache Software License, Version 1.1
005     *
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions
008     * are met:
009     *
010     * 1. Redistributions of source code must retain the above copyright
011     *    notice, this list of conditions and the following disclaimer.
012     *
013     * 2. Redistributions in binary form must reproduce the above copyright
014     *    notice, this list of conditions and the following disclaimer in
015     *    the documentation and/or other materials provided with the
016     *    distribution.
017     *
018     * 3. The end-user documentation included with the redistribution, if
019     *    any, must include the following acknowlegement:
020     *       "This product includes software developed by the
021     *        Caucho Technology (http://www.caucho.com/)."
022     *    Alternately, this acknowlegement may appear in the software itself,
023     *    if and wherever such third-party acknowlegements normally appear.
024     *
025     * 4. The names "Burlap", "Resin", and "Caucho" must not be used to
026     *    endorse or promote products derived from this software without prior
027     *    written permission. For written permission, please contact
028     *    info@caucho.com.
029     *
030     * 5. Products derived from this software may not be called "Resin"
031     *    nor may "Resin" appear in their names without prior written
032     *    permission of Caucho Technology.
033     *
034     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
035     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
036     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
037     * DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
038     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
039     * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
040     * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
041     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
042     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
043     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
044     * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
045     *
046     * @author Scott Ferguson
047     */
048    
049    package com.caucho.burlap.server;
050    
051    import com.caucho.burlap.io.BurlapInput;
052    import com.caucho.burlap.io.BurlapOutput;
053    import com.caucho.services.server.Service;
054    import com.caucho.services.server.ServiceContext;
055    
056    import javax.servlet.GenericServlet;
057    import javax.servlet.Servlet;
058    import javax.servlet.ServletConfig;
059    import javax.servlet.ServletException;
060    import javax.servlet.ServletRequest;
061    import javax.servlet.ServletResponse;
062    import javax.servlet.http.HttpServletRequest;
063    import javax.servlet.http.HttpServletResponse;
064    import java.io.IOException;
065    import java.io.InputStream;
066    import java.io.OutputStream;
067    import java.io.PrintWriter;
068    
069    /**
070     * Servlet for serving Burlap services.
071     */
072    public class BurlapServlet extends GenericServlet {
073      private Class<?> _apiClass;
074      private Object _service;
075      
076      private BurlapSkeleton _skeleton;
077    
078      public String getServletInfo()
079      {
080        return "Burlap Servlet";
081      }
082    
083      /**
084       * Sets the service class.
085       */
086      public void setService(Object service)
087      {
088        _service = service;
089      }
090    
091      /**
092       * Sets the api-class.
093       */
094      public void setAPIClass(Class<?> apiClass)
095      {
096        _apiClass = apiClass;
097      }
098    
099      /**
100       * Initialize the service, including the service object.
101       */
102      public void init(ServletConfig config)
103        throws ServletException
104      {
105        super.init(config);
106        
107        try {
108          if (_service == null) {
109            String className = getInitParameter("service-class");
110            Class<?> serviceClass = null;
111    
112            if (className != null) {
113              ClassLoader loader = Thread.currentThread().getContextClassLoader();
114    
115              if (loader != null)
116                serviceClass = Class.forName(className, false, loader);
117              else
118                serviceClass = Class.forName(className);
119            }
120            else {
121              if (getClass().equals(BurlapServlet.class))
122                throw new ServletException("server must extend BurlapServlet");
123    
124              serviceClass = getClass();
125            }
126    
127            _service = serviceClass.newInstance();
128    
129            if (_service instanceof BurlapServlet)
130              ((BurlapServlet) _service).setService(this);
131            if (_service instanceof Service)
132              ((Service) _service).init(getServletConfig());
133            else if (_service instanceof Servlet)
134              ((Servlet) _service).init(getServletConfig());
135          }
136          
137          if (_apiClass == null) {
138            String className = getInitParameter("api-class");
139    
140            if (className != null) {
141              ClassLoader loader = Thread.currentThread().getContextClassLoader();
142    
143              if (loader != null)
144                _apiClass = Class.forName(className, false, loader);
145              else
146                _apiClass = Class.forName(className);
147            }
148            else
149              _apiClass = _service.getClass();
150          }
151    
152          _skeleton = new BurlapSkeleton(_service, _apiClass);
153        } catch (ServletException e) {
154          throw e;
155        } catch (Exception e) {
156          throw new ServletException(e);
157        }
158      }
159      
160      /**
161       * Execute a request.  The path-info of the request selects the bean.
162       * Once the bean's selected, it will be applied.
163       */
164      public void service(ServletRequest request, ServletResponse response)
165        throws IOException, ServletException
166      {
167        HttpServletRequest req = (HttpServletRequest) request;
168        HttpServletResponse res = (HttpServletResponse) response;
169    
170        if (! req.getMethod().equals("POST")) {
171          res.setStatus(500, "Burlap Requires POST");
172          PrintWriter out = res.getWriter();
173    
174          res.setContentType("text/html");
175          out.println("<h1>Burlap Requires POST</h1>");
176          
177          return;
178        }
179    
180        String serviceId = req.getPathInfo();
181        String objectId = req.getParameter("id");
182        if (objectId == null)
183          objectId = req.getParameter("ejbid");
184    
185        ServiceContext.begin(req, res, serviceId, objectId);
186    
187        try {
188          InputStream is = request.getInputStream();
189          OutputStream os = response.getOutputStream();
190    
191          BurlapInput in = new BurlapInput(is);
192          BurlapOutput out = new BurlapOutput(os);
193    
194          _skeleton.invoke(in, out);
195        } catch (RuntimeException e) {
196          throw e;
197        } catch (ServletException e) {
198          throw e;
199        } catch (Throwable e) {
200          throw new ServletException(e);
201        } finally {
202          ServiceContext.end();
203        }
204      }
205    }