Package org.opensocial.explorer.specserver.servlet

Source Code of org.opensocial.explorer.specserver.servlet.GadgetSpecServlet

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.opensocial.explorer.specserver.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.wink.json4j.JSONException;
import org.apache.wink.json4j.JSONObject;
import org.opensocial.explorer.specserver.api.GadgetRegistry;
import org.opensocial.explorer.specserver.api.GadgetResource;
import org.opensocial.explorer.specserver.api.GadgetSpec;
import org.opensocial.explorer.specserver.api.JSONSerializable;
import org.opensocial.explorer.specserver.temp.TempGadgetSpec;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import com.google.inject.Inject;

/**
* A servlet used for accessing and manipulating {@link GadgetSpec} objects in the
* {@link GadgetRegistry}.
*
* <pre>
* GET /gadgetspec/specTree
* - Returns a JSON representation of the {@link GadgetRegistry}.
* - @see {@link GadgetRegistry#getSpecTree()}
*
* GET /gadgetspec/default
* - Returns a JSON representation of the default {@link GadgetSpec}
* - @see {@link GadgetRegistry#getDefaultGadget()}
*
* GET /gadgetspec/{id}[/{resource}]
* - If no {resource} name is provided, this returns a JSON representation of the {@link GadgetSpec} whose ID is {id}
* - If a {resource} name is provided, this returns the resource given by {resource} for the {@link GadgetSpec} whose ID is {id}
*
* POST /gadgetspec
* - Creates a new temporary {@link GadgetSpec} with from the JSON POST data.
* - @see {@link TempGadgetSpec}
* - @see {@link #doPost(HttpServletRequest, HttpServletResponse)}
*
* </pre>
*/
public class GadgetSpecServlet extends ExplorerInjectedServlet {
  private static final long serialVersionUID = -6848715863895692189L;
  private static final String CLASS = GadgetSpecServlet.class.getName();
  private static final Logger LOG = Logger.getLogger(CLASS);
  private GadgetRegistry registry;
  private Map<String, GadgetSpec> tempSpecs = Maps.newConcurrentMap();

  @Inject
  public void setRegistry(GadgetRegistry registry) {
    checkInitialized();
    this.registry = registry;
  }

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
          IOException {
    final String method = "doGet";

    // Enforce an ID
    String[] paths = getPaths(req);
    if (paths.length == 0) {
      resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "The request must specify a gadget id.");
      return;
    }
    String specId = paths[0];

    if ("specTree".equals(specId)) { // /gadgetspec/specTree
      String specTree = registry.getSpecTree().toString();
      resp.setContentLength(specTree.length());
      resp.setContentType(JSON_CONTENT_TYPE);
     
      PrintWriter writer = resp.getWriter();
      writer.print(specTree);
      writer.flush();
      return;
    }

    if ("default".equalsIgnoreCase(specId)) { // /gadgetspec/default
      GadgetSpec spec = registry.getDefaultGadget();
      if (spec == null) {
        resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No default gadget spec was found.");
      } else {
        returnJSONResult(spec, resp);
      }
      return;
    }

    // /gadgetspec/{id}[/{resource}]
    GadgetSpec spec;
    // Check the tempSpecs first then go to the registry
    if (this.tempSpecs.containsKey(specId)) {
      spec = this.tempSpecs.get(specId);
    } else {
      spec = registry.getGadgetSpec(specId);
    }

    if (spec == null) {
      resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Gadget spec with ID {" + specId
              + "} was not found.");
      return;
    }

