All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tinkerpop.rexster.BaseResource Maven / Gradle / Ivy

package com.tinkerpop.rexster;

import com.tinkerpop.rexster.extension.HttpMethod;
import com.tinkerpop.rexster.server.RexsterApplication;
import com.tinkerpop.rexster.util.StatisticsHelper;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Variant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Base resource from which most other resources extend.  Exposes the request/response object and other
 * request and context information.
 *
 * @author Stephen Mallette (http://stephen.genoprime.com)
 */
public abstract class BaseResource {

    private static Logger logger = Logger.getLogger(BaseResource.class);

    protected final List producesVariantList = Variant.VariantListBuilder.newInstance().mediaTypes(
            MediaType.APPLICATION_JSON_TYPE,
            RexsterMediaType.APPLICATION_REXSTER_JSON_TYPE,
            RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON_TYPE).add().build();

    protected final StatisticsHelper sh = new StatisticsHelper();

    /**
     * This request object goes through the mapping of a URI to JSON.
     */
    private JSONObject requestObject = null;

    /**
     * This request object is just a single layered map of keys/values.
     */
    private JSONObject requestObjectFlat = null;

    protected JSONObject resultObject = new JSONObject();

    @Context
    private RexsterApplication rexsterApplication;

    @Context
    protected HttpServletRequest httpServletRequest;

    @Context
    protected UriInfo uriInfo;

    @Context
    protected ServletContext servletContext;

    @Context
    protected SecurityContext securityContext;

    public BaseResource(final RexsterApplication rexsterApplication) {
        if (rexsterApplication != null) {
            this.rexsterApplication = rexsterApplication;
        }

        sh.stopWatch();

        try {
            this.resultObject.put(Tokens.VERSION, Tokens.REXSTER_VERSION);
        } catch (JSONException ex) {
            JSONObject error = generateErrorObject(ex.getMessage());
            throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build());
        }
    }

    public JSONObject generateErrorObject(String message) {
        return generateErrorObject(message, null);
    }

    public JSONObject generateErrorObjectJsonFail(Throwable source) {
        return generateErrorObject("An error occurred while generating the response object", source);
    }

    public JSONObject generateErrorObject(String message, Throwable source) {
        Map m = new HashMap();
        m.put(Tokens.MESSAGE, message);

        if (source != null) {
            m.put("error", source.getMessage());
        }

        // use a hashmap with the constructor so that a JSONException
        // will not be thrown
        return new JSONObject(m);
    }

    protected RexsterApplication getRexsterApplication() {
        return this.rexsterApplication;
    }

    protected String getUriPath() {
        String baseUri = "";
        if (this.uriInfo != null) {
            baseUri = this.uriInfo.getAbsolutePath().toString();

            if (!baseUri.endsWith("/")) {
                baseUri = baseUri + "/";
            }
        }

        return baseUri;
    }

    /**
     * Sets the request object.
     * 

* If this is set then the any previous call to getRequestObject which instantiated * the request object from the URI parameters will be overriden. * * @param jsonObject The JSON Object. */ protected void setRequestObject(final JSONObject jsonObject) { this.requestObject = jsonObject; this.requestObjectFlat = jsonObject; } protected void setRequestObject(final MultivaluedMap formData) { final Map m = new HashMap(); for(MultivaluedMap.Entry> entry : formData.entrySet()) { // only grabs the first item for JSON support m.put(entry.getKey(), entry.getValue().get(0)); } this.requestObject = new JSONObject(m); this.requestObjectFlat = new JSONObject(m); } public JSONObject getRequestObject() { return this.getRequestObject(true); } public JSONObject getRequestObjectFlat() { return this.getRequestObject(false); } /** * Gets the request object. *

* If it does not exist then an attempt is made to parse the parameter list on * the URI into a JSON object. * * @return The request object. */ public JSONObject getRequestObject(final boolean parseToJson) { if (this.requestObject == null) { try { this.requestObject = new JSONObject(); this.requestObjectFlat = new JSONObject(); if (this.httpServletRequest != null && this.httpServletRequest.getParameterNames().hasMoreElements()) { // unclear if this block of code is still necessary. seems like this is here as a fallback // for when the request comes through without the parameters being extracted from an entity. // doesn't seem like it is a likely thing to happen, but can't think of the corner case that // allows it to happen. final Map queryParameters = this.httpServletRequest.getParameterMap(); this.buildRequestObject(queryParameters); } } catch (JSONException ex) { logger.error(ex); final JSONObject error = generateErrorObjectJsonFail(ex); throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build()); } } if (parseToJson) { return this.requestObject; } else { return this.requestObjectFlat; } } private void buildRequestObject(final Map queryParameters) throws JSONException { final Map flatMap = new HashMap(); for (String key : (Set) queryParameters.keySet()) { final String[] keys = key.split(Tokens.PERIOD_REGEX); JSONObject embeddedObject = this.requestObject; for (int i = 0; i < keys.length - 1; i++) { JSONObject tempEmbeddedObject = (JSONObject) embeddedObject.opt(keys[i]); if (null == tempEmbeddedObject) { tempEmbeddedObject = new JSONObject(); embeddedObject.put(keys[i], tempEmbeddedObject); } embeddedObject = tempEmbeddedObject; } String rawValue; final Object val = queryParameters.get(key); if (val instanceof String) { rawValue = (String) val; } else { // supports multiple parameters on the same key...just take the first? String[] values = (String[]) val; rawValue = values[0]; } flatMap.put(key, rawValue); try { if (rawValue.startsWith(Tokens.LEFT_BRACKET) && rawValue.endsWith(Tokens.RIGHT_BRACKET)) { rawValue = rawValue.substring(1, rawValue.length() - 1); final JSONArray array = new JSONArray(); for (String value : rawValue.split(Tokens.COMMA)) { array.put(value.trim()); } embeddedObject.put(keys[keys.length - 1], array); } else { final Object parsedValue = new JSONObject(rawValue); embeddedObject.put(keys[keys.length - 1], parsedValue); } } catch (JSONException e) { embeddedObject.put(keys[keys.length - 1], rawValue); } } this.requestObjectFlat = new JSONObject(flatMap); } protected JSONObject getNonRexsterRequest() throws JSONException { JSONObject object = new JSONObject(); Iterator keys = this.getRequestObject().keys(); while (keys.hasNext()) { String key = keys.next().toString(); if (!key.equals(Tokens.REXSTER)) { object.put(key, this.getRequestObject().opt(key)); } } return object; } protected List getNonRexsterRequestKeys() throws JSONException { final List keys = new ArrayList(); final JSONObject request = this.getNonRexsterRequest(); if (request.length() > 0) { final Iterator itty = request.keys(); while (itty.hasNext()) { keys.add((String) itty.next()); } } return keys; } /* * NOT SURE WHAT THIS CODE WAS EVERY DOING. it was being called within VertexResource and was filtering * each element for some reason in the getVertexEdges method. wasn't used anywhere else. its only purpose * seemed to be related to the filtering of elements by label...not sure if this is safe to remove yet. protected boolean hasPropertyValues(Element element, JSONObject properties) throws JSONException { Iterator keys = properties.keys(); while (keys.hasNext()) { String key = keys.next().toString(); Object temp; if (key.equals(Tokens._ID)) temp = element.getId(); else if (key.equals(Tokens._LABEL)) temp = ((Edge) element).getLabel(); else if (key.equals(Tokens._IN_V)) temp = ((Edge) element).getVertex(Direction.IN).getId(); else if (key.equals(Tokens._OUT_V)) temp = ((Edge) element).getVertex(Direction.OUT).getId(); else if (key.equals(Tokens._TYPE)) { if (element instanceof Vertex) temp = Tokens.VERTEX; else temp = Tokens.EDGE; } else temp = element.getProperty(key); if (null == temp || !temp.equals(properties.get(key))) return false; } return true; } */ protected String getTimeAlive() { long timeMillis = System.currentTimeMillis() - this.rexsterApplication.getStartTime(); long timeSeconds = timeMillis / 1000; long timeMinutes = timeSeconds / 60; long timeHours = timeMinutes / 60; long timeDays = timeHours / 24; String seconds = Integer.toString((int) (timeSeconds % 60)); String minutes = Integer.toString((int) (timeMinutes % 60)); String hours = Integer.toString((int) timeHours % 24); String days = Integer.toString((int) timeDays); for (int i = 0; i < 2; i++) { if (seconds.length() < 2) { seconds = "0" + seconds; } if (minutes.length() < 2) { minutes = "0" + minutes; } if (hours.length() < 2) { hours = "0" + hours; } } return days + "[d]:" + hours + "[h]:" + minutes + "[m]:" + seconds + "[s]"; } /** * Includes all HTTP Methods in allowable options. */ protected Response buildOptionsResponse() { return buildOptionsResponse(HttpMethod.DELETE.toString(), HttpMethod.GET.toString(), HttpMethod.POST.toString(), HttpMethod.PUT.toString()); } protected Response buildOptionsResponse(final String... methods) { final String requestHeaders = this.httpServletRequest.getHeader("Access-Control-Request-Headers"); final String allowHeaders = requestHeaders == null ? "*" : requestHeaders; return Response.ok() .header("Access-Control-Allow-Methods", "OPTIONS," + StringUtils.join(methods, ",")) .header("Access-Control-Allow-Headers", allowHeaders) .header("Access-Control-Max-Age", "1728000").build(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy