org.eclipse.orion.internal.server.servlets.file.ServletFileStoreHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.orion.internal.server.servlets.file.ServletFileStoreHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2010, 2013 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.orion.internal.server.servlets.file;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.core.filesystem.*;
import org.eclipse.core.filesystem.provider.FileInfo;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.orion.internal.server.servlets.ProtocolConstants;
import org.eclipse.orion.internal.server.servlets.ServletResourceHandler;
import org.eclipse.orion.server.core.ServerStatus;
import org.eclipse.orion.server.servlets.OrionServlet;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.osgi.util.NLS;
import org.json.JSONException;
import org.json.JSONObject;
import org.osgi.framework.Version;

/**
 * General responder for IFileStore. This class provides general support for serializing
 * and deserializing file and directory representations in server requests and responses.
 * Specific behavior for a particular request is performed by a separate handler
 * depending on file type and protocol version.
 */
public class ServletFileStoreHandler extends ServletResourceHandler<IFileStore> {
    public static VersionRange VERSION1 = new VersionRange("[1,2)"); //$NON-NLS-1$
    //The following two arrays must define their attributes in the same order
    private static int[] ATTRIBUTE_BITS = new int[] { EFS.ATTRIBUTE_ARCHIVE, EFS.ATTRIBUTE_EXECUTABLE,
            EFS.ATTRIBUTE_HIDDEN, EFS.ATTRIBUTE_IMMUTABLE, EFS.ATTRIBUTE_READ_ONLY, EFS.ATTRIBUTE_SYMLINK };
    private static String[] ATTRIBUTE_KEYS = new String[] { ProtocolConstants.KEY_ATTRIBUTE_ARCHIVE,
            ProtocolConstants.KEY_ATTRIBUTE_EXECUTABLE, ProtocolConstants.KEY_ATTRIBUTE_HIDDEN,
            ProtocolConstants.KEY_ATTRIBUTE_IMMUTABLE, ProtocolConstants.KEY_ATTRIBUTE_READ_ONLY,
            ProtocolConstants.KEY_ATTRIBUTE_SYMLINK };

    private final ServletResourceHandler<IFileStore> directorySerializerV1;
    private final ServletResourceHandler<IFileStore> fileSerializerV1;
    private final ServletResourceHandler<IFileStore> genericDirectorySerializer;
    private final ServletResourceHandler<IFileStore> genericFileSerializer;

    final ServletResourceHandler<IStatus> statusHandler;

    public static IFileInfo fromJSON(JSONObject object) {
        FileInfo info = (FileInfo) EFS.createFileInfo();
        copyJSONToFileInfo(object, info);
        return info;
    }

    /**
     * Copies any defined fields in the provided JSON object into the destination file info.
     * @param source The JSON object to copy fields from
     * @param destination The file info to copy fields to
     */
    public static void copyJSONToFileInfo(JSONObject source, FileInfo destination) {
        destination.setName(source.optString(ProtocolConstants.KEY_NAME, destination.getName()));
        destination.setLastModified(
                source.optLong(ProtocolConstants.KEY_LAST_MODIFIED, destination.getLastModified()));
        destination.setDirectory(source.optBoolean(ProtocolConstants.KEY_DIRECTORY, destination.isDirectory()));

        JSONObject attributes = source.optJSONObject(ProtocolConstants.KEY_ATTRIBUTES);
        if (attributes != null) {
            for (int i = 0; i < ATTRIBUTE_KEYS.length; i++) {
                //undefined means the client does not want to change the value, so can't interpret as false
                if (!attributes.isNull(ATTRIBUTE_KEYS[i]))
                    destination.setAttribute(ATTRIBUTE_BITS[i], attributes.optBoolean(ATTRIBUTE_KEYS[i]));
            }
        }
    }

    public static IFileInfo fromJSON(HttpServletRequest request) throws IOException, JSONException {
        return fromJSON(OrionServlet.readJSONRequest(request));
    }

