1 52 53 package com.go.teaservlet; 54 55 import java.io.IOException ; 56 import java.io.PrintWriter ; 57 import java.io.StringWriter ; 58 import java.util.Collections ; 59 import java.util.Enumeration ; 60 import java.util.LinkedList ; 61 import java.util.List ; 62 import java.lang.reflect.Array ; 63 64 import javax.servlet.ServletConfig ; 65 import javax.servlet.ServletException ; 66 import javax.servlet.UnavailableException ; 67 import javax.servlet.http.Cookie ; 68 import javax.servlet.http.HttpServlet ; 69 import javax.servlet.http.HttpServletRequest ; 70 import javax.servlet.http.HttpServletResponse ; 71 72 import com.go.trove.io.CharToByteBuffer; 73 import com.go.trove.log.Log; 74 import com.go.trove.log.LogEvent; 75 import com.go.trove.log.LogListener; 76 import com.go.trove.util.Utils; 77 import com.go.trove.util.PropertyMap; 78 import com.go.tea.runtime.TemplateLoader; 79 80 117 public class TeaServlet extends HttpServlet { 118 private static final Object [] NO_PARAMS = new Object [0]; 119 private static final boolean DEBUG = false; 120 private static final String ENGINE_ATTR = 121 "com.go.teaservlet.TeaServletEngine"; 122 123 private ApplicationDepot mApplicationDepot; 124 private Log mLog; 125 126 127 private List mLogEvents; 128 129 private String mQuerySeparator; 130 private String mParameterSeparator; 131 private String mValueSeparator; 132 133 private boolean mUseSpiderableRequest; 134 135 140 public void init(ServletConfig config) throws ServletException { 141 super.init(config); 142 String ver = System.getProperty("java.version"); 143 if (ver.startsWith("0.") || ver.startsWith("1.0") || 144 ver.startsWith("1.1")) { 145 System.err.println 146 ("The TeaServlet requires Java 1.2 or higher to run properly"); 147 } 148 149 ApplicationDepot applicationDepot = 150 new ApplicationDepot(this, getServletConfig(), mLog); 151 152 PropertyMap properties = applicationDepot.getProperties(); 153 Log log = applicationDepot.getLog(); 154 155 mQuerySeparator = properties.getString("separator.query", "?"); 156 mParameterSeparator = properties.getString("separator.parameter", "&"); 157 mValueSeparator = properties.getString("separator.value", "="); 158 159 mUseSpiderableRequest = 160 (!"?".equals(mQuerySeparator)) || 161 (!"&".equals(mParameterSeparator)) || 162 (!"=".equals(mValueSeparator)); 163 164 if (mLog == null) { 165 mLog = log; 166 167 mLogEvents = Collections.synchronizedList(new LinkedList ()); 169 170 int max = 100; 172 String maxLogEventsParam = properties.getString("log.max"); 173 if (maxLogEventsParam != null) { 174 try { 175 max = Integer.parseInt(maxLogEventsParam); 176 } 177 catch (NumberFormatException e) { 178 } 179 } 180 181 final int logEventsMax = max; 182 183 mLog.addRootLogListener(new LogListener() { 184 public void logMessage(LogEvent e) { 185 checkSize(); 186 mLogEvents.add(e); 187 } 188 189 public void logException(LogEvent e) { 190 checkSize(); 191 mLogEvents.add(e); 192 } 193 194 private void checkSize() { 195 while (mLogEvents.size() >= logEventsMax) { 196 mLogEvents.remove(0); 197 } 198 } 199 }); 200 201 logVersionInfo(TeaServlet.class, "TeaServlet"); 202 mLog.info("Copyright (C) 1999-2001 WDIG http://opensource.go.com"); 203 logVersionInfo(TemplateLoader.class, "Tea"); 204 mLog.info("Copyright (C) 1997-2001 WDIG http://opensource.go.com"); 205 } 206 207 ApplicationDepot oldApp; 208 synchronized (this) { 209 oldApp = mApplicationDepot; 210 mApplicationDepot = applicationDepot; 211 mLog = log; 212 213 214 Object tse = config.getServletContext().getAttribute(ENGINE_ATTR); 215 TeaServletEngine[] tsea; 216 217 if (tse == null || !(tse instanceof TeaServletEngine[])) { 218 tsea = new TeaServletEngine[]{applicationDepot}; 219 } 220 else { 221 TeaServletEngine[] old_tsea = (TeaServletEngine[])tse; 222 int old_length = old_tsea.length; 223 tsea = new TeaServletEngine[old_length + 1]; 224 int i; 225 for (i=0; i<old_length; i++) { 226 tsea[i] = old_tsea[i]; 227 } 228 tsea[i] = applicationDepot; 229 } 230 231 config.getServletContext().setAttribute(ENGINE_ATTR, tsea); 232 } 233 234 if (oldApp != null) { 235 oldApp.destroy(); 236 } 237 } 238 239 242 public void destroy() { 243 if (mApplicationDepot != null) { 244 mLog.info("Destroying Application"); 245 mApplicationDepot.destroy(); 246 } 247 mLog.info("Destroying TeaServlet"); 248 super.destroy(); 249 } 250 251 254 public String getServletInfo() { 255 return "Tea template servlet"; 256 } 257 258 261 protected void doPost(HttpServletRequest request, 262 HttpServletResponse response) 263 throws ServletException , IOException  264 { 265 doGet(request, response); 266 } 267 268 274 protected void doGet(HttpServletRequest request, 275 HttpServletResponse response) 276 throws ServletException , IOException  277 { 278 if (mUseSpiderableRequest) { 279 request = new SpiderableRequest(request, 280 mQuerySeparator, 281 mParameterSeparator, 282 mValueSeparator); 283 } 284 285 response.setContentType("text/html"); 286 287 ApplicationResponse appResponse = 289 new ApplicationResponseImpl(response, mLog); 290 291 processTemplate(request, appResponse); 292 293 appResponse.finish(); 294 } 295 296 327 protected Object convertParameter(String value, Class toType) { 328 if (toType == Integer .class) { 329 try { 330 return new Integer (value); 331 } 332 catch (NumberFormatException e) { 333 return null; 334 } 335 } 336 else if (toType == Long .class) { 337 try { 338 return new Long (value); 339 } 340 catch (NumberFormatException e) { 341 return null; 342 } 343 } 344 else if (toType == Float .class) { 345 try { 346 return new Float (value); 347 } 348 catch (NumberFormatException e) { 349 return null; 350 } 351 } 352 else if (toType == Double .class) { 353 try { 354 return new Double (value); 355 } 356 catch (NumberFormatException e) { 357 return null; 358 } 359 } 360 else if (toType == Number .class || toType == Object .class) { 361 try { 362 return new Integer (value); 363 } 364 catch (NumberFormatException e) { 365 } 366 try { 367 return new Long (value); 368 } 369 catch (NumberFormatException e) { 370 } 371 try { 372 return new Double (value); 373 } 374 catch (NumberFormatException e) { 375 return (toType == Object .class) ? value : null; 376 } 377 } 378 else { 379 return null; 380 } 381 } 382 383 386 ApplicationDepot getApplicationDepot() { 387 return mApplicationDepot; 388 } 389 390 394 Log getLog() { 395 return mLog; 396 } 397 398 402 LogEvent[] getLogEvents() { 403 if (mLogEvents == null) { 404 return new LogEvent[0]; 405 } 406 else { 407 LogEvent[] events = new LogEvent[mLogEvents.size()]; 408 return (LogEvent[])mLogEvents.toArray(events); 409 } 410 } 411 412 418 private void processTemplate(HttpServletRequest request, 419 ApplicationResponse appResponse) 420 throws IOException  421 { 422 String path; 424 if ((path = request.getPathInfo()) == null) { 425 if ((path = request.getServletPath()) == null) { 426 path = "/"; 427 } 428 else { 429 int index = path.lastIndexOf('.'); 431 if (index >= 0) { 432 path = path.substring(0, index); 433 } 434 } 435 } 436 437 if (DEBUG) { 438 mLog.debug("aagggghhh... i've been hit! (" + path + ")"); 440 mLog.debug("Finding template for " + path); 441 } 442 443 try { 444 TemplateLoader.Template template = 446 mApplicationDepot.findTemplate(path, request, appResponse); 447 if (appResponse.isRedirectOrError()) { 448 return; 449 } 450 451 if (template == null) { 452 appResponse.sendError 453 (appResponse.SC_NOT_FOUND, request.getRequestURI()); 454 return; 455 } 456 457 Object [] params; 459 Class [] paramTypes = template.getParameterTypes(); 460 if (paramTypes.length == 0) { 461 params = NO_PARAMS; 462 } 463 else { 464 params = new Object [paramTypes.length]; 465 String [] paramNames = template.getParameterNames(); 466 for (int i=0; i<paramNames.length; i++) { 467 String paramName = paramNames[i]; 468 if (paramName == null) { 469 continue; 470 } 471 472 Class paramType = paramTypes[i]; 473 474 if (!paramType.isArray()) { 475 String value = request.getParameter(paramName); 476 if (value == null || paramType == String .class) { 477 params[i] = value; 478 } 479 else { 480 params[i] = convertParameter(value, paramType); 481 } 482 } 483 else { 484 String [] values = 485 request.getParameterValues(paramName); 486 if (values == null || paramType == String [].class) { 487 params[i] = values; 488 } 489 else { 490 paramType = paramType.getComponentType(); 491 Object converted = 492 Array.newInstance(paramType, values.length); 493 params[i] = converted; 494 for (int j=0; j<values.length; j++) { 495 Array.set 496 (converted, j, 497 convertParameter(values[j], paramType)); 498 } 499 } 500 } 501 } 502 } 503 504 ApplicationRequest appRequest = 505 new ApplicationRequestImpl(request, template); 506 507 HttpContext context = 508 mApplicationDepot.createContext(appRequest, appResponse); 509 510 if (DEBUG) { 511 mLog.debug("Executing template"); 512 } 513 try { 514 template.execute(context, params); 515 } 516 catch (AbortTemplateException e) { 517 if (DEBUG) { 518 mLog.debug("Template execution aborted!"); 519 } 520 } 521 catch (RuntimeException e) { 522 if (mApplicationDepot.getTemplateDepot(). 523 isExceptionGuardianEnabled()) { 524 mLog.error(e); 526 } 527 else { 528 throw new ServletException (e); 529 } 530 } 531 catch (IOException e) { 532 throw e; 533 } 534 catch (ServletException e) { 535 throw e; 536 } 537 catch (Exception e) { 538 throw new ServletException (e); 539 } 540 541 if (DEBUG) { 542 mLog.debug("Finished executing template"); 543 } 544 } 545 catch (ServletException e) { 546 StringBuffer msg = new StringBuffer (); 548 msg.append("Error processing request for "); 549 msg.append(request.getRequestURI()); 550 if (request.getQueryString() != null) { 551 msg.append('?'); 552 msg.append(request.getQueryString()); 553 } 554 mLog.error(msg.toString()); 555 556 Throwable t = e; 557 while (t instanceof ServletException ) { 558 e = (ServletException )t; 559 if (e.getRootCause() != null) { 560 String message = e.getMessage(); 561 if (message != null && message.length() > 0) { 562 mLog.error(message); 563 } 564 mLog.error(t = e.getRootCause()); 565 } 566 else { 567 mLog.error(e); 568 break; 569 } 570 } 571 572 if (!appResponse.isRedirectOrError()) { 574 String displayMessage = e.getLocalizedMessage(); 575 if (displayMessage == null || displayMessage.length() == 0) { 576 appResponse.sendError 577 (appResponse.SC_INTERNAL_SERVER_ERROR); 578 } 579 else { 580 appResponse.sendError 581 (appResponse.SC_INTERNAL_SERVER_ERROR, displayMessage); 582 } 583 } 584 } 585 } 586 587 private void logVersionInfo(Class clazz, String title) { 588 Package pack = clazz.getPackage(); 589 String version = null; 590 if (pack != null) { 591 if (pack.getImplementationTitle() != null) { 592 title = pack.getImplementationTitle(); 593 } 594 version = pack.getImplementationVersion(); 595 } 596 if (version == null) { 597 try { 598 String classname = clazz.getName(); 599 Class packinf = Class.forName( 600 classname.substring(0,classname.lastIndexOf('.')) 601 + ".PackageInfo"); 602 java.lang.reflect.Method mo = packinf.getMethod( 603 "getProductVersion",null); 604 version = mo.invoke(null,null).toString(); 605 } 606 catch (Exception pie) { 607 mLog.info("PackageInfo not found"); 608 mLog.debug(pie); 609 } 610 if (version == null) { 611 version = "<unknown>"; 612 } 613 } 614 mLog.info(title + " version " + version); 615 } 616 } 617
| Popular Tags
|