io.personium.engine.rs.AbstractService.java Source code

Java tutorial

Introduction

Here is the source code for io.personium.engine.rs.AbstractService.java

Source

/**
 * Personium
 * Copyright 2014 - 2017 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.engine.rs;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import io.personium.engine.PersoniumEngineContext;
import io.personium.engine.PersoniumEngineException;
import io.personium.engine.source.ISourceManager;
import io.personium.engine.utils.PersoniumEngineConfig;

/**
 * Service.
 */
public abstract class AbstractService {
    /** . */
    private static Log log = LogFactory.getLog(AbstractService.class);

    /** ??. */
    private String sourcePath = "";
    /** Service??. */
    private String serviceName = "";
    /** . */
    @Context
    private ServletContext context;
    /** URL???????. */
    private static final String KEY_HEADER_BASEURL = "X-Baseurl";
    /** URL???????. */
    private static final String KEY_HEADER_REQUEST_URI = "X-Request-Uri";

    /** HTTP?. */
    private static final int PORT_HTTP = 80;
    /** HTTPS?. */
    private static final int PORT_HTTPS = 443;

    /** ??? . */
    @HeaderParam("X-Personium-Es-Index")
    private String index;
    /** ???. */
    @HeaderParam("X-Personium-Es-Type")
    private String type;
    /** ???ID. */
    @HeaderParam("X-Personium-Es-Id")
    private String id;
    /** ???RoutingID. */
    @HeaderParam("X-Personium-Es-Routing-Id")
    private String routingId;
    /** ???FsPath. */
    @HeaderParam("X-Personium-Fs-Path")
    private String fsPath;
    /** FsRoutingId obtained from the request header. */
    @HeaderParam("X-Personium-Fs-Routing-Id")
    private String fsRoutingId;

    /** . */
    String serviceSubject;

    /** ?. */
    ISourceManager sourceManager;

    /**
     * ????.
     * @return 
     */
    public final String getSourcePath() {
        return this.sourcePath;
    }

    /**
     * ???.
     * @param value 
     */
    public final void setSourcePath(final String value) {
        this.sourcePath = value;
    }

    /**
     * Service????.
     * @return Service??
     */
    public final String getServiceName() {
        return this.serviceName;
    }

    /**
     * Service???.
     * @param value Service??
     */
    public final void setServiceName(final String value) {
        this.serviceName = value;
    }

    /**
     * ??.
     * @return the index
     */
    public final String getIndex() {
        return index;
    }

    /**
     * ??.
     * @return the type
     */
    public final String getType() {
        return type;
    }

    /**
     * ID??.
     * @return the id
     */
    public final String getId() {
        return id;
    }

    /**
     * RoutingID??.
     * @return the routingId
     */
    public final String getRoutingId() {
        return routingId;
    }

    /**
     * FsPath??.
     * @return the fsPath
     */
    public final String getFsPath() {
        return fsPath;
    }

    /**
     * Get fsRoutingId.
     * @return fsRoutingId
     */
    public String getFsRoutingId() {
        return fsRoutingId;
    }

    /**
     * GET.
     * @param cell Cell??
     * @param schema URI
     * @param svcName ??
     * @param request 
     * @param response ?
     * @param is 
     * @return Response
     */
    @GET
    public final Response evalJsgiForGet(@PathParam("cell") final String cell,
            @PathParam("schema") final String schema, @PathParam("id") final String svcName,
            @Context final HttpServletRequest request, @Context final HttpServletResponse response,
            final InputStream is) {
        return run(cell, schema, svcName, request, response, is);
    }

    /**
     * POST.
     * @param cell Cell??
     * @param schema URI
     * @param svcName ??
     * @param request 
     * @param response ?
     * @param is 
     * @return Response
     */
    @POST
    public final Response evalJsgiForPost(@PathParam("cell") final String cell,
            @PathParam("schema") final String schema, @PathParam("id") final String svcName,
            @Context final HttpServletRequest request, @Context final HttpServletResponse response,
            final InputStream is) {
        return run(cell, schema, svcName, request, response, is);
    }

    /**
     * PUT.
     * @param cell Cell??
     * @param schema URI
     * @param svcName ??
     * @param request 
     * @param response ?
     * @param is 
     * @return Response
     */
    @PUT
    public final Response evalJsgiForPutMethod(@PathParam("cell") final String cell,
            @PathParam("schema") final String schema, @PathParam("id") final String svcName,
            @Context final HttpServletRequest request, @Context final HttpServletResponse response,
            final InputStream is) {
        return run(cell, schema, svcName, request, response, is);
    }

    /**
     * DELETE.
     * @param cell Cell??
     * @param schema URI
     * @param svcName ??
     * @param request 
     * @param response ?
     * @param is 
     * @return Response
     */
    @DELETE
    public final Response evalJsgiForDeleteMethod(@PathParam("cell") final String cell,
            @PathParam("schema") final String schema, @PathParam("id") final String svcName,
            @Context final HttpServletRequest request, @Context final HttpServletResponse response,
            final InputStream is) {
        return run(cell, schema, svcName, request, response, is);
    }

    /**
     * ??.
     * @param value 
     */
    public final void setServletContext(final ServletContext value) {
        this.context = value;
    }

    /**
     * ?.
     * @return 
     */
    public final ServletContext getServletContext() {
        return this.context;
    }

    /**
     * Service.
     * @param cell Cell??
     * @param schema URI
     * @param svcName ???
     * @param req Request
     * @param res Response
     * @param is 
     * @return Response
     */
    public final Response run(final String cell, final String schema, final String svcName,
            final HttpServletRequest req, final HttpServletResponse res, final InputStream is) {
        StringBuilder msg = new StringBuilder();
        msg.append("[" + PersoniumEngineConfig.getVersion() + "] " + ">>> Request Started ");
        msg.append(" method:");
        msg.append(req.getMethod());
        msg.append(" method:");
        msg.append(req.getRequestURL());
        msg.append(" url:");
        msg.append(cell);
        msg.append(" schema:");
        msg.append(schema);
        msg.append(" svcName:");
        msg.append(svcName);
        log.info(msg);

        // ? ????
        Enumeration<String> multiheaders = req.getHeaderNames();
        for (String headerName : Collections.list(multiheaders)) {
            Enumeration<String> headers = req.getHeaders(headerName);
            for (String header : Collections.list(headers)) {
                log.debug("RequestHeader['" + headerName + "'] = " + header);
            }
        }
        this.setServiceName(svcName);

        // ?URL??
        String targetCell = cell;
        if (cell == null) {
            targetCell = getCell();
        }
        String targetSchema = schema;
        if (schema == null) {
            targetSchema = getSchemaURI();
        }
        String targetServiceName = svcName;

        String baseUrl;
        try {
            baseUrl = parseRequestUri(req, res);
        } catch (MalformedURLException e) {
            // URL???????
            return makeErrorResponse("Server Error", PersoniumEngineException.STATUSCODE_SERVER_ERROR);
        }

        Response response = null;
        PersoniumEngineContext pecx = null;
        try {
            try {
                pecx = new PersoniumEngineContext();
            } catch (PersoniumEngineException e) {
                return errorResponse(e);
            }

            // ???
            try {
                this.sourceManager = this.getServiceCollectionManager();
                pecx.setSourceManager(this.sourceManager);
                this.serviceSubject = this.sourceManager.getServiceSubject();
            } catch (PersoniumEngineException e) {
                return errorResponse(e);
            }
            // ??
            pecx.loadGlobalObject(baseUrl, targetCell, targetSchema, targetSchema, targetServiceName);
            // ???
            String source = "";
            try {
                String sourceName = this.sourceManager.getScriptNameForServicePath(targetServiceName);
                source = this.sourceManager.getSource(sourceName);
            } catch (PersoniumEngineException e) {
                return errorResponse(e);
            } catch (Exception e) {
                log.info("User Script not found to targetCell(" + targetCell + ", targetschema(" + targetSchema
                        + "), targetServiceName(" + targetServiceName + ")");
                log.info(e.getMessage(), e);
                return errorResponse(new PersoniumEngineException("404 Not Found (User Script)",
                        PersoniumEngineException.STATUSCODE_NOTFOUND));
            }
            // JSGI
            try {
                response = pecx.runJsgi(source, req, res, is, this.serviceSubject);
            } catch (PersoniumEngineException e) {
                return errorResponse(e);
            } catch (Exception e) {
                log.warn(" unknown Exception(" + e.getMessage() + ")");
                return errorResponse(new PersoniumEngineException("404 Not Found (Service Execute Error)",
                        PersoniumEngineException.STATUSCODE_NOTFOUND));
            }
        } finally {
            IOUtils.closeQuietly(pecx);
        }
        return response;
    }

    /**
     * ??.
     * @param e Exception
     * @return Response
     */
    final Response errorResponse(final PersoniumEngineException e) {
        return makeErrorResponse(e.getMessage(), e.getStatusCode());
    }

    /**
     * ???.
     * @param msg 
     * @param code 
     * @return Response
     */
    private Response makeErrorResponse(final String msg, final int code) {
        return Response.status(code).header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML)
                .header(HttpHeaders.CONTENT_LENGTH, msg.getBytes().length).entity(msg).build();
    }

    /**
     * Cell???.
     * @return Cell??
     */
    public abstract String getCell();

    /**
     * URI?.
     * @return URI
     */
    public abstract String getSchemaURI();

    /**
     * ??.
     * @param req Request
     * @param res Response
     * @return URL
     * @throws MalformedURLException 
     */
    public final String parseRequestUri(final HttpServletRequest req, final HttpServletResponse res)
            throws MalformedURLException {
        String baseUrl = "";

        // URI??URI????????
        //  /personium-engine/engine-test/ds-engine-test/service/hello?a=b&c=d
        // DC??????URI?????????
        // ?Personium-Engine???URI???
        String requestUri = req.getHeader(KEY_HEADER_REQUEST_URI);
        if (requestUri == null || requestUri.length() == 0) {
            requestUri = req.getRequestURI();
            String query = req.getQueryString();
            if (query != null && query.length() > 0) {
                requestUri += "?" + query;
            }
        }

        // URI??????????
        // /personium-engine/engine-test/personium-engine-test/service/hello
        int indexQ = requestUri.indexOf("?");
        String scriptName = requestUri;
        if (indexQ > 0) {
            scriptName = requestUri.substring(0, indexQ);
        }

        // ?????JSGI????
        req.setAttribute("env.requestUri", requestUri);
        req.setAttribute("scriptName", scriptName);

        // ?????URL??
        // DC??????URL?????????
        baseUrl = req.getHeader(KEY_HEADER_BASEURL);

        // ?????JSGI????
        URL baseUrlObj = new URL(baseUrl);
        int port = baseUrlObj.getPort();
        String proto = baseUrlObj.getProtocol();
        String host = baseUrlObj.getHost();
        String hostHeader = host;
        if (port < 0) {
            if ("http".endsWith(proto)) {
                port = PORT_HTTP;
            }
            if ("https".endsWith(proto)) {
                port = PORT_HTTPS;
            }
        } else {
            hostHeader += ":" + port;
        }
        req.setAttribute("HostHeader", hostHeader);
        req.setAttribute("host", baseUrlObj.getHost());
        req.setAttribute("port", port);
        req.setAttribute("scheme", proto);
        return baseUrl;
    }

    /**
     * ServiceCollectionManager?.
     * @return ISourceManager
     * @throws PersoniumEngineException Exception about Engine
     */
    public abstract ISourceManager getServiceCollectionManager() throws PersoniumEngineException;

}