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.simple;
020:
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.net.Socket;
025: import java.nio.channels.ReadableByteChannel;
026: import java.nio.channels.WritableByteChannel;
027:
028: import org.restlet.Server;
029: import org.restlet.data.Parameter;
030: import org.restlet.util.Series;
031:
032: import simple.http.Request;
033: import simple.http.Response;
034:
035: import com.noelios.restlet.http.HttpServerCall;
036:
037: /**
038: * Call that is used by the Simple HTTP server.
039: *
040: * @author Lars Heuer (heuer[at]semagia.com) <a
041: * href="http://semagia.com/">Semagia</a>
042: * @author Jerome Louvel (contact@noelios.com)
043: */
044: public class SimpleCall extends HttpServerCall {
045: /**
046: * Simple Request.
047: */
048: private Request request;
049:
050: /**
051: * Simple Response.
052: */
053: private Response response;
054:
055: /** Indicates if the request headers were parsed and added. */
056: private boolean requestHeadersAdded;
057:
058: /**
059: * Constructs this class with the specified {@link simple.http.Request} and
060: * {@link simple.http.Response}.
061: *
062: * @param server
063: * The parent server.
064: * @param request
065: * Request to wrap.
066: * @param response
067: * Response to wrap.
068: * @param confidential
069: * Indicates if this call is acting in HTTP or HTTPS mode.
070: */
071: SimpleCall(Server server, Request request, Response response,
072: boolean confidential) {
073: super (server);
074: this .request = request;
075: this .response = response;
076: setConfidential(confidential);
077: this .requestHeadersAdded = false;
078: }
079:
080: @Override
081: public String getClientAddress() {
082: return request.getInetAddress().getHostAddress();
083: }
084:
085: @Override
086: public int getClientPort() {
087: Socket sock = (Socket) request
088: .getAttribute(SimplePipelineFactory.PROPERTY_SOCKET);
089: return (sock != null) ? sock.getPort() : -1;
090: }
091:
092: /**
093: * Returns the request method.
094: *
095: * @return The request method.
096: */
097: public String getMethod() {
098: return request.getMethod();
099: }
100:
101: /**
102: * Returns the request entity channel if it exists.
103: *
104: * @return The request entity channel if it exists.
105: */
106: public ReadableByteChannel getRequestChannel() {
107: // Unsupported.
108: return null;
109: }
110:
111: /**
112: * Returns the list of request headers.
113: *
114: * @return The list of request headers.
115: */
116: public Series<Parameter> getRequestHeaders() {
117: Series<Parameter> result = super .getRequestHeaders();
118:
119: if (!this .requestHeadersAdded) {
120: int headerCount = request.headerCount();
121: for (int i = 0; i < headerCount; i++) {
122: result.add(new Parameter(request.getName(i), request
123: .getValue(i)));
124: }
125:
126: this .requestHeadersAdded = true;
127: }
128:
129: return result;
130: }
131:
132: /**
133: * Returns the request entity stream if it exists.
134: *
135: * @return The request entity stream if it exists.
136: */
137: public InputStream getRequestStream() {
138: try {
139: return request.getInputStream();
140: } catch (IOException ex) {
141: return null;
142: }
143: }
144:
145: /**
146: * Returns the full request URI.
147: *
148: * @return The full request URI.
149: */
150: public String getRequestUri() {
151: return request.getURI();
152: }
153:
154: /**
155: * Returns the response channel if it exists.
156: *
157: * @return The response channel if it exists.
158: */
159: public WritableByteChannel getResponseChannel() {
160: // Unsupported.
161: return null;
162: }
163:
164: /**
165: * Returns the response stream if it exists.
166: *
167: * @return The response stream if it exists.
168: */
169: public OutputStream getResponseStream() {
170: try {
171: return response.getOutputStream();
172: } catch (IOException ex) {
173: return null;
174: }
175: }
176:
177: @Override
178: public String getVersion() {
179: return request.getMajor() + "." + request.getMinor();
180: }
181:
182: @Override
183: public void writeResponseHead(
184: org.restlet.data.Response restletResponse)
185: throws IOException {
186: response.clear();
187: for (Parameter header : getResponseHeaders()) {
188: response.add(header.getName(), header.getValue());
189: }
190:
191: // Set the status
192: response.setCode(getStatusCode());
193: response.setText(getReasonPhrase());
194:
195: // To ensure that Simple doesn't switch to chunked encoding
196: if (restletResponse.getEntity() == null) {
197: response.setContentLength(0);
198: }
199: }
200: }
|