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

org.wisdom.framework.vertx.ContextFromVertx Maven / Gradle / Ivy

There is a newer version: 0.10.0
Show newest version
/*
 * #%L
 * Wisdom-Framework
 * %%
 * Copyright (C) 2013 - 2014 Wisdom Framework
 * %%
 * 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.
 * #L%
 */
package org.wisdom.framework.vertx;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.apache.commons.io.IOUtils;
import org.vertx.java.core.Vertx;
import org.vertx.java.core.http.HttpServerRequest;
import org.wisdom.api.content.BodyParser;
import org.wisdom.api.cookies.Cookie;
import org.wisdom.api.cookies.Cookies;
import org.wisdom.api.cookies.FlashCookie;
import org.wisdom.api.cookies.SessionCookie;
import org.wisdom.api.http.*;
import org.wisdom.api.router.Route;
import org.wisdom.framework.vertx.cookies.CookieHelper;
import org.wisdom.framework.vertx.cookies.FlashCookieImpl;
import org.wisdom.framework.vertx.cookies.SessionCookieImpl;
import org.wisdom.framework.vertx.file.VertxFileUpload;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

/**
 * An implementation of {@link org.wisdom.api.http.Context} for Vert.x.
 */
public class ContextFromVertx implements Context {

    private static AtomicLong ids = new AtomicLong();
    private final long id;
    private final ServiceAccessor services;
    private final FlashCookieImpl flash;
    private final SessionCookieImpl session;
    private final Vertx vertx;


    private /*not final*/ Route route;
    /**
     * the request object, created lazily.
     */
    private RequestFromVertx request;
    private org.vertx.java.core.Context vertxContext;


    /**
     * Creates a new context.
     *
     * @param accessor a structure containing the used services.
     * @param req      the incoming HTTP Request.
     */
    public ContextFromVertx(Vertx vertx, ServiceAccessor accessor, HttpServerRequest req) {
        id = ids.getAndIncrement();
        services = accessor;
        request = new RequestFromVertx(this, req, accessor.getConfiguration());
        this.vertx = vertx;

        flash = new FlashCookieImpl(accessor.getConfiguration());
        session = new SessionCookieImpl(accessor.getCrypto(), accessor.getConfiguration());
        flash.init(this);
        session.init(this);
    }


    /**
     * The context id (unique).
     */
    @Override
    public Long id() {
        return id;
    }

    /**
     * Returns the current request.
     */
    @Override
    public Request request() {
        return request;
    }

    /**
     * Returns the path that the controller should act upon.
     * 

* For instance in servlets you could have something like a context prefix. * /myContext/app *

* If your route only defines /app it will work as the requestpath will * return only "/app". A context path is not returned. *

* It does NOT decode any parts of the url. *

* Interesting reads: - * http://www.lunatech-research.com/archives/2009/02/03/ * what-every-web-developer-must-know-about-url-encoding - * http://stackoverflow * .com/questions/966077/java-reading-undecoded-url-from-servlet * * @return The the path as seen by the server. Does exclude any container * set context prefixes. Not decoded. */ @Override public String path() { return request().path(); } /** * Returns the flash cookie. Flash cookies only live for one request. Good * uses are error messages to display. Almost everything else is bad use of * Flash Cookies. *

* A FlashCookie is usually not signed. Don't trust the content. * * @return the flash cookie of that request. */ @Override public FlashCookie flash() { return flash; } /** * Returns the client side session. It is a cookie. Therefore you cannot * store a lot of information inside the cookie. This is by intention. *

* If you have the feeling that the session cookie is too small for what you * want to achieve thing again. Most likely your design is wrong. * * @return the Session of that request / response cycle. */ @Override public SessionCookie session() { return session; } /** * Get cookie from context. * * @param cookieName Name of the cookie to retrieve * @return the cookie with that name or null. */ @Override public Cookie cookie(String cookieName) { return request().cookie(cookieName); } /** * Checks whether the context contains a given cookie. * * @param cookieName Name of the cookie to check for * @return {@code true} if the context has a cookie with that name. */ @Override public boolean hasCookie(String cookieName) { return request().cookie(cookieName) != null; } /** * Get all cookies from the context. * * @return the cookie with that name or null. */ @Override public Cookies cookies() { return request().cookies(); } /** * Get the context path on which the application is running. * * @return the context-path with a leading "/" or "" if running on root */ @Override public String contextPath() { return ""; } /** * Get the parameter with the given key from the request. The parameter may * either be a query parameter, or in the case of form submissions, may be a * form parameter. *

* When the parameter is multivalued, returns the first value. *

* The parameter is decoded by default. * * @param name The key of the parameter * @return The value, or null if no parameter was found. * @see #parameterMultipleValues */ @Override public String parameter(String name) { return request.parameter(name); } @Override public Map> attributes() { return form(); } /** * Gets the data sent to the server using an HTML Form. * * @return the form data */ @Override public Map> form() { return request.getFormData(); } /** * Get the parameter with the given key from the request. The parameter may * either be a query parameter, or in the case of form submissions, may be a * form parameter. *

* The parameter is decoded by default. * * @param name The key of the parameter * @return The values, possibly an empty list. */ @Override public List parameterMultipleValues(String name) { return request.parameterMultipleValues(name); } /** * Like {@link #parameter(String)}, but returns given defaultValue * instead of null in case parameter cannot be found. *

* The parameter is decoded by default. * * @param name The name of the parameter * @param defaultValue A default value if parameter not found. * @return The value of the parameter of the defaultValue if not found. */ @Override public String parameter(String name, String defaultValue) { return request.parameter(name, defaultValue); } /** * Like {@link #parameter(String)}, but converts the parameter to * Integer if found. *

* The parameter is decoded by default. * * @param name The name of the parameter * @return The value of the parameter or null if not found. */ @Override public Integer parameterAsInteger(String name) { return request.parameterAsInteger(name); } /** * Like {@link #parameter(String, String)}, but converts the * parameter to Integer if found. *

* The parameter is decoded by default. * * @param name The name of the parameter * @param defaultValue A default value if parameter not found. * @return The value of the parameter of the defaultValue if not found. */ @Override public Integer parameterAsInteger(String name, Integer defaultValue) { return request.parameterAsInteger(name, defaultValue); } /** * Like {@link #parameter(String)}, but converts the * parameter to Boolean if found. *

* The parameter is decoded by default. * * @param name The name parameter * @return The value of the parameter of the defaultValue if not found. */ @Override public Boolean parameterAsBoolean(String name) { return request.parameterAsBoolean(name); } /** * Like {@link #parameter(String, String)}, but converts the * parameter to Boolean if found. *

* The parameter is decoded by default. * * @param name The name of the parameter * @param defaultValue A default value if parameter not found. * @return The value of the parameter of the defaultValue if not found. */ @Override public Boolean parameterAsBoolean(String name, boolean defaultValue) { return request.parameterAsBoolean(name, defaultValue); } /** * Get the path parameter for the given key. *

* The parameter will be decoded based on the RFCs. *

* Check out http://docs.oracle.com/javase/6/docs/api/java/net/URI.html for * more information. * * @param name The name of the path parameter in a route. Eg * /{myName}/rest/of/url * @return The decoded path parameter, or null if no such path parameter was * found. */ @Override public String parameterFromPath(String name) { String encodedParameter = route.getPathParametersEncoded( path()).get(name); if (encodedParameter == null) { return null; } else { return URI.create(encodedParameter).getPath(); } } /** * Get the path parameter for the given key. *

* Returns the raw path part. That means you can get stuff like: * blue%2Fred%3Fand+green * * @param name The name of the path parameter in a route. Eg * /{myName}/rest/of/url * @return The encoded (!) path parameter, or null if no such path parameter * was found. */ @Override public String parameterFromPathEncoded(String name) { return route.getPathParametersEncoded(path()).get(name); } /** * Get the path parameter for the given key and convert it to Integer. *

* The parameter will be decoded based on the RFCs. *

* Check out http://docs.oracle.com/javase/6/docs/api/java/net/URI.html for * more information. * * @param key the key of the path parameter * @return the numeric path parameter, or null of no such path parameter is * defined, or if it cannot be parsed to int */ @Override public Integer parameterFromPathAsInteger(String key) { String parameter = parameterFromPath(key); if (parameter == null) { return null; } else { return Integer.parseInt(parameter); } } /** * Get all the parameters from the request (query string). Path parameters can be retrieved using the {@link * #parameterFromPath(String)} method. This method does not check the formData. * * @return The parameters */ @Override public Map> parameters() { return request.parameters(); } /** * Get the (first) request header with the given name. * * @return The header value */ @Override public String header(String name) { List list = request.headers().get(name); if (list != null && !list.isEmpty()) { return list.get(0); } return null; } /** * Get all the request headers with the given name. * * @return the header values */ @Override public List headers(String name) { return request.headers().get(name); } /** * Get all the headers from the request. * * @return The headers */ @Override public Map> headers() { return request.headers(); } /** * Get the cookie value from the request, if defined. * * @param name The name of the cookie * @return The cookie value, or null if the cookie was not found */ @Override public String cookieValue(String name) { return CookieHelper.getCookieValue(name, request().cookies()); } /** * This will give you the request body nicely parsed. You can register your * own parsers depending on the request type. *

* * @param classOfT The class of the result. * @return The parsed request or null if something went wrong. */ @Override public T body(Class classOfT) { return body(classOfT, null); } /** * This will give you the request body nicely parsed. You can register your * own parsers depending on the request type. *

* * @param classOfT The class of the result. * @return The parsed request or null if something went wrong. */ @Override public T body(Class classOfT, Type genericType) { String rawContentType = request().contentType(); // If the Content-type: xxx header is not set we return null. // we cannot parse that request. if (rawContentType == null) { return null; } // If Content-type is application/json; charset=utf-8 we split away the charset // application/json String contentTypeOnly = HttpUtils.getContentTypeFromContentTypeAndCharacterSetting( rawContentType); BodyParser parser = services.getContentEngines().getBodyParserEngineForContentType(contentTypeOnly); if (parser == null) { return null; } return parser.invoke(this, classOfT, genericType); } /** * Retrieves the request body as a String. If the request has no body, {@code null} is returned. * * @return the body as String */ public String body() { return request.getRawBodyAsString(); } /** * Retrieves the request body as a byte array. If the request has no body, {@code null} is returned. * * @return the body as byte array, as sent in the request */ @Override public byte[] raw() { return request.getRawBody(); } /** * Gets the reader to read the request. * * @return The reader */ @Override public BufferedReader reader() throws IOException { byte[] raw = request.getRawBody(); if (raw != null) { return IOUtils.toBufferedReader(new InputStreamReader(new ByteArrayInputStream(raw))); } return null; } /** * Get the route for this context. * * @return The route */ @Override public Route route() { return route; } /** * Sets the route associated with the current context. * * @param route the route */ public void route(Route route) { // Can be called only once, with a non null route. Preconditions.checkState(this.route == null); Preconditions.checkNotNull(route); this.route = route; } /** * Check if request is of type multipart. Important when you want to process * uploads for instance. *

* Also check out: http://commons.apache.org/fileupload/streaming.html * * @return true if request is of type multipart. */ @Override public boolean isMultipart() { return MimeTypes.MULTIPART.equals(request.getHeader(HeaderNames.CONTENT_TYPE)); } /** * Gets the collection of uploaded files. * * @return the collection of files, {@literal empty} if no files. */ @Override public Collection files() { return request.getFiles(); } /** * Gets the uploaded file having a form's field matching the given name. * * @param name the name of the field of the form that have uploaded the file * @return the file object, {@literal null} if there are no file with this name */ @Override public FileItem file(String name) { for (FileItem item : request.getFiles()) { // FileItem that do not have an real file attached, should not be returned if (item.field().equals(name) && !Strings.isNullOrEmpty(item.name())) { return item; } } return null; } /** * Releases uploaded files. */ public void cleanup() { for (VertxFileUpload item : request.getFiles()) { item.cleanup(); } } /** * Callback called when the request has been read completely. */ public boolean ready() { // Store the vertx context, used to finalize the response vertxContext = vertx.currentContext(); return request.ready(); } /** * @return the vertx singleton. */ public Vertx vertx() { return vertx; } /** * @return the vertx context that will be used to write the response to the client. */ public org.vertx.java.core.Context vertxContext() { return vertxContext; } @Override public String toString() { return "context-" + id + " / " + vertxContext; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy