1 package dinamica; 2 3 import java.io.IOException ; 4 import java.io.StringWriter ; 5 import javax.servlet.ServletContext ; 6 import javax.servlet.ServletException ; 7 import javax.servlet.http.HttpServlet ; 8 import javax.servlet.http.HttpServletRequest ; 9 import javax.servlet.http.HttpServletResponse ; 10 import javax.servlet.http.HttpSession ; 11 import javax.servlet.RequestDispatcher ; 12 import javax.sql.DataSource ; 13 import java.sql.*; 14 import java.io.PrintWriter ; 15 import electric.xml.*; 16 import java.util.HashMap ; 17 import java.util.regex.Pattern ; 18 19 41 public class Controller extends HttpServlet 42 { 43 44 47 private static final long serialVersionUID = 1L; 48 49 52 String _jndiPrefix = null; 53 54 57 ServletContext _ctx = null; 58 59 62 DataSource _ds = null; 63 64 67 String _logFile = null; 68 69 72 String _validationErrorAction = null; 73 74 77 String _requestEncoding = null; 78 79 82 String _fileEncoding = null; 83 84 88 protected void service(HttpServletRequest req, HttpServletResponse res) 89 throws ServletException , IOException 90 { 91 92 String method = req.getMethod().toUpperCase(); 94 if (!method.equals("GET") && !method.equals("POST")) 95 { 96 res.sendError(501, method + " not supported"); 97 return; 98 } 99 101 102 GenericTransaction t = null; GenericOutput o = null; Recordset inputValues = null; 106 107 int returnCode = 0; 108 109 110 long t1 = 0; 111 long t2 = 0; 112 113 114 boolean saveMvcLog = false; 115 boolean saveJdbcLog = false; 116 117 118 StringWriter logWriter = new StringWriter (); 119 PrintWriter logPrinter = new PrintWriter (logWriter); 120 121 Config config = null; 122 123 try 124 { 125 126 127 String path = getPath(req); 128 129 130 String configData = StringUtil.getResource(_ctx, path + "config.xml"); 131 132 133 config = new Config(configData, path); 134 135 141 if (config.requestEncoding!=null) { 142 req.setCharacterEncoding(config.requestEncoding); 143 } else { 144 if (_requestEncoding!=null) 145 req.setCharacterEncoding(_requestEncoding); 146 } 147 148 149 150 setRequestValues(req, config); 151 152 153 if (config.jdbcLog!=null && config.jdbcLog.equals("true")) 154 saveJdbcLog = true; 155 156 if (config.mvcLog.equals("true")) 157 { 158 saveMvcLog = true; 159 160 logPrinter.println("--REQUEST-START"); 161 logPrinter.println("Request: " + path); 162 logPrinter.println("Summary: " + config.summary); 163 logPrinter.println("Date: " + new java.util.Date (System.currentTimeMillis())); 164 logPrinter.println("Thread: " + Thread.currentThread().getName());; 165 166 } 167 168 169 if (config.transValidator!=null && config.transValidator.equals("true")) 170 { 171 172 Connection con = null; 173 try 174 { 175 176 if (config.transDataSource!=null) 177 con = Jndi.getDataSource(_jndiPrefix + config.transDataSource).getConnection(); 178 else 179 con = _ds.getConnection(); 180 181 182 inputValues = validateInput(req, config, con, saveJdbcLog, logPrinter); 183 184 } catch (Throwable verror) 185 { 186 throw verror; 187 } finally 188 { 189 if (con!=null) con.close(); 190 } 191 } 192 193 t1 = System.currentTimeMillis(); 194 195 196 if (config.transClassName!=null) 197 { 198 199 Connection con = null; 200 201 try 202 { 203 204 205 if (config.transDataSource!=null) 206 con = Jndi.getDataSource(_jndiPrefix + config.transDataSource).getConnection(); 207 else 208 con = _ds.getConnection(); 209 210 211 t = (GenericTransaction) getObject(config.transClassName); 212 t.init(_ctx, req, res); 213 t.setConfig(config); 214 t.setConnection(con); 215 216 217 if (saveJdbcLog) 218 t.setLogWriter(logPrinter); 219 220 221 if (config.transTransactions.equals("true")) 222 con.setAutoCommit(false); 223 else 224 con.setAutoCommit(true); 225 226 227 IServiceWrapper w = null; 228 if (t instanceof dinamica.IServiceWrapper) 229 { 230 w = (IServiceWrapper)t; 231 w.beforeService(inputValues); 232 } 233 234 235 returnCode = t.service(inputValues); 236 237 238 if (w!=null) 239 w.afterService(inputValues); 240 241 242 if (!con.getAutoCommit()) 243 con.commit(); 244 245 } 246 catch (Throwable e) 247 { 248 if (con!=null && !con.getAutoCommit()) 249 con.rollback(); 250 throw e; 251 } 252 finally 253 { 254 if (con!=null) con.close(); 255 } 256 257 } 258 259 t2 = System.currentTimeMillis(); 260 if (saveMvcLog) 261 logPrinter.println("Transaction performance (ms): " + (t2-t1)); 262 263 264 String forwardUri = config.getUriForExitCode(returnCode); 265 if (forwardUri!=null) 266 forward(forwardUri,req,res); 267 268 t1 = System.currentTimeMillis(); 269 270 271 if (config.outClassName!=null) 272 { 273 274 if (config.headers.equals("true")) 275 { 276 277 String contentType = config.contentType; 278 if (contentType!=null) { 279 if (config.contentType.startsWith("text")) 280 { 281 if (contentType.indexOf("charset")<0 && _fileEncoding!=null) 282 contentType = contentType + "; charset=" + _fileEncoding; 283 } 284 res.setContentType(contentType); 285 } 286 if (config.expiration!=null) 287 { 288 res.setHeader("Cache-Control","max-age=" + config.expiration); 289 if (Integer.parseInt(config.expiration)==0) 290 res.setHeader("Cache-Control","no-cache"); 291 } 292 } 293 294 295 o = (GenericOutput) getObject(config.outClassName); 296 o.init(_ctx, req, res); 297 o.setConfig(config); 298 299 300 if ( config.contentType!=null && config.contentType.startsWith("text") ) 301 { 302 303 String template = o.getResource(config.outTemplate); 304 TemplateEngine te = new TemplateEngine(_ctx, req, template); 305 306 307 HttpSession s = req.getSession(true); 308 java.util.Locale l = (java.util.Locale )s.getAttribute("dinamica.user.locale"); 309 te.setLocale(l); 310 311 312 if (config.templateEncoding!=null) 313 te.setEncoding(config.templateEncoding); 314 else 315 te.setEncoding(_fileEncoding); 316 317 318 o.print(te, t); 319 320 321 te.print(res); 322 323 } 324 else 325 { 326 327 o.print(t); 328 } 329 330 } 331 332 t2 = System.currentTimeMillis(); 333 if (saveMvcLog) 334 { 335 logPrinter.println("Output performance (ms): " + (t2-t1)); 336 } 337 338 } 339 340 341 catch (RequestValidationException vex) { 342 RequestDispatcher rd = _ctx.getRequestDispatcher(_validationErrorAction); 343 req.setAttribute("dinamica.errors", vex.getErrors()); 344 rd.forward(req,res); 345 } 346 347 348 catch (Throwable e) { 349 350 StringWriter s = new StringWriter (); 352 PrintWriter err = new PrintWriter (s); 353 e.printStackTrace(err); 354 355 357 req.setAttribute("dinamica.error.description", e.getMessage()); 358 req.setAttribute("dinamica.error.url", req.getRequestURL().toString()); 359 req.setAttribute("dinamica.error.stacktrace", s.toString()); 360 req.setAttribute("dinamica.error.user", req.getRemoteUser()); 361 req.setAttribute("dinamica.error.remote_addr", req.getRemoteAddr()); 362 throw new ServletException (e); 363 } 364 365 finally { 366 367 if (saveJdbcLog || saveMvcLog) 368 saveLog(logWriter.toString()); 369 } 370 371 } 372 373 378 String getPath(HttpServletRequest req) throws Throwable 379 { 380 381 String uri = null; 382 383 384 uri = (String )req.getAttribute("javax.servlet.include.request_uri"); 385 386 if (uri==null) 387 uri = req.getRequestURI(); 388 389 390 String find = getInitParameter("base-dir"); 391 392 393 int pos = uri.indexOf(find); 394 if (pos >= 0) 395 { 396 397 String path = uri.substring(pos); 399 req.setAttribute("dinamica.action.path", path); 400 402 return "/WEB-INF" + path + "/"; 403 } 404 else 405 { 406 throw new Throwable ("Invalid base-dir parameter for this request (" + uri + ") - can't extract Transaction path from URI using this prefix: " + find); 407 } 408 409 } 410 411 412 418 public void init() throws ServletException 419 { 420 421 try 422 { 423 424 425 _ctx = getServletContext(); 426 427 428 _jndiPrefix = _ctx.getInitParameter("jndi-prefix"); 429 if (_jndiPrefix==null) 430 _jndiPrefix = ""; 431 432 433 String dsName = _jndiPrefix + _ctx.getInitParameter("def-datasource"); 434 if (dsName == null || dsName.trim().equals("")) 435 throw new ServletException ("Configuration problem detected in WEB.XML: def-datasource context parameter cannot be undefined!"); 436 437 _ds = Jndi.getDataSource(dsName); 438 439 440 _logFile = _ctx.getInitParameter("log-file"); 441 if (_logFile == null || _logFile.trim().equals("")) 442 throw new ServletException ("Configuration problem detected in WEB.XML: log-file context parameter cannot be undefined!"); 443 444 445 _validationErrorAction = _ctx.getInitParameter("on-validation-error"); 446 if (_validationErrorAction == null || _validationErrorAction.trim().equals("")) 447 throw new ServletException ("Configuration problem detected in WEB.XML: on-validation-error context parameter cannot be undefined!"); 448 449 450 _requestEncoding = _ctx.getInitParameter("request-encoding"); 451 if (_requestEncoding != null && _requestEncoding.trim().equals("")) 452 _requestEncoding = null; 453 454 455 _fileEncoding = _ctx.getInitParameter("file-encoding"); 456 if (_fileEncoding != null && _fileEncoding.trim().equals("")) 457 _fileEncoding = null; 458 459 super.init(); 460 461 } 462 catch (Throwable e) 463 { 464 log("Controller servlet failed on init!"); 465 throw new ServletException (e); 466 } 467 468 } 469 470 475 void saveLog(String message) 476 { 477 StringUtil.saveMessage(_logFile, message); 478 } 479 480 488 Recordset validateInput(HttpServletRequest req, Config config, Connection conn, boolean jdbcLog, PrintWriter jdbcLogPrinter) throws Throwable 489 { 490 491 492 RequestValidationException errors = new RequestValidationException(); 493 494 495 String dateFormat = _ctx.getInitParameter("def-input-date"); 496 497 498 Recordset inputs = new Recordset(); 499 500 501 String file = config.path + "validator.xml"; 502 Document xml = new Document( StringUtil.getResource(_ctx, file)); 503 Element root = xml.getRoot(); 504 505 506 Elements elements = root.getElements( "parameter" ); 507 Element param; 508 509 while ( elements.hasMoreElements() ) 510 { 511 512 513 String type = null; 514 String id = null; 515 String label = null; 516 int sqlType = 0; 517 String required = null; 518 519 param = elements.next(); 520 521 522 id = param.getAttributeValue( "id" ); 523 if (id==null) 524 throw new Exception ("Invalid Validator. Attribute [id] not found: " + file); 525 526 type = param.getAttributeValue( "type" ); 527 if (type==null) 528 throw new Exception ("Invalid Validator. Attribute [type] not found: " + file); 529 530 required = param.getAttributeValue( "required" ); 531 if (required==null) 532 throw new Exception ("Invalid Validator. Attribute [required] not found: " + file); 533 534 label = param.getAttributeValue( "label" ); 535 if (label==null) 536 throw new Exception ("Invalid Validator. Attribute [label] not found: " + file); 537 538 539 540 if (type.equals("varchar")) 541 sqlType = Types.VARCHAR; 542 else if (type.equals("integer")) 543 sqlType = Types.INTEGER; 544 else if (type.equals("double")) 545 sqlType = Types.DOUBLE; 546 else if (type.equals("date")) 547 sqlType = Types.DATE; 548 else 549 throw new Exception ("Invalid validator data type (" + type + ") in file: " + file); 550 551 552 inputs.append(id, sqlType); 553 554 } 555 556 557 inputs.addNew(); 558 559 560 elements = root.getElements( "parameter" ); 561 562 while ( elements.hasMoreElements() ) 563 { 564 565 566 String type = null; 567 String value = null; 568 String id = null; 569 String label = null; 570 int sqlType = 0; 571 String required = ""; 572 int maxLen = 0; 573 String maxLenAttr = ""; 574 int minValue = 0; 575 int maxValue = 0; 576 String minValueAttr = ""; 577 String maxValueAttr = ""; 578 String regexp = null; 579 String regexpError = null; 580 581 param = elements.next(); 582 583 584 id = param.getAttributeValue( "id" ); 585 type = param.getAttributeValue( "type" ); 586 required = param.getAttributeValue( "required" ); 587 label = param.getAttributeValue( "label" ); 588 maxLenAttr = param.getAttributeValue( "maxlen" ); 589 minValueAttr = param.getAttributeValue( "min" ); 590 maxValueAttr = param.getAttributeValue( "max" ); 591 regexp = param.getAttributeValue( "regexp" ); 592 regexpError = param.getAttributeValue( "regexp-error-label" ); 593 594 if (maxLenAttr!=null) 595 maxLen = Integer.parseInt(maxLenAttr); 596 if (minValueAttr!=null) 597 minValue = Integer.parseInt(minValueAttr); 598 if (maxValueAttr!=null) 599 maxValue = Integer.parseInt(maxValueAttr); 600 601 602 if (type.equals("varchar")) 603 sqlType = Types.VARCHAR; 604 else if (type.equals("integer")) 605 sqlType = Types.INTEGER; 606 else if (type.equals("double")) 607 sqlType = Types.DOUBLE; 608 else if (type.equals("date")) 609 sqlType = Types.DATE; 610 611 612 String data[] = req.getParameterValues(id); 613 if (data!=null && !data[0].trim().equals("")) 614 { 615 616 if (data.length==1) 617 { 618 619 value = data[0].trim(); 620 621 622 if (maxLen>0) 623 { 624 if (value.length()>maxLen) 625 errors.addMessage( label + ": " + "${lbl:data_too_long}" + maxLen); 626 } 627 628 629 if (sqlType==Types.VARCHAR && regexp!=null) 630 { 631 boolean isMatch = Pattern.matches(regexp, value); 632 if (!isMatch) 633 errors.addMessage( label + ": " + regexpError); 634 } 635 636 637 638 switch (sqlType) 639 { 640 case Types.DATE: 641 java.util.Date d = ValidatorUtil.testDate(value, dateFormat); 642 if (d==null) 643 errors.addMessage( label + ": " + "${lbl:invalid_date}"); 644 else 645 inputs.setValue(id, d); 646 647 break; 648 649 case Types.DOUBLE: 650 Double dbl = ValidatorUtil.testDouble(value); 651 if (dbl==null) 652 errors.addMessage( label + ": " + "${lbl:invalid_double}"); 653 else 654 inputs.setValue(id, dbl); 655 656 if (minValueAttr!=null && dbl!=null && dbl.doubleValue() < Double.parseDouble(minValueAttr)) 657 errors.addMessage( label + ": " + "${lbl:min_value_violation}" + minValue); 658 if (maxValueAttr!=null && dbl!=null && dbl.doubleValue() > Double.parseDouble(maxValueAttr)) 659 errors.addMessage( label + ": " + "${lbl:max_value_violation}" + maxValue); 660 661 break; 662 663 case Types.INTEGER: 664 Integer i = ValidatorUtil.testInteger(value); 665 if (i==null) 666 errors.addMessage( label + ": " + "${lbl:invalid_integer}"); 667 else 668 inputs.setValue(id, i); 669 670 if (minValueAttr!=null && i!=null && i.intValue() < minValue) 671 errors.addMessage( label + ": " + "${lbl:min_value_violation}" + minValue); 672 if (maxValueAttr!=null && i!=null && i.intValue() > maxValue) 673 errors.addMessage( label + ": " + "${lbl:max_value_violation}" + maxValue); 674 675 break; 676 677 case Types.VARCHAR: 678 inputs.setValue(id, value); 679 break; 680 681 } 682 683 } 684 else 685 { 686 throw new Throwable ("Invalid parameter. Generic validator can't process array parameters. Parameter (" + id + ") in file: " + file); 687 } 688 689 } 690 else if (required.equals("true")) 691 { 692 errors.addMessage( label + ": " + "${lbl:parameter_required}"); 693 } 694 695 } 696 697 702 if (errors.getErrors().getRecordCount()==0) 703 { 704 Elements valds = root.getElements("custom-validator"); 705 while ( valds.hasMoreElements() ) 706 { 707 708 709 HashMap a = new HashMap (5); 710 Element validator = valds.next(); 711 String className = validator.getAttributeValue( "classname" ); 712 String onErrorLabel = validator.getAttributeValue( "on-error-label" ); 713 714 715 Attributes attribs = validator.getAttributeObjects(); 716 while (attribs.hasMoreElements()) 717 { 718 Attribute ax = attribs.next(); 719 a.put(ax.getName(), ax.getValue()); 720 } 721 722 723 AbstractValidator t = null; 724 t = (AbstractValidator) getObject(className); 725 t.init(_ctx, req, null); 726 t.setConfig(config); 727 t.setConnection(conn); 728 729 730 if (jdbcLog) 731 t.setLogWriter(jdbcLogPrinter); 732 733 734 boolean b = t.isValid(req, inputs, a); 735 736 737 if (!b) 738 { 739 String err = t.getErrorMessage(); 740 if (err==null) 741 err = onErrorLabel; 742 errors.addMessage(err); 743 } 744 745 } 746 } 747 748 if (errors.getErrors().getRecordCount()>0) 749 { 750 req.setAttribute("_request", inputs); 751 throw errors; 752 } 753 else 754 return inputs; 755 756 } 757 758 763 void forward(String uri, HttpServletRequest req, HttpServletResponse res) throws Throwable 764 { 765 RequestDispatcher rd = _ctx.getRequestDispatcher(uri); 766 rd.forward(req, res); 767 } 768 769 775 void setRequestValues(HttpServletRequest req, Config config) throws Throwable 776 { 777 778 Document doc = config.getDocument(); 779 780 Elements e = doc.getRoot().getElements("set-request-attribute"); 781 if (e!=null) 782 { 783 while (e.hasMoreElements()) 784 { 785 Element r = e.next(); 786 String id = r.getAttribute("id"); 787 String value = r.getAttribute("value"); 788 req.setAttribute(id, value); 789 } 790 } 791 792 } 793 794 802 Object getObject(String className) throws Throwable 803 { 804 805 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 806 807 try 808 { 809 return loader.loadClass(className).newInstance(); 810 } 811 catch (Throwable e) 812 { 813 String date = StringUtil.formatDate(new java.util.Date (), "dd-MM-yyyy HH:mm:ss"); 814 System.err.println("[WARNING@" + date + "]: " + e.getMessage()); 815 System.err.println("[WARNING@" + date + "]: Context class loader failed to load class [" + className + "]. Using Class.forName()"); 816 return Class.forName(className).newInstance(); 817 } 818 819 } 820 821 } 822 | Popular Tags |