Java tutorial
/* * 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; } }