com.noelios.restlet.local.EntityClientHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.restlet
Show all versions of org.apache.servicemix.bundles.restlet
This OSGi bundle wraps org.restlet, and com.noelios.restlet ${pkgVersion} jar files.
The newest version!
/**
* Copyright 2005-2008 Noelios Technologies.
*
* The contents of this file are subject to the terms of the following open
* source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.gnu.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.sun.com/cddl/cddl.html
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royaltee free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.noelios.com/products/restlet-engine
*
* Restlet is a registered trademark of Noelios Technologies.
*/
package com.noelios.restlet.local;
import java.util.Collection;
import java.util.Iterator;
import org.restlet.Client;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Preference;
import org.restlet.data.Reference;
import org.restlet.data.ReferenceList;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.Representation;
import org.restlet.service.MetadataService;
/**
* Connector to the local entities. That connector supports the content
* negotiation feature (i.e. for GET and HEAD methods) and implements the
* response to GET/HEAD methods.
*
* @author Thierry Boileau
*/
public abstract class EntityClientHelper extends LocalClientHelper {
/**
* Constructor.
*
* @param client
* The client to help.
*/
public EntityClientHelper(Client client) {
super(client);
}
/**
* Generate a Reference for a variant name (which is URL decoded) and handle
* the translation between the incoming requested path (which is URL
* encoded).
*
* @param scheme
* The scheme of the requested resource.
* @param encodedParentDirPath
* The encoded path of the parent dir of the requested resource.
* @param encodedEntityName
* The encoded name of the requested resource.
* @param decodedVariantName
* The decoded name of a returned resource.
* @return A new Reference.
*/
public Reference createReference(String scheme,
String encodedParentDirPath, String encodedEntityName,
String decodedVariantName) {
Reference result = new Reference(scheme
+ "://"
+ encodedParentDirPath
+ "/"
+ getReencodedVariantEntityName(encodedEntityName,
decodedVariantName));
return result;
}
/**
* Returns a local entity for the given path.
*
* @param path
* The path of the entity.
* @return A local entity for the given path.
*/
public abstract Entity getEntity(String path);
/**
* Percent-encodes the given percent-decoded variant name of a resource
* whose percent-encoded name is given. Tries to match the longest common
* part of both encoded entity name and decoded variant name.
*
* @param encodedEntityName
* the percent-encoded name of the initial resource
* @param decodedVariantEntityName
* the percent-decoded entity name of a variant of the initial
* resource.
* @return The variant percent-encoded entity name.
*/
protected String getReencodedVariantEntityName(String encodedEntityName,
String decodedVariantEntityName) {
int i = 0;
int j = 0;
boolean stop = false;
char[] encodeds = encodedEntityName.toCharArray();
char[] decodeds = decodedVariantEntityName.toCharArray();
for (i = 0; (i < decodeds.length) && (j < encodeds.length) && !stop; i++) {
char decodedChar = decodeds[i];
char encodedChar = encodeds[j];
if (encodedChar == '%') {
String dec = Reference.decode(encodedEntityName.substring(j,
j + 3));
if (decodedChar == dec.charAt(0)) {
j += 3;
} else {
stop = true;
}
} else if (decodedChar == encodedChar) {
j++;
} else {
String dec = Reference.decode(encodedEntityName.substring(j,
j + 1));
if (decodedChar == dec.charAt(0)) {
j++;
} else {
stop = true;
}
}
}
if (stop) {
return encodedEntityName.substring(0, j)
+ decodedVariantEntityName.substring(i - 1);
}
if (j == encodedEntityName.length()) {
return encodedEntityName.substring(0, j)
+ decodedVariantEntityName.substring(i);
}
return encodedEntityName.substring(0, j - 1);
}
/**
* Handles a call.
*
* @param request
* The request to handle.
* @param response
* The response to update.
*/
@Override
public void handle(Request request, Response response) {
// Ensure that all ".." and "." are normalized into the path
// to prevent unauthorized access to user directories.
request.getResourceRef().normalize();
String path = request.getResourceRef().getPath();
// As the path may be percent-encoded, it has to be percent-decoded.
// Then, all generated uris must be encoded.
final String decodedPath = Reference.decode(path);
final MetadataService metadataService = getMetadataService(request);
// Finally, actually handle the call
handleEntity(request, response, path, decodedPath, metadataService);
}
/**
* Handles a call for a local entity. By default, only GET and HEAD methods
* are implemented.
*
* @param request
* The request to handle.
* @param response
* The response to update.
* @param path
* The entity path.
* @param decodedPath
* The URL decoded entity path.
* @param metadataService
* The metadataService.
*/
protected void handleEntity(Request request, Response response,
String path, final String decodedPath,
final MetadataService metadataService) {
if (Method.GET.equals(request.getMethod())
|| Method.HEAD.equals(request.getMethod())) {
handleEntityGet(request, response, path, getEntity(decodedPath),
metadataService);
} else {
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
response.getAllowedMethods().add(Method.GET);
response.getAllowedMethods().add(Method.HEAD);
}
}
/**
* Handles a GET call.
*
* @param request
* The request to answer.
* @param response
* The response to update.
* @param path
* The encoded path of the requested entity.
* @param entity
* The requested entity (normal or directory).
* @param metadataService
* The metadata service.
*/
protected void handleEntityGet(Request request, Response response,
String path, Entity entity, final MetadataService metadataService) {
Representation output = null;
// Get variants for a resource
boolean found = false;
final Iterator> iterator = request
.getClientInfo().getAcceptedMediaTypes().iterator();
while (iterator.hasNext() && !found) {
final Preference pref = iterator.next();
found = pref.getMetadata().equals(MediaType.TEXT_URI_LIST);
}
if (found) {
// Try to list all variants of this resource
// 1- set up base name as the longest part of the name without known
// extensions (beginning from the left)
final String baseName = entity.getBaseName(metadataService);
// 2- looking for resources with the same base name
Entity parent = entity.getParent();
if (parent != null) {
final Collection entities = parent.getChildren();
if (entities != null) {
final ReferenceList rl = new ReferenceList(entities.size());
final String scheme = request.getResourceRef().getScheme();
final String encodedParentDirectoryURI = path.substring(0,
path.lastIndexOf("/"));
final String encodedEntityName = path.substring(path
.lastIndexOf("/") + 1);
for (final Entity entry : entities) {
if (baseName.equals(entry.getBaseName(metadataService))) {
rl.add(createReference(scheme,
encodedParentDirectoryURI,
encodedEntityName, entry.getName()));
}
}
output = rl.getTextRepresentation();
}
}
} else {
if (entity.exists()) {
if (entity.isDirectory()) {
// Return the directory listing
final Collection children = entity.getChildren();
final ReferenceList rl = new ReferenceList(children.size());
String directoryUri = request.getResourceRef().toString();
// Ensures that the directory URI ends with a slash
if (!directoryUri.endsWith("/")) {
directoryUri += "/";
}
for (final Entity entry : children) {
rl
.add(directoryUri
+ Reference.encode(entry.getName()));
}
output = rl.getTextRepresentation();
} else {
// Return the file content
output = entity.getRepresentation(metadataService
.getDefaultMediaType(), getTimeToLive());
output.setIdentifier(request.getResourceRef());
updateMetadata(metadataService, entity.getName(), output);
}
} else {
// We look for the possible variant which has the same
// extensions in a distinct order.
Entity uniqueVariant = null;
// 1- set up base name as the longest part of the name without
// known extensions (beginning from the left)
final String baseName = entity.getBaseName(metadataService);
final Collection extensions = entity
.getExtensions(metadataService);
// 2- loooking for resources with the same base name
Entity parent = entity.getParent();
if (parent != null) {
final Collection files = parent.getChildren();
if (files != null) {
for (final Entity entry : files) {
if (baseName.equals(entry
.getBaseName(metadataService))) {
final Collection entryExtensions = entry
.getExtensions(metadataService);
if (entryExtensions.containsAll(extensions)
&& extensions
.containsAll(entryExtensions)) {
// The right representation has been found.
uniqueVariant = entry;
break;
}
}
}
}
}
if (uniqueVariant != null) {
// Return the file content
output = uniqueVariant.getRepresentation(metadataService
.getDefaultMediaType(), getTimeToLive());
output.setIdentifier(request.getResourceRef());
updateMetadata(metadataService, entity.getName(), output);
}
}
}
if (output == null) {
response.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
} else {
output.setIdentifier(request.getResourceRef());
response.setEntity(output);
response.setStatus(Status.SUCCESS_OK);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy