io.personium.core.rs.box.PersoniumEngineSvcCollectionResource.java Source code

Java tutorial

Introduction

Here is the source code for io.personium.core.rs.box.PersoniumEngineSvcCollectionResource.java

Source

/**
 * personium.io
 * Copyright 2014 FUJITSU LIMITED
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.personium.core.rs.box;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.wink.webdav.WebDAVMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.personium.common.utils.PersoniumCoreUtils;
import io.personium.core.PersoniumCoreException;
import io.personium.core.PersoniumUnitConfig;
import io.personium.core.annotations.ACL;
import io.personium.core.auth.BoxPrivilege;
import io.personium.core.model.DavCmp;
import io.personium.core.model.DavMoveResource;
import io.personium.core.model.DavRsCmp;
import io.personium.core.model.impl.fs.DavCmpFsImpl;

/**
 * PersoniumEngineSvcCollectionResource?JAX-RS.
 */
public final class PersoniumEngineSvcCollectionResource {
    private static Logger log = LoggerFactory.getLogger(PersoniumEngineSvcCollectionResource.class);

    DavCmp davCmp = null;
    DavCollectionResource dcr = null;
    DavRsCmp davRsCmp;

    /**
     * constructor.
     * @param parent DavRsCmp
     * @param davCmp DavCmp
     */
    public PersoniumEngineSvcCollectionResource(final DavRsCmp parent, final DavCmp davCmp) {
        this.davCmp = davCmp;
        this.dcr = new DavCollectionResource(parent, davCmp);
        this.davRsCmp = new DavRsCmp(parent, davCmp);
    }

    /**
     * PROPFIND??.
     * @param requestBodyXml 
     * @param depth Depth
     * @param contentLength Content-Length 
     * @param transferEncoding Transfer-Encoding 
     * @return JAX-RS Response
     */
    @WebDAVMethod.PROPFIND
    public Response propfind(final Reader requestBodyXml,
            @HeaderParam(PersoniumCoreUtils.HttpHeaders.DEPTH) final String depth,
            @HeaderParam(HttpHeaders.CONTENT_LENGTH) final Long contentLength,
            @HeaderParam("Transfer-Encoding") final String transferEncoding) {

        return this.davRsCmp.doPropfind(requestBodyXml, depth, contentLength, transferEncoding,
                BoxPrivilege.READ_PROPERTIES, BoxPrivilege.READ_ACL);

    }

    /**
     * DELETE????????.
     * @return JAX-RS
     */
    @DELETE
    public Response delete() {
        // 
        // DavEngineSvcCollectionResource??(??Box)?????this.davRsCmp.getParent()???null???????
        this.davRsCmp.getParent().checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.WRITE);

        if (!this.davRsCmp.getDavCmp().isEmpty()) {
            throw PersoniumCoreException.Dav.HAS_CHILDREN;
        }
        return this.davCmp.delete(null, false).build();
    }

    /**
     * PROPPATCH??.
     * @param requestBodyXml 
     * @return JAX-RS Response
     */
    @WebDAVMethod.PROPPATCH
    public Response proppatch(final Reader requestBodyXml) {
        // 
        this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.WRITE_PROPERTIES);
        return this.davRsCmp.doProppatch(requestBodyXml);
    }

    /**
     * ACL??. ACL??.
     * @param reader XML
     * @return JAX-RS Response
     */
    @ACL
    public Response acl(final Reader reader) {
        // 
        this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.WRITE_ACL);
        return this.davCmp.acl(reader).build();
    }

    /**
     * OPTIONS.
     * @return JAX-RS Response
     */
    @OPTIONS
    public Response options() {
        // 
        this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.READ);
        return PersoniumCoreUtils.responseBuilderForOptions(HttpMethod.DELETE,
                io.personium.common.utils.PersoniumCoreUtils.HttpMethod.MOVE,
                io.personium.common.utils.PersoniumCoreUtils.HttpMethod.PROPFIND,
                io.personium.common.utils.PersoniumCoreUtils.HttpMethod.PROPPATCH,
                io.personium.common.utils.PersoniumCoreUtils.HttpMethod.ACL).build();
    }

    /**
     * ?Jax-RS?.
     * @return DavFileResource
     */
    @Path("__src")
    public PersoniumEngineSourceCollection src() {
        DavCmp nextCmp = this.davCmp.getChild(DavCmp.SERVICE_SRC_COLLECTION);
        if (nextCmp.exists()) {
            return new PersoniumEngineSourceCollection(this.davRsCmp, nextCmp);
        } else {
            // ??????404??
            throw PersoniumCoreException.Dav.RESOURCE_NOT_FOUND;
        }
    }

    /**
     * relay_GET.
     * @param path ??
     * @param uriInfo URI
     * @param headers 
     * @return JAX-RS Response
     */
    @Path("{path}")
    @GET
    public Response relayget(@PathParam("path") String path, @Context final UriInfo uriInfo,
            @Context HttpHeaders headers) {
        // 
        this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.EXEC);
        return relaycommon(HttpMethod.GET, uriInfo, path, headers, null);
    }

    /**
     * relay_POST.
     * @param path ??
     * @param uriInfo URI
     * @param headers 
     * @param is 
     * @return JAX-RS Response
     */
    @Path("{path}")
    @POST
    public Response relaypost(@PathParam("path") String path, @Context final UriInfo uriInfo,
            @Context HttpHeaders headers, final InputStream is) {
        // 
        this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.EXEC);
        return relaycommon(HttpMethod.POST, uriInfo, path, headers, is);
    }

    /**
     * relay_PUT.
     * @param path ??
     * @param uriInfo URI
     * @param headers 
     * @param is 
     * @return JAX-RS Response
     */
    @Path("{path}")
    @PUT
    public Response relayput(@PathParam("path") String path, @Context final UriInfo uriInfo,
            @Context HttpHeaders headers, final InputStream is) {
        // 
        this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.EXEC);
        return relaycommon(HttpMethod.PUT, uriInfo, path, headers, is);
    }

    /**
     * relay_DELETE.
     * @param path ??
     * @param uriInfo URI
     * @param headers 
     * @return JAX-RS Response
     */
    @Path("{path}")
    @DELETE
    public Response relaydelete(@PathParam("path") String path, @Context final UriInfo uriInfo,
            @Context HttpHeaders headers) {
        // 
        this.davRsCmp.checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.EXEC);
        return relaycommon(HttpMethod.DELETE, uriInfo, path, headers, null);
    }

    /**
     * relay??.
     * @param method 
     * @param uriInfo URI
     * @param path ??
     * @param headers 
     * @param is 
     * @return JAX-RS Response
     */
    public Response relaycommon(String method, UriInfo uriInfo, String path, HttpHeaders headers, InputStream is) {

        String cellName = this.davRsCmp.getCell().getName();
        String boxName = this.davRsCmp.getBox().getName();
        String requestUrl = String.format("http://%s:%s/%s/%s/%s/service/%s", PersoniumUnitConfig.getEngineHost(),
                PersoniumUnitConfig.getEnginePort(), PersoniumUnitConfig.getEnginePath(), cellName, boxName, path);

        // baseUrl?
        String baseUrl = uriInfo.getBaseUri().toString();

        // ???
        HttpClient client = new DefaultHttpClient();
        HttpUriRequest req = null;
        if (method.equals(HttpMethod.POST)) {
            HttpPost post = new HttpPost(requestUrl);
            InputStreamEntity ise = new InputStreamEntity(is, -1);
            ise.setChunked(true);
            post.setEntity(ise);
            req = post;
        } else if (method.equals(HttpMethod.PUT)) {
            HttpPut put = new HttpPut(requestUrl);
            InputStreamEntity ise = new InputStreamEntity(is, -1);
            ise.setChunked(true);
            put.setEntity(ise);
            req = put;
        } else if (method.equals(HttpMethod.DELETE)) {
            HttpDelete delete = new HttpDelete(requestUrl);
            req = delete;
        } else {
            HttpGet get = new HttpGet(requestUrl);
            req = get;
        }

        req.addHeader("X-Baseurl", baseUrl);
        req.addHeader("X-Request-Uri", uriInfo.getRequestUri().toString());
        if (davCmp instanceof DavCmpFsImpl) {
            DavCmpFsImpl dcmp = (DavCmpFsImpl) davCmp;
            req.addHeader("X-Personium-Fs-Path", dcmp.getFsPath());
            req.addHeader("X-Personium-Fs-Routing-Id", dcmp.getCellId());
        }
        req.addHeader("X-Personium-Box-Schema", this.davRsCmp.getBox().getSchema());

        // ???
        MultivaluedMap<String, String> multivalueHeaders = headers.getRequestHeaders();
        for (Iterator<Entry<String, List<String>>> it = multivalueHeaders.entrySet().iterator(); it.hasNext();) {
            Entry<String, List<String>> entry = it.next();
            String key = (String) entry.getKey();
            if (key.equalsIgnoreCase(HttpHeaders.CONTENT_LENGTH)) {
                continue;
            }
            List<String> valueList = (List<String>) entry.getValue();
            for (Iterator<String> i = valueList.iterator(); i.hasNext();) {
                String value = (String) i.next();
                req.setHeader(key, value);
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("?EngineRelay " + req.getMethod() + "  " + req.getURI());
            Header[] reqHeaders = req.getAllHeaders();
            for (int i = 0; i < reqHeaders.length; i++) {
                log.debug("RelayHeader[" + reqHeaders[i].getName() + "] : " + reqHeaders[i].getValue());
            }
        }

        // Engine??
        HttpResponse objResponse = null;
        try {
            objResponse = client.execute(req);
        } catch (ClientProtocolException e) {
            throw PersoniumCoreException.ServiceCollection.SC_INVALID_HTTP_RESPONSE_ERROR;
        } catch (Exception ioe) {
            throw PersoniumCoreException.ServiceCollection.SC_ENGINE_CONNECTION_ERROR.reason(ioe);
        }

        // 
        ResponseBuilder res = Response.status(objResponse.getStatusLine().getStatusCode());
        Header[] headersResEngine = objResponse.getAllHeaders();
        // ?
        for (int i = 0; i < headersResEngine.length; i++) {
            // Engine????Transfer-Encoding????
            // ?MW????????Content-Length???Transfer-Encoding????
            // 2??????????????????????
            if ("Transfer-Encoding".equalsIgnoreCase(headersResEngine[i].getName())) {
                continue;
            }
            // Engine????Date????
            // Web??MW?Jetty???2?????????
            if (HttpHeaders.DATE.equalsIgnoreCase(headersResEngine[i].getName())) {
                continue;
            }
            res.header(headersResEngine[i].getName(), headersResEngine[i].getValue());
        }

        InputStream isResBody = null;

        // ?
        HttpEntity entity = objResponse.getEntity();
        if (entity != null) {
            try {
                isResBody = entity.getContent();
            } catch (IllegalStateException e) {
                throw PersoniumCoreException.ServiceCollection.SC_UNKNOWN_ERROR.reason(e);
            } catch (IOException e) {
                throw PersoniumCoreException.ServiceCollection.SC_ENGINE_CONNECTION_ERROR.reason(e);
            }
            final InputStream isInvariable = isResBody;
            // ??
            StreamingOutput strOutput = new StreamingOutput() {
                @Override
                public void write(final OutputStream os) throws IOException {
                    int chr;
                    try {
                        while ((chr = isInvariable.read()) != -1) {
                            os.write(chr);
                        }
                    } finally {
                        isInvariable.close();
                    }
                }
            };
            res.entity(strOutput);
        }

        // ??
        return res.build();
    }

    /**
     * MOVE??.
     * @param headers 
     * @return JAX-RS
     */
    @WebDAVMethod.MOVE
    public Response move(@Context HttpHeaders headers) {
        // ??(????)
        this.davRsCmp.getParent().checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.WRITE);
        return new DavMoveResource(this.davRsCmp.getParent(), this.davRsCmp.getDavCmp(), headers).doMove();
    }
}