    public static JSONObject toJSON(IFileStore store, IFileInfo info, URI location) {
        JSONObject result = new JSONObject();
        try {
            result.put(ProtocolConstants.KEY_NAME, info.getName());
            result.put(ProtocolConstants.KEY_LOCAL_TIMESTAMP, info.getLastModified());
            result.put(ProtocolConstants.KEY_DIRECTORY, info.isDirectory());
            result.put(ProtocolConstants.KEY_LENGTH, info.getLength());
            if (location != null) {
                result.put(ProtocolConstants.KEY_LOCATION, location);
                if (info.isDirectory())
                    try {
                        result.put(ProtocolConstants.KEY_CHILDREN_LOCATION, new URI(location.getScheme(),
                                location.getAuthority(), location.getPath(), "depth=1", location.getFragment())); //$NON-NLS-1$
                    } catch (URISyntaxException e) {
                        throw new RuntimeException(e);
                    }
            }
            result.put(ProtocolConstants.KEY_ATTRIBUTES, getAttributes(store, info));
        } catch (JSONException e) {
            //cannot happen because the key is non-null and the values are strings
            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * Returns a JSON Object containing the attributes supported and defined by the given file.
     */
    private static JSONObject getAttributes(IFileStore store, IFileInfo info) throws JSONException {
        int supported = store.getFileSystem().attributes();
        JSONObject attributes = new JSONObject();
        for (int i = 0; i < ATTRIBUTE_KEYS.length; i++)
            if ((supported & ATTRIBUTE_BITS[i]) != 0)
                attributes.put(ATTRIBUTE_KEYS[i], info.getAttribute(ATTRIBUTE_BITS[i]));
        return attributes;
    }

    public ServletFileStoreHandler(ServletResourceHandler<IStatus> statusHandler, ServletContext context) {
        this.statusHandler = statusHandler;
        fileSerializerV1 = new FileHandlerV1(statusHandler, context);
        genericFileSerializer = new GenericFileHandler(context);
        directorySerializerV1 = new DirectoryHandlerV1(statusHandler);
        genericDirectorySerializer = new GenericDirectoryHandler();
    }

    private boolean handleDirectory(HttpServletRequest request, HttpServletResponse response, IFileStore file)
            throws ServletException {
        String versionString = request.getHeader(ProtocolConstants.HEADER_ORION_VERSION);
        Version version = versionString == null ? null : new Version(versionString);
        ServletResourceHandler<IFileStore> handler;
        if (version != null && VERSION1.isIncluded(version))
            handler = directorySerializerV1;
        else
            handler = genericDirectorySerializer;
        return handler.handleRequest(request, response, file);
    }

    private boolean handleFile(HttpServletRequest request, HttpServletResponse response, IFileStore file)
            throws ServletException {
        //could plug in more complex mapping here
        String versionString = request.getHeader(ProtocolConstants.HEADER_ORION_VERSION);
        Version version = versionString == null ? null : new Version(versionString);
        ServletResourceHandler<IFileStore> handler;
        if (version != null && VERSION1.isIncluded(version))
            handler = fileSerializerV1;
        else
            handler = genericFileSerializer;
        return handler.handleRequest(request, response, file);
    }

    public boolean handleRequest(HttpServletRequest request, HttpServletResponse response, IFileStore file)
            throws ServletException {
        IFileInfo fileInfo;
        try {
            fileInfo = file.fetchInfo(EFS.NONE, null);
        } catch (CoreException e) {
            if (handleAuthFailure(request, response, e))
                return true;
            //assume file does not exist
            fileInfo = new FileInfo(file.getName());
            ((FileInfo) fileInfo).setExists(false);
        }
        if (!request.getMethod().equals("PUT") && !fileInfo.exists()) //$NON-NLS-1$
            return statusHandler.handleRequest(request, response, new ServerStatus(IStatus.ERROR, 404,
                    NLS.bind("File not found: {0}", request.getPathInfo()), null));
        if (fileInfo.isDirectory())
            return handleDirectory(request, response, file);
        return handleFile(request, response, file);
    }

}