    // Check to see if resources are being requested through this servlet
    if (paths.length > 1) {
      String resourceName = paths[1];
      GadgetResource resource = findResource(spec, resourceName);
      if (resource != null) {
        returnResource(resource, resp);
      } else {
        // 404 - Not Found
        resp.sendError(HttpServletResponse.SC_NOT_FOUND, resourceName + " was not found");
      }
    } else {
      // No resources being requested, just the spec. Return it.
      returnJSONResult(spec, resp);
    }
  }

  /**
   * Servlet to POST a gadget to the server so it can be served back up and rendered. The POST body
   * should be JSON and be modeled after the following sample.
   *
   * <pre>
   * {
   *  "cssResources":[
   *    {
   *      "content":<css content string>,
   *      "name":<css filename string>
   *    }
   *  ],
   *  "jsResources":[
   *    {
   *      "content":<js content string>,
   *      "name":<js filename string>
   *    }
   *  ],
   *  "gadgetResource":{
   *    "content":<gadget content string>,
   *    "name":<gadget filename string>
   *  },
   *  "htmlResources":[
   *    {
   *      "content":<html content string>,
   *      "name":<html filename string>
   *    }
   *  ]
   * }
   * </pre>
   */
  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
          IOException {

    // Enforce request content type as JSON
    if (!req.getContentType().startsWith(JSON_CONTENT_TYPE)) {
      resp.sendError(HttpURLConnection.HTTP_BAD_REQUEST,
              "The request content-type must be application/json.");
      return;
    }
    String jsonString = getRequestBody(req);
    PrintWriter writer = null;
    try {
      JSONObject json = new JSONObject(jsonString);
      GadgetSpec tempSpec = TempGadgetSpec.parse(json);
      String tempSpecId = tempSpec.getId();
      this.tempSpecs.put(tempSpecId, tempSpec);

      // Respond with the ID of the temp spec
      JSONObject respObj = new JSONObject();
      respObj.put(GadgetSpec.SPEC_ID, tempSpecId);
     
      resp.setContentType(JSON_CONTENT_TYPE);
     
      writer = resp.getWriter();
      writer.print(respObj.toString());
    } catch (JSONException e) {
      resp.sendError(HttpURLConnection.HTTP_BAD_REQUEST,
              "Invalid JSON object: " + e.getLocalizedMessage());
    } finally {
      if (writer != null) {
        writer.flush();
      }
    }
  }

  @VisibleForTesting
  GadgetResource findResource(GadgetSpec spec, String resourceName) {
    Map<String, GadgetResource> resources = null;
    if (resourceName.endsWith(".js")) {
      resources = spec.getJsResources();
    } else if (resourceName.endsWith(".html")) {
      resources = spec.getHtmlResources();
    } else if (resourceName.endsWith(".css")) {
      resources = spec.getCssResources();
    } else if (resourceName.endsWith(".xml")
            && spec.getGadgetResource().getName().equals(resourceName)) {
      // Just return the gadget resource
      return spec.getGadgetResource();
    } else {
      LOG.warning("Unknown resource type: " + resourceName);
      return null;
    }

    if (resources == null) {
      // We didn't find any resources of the given type
      return null;
    }

    Iterator<Entry<String, GadgetResource>> itr = resources.entrySet().iterator();
    Entry<String, GadgetResource> entry;
    GadgetResource resource = null;
    while (itr.hasNext()) {
      entry = itr.next();
      resource = entry.getValue();
      if (resource.getName().equals(resourceName)) {
        break;
      }
    }
    return resource;
  }

  private void returnJSONResult(JSONSerializable spec, HttpServletResponse resp) throws IOException {
    final String method = "returnJSONResult";
    PrintWriter writer = null;
    try {
      String specString = spec.toJSON().toString();
      resp.setContentLength(specString.length());
      resp.setContentType(JSON_CONTENT_TYPE);
     
      writer = resp.getWriter();
      writer.print(specString);
    } catch (Exception e) {
      LOG.logp(Level.WARNING, CLASS, method, "An exception occurred returning a JSON result", e);
      resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    } finally {
      if (writer != null) {
        writer.flush();
      }
    }
  }

  private void returnResource(GadgetResource resource, HttpServletResponse resp) throws IOException {
    final String method = "returnResource";
    PrintWriter writer = null;
    try {

      String content = resource.getContent();
      resp.setContentLength(content.length());
      resp.setContentType(resource.getContentType());
    
      writer = resp.getWriter();
      writer.print(content);
    } catch (Exception e) {
      LOG.logp(Level.WARNING, CLASS, method, e.getMessage(), e);
      resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    } finally {
      if (writer != null) {
        writer.flush();
      }
    }
  }
}
TOP

Related Classes of org.opensocial.explorer.specserver.servlet.GadgetSpecServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.