Package org.cruxframework.crux.core.server.rest.spi

Source Code of org.cruxframework.crux.core.server.rest.spi.HttpUtil

/*
* Copyright 2013 cruxframework.org.
*
* 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.cruxframework.crux.core.server.rest.spi;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPOutputStream;

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

import org.apache.commons.lang.StringUtils;
import org.cruxframework.crux.core.server.rest.core.Cookie;
import org.cruxframework.crux.core.server.rest.core.EntityTag;
import org.cruxframework.crux.core.server.rest.core.Headers;
import org.cruxframework.crux.core.server.rest.core.HttpHeaders;
import org.cruxframework.crux.core.server.rest.core.MediaType;
import org.cruxframework.crux.core.server.rest.core.MultivaluedMap;
import org.cruxframework.crux.core.server.rest.core.UriBuilder;
import org.cruxframework.crux.core.server.rest.core.dispatch.CacheInfo;
import org.cruxframework.crux.core.server.rest.core.dispatch.ConditionalResponse;
import org.cruxframework.crux.core.server.rest.core.dispatch.ResourceMethod.MethodReturn;
import org.cruxframework.crux.core.server.rest.util.HttpHeaderNames;
import org.cruxframework.crux.core.server.rest.util.HttpResponseCodes;
import org.cruxframework.crux.core.server.rest.util.MediaTypeHelper;
import org.cruxframework.crux.core.server.rest.util.PathHelper;
import org.cruxframework.crux.core.server.rest.util.header.MediaTypeHeaderParser;

/**
*
* @author Thiago da Rosa de Bustamante
*
*/
public class HttpUtil
{
  public static UriInfo extractUriInfo(HttpServletRequest request)
  {
    String servletPrefix = request.getServletPath();
    String contextPath = request.getContextPath();
    if (servletPrefix != null && servletPrefix.length() > 0 && !servletPrefix.equals("/"))
    {
      if (!contextPath.endsWith("/") && !servletPrefix.startsWith("/"))
      {
        contextPath += "/";
      }
      contextPath += servletPrefix;
    }
    URI absolutePath = null;
    try
    {
      URL absolute = new URL(request.getRequestURL().toString());

      UriBuilder builder = new UriBuilder();
      builder.scheme(absolute.getProtocol());
      builder.host(absolute.getHost());
      builder.port(absolute.getPort());
      builder.path(absolute.getPath());
      builder.replaceQuery(null);
      absolutePath = builder.build();
    }
    catch (MalformedURLException e)
    {
      throw new RuntimeException(e);
    }

    String path = PathHelper.getEncodedPathInfo(absolutePath.getRawPath(), contextPath);
    URI relativeURI = UriBuilder.fromUri(path).replaceQuery(request.getQueryString()).build();

    URI baseURI = absolutePath;
    if (!path.trim().equals(""))
    {
      String tmpContextPath = contextPath;
      if (!tmpContextPath.endsWith("/"))
      {
        tmpContextPath += "/";
      }
      baseURI = UriBuilder.fromUri(absolutePath).replacePath(tmpContextPath).build();
    }
    UriInfo uriInfo = new UriInfo(baseURI, relativeURI);
    return uriInfo;
  }

  public static HttpHeaders extractHttpHeaders(HttpServletRequest request)
  {
    HttpHeaders headers = new HttpHeaders();

    MultivaluedMap<String, String> requestHeaders = extractRequestHeaders(request);
    headers.setRequestHeaders(requestHeaders);
    List<MediaType> acceptableMediaTypes = extractAccepts(requestHeaders);
    List<String> acceptableLanguages = extractLanguages(requestHeaders);
    headers.setAcceptableMediaTypes(acceptableMediaTypes);
    headers.setAcceptableLanguages(acceptableLanguages);
    headers.setLanguage(requestHeaders.getFirst(HttpHeaderNames.CONTENT_LANGUAGE));

    String contentType = request.getContentType();
    if (contentType != null)
    {
      headers.setMediaType(MediaType.valueOf(contentType));
    }

    Map<String, Cookie> cookies = extractCookies(request);
    headers.setCookies(cookies);
    return headers;

  }

  public static String wGet(String targetURL, String urlParameters, String method, String locale)
  {
    URL url;
    HttpURLConnection connection = null
    try {
      //Create connection
      if(method != null && method.equals("GET") && !StringUtils.isEmpty(urlParameters))
      {
        targetURL += "?" + urlParameters;
      }
     
      url = new URL(targetURL);
      connection = (HttpURLConnection)url.openConnection();
     
      connection.setRequestMethod(method);
      connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
      connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
      connection.setRequestProperty("Content-Language", locale)
      connection.setUseCaches(false);
      connection.setDoInput(true);
     
      //Send request
      if(method != null && method.equals("POST"))
      {
        DataOutputStream wr = new DataOutputStream (
            connection.getOutputStream ());
        connection.setDoOutput(true);
        wr.writeBytes (urlParameters);
        wr.flush ();
        wr.close ()
      }

      //Get Response 
      InputStream is = connection.getInputStream();
      BufferedReader rd = new BufferedReader(new InputStreamReader(is));
      String line;
      StringBuffer response = new StringBuffer();
      while((line = rd.readLine()) != null) {
        response.append(line);
        response.append('\r');
      }
      rd.close();
      return response.toString();
    } catch (Exception e)
    {
      e.printStackTrace();
      return null;
    } finally
    {
      if(connection != null)
      {
        connection.disconnect();
      }
    }
  }

  static Map<String, Cookie> extractCookies(HttpServletRequest request)
  {
    Map<String, Cookie> cookies = new HashMap<String, Cookie>();
    if (request.getCookies() != null)
    {
      for (javax.servlet.http.Cookie cookie : request.getCookies())
      {
        cookies.put(cookie.getName(), new Cookie(cookie.getName(), cookie.getValue(), cookie.getPath(), cookie.getDomain(), cookie.getVersion()));
      }
    }
    return cookies;
  }

  public static List<MediaType> extractAccepts(MultivaluedMap<String, String> requestHeaders)
  {
    List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
    List<String> accepts = requestHeaders.get(HttpHeaderNames.ACCEPT);
    if (accepts == null)
    {
      return acceptableMediaTypes;
    }

    for (String accept : accepts)
    {
      acceptableMediaTypes.addAll(MediaTypeHelper.parseHeader(accept));
    }
    return acceptableMediaTypes;
  }

  public static List<String> extractLanguages(MultivaluedMap<String, String> requestHeaders)
  {
    List<String> acceptable = new ArrayList<String>();
    List<String> accepts = requestHeaders.get(HttpHeaderNames.ACCEPT_LANGUAGE);
    if (accepts == null)
    {
      return acceptable;
    }

    for (String accept : accepts)
    {
      String[] splits = accept.split(",");
      for (String split : splits)
      {
        acceptable.add(split.trim());
      }
    }
    return acceptable;
  }

