001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/main/OpenCmsServlet.java,v $
003: * Date : $Date: 2008-02-27 12:05:39 $
004: * Version: $Revision: 1.62 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.main;
033:
034: import org.opencms.file.CmsFile;
035: import org.opencms.file.CmsObject;
036: import org.opencms.file.CmsResourceFilter;
037: import org.opencms.i18n.CmsMessageContainer;
038: import org.opencms.staticexport.CmsStaticExportData;
039: import org.opencms.staticexport.CmsStaticExportRequest;
040: import org.opencms.util.CmsRequestUtil;
041:
042: import java.io.IOException;
043:
044: import javax.servlet.ServletConfig;
045: import javax.servlet.ServletException;
046: import javax.servlet.http.HttpServlet;
047: import javax.servlet.http.HttpServletRequest;
048: import javax.servlet.http.HttpServletResponse;
049:
050: import org.apache.commons.logging.Log;
051:
052: /**
053: * This the main servlet of the OpenCms system.<p>
054: *
055: * From here, all operations that are results of HTTP requests are invoked.
056: * Any incoming request is handled in multiple steps:
057: *
058: * <ol><li>The requesting <code>{@link org.opencms.file.CmsUser}</code> is authenticated
059: * and a <code>{@link org.opencms.file.CmsObject}</code> with this users context information
060: * is created. This <code>{@link org.opencms.file.CmsObject}</code> is used to access all functions of OpenCms, limited by
061: * the authenticated users permissions. If the user is not identified, it is set to the default user, usually named "Guest".</li>
062: *
063: * <li>The requested <code>{@link org.opencms.file.CmsResource}</code> is loaded into OpenCms and depending on its type
064: * (and the users persmissions to display or modify it),
065: * it is send to one of the OpenCms <code>{@link org.opencms.loader.I_CmsResourceLoader}</code> implementations
066: * do be processed.</li>
067: *
068: * <li>
069: * The <code>{@link org.opencms.loader.I_CmsResourceLoader}</code> will then decide what to do with the
070: * contents of the requested <code>{@link org.opencms.file.CmsResource}</code>.
071: * In case of a JSP resource the JSP handling mechanism is invoked with the <code>{@link org.opencms.loader.CmsJspLoader}</code>,
072: * in case of an image (or another static resource) this will be returned by the <code>{@link org.opencms.loader.CmsDumpLoader}</code>
073: * etc.
074: * </li></ol>
075: *
076: * @author Alexander Kandzior
077: * @author Michael Emmerich
078: *
079: * @version $Revision: 1.62 $
080: *
081: * @since 6.0.0
082: *
083: * @see org.opencms.main.CmsShell
084: * @see org.opencms.file.CmsObject
085: * @see org.opencms.main.OpenCms
086: */
087: public class OpenCmsServlet extends HttpServlet implements
088: I_CmsRequestHandler {
089:
090: /** Name of the <code>DefaultWebApplication</code> parameter in the <code>web.xml</code> OpenCms servlet configuration. */
091: public static final String SERVLET_PARAM_DEFAULT_WEB_APPLICATION = "DefaultWebApplication";
092:
093: /** Name of the <code>OpenCmsHome</code> parameter in the <code>web.xml</code> OpenCms servlet configuration. */
094: public static final String SERVLET_PARAM_OPEN_CMS_HOME = "OpenCmsHome";
095:
096: /** Name of the <code>OpenCmsServlet</code> parameter in the <code>web.xml</code> OpenCms servlet configuration. */
097: public static final String SERVLET_PARAM_OPEN_CMS_SERVLET = "OpenCmsServlet";
098:
099: /** Name of the <code>WebApplicationContext</code> parameter in the <code>web.xml</code> OpenCms servlet configuration. */
100: public static final String SERVLET_PARAM_WEB_APPLICATION_CONTEXT = "WebApplicationContext";
101:
102: /** Handler prefix. */
103: private static final String HANDLE_PATH = "/handle";
104:
105: /** Path to handler "error page" files in the VFS. */
106: private static final String HANDLE_VFS_PATH = "/system/handler"
107: + HANDLE_PATH;
108:
109: /** Handler "error page" file suffix. */
110: private static final String HANDLE_VFS_SUFFIX = ".html";
111:
112: /** Handler implementation names. */
113: private static final String[] HANDLER_NAMES = { "404" };
114:
115: /** The log object for this class. */
116: private static final Log LOG = CmsLog.getLog(OpenCmsServlet.class);
117:
118: /** Serial version UID required for safe serialization. */
119: private static final long serialVersionUID = 4729951599966070050L;
120:
121: /**
122: * OpenCms servlet main request handling method.<p>
123: *
124: * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
125: */
126: public void doGet(HttpServletRequest req, HttpServletResponse res)
127: throws IOException, ServletException {
128:
129: // check to OpenCms runlevel
130: int runlevel = OpenCmsCore.getInstance().getRunLevel();
131:
132: // write OpenCms server identification in the response header
133: res.setHeader(CmsRequestUtil.HEADER_SERVER, OpenCmsCore
134: .getInstance().getSystemInfo().getVersion());
135:
136: if (runlevel != OpenCms.RUNLEVEL_4_SERVLET_ACCESS) {
137: // not the "normal" servlet runlevel
138: if (runlevel == OpenCms.RUNLEVEL_3_SHELL_ACCESS) {
139: // we have shell runlevel only, upgrade to servlet runlevel (required after setup wizard)
140: init(getServletConfig());
141: } else {
142: // illegal runlevel, we can't process requests
143: // sending status code 403, indicating the server understood the request but refused to fulfill it
144: res.sendError(HttpServletResponse.SC_FORBIDDEN);
145: // goodbye
146: return;
147: }
148: }
149:
150: String path = OpenCmsCore.getInstance().getPathInfo(req);
151: if (path.startsWith(HANDLE_PATH)) {
152: // this is a request to an OpenCms handler URI
153: invokeHandler(req, res);
154: } else {
155: // standard request to a URI in the OpenCms VFS
156: OpenCmsCore.getInstance().showResource(req, res);
157: }
158: }
159:
160: /**
161: * OpenCms servlet POST request handling method,
162: * will just call {@link #doGet(HttpServletRequest, HttpServletResponse)}.<p>
163: *
164: * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
165: */
166: public void doPost(HttpServletRequest req, HttpServletResponse res)
167: throws IOException, ServletException {
168:
169: doGet(req, res);
170: }
171:
172: /**
173: * @see org.opencms.main.I_CmsRequestHandler#getHandlerNames()
174: */
175: public String[] getHandlerNames() {
176:
177: return HANDLER_NAMES;
178: }
179:
180: /**
181: * @see org.opencms.main.I_CmsRequestHandler#handle(HttpServletRequest, HttpServletResponse, String)
182: */
183: public void handle(HttpServletRequest req, HttpServletResponse res,
184: String name) throws IOException, ServletException {
185:
186: int errorCode;
187: try {
188: errorCode = Integer.valueOf(name).intValue();
189: } catch (NumberFormatException nf) {
190: res.sendError(HttpServletResponse.SC_FORBIDDEN);
191: return;
192: }
193: switch (errorCode) {
194: case 404:
195: CmsObject cms = null;
196: CmsStaticExportData exportData = null;
197: try {
198: cms = OpenCms.initCmsObject(OpenCms.getDefaultUsers()
199: .getUserExport());
200: exportData = OpenCms.getStaticExportManager()
201: .getExportData(req, cms);
202: } catch (CmsException e) {
203: // unlikely to happen
204: if (LOG.isWarnEnabled()) {
205: LOG
206: .warn(
207: Messages
208: .get()
209: .getBundle()
210: .key(
211: Messages.LOG_INIT_CMSOBJECT_IN_HANDLER_2,
212: name,
213: OpenCmsCore
214: .getInstance()
215: .getPathInfo(
216: req)),
217: e);
218: }
219: }
220: if (exportData != null) {
221: try {
222: // generate a static export request wrapper
223: CmsStaticExportRequest exportReq = new CmsStaticExportRequest(
224: req, exportData);
225: // export the resource and set the response status according to the result
226: res.setStatus(OpenCms.getStaticExportManager()
227: .export(exportReq, res, cms, exportData));
228: } catch (Throwable t) {
229: if (LOG.isWarnEnabled()) {
230: LOG.warn(Messages.get().getBundle()
231: .key(Messages.LOG_ERROR_EXPORT_1,
232: exportData), t);
233: }
234: openErrorHandler(req, res, errorCode);
235: }
236: } else {
237: openErrorHandler(req, res, errorCode);
238: }
239: break;
240: default:
241: openErrorHandler(req, res, errorCode);
242: }
243: }
244:
245: /**
246: * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
247: */
248: public synchronized void init(ServletConfig config)
249: throws ServletException {
250:
251: super .init(config);
252: try {
253: // upgrade the runlevel
254: // usually this should have already been done by the context listener
255: // however, after a fresh install / setup this will be done from here
256: OpenCmsCore.getInstance().upgradeRunlevel(
257: config.getServletContext());
258: // finalize OpenCms initialization
259: OpenCmsCore.getInstance().initServlet(this );
260: } catch (CmsInitException e) {
261: if (Messages.ERR_CRITICAL_INIT_WIZARD_0.equals(e
262: .getMessageContainer().getKey())) {
263: // if wizard is still enabled - allow retry of initialization (required for setup wizard)
264: // this means the servlet init() call must be terminated by an exception
265: if (OpenCmsCore.getInstance().getSystemInfo()
266: .isFailedInitializationThrowsException()) {
267: throw new ServletException(e.getMessage());
268: } else {
269: // this is needed since some servlet containers does not like the servlet to throw exceptions,
270: // like BEA WLS 9.x and Resin
271: LOG.error(Messages.get().getBundle().key(
272: Messages.LOG_ERROR_GENERIC_0), e);
273: }
274: }
275: } catch (Throwable t) {
276: LOG.error(Messages.get().getBundle().key(
277: Messages.LOG_ERROR_GENERIC_0), t);
278: }
279: }
280:
281: /**
282: * Manages requests to internal OpenCms request handlers.<p>
283: *
284: * @param req the current request
285: * @param res the current response
286: * @throws ServletException
287: * @throws ServletException in case an error occurs
288: * @throws IOException in case an error occurs
289: */
290: protected void invokeHandler(HttpServletRequest req,
291: HttpServletResponse res) throws IOException,
292: ServletException {
293:
294: String name = OpenCmsCore.getInstance().getPathInfo(req)
295: .substring(HANDLE_PATH.length());
296: I_CmsRequestHandler handler = OpenCmsCore.getInstance()
297: .getRequestHandler(name);
298: if (handler != null) {
299: handler.handle(req, res, name);
300: } else {
301: openErrorHandler(req, res,
302: HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
303: }
304: }
305:
306: /**
307: * Displays an error code handler loaded from the OpenCms VFS,
308: * or if such a page does not exist,
309: * displays the default servlet container error code.<p>
310: *
311: * @param req the current request
312: * @param res the current response
313: * @param errorCode the error code to display
314: * @throws IOException if something goes wrong
315: * @throws ServletException if something goes wrong
316: */
317: protected void openErrorHandler(HttpServletRequest req,
318: HttpServletResponse res, int errorCode) throws IOException,
319: ServletException {
320:
321: String handlerUri = (new StringBuffer(64)).append(
322: HANDLE_VFS_PATH).append(errorCode).append(
323: HANDLE_VFS_SUFFIX).toString();
324: CmsObject cms;
325: CmsFile file;
326: try {
327: // create OpenCms context
328: cms = OpenCms.initCmsObject(OpenCms.getDefaultUsers()
329: .getUserGuest());
330: cms.getRequestContext().setUri(handlerUri);
331: // read the error handler file
332: file = cms.readFile(handlerUri,
333: CmsResourceFilter.IGNORE_EXPIRATION);
334: } catch (CmsException e) {
335: // unlikely to happen as the OpenCms "Guest" context can always be initialized
336: CmsMessageContainer container = Messages.get().container(
337: Messages.LOG_INIT_CMSOBJECT_IN_HANDLER_2,
338: new Integer(errorCode), handlerUri);
339: if (LOG.isWarnEnabled()) {
340: LOG.warn(org.opencms.jsp.Messages.getLocalizedMessage(
341: container, req), e);
342: }
343: // however, if it _does_ happen, then we really can't continue here
344: if (!res.isCommitted()) {
345: // since the handler file is not accessible, display the default error page
346: res.sendError(errorCode, e.getLocalizedMessage());
347: }
348: return;
349: }
350: try {
351: // provide the original error code in a request attribute
352: req.setAttribute(CmsRequestUtil.ATTRIBUTE_ERRORCODE,
353: new Integer(errorCode));
354: OpenCms.getResourceManager().loadResource(cms, file, req,
355: res);
356: } catch (CmsException e) {
357: // unable to load error page handler VFS resource
358: CmsMessageContainer container = Messages.get().container(
359: Messages.ERR_SHOW_ERR_HANDLER_RESOURCE_2,
360: new Integer(errorCode), handlerUri);
361: throw new ServletException(org.opencms.jsp.Messages
362: .getLocalizedMessage(container, req), e);
363: }
364: }
365: }
|