001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package com.noelios.restlet.ext.servlet;
020:
021: import java.io.IOException;
022:
023: import javax.servlet.ServletContext;
024: import javax.servlet.ServletException;
025: import javax.servlet.http.HttpServletRequest;
026: import javax.servlet.http.HttpServletResponse;
027:
028: import org.restlet.Context;
029: import org.restlet.Restlet;
030: import org.restlet.data.Reference;
031:
032: import com.noelios.restlet.http.HttpRequest;
033: import com.noelios.restlet.http.HttpResponse;
034: import com.noelios.restlet.http.HttpServerConverter;
035:
036: /**
037: * HTTP converter from Servlet calls to Restlet calls. This class can be used in
038: * any Servlet, just create a new instance and override the service() method in
039: * your Servlet to delegate all those calls to this class's service() method.
040: * Remember to set the target Restlet, for example using a Restlet Router
041: * instance. You can get the Restlet context directly on instances of this
042: * class, it will be based on the parent Servlet's context for logging purpose.<br/>
043: * <br/>
044: *
045: * This class is especially useful when directly integrating Restlets with
046: * Spring managed Web applications. Here is a simple usage example:
047: *
048: * <pre>
049: * public class TestServlet extends HttpServlet {
050: * private ServletConverter converter;
051: *
052: * public void init() throws ServletException {
053: * super.init();
054: * this.converter = new ServletConverter(getServletContext());
055: *
056: * Restlet trace = new Restlet(this.converter.getContext()) {
057: * public void handle(Request req, Response res) {
058: * getLogger().info("Hello World");
059: * res.setEntity("Hello World!", MediaType.TEXT_PLAIN);
060: * }
061: * };
062: *
063: * this.converter.setTarget(trace);
064: * }
065: *
066: * protected void service(HttpServletRequest req, HttpServletResponse res)
067: * throws ServletException, IOException {
068: * this.converter.service(req, res);
069: * }
070: * }
071: * </pre>
072: *
073: * @author Jerome Louvel (contact@noelios.com)
074: */
075: public class ServletConverter extends HttpServerConverter {
076: /** The target Restlet. */
077: private Restlet target;
078:
079: /**
080: * Constructor. Remember to manually set the "target" property before
081: * invoking the service() method.
082: *
083: * @param context
084: * The Servlet context.
085: */
086: public ServletConverter(ServletContext context) {
087: this (context, null);
088: }
089:
090: /**
091: * Constructor.
092: *
093: * @param context
094: * The Servlet context.
095: * @param target
096: * The target Restlet.
097: */
098: public ServletConverter(ServletContext context, Restlet target) {
099: super (new Context(new ServletLogger(context)));
100: this .target = target;
101: }
102:
103: /**
104: * Services a HTTP Servlet request as a Restlet request handled by the
105: * "target" Restlet.
106: *
107: * @param request
108: * The HTTP Servlet request.
109: * @param response
110: * The HTTP Servlet response.
111: */
112: public void service(HttpServletRequest request,
113: HttpServletResponse response) throws ServletException,
114: IOException {
115: if (getTarget() != null) {
116: // Convert the Servlet call to a Restlet call
117: ServletCall servletCall = new ServletCall(getLogger(),
118: request.getLocalAddr(), request.getLocalPort(),
119: request, response);
120: HttpRequest httpRequest = toRequest(servletCall);
121: HttpResponse httpResponse = new HttpResponse(servletCall,
122: httpRequest);
123:
124: // Adjust the relative reference
125: httpRequest.getResourceRef()
126: .setBaseRef(getBaseRef(request));
127:
128: // Adjust the root reference
129: httpRequest.setRootRef(getRootRef(request));
130:
131: // Handle the request and commit the response
132: getTarget().handle(httpRequest, httpResponse);
133: commit(httpResponse);
134: } else {
135: getLogger().warning("Unable to find the Restlet target");
136: }
137: }
138:
139: /**
140: * Returns the base reference of new Restlet requests.
141: *
142: * @param request
143: * The Servlet request.
144: * @return The base reference of new Restlet requests.
145: */
146: public Reference getBaseRef(HttpServletRequest request) {
147: Reference result = null;
148: String basePath = request.getContextPath()
149: + request.getServletPath();
150: String baseUri = request.getRequestURL().toString();
151: int baseIndex = baseUri.indexOf(basePath);
152: if (baseIndex != -1) {
153: result = new Reference(baseUri.substring(0, baseIndex
154: + basePath.length()));
155: }
156:
157: return result;
158: }
159:
160: /**
161: * Returns the root reference of new Restlet requests. By default it returns
162: * the result of getBaseRef().
163: *
164: * @param request
165: * The Servlet request.
166: * @return The root reference of new Restlet requests.
167: */
168: public Reference getRootRef(HttpServletRequest request) {
169: return getBaseRef(request);
170: }
171:
172: /**
173: * Returns the target Restlet.
174: *
175: * @return The target Restlet.
176: */
177: public Restlet getTarget() {
178: return this .target;
179: }
180:
181: /**
182: * Sets the target Restlet.
183: *
184: * @param target
185: * The target Restlet.
186: */
187: public void setTarget(Restlet target) {
188: this.target = target;
189: }
190:
191: }
|