There are no available options for this view.

Parent Directory Parent Directory | Revision Log Revision Log

Revision 6 - (show annotations) (download) (as text)
Wed Nov 19 22:34:23 2008 UTC (3 years, 2 months ago) by hartig
File MIME type: text/x-java
File size: 9555 byte(s)
initial commit
1 /*
2 Copyright 2008 Olaf Hartig
3
4 This file is part of SQUIN.
5
6 SQUIN is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 SQUIN is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with SQUIN. If not, see <http://www.gnu.org/licenses/>.
18 */
19 package org.squin.servlet;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.io.UnsupportedEncodingException;
24
25 import java.net.URLDecoder;
26
27 import java.util.Arrays;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32
33 import javax.naming.Context;
34 import javax.naming.InitialContext;
35 import javax.naming.NameNotFoundException;
36 import javax.naming.NamingException;
37 import javax.servlet.http.HttpServlet;
38 import javax.servlet.http.HttpServletRequest;
39 import javax.servlet.http.HttpServletResponse;
40
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43
44 import com.hp.hpl.jena.util.FileManager;
45 import com.hp.hpl.jena.query.Query;
46 import com.hp.hpl.jena.query.QueryException;
47 import com.hp.hpl.jena.query.QueryExecution;
48 import com.hp.hpl.jena.query.QueryExecutionFactory;
49 import com.hp.hpl.jena.query.QueryFactory;
50 import com.hp.hpl.jena.query.ResultSet;
51 import com.hp.hpl.jena.query.ResultSetFormatter;
52 import com.hp.hpl.jena.sparql.resultset.ResultSetMem;
53 import com.hp.hpl.jena.sparql.util.Utils;
54
55 import de.fuberlin.wiwiss.ng4j.semwebclient.SemanticWebClient;
56
57
58 /**
59 * The servlet that processes requests to the SQUIN service.
60 *
61 * @author Olaf Hartig
62 */
63 public class Servlet extends HttpServlet
64 {
65 // members
66
67 static private Log log = LogFactory.getLog( Servlet.class );
68
69 static final public String MIME_TYPE_RESULT_XML = "application/sparql-results+xml";
70 static final public String MIME_TYPE_RESULT_JSON = "application/sparql-results+json";
71 static final public String MIME_TYPE_XML1 = "application/xml";
72 static final public String MIME_TYPE_XML2 = "text/xml";
73 static final public String MIME_TYPE_JSON = "application/json";
74
75 static private Context namingContext = null;
76
77
78 // initialization
79
80 public Servlet ()
81 {
82 }
83
84
85 // implementation of the HttpServlet interface
86
87 protected void doGet ( HttpServletRequest req, HttpServletResponse resp )
88 {
89 log.info( "Start processing request " + req.hashCode() + "." );
90 // log.info( "real path: " + getServletContext().getRealPath("WW") );
91 log.info( "getInitialFilesDirectory: " + getInitialFilesDirectory() );
92
93 String accept = req.getHeader( "ACCEPT" );
94 if ( accept != null
95 && ! accept.contains(MIME_TYPE_RESULT_XML)
96 && ! accept.contains(MIME_TYPE_XML1)
97 && ! accept.contains(MIME_TYPE_XML2)
98 && ! accept.contains(MIME_TYPE_RESULT_JSON)
99 && ! accept.contains(MIME_TYPE_JSON)
100 && ! accept.contains("application/*")
101 && ! accept.contains("*/*") )
102 {
103 log.info( "NOT ACCEPTABLE for request " + req.hashCode() + " (ACCEPT header field: " + accept + ")" );
104
105 try {
106 resp.sendError( HttpServletResponse.SC_NOT_ACCEPTABLE, "Your client does not seem to accept '" + MIME_TYPE_RESULT_XML + "'." );
107 } catch ( IOException e ) {
108 log.error( "Sending the error reponse to request " + req.hashCode() + " caused a " + Utils.className(e) + ": " + e.getMessage(), e );
109 }
110
111 return;
112 }
113
114 // get (and check) the request parameters
115 String errorMsgs = "";
116 // - the SPARQL query
117 Query query = null;
118 String queryString = req.getParameter("query");
119 if ( queryString == null || queryString.isEmpty() )
120 {
121 errorMsgs += "Query not specified. ";
122 }
123 else
124 {
125 try
126 {
127 query = QueryFactory.create( queryString );
128 if ( ! query.isSelectType() ) {
129 errorMsgs += "Query must be a SELECT query. ";
130 }
131 }
132 catch ( QueryException e ) {
133 errorMsgs += e.getMessage() + " ";
134 }
135 }
136
137 // - the output type
138 String responseContentType = null;
139 String output = req.getParameter("output");
140 if ( output != null )
141 {
142 if ( output.equals("json") ) {
143 responseContentType = MIME_TYPE_RESULT_JSON;
144 } else if ( output.equals("xml") ) {
145 responseContentType = MIME_TYPE_RESULT_XML;
146 } else {
147 errorMsgs += "Unsupported output format requested. ";
148 }
149 }
150 else
151 {
152 if ( accept != null
153 && ( accept.contains(MIME_TYPE_RESULT_JSON)
154 || accept.contains(MIME_TYPE_RESULT_JSON) ) ) {
155 responseContentType = MIME_TYPE_RESULT_JSON;
156 } else {
157 responseContentType = MIME_TYPE_RESULT_XML;
158 }
159 }
160
161 if ( ! errorMsgs.isEmpty() )
162 {
163 log.info( "BAD REQUEST for request " + req.hashCode() + ": " + errorMsgs );
164
165 try {
166 resp.sendError( HttpServletResponse.SC_BAD_REQUEST, errorMsgs );
167 } catch ( IOException e ) {
168 log.error( "Sending the error reponse to request " + req.hashCode() + " caused a " + Utils.className(e) + ": " + e.getMessage(), e );
169 }
170
171 return;
172 }
173
174 // execute the query
175 log.info( "Start executing request " + req.hashCode() + " with query:" );
176 log.info( queryString );
177 QueryExecution qe = QueryExecutionFactory.create( query,
178 getSemanticWebClient().asJenaModel("default") );
179 ResultSetMem rs = new ResultSetMem( qe.execSelect() );
180 // ResultSet rs = qe.execSelect();
181
182 log.info( "Created the result set (size: " + rs.size() + ") for request " + req.hashCode() + "." );
183
184 // create the response
185 OutputStream out = null;
186 try {
187 out = resp.getOutputStream();
188 }
189 catch ( IOException e )
190 {
191 log.error( "Getting the response output stream for request " + req.hashCode() + " caused a " + Utils.className(e) + ": " + e.getMessage(), e );
192
193 try {
194 resp.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
195 } catch ( IOException e2 ) {
196 log.error( "Sending the error reponse for request " + req.hashCode() + " caused a " + Utils.className(e2) + ": " + e2.getMessage(), e2 );
197 }
198
199 return;
200 }
201
202 // write the response
203 resp.setContentType( responseContentType );
204 try
205 {
206 if ( responseContentType == MIME_TYPE_RESULT_JSON ) {
207 ResultSetFormatter.outputAsJSON( out, rs );
208 } else {
209 ResultSetFormatter.outputAsXML( out, rs );
210 }
211
212 log.info( "Result written to the response stream for request " + req.hashCode() + "." );
213 }
214 catch ( Exception e )
215 {
216 log.error( "Writing the model to the response stream for request " + req.hashCode() + " caused a " + Utils.className(e) + ": " + e.getMessage() );
217 try {
218 resp.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
219 } catch ( IOException e2 ) {
220 log.error( "Sending an error response for request " + req.hashCode() + " caused a " + Utils.className(e2) + ": " + e2.getMessage(), e2 );
221 }
222 }
223
224 // finish
225 try
226 {
227 out.flush();
228 resp.flushBuffer();
229 log.info( "Response buffer for request " + req.hashCode() + " flushed." );
230 }
231 catch ( IOException e )
232 {
233 log.error( "Flushing the response buffer for request " + req.hashCode() + " caused a " + Utils.className(e) + ": " + e.getMessage(), e );
234 }
235
236 log.info( "Finished processing request " + req.hashCode() + "." );
237 }
238
239
240 // helper methods
241
242 private SemanticWebClient getSemanticWebClient ()
243 {
244 SemanticWebClient semweb = (SemanticWebClient) getServletContext().getAttribute( "org.squin.servlet.Servlet.semanticWebClient" );
245 if ( semweb == null )
246 {
247 semweb = createSemanticWebClient();
248 getServletContext().setAttribute( "org.squin.servlet.Servlet.semanticWebClient", semweb );
249 }
250
251 return semweb;
252 }
253
254 private SemanticWebClient createSemanticWebClient ()
255 {
256 log.debug( "Creating new SemanticWebClient object for the servlet." );
257
258 SemanticWebClient semweb = new SemanticWebClient();
259
260 semweb.setConfig( SemanticWebClient.CONFIG_MAXTHREADS, "50" );
261 semweb.setConfig( SemanticWebClient.CONFIG_MAXSTEPS, "5" );
262 semweb.setConfig( SemanticWebClient.CONFIG_DEREF_CONNECT_TIMEOUT, "9000" );
263 semweb.setConfig( SemanticWebClient.CONFIG_DEREF_READ_TIMEOUT, "9000" );
264
265 return semweb;
266 }
267
268 // static private void loadInitialGraphs ( SemanticWebClient semweb )
269 // {
270 //
271 //
272 // FileManager fm = new FileManager();
273 // fm.addLocatorFile( "tests" + FileManager.filePathSeparator + "data" );
274 //
275 // try {
276 // dataModel = fm.loadModel( "data1.n3" );
277 // } catch ( Exception e ) {
278 // throw new Exception( "Loading the file with our test data caused a " + Utils.className(e) + ": " + e.getMessage(), e );
279 // }
280 //
281 // }
282 //
283
284 static protected String getInitialFilesDirectory ()
285 {
286 Context nCtx = getNamingContext();
287
288 try {
289 return (String) nCtx.lookup( "InitialFilesDirectory" );
290 } catch ( NameNotFoundException e ) {
291 return null;
292 } catch ( NamingException e ) {
293 throw new Error( "Looking up the object named 'InitialFilesDirectory' caused a " + Utils.className(e) + ": " + e.getMessage(), e );
294 }
295 }
296
297 static protected Context getNamingContext ()
298 {
299 if ( namingContext == null )
300 {
301 try {
302 namingContext = (Context) ( new InitialContext() ).lookup( "java:comp/env" );
303 } catch ( NamingException e ) {
304 throw new Error( "Looking up the application naming context caused a " + Utils.className(e) + ": " + e.getMessage(), e );
305 }
306 }
307
308 return namingContext;
309 }
310
311 }