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.local;
020:
021: import java.io.File;
022: import java.io.IOException;
023: import java.net.URL;
024: import java.util.logging.Level;
025:
026: import org.restlet.Client;
027: import org.restlet.data.LocalReference;
028: import org.restlet.data.Method;
029: import org.restlet.data.Protocol;
030: import org.restlet.data.Reference;
031: import org.restlet.data.Request;
032: import org.restlet.data.Response;
033: import org.restlet.data.Status;
034: import org.restlet.resource.InputRepresentation;
035: import org.restlet.resource.Representation;
036: import org.restlet.service.MetadataService;
037:
038: /**
039: * Connector to the class loaders.
040: *
041: * @author Jerome Louvel (contact@noelios.com)
042: */
043: public class ClapClientHelper extends LocalClientHelper {
044: /**
045: * Constructor. Note that the common list of metadata associations based on
046: * extensions is added, see the addCommonExtensions() method.
047: *
048: * @param client
049: * The client to help.
050: */
051: public ClapClientHelper(Client client) {
052: super (client);
053: getProtocols().add(Protocol.CLAP);
054: }
055:
056: /**
057: * Handles a call.
058: *
059: * @param request
060: * The request to handle.
061: * @param response
062: * The response to update.
063: */
064: public void handle(Request request, Response response) {
065: String scheme = request.getResourceRef().getScheme();
066:
067: // Ensure that all ".." and "." are normalized into the path
068: // to preven unauthorized access to user directories.
069: request.getResourceRef().normalize();
070:
071: if (scheme.equalsIgnoreCase(Protocol.CLAP.getSchemeName())) {
072: LocalReference cr = new LocalReference(request
073: .getResourceRef());
074:
075: if (cr.getClapAuthorityType() == LocalReference.CLAP_CLASS) {
076: handleClassLoader(request, response, getClass()
077: .getClassLoader());
078: } else if (cr.getClapAuthorityType() == LocalReference.CLAP_SYSTEM) {
079: handleClassLoader(request, response, ClassLoader
080: .getSystemClassLoader());
081: } else if (cr.getClapAuthorityType() == LocalReference.CLAP_THREAD) {
082: handleClassLoader(request, response, Thread
083: .currentThread().getContextClassLoader());
084: }
085: } else {
086: throw new IllegalArgumentException(
087: "Protocol \""
088: + scheme
089: + "\" not supported by the connector. Only CLAP is supported.");
090: }
091: }
092:
093: /**
094: * Handles a call with a given class loader.
095: *
096: * @param request
097: * The request to handle.
098: * @param response
099: * The response to update.
100: */
101: protected void handleClassLoader(Request request,
102: Response response, ClassLoader classLoader) {
103: MetadataService metadataService = getMetadataService(request);
104:
105: if (request.getMethod().equals(Method.GET)
106: || request.getMethod().equals(Method.HEAD)) {
107: String path = request.getResourceRef().getPath();
108:
109: // Prepare a classloader URI, removing the leading slash
110: if ((path != null) && path.startsWith("/"))
111: path = path.substring(1);
112: // As the path may be percent-encoded, it has to be percent-decoded.
113: URL url = classLoader.getResource(Reference.decode(path));
114:
115: // The ClassLoader returns a directory listing in some cases.
116: // As this listing is partial, it is of little value in the context
117: // of the CLAP client, so we have to ignore them.
118: if (url != null) {
119: if (url.getProtocol().equals("file")) {
120: File file = new File(url.getFile());
121: if (file.isDirectory()) {
122: url = null;
123: }
124: }
125: }
126:
127: if (url != null) {
128: try {
129: Representation output = new InputRepresentation(url
130: .openStream(), metadataService
131: .getDefaultMediaType());
132: output.setIdentifier(request.getResourceRef());
133:
134: // Update the metadata based on file extensions
135: String name = path
136: .substring(path.lastIndexOf('/') + 1);
137: updateMetadata(metadataService, name, output);
138:
139: // Update the response
140: response.setEntity(output);
141: response.setStatus(Status.SUCCESS_OK);
142: } catch (IOException ioe) {
143: getLogger()
144: .log(
145: Level.WARNING,
146: "Unable to open the representation's input stream",
147: ioe);
148: response.setStatus(Status.SERVER_ERROR_INTERNAL);
149: }
150: } else {
151: response.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
152: }
153: } else {
154: response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
155: response.getAllowedMethods().add(Method.GET);
156: response.getAllowedMethods().add(Method.HEAD);
157: }
158: }
159:
160: }
|