001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb;
031:
032: import com.caucho.ejb.protocol.ProtocolContainer;
033: import com.caucho.ejb.protocol.Skeleton;
034: import com.caucho.ejb.manager.EjbContainer;
035: import com.caucho.log.Log;
036: import com.caucho.server.connection.AbstractHttpRequest;
037: import com.caucho.server.connection.AbstractHttpResponse;
038: import com.caucho.server.util.CauchoSystem;
039: import com.caucho.server.webapp.Application;
040: import com.caucho.server.webapp.WebApp;
041: import com.caucho.util.CharBuffer;
042: import com.caucho.util.L10N;
043: import com.caucho.vfs.Path;
044:
045: import javax.servlet.GenericServlet;
046: import javax.servlet.ServletException;
047: import javax.servlet.ServletRequest;
048: import javax.servlet.ServletResponse;
049: import java.io.IOException;
050: import java.io.InputStream;
051: import java.io.PrintWriter;
052: import java.util.Hashtable;
053: import java.util.logging.Level;
054: import java.util.logging.Logger;
055:
056: /**
057: * Servlet for serving EJBs from the Resin web server.
058: */
059: public class EJBServlet extends GenericServlet {
060: private static final L10N L = new L10N(EJBServlet.class);
061: private final Logger log = Log.open(EJBServlet.class);
062:
063: private String _urlPrefix;
064:
065: private String _ejbServerJndiName = "java:comp/env/cmp";
066: private String _containerId;
067: private String _servletId;
068: private String _localId;
069:
070: private boolean _isDebug;
071:
072: // URL to bean map
073: private Hashtable<CharSequence, Skeleton> _beanMap = new Hashtable<CharSequence, Skeleton>();
074:
075: private EjbContainer _ejbManager;
076: private ProtocolContainer _protocolContainer;
077:
078: private ServletException _exception;
079:
080: private Path _workPath;
081:
082: protected String getDefaultProtocolContainer() {
083: return "com.caucho.hessian.HessianProtocol";
084: }
085:
086: /**
087: * Set true for a debug.
088: */
089: public void setDebug(boolean debug) {
090: _isDebug = debug;
091: }
092:
093: public void setURLPrefix(String prefix) {
094: _urlPrefix = prefix;
095: }
096:
097: /**
098: * Initialize the servlet
099: */
100: public void init() throws ServletException {
101: _ejbManager = EjbContainer.getCurrent();
102:
103: if (_ejbManager == null) {
104: throw new ServletException(
105: L
106: .l(
107: "No <ejb-server> detected. '{0}' requires a configured <ejb-server>",
108: getClass().getName()));
109: }
110:
111: _workPath = CauchoSystem.getWorkPath();
112:
113: _urlPrefix = getInitParameter("url-prefix");
114:
115: _localId = getInitParameter("local-prefix");
116:
117: String protocol = getInitParameter("protocol");
118: if (protocol == null)
119: protocol = getInitParameter("protocol-container");
120: if (protocol == null)
121: protocol = getInitParameter("protocol-factory");
122: if (protocol == null)
123: protocol = getDefaultProtocolContainer();
124:
125: try {
126: Class cl = CauchoSystem.loadClass(protocol);
127:
128: _protocolContainer = (ProtocolContainer) cl.newInstance();
129: } catch (Exception e) {
130: throw new ServletException(e);
131: }
132:
133: Application app = (Application) getServletContext();
134:
135: // need to initialize in the case of message driven beans.
136: //if (containerId == null)
137: // containerId = app.getURL();
138:
139: initEjb();
140:
141: if (_urlPrefix != null)
142: initProtocol();
143: }
144:
145: /**
146: * Execute a request. The path-info of the request selects the bean.
147: * Once the bean's selected, it will be applied.
148: */
149: public void service(ServletRequest request, ServletResponse response)
150: throws IOException, ServletException {
151: AbstractHttpRequest req = (AbstractHttpRequest) request;
152: AbstractHttpResponse res = (AbstractHttpResponse) response;
153:
154: if (_urlPrefix == null) {
155: synchronized (this ) {
156: if (_urlPrefix == null)
157: serverInit(req);
158: }
159: }
160:
161: if (!req.getMethod().equals("POST")) {
162: String protocol = _protocolContainer.getName();
163: res.setStatus(500, protocol + " Protocol Error");
164: PrintWriter out = res.getWriter();
165: out.println(protocol
166: + " expects a POST containing an RPC call.");
167: return;
168: }
169:
170: try {
171: String pathInfo = req.getPathInfo();
172: String queryString = req.getQueryString();
173:
174: CharBuffer cb = new CharBuffer();
175: cb.append(pathInfo);
176: cb.append('?');
177: cb.append(queryString);
178:
179: InputStream is = req.getInputStream();
180:
181: if (_isDebug) {
182: }
183:
184: Skeleton skeleton = (Skeleton) _beanMap.get(cb);
185:
186: if (skeleton == null) {
187: // If this was a load just to force the initialization, then return
188: if (req.getParameter("ejb-load") != null)
189: return;
190:
191: if (_exception != null)
192: throw _exception;
193:
194: try {
195: if (pathInfo == null)
196: pathInfo = "";
197:
198: skeleton = _protocolContainer.getSkeleton(pathInfo,
199: queryString);
200: } catch (Exception e) {
201: log.log(Level.WARNING, e.toString(), e);
202:
203: skeleton = _protocolContainer
204: .getExceptionSkeleton();
205:
206: if (skeleton != null) {
207: skeleton._service(req.getInputStream(), res
208: .getOutputStream(), e);
209:
210: return;
211: } else
212: throw e;
213: }
214:
215: if (skeleton == null)
216: throw new ServletException(L.l(
217: "Can't load skeleton for '{0}?{1}'",
218: pathInfo, queryString));
219:
220: if (skeleton != null) {
221: skeleton.setDebug(_isDebug);
222: _beanMap.put(cb, skeleton);
223: }
224: }
225:
226: skeleton._service(req.getInputStream(), res
227: .getOutputStream());
228: } catch (ServletException e) {
229: throw e;
230: } catch (Throwable e) {
231: log.log(Level.WARNING, e.toString(), e);
232:
233: throw new ServletException(e);
234: }
235: }
236:
237: /**
238: * Returns the server container responsible for handling the request
239: *
240: * @param pathInfo the path info of the request
241: *
242: * @return the server bean responsible for handling the request
243: */
244: Skeleton getSkeleton(String pathInfo, String queryString)
245: throws Exception {
246: CharBuffer cb = CharBuffer.allocate();
247: cb.append(pathInfo);
248: cb.append('?');
249: cb.append(queryString);
250:
251: Skeleton skeleton = (Skeleton) _beanMap.get(cb);
252:
253: if (skeleton != null) {
254: cb.free();
255: return skeleton;
256: }
257:
258: skeleton = _protocolContainer
259: .getSkeleton(pathInfo, queryString);
260:
261: _beanMap.put(cb, skeleton);
262:
263: return skeleton;
264: }
265:
266: /**
267: * Initialize the server.
268: */
269: private void serverInit(AbstractHttpRequest req)
270: throws ServletException {
271: if (_urlPrefix != null)
272: return;
273:
274: WebApp app = (WebApp) getServletContext();
275:
276: // calculate the URL prefix
277: _servletId = req.getServletPath();
278:
279: CharBuffer cb = CharBuffer.allocate();
280:
281: if (!"default".equals(app.getAdmin().getHost().getName())
282: && !"".equals(app.getAdmin().getHost().getName())) {
283: String hostName = app.getAdmin().getHost().getURL();
284:
285: cb.append(hostName);
286: cb.append(app.getContextPath());
287: cb.append(_servletId);
288: } else {
289: cb.append(req.getScheme());
290: cb.append("://");
291: cb.append(req.getServerName());
292: cb.append(":");
293: cb.append(req.getServerPort());
294: cb.append(app.getContextPath());
295: cb.append(_servletId);
296: }
297:
298: _urlPrefix = cb.close();
299:
300: initProtocol();
301: }
302:
303: private void initProtocol() {
304: normalizeId();
305:
306: _protocolContainer.setProtocolManager(_ejbManager
307: .getProtocolManager());
308: _protocolContainer.setURLPrefix(_urlPrefix);
309: _protocolContainer.setWorkPath(_workPath);
310:
311: EjbContainer manager = _ejbManager;
312:
313: for (; manager != null; manager = manager.getParent()) {
314: manager.getProtocolManager().addProtocolContainer(
315: _protocolContainer);
316: }
317: }
318:
319: private void normalizeId() {
320: if (_urlPrefix == null)
321: return;
322:
323: Application application = (Application) getServletContext();
324: String hostName = "localhost"; // application.getHost();
325: String contextPath = application.getContextPath();
326:
327: if (_urlPrefix.startsWith("/")) {
328: _servletId = _urlPrefix;
329: _urlPrefix = application.getURL() + _urlPrefix;
330: } else if (_urlPrefix.startsWith("http://")) {
331: int p = _urlPrefix.indexOf('/', "http://".length());
332:
333: String uri = _urlPrefix;
334: if (p > 0)
335: uri = _urlPrefix.substring(p);
336: else
337: uri = "";
338:
339: if (uri.startsWith(contextPath))
340: _servletId = uri.substring(contextPath.length());
341: else if (_servletId == null)
342: _servletId = uri;
343: } else if (_urlPrefix.startsWith("https://")) {
344: int p = _urlPrefix.indexOf('/', "https://".length());
345:
346: String uri = _urlPrefix;
347: if (p > 0)
348: uri = _urlPrefix.substring(p);
349: else
350: uri = "";
351:
352: if (uri.startsWith(contextPath))
353: _servletId = uri.substring(contextPath.length());
354: else if (_servletId == null)
355: _servletId = uri;
356: } else if (_urlPrefix.startsWith("cron:")) {
357: _urlPrefix = application.getURL() + _servletId;
358: } else
359: _servletId = _urlPrefix;
360:
361: if (_servletId.equals(""))
362: _servletId = "/";
363: }
364:
365: private void initEjb() throws ServletException {
366: if (_ejbManager != null)
367: return;
368:
369: /*
370: String cmpJndi = "java:comp/env/cmp";
371: try {
372: Object cmp = new InitialContext().lookup(cmpJndi);
373:
374: if (cmp instanceof LocalContext) {
375: LocalContext cxt = (LocalContext) cmp;
376:
377: LocalModel model = (LocalModel) cxt.getModel();
378: _ejbManager = model.getServerContainer();
379: }
380: } catch (Exception e) {
381: }
382:
383: if (_serverContainer == null)
384: throw new ServletException(L.l("Can't find servers container at `{0}'",
385: cmpJndi));
386: */
387:
388: if (_urlPrefix != null) {
389: normalizeId();
390:
391: _protocolContainer.setServerManager(_ejbManager);
392: _protocolContainer.setURLPrefix(_urlPrefix);
393: _protocolContainer.setWorkPath(_workPath);
394:
395: EjbContainer manager = _ejbManager;
396:
397: for (; manager != null; manager = manager.getParent()) {
398: manager.getProtocolManager().addProtocolContainer(
399: _protocolContainer);
400: }
401: }
402: }
403:
404: public void destroy() {
405: EjbContainer manager = _ejbManager;
406:
407: for (; manager != null; manager = manager.getParent()) {
408: manager.getProtocolManager().removeProtocolContainer(
409: _protocolContainer);
410: }
411: }
412: }
|