1 5 6 package org.joseki.server.http; 7 8 import java.io.*; 9 import java.util.*; 10 import org.apache.commons.logging.*; 11 12 import javax.servlet.*; 13 import javax.servlet.http.*; 14 15 import com.hp.hpl.jena.rdf.model.*; 16 import com.hp.hpl.jena.shared.JenaException; 17 18 import org.joseki.util.Convert; 19 import org.joseki.server.*; 20 import org.joseki.Joseki ; 21 22 23 27 28 public class JosekiWebAPI extends HttpServlet implements Connector 29 { 30 protected static Log log = null ; 33 static { 35 try { log = LogFactory.getLog(JosekiWebAPI.class) ; } 36 catch (Exception ex) 37 { 38 System.err.println("Exception creating the logger") ; 39 System.err.println("Commons logging jar files in WEB-INF/lib/?") ; 40 System.err.println(ex.getMessage()); 41 } 43 } 44 45 static int urlLimit = 4*1024 ; 47 static boolean initAttempted = false ; 48 49 protected Dispatcher dispatcher = null ; 50 protected HttpOperationCodec httpCodec = new HttpOperationCodec() ; 51 52 String printName = "HTTP RDF WebAPI"; 53 ServletConfig servletConfig = null; 55 ServletContext servletContext = null; 57 58 63 64 public JosekiWebAPI() 65 { 66 log.debug("Created") ; 67 } 68 69 public void init() throws ServletException 70 { 71 super.init() ; 72 return ; 73 } 74 75 77 public void init(ServletConfig config) throws ServletException 78 { 79 super.init(config); 80 81 85 if ( initAttempted ) 86 { 87 log.info("Re-initialization of servlet attempted") ; 88 if ( dispatcher == null ) 89 dispatcher = new Dispatcher() ; 90 return ; 91 } 92 initAttempted = true ; 93 94 servletConfig = config; 95 96 if (config != null) 97 { 98 servletContext = config.getServletContext(); 99 FileManager.getInstance().setServletContext(servletContext) ; 100 } 101 102 printName = config.getServletName(); 103 104 servletEnv() ; 105 DispatcherRegistry dispatcherRegistry = DispatcherRegistry.getInstance() ; 106 107 if ( ! dispatcherRegistry.contains(RDFServer.DispatcherName) ) 108 { 109 log.info("Creating dispatcher") ; 110 Dispatcher tmp = new Dispatcher() ; 111 try { 113 initDispatcher(tmp); 114 } catch (ConfigurationErrorException confEx) 115 { 116 throw new ServletException("Joseki configuration error", confEx) ; 117 } 118 dispatcherRegistry.add(RDFServer.DispatcherName, tmp) ; 119 dispatcher = dispatcherRegistry.find(RDFServer.DispatcherName) ; 120 } 121 else 122 { 123 log.info("Using existing dispatcher") ; 124 dispatcher = dispatcherRegistry.find(RDFServer.DispatcherName) ; 125 } 126 } 127 128 130 public void destroy() 131 { 132 log.debug("destroy"); 133 } 134 135 143 public void doGet(HttpServletRequest httpRequest, HttpServletResponse httpResponse) 144 { 145 try { 146 if ( log.isDebugEnabled() ) 147 log.debug(fmtRequest(httpRequest)) ; 148 149 152 String requestURL = httpRequest.getRequestURL().toString() ; 153 String uri = httpRequest.getRequestURI() ; 154 155 if ( uri.length() > urlLimit ) 156 { 157 httpResponse.setStatus(HttpServletResponse.SC_REQUEST_URI_TOO_LONG) ; 158 return ; 159 } 160 161 uri = formDispatchURI(uri, httpRequest) ; 162 163 166 String queryLang = httpRequest.getParameter("lang"); 167 168 if ( httpRequest.getParameterMap().size() == 0 ) 169 queryLang = "GET" ; 171 172 try { 173 Request opRequest = dispatcher.createQueryRequest(uri, requestURL, queryLang) ; 174 175 Map m = httpRequest.getParameterMap() ; 176 for ( Iterator iter = m.keySet().iterator() ; iter.hasNext() ; ) 177 { 178 String k = (String)iter.next() ; 179 String[] v = (String[])m.get(k) ; 180 if ( k.equals("q") ) 181 k = "query" ; 182 for ( int vi = 0 ; vi < v.length ; vi++ ) 183 opRequest.setParam(k,v[vi]) ; 184 } 185 186 execute(opRequest, httpRequest, httpResponse) ; 187 } catch (ExecutionException execEx) 188 { 189 doResponse(execEx, uri, httpResponse) ; 190 return ; 191 } 192 } catch (Exception ex) 193 { 194 try { 195 log.warn("Internal server error", ex) ; 196 httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR) ; 197 httpResponse.flushBuffer() ; 198 httpResponse.getWriter().close() ; 199 } catch (Exception e) {} 200 } 201 } 202 203 204 public void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) 205 { 206 try { 207 if ( log.isDebugEnabled() ) 208 log.debug(fmtRequest(httpRequest)) ; 209 210 String requestURL = httpRequest.getRequestURL().toString() ; 211 String uri = httpRequest.getRequestURI() ; 212 String httpQueryString = httpRequest.getQueryString() ; 213 214 uri = formDispatchURI(uri, httpRequest) ; 215 216 if ( httpQueryString == null ) 217 { 218 httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "The HTTP query string specified in POST is empty: it must be ?op=<opName>") ; 219 return ; 220 } 221 222 225 String reqName = httpQueryString ; 227 int i = reqName.indexOf('&') ; 229 if ( i != -1 ) 230 { 231 reqName = reqName.substring(0,i) ; 232 } 234 235 239 if ( reqName.startsWith("op=") ) 240 reqName = reqName.substring("op=".length()) ; 241 242 try { 243 Request opRequest = 244 dispatcher.createOperation(uri, requestURL, reqName) ; 245 httpCodec.setParameters(opRequest, httpRequest) ; 246 httpCodec.setArgs(opRequest, httpRequest) ; 247 execute(opRequest, httpRequest, httpResponse) ; 248 } catch (ExecutionException execEx) 249 { 250 doResponse(execEx, uri, httpResponse) ; 251 return ; 252 } 253 } 254 catch (Exception ex) 255 { 256 ex.printStackTrace(System.err) ; 257 doResponse(httpResponse, HttpServletResponse.SC_INTERNAL_SERVER_ERROR) ; 259 return ; 260 } 261 } 262 263 264 public void doOptions(HttpServletRequest httpRequest, HttpServletResponse httpResponse) 265 throws ServletException, java.io.IOException 266 { 267 try { 268 log.debug(fmtRequest(httpRequest)) ; 269 270 String requestURL = httpRequest.getRequestURL().toString() ; 271 String uri = httpRequest.getRequestURI() ; 272 273 uri = formDispatchURI(uri, httpRequest) ; 274 275 276 log.debug("Context path="+httpRequest.getContextPath()+" :: PathInfo="+httpRequest.getPathInfo()+" :: PathTranslated="+httpRequest.getPathTranslated()) ; 278 279 if ( uri.length() > urlLimit ) 280 { 281 httpResponse.setStatus(HttpServletResponse.SC_REQUEST_URI_TOO_LONG) ; 282 return ; 283 } 284 285 String baseURL = "http://"+httpRequest.getServerName() ; 288 int port = httpRequest.getServerPort() ; 289 if ( port != 80 ) 290 baseURL= baseURL+":"+port ; 291 292 try { 293 if (uri.equals("*") || uri.equals("/") || uri.equals("/*")) 295 { 296 try { 298 Request opHostRequest = dispatcher.createRequest(uri, requestURL, "options", false) ; 299 opHostRequest.setParam("baseURL", baseURL) ; 300 log.info("Options: URI="+ opHostRequest.getModelURI() + " Request="+opHostRequest.getName()) ; 302 Model resultModel = dispatcher.getOptionsModel(baseURL); 303 doResponse(resultModel, opHostRequest, httpRequest, httpResponse) ; 304 } 305 catch (ExecutionException execEx) { doResponse(execEx, uri, httpResponse); } 306 return ; 307 } 308 309 Request opRequest = dispatcher.createOperation(uri, requestURL, "options") ; 310 opRequest.setParam("baseURL", baseURL) ; 311 execute(opRequest, httpRequest, httpResponse); 312 } catch (ExecutionException execEx) 313 { 314 doResponse(execEx, uri, httpResponse) ; 315 return ; 316 } 317 } 318 catch (Exception ex) 319 { 320 try 321 { 322 httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 323 httpResponse.flushBuffer(); 324 httpResponse.getWriter().close(); 325 } catch (Exception e) { } 326 } 327 } 328 329 336 337 private String formDispatchURI(String uri, HttpServletRequest httpRequest) 338 { 339 String dispatchURI = uri ; 340 String contextPath = httpRequest.getContextPath() ; 341 342 if ( contextPath != null && contextPath.length() > 0 ) 343 dispatchURI = dispatchURI.substring(contextPath.length()) ; 344 345 String servletPath = httpRequest.getServletPath() ; 347 if ( servletPath != null && servletPath.length() > 0 ) 348 dispatchURI = dispatchURI.substring(servletPath.length()) ; 349 350 if ( log.isDebugEnabled() ) 351 { 352 if ( servletPath == null ) 353 servletPath = "" ; 354 if ( contextPath == null ) 355 contextPath = "" ; 356 log.debug("DispatchURI: "+uri+" => "+dispatchURI+" (ContextPath = "+contextPath+", ServletPath = "+servletPath+")") ; 357 } 358 return dispatchURI ; 359 } 360 361 362 protected void execute(Request req, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ExecutionException 363 { 364 Model resultModel = null ; 365 366 if ( req.getName().equals("query") ) 367 log.debug("URI="+ req.getModelURI() + " Query="+req.getParam("lang")) ; 368 else 369 log.debug("URI="+ req.getModelURI() + " Request="+req.getName()) ; 370 371 resultModel = dispatcher.exec(req) ; 372 doResponse(resultModel, req, httpRequest, httpResponse); 373 374 } 379 380 381 384 private Map getParameters(String queryString) 385 { 386 Map map = new HashMap() ; 387 388 String[] params = queryString.split("&") ; 389 for ( int i = 0 ; i < params.length ; i++ ) 390 { 391 String p = params[i] ; 392 String[] x = p.split("=",2) ; 393 394 if ( x.length == 0 ) 395 continue ; 396 397 String pName = x[0] ; 398 String pValue = "" ; 399 if ( x.length == 2 ) 400 pValue = x[1] ; 401 map.put(pName, "") ; 402 } 403 return null ; 405 } 406 407 409 protected void doResponse(Model resultModel, Request opRequest, 410 HttpServletRequest httpRequest, 411 HttpServletResponse httpResponse) 412 { 413 try 414 { 415 log.debug("Successful operation: URI = " + opRequest.getModelURI()+" : Request = "+opRequest.getName() ) ; 416 try 417 { 418 if ( httpCodec.sendResponse(resultModel, opRequest, 419 httpRequest, httpResponse) ) 420 log.info("OK - "+fmtRequest(httpRequest)) ; 421 } 422 catch (RDFException rdfEx) 423 { 424 log.warn("RDFException", rdfEx); 426 httpResponse.sendError( 428 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 429 "RDFException: " + rdfEx); 430 return; 431 } 432 catch (JenaException jEx) 433 { 434 log.warn("JenaException: "+jEx.getMessage()); 436 if ( jEx.getCause() != null ) 437 jEx.getCause().printStackTrace(httpResponse.getWriter()); 438 else 439 jEx.printStackTrace(httpResponse.getWriter()); 440 httpResponse.sendError( 441 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 442 "JenaException: " + jEx); 443 return; 444 } 445 catch (Exception ex) 446 { 447 log.warn("Exception", ex); 449 450 httpResponse.sendError( 451 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 452 "Exception: " + ex); 453 return; 454 } 455 } 456 catch (IOException ioEx) 457 { 458 log.warn("IOException in normal response") ; 460 try { 461 httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 462 httpResponse.flushBuffer(); 463 httpResponse.getWriter().close(); 464 } catch (Exception e) { } 465 } 466 } 467 468 470 protected void doResponse(ExecutionException execEx, String uri, HttpServletResponse response) 471 { 472 473 try { 474 String httpMsg = ExecutionError.errorString(execEx.returnCode); 475 log.info("Error: URI = " + uri + " : " + httpMsg); 477 httpCodec.sendError(execEx, response) ; 478 return; 479 } catch (IOException ioEx) 480 { 481 log.warn("IOException in exception response") ; 482 try { 483 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 484 response.flushBuffer(); 485 response.getWriter().close(); 486 } catch (Exception e) { } 487 } 488 } 489 490 491 493 protected void doResponse(HttpServletResponse response, int reason) 494 { 495 try { 497 response.setHeader(Joseki.httpHeaderField, Joseki.httpHeaderValue) ; 498 response.setStatus(reason) ; 499 response.flushBuffer() ; 500 response.getWriter().close() ; 501 } catch (Exception e) {} 502 } 503 504 505 507 public String getServletInfo() 508 { 509 return printName; 511 } 512 513 static String fmtRequest(HttpServletRequest request) 514 { 515 StringBuffer sbuff = new StringBuffer() ; 516 sbuff.append(request.getMethod()) ; 517 sbuff.append(" ") ; 518 sbuff.append(Convert.decWWWForm(request.getRequestURL())); 519 520 String qs = request.getQueryString(); 521 if (qs != null) 522 { 523 String tmp = request.getQueryString() ; 524 tmp = Convert.decWWWForm(tmp) ; 525 tmp = tmp.replace('\n', ' ') ; 526 tmp = tmp.replace('\r', ' ') ; 527 sbuff.append("?").append(tmp); 528 } 529 return sbuff.toString() ; 530 } 531 532 535 539 540 541 542 552 553 private boolean initDispatcher(Dispatcher disp) throws ConfigurationErrorException 554 { 555 String tmp = System.getProperty(RDFServer.propertyModelSet) ; 556 if ( tmp != null && tmp.equals(RDFServer.noMapValue)) 557 return false ; 558 559 if ( tmp != null ) 560 if (attemptLoad(tmp, "System property: " + RDFServer.propertyModelSet, disp)) 561 return true; 562 563 if (servletConfig != null 564 && attemptLoad( 565 servletConfig.getInitParameter(RDFServer.propertyModelSet), 566 "Servlet configuration parameter: " + RDFServer.propertyModelSet, 567 disp) ) 568 return true; 569 570 if (attemptLoad(RDFServer.defaultConfigFile, "Default filename",disp) ) 572 return true; 573 574 return false; 575 } 576 577 private boolean attemptLoad(String filename, String reason, Dispatcher disp) 578 throws ConfigurationErrorException 579 { 580 if (filename == null) 581 return false; 582 583 try 584 { 585 disp.getModelSet().load(filename) ; 586 log.info("Loaded data source configuration: " + filename); 587 return true; 589 } catch (RDFException rdfEx) 590 { 591 throw new ConfigurationErrorException("RDF Exception: "+rdfEx.getMessage(), rdfEx) ; 593 } catch (IOException ioEx) 595 { 596 throw new ConfigurationErrorException("IO Exception: "+ioEx.getMessage(), ioEx) ; 597 } 599 } 600 601 public void setDispatcher(Dispatcher d) 602 { 603 dispatcher = d ; 604 } 605 606 public Dispatcher getDispatcher() 607 { 608 return dispatcher ; 609 } 610 611 612 private void servletEnv() 613 { 614 if ( ! log.isDebugEnabled() ) 615 return ; 616 617 try { 618 java.net.URL url = servletContext.getResource("/") ; 619 log.trace("Joseki base directory: "+url) ; 620 } catch (Exception ex) {} 621 622 if (servletConfig != null) 623 { 624 String tmp = servletConfig.getServletName() ; 625 log.trace("Servlet = " + (tmp != null ? tmp : "<null>")); 626 Enumeration enum = servletConfig.getInitParameterNames(); 627 628 for (; enum.hasMoreElements();) 629 { 630 String s = (String) enum.nextElement(); 631 log.trace("Servlet parameter: " + s + " = " + servletConfig.getInitParameter(s)); 632 } 633 } 634 if (servletContext != null) 635 { 636 String tmp = servletContext.getServletContextName(); 638 log.debug("Webapp = " + (tmp != null ? tmp : "<null>")); 640 641 643 Enumeration enum = servletContext.getInitParameterNames(); 644 for (;enum.hasMoreElements();) 645 { 646 String s = (String) enum.nextElement(); 647 log.debug("Webapp parameter: " + s + " = " + servletContext.getInitParameter(s)); 648 } 649 } 650 657 } 658 } 659 660 686 | Popular Tags |