org.openjena.riot.web.HttpOp.java Source code

Java tutorial

Introduction

Here is the source code for org.openjena.riot.web.HttpOp.java

Source

/*
 * 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.openjena.riot.web;

import static java.lang.String.format;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.openjena.atlas.web.HttpException;
import org.openjena.atlas.web.MediaType;
import org.openjena.riot.WebContent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hp.hpl.jena.sparql.ARQInternalErrorException;

/** Simplified HTTP operations; simplification means only supporting certain needed uses of HTTP.
 * The expectation is that the simplified operations in this class can be used by other code to
 * generate more application specific HTTP interactions (e.g. SPARQL queries).        
 * <p>
 * For HTTP GET, the application supplies a URL, the accept header string, and a 
 * list of handlers to deal with different content type responses. 
 * <p>
 * For HTTP POST, the application supplies a URL, content, 
 * the accept header string, and a list of handlers to deal with different content type responses,
 * or no response is expected.
 * @see HttpNames HttpNames, for HTTP related constants
 * @see WebContent WebContent, for content type name constants
 */
public class HttpOp {

    // See also:
    //   Fluent API in HttpClient from v4.2

    static private Logger log = LoggerFactory.getLogger(HttpOp.class);

    static private AtomicLong counter = new AtomicLong(0);

    //    /** GET with unencoded query string.
    //     *  See {@link #execHttpGet(String, String, Map)} for additional details.
    //     *  <p>The query string will be encoded as needed and appended to the URL, inserting a "?".
    //     */
    //    public static void execHttpGet(String url, String queryString, String acceptHeader, Map<String, HttpResponseHandler> handlers)
    //    {
    //        try {
    //            System.err.println("BROKEN - encodes the queyr string structure") ;
    //            String requestURL = url+"?"+URLEncoder.encode(queryString, "UTF-8")  ;
    //            execHttpGet(requestURL, acceptHeader, handlers) ;
    //        } catch (UnsupportedEncodingException ex)
    //        {
    //            // UTF-8 required of all Java platforms.
    //            throw new ARQInternalErrorException("No UTF-8 charset") ;
    //        }
    //    }

    /** GET
     *  <p>The acceptHeader string is any legal value for HTTP Accept: field.
     *  <p>The handlers are the set of content types (without charset),
     *  used to dispatch the response body for handling.
     *  <p>A Map entry of ("*",....) is used "no handler found".
     *  <p>HTTP responses 400 and 500 become exceptions.   
     */
    public static void execHttpGet(String url, String acceptHeader, Map<String, HttpResponseHandler> handlers) {
        try {
            long id = counter.incrementAndGet();
            String requestURI = determineRequestURI(url);
            String baseIRI = determineBaseIRI(requestURI);

            HttpGet httpget = new HttpGet(requestURI);
            if (log.isDebugEnabled())
                log.debug(format("[%d] %s %s", id, httpget.getMethod(), httpget.getURI().toString()));
            // Accept
            if (acceptHeader != null)
                httpget.addHeader(HttpNames.hAccept, acceptHeader);

            // Execute
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(httpget);
            // Handle response
            httpResponse(id, response, baseIRI, handlers);
            httpclient.getConnectionManager().shutdown();
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
        }
    }

    /** POST a string without response body.
     * <p>Execute an HTTP POST, with the string as content.
     * <p>No response content expected or processed. 
     */
    //TODO Use MediaType
    public static void execHttpPost(String url, String contentType, String content) {
        execHttpPost(url, contentType, content, null, null);
    }

    /** POST without response body.
     * Content read from the the input stream.
     * <p>Execute an HTTP POST, with the string as content.
     * <p>No response content expected or processed. 
     */
    //TODO Use MediaType
    public static void execHttpPost(String url, String contentType, InputStream input, int length) {
        execHttpPost(url, contentType, input, length, null, null);
    }

    /** POST a string, expect a response body.*/
    public static void execHttpPost(String url, String contentType, String content, String acceptType,
            Map<String, HttpResponseHandler> handlers) {
        StringEntity e = null;
        try {
            e = new StringEntity(content, "UTF-8");
            e.setContentType(contentType);
            execHttpPost(url, e, acceptType, handlers);
        } catch (UnsupportedEncodingException e1) {
            throw new ARQInternalErrorException("Platform does not support required UTF-8");
        } finally {
            closeEntity(e);
        }
    }

    /** POST with response body.
     * The input stream is assumed to be UTF-8.
     */
    public static void execHttpPost(String url, String contentType, InputStream input, int length,
            String acceptType, Map<String, HttpResponseHandler> handlers) {

        InputStreamEntity e = new InputStreamEntity(input, length);
        e.setContentType(contentType);
        e.setContentEncoding("UTF-8");
        execHttpPost(url, e, acceptType, handlers);
    }

    /** POST with response body */
    public static void execHttpPost(String url, String contentType, ContentProducer provider, String acceptType,
            Map<String, HttpResponseHandler> handlers) {
        EntityTemplate entity = new EntityTemplate(provider);
        entity.setContentType(contentType);
        execHttpPost(url, entity, acceptType, handlers);
    }

