001/* 002 * $Source: /cvsroot2/open/projects/WebARTS/ca/bc/webarts/servlet/DbXmlXsl.java,v $ 003 * $Name: $ 004 * $Revision: 1.3 $ 005 * $Date: 2005-04-10 11:53:16 -0700 (Sun, 10 Apr 2005) $ 006 * $Locker: $ 007 */ 008/* 009 * Copyright (C) 2001 WebARTS Design, North Vancouver Canada 010 * http://www.webarts.bc.ca 011 * 012 * This program is free software; you can redistribute it and/or modify 013 * it under the terms of the GNU General Public License as published by 014 * the Free Software Foundation; either version 2 of the License, or 015 * (at your option) any later version. 016 * 017 * This program is distributed in the hope that it will be useful, 018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 020 * GNU General Public License for more details. 021 * 022 * You should have received a copy of the GNU General Public License 023 * along with this program; if not, write to the Free Software 024 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 025 */ 026 027package ca.bc.webarts.servlet; 028 029import db2xml.util.DB2XMLException; 030import db2xml.util.JDBCXMLProperties; 031import db2xml.util.XMLOutput; 032 033import db2xml.xml.JDBCXML; 034import db2xml.xml.XMLDocument; 035 036import java.io.File; 037import java.io.FileInputStream; 038import java.io.FileWriter; 039import java.io.InputStream; 040import java.io.IOException; 041import java.io.OutputStream; 042import java.io.PrintWriter; 043import java.io.Writer; 044 045import java.net.InetAddress; 046import java.net.MalformedURLException; 047import java.net.UnknownHostException; 048import java.net.URL; 049import java.net.URLConnection; 050 051import java.util.Calendar; 052import java.util.Enumeration; 053import java.util.Hashtable; 054import java.util.Vector; 055 056import javax.servlet.GenericServlet; 057import javax.servlet.ServletConfig; 058import javax.servlet.ServletException; 059import javax.servlet.ServletRequest; 060import javax.servlet.ServletResponse; 061 062import javax.servlet.http.HttpServlet; 063import javax.servlet.http.HttpServletRequest; 064import javax.servlet.http.HttpServletResponse; 065 066import javax.xml.parsers.DocumentBuilder; 067import javax.xml.parsers.DocumentBuilderFactory; 068import javax.xml.parsers.ParserConfigurationException; 069 070import javax.xml.transform.Result; 071import javax.xml.transform.Source; 072import javax.xml.transform.stream.StreamResult; 073import javax.xml.transform.stream.StreamSource; 074import javax.xml.transform.Transformer; 075import javax.xml.transform.TransformerConfigurationException; 076import javax.xml.transform.TransformerException; 077import javax.xml.transform.TransformerFactory; 078import javax.xml.transform.dom.DOMSource; 079 080import org.w3c.dom.Document; 081 082import org.xml.sax.SAXException; 083 084 085 086 087/** 088 * The class <code>DbXmlXsl</code> provides a server side engine for processing 089 * a variety of XML/XSL tasks based on a SQL db query, or a saved XML file. <P> 090 * 091 * The XSL processing syntax assumes the Xalan package from 092 * <a href="http://xml.apache.org">xml.apache.org</A>.<P> 093 * All funtional options are accessible via the parameters passed to it. 094 * <P>The db SQL to XML extraction is provided by the GNU 095 * <A href="http://www-1.informatik.fh-wiesbaden.de/~turau/DB2XM">DB2XML library 096 * </A> of Java classes. 097 * 098 * This servlet has the following capabilities: 099 * <OL> 100 * <LI> query a specified jdbc URL with a specified SQL statement and provide 101 * the result set in XML, 102 * <LI> transform the XMLResultSet using a specified XSL transform, 103 * <LI> save the XMLResultSet to a specified filename, 104 * <LI> transform XML (either from the above query, specified file, or parameter) 105 * with a XSL template 106 * <UL> 107 * <LI> XSL template specified by the caller 108 * <LI> to a html table representation of the data (default if a transformation 109 * is requested without a XSL file specified) 110 * </UL> 111 * 112 * <LI> return the generated XML document with MIME type 113 * <code>text/xml</code></LI></OL> 114 * . 115 116 * <BR><BR><B>DbXmlXsl usage</B>:<BR> 117 * <pre>http://servername/DbXmlXsl?parameterList</PRE>where parameter list is 118 * a list of acceptable servlet parameter name value pairs separated 119 * by the & character.<BR>This servlet will accept the following 120 * parameters: <UL> 121 * <LI>dbQuery - the SQL to hit the db with 122 * <LI>saveXmlFile - true or false to save or not save the resultant xml 123 * from the dbQuery 124 * <LI>fileBaseDir - base dir for the xml save 125 * <LI>xslTransform - true or false to do or not do a transform 126 * <LI>xslURL - a URL to the xsl 127 * <LI>xmlURL - a URL to the xsl 128 * <LI>numXmlFiles - does mor than 1 transform at a time by taking the 129 * urls you give and appending a number to the end of them to get the 130 * sequence of urls 131 * <LI>xmlSource - directory based source for your xml on this server 132 * <LI>jdbcDriverClass - overrides the default to visit a different db 133 * with your dbQuery string 134 * <LI>jdbcURL - overrides the default to visit a different db 135 * <LI>jdbcUsername - overrides the default to visit a different db 136 * <LI>jdbcPassword - overrides the default to visit a different db 137 * <LI>dumpDebug - DOES not do the db Query or transform... 138 * just dumps the info it would have used 139 * </UL><BR>You can get this servlet to do a transform on its own 140 * (without a db query) by specifying the xslURL, xmlURL, and xslTransform. 141 * <BR>As Follows: 142 * <PRE>/DbXmlXsl?xslURL=http://yoururl&xmlURL=http://yoururl&xslTransform=true</PRE> 143 * <BR>Have Fun!<BR> 144 * Tom Gutwin P.Eng. 145 * 146 * @author Tom Gutwin P.Eng 147 */ 148public class DbXmlXsl extends HttpServlet 149{ 150 151 /** 152 * The Default XSL template to use (in the form of a URL) 153 */ 154 String DEFAULT_XSL_STYLESHEET_URL = "http://warp2.webarts.bc.ca/xml/FancyXmlTreeViewer.xsl"; 155 /** A holder for this Servers System File Separator. **/ 156 private static final String SYSTEM_FILE_SEPERATOR = File.separator; 157 /** 158 * Description of the Field 159 */ 160 private JDBCXML jx_ = null; 161 /** 162 * Description of the Field 163 */ 164 private static JDBCXMLProperties map_ = null; 165 private static String db2XmlPropFile_ = "db2xml.properties"; 166 /** 167 * Description of the Field 168 */ 169 private String xmlFileOutputName_ = "DbXmlXsl"; 170 /** 171 * Description of the Field 172 */ 173 private String xmlFileOutputDir_ = SYSTEM_FILE_SEPERATOR+"xml"; 174 /** 175 * Description of the Field 176 */ 177 private String fileBaseDir_ = SYSTEM_FILE_SEPERATOR; 178 /** 179 * The URL of this servlet 180 */ 181 private String servletUrlStr_ = "/DbXmlXsl"; 182 183 private boolean dumpDebug_ = true; 184 185 /** 186 * This Servers Host Internet Address. 187 **/ 188 private String myHost_ = null; 189 /** 190 * This Servers Host port. 191 **/ 192 private String myPort_ = null; 193 194 public String usageHtml_ = "<BR><BR><B>DbXmlXsl usage</B>:<BR>\n"+ 195 "<pre>http://servername/DbXmlXsl?parameterList</PRE>where parameter list is"+ 196 " a list of acceptable servlet parameter name value pairs separated " + 197 "by the & character.<BR>\nThis servlet will accept the following "+ 198 "parameters:\n <UL>\n"+ 199 " <LI>dbQuery - the SQL to hit the db with\n"+ 200 " <LI>saveXmlFile - true or false to save or not save the resultant xml "+ 201 "from the dbQuery\n"+ 202 " <LI>fileBaseDir - base dir for the xml save\n"+ 203 " <LI>xslTransform - true or false to do or not do a transform\n"+ 204 " <LI>xslURL - a URL to the xsl\n"+ 205 " <LI>xmlURL - a URL to the xsl\n"+ 206 " <LI>numXmlFiles - does mor than 1 transform at a time by taking the "+ 207 "urls you give and appending a number to the end of them to get the "+ 208 "sequence of urls\n"+ 209 " <LI>xmlSource - directory based source for your xml on this server\n"+ 210 " <LI>jdbcDriverClass - overrides the default to visit a different db "+ 211 "with your dbQuery string\n"+ 212 " <LI>jdbcURL - overrides the default to visit a different db\n"+ 213 " <LI>jdbcUsername - overrides the default to visit a different db\n"+ 214 " <LI>jdbcPassword - overrides the default to visit a different db\n"+ 215 " <LI>dumpDebug - DOES not do the db Query or transform... "+ 216 "just dumps the info it would have used\n"+ 217 "</UL><BR>\nYou can get this servlet to do a transform on its own "+ 218 "(without a db query) by specifying the xslURL, xmlURL, and xslTransform."+ 219 "<BR>\nAs Follows:<PRE>/DbXmlXsl?xslURL=http://yoururl&xmlURL"+ 220 "=http://yoururl&xslTransform=true</PRE><BR>\nHave Fun!<BR>"+ 221 "Tom Gutwin P.Eng."; 222 223 224 /** 225 * Creates a timestamp for the current time in the form of 'hour + "-" + min + 226 * "-" + sec + "-" + millis'. 227 * 228 * @return The CurrentTimeStamp value. 229 */ 230 public static String createCurrentTimeStamp() 231 { 232 String value = ""; 233 Calendar calendar_ = Calendar.getInstance(); 234 int currMillis = calendar_.get(calendar_.MILLISECOND); 235 String millis = String.valueOf(currMillis); 236 if (currMillis < 10) 237 { 238 millis = "00" + currMillis; 239 } 240 else if (currMillis < 100) 241 { 242 millis = "0" + currMillis; 243 } 244 int currSec = calendar_.get(calendar_.SECOND); 245 String sec = String.valueOf(currSec); 246 if (currSec < 10) 247 { 248 sec = "0" + currSec; 249 } 250 int currMin = calendar_.get(calendar_.MINUTE); 251 String min = String.valueOf(currMin); 252 if (currMin < 10) 253 { 254 min = "0" + currMin; 255 } 256 int currHr = calendar_.get(calendar_.HOUR_OF_DAY); 257 String hour = String.valueOf(currHr); 258 if (currHr < 10) 259 { 260 hour = "0" + currHr; 261 } 262 263 return (String) hour + "-" + min + "-" + sec + "-" + millis; 264 } 265 266 267 /** 268 * Initializes the servlet and loads some db2xml init data. The init method is 269 * called once, automatically, by the network service each time it loads the 270 * servlet. It is guaranteed to finish before any service requests are accepted. 271 * <br> 272 * The JDBCXML properties are read from a file named <code>db2xml.properties</code> 273 * if an Servlet Init Parm - 'db2XmlPropFile' was not specified. This default 274 * file must be placed in a server config directory or other suitable directory. 275 * 276 * @param config servlet configuration information 277 * @exception ServletException if an error occured during initialization 278 */ 279 public void init(ServletConfig config) throws ServletException 280 { 281 super.init(config); // invoked on GenericServlet and saves a reference of 282 // the config for later use 283 String initProp = getInitParameter("db2XmlPropFile"); 284 String fileOutputDir = getInitParameter("fileOutputDir"); 285 String fileBaseDir = getInitParameter("fileBaseDir"); 286 myPort_ = getInitParameter("hostPort"); 287 try 288 { 289 myHost_ = InetAddress.getLocalHost().getHostAddress(); 290 System.out.println("DbXmlXsl Servlet init(): myHost: "+myHost_); 291 System.out.println("DbXmlXsl Servlet init(): myPort: "+myPort_); 292 if (db2XmlPropFile_ != null && !db2XmlPropFile_.equals("")) 293 { 294 System.out.println("DbXmlXsl Servlet init(): Reading db2xml "+ 295 "properties file from " + initProp); 296 db2XmlPropFile_ = initProp; 297 map_ = new JDBCXMLProperties(db2XmlPropFile_); 298 } 299 else 300 { 301 // read from the default location 302 map_ = new JDBCXMLProperties(); 303 } 304 305 if (fileBaseDir != null && !fileBaseDir.equals("")) 306 { 307 System.out.println("DbXmlXsl Servlet init(): File Base Dir: "+ 308 "" + fileBaseDir); 309 fileBaseDir_ = fileBaseDir; 310 if (!fileBaseDir_.endsWith(SYSTEM_FILE_SEPERATOR)) 311 fileBaseDir_ += SYSTEM_FILE_SEPERATOR; 312 } 313 314 if (fileOutputDir != null && !fileOutputDir.equals("")) 315 { 316 System.out.println("DbXmlXsl Servlet init(): File Output: "+ 317 "" + fileOutputDir); 318 xmlFileOutputDir_ = fileOutputDir; 319 } 320 321 servletUrlStr_ = getServletName(); 322 } 323 catch (DB2XMLException e) 324 { 325 throw new ServletException("2: " + e.getMessage()); 326 } 327 catch (UnknownHostException e2) 328 { 329 throw new ServletException("2: " + e2.getMessage()); 330 } 331 332 } 333 334 335 /** 336 * A method to generate an XML Document based on the result set from an SQL query 337 * on a db. All db parameters are passed in the method parameters. 338 * 339 * @param jdbcDriverClass the DriverClass name to override the defaults 340 * @param jdbcUrl the URL name to override the defaults 341 * @param jdbcUser the User name to override the defaults 342 * @param jdbcUserPassword the Password to override the defaults 343 * @param sqlStatement the SQL to execute 344 * 345 * @return The result query as an XML doc 346 */ 347 public static XMLDocument db2XmlDocument(String jdbcDriverClass, 348 String jdbcUrl, 349 String jdbcUser, 350 String jdbcUserPassword, 351 String sqlStatement) throws DB2XMLException 352 { 353 XMLDocument retVal = null; 354 JDBCXMLProperties map = null; 355 if (map_ != null) 356 map = map_; 357 else 358 map = new JDBCXMLProperties(); // uses the defaults 359 360 if (jdbcDriverClass != null && !jdbcDriverClass.equals("") && 361 jdbcUrl != null && !jdbcUrl.equals("") && 362 jdbcUser != null && 363 jdbcUserPassword != null && 364 sqlStatement != null) 365 { 366 map.setProperty("driverClass", jdbcDriverClass); 367 map.setProperty("dbUrl", jdbcUrl); 368 map.setProperty("user", jdbcUser); 369 map.setProperty("password", jdbcUserPassword); 370 map.setProperty("dbQuery", sqlStatement); 371 372 JDBCXML jx = new JDBCXML(map); 373 try 374 { 375 jx.generateXML(); 376 retVal = jx.getXMLDocument(); 377 } 378 catch (Exception ex) 379 { 380 } 381 if (jx != null) 382 { 383 jx.closeDatabase(); 384 } 385 } 386 return retVal; 387 } 388 389 390 /** 391 * A method to generate an XML Document based on the result set from an 392 * SQL query on a the default db and username. All db parameters are 393 * retrieved the from db2XmlPropFile_ field. 394 * 395 * @param sqlStatement the SQL to execute 396 * 397 * @return The result query as an XML doc 398 */ 399 public static XMLDocument db2XmlDocument(String sqlStatement) 400 throws DB2XMLException 401 { 402 JDBCXMLProperties map = null; 403 if (map_ != null) 404 map = map_; 405 else if (db2XmlPropFile_ != null && !db2XmlPropFile_.equals("")) 406 map = new JDBCXMLProperties(db2XmlPropFile_); 407 else 408 map = new JDBCXMLProperties(); 409 410 return db2XmlDocument(sqlStatement, map); 411 } 412 413 414 /** 415 * A method to generate an XML Document based on the result set from an 416 * SQL query on a the default db and username. All db parameters are 417 * retrieved the passed map parameter. 418 * 419 * @param sqlStatement the SQL to execute 420 * @param map The properties map to use for this query. 421 * 422 * @return The result query as an XML doc 423 */ 424 public static XMLDocument db2XmlDocument(String sqlStatement, 425 JDBCXMLProperties map) 426 throws DB2XMLException 427 { 428 XMLDocument retVal = null; 429 if (sqlStatement != null) 430 { 431 map.setProperty("dbQuery", sqlStatement); 432 433 JDBCXML jx = new JDBCXML(map); 434 try 435 { 436 jx.generateXML(); 437 retVal = jx.getXMLDocument(); 438 } 439 catch (Exception ex) 440 { 441 } 442 if (jx != null) 443 { 444 jx.closeDatabase(); 445 } 446 } 447 return retVal; 448 } 449 450 451 /** 452 * Writes the passed in XMLDocument to the specified XML file. 453 * 454 * @param xmlFilename the resultant XMLfilename 455 * @param xmlDoc The XML Documewnt to write out 456 * 457 * @see #db2XmlDocument(String) 458 */ 459 public static void writeXmlFile(String xmlFilename, XMLDocument xmlDoc) 460 throws IOException, DB2XMLException 461 { 462 JDBCXMLProperties map = null; 463 if (map_ != null) 464 map = map_; 465 else if (db2XmlPropFile_ != null && !db2XmlPropFile_.equals("")) 466 map = new JDBCXMLProperties(db2XmlPropFile_); 467 else 468 map = new JDBCXMLProperties(); 469 writeXmlFile(xmlFilename, xmlDoc, map); 470 } 471 472 473 /** 474 * Writes the passed in XMLDocument to the specified XML file. 475 * 476 * @param xmlFilename the resultant XMLfilename 477 * @param xmlDoc The XML Documewnt to write out 478 * @param map The properties map to use for th DB2XML usage. 479 */ 480 public static void writeXmlFile(String xmlFilename, 481 XMLDocument xmlDoc, 482 JDBCXMLProperties map) 483 throws IOException, DB2XMLException 484 { 485 XMLOutput xmlOut = null; 486 PrintWriter fileOut = new PrintWriter(new FileWriter(xmlFilename)); 487 xmlOut = new XMLOutput(map, fileOut, xmlDoc); 488 xmlOut.writeToOutput(); 489 } 490 491 492 /** 493 * Performs the XSL transform on the XML. 494 * 495 * @param xmlUrl The URL for the XML data 496 * @param xslUrl The URL for the XSL data 497 * @param outWriter The output writer to dump the output from the transform 498 * @param params other parameters to pass directly to the transform 499 */ 500 public static void doTransform(URL xmlUrl, 501 URL xslUrl, 502 PrintWriter outWriter, 503 Hashtable params) 504 throws IOException, 505 TransformerConfigurationException, 506 TransformerException, 507 IOException, 508 ParserConfigurationException, 509 SAXException 510 { 511 if (xmlUrl != null && xslUrl != null && outWriter != null) 512 { 513 InputStream xmlStream = xmlUrl.openStream(); 514 InputStream xslStream = xslUrl.openStream(); 515 if (xmlStream != null && xslStream != null) 516 { 517 doTransform(xmlStream, xslStream, outWriter, params); 518 } 519 } 520 } 521 522 523 /** 524 * Performs the XSL transform on the XML. 525 * 526 * @param xmlStream The Stream of XML data 527 * @param xslStream The Stream of XSL data 528 * @param outStream The Stream to dump the output from the transform 529 * @param params other parameters to pass directly to the transform 530 */ 531 public static void doTransform(InputStream xmlStream, 532 InputStream xslStream, 533 OutputStream outStream, 534 Hashtable params) 535 throws TransformerConfigurationException, 536 TransformerException, 537 IOException, 538 ParserConfigurationException, 539 SAXException 540 { 541 doTransform(xmlStream, xslStream, new PrintWriter(outStream), params); 542 } 543 544 545 /** 546 * Performs the XSL transform on the XML. 547 * 548 * @param xmlStream The Stream of XML data 549 * @param xslStream The Stream of XSL data 550 * @param outWriter The OutputPrinter to dump the output from the transform 551 * @param params other parameters to pass directly to the transform 552 */ 553 public static void doTransform(InputStream xmlStream, 554 InputStream xslStream, 555 PrintWriter outWriter, 556 Hashtable params) 557 throws TransformerConfigurationException, 558 TransformerException, 559 IOException, 560 ParserConfigurationException, 561 SAXException 562 { 563 //System.setProperty("javax.xml.transform.TransformerFactory","bla.bla"); 564 565 TransformerFactory tFactory = TransformerFactory.newInstance(); 566 if(false && tFactory.getFeature(DOMSource.FEATURE)) 567 { 568 System.out.println("Using A Dom Parser"); 569 //Instantiate a DocumentBuilderFactory. 570 DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); 571 572 // And setNamespaceAware, which is required when parsing xsl files 573 dFactory.setNamespaceAware(true); 574 575 //Use the DocumentBuilderFactory to create a DocumentBuilder. 576 DocumentBuilder dBuilder = dFactory.newDocumentBuilder(); 577 578 //Use the DocumentBuilder to parse the XSL stylesheet. 579 Document xslDoc = dBuilder.parse(xslStream); 580 581 // Use the DOM Document to define a DOMSource object. 582 DOMSource xslDomSource = new DOMSource(xslDoc); 583 584 // Set the systemId: note this is actually a URL, not a local filename 585 //xslDomSource.setSystemId(xmlFileOutputDir_); 586 587 // Process the stylesheet DOMSource and generate a Transformer. 588 Transformer transformer = tFactory.newTransformer(xslDomSource); 589 590 //Use the DocumentBuilder to parse the XML input. 591 Document xmlDoc = dBuilder.parse(xmlStream); 592 593 // Use the DOM Document to define a DOMSource object. 594 DOMSource xmlDomSource = new DOMSource(xmlDoc); 595 596 // Set the base URI for the DOMSource so any relative URIs it contains can 597 // be resolved. 598 //xmlDomSource.setSystemId(xmlFileOutputDir_); 599 600 String name = null; 601 for (Enumeration myEnum = params.keys(); myEnum.hasMoreElements();) 602 { 603 name = (String)myEnum.nextElement(); 604 transformer.setParameter(name, (String)params.get(name)); 605 } 606 607 transformer.transform(xmlDomSource, new StreamResult(outWriter)); 608 } 609 else 610 { // use the default SAX parser 611 // Get the XML input document and the stylesheet. 612 Source xslSource = new StreamSource(xslStream); 613 // Generate the transformer. 614 Transformer transformer = tFactory.newTransformer(xslSource); 615 616 String name = null; 617 for (Enumeration myEnum = params.keys(); myEnum.hasMoreElements();) 618 { 619 name = (String)myEnum.nextElement(); 620 transformer.setParameter(name, (String)params.get(name)); 621 } 622 623 // StreamSource wants either a reader or an inputStream 624 Source xmlSource = new StreamSource(xmlStream); 625 // Perform the transformation, sending the output to the response. 626 transformer.transform(xmlSource, new StreamResult(outWriter)); 627 } 628 } 629 630 631 /** 632 * Handles Post Requests by simply calling the doGet Method. 633 * 634 * @param req HttpServletRequest that encapsulates the 635 * request to the servlet 636 * @param res HttpServletResponse that encapsulates the 637 * response from the servlet 638 * @exception ServletException if the request could not be handled 639 * @exception IOException in case of an write error while handling 640 * request 641 */ 642 public void doPost(HttpServletRequest req, HttpServletResponse res) 643 throws ServletException, IOException 644 { 645 doGet(req, res); 646 } 647 648 649 /** 650 * Performs the HTTP GET operation. This is the universal entry point to this 651 * servlets functions. <P> 652 * 653 * It provides many options for how things are processed: 654 * <UL> 655 * <LI> db/sql --> XML file</LI> 656 * <LI> db/sql --> XML returned to http response outputstream</LI> 657 * <LI> db/sql --> XML --> XSL (specified by the caller) 658 * <UL>default transforms available 659 * <LI> XML --> html tree representation</LI> 660 * <LI> XML --> html table representation</LI> 661 * <LI> XML --> comma separated value listing</LI> 662 * </UL> 663 * </LI> 664 * <LI> XML file --> XSL</LI> 665 * <LI> XML data from a passed parameter --> XSL</LI> 666 * </UL> 667 * The XSL template can be specified: 668 * <UL> 669 * <LI> As a URL to a XSL file</LI> or as 670 * <LI> XSL data from a passed parameter</LI> 671 * </UL> 672 * The parameters used/passed that control the operation are: 673 * <UL> 674 * <LI> dbQuery (valid sql query) default = ""</LI> 675 * <LI> xslTransform (true/false) default = "true"</LI> 676 * <LI> xslURL (a valid URL to an xsl file) default = "file://./defaultHtmlTable.xsl" 677 * </LI> 678 * <LI> saveXmlFile (true/false) default = "false"</LI> 679 * <LI> xmlURL (a valid URL to an xml file) default = ""</LI> 680 * <LI> xmlSource (valid xml) default = ""</LI> 681 * <LI> 682 * <OL>The following jdbc parametyers can be spec'd to override the defaults 683 * set in the db2xml.properties file. 684 * <LI> jdbcDriverClass (a driver package.classname) default = ""</LI> 685 * <LI> jdbcURL (the url of the db to query) default = ""</LI> 686 * <LI> jdbcUsername (the username to connect with) default = ""</LI> 687 * <LI> jdbcPassword (the password to connect with) default = ""</LI> 688 * </OL> 689 * </LI> 690 * <LI> </LI> 691 * <LI> </LI> 692 * <LI> </LI> 693 * </UL> 694 * 695 * 696 * @param req HttpServletRequest that encapsulates the 697 * request to the servlet. 698 * @param res HttpServletResponse that encapsulates the 699 * response from the servlet. 700 * @exception ServletException if the request could not be handled. 701 * @exception IOException in case of an write error while handling 702 * request. 703 */ 704 public void doGet(HttpServletRequest req, HttpServletResponse res) 705 throws IOException, ServletException 706 { 707 Hashtable otherParams = new Hashtable(); 708 709 // define a simple Vector of all acceptable parms so we can use the 710 // '.contains' method to quickly check if a param is expected 711 Vector definedParamKeys = new Vector(); 712 definedParamKeys.add("dbQuery"); 713 definedParamKeys.add("xslTransform"); 714 definedParamKeys.add("saveXmlFile"); 715 definedParamKeys.add("xslURL"); 716 definedParamKeys.add("xmlURL"); 717 definedParamKeys.add("numXmlFiles"); 718 definedParamKeys.add("xmlSource"); 719 definedParamKeys.add("jdbcDriverClass"); 720 definedParamKeys.add("jdbcURL"); 721 definedParamKeys.add("jdbcUsername"); 722 definedParamKeys.add("jdbcPassword"); 723 definedParamKeys.add("dumpDebug"); 724 definedParamKeys.add("fileBaseDir"); 725 726 //These properties should be set in a servlet environment 727 //regardless of the values defined in the property file 728 map_.setProperty("out", "stream"); 729 map_.setProperty("el.binfields", "ignore"); 730 map_.setBooleanProperty("el.protectStrings", true); 731 map_.setProperty("genDTD", "no"); 732 733 // get the input parameters 734 String dbQuery = req.getParameter("dbQuery"); 735 String xslTransformStr = req.getParameter("xslTransform"); 736 String xslURL = req.getParameter("xslURL"); 737 String saveXmlFileStr = req.getParameter("saveXmlFile"); 738 String xmlURL = req.getParameter("xmlURL"); 739 String numXmlFilesStr = req.getParameter("numXmlFiles"); 740 String xmlSource = req.getParameter("xmlSource"); 741 String jdbcDriverClass = req.getParameter("jdbcDriverClass"); 742 String jdbcURL = req.getParameter("jdbcURL"); 743 String jdbcUsername = req.getParameter("jdbcUsername"); 744 String jdbcPassword = req.getParameter("jdbcPassword"); 745 String dumpDebugStr = req.getParameter("dumpDebug"); 746 String fileBaseDir = req.getParameter("fileBaseDir"); 747 748 // now get any other params that were passed, so we can forward them to the 749 // transformer 750 Enumeration myEnum = req.getParameterNames(); 751 String name = null; 752 while (myEnum.hasMoreElements()) 753 { 754 name = (String) myEnum.nextElement(); 755 if (!definedParamKeys.contains(name)) 756 otherParams.put(name, req.getParameter(name)); 757 } 758 759 String contentTypeStr = "text/html"; 760 boolean proceed = true; 761 boolean useXmlSource = false; 762 String errorMsg = "unknown"; 763 String xmlFileOutputName = xmlFileOutputName_; 764 765 // cast parameters to appropriate types and validate at the same time 766 boolean saveXmlFile = 767 (saveXmlFileStr != null ? saveXmlFileStr.equals("true") : false); 768 boolean doXslTransform = 769 (xslTransformStr != null ? xslTransformStr.equals("true") : true); 770 dumpDebug_ = 771 (dumpDebugStr != null ? dumpDebugStr.equals("true") : false); 772 int numXmlFiles = 1; 773 if (numXmlFilesStr != null && !numXmlFilesStr.equals("")) 774 { 775 numXmlFiles = Integer.parseInt(numXmlFilesStr); 776 } 777 778 //Parameter validation 779 boolean doDbQuery = (dbQuery != null ? !dbQuery.equals("") : false); 780 boolean streamXmlOut = 781 (doDbQuery && !saveXmlFile && !doXslTransform ? true : false); 782 783 // confirm BaseDir info 784 if (fileBaseDir != null && !fileBaseDir.equals("")) 785 { 786 fileBaseDir_ = fileBaseDir; 787 if (!fileBaseDir_.endsWith(SYSTEM_FILE_SEPERATOR)) 788 fileBaseDir_ += SYSTEM_FILE_SEPERATOR; 789 } 790 791 // confirm xsl info 792 if (xslURL == null || xslURL.equals("")) 793 { 794 xslURL = DEFAULT_XSL_STYLESHEET_URL; 795 } 796 797 // confirm xml data source 798 if (!doDbQuery) 799 { 800 dbQuery = ""; 801 if (saveXmlFile) 802 { 803 proceed = false; 804 errorMsg = "Request to Save the XML to file BUT " + 805 "no dbQuery parameter was specified."+usageHtml_; 806 } 807 else 808 { 809 // we better make sure there is valid XML coming from somewhere else 810 if ((xmlURL == null || xmlURL.equals(""))) 811 { 812 if (xmlSource == null || xmlSource.equals("")) 813 { 814 // no XML found 815 proceed = false; 816 errorMsg = "At least one source for the XML must be specified: " + 817 "dbQuery, xmlURL or xmlSource."+usageHtml_; 818 } 819 else 820 { 821 useXmlSource = true; 822 } 823 } 824 else //valid xmlURL 825 { 826 // do nothing here ... save the actual processing for later 827 } 828 } 829 } 830 else // we are doing a dbQuery 831 { 832 if (!streamXmlOut) 833 { 834 if(!doXslTransform) 835 { 836 // we have been asked to send the output to a file so validate the 837 // filename 838 if(xmlURL == null || xmlURL.equals("")) 839 { 840 // XML output filename not spec'd so bug out 841 proceed = false; 842 errorMsg = "Request to Save the XML to file BUT " + 843 "no xmlURL parameter was specified."+usageHtml_; 844 } 845 } 846 } 847 else 848 { 849 contentTypeStr = "text/xml"; 850 } 851 } 852 // by now we have 853 // the proceed flag init and 854 // a valid Xml data Source and 855 // an xsl data source URL set up and 856 // the returned contentType is set 857 858 // lets do the work for the request 859 PrintWriter out = res.getWriter(); 860 String absoluteFilename = ""; 861 862 if (proceed) 863 { 864 res.setStatus(HttpServletResponse.SC_OK); 865 XMLDocument xmlDoc = null; 866 try 867 { 868 if (doDbQuery) 869 { 870 // query the db and return the XML 871 xmlDoc = db2XmlDocument(dbQuery); 872 if (saveXmlFile) 873 { 874 absoluteFilename = xmlFileOutputDir_ + this.SYSTEM_FILE_SEPERATOR + 875 convertSystemDependantPath(parseIntoUrl(xmlURL)); 876 writeXmlFile(absoluteFilename, xmlDoc); 877 xmlURL = "file:///"+ absoluteFilename; 878 } 879 else 880 { 881 // we need to Pump the XMLOutput from the xmlDoc into an InputStream 882 // for now just dump into a temp file that we can read from. 883 String tmp = System.getProperty("java.io.tmpdir"); 884 if (tmp == null || tmp.equals("")) 885 tmp = "." + SYSTEM_FILE_SEPERATOR; 886 else 887 { 888 if (!(tmp.trim().endsWith(SYSTEM_FILE_SEPERATOR))) 889 { 890 tmp = tmp.trim() + SYSTEM_FILE_SEPERATOR; 891 } 892 } 893 absoluteFilename = tmp + xmlFileOutputName_ + "TempStream.xml"; 894 writeXmlFile(absoluteFilename, xmlDoc); 895 xmlURL = "file:///"+ absoluteFilename; 896 } 897 898 } 899 else // no db query specified 900 { 901 absoluteFilename = parseIntoUrl(xmlURL).toString(); 902 // we only have to do something if we are going to Stream 903 if (streamXmlOut) 904 { 905 // not implemented yet 906 xmlDoc = new XMLDocument(map_); 907 // the xmlDoc will now have to be filled with the data from 908 // either the xmlSource or xmlURL 909 } 910 } 911 912 /* Now the XML is is place.. so send something back to the requester */ 913 /* ***************************************************************** */ 914 if (dumpDebug_) 915 { 916 res.setContentType("text/html"); 917 out.write("<HTML>\n"); 918 out.write("<Head>\n"); 919 out.write("<title>" + getServletName() + 920 " - Debug Output</TITLE></head>\n"); 921 out.write("<body>\n<h2>" + getServletName() + 922 " - Debug Output</h2>\n"); 923 out.write("<H4>Request was:" + "</H4>" + req.getQueryString() + 924 "<H4>Request Parms are:</H4><OL>"); 925 String parm; 926 String val; 927 for (Enumeration parmEnum = req.getParameterNames(); 928 parmEnum.hasMoreElements(); ) 929 { 930 parm = (String) parmEnum.nextElement(); 931 val = req.getParameter(parm); 932 out.write("<LI>"+parm + " : " + val + "</LI>"); 933 } 934 out.write("</OL>\n<B>Other Settings</B><BR>\n"); 935 out.write((saveXmlFile?"Saved ":"UnSaved ")+"XML File=" + 936 absoluteFilename + "<BR>\n"); 937 out.write("doXslTransform = " +doXslTransform + "<BR>\n"); 938 out.write("users current dir = " +System.getProperty("user.dir") + 939 "<BR>\n"); 940 out.write("XML URL = " + parseIntoUrl(xmlURL) + "<BR>\n"); 941 out.write("XSL URL = " +parseIntoUrl(xslURL) + "<BR>\n"); 942 for (Enumeration parmEnum = otherParams.keys(); 943 parmEnum.hasMoreElements(); ) 944 { 945 parm = (String) parmEnum.nextElement(); 946 val = (String)otherParams.get(parm); 947 out.write(" - "+parm + " : " + val + "<BR>\n"); 948 } 949 out.write(" " + 950 "\n"); 951 out.write("</body>\n</html>"); 952 } 953 else // now send something back to the Client 954 { 955 res.setContentType("text/html"); 956 if (doXslTransform) 957 { 958 InputStream xmlStream = null; 959 InputStream xslStream = null; 960 if (numXmlFiles == 1) 961 { 962 URL in = parseIntoUrl(xmlURL); 963 URL trans = parseIntoUrl(xslURL); 964 965 if (!in.getProtocol().equals("file")) 966 { 967 968 URLConnection inConnection = in.openConnection(); 969 URLConnection transConnection = trans.openConnection(); 970 971 // test for access 972 try 973 { 974 xmlStream = inConnection.getInputStream(); 975 xslStream = transConnection.getInputStream(); 976 } 977 catch (IOException ex) 978 { 979 try 980 { 981 xmlStream = in.openStream(); 982 xslStream = trans.openStream(); 983 } 984 catch (Exception ex2) 985 { 986 errorMsg = ex2.getMessage() + 987 "<BR>Unable to complete the transformation because I "+ 988 "cannot read one of the required files:<BR>" + 989 "Please check the xmlURL and the xslURL.<BR>"+ 990 "xml=" + in.toExternalForm() + 991 "<BR>xsl=" + trans.toExternalForm()+usageHtml_ ; 992 proceed = false; 993 } 994 } 995 } 996 else 997 { //get a file Input stream 998 xmlStream = new FileInputStream(fileBaseDir_ + xmlURL); 999 xslStream = new FileInputStream(fileBaseDir_ + xslURL); 1000 } 1001 1002 if (xmlStream != null && xslStream != null && proceed) 1003 doTransform(xmlStream, xslStream, out, otherParams); 1004 else 1005 { 1006 if (proceed) 1007 { 1008 errorMsg = "Unable to complete the transformation because " + 1009 "I cannot read one of the required files:<BR>" + 1010 "Please check the xmlURL and the xslURL."+usageHtml_; 1011 proceed = false; 1012 } 1013 } 1014 } 1015 else 1016 { 1017 // build in the capability to process more than 1 xml/xsl in line 1018 // produce 1 output report based on a number of xml files 1019 for (int i=1; i <= numXmlFiles; i++) 1020 { 1021 //alter the URL names we are looking for 1022 xmlStream = parseIntoUrl(xmlURL+i+".xml").openStream(); 1023 xslStream = parseIntoUrl(xslURL+i+".xsl").openStream(); 1024 doTransform(xmlStream, xslStream, out, otherParams); 1025 } 1026 } 1027 } 1028 else if (streamXmlOut) 1029 { 1030 res.setContentType("text/xml"); 1031 1032 // send the XML straight back to the client 1033 // yet to implement 1034 } 1035 else 1036 { 1037 if (saveXmlFile) 1038 { 1039 res.setContentType("text/html"); 1040 out.write("<HTML>\n"); 1041 out.write("<Head>\n"); 1042 out.write("<title>" + getServletName() + 1043 " - Completed</TITLE></head>\n"); 1044 out.write("<body>\n<h2>" + getServletName() + 1045 " - Completed</h2>\n"); 1046 out.write("<H4>File Saved Successfully:</H4>"); 1047 out.write("XML File=" + absoluteFilename + "<BR>\n"); 1048 out.write("XML URL = " + parseIntoUrl(xmlURL) + "<BR>\n"); 1049 out.write("</body>\n</html>"); 1050 1051 } 1052 else // error ... an error response is provided below 1053 { 1054 errorMsg = "One of the following 3 output options was not " + 1055 "specified/completed:\n<OL><LI>XSL Transformation<LI>Stream " + 1056 "the XML Results back without transformation<LI>Save the XML " + 1057 "to a file.</OL>"+usageHtml_; 1058 proceed = false; 1059 } 1060 } 1061 } 1062 } 1063 catch (Exception e) 1064 { 1065 out.write("<H3>DbXmlXsl threw an exception on the server:</H3>" + 1066 "<H4>query was:</H4>" + dbQuery + 1067 "<H4>Request was:" + "</H4>" + req.getQueryString() + 1068 "<H4>Request Parms are:</H4>"); 1069 1070 String parm; 1071 String val; 1072 for (Enumeration parmEnum = req.getParameterNames(); 1073 parmEnum.hasMoreElements(); ) 1074 { 1075 parm = (String) parmEnum.nextElement(); 1076 val = req.getParameter(parm); 1077 out.write(parm + " : " + val + "<BR>"); 1078 } 1079 out.write("</OL>\n<B>Other Settings</B><BR>\n"); 1080 out.write((saveXmlFile?"Saved ":"UnSaved ")+"XML File=" + 1081 absoluteFilename + "<BR>\n"); 1082 out.write("doXslTransform = " +doXslTransform + "<BR>\n"); 1083 out.write("users current dir = " +System.getProperty("user.dir") + 1084 "<BR>\n"); 1085 out.write("XML URL = " + parseIntoUrl(xmlURL) + "<BR>\n"); 1086 out.write("XSL URL = " +parseIntoUrl(xslURL) + "<BR>\n"); 1087 for (Enumeration parmEnum = otherParams.keys(); 1088 parmEnum.hasMoreElements(); ) 1089 { 1090 parm = (String) parmEnum.nextElement(); 1091 val = (String)otherParams.get(parm); 1092 out.write(" - "+parm + " : " + val + "<BR>\n"); 1093 } 1094 out.write(" " + 1095 "\n"); 1096 out.write("<H4>error message:</H4>" + e.getMessage() + "<BR><PRE>"); 1097 e.printStackTrace(out); 1098 out.write("</PRE><HR>"+usageHtml_+"</body></html>"); 1099 } 1100 } 1101 1102 if (!proceed) 1103 { 1104 res.setStatus(HttpServletResponse.SC_BAD_REQUEST); 1105 res.setContentType("text/html"); 1106 out.write("<HTML>\n"); 1107 out.write("<Head>\n"); 1108 out.write("<title>" + getServletName() + 1109 " - Request Not Completed</TITLE></head>\n"); 1110 out.write("<body>\n<h2>" + getServletName() + 1111 " - Request Not Completed</h2>\n"); 1112 out.write("<H4>Request was:" + "</H4>" + req.getQueryString() + 1113 "<H4>Request Parms are:</H4>"); 1114 String parm; 1115 String val; 1116 for (Enumeration parmEnum = req.getParameterNames(); 1117 parmEnum.hasMoreElements(); ) 1118 { 1119 parm = (String) parmEnum.nextElement(); 1120 val = req.getParameter(parm); 1121 out.write(parm + " : " + val + "<BR>"); 1122 } 1123 out.write("<HR>\n"); 1124 out.write("<P>Possible error: " + errorMsg + "\n"); 1125 out.write("<P>Please review/correct the request parameters " + 1126 "and resubmit.\n"); 1127 out.write("</body>\n</html>"); 1128 } 1129 out.flush(); 1130 1131 } 1132 1133 1134 /** 1135 * Parses a String representation of a URL or absolute file path and converts 1136 * it into a URL.<P>This method is a bit forgiving... if the string is not 1137 * a correctlty formatted http, ftp, or file URL it will assume it is a file 1138 * URL and create the returned URL as such. 1139 * 1140 * @param value is the String to convert into a URL. 1141 * 1142 * @return the Valid URL for the Executable or null if this method failed to 1143 * convert the passed in string. 1144 * 1145 * @throws MalformedURLException if the passed in String is not a URL 1146 **/ 1147 private URL parseIntoUrl(String value) 1148 throws MalformedURLException 1149 { 1150 URL retVal = null; 1151 if (value != null) 1152 { 1153 if (value.toLowerCase().startsWith("http:/") || 1154 value.toLowerCase().startsWith("ftp:/") || 1155 value.toLowerCase().startsWith("file:/")) 1156 { 1157 // the following throws a MalformedURLException if value is bad 1158 retVal = new URL(value); 1159 } 1160 else // assume it is a http:// path 1161 { 1162 try 1163 { 1164 String tempPath = value; // Assume Un*x ... no replacement needed 1165 if (SYSTEM_FILE_SEPERATOR.equals("\\")) 1166 { 1167 /* Replace the file separators with the forward slash */ 1168 tempPath = ""; // start from scratch 1169 for ( int i = 0; i < value.length(); i++) 1170 { 1171 if (value.charAt(i) != SYSTEM_FILE_SEPERATOR.charAt(0) ) 1172 { 1173 tempPath += value.substring(i,i+1); 1174 } 1175 else 1176 { 1177 tempPath += "/"; 1178 } 1179 } 1180 } 1181 retVal = new URL("file://" + fileBaseDir_ + tempPath); 1182 } 1183 catch (NullPointerException badUrl) 1184 { 1185 throw new MalformedURLException("Can't parse the location URL from the " + 1186 "file path provided."); 1187 } 1188 } 1189 } 1190 return retVal; 1191 } 1192 1193 1194 /** 1195 * Converts the path component of a URL to the native relative file path. 1196 * 1197 * @param the url to use to convert. 1198 * 1199 * @return the converted path string. It will return a "" if the URL does not 1200 * include a filepath portion. 1201 **/ 1202 public String convertSystemDependantPath(URL url) 1203 { 1204 String retVal = ""; 1205 1206 // First check if we need to do the '/' conversion 1207 if (url != null && SYSTEM_FILE_SEPERATOR.equals("\\")) 1208 { 1209 // yup... we have to switch 'em 1210 // gotta use getFile instead of getPath which is a jdk 1.3 method 1211 String tempPath = url.getFile(); 1212 for ( int i = 0; i < tempPath.length();i++) 1213 { 1214 if (tempPath.charAt(i) != '/' ) 1215 { 1216 retVal += tempPath.substring(i,i+1); 1217 } 1218 else 1219 { 1220 if (i != 0) 1221 retVal += "\\"; 1222 } 1223 } 1224 } 1225 else if (url != null) 1226 // It is a Un*x path (no conversion needed) 1227 retVal = url.getFile().substring(1); 1228 1229 return retVal; 1230 } 1231}