1 5 6 package org.infohazard.maverick; 7 8 import org.apache.commons.logging.Log; 9 import org.apache.commons.logging.LogFactory; 10 import org.infohazard.maverick.flow.Loader; 11 import org.infohazard.maverick.flow.Command; 12 import org.infohazard.maverick.flow.ConfigException; 13 import org.infohazard.maverick.flow.MaverickContext; 14 15 import org.jdom.Document; 16 import org.jdom.input.SAXBuilder; 17 import org.jdom.output.XMLOutputter; 18 import org.jdom.transform.JDOMResult; 19 20 import java.util.*; 21 import java.io.*; 22 import java.net.*; 23 import javax.servlet.*; 24 import javax.servlet.http.*; 25 import javax.xml.transform.*; 26 import javax.xml.transform.stream.StreamSource ; 27 28 29 74 public class Dispatcher extends HttpServlet 75 { 76 82 public static final String MAVERICK_APPLICATION_KEY = "mav.dispatcher"; 83 84 91 public static final String KEY_CONFIG_FILE = "mav.configFile"; 92 93 102 public static final String INITPARAM_CONFIG_FILE = "configFile"; 103 104 112 public static final String KEY_CONFIG_TRANSFORM = "mav.configTransform"; 113 114 122 public static final String INITPARAM_CONFIG_TRANSFORM = "configTransform"; 123 124 131 public static final String INITPARAM_RELOAD_COMMAND = "reloadCommand"; 132 133 141 public static final String INITPARAM_CURRENT_CONFIG_COMMAND = 142 "currentConfigCommand"; 143 144 151 public static final String INITPARAM_DEFAULT_REQUEST_CHARSET = 152 "defaultRequestCharset"; 153 154 161 public static final String INITPARAM_LIMIT_TRANSFORMS_PARAM = 162 "limitTransformsParam"; 163 164 171 public static final String INITPARAM_REUSE_CONTEXT = "reuseMaverickContext"; 172 173 183 protected static final String DEFAULT_CONFIG_FILE = "/WEB-INF/maverick.xml"; 184 185 192 protected static final String SAVED_MAVCTX_KEY = "mav.context"; 193 194 199 private static Log log = LogFactory.getLog(Dispatcher.class); 200 201 206 protected Map commands; 207 208 213 protected Document configDocument; 214 215 231 protected String defaultRequestCharset; 232 233 245 protected String limitTransformsParam; 246 247 264 protected boolean reuseMaverickContext; 265 266 271 public void init() throws ServletException 272 { 273 this.getServletContext().setAttribute(MAVERICK_APPLICATION_KEY, this); 275 276 this.defaultRequestCharset = this.getInitParameter(INITPARAM_DEFAULT_REQUEST_CHARSET); 278 279 this.limitTransformsParam = this.getInitParameter(INITPARAM_LIMIT_TRANSFORMS_PARAM); 281 282 this.reuseMaverickContext = "true".equals(this.getInitParameter(INITPARAM_REUSE_CONTEXT)); 284 285 try 286 { 287 reloadConfig(); 288 } 289 catch(ConfigException e) 290 { 291 log.error(e.getMessage(), e); 292 throw e; 293 } 294 } 295 296 301 protected void service(HttpServletRequest request, HttpServletResponse 302 response) throws IOException, ServletException 303 { 304 String commandName = extractCommandName(request); 306 307 Command cmd = this.getCommand(commandName); 309 310 if (cmd == null) 311 { 312 log.warn("No such command " + commandName); 313 314 response.sendError(HttpServletResponse.SC_NOT_FOUND, "There is no such command \"" + commandName + "\"."); 316 } 317 else 318 { 319 if (log.isDebugEnabled()) 320 log.debug("Servicing command: " + commandName); 321 322 if (this.defaultRequestCharset != null) 324 request.setCharacterEncoding(this.defaultRequestCharset); 325 326 MaverickContext ctx; 329 330 if (this.reuseMaverickContext) 331 { 332 ctx = (MaverickContext)request.getAttribute(SAVED_MAVCTX_KEY); 333 334 if (ctx == null) 335 { 336 ctx = new MaverickContext(this, request, response); 337 request.setAttribute(SAVED_MAVCTX_KEY, ctx); 338 } 339 } 340 else 341 { 342 ctx = new MaverickContext(this, request, response); 343 } 344 345 cmd.go(ctx); 346 } 347 } 348 349 355 protected String extractCommandName(HttpServletRequest request) 356 { 357 String path = (String )request.getAttribute("javax.servlet.include.servlet_path"); 362 if (path == null) 363 path = request.getServletPath(); 364 365 if (log.isDebugEnabled()) 366 { 367 log.debug("Command servlet path is: " + path); 368 log.debug("Command context path is: " + request.getContextPath()); 369 } 370 371 int firstChar = 0; 372 if (path.startsWith("/")) 373 firstChar = 1; 374 375 int period = path.lastIndexOf("."); 376 377 path = path.substring(firstChar, period); 378 379 return path; 380 } 381 382 389 protected void reloadConfig() throws ConfigException 390 { 391 log.info("Starting configuration load"); 392 393 Document replacementConfigDocument = this.loadConfigDocument(); 394 Loader loader = new Loader(replacementConfigDocument, 395 this.getServletConfig()); 396 Map replacementCommands = loader.getCommands(); 397 398 String reloadStr = this.getInitParameter(INITPARAM_RELOAD_COMMAND); 402 if (reloadStr != null) 403 { 404 Command reload = new Command() { 405 public void go(MaverickContext mctx) throws IOException, ServletException 406 { 407 try 408 { 409 reloadConfig(); 410 } 411 catch(ConfigException e) 412 { 413 log.error(e.getMessage(), e); 414 throw e; 415 } 416 } 417 }; 418 419 replacementCommands.put(reloadStr, reload); 420 } 421 422 String currentConfigStr = this.getInitParameter(INITPARAM_CURRENT_CONFIG_COMMAND); 426 if (currentConfigStr != null) 427 { 428 Command currentConfig = new Command() { 429 public void go(MaverickContext mctx) throws IOException, ServletException 430 { 431 XMLOutputter outputter = new XMLOutputter(" ", true, "UTF-8"); 432 433 mctx.getRealResponse().setContentType("text/xml; charset=UTF-8"); 434 outputter.output(configDocument, mctx.getRealResponse().getOutputStream()); 435 } 436 }; 437 438 replacementCommands.put(currentConfigStr, currentConfig); 439 } 440 441 this.commands = replacementCommands; 445 this.configDocument = replacementConfigDocument; 446 447 log.info("Finished configuration load"); 448 } 449 450 457 protected Command getCommand(String name) 458 { 459 Command cmd = (Command)this.commands.get(name); 460 461 if (cmd == null) 462 { 463 cmd = (Command)this.commands.get("*"); 464 if (cmd != null) 465 log.warn("Unknown command " + name + ", using *."); 466 } 467 468 return cmd; 469 } 470 471 477 protected Document loadConfigDocument() throws ConfigException 478 { 479 try 480 { 481 String configFile = (String )this.getServletContext().getAttribute(KEY_CONFIG_FILE); 483 484 if (configFile == null) 485 configFile = this.getInitParameter(INITPARAM_CONFIG_FILE); 486 487 if (configFile == null) 488 configFile = DEFAULT_CONFIG_FILE; 489 490 java.net.URL configURL = this.convertToURL(configFile); 491 log.info("Loading config from " + configURL.toString()); 492 493 String configTransform = (String )this.getServletContext().getAttribute(KEY_CONFIG_TRANSFORM); 495 496 if (configTransform == null) 497 configTransform = this.getInitParameter(INITPARAM_CONFIG_TRANSFORM); 498 499 if (configTransform == null) 501 { 502 try 503 { 504 SAXBuilder builder = new SAXBuilder(); 505 return builder.build(configURL.openStream(), configURL.toString()); 506 } 507 catch (org.jdom.JDOMException jde) 508 { 509 throw new ConfigException(jde); 510 } 511 } 512 else { 514 java.net.URL transURL = this.convertToURL(configTransform); 515 log.info("Transforming config with " + transURL.toString()); 516 517 try 518 { 519 Transformer transformer = TransformerFactory.newInstance() 520 .newTransformer(new StreamSource (transURL.openStream(), transURL.toString())); 521 522 Source in = new StreamSource (configURL.openStream(), configURL.toString()); 523 JDOMResult out = new JDOMResult(); 524 525 transformer.transform(in, out); 526 return out.getDocument(); 527 } 528 catch (TransformerException ex) 529 { 530 throw new ConfigException(ex); 531 } 532 } 533 } 534 catch (IOException ex) 535 { 536 throw new ConfigException(ex); 537 } 538 } 539 540 546 public Document getConfigDocument() 547 { 548 return this.configDocument; 549 } 550 551 557 public String getLimitTransformsParam() 558 { 559 return this.limitTransformsParam; 560 } 561 562 568 protected URL convertToURL(String path) throws MalformedURLException 569 { 570 if (path.startsWith("file:") || path.startsWith("http:") 571 || path.startsWith("https:") || path.startsWith("ftp:") 572 || path.startsWith("jar:")) 573 return new URL(path); 574 else 575 { 576 if (!path.startsWith("/")) 578 path = "/" + path; 579 580 return this.getServletContext().getResource(path); 581 } 582 } 583 } 584 | Popular Tags |