    /** POST with response body.
     * <p>The content for the POST body comes from the HttpEntity.
     * <p>The response is handled bythe handler map, as per {@link #execHttpGet(String, String, Map)}
     */
    public static void execHttpPost(String url, HttpEntity provider, String acceptType,
            Map<String, HttpResponseHandler> handlers) {
        try {
            long id = counter.incrementAndGet();
            String requestURI = determineBaseIRI(url);
            String baseIRI = determineBaseIRI(requestURI);

            HttpPost httppost = new HttpPost(requestURI);
            if (log.isDebugEnabled())
                log.debug(format("[%d] %s %s", id, httppost.getMethod(), httppost.getURI().toString()));

            if (provider.getContentType() == null)
                log.debug(format("[%d] No content type"));

            // Execute
            HttpClient httpclient = new DefaultHttpClient();
            httppost.setEntity(provider);
            HttpResponse response = httpclient.execute(httppost);
            httpResponse(id, response, baseIRI, handlers);

            httpclient.getConnectionManager().shutdown();
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
        } finally {
            closeEntity(provider);
        }
    }

    private static void closeEntity(HttpEntity entity) {
        if (entity == null)
            return;
        try {
            entity.getContent().close();
        } catch (Exception e) {
        }
    }

    private static String determineRequestURI(String url) {
        String requestURI = url;
        if (requestURI.contains("#")) {
            // No frag ids.
            int i = requestURI.indexOf('#');
            requestURI = requestURI.substring(0, i);
        }
        return requestURI;
    }

    private static String determineBaseIRI(String requestURI) {
        // Technically wrong, but including the query string is "unhelpful"
        String baseIRI = requestURI;
        if (requestURI.contains("?")) {
            // No frag ids.
            int i = requestURI.indexOf('?');
            baseIRI = requestURI.substring(0, i);
        }
        return baseIRI;
    }

    private static void httpResponse(long id, HttpResponse response, String baseIRI,
            Map<String, HttpResponseHandler> handlers) throws IllegalStateException, IOException {
        if (response == null)
            return;
        try {
            StatusLine statusLine = response.getStatusLine();
            if (statusLine.getStatusCode() >= 400) {
                log.debug(format("[%d] %s %s", id, statusLine.getStatusCode(), statusLine.getReasonPhrase()));
                throw new HttpException(statusLine.getStatusCode() + " " + statusLine.getReasonPhrase());
            }

            String ct = "*";
            MediaType mt = null;
            if (statusLine.getStatusCode() == 200) {
                String contentType = response.getFirstHeader(HttpNames.hContentType).getValue();
                if (contentType != null) {
                    mt = new MediaType(contentType);
                    if (log.isDebugEnabled())
                        log.debug(format("[%d] %d %s :: %s", id, statusLine.getStatusCode(),
                                statusLine.getReasonPhrase(), mt));
                } else {
                    if (log.isDebugEnabled())
                        log.debug(format("[%d] %d %s :: (no content type)", id, statusLine.getStatusCode(),
                                statusLine.getReasonPhrase()));
                }
                HttpResponseHandler handler = handlers.get(ct);
                if (handler == null)
                    // backstop
                    handler = handlers.get("*");
                if (handler != null)
                    handler.handle(ct, baseIRI, response);
                else
                    log.warn(format("[%d] No handler found for %s", id, ct));
            } else {
                if (handlers != null)
                    log.warn(format("[%d] No content returned but handlers provided"));
            }
        } finally {
            closeEntity(response.getEntity());
        }
    }

    //    public static void main2(String...argv) throws Exception
    //    {
    //        String queryString =  "SELECT * { ?s ?p ?o } LIMIT 1" ;
    //        // HttpClient 4.1.2
    //        URI uri = URIUtils.createURI("http",
    //                                     "sparql.org",
    //                                     -1, 
    //                                     "books",
    //                                     "query="+URLEncoder.encode(queryString,"UTF-8"),
    //                                     null
    //                                     ) ;
    //        HttpGet httpget = new HttpGet(uri);
    //        httpget.addHeader("Accept", "application/sparql-results+json") ;
    //        
    //        System.out.println(httpget.getURI());
    //        
    //        DefaultHttpClient httpclient = new DefaultHttpClient();
    //
    //        HttpContext localContext = new BasicHttpContext();
    //        
    //        HttpResponse response = httpclient.execute(httpget, localContext) ;
    //        System.out.println(response.getFirstHeader("Content-type")) ;
    //        
    //        System.out.println(response.getStatusLine()) ;
    //        HttpEntity entity = response.getEntity();
    //        InputStream instream = entity.getContent() ;
    //        try {
    //            //entity = new BufferedHttpEntity(entity) ;
    //            String x = FileUtils.readWholeFileAsUTF8(instream) ;
    //            System.out.print(x) ;  
    //        } finally {
    //            instream.close();
    //        }
    //    }
}