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.application;
020:
021: import org.restlet.Application;
022: import org.restlet.Filter;
023: import org.restlet.data.CharacterSet;
024: import org.restlet.data.Encoding;
025: import org.restlet.data.Form;
026: import org.restlet.data.Language;
027: import org.restlet.data.MediaType;
028: import org.restlet.data.Metadata;
029: import org.restlet.data.Method;
030: import org.restlet.data.Preference;
031: import org.restlet.data.Request;
032: import org.restlet.data.Response;
033:
034: /**
035: * Filter tunnelling browser calls into full REST calls. The request method can
036: * be changed (via POST requests only) as well as the accepted media types,
037: * languages, encodings and character sets.
038: *
039: * @author Jerome Louvel (contact@noelios.com)
040: */
041: public class TunnelFilter extends Filter {
042: /** The application. */
043: private Application application;
044:
045: /**
046: * Constructor.
047: *
048: * @param application
049: * The parent application.
050: */
051: public TunnelFilter(Application application) {
052: super (application.getContext());
053: this .application = application;
054: }
055:
056: /**
057: * Returns the application.
058: *
059: * @return The application.
060: */
061: public Application getApplication() {
062: return this .application;
063: }
064:
065: /**
066: * Allows filtering before its handling by the target Restlet. Does nothing
067: * by default.
068: *
069: * @param request
070: * The request to handle.
071: * @param response
072: * The response to update.
073: */
074: public void beforeHandle(Request request, Response response) {
075: super .beforeHandle(request, response);
076: Form query = request.getResourceRef().getQueryAsForm(null);
077: boolean queryModified = false;
078:
079: // Tunnels the extracted attributes into the proper call objects.
080: if (getApplication().getTunnelService().isMethodTunnel()
081: && request.getMethod().equals(Method.POST)) {
082: String methodName = query.getFirstValue(getApplication()
083: .getTunnelService().getMethodParameter());
084:
085: if (methodName != null) {
086: request.setMethod(Method.valueOf(methodName));
087:
088: // The parameter is removed from the query
089: query.removeFirst(getApplication().getTunnelService()
090: .getMethodParameter());
091: queryModified = true;
092: }
093: }
094:
095: if (request.getMethod().equals(Method.GET)
096: && getApplication().getTunnelService()
097: .isPreferencesTunnel()) {
098: // Extract the header values
099: String acceptCharset = query.getFirstValue(getApplication()
100: .getTunnelService().getCharacterSetAttribute());
101: String acceptEncoding = query
102: .getFirstValue(getApplication().getTunnelService()
103: .getEncodingAttribute());
104: String acceptLanguage = query
105: .getFirstValue(getApplication().getTunnelService()
106: .getLanguageAttribute());
107: String acceptMediaType = query
108: .getFirstValue(getApplication().getTunnelService()
109: .getMediaTypeAttribute());
110:
111: // Parse the headers and update the call preferences
112: Metadata metadata = null;
113: if (acceptCharset != null) {
114: metadata = getApplication().getMetadataService()
115: .getMetadata(acceptCharset);
116:
117: if (metadata instanceof CharacterSet) {
118: request.getClientInfo().getAcceptedCharacterSets()
119: .clear();
120: request.getClientInfo().getAcceptedCharacterSets()
121: .add(
122: new Preference<CharacterSet>(
123: (CharacterSet) metadata));
124:
125: // The parameter is removed from the query
126: query.removeFirst(getApplication()
127: .getTunnelService()
128: .getCharacterSetAttribute());
129: queryModified = true;
130: }
131: }
132:
133: if (acceptEncoding != null) {
134: metadata = getApplication().getMetadataService()
135: .getMetadata(acceptEncoding);
136:
137: if (metadata instanceof Encoding) {
138: request.getClientInfo().getAcceptedEncodings()
139: .clear();
140: request.getClientInfo().getAcceptedEncodings().add(
141: new Preference<Encoding>(
142: (Encoding) metadata));
143:
144: // The parameter is removed from the query
145: query.removeFirst(getApplication()
146: .getTunnelService().getEncodingAttribute());
147: queryModified = true;
148: }
149: }
150:
151: if (acceptLanguage != null) {
152: metadata = getApplication().getMetadataService()
153: .getMetadata(acceptLanguage);
154:
155: if (metadata instanceof Language) {
156: request.getClientInfo().getAcceptedLanguages()
157: .clear();
158: request.getClientInfo().getAcceptedLanguages().add(
159: new Preference<Language>(
160: (Language) metadata));
161:
162: // The parameter is removed from the query
163: query.removeFirst(getApplication()
164: .getTunnelService().getLanguageAttribute());
165: queryModified = true;
166: }
167: }
168:
169: if (acceptMediaType != null) {
170: metadata = getApplication().getMetadataService()
171: .getMetadata(acceptMediaType);
172:
173: if (metadata instanceof MediaType) {
174: request.getClientInfo().getAcceptedMediaTypes()
175: .clear();
176: request.getClientInfo().getAcceptedMediaTypes()
177: .add(
178: new Preference<MediaType>(
179: (MediaType) metadata));
180:
181: // The parameter is removed from the query
182: query
183: .removeFirst(getApplication()
184: .getTunnelService()
185: .getMediaTypeAttribute());
186: queryModified = true;
187: }
188: }
189: }
190:
191: // Update the query if it has been modified
192: if (queryModified) {
193: request.getResourceRef().setQuery(
194: query.getQueryString(null));
195: }
196: }
197:
198: }
|