001: /*
002: * $Id: APIServlet.java,v 1.285 2007/09/18 08:45:03 agoubard Exp $
003: *
004: * Copyright 2003-2007 Orange Nederland Breedband B.V.
005: * See the COPYRIGHT file for redistribution and use restrictions.
006: */
007: package org.xins.server;
008:
009: import java.io.IOException;
010:
011: import javax.servlet.ServletConfig;
012: import javax.servlet.ServletContext;
013: import javax.servlet.ServletException;
014: import javax.servlet.http.HttpServlet;
015: import javax.servlet.http.HttpServletRequest;
016: import javax.servlet.http.HttpServletResponse;
017:
018: import org.xins.common.MandatoryArgumentChecker;
019:
020: /**
021: * HTTP servlet that forwards requests to an <code>API</code>.
022: *
023: * <h3>HTTP status codes</h3>
024: *
025: * <p>This servlet supports various HTTP methods, depending on the calling
026: * conventions. A request with an unsupported method makes this servlet
027: * return the HTTP status code <code>405 Method Not Allowed</code>.
028: *
029: * <p>If no matching function is found, then this servlet returns HTTP status
030: * code <code>404 Not Found</code>.
031: *
032: * <p>If the servlet is temporarily unavailable, then the HTTP status
033: * <code>503 Service Unavailable</code> is returned.
034: *
035: * <p>If the servlet encountered an initialization error, then the HTTP status
036: * code <code>500 Internal Server Error</code> is returned.
037: *
038: * <p>If the state is <em>ready</em> then the HTTP status code
039: * <code>200 OK</code> is returned.
040: *
041: *
042: * <h3>Initialization</h3>
043: *
044: * <p>When the servlet is initialized, it gathers configuration information
045: * from different sources:
046: *
047: * <dl>
048: * <dt><strong>1. Build-time settings</strong></dt>
049: * <dd>The application package contains a <code>web.xml</code> file with
050: * build-time settings. Some of these settings are required in order
051: * for the XINS/Java Server Framework to start up, while others are
052: * optional. These build-time settings are passed to the servlet by the
053: * application server as a {@link ServletConfig} object. See
054: * {@link #init(ServletConfig)}.
055: * <br>The servlet configuration is the responsibility of the
056: * <em>assembler</em>.</dd>
057: *
058: * <dt><strong>2. System properties</strong></dt>
059: * <dd>The location of the configuration file must be passed to the Java VM
060: * at startup, as a system property.
061: * <br>System properties are the responsibility of the
062: * <em>system administrator</em>.
063: * <br>Example:
064: * <br><code>java -Dorg.xins.server.config=`pwd`/config/xins.properties
065: * -jar orion.jar</code></dd>
066: *
067: * <dt><strong>3. Configuration file</strong></dt>
068: * <dd>The configuration file should contain runtime configuration
069: * settings, like the settings for the logging subsystem.
070: * <br>Runtime properties are the responsibility of the
071: * <em>system administrator</em>.
072: * <br>Example contents for a configuration file:
073: * <blockquote><code>log4j.rootLogger=DEBUG, console
074: * <br>log4j.appender.console=org.apache.log4j.ConsoleAppender
075: * <br>log4j.appender.console.layout=org.apache.log4j.PatternLayout
076: * <br>log4j.appender.console.layout.ConversionPattern=%d %-5p [%c]
077: * %m%n</code></blockquote></dd>
078: * </dl>
079: *
080: * @version $Revision: 1.285 $ $Date: 2007/09/18 08:45:03 $
081: * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
082: * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
083: * @author <a href="mailto:mees.witteman@orange-ftgroup.com">Mees Witteman</a>
084: *
085: * @since XINS 1.0.0
086: */
087: public final class APIServlet extends HttpServlet {
088:
089: /**
090: * XINS server engine. Initially <code>null</code> but set to a
091: * non-<code>null</code> value in the {@link #init(ServletConfig)} method.
092: */
093: private Engine _engine;
094:
095: /**
096: * Initializes the loggers to log to the console using a simple format
097: * and no threshold. This is done by calling
098: * {@link Engine#configureLoggerFallback()}.
099: */
100: static {
101: ConfigManager.configureLoggerFallback();
102: }
103:
104: /**
105: * Constructs a new <code>APIServlet</code> object.
106: */
107: public APIServlet() {
108: // empty
109: }
110:
111: /**
112: * Returns information about this servlet, as plain text.
113: *
114: * @return
115: * textual description of this servlet, not <code>null</code> and not an
116: * empty character string.
117: */
118: public String getServletInfo() {
119: return "XINS/Java Server Framework " + Library.getVersion();
120: }
121:
122: /**
123: * Initializes this servlet using the specified configuration.
124: *
125: * @param config
126: * the {@link ServletConfig} object which contains bootstrap properties for
127: * this servlet, as specified by the <em>assembler</em>, cannot be
128: * <code>null</code>.
129: *
130: * @throws IllegalArgumentException
131: * if <code>config == null
132: * || config.{@link ServletConfig#getServletContext()} == null</code>.
133: *
134: * @throws ServletException
135: * if the servlet could not be initialized.
136: */
137: public void init(ServletConfig config)
138: throws IllegalArgumentException, ServletException {
139:
140: // Check arguments
141: MandatoryArgumentChecker.check("config", config);
142:
143: // Get the ServletContext
144: ServletContext context = config.getServletContext();
145: if (context == null) {
146: String message = "config.getServletContext() == null";
147: Log.log_3202(message);
148: throw new IllegalArgumentException(message);
149: }
150:
151: // Compare the expected with the implemented Java Servlet API version;
152: // versions 2.2, 2.3, 2.4 and 2.5 are supported
153: int major = context.getMajorVersion();
154: int minor = context.getMinorVersion();
155: if (major != 2 || minor < 2 || minor > 5) {
156: String expected = "2.2/2.3/2.4/2.5";
157: String actual = major + "." + minor;
158: Log.log_3203(actual, expected);
159: }
160:
161: // Construct an engine
162: try {
163: _engine = new Engine(config);
164:
165: // Fail silently, so that the servlet container will not keep trying to
166: // re-initialize this servlet (possibly on each call!)
167: } catch (Throwable exception) {
168: Log.log_3444(exception);
169: return;
170: }
171: }
172:
173: /**
174: * Returns the <code>ServletConfig</code> object which contains the
175: * bootstrap properties for this servlet. The returned {@link ServletConfig}
176: * object is the one passed to the {@link #init(ServletConfig)} method.
177: *
178: * @return
179: * the {@link ServletConfig} object that was used to initialize this
180: * servlet, or <code>null</code> if this servlet is not yet
181: * initialized.
182: */
183: public ServletConfig getServletConfig() {
184: return (_engine == null) ? null : _engine.getServletConfig();
185: }
186:
187: /**
188: * Handles an HTTP request to this servlet. If any of the arguments is
189: * <code>null</code>, then the behaviour of this method is undefined.
190: *
191: * @param request
192: * the servlet request, should not be <code>null</code>.
193: *
194: * @param response
195: * the servlet response, should not be <code>null</code>.
196: *
197: * @throws NullPointerException
198: * if this servlet is yet uninitialized.
199: *
200: * @throws IOException
201: * if there is an error error writing to the response output stream.
202: */
203: public void service(HttpServletRequest request,
204: HttpServletResponse response) throws NullPointerException,
205: IOException {
206:
207: // Engine failed to initialize, return '500 Internal Server Error'
208: if (_engine == null) {
209: response
210: .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
211: return;
212: }
213:
214: // Pass control to the Engine
215: _engine.service(request, response);
216: }
217:
218: /**
219: * Destroys this servlet. A best attempt will be made to release all
220: * resources.
221: *
222: * <p>After this method has finished, no more requests will be handled
223: * successfully.
224: */
225: public void destroy() {
226: if (_engine != null) {
227: _engine.destroy();
228: _engine = null;
229: }
230: }
231: }
|