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.jetty;
020:
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.nio.channels.ReadableByteChannel;
025: import java.nio.channels.WritableByteChannel;
026: import java.util.Enumeration;
027: import java.util.Iterator;
028: import java.util.logging.Level;
029:
030: import org.mortbay.jetty.HttpConnection;
031: import org.restlet.Server;
032: import org.restlet.data.Parameter;
033: import org.restlet.data.Response;
034: import org.restlet.data.Status;
035: import org.restlet.util.Series;
036:
037: import com.noelios.restlet.http.HttpServerCall;
038:
039: /**
040: * Call that is used by the Jetty 6 HTTP server connector.
041: *
042: * @author Jerome Louvel (contact@noelios.com)
043: */
044: public class JettyCall extends HttpServerCall {
045: /** The wrapped Jetty HTTP connection. */
046: private HttpConnection connection;
047:
048: /** Indicates if the request headers were parsed and added. */
049: private boolean requestHeadersAdded;
050:
051: /**
052: * Constructor.
053: *
054: * @param server
055: * The parent server.
056: * @param connection
057: * The wrapped Jetty HTTP connection.
058: */
059: public JettyCall(Server server, HttpConnection connection) {
060: super (server);
061: this .connection = connection;
062: this .requestHeadersAdded = false;
063: }
064:
065: @Override
066: public String getClientAddress() {
067: return getConnection().getRequest().getRemoteAddr();
068: }
069:
070: @Override
071: public int getClientPort() {
072: return getConnection().getRequest().getRemotePort();
073: }
074:
075: /**
076: * Returns the wrapped Jetty HTTP connection.
077: *
078: * @return The wrapped Jetty HTTP connection.
079: */
080: public HttpConnection getConnection() {
081: return this .connection;
082: }
083:
084: /**
085: * Returns the request method.
086: *
087: * @return The request method.
088: */
089: public String getMethod() {
090: return getConnection().getRequest().getMethod();
091: }
092:
093: /**
094: * Returns the request entity channel if it exists.
095: *
096: * @return The request entity channel if it exists.
097: */
098: public ReadableByteChannel getRequestChannel() {
099: return null;
100: }
101:
102: /**
103: * Returns the list of request headers.
104: *
105: * @return The list of request headers.
106: */
107: @SuppressWarnings("unchecked")
108: public Series<Parameter> getRequestHeaders() {
109: Series<Parameter> result = super .getRequestHeaders();
110:
111: if (!requestHeadersAdded) {
112: // Copy the headers from the request object
113: String headerName;
114: String headerValue;
115: for (Enumeration<String> names = getConnection()
116: .getRequest().getHeaderNames(); names
117: .hasMoreElements();) {
118: headerName = names.nextElement();
119: for (Enumeration<String> values = getConnection()
120: .getRequest().getHeaders(headerName); values
121: .hasMoreElements();) {
122: headerValue = values.nextElement();
123: result.add(new Parameter(headerName, headerValue));
124: }
125: }
126:
127: requestHeadersAdded = true;
128: }
129:
130: return result;
131: }
132:
133: /**
134: * Returns the request entity stream if it exists.
135: *
136: * @return The request entity stream if it exists.
137: */
138: public InputStream getRequestStream() {
139: try {
140: return getConnection().getRequest().getInputStream();
141: } catch (IOException e) {
142: return null;
143: }
144: }
145:
146: /**
147: * Returns the URI on the request line (most like a relative reference, but
148: * not necessarily).
149: *
150: * @return The URI on the request line.
151: */
152: public String getRequestUri() {
153: return getConnection().getRequest().getUri().toString();
154: }
155:
156: /**
157: * Returns the response channel if it exists.
158: *
159: * @return The response channel if it exists.
160: */
161: public WritableByteChannel getResponseChannel() {
162: return null;
163: }
164:
165: /**
166: * Returns the response stream if it exists.
167: *
168: * @return The response stream if it exists.
169: */
170: public OutputStream getResponseStream() {
171: try {
172: return getConnection().getResponse().getOutputStream();
173: } catch (IOException e) {
174: return null;
175: }
176: }
177:
178: /**
179: * Returns the response address.<br/> Corresponds to the IP address of the
180: * responding server.
181: *
182: * @return The response address.
183: */
184: public String getServerAddress() {
185: return getConnection().getRequest().getLocalAddr();
186: }
187:
188: /**
189: * Indicates if the request was made using a confidential mean.<br/>
190: *
191: * @return True if the request was made using a confidential mean.<br/>
192: */
193: public boolean isConfidential() {
194: return getConnection().getRequest().isSecure();
195: }
196:
197: @Override
198: public void sendResponse(Response response) throws IOException {
199: // Add call headers
200: Parameter header;
201: for (Iterator<Parameter> iter = getResponseHeaders().iterator(); iter
202: .hasNext();) {
203: header = iter.next();
204: getConnection().getResponse().addHeader(header.getName(),
205: header.getValue());
206: }
207:
208: // Set the status code in the response. We do this after adding the
209: // headers because when we have to rely on the 'sendError' method,
210: // the Servlet containers are expected to commit their response.
211: if (Status.isError(getStatusCode()) && (response == null)) {
212: try {
213: getConnection().getResponse().sendError(
214: getStatusCode(), getReasonPhrase());
215: } catch (IOException ioe) {
216: getLogger().log(Level.WARNING,
217: "Unable to set the response error status", ioe);
218: }
219: } else {
220: // Send the response entity
221: getConnection().getResponse().setStatus(getStatusCode());
222: super .sendResponse(response);
223: }
224:
225: // Fully complete and commit the response
226: this .connection.completeResponse();
227: this .connection.commitResponse(true);
228: }
229:
230: }
|