jena-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a...@apache.org
Subject svn commit: r1243160 - in /incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http: HttpQuery.java QueryEngineHTTP.java
Date Sat, 11 Feb 2012 22:02:13 GMT
Author: andy
Date: Sat Feb 11 22:02:13 2012
New Revision: 1243160

URL: http://svn.apache.org/viewvc?rev=1243160&view=rev
Log:
JENA-210 patch applied with fixes and changes as detailed in the JIRA.

Modified:
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/HttpQuery.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/QueryEngineHTTP.java

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/HttpQuery.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/HttpQuery.java?rev=1243160&r1=1243159&r2=1243160&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/HttpQuery.java
(original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/HttpQuery.java
Sat Feb 11 22:02:13 2012
@@ -18,20 +18,21 @@
 
 package com.hp.hpl.jena.sparql.engine.http;
 
-import java.io.ByteArrayInputStream ;
-import java.io.IOException ;
-import java.io.InputStream ;
-import java.io.OutputStream ;
-import java.io.UnsupportedEncodingException ;
+import java.io.* ;
 import java.net.HttpURLConnection ;
 import java.net.MalformedURLException ;
+import java.net.SocketTimeoutException ;
 import java.net.URL ;
+import java.util.ArrayList ;
 import java.util.Iterator ;
 import java.util.List ;
 import java.util.Map ;
 import java.util.regex.Pattern ;
+import java.util.zip.DeflaterInputStream ;
+import java.util.zip.GZIPInputStream ;
 
 import org.apache.commons.codec.binary.Base64 ;
+import org.openjena.atlas.lib.StrUtils ;
 import org.slf4j.Logger ;
 import org.slf4j.LoggerFactory ;
 
@@ -73,6 +74,12 @@ public class HttpQuery extends Params
     boolean serviceParams = false ;
     private final Pattern queryParamPattern = Pattern.compile(".+[&|\\?]query=.*") ;
     
+    int connectTimeout = 0;
+    int readTimeout = 0;
+    
+    private boolean allowGZip = false ;
+    private boolean allowDeflate = false;
+    
     //static final String ENC_UTF8 = "UTF-8" ;
     
     /** Create a execution object for a whole model GET
@@ -126,6 +133,16 @@ public class HttpQuery extends Params
         contentTypeResult = contentType ;
     }
     
+    public void setAllowGZip(boolean allow)
+    {
+    	allowGZip = allow;
+    }
+    
+    public void setAllowDeflate(boolean allow)
+    {
+    	allowDeflate = allow;
+    }
+    
     public void setBasicAuthentication(String user, char[] password)
     {
         this.user = user ;
@@ -151,6 +168,38 @@ public class HttpQuery extends Params
     {
         forcePOST = true ;
     }
+    
+    /**
+     * Sets HTTP Connection timeout, any value <= 0 is taken to mean no timeout
+     */
+    public void setConnectTimeout(int timeout)
+    {
+    	connectTimeout = timeout;
+    }
+    
+    /**
+     * Gets the HTTP Connection timeout
+     */
+    public int getConnectTimeout()
+    {
+    	return connectTimeout;
+    }
+    
+    /**
+     * Sets HTTP Read timeout, any value <= 0 is taken to mean no timeout
+     */
+    public void setReadTimeout(int timeout)
+    {
+    	readTimeout = timeout;
+    }
+    
+    /**
+     * Gets the HTTP Read timeout
+     */
+    public int getReadTimeout()
+    {
+    	return readTimeout;
+    }
 
     /** Execute the operation
      * @return Model    The resulting model
@@ -201,6 +250,8 @@ public class HttpQuery extends Params
             // By default, following 3xx redirects is true
             //conn.setFollowRedirects(true) ;
             basicAuthentication(httpConnection) ;
+            applyTimeouts(httpConnection);
+            applyEncodings(httpConnection);
             
             httpConnection.setDoInput(true);
             httpConnection.connect();
@@ -240,6 +291,8 @@ public class HttpQuery extends Params
             httpConnection.setRequestProperty("Accept", contentTypeResult) ;
             httpConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
;
             basicAuthentication(httpConnection) ;
+            applyTimeouts(httpConnection);
+            applyEncodings(httpConnection);
             httpConnection.setDoOutput(true) ;
             
             boolean first = true ;
@@ -263,6 +316,8 @@ public class HttpQuery extends Params
         }
         catch (java.net.ConnectException connEx)
         { throw new QueryExceptionHTTP(-1, "Failed to connect to remote server"); }
+        catch (SocketTimeoutException timeoutEx)
+        { throw new QueryExceptionHTTP(-1, "Failed to connect to remove server within specified
timeout"); }
         catch (IOException ioEx)
         { throw new QueryExceptionHTTP(ioEx); }
     }
@@ -297,6 +352,29 @@ public class HttpQuery extends Params
         }
     }
 
+    private void applyTimeouts(HttpURLConnection conn)
+    {
+    	if (connectTimeout > 0)
+    	{
+    		conn.setConnectTimeout(connectTimeout);
+    	}
+    	if (readTimeout > 0)
+    	{
+    		conn.setReadTimeout(readTimeout);
+    	}
+    }
+    
+    private void applyEncodings(HttpURLConnection conn)
+    {
+    	List<String> encodings = new ArrayList<String>();
+    	if (allowGZip) encodings.add("gzip");
+    	if (allowDeflate) encodings.add("deflate");
+    	if (encodings.size() > 0)
+    	{
+    		//Apply the Accept-Encoding header if at least one encoding has been selected
+    		conn.setRequestProperty("Accept-Encoding", StrUtils.strjoin(", ", encodings));
+    	}
+    }
 
     private InputStream execCommon() throws QueryExceptionHTTP
     {
@@ -330,9 +408,36 @@ public class HttpQuery extends Params
                     throw new QueryExceptionHTTP(responseCode, responseMessage) ;
             }
             
-            // Request suceeded
+            // Request succeeded
             //httpConnection.setReadTimeout(10) ;
             InputStream in = httpConnection.getInputStream() ;
+
+            String x$ = httpConnection.getContentType() ;
+            String y$ = httpConnection.getContentEncoding() ;
+            
+            //If compression was enabled and we got a compressed response as indicated by
the presence of
+            //a Transfer-Encoding header we need to ensure the input stream is appropriately
wrapped in
+            //the relevant stream type but checking that the JVM hasn't been clever enough
to do
+            //this for us already
+            String contentEnc = httpConnection.getContentEncoding() ;
+            
+            if (contentEnc != null)
+            {
+            	if (contentEnc.equalsIgnoreCase("gzip"))
+            	{
+            		if (!(in instanceof GZIPInputStream))
+            		{
+            			in = new GZIPInputStream(in);
+            		}
+            	}
+            	else if (contentEnc.equalsIgnoreCase("deflate"))
+            	{
+            		if (!(in instanceof DeflaterInputStream))
+            		{
+            			in = new DeflaterInputStream(in);
+            		}
+            	}
+            }
             
             if ( false )
             {

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/QueryEngineHTTP.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/QueryEngineHTTP.java?rev=1243160&r1=1243159&r2=1243160&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/QueryEngineHTTP.java
(original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/engine/http/QueryEngineHTTP.java
Sat Feb 11 22:02:13 2012
@@ -27,22 +27,17 @@ import java.util.Map ;
 import java.util.concurrent.TimeUnit ;
 
 import org.openjena.atlas.io.IO ;
-import org.openjena.atlas.lib.NotImplemented ;
+import org.openjena.riot.Lang ;
 import org.openjena.riot.WebContent ;
 import org.slf4j.Logger ;
 import org.slf4j.LoggerFactory ;
 
-import com.hp.hpl.jena.query.ARQ ;
-import com.hp.hpl.jena.query.Dataset ;
-import com.hp.hpl.jena.query.Query ;
-import com.hp.hpl.jena.query.QueryExecException ;
-import com.hp.hpl.jena.query.QueryExecution ;
-import com.hp.hpl.jena.query.QuerySolution ;
-import com.hp.hpl.jena.query.ResultSet ;
-import com.hp.hpl.jena.query.ResultSetFactory ;
+import com.hp.hpl.jena.query.* ;
 import com.hp.hpl.jena.rdf.model.Model ;
 import com.hp.hpl.jena.sparql.ARQException ;
 import com.hp.hpl.jena.sparql.graph.GraphFactory ;
+import com.hp.hpl.jena.sparql.resultset.CSVInput ;
+import com.hp.hpl.jena.sparql.resultset.JSONInput ;
 import com.hp.hpl.jena.sparql.resultset.XMLInput ;
 import com.hp.hpl.jena.sparql.util.Context ;
 import com.hp.hpl.jena.util.FileManager ;
@@ -69,6 +64,33 @@ public class QueryEngineHTTP implements 
     
     private boolean finished = false ;
     
+    //Timeouts
+    private long connectTimeout = 0;
+    private TimeUnit connectTimeoutUnit = TimeUnit.MILLISECONDS;
+    private long readTimeout = 0;
+    private TimeUnit readTimeoutUnit = TimeUnit.MILLISECONDS;
+    
+    //Compression Support
+    private boolean allowGZip = true ;
+    private boolean	allowDeflate = true;
+    
+    //Content Types
+    private String selectContentType = WebContent.contentTypeResultsXML;
+    private String askContentType = WebContent.contentTypeResultsXML;
+    private String modelContentType = WebContent.contentTypeRDFXML;
+    public static String[] supportedSelectContentTypes = new String []
+    		{
+    			WebContent.contentTypeResultsXML,
+    			WebContent.contentTypeResultsJSON,
+    			WebContent.contentTypeTextTSV,
+    			WebContent.contentTypeTextCSV
+    		};
+    public static String[] supportedAskContentTypes = new String []
+    		{
+    			WebContent.contentTypeResultsXML,
+    			WebContent.contentTypeJSON
+    		};
+    
     // Releasing HTTP input streams is important. We remember this for SELECT,
     // and will close when the engine is closed
     private InputStream retainedConnection = null;
@@ -118,6 +140,22 @@ public class QueryEngineHTTP implements 
     {
         this.namedGraphURIs = namedGraphURIs ;
     }
+    
+    /**
+     * Sets whether the HTTP request will specify Accept-Encoding: gzip
+     */
+    public void setAllowGZip(boolean allowed)
+    {
+    	allowGZip = allowed;
+    }
+    
+    /**
+     * Sets whether the HTTP requests will specify Accept-Encoding: deflate
+     */
+    public void setAllowDeflate(boolean allowed)
+    {
+    	allowDeflate = allowed;
+    }
 
     public void addParam(String field, String value)
     {
@@ -159,7 +197,7 @@ public class QueryEngineHTTP implements 
     {
         HttpQuery httpQuery = makeHttpQuery() ;
         // TODO Allow other content types.
-        httpQuery.setAccept(HttpParams.contentTypeResultsXML) ;
+        httpQuery.setAccept(selectContentType) ;
         InputStream in = httpQuery.exec() ;
         
         if ( false )
@@ -170,9 +208,17 @@ public class QueryEngineHTTP implements 
             in = new ByteArrayInputStream(b) ; 
         }
         
-        ResultSet rs = ResultSetFactory.fromXML(in) ;
         retainedConnection = in; // This will be closed on close()
-        return rs ;
+        //TODO: Find a way to auto-detect how to create the ResultSet based on the content
type in use
+        if (selectContentType.equals(WebContent.contentTypeResultsXML))
+            return ResultSetFactory.fromXML(in);
+        if (selectContentType.equals(WebContent.contentTypeResultsJSON))
+            return  ResultSetFactory.fromJSON(in);
+        if (selectContentType.equals(WebContent.contentTypeTextTSV))
+            return ResultSetFactory.fromTSV(in);
+        if (selectContentType.equals(WebContent.contentTypeTextCSV))
+            return CSVInput.fromCSV(in);
+        throw new QueryException("SELECT Content-Type is not yet supported by this query
engine");
     }
 
     @Override
@@ -190,9 +236,14 @@ public class QueryEngineHTTP implements 
     private Model execModel(Model model)
     {
         HttpQuery httpQuery = makeHttpQuery() ;
-        httpQuery.setAccept(HttpParams.contentTypeRDFXML) ;
+        httpQuery.setAccept(modelContentType) ;
         InputStream in = httpQuery.exec() ;
-        model.read(in, null) ;
+        
+        //Try to select language appropriately here based on the model content type
+        Lang lang = WebContent.contentTypeToLang(modelContentType);
+        if (!lang.isTriples()) throw new QueryException("Content Type returned is not a valid
RDF Graph syntax");
+        model.read(in, null, lang.getName()) ; 
+        
         return model ;
     }
     
@@ -200,13 +251,21 @@ public class QueryEngineHTTP implements 
     public boolean execAsk()
     {
         HttpQuery httpQuery = makeHttpQuery() ;
-        httpQuery.setAccept(HttpParams.contentTypeResultsXML) ;
+        httpQuery.setAccept(askContentType) ;
         InputStream in = httpQuery.exec() ;
-        boolean result = XMLInput.booleanFromXML(in) ;
-        // Ensure connection is released
-        try { in.close(); }
-        catch (java.io.IOException e) { log.warn("Failed to close connection", e); }
-        return result;
+
+        try {
+            //Parse the result appropriately depending on the selected content type
+            if (askContentType.equals(WebContent.contentTypeResultsXML))
+                return XMLInput.booleanFromXML(in) ;
+            if (askContentType.equals(WebContent.contentTypeResultsJSON))
+                return JSONInput.booleanFromJSON(in) ;
+            throw new QueryException("ASK Content-Type is not yet supported by this query
engine");
+        } finally {
+            // Ensure connection is released
+            try { in.close(); }
+            catch (java.io.IOException e) { log.warn("Failed to close connection", e); }
+        }
     }
 
     @Override
@@ -220,31 +279,37 @@ public class QueryEngineHTTP implements 
     @Override public Query getQuery()       { return query ; }
     
     @Override
-    public void setTimeout(long timeout)
+    public void setTimeout(long readTimeout)
     {
-        throw new NotImplemented("Not implemented yet - please send a patch to the Apache
Jena project : https://issues.apache.org/jira/browse/JENA-56") ;
+        this.readTimeout = readTimeout;
+        this.readTimeoutUnit = TimeUnit.MILLISECONDS;
     }
 
     @Override
-    public void setTimeout(long timeout1, long timeout2)
+    public void setTimeout(long readTimeout, long connectTimeout)
     {
-        throw new NotImplemented("Not implemented yet - please send a patch to the Apache
Jena project : https://issues.apache.org/jira/browse/JENA-56") ;
+        this.readTimeout = readTimeout;
+        this.readTimeoutUnit = TimeUnit.MILLISECONDS;
+        this.connectTimeout = connectTimeout;
+        this.connectTimeoutUnit = TimeUnit.MILLISECONDS;
     }
 
 
     @Override
-    public void setTimeout(long timeout, TimeUnit timeoutUnits)
+    public void setTimeout(long readTimeout, TimeUnit timeoutUnits)
     {
-        throw new NotImplemented("Not implemented yet - please send a patch to the Apache
Jena project : https://issues.apache.org/jira/browse/JENA-56") ;
+        this.readTimeout = readTimeout;
+        this.readTimeoutUnit = timeoutUnits;
     }
 
     @Override
     public void setTimeout(long timeout1, TimeUnit timeUnit1, long timeout2, TimeUnit timeUnit2)
     {
-        throw new NotImplemented("Not implemented yet - please send a patch to the Apache
Jena project : https://issues.apache.org/jira/browse/JENA-56") ;
+        this.readTimeout = timeout1;
+        this.readTimeoutUnit = timeUnit1;
+        this.connectTimeout = timeout2;
+        this.connectTimeoutUnit = timeUnit2;
     }
-
-
     
     private HttpQuery makeHttpQuery()
     {
@@ -270,9 +335,27 @@ public class QueryEngineHTTP implements 
         if ( params != null )
             httpQuery.merge(params) ;
         
+        if (allowGZip)
+        	httpQuery.setAllowGZip(true);
+
+        if (allowDeflate)
+        	httpQuery.setAllowDeflate(true);
+        
         httpQuery.setBasicAuthentication(user, password) ;
+        
+        //Apply timeouts
+        if (connectTimeout > 0)
+        {
+        	httpQuery.setConnectTimeout((int)connectTimeoutUnit.toMillis(connectTimeout));
+        }
+        if (readTimeout > 0)
+        {
+        	httpQuery.setReadTimeout((int)readTimeoutUnit.toMillis(readTimeout));
+        }
+        
         return httpQuery ;
     }
+
     
     // This is to allow setting additional/optional query parameters on a per SERVICE level,
see: JENA-195
     protected static Params getServiceParams(String serviceURI, Context context) throws QueryExecException
@@ -322,4 +405,56 @@ public class QueryEngineHTTP implements 
         HttpQuery httpQuery = makeHttpQuery() ;
         return "GET "+httpQuery.toString() ;
     }
+    
+    /**
+     * Sets the Content Type for SELECT queries provided that the format is supported
+     * @param contentType
+     */
+    public void setSelectContentType(String contentType)
+    {
+    	boolean ok = false;
+    	for (String supportedType : supportedSelectContentTypes)
+    	{
+    		if (supportedType.equals(contentType))
+    		{
+    			ok = true;
+    			break;
+    		}
+    	}
+    	if (!ok) throw new IllegalArgumentException("Given Content Type '" + contentType + "'
is not a supported SELECT results format");
+    	selectContentType = contentType;
+    }
+    
+    /**
+     * Sets the Content Type for ASK queries provided that the format is supported
+     * @param contentType
+     */
+    public void setAskContentType(String contentType)
+    {
+    	boolean ok = false;
+    	for (String supportedType : supportedAskContentTypes)
+    	{
+    		if (supportedType.equals(contentType))
+    		{
+    			ok = true;
+    			break;
+    		}
+    	}
+    	if (!ok) throw new IllegalArgumentException("Given Content Type '" + contentType + "'
is not a supported ASK results format");
+    	askContentType = contentType;
+    }
+    
+    /**
+     * Sets the Content Type for CONSTRUCT/DESCRIBE queries provided that the format is supported
+     * @param contentType
+     */
+    public void setModelContentType(String contentType)
+    {
+    	//Check that this is a valid setting
+    	Lang lang = WebContent.contentTypeToLang(contentType);
+    	if (lang == null) throw new IllegalArgumentException("Given Content Type '" + contentType
+ "' is not supported by RIOT");
+    	if (!lang.isTriples()) throw new IllegalArgumentException("Given Content Type '" + contentType
+ " is not a RDF Graph format");
+    	
+    	modelContentType = contentType;
+    }
 }



Mime
View raw message