  @SuppressWarnings("unchecked")
  public static MultivaluedMap<String, String> extractRequestHeaders(HttpServletRequest request)
  {
    Headers<String> requestHeaders = new Headers<String>();

    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements())
    {
      String headerName = headerNames.nextElement();
      Enumeration<String> headerValues = request.getHeaders(headerName);
      while (headerValues.hasMoreElements())
      {
        String headerValue = headerValues.nextElement();
        // System.out.println("ADDING HEADER: " + headerName +
        // " value: " + headerValue);
        requestHeaders.add(headerName, headerValue);
      }
    }
    return requestHeaders;
  }

  public static boolean acceptsGzipEncoding(HttpRequest request)
  {
    assert (request != null);

    String acceptEncoding = request.getHttpHeaders().getHeaderString(HttpHeaderNames.ACCEPT_ENCODING);
    if (null == acceptEncoding)
    {
      return false;
    }

    return (acceptEncoding.indexOf("gzip") != -1);
  }

  private static final int UNCOMPRESSED_BYTE_SIZE_LIMIT = 256;

  private static boolean exceedsUncompressedContentLengthLimit(String content)
  {
    return (content != null) && ((content.length() * 2) > UNCOMPRESSED_BYTE_SIZE_LIMIT);
  }

  public static boolean shouldGzipResponseContent(HttpRequest request, String responseContent)
  {
    return acceptsGzipEncoding(request) && exceedsUncompressedContentLengthLimit(responseContent);
  }

  public static void writeResponse(HttpRequest request, HttpResponse response, MethodReturn methodReturn) throws IOException
  {
    HttpServletResponseHeaders outputHeaders = response.getOutputHeaders();
    if (methodReturn == null)
    {
      response.sendEmptyResponse();
    }
    else if (methodReturn.getCheckedExceptionData() != null)
    {
      response.sendError(HttpResponseCodes.SC_FORBIDDEN, methodReturn.getCheckedExceptionData());
    }
    else if (!methodReturn.hasReturnType())
    {
      response.setContentLength(0);
      response.setStatus(HttpServletResponse.SC_NO_CONTENT);
    }
    else if (methodReturn.getConditionalResponse() != null)
    {
      writeConditionalResponse(response, methodReturn, outputHeaders);
    }
    else
    {
      CacheInfo cacheInfo = methodReturn.getCacheInfo();
      if (cacheInfo != null)
      {
        writeCacheHeaders(response, cacheInfo, methodReturn.getEtag(), methodReturn.getDateModified(), methodReturn.isEtagGenerationEnabled());
      }

      String responseContent = methodReturn.getReturn();
      byte[] responseBytes = getResponseBytes(request, response, responseContent);
      response.setContentLength(responseBytes.length);
      response.setStatus(HttpServletResponse.SC_OK);
      outputHeaders.putSingle(HttpHeaderNames.CONTENT_TYPE, new MediaType("application", "json", "UTF-8"));
      response.getOutputStream().write(responseBytes);
    }
  }

  private static void writeConditionalResponse(HttpResponse response, MethodReturn methodReturn, HttpServletResponseHeaders outputHeaders)
  {
    ConditionalResponse conditionalResponse = methodReturn.getConditionalResponse();
    response.setStatus(conditionalResponse.getStatus());

    EntityTag etag = conditionalResponse.getEtag();
    long dateModified = conditionalResponse.getLastModified();
    CacheInfo cacheInfo = methodReturn.getCacheInfo();

    if (cacheInfo != null)
    {
      writeCacheHeaders(response, cacheInfo, etag, dateModified, methodReturn.isEtagGenerationEnabled());
    }
    else
    {
      //Confirmar se devo mandar etag e last modified em 412 ou 304 para escritas
      if (etag != null)
      {
        outputHeaders.putSingle(HttpHeaderNames.ETAG, etag);
      }
      if (dateModified > 0)
      {
        outputHeaders.addDateHeader(HttpHeaderNames.LAST_MODIFIED, dateModified);
      }
    }
  }

  private static void writeCacheHeaders(HttpResponse response, CacheInfo cacheInfo, EntityTag etag, long dateModified, boolean forceEtagGeneration)
  {
    org.cruxframework.crux.core.server.rest.core.CacheControl cacheControl = new org.cruxframework.crux.core.server.rest.core.CacheControl();
    HttpServletResponseHeaders outputHeaders = response.getOutputHeaders();
    if (!cacheInfo.isCacheEnabled())
    {
      cacheControl.setNoStore(true);
      outputHeaders.addDateHeader(HttpHeaderNames.EXPIRES, 0);
      if (forceEtagGeneration && etag != null)
      {
        outputHeaders.putSingle(HttpHeaderNames.ETAG, etag);
      }
    }
    else
    {
      outputHeaders.add(HttpHeaderNames.VARY, HttpHeaderNames.ACCEPT_LANGUAGE);
      long expires = cacheInfo.defineExpires();
      outputHeaders.addDateHeader(HttpHeaderNames.EXPIRES, expires);
      if (etag != null)
      {
        outputHeaders.putSingle(HttpHeaderNames.ETAG, etag);
      }
      if (dateModified > 0)
      {
        outputHeaders.addDateHeader(HttpHeaderNames.LAST_MODIFIED, dateModified);
      }
      switch (cacheInfo.getCacheControl())
      {
      case PUBLIC:
        cacheControl.setPublic(true);
        cacheControl.setMaxAge(cacheInfo.getCacheTime());
        break;
      case PRIVATE:
        cacheControl.setPrivate(true);
        cacheControl.setMaxAge(cacheInfo.getCacheTime());
        break;
      case NO_CACHE:
        cacheControl.setNoCache(true);
        break;
      }
      cacheControl.setNoTransform(cacheInfo.isNoTransform());
      cacheControl.setMustRevalidate(cacheInfo.isMustRevalidate());
      cacheControl.setProxyRevalidate(cacheInfo.isProxyRevalidate());
    }
    outputHeaders.putSingle(HttpHeaderNames.CACHE_CONTROL, cacheControl);
  }

  private static byte[] getResponseBytes(HttpRequest request, HttpResponse response, String responseContent) throws UnsupportedEncodingException, IOException
  {
    boolean gzipResponse = shouldGzipResponseContent(request, responseContent);
    byte[] responseBytes = (responseContent!=null?responseContent.getBytes("UTF-8"):new byte[0]);
    if (gzipResponse)
    {
      ByteArrayOutputStream output = null;
      GZIPOutputStream gzipOutputStream = null;
      try
      {
        output = new ByteArrayOutputStream(responseBytes.length);
        gzipOutputStream = new GZIPOutputStream(output);
        gzipOutputStream.write(responseBytes);
        gzipOutputStream.finish();
        gzipOutputStream.flush();
        response.getOutputHeaders().putSingle(HttpHeaderNames.CONTENT_ENCODING, "gzip");
        responseBytes = output.toByteArray();
      }
      catch (IOException e)
      {
        throw new InternalServerErrorException("Unable to compress response", "Error processing requested service", e);
      }
      finally
      {
        if (null != gzipOutputStream)
        {
          gzipOutputStream.close();
        }
        if (null != output)
        {
          output.close();
        }
      }
    }
    return responseBytes;
  }

  public static void sendError(HttpServletResponse response, int status, String message) throws IOException
  {
    response.setStatus(status);
    if (message!= null)
    {
      byte[] responseBytes = HttpResponse.serializeException(message).getBytes("UTF-8");
      response.setContentLength(responseBytes.length);
      response.setHeader(HttpHeaderNames.CONTENT_TYPE, MediaTypeHeaderParser.toString(new MediaType("text", "plain", "UTF-8")));
      response.getOutputStream().write(responseBytes);
    }
  }
}
TOP

Related Classes of org.cruxframework.crux.core.server.rest.spi.HttpUtil

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.