org.ow2.chameleon.everest.servlet.EverestServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.ow2.chameleon.everest.servlet.EverestServlet.java

Source

/*
 * Copyright 2013 OW2 Chameleon
 * 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 org.ow2.chameleon.everest.servlet;

import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.felix.ipojo.annotations.*;
import org.ow2.chameleon.everest.impl.DefaultRequest;
import org.ow2.chameleon.everest.services.*;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

import static org.ow2.chameleon.everest.servlet.HttpUtils.*;

/**
 * The Everest servlet.
 */
@Component(immediate = true)
@Instantiate
public class EverestServlet extends HttpServlet {

    /**
     * The system property used to dump requests to System.out.
     */
    public static final String DEBUG_SERVLET = "everest.debug.servlet";

    public static final String EVEREST_SERVLET_PATH = "/everest";

    @Requires
    private EverestService everest;

    @Bind
    public void bindHttp(HttpService service, Map properties) throws ServletException, NamespaceException {
        service.registerServlet(EVEREST_SERVLET_PATH, this, null, null);
    }

    @Unbind
    public void unbindHttp(HttpService service) throws ServletException, NamespaceException {
        service.unregister(EVEREST_SERVLET_PATH);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String debug = System.getProperty(DEBUG_SERVLET);
        if (debug != null && debug.equalsIgnoreCase("true")) {
            //Trace
            System.out.println("Everest servlet called");
            //End Trace
        }

        // Translate request
        DefaultRequest request = translate(req);
        if (request == null) {
            ObjectNode node = JsonUtils.get().newObject();
            node.put("error", "The HTTP request cannot be translated to Everest");
            notimplemented(node).wrap(resp);
            return;
        }

        HttpResult result = null;
        try {
            Resource resource = everest.process(request);
            if (!isHead(req)) {
                // PUT => CREATION
                if (isPut(req)) {
                    result = created(toJSON(req, resource));
                } else {
                    result = ok(toJSON(req, resource));
                }
            } else {
                result = ok();
            }
            // Compute and add location
            result.location(toURL(req, resource.getPath()));

        } catch (IllegalActionOnResourceException e) {
            ObjectNode node = JsonUtils.get().newObject();
            node.put("error", "illegal action on resource");
            node.put("path", request.path().toString());
            node.put("action", request.action().toString());
            node.put("message", e.getMessage());
            result = notallowed(node);
        } catch (ResourceNotFoundException e) {
            ObjectNode node = JsonUtils.get().newObject();
            node.put("error", "resource not found");
            node.put("path", request.path().toString());
            node.put("action", request.action().toString());
            node.put("message", e.getMessage());
            result = notfound(node);
        }

        result.wrap(resp);
    }

    /**
     * Computes the HTTP url of the given path.
     * The url is computed thanks to the request.
     * @param  request the HTTP Request
     * @param path the path
     * @return the URL pointing to the given path
     */
    private String toURL(HttpServletRequest request, Path path) {
        return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
                + EVEREST_SERVLET_PATH + "/" + path.toString();
    }

    protected ObjectNode toJSON(HttpServletRequest request, Resource resource) throws IOException {
        ObjectNode root = JsonUtils.get(request).newObject();

        // Metadata
        for (Map.Entry<String, Object> entry : resource.getMetadata().entrySet()) {
            String k = entry.getKey();
            root.put(k, JsonUtils.get(request).toJson(entry.getValue()));
        }

        // Relations
        // Relations are indexed by their name
        ObjectNode relations = JsonUtils.get(request).newObject();
        for (Relation relation : resource.getRelations()) {
            relations.put(relation.getName(), JsonUtils.get(request).toJson(relation));
        }

        root.put("__relations", relations);
        root.put("__observable", resource.isObservable());
        return root;
    }

    protected ObjectNode toJSON(Resource resource) throws IOException {
        ObjectNode root = JsonUtils.get().newObject();

        // Metadata
        for (Map.Entry<String, Object> entry : resource.getMetadata().entrySet()) {
            String k = entry.getKey();
            root.put(k, JsonUtils.get().toJson(entry.getValue()));
        }

        return root;
    }

    public static DefaultRequest translate(HttpServletRequest request) {

        String debug = System.getProperty(DEBUG_SERVLET);
        if (debug != null && debug.equalsIgnoreCase("true")) {
            //Trace
            System.out.println("Path info : " + request.getPathInfo());
            //End Trace
        }

        Path path = Path.from(request.getPathInfo());

        Action action;
        if (isGet(request) || isHead(request)) {
            action = Action.READ;
        } else if (isPut(request)) {
            action = Action.CREATE;
        } else if (isPost(request)) {
            action = Action.UPDATE;
        } else if (isDelete(request)) {
            action = Action.DELETE;
        } else {
            return null; // Unsupported request.
        }

        Map<String, ?> params = flat(request.getParameterMap());

        return new DefaultRequest(action, path, params); // TODO Detect JSON.
    }

    public static Map<String, ?> flat(Map<String, String[]> params) {
        if (params == null) {
            return Collections.emptyMap();
        }
        LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
        for (Map.Entry<String, String[]> entry : params.entrySet()) {
            if (entry.getValue() == null) {
                // No value.
                map.put(entry.getKey(), null);
            } else if (entry.getValue().length == 0) {
                map.put(entry.getKey(), Boolean.TRUE.toString());
            } else if (entry.getValue().length == 1) {
                // Scalar parameter.
                map.put(entry.getKey(), entry.getValue()[0]);
            } else if (entry.getValue().length > 1) {
                // Translate to list
                map.put(entry.getKey(), Arrays.asList(entry.getValue()));
            }
        }
        return map;
    }
}