Package org.restlet.engine.local

Source Code of org.restlet.engine.local.EntityClientHelper

/**
* Copyright 2005-2011 Noelios Technologies.
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL 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.opensource.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.opensource.org/licenses/lgpl-2.1.php
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.opensource.org/licenses/cddl1.php
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty 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 org.restlet.engine.local;

import java.util.Collection;
import java.util.Iterator;

import org.restlet.Client;
import org.restlet.Request;
import org.restlet.Response;
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.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.Variant;

/**
* 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 directory 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);
    }

    /**
     * Handles a GET call.
     *
     * @param request
     *            The request to answer.
     * @param response
     *            The response to update.
     * @param entity
     *            The requested entity (normal or directory).
     */
    protected void handleEntityGet(Request request, Response response,
            Entity entity) {
        Representation output = null;

        // Get variants for a resource
        boolean found = false;
        Iterator<Preference<MediaType>> iterator = request.getClientInfo()
                .getAcceptedMediaTypes().iterator();
        while (iterator.hasNext() && !found) {
            Preference<MediaType> 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)
            String baseName = entity.getBaseName();

            // 2- looking for resources with the same base name
            Entity parent = entity.getParent();

            if (parent != null) {
                Collection<Entity> entities = parent.getChildren();

                if (entities != null) {
                    ReferenceList rl = new ReferenceList(entities.size());
                    String scheme = request.getResourceRef().getScheme();
                    String path = request.getResourceRef().getPath();
                    String encodedParentDirectoryURI = path.substring(0, path
                            .lastIndexOf("/"));
                    String encodedEntityName = path.substring(path
                            .lastIndexOf("/") + 1);

                    for (Entity entry : entities) {
                        if (baseName.equals(entry.getBaseName())) {
                            rl.add(createReference(scheme,
                                    encodedParentDirectoryURI,
                                    encodedEntityName, entry.getName()));
                        }
                    }

                    output = rl.getTextRepresentation();
                }
            }
        } else {
            if (entity.exists()) {
                if (entity.isDirectory()) {
                    // Return the directory listing
                    Collection<Entity> children = entity.getChildren();
                    ReferenceList rl = new ReferenceList(children.size());
                    String directoryUri = request.getResourceRef()
                            .getTargetRef().toString();

                    // Ensures that the directory URI ends with a slash
                    if (!directoryUri.endsWith("/")) {
                        directoryUri += "/";
                    }

                    for (Entity entry : children) {
                        if (entry.isDirectory()) {
                            rl.add(directoryUri
                                    + Reference.encode(entry.getName()) + "/");
                        } else {
                            rl.add(directoryUri
                                    + Reference.encode(entry.getName()));
                        }
                    }

                    output = rl.getTextRepresentation();
                } else {
                    // Return the file content
                    output = entity.getRepresentation(getMetadataService()
                            .getDefaultMediaType(), getTimeToLive());
                    output.setLocationRef(request.getResourceRef());
                    Entity.updateMetadata(entity.getName(), output, true,
                            getMetadataService());
                }
            } else {
                // We look for the possible variant which has the same
                // metadata based on extensions (in a distinct order) and
                // default metadata.
                Entity uniqueVariant = null;

                // 1- set up base name as the longest part of the name without
                // known extensions (beginning from the left)
                String baseName = entity.getBaseName();
                Variant entityVariant = entity.getVariant();

                // 2- looking for resources with the same base name
                Entity parent = entity.getParent();
                if (parent != null) {
                    Collection<Entity> files = parent.getChildren();

                    if (files != null) {
                        for (Entity entry : files) {
                            if (baseName.equals(entry.getBaseName())) {
                                Variant entryVariant = entry.getVariant();

                                if (entityVariant.isCompatible(entryVariant)) {
                                    // The right representation has been found.
                                    uniqueVariant = entry;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (uniqueVariant != null) {
                    // Return the file content
                    output = uniqueVariant.getRepresentation(
                            getMetadataService().getDefaultMediaType(),
                            getTimeToLive());
                    output.setLocationRef(request.getResourceRef());
                    Entity.updateMetadata(entity.getName(), output, true,
                            getMetadataService());
                }
            }
        }

        if (output == null) {
            response.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
        } else {
            output.setLocationRef(request.getResourceRef());
            response.setEntity(output);
            response.setStatus(Status.SUCCESS_OK);
        }
    }

    @Override
    protected void handleLocal(Request request, Response response,
            String decodedPath) {
        if (Method.GET.equals(request.getMethod())
                || Method.HEAD.equals(request.getMethod())) {
            handleEntityGet(request, response, getEntity(decodedPath));
        } else {
            response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
            response.getAllowedMethods().add(Method.GET);
            response.getAllowedMethods().add(Method.HEAD);
        }
    }
}
TOP

Related Classes of org.restlet.engine.local.EntityClientHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.