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: package com.noelios.restlet.ext.asyncweb;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.OutputStream;
023: import java.nio.channels.ReadableByteChannel;
024: import java.nio.channels.WritableByteChannel;
025: import java.util.Iterator;
026:
027: import org.restlet.Server;
028: import org.restlet.data.CharacterSet;
029: import org.restlet.data.Parameter;
030: import org.restlet.data.Reference;
031: import org.restlet.util.Series;
032: import org.safehaus.asyncweb.http.HttpRequest;
033: import org.safehaus.asyncweb.http.HttpResponse;
034: import org.safehaus.asyncweb.http.ResponseStatus;
035: import org.safehaus.asyncweb.http.internal.HttpHeaders;
036: import org.safehaus.asyncweb.http.internal.Request;
037: import org.safehaus.asyncweb.http.internal.Response;
038:
039: import com.noelios.restlet.http.HttpServerCall;
040:
041: /**
042: * HttpServerCall implementation used by the AsyncServer.
043: *
044: * @author Lars Heuer (heuer[at]semagia.com) <a
045: * href="http://www.semagia.com/">Semagia</a>
046: */
047: public class AsyncWebServerCall extends HttpServerCall {
048: /** AsyncWeb request. */
049: private Request request;
050:
051: /** Indicates if the request headers were parsed and added. */
052: private boolean requestHeadersAdded;
053:
054: /**
055: * AsyncWeb response.
056: */
057: private Response response;
058:
059: /**
060: * Constructor.
061: *
062: * @param server
063: * The parent server connector.
064: * @param request
065: * The AsyncWebRequest.
066: * @param response
067: * The AsyncWebResponse.
068: * @param confidential
069: * Indicates if the server is acting in HTTPS mode.
070: */
071: public AsyncWebServerCall(Server server, HttpRequest request,
072: HttpResponse response, boolean confidential) {
073: super (server);
074: this .request = (Request) request;
075: this .requestHeadersAdded = false;
076: this .response = (Response) response;
077: setConfidential(confidential);
078: }
079:
080: @Override
081: public String getClientAddress() {
082: return request.getRemoteAddress();
083: }
084:
085: @Override
086: public int getClientPort() {
087: return request.getRemotePort();
088: }
089:
090: @SuppressWarnings("unchecked")
091: @Override
092: public String getRequestUri() {
093: StringBuilder stringBuilder = new StringBuilder(request
094: .getRequestURI());
095:
096: // The query seems to be automatically parsed and decoded by AsyncWeb.
097: // Therefore, we should rebuild the entire query string in order to
098: // generate a proper URI.
099: if (request.getParameterNames().hasNext()) {
100: stringBuilder.append("?");
101: for (Iterator<String> iterName = request
102: .getParameterNames(); iterName.hasNext();) {
103: String name = (String) iterName.next();
104: if (request.getParameterValues(name).hasNext()) {
105: for (Iterator<String> iterValue = request
106: .getParameterValues(name); iterValue
107: .hasNext();) {
108: String value = (String) iterValue.next();
109: // As the query seems to be decoded in the Latin1
110: // character set, we should encode it.
111: stringBuilder
112: .append(
113: Reference
114: .encode(
115: name,
116: CharacterSet.ISO_8859_1))
117: .append("=")
118: .append(
119: Reference
120: .encode(
121: value,
122: CharacterSet.ISO_8859_1));
123: if (iterValue.hasNext()) {
124: stringBuilder.append("&");
125: }
126: }
127:
128: }
129: if (iterName.hasNext()) {
130: stringBuilder.append("&");
131: }
132: }
133: }
134: return stringBuilder.toString();
135: }
136:
137: @Override
138: public String getMethod() {
139: return request.getMethod().getName();
140: }
141:
142: @Override
143: public Series<Parameter> getRequestHeaders() {
144: Series<Parameter> result = super .getRequestHeaders();
145:
146: if (!this .requestHeadersAdded) {
147: HttpHeaders headers = request.getHeaders();
148: int headerCount = headers.getSize();
149: for (int i = 0; i < headerCount; i++) {
150: result.add(headers.getHeaderName(i).getValue(), headers
151: .getHeaderValue(i).getValue());
152: }
153:
154: this .requestHeadersAdded = true;
155: }
156:
157: return result;
158: }
159:
160: @Override
161: public void writeResponseHead(
162: org.restlet.data.Response restletResponse)
163: throws IOException {
164: response.setStatus(ResponseStatus.forId(getStatusCode()),
165: getReasonPhrase());
166:
167: // Ensure that headers are empty
168: response.getHeaders().dispose();
169: for (Parameter header : super .getResponseHeaders()) {
170: response.addHeader(header.getName(), header.getValue());
171: }
172: }
173:
174: @Override
175: public ReadableByteChannel getRequestChannel() {
176: // Unsupported.
177: return null;
178: }
179:
180: @Override
181: public InputStream getRequestStream() {
182: return request.getInputStream();
183: }
184:
185: @Override
186: public WritableByteChannel getResponseChannel() {
187: // Unsupported.
188: return null;
189: }
190:
191: @Override
192: public OutputStream getResponseStream() {
193: return response.getOutputStream();
194: }
195:
196: }
|