Project

General

Profile

1 87 jones
/**
2 203 jones
 *  '$RCSfile$'
3
 *    Purpose: A Class that transforms an XML text document
4
 *             into a another type using XSL
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Matt Jones
8 87 jones
 *
9 1929 brooke
 * '$Author$'
10
 * '$Date$'
11 203 jones
 * '$Revision$'
12 669 jones
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 87 jones
 */
27
28
package edu.ucsb.nceas.metacat;
29
30
import java.io.*;
31
import java.net.URL;
32
import java.net.MalformedURLException;
33
import java.sql.*;
34 1688 tao
import java.util.Enumeration;
35 1664 tao
import java.util.Hashtable;
36 3675 barteau
import java.util.Iterator;
37
import java.util.Map;
38
import java.util.Map.Entry;
39 87 jones
import java.util.Stack;
40
41 906 berkley
import javax.xml.transform.TransformerFactory;
42
import javax.xml.transform.Transformer;
43
import javax.xml.transform.stream.StreamSource;
44
import javax.xml.transform.stream.StreamResult;
45
import javax.xml.transform.TransformerException;
46
import javax.xml.transform.TransformerConfigurationException;
47
48 2663 sgarg
import org.apache.log4j.Logger;
49 906 berkley
import org.apache.xerces.parsers.DOMParser;
50
import org.w3c.dom.Attr;
51
import org.w3c.dom.NamedNodeMap;
52
import org.w3c.dom.NodeList;
53
import org.w3c.dom.Document;
54
import org.w3c.dom.Node;
55
import org.w3c.dom.NodeList;
56
import org.w3c.dom.DocumentType;
57
import org.xml.sax.SAXException;
58
import org.xml.sax.InputSource;
59
import org.apache.xerces.dom.DocumentTypeImpl;
60
import org.apache.xpath.XPathAPI;
61
import org.w3c.dom.NamedNodeMap;
62
63
/*
64 87 jones
import oracle.xml.parser.v2.XSLStylesheet;
65
import oracle.xml.parser.v2.XSLException;
66 832 jones
import oracle.xml.parser.v2.XMLParseException;
67 87 jones
import oracle.xml.parser.v2.XSLProcessor;
68
import oracle.xml.parser.v2.XMLDocument;
69
import oracle.xml.parser.v2.DOMParser;
70 906 berkley
*/
71 832 jones
import org.w3c.dom.Document;
72
import org.w3c.dom.Node;
73
import org.w3c.dom.Element;
74
import org.xml.sax.SAXException;
75 87 jones
76 2896 sgarg
import java.util.Properties;
77 2893 sgarg
78 2912 harris
79 1716 berkley
/**
80 87 jones
 * A Class that transforms XML documents utitlizing XSL style sheets
81
 */
82
public class DBTransform {
83
84 1217 tao
  //private Connection	conn = null;
85 832 jones
  private MetaCatUtil   util = null;
86
  private String 	configDir = null;
87
  private String	defaultStyle = null;
88 2663 sgarg
  private Logger logMetacat = Logger.getLogger(DBTransform.class);
89 3780 daigle
  private String httpServer = null;
90 3725 tao
  private String contextURL = null;
91 3780 daigle
  private String servletURL = null;
92 2663 sgarg
93 87 jones
  /**
94
   * construct a DBTransform instance.
95
   *
96
   * Generally, one calls transformXMLDocument() after constructing the instance
97
   *
98
   * @param conn the database connection from which to lookup the public ids
99
   */
100 1716 berkley
  public DBTransform()
101
                  throws IOException,
102
                         SQLException,
103 87 jones
                         ClassNotFoundException
104
  {
105 1217 tao
    //this.conn = conn;
106 832 jones
    util = new MetaCatUtil();
107
    configDir = util.getOption("config-dir");
108
    defaultStyle = util.getOption("default-style");
109 3780 daigle
    httpServer = util.getOption("httpserver");
110
    contextURL = util.getOption("httpserver")+"/"+util.getOption("context");
111
    servletURL = util.getOption("httpserver")+util.getOption("servletpath");
112 87 jones
  }
113 1716 berkley
114 87 jones
  /**
115 1716 berkley
   * @see transformXMLDocument(String doc, String sourceType,
116
   *            String targetType, String qformat, PrintWriter pw,
117
   *            String sessionid)
118
   */
119
  public void transformXMLDocument(String doc, String sourceType,
120 1717 berkley
                String targetType, String qformat, PrintWriter pw,
121
                Hashtable param)
122 1716 berkley
  {
123 1717 berkley
    transformXMLDocument(doc, sourceType, targetType, qformat, pw, param, null);
124 1716 berkley
  }
125
126 2088 tao
   /**
127
   * @see transformXMLDocument(String doc, String sourceType,
128
   *            String targetType, String qFormat, StringWriter pw
129
   *            String sessionid)
130
   */
131
  public void transformXMLDocument(String doc, String sourceType,
132
                String targetType, String qFormat, StringWriter pw)
133
  {
134
    transformXMLDocument(doc, sourceType, targetType, qFormat, pw, null);
135
  }
136
137
138 1716 berkley
  /**
139 87 jones
   * Transform an XML document using the stylesheet reference from the db
140
   *
141
   * @param doc the document to be transformed
142
   * @param sourcetype the document type of the source
143
   * @param targettype the target document type
144 832 jones
   * @param qformat the name of the style set to use
145
   * @param pw the PrintWriter to which output is printed
146 1664 tao
   * @param params some parameters for eml2 transformation
147 87 jones
   */
148 1716 berkley
  public void transformXMLDocument(String doc, String sourceType,
149
                                   String targetType, String qformat,
150
                                   PrintWriter pw, Hashtable param,
151
                                   String sessionid)
152 1664 tao
 {
153 1716 berkley
154 87 jones
    // Look up the stylesheet for this type combination
155 941 tao
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
156 2088 tao
    if (xslSystemId != null)
157
    {
158
      try
159
      {// Create a stylesheet from the system id that was found
160
        doc = removeDOCTYPE(doc);
161
        StringReader xml = new StringReader(doc);
162
        StreamResult result = new StreamResult(pw);
163
        doTransform(xml, result, xslSystemId, param, qformat, sessionid);
164 87 jones
165 2088 tao
      }
166
      catch (Exception e)
167
      {
168 3780 daigle
        pw.println(xslSystemId + ": Error transforming document in " +
169 675 berkley
                   "DBTransform.transformXMLDocument: " +
170 87 jones
                   e.getMessage());
171 1716 berkley
172 87 jones
      }
173 2088 tao
    }
174
    else
175
    {
176 1716 berkley
      // No stylesheet registered form this document type, so just return the
177 87 jones
      // XML stream we were passed
178 100 jones
      pw.print(doc);
179 87 jones
    }
180
  }
181 1716 berkley
182 941 tao
  /**
183 1716 berkley
   * Transform an XML document to StringWriter using the stylesheet reference
184 941 tao
   * from the db
185
   * @param doc the document to be transformed
186
   * @param sourceType the document type of the source
187
   * @param targetType the target document type
188
   * @param qFormat the name of the style set to use
189
   * @param pw the StringWriter to which output will be stored
190
   */
191
  public void transformXMLDocument(String doc, String sourceType,
192 1716 berkley
                String targetType, String qFormat, StringWriter pw,
193 2088 tao
                String sessionid)
194
  {
195 941 tao
196
    // Look up the stylesheet for this type combination
197
    String xslSystemId = getStyleSystemId(qFormat, sourceType, targetType);
198 2088 tao
    if (xslSystemId != null)
199
    {
200 941 tao
      // Create a stylesheet from the system id that was found
201 2088 tao
      try
202
      {
203 1903 tao
        doc = removeDOCTYPE(doc);
204 2088 tao
        StringReader xml = new StringReader(doc);
205
        StreamResult result = new StreamResult(pw);
206
        doTransform(xml, result, xslSystemId, null, qFormat, sessionid);
207
      }
208
      catch (Exception e)
209
      {
210 3780 daigle
        logMetacat.error(xslSystemId + ": Error transforming document in " +
211 941 tao
                   "DBTransform.transformXMLDocument: " +
212 2663 sgarg
                   e.getMessage());
213 1716 berkley
214 941 tao
      }
215 2088 tao
    }
216
    else
217
    {
218 1716 berkley
      // No stylesheet registered form this document type, so just return the
219 941 tao
      // XML stream we were passed
220 950 tao
      pw.write(doc);
221 941 tao
    }
222
  }
223 1716 berkley
224 906 berkley
  /**
225 2088 tao
   * Method to do transform for a string reader
226
   * @param doc the document to be transformed
227
   * @param sourcetype the document type of the source
228
   * @param targettype the target document type
229
   * @param qformat the name of the style set to use
230
   * @param pw the PrintWriter to which output is printed
231
   * @param params some parameters for eml2 transformation
232 1716 berkley
   */
233 2088 tao
   public void transformXMLDocument(StringReader docContent, String sourceType,
234
                                   String targetType, String qformat,
235
                                   PrintWriter pw, Hashtable param,
236
                                   String sessionid)
237
   {
238
     // Look up the stylesheet for this type combination
239
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
240
    if (xslSystemId != null)
241
    {
242
      try
243
      {// Create a stylesheet from the system id that was found
244
        StreamResult result = new StreamResult(pw);
245
        doTransform(docContent, result, xslSystemId, param, qformat, sessionid);
246
247
      }
248
      catch (Exception e)
249
      {
250 3780 daigle
        pw.println(xslSystemId + ": Error transforming document in " +
251 2088 tao
                   "DBTransform.transformXMLDocument: " +
252
                   e.getMessage());
253
254
      }
255
    }
256
    else
257
    {
258
      // No stylesheet registered form this document type, so just return the
259
      // XML stream we were passed
260
      pw.print(docContent);
261
    }
262
   }
263
264 3675 barteau
  /**
265
   * Reads skin's config file if it exists, and populates Transformer paramaters
266
   * with its contents.
267
   * It then adds the parameters passed to it via Hashtable param to the Transformer.
268
   * It then calls the Transformer.transform method.
269 2088 tao
   */
270 3675 barteau
  private void doTransform(StringReader docContent,
271
          StreamResult resultOutput,
272
          String xslSystemId,
273
          Hashtable param,
274
          String qformat,
275
          String sessionid)
276
          throws Exception {
277
278
      Properties skinOptions;
279
      TransformerFactory tFactory;
280
      Transformer transformer;
281
      String key, value;
282
      StreamSource xml;
283
      Enumeration en;
284
      Iterator iterIt;
285
      Map.Entry entry;
286
287
      if (xslSystemId != null) {
288
        tFactory = TransformerFactory.newInstance();
289
        transformer = tFactory.newTransformer(new StreamSource(xslSystemId));
290
291 2088 tao
        transformer.setParameter("qformat", qformat);
292 2663 sgarg
        logMetacat.warn("qformat: "+qformat);
293 2893 sgarg
294 3675 barteau
        if (MetaCatUtil.hasSkinConfig(qformat)) {
295
            skinOptions = MetaCatUtil.getSkinConfig(qformat);
296 2897 sgarg
297 3675 barteau
            iterIt = skinOptions.entrySet().iterator();
298
            while (iterIt.hasNext()) {
299
                entry = (Entry) iterIt.next();
300
                key = (String) entry.getKey();
301
                value = (String) entry.getValue();
302
                transformer.setParameter(key, value);
303
            }
304
        }
305 2893 sgarg
306 3675 barteau
        if (sessionid != null && !sessionid.equals("null")) {
307 2088 tao
          transformer.setParameter("sessid", sessionid);
308
        }
309 3675 barteau
310 3733 leinfelder
        //set up the default params (can be overridden by the passed in params)
311
        String cgiPrefix = MetaCatUtil.getOption("cgi-prefix");
312 3736 leinfelder
        logMetacat.debug("cgi-prefix=" + cgiPrefix);
313 3780 daigle
        logMetacat.debug("httpServer=" + httpServer);
314 3736 leinfelder
        logMetacat.debug("contextURL=" + contextURL);
315 3780 daigle
        logMetacat.debug("serletPath=" + servletURL);
316 3733 leinfelder
        transformer.setParameter("cgi-prefix", cgiPrefix);
317 3780 daigle
        transformer.setParameter("httpServer", httpServer);
318 3733 leinfelder
        transformer.setParameter("contextURL", contextURL);
319 3780 daigle
        transformer.setParameter("servletURL", servletURL);
320 3733 leinfelder
321 2088 tao
        // Set up parameter for transformation
322 3675 barteau
        if ( param != null) {
323
          en = param.keys();
324
          while (en.hasMoreElements()) {
325
            key = (String) en.nextElement();
326
            value = ((String[]) (param.get(key)))[0];
327 2668 sgarg
            logMetacat.info(key+" : "+value);
328 2088 tao
            transformer.setParameter(key, value);
329
          }
330
        }
331 3675 barteau
        xml = new StreamSource(docContent);
332 2088 tao
        transformer.transform(xml,resultOutput);
333
    }
334
  }//doTransform
335
336
337 1716 berkley
  /**
338 906 berkley
   * gets the content of a tag in a given xml file with the given path
339
   * @param f the file to parse
340
   * @param path the path to get the content from
341
   */
342 1716 berkley
  public static NodeList getPathContent(File f, String path)
343 906 berkley
  {
344
    if(f == null)
345
    {
346
      return null;
347
    }
348 1716 berkley
349 906 berkley
    DOMParser parser = new DOMParser();
350
    InputSource in;
351
    FileInputStream fs;
352 1716 berkley
353 906 berkley
    try
354 1716 berkley
    {
355 906 berkley
      fs = new FileInputStream(f);
356
      in = new InputSource(fs);
357
    }
358
    catch(FileNotFoundException fnf)
359
    {
360
      fnf.printStackTrace();
361
      return null;
362
    }
363 1716 berkley
364 906 berkley
    try
365
    {
366
      parser.parse(in);
367
      fs.close();
368
    }
369
    catch(Exception e1)
370
    {
371 1716 berkley
      System.err.println("File: " + f.getPath() + " : parse threw: " +
372 906 berkley
                         e1.toString());
373
      return null;
374
    }
375 1716 berkley
376 906 berkley
    Document doc = parser.getDocument();
377 1716 berkley
378 906 berkley
    try
379
    {
380
      NodeList docNodeList = XPathAPI.selectNodeList(doc, path);
381
      return docNodeList;
382
    }
383
    catch(Exception se)
384
    {
385 1716 berkley
      System.err.println("file: " + f.getPath() + " : parse threw: " +
386 906 berkley
                         se.toString());
387
      return null;
388
    }
389
  }
390 87 jones
391
  /**
392
   * Lookup a stylesheet reference from the db catalog
393
   *
394 832 jones
   * @param qformat    the named style-set format
395
   * @param sourcetype the document type of the source
396
   * @param targettype the document type of the target
397
   */
398 1716 berkley
  public String getStyleSystemId(String qformat, String sourcetype,
399 832 jones
                String targettype) {
400
    String systemId = null;
401
402
    if ((qformat == null) || (qformat.equals("html"))) {
403
      qformat = defaultStyle;
404
    }
405
406
    // Load the style-set map for this qformat into a DOM
407
    try {
408 906 berkley
      boolean breakflag = false;
409 1929 brooke
      String filename = configDir + "/" + qformat + "/" + qformat + ".xml";
410 2663 sgarg
      logMetacat.warn("Trying style-set file: " + filename);
411 906 berkley
      File f = new File(filename);
412
      NodeList nlDoctype = getPathContent(f, "/style-set/doctype");
413
      NodeList nlDefault = getPathContent(f, "/style-set/default-style");
414
      Node nDefault = nlDefault.item(0);
415
      systemId = nDefault.getFirstChild().getNodeValue(); //set the default
416 1716 berkley
417 906 berkley
      for(int i=0; i<nlDoctype.getLength(); i++)
418
      { //look for the right sourcetype
419
        Node nDoctype = nlDoctype.item(i);
420
        NamedNodeMap atts = nDoctype.getAttributes();
421
        Node nAtt = atts.getNamedItem("publicid");
422
        String doctype = nAtt.getFirstChild().getNodeValue();
423
        if(doctype.equals(sourcetype))
424
        { //found the right sourcetype now we need to get the target type
425
          NodeList nlChildren = nDoctype.getChildNodes();
426
          for(int j=0; j<nlChildren.getLength(); j++)
427
          {
428
            Node nChild = nlChildren.item(j);
429
            String childName = nChild.getNodeName();
430
            if(childName.equals("target"))
431
            {
432
              NamedNodeMap childAtts = nChild.getAttributes();
433
              Node nTargetPublicId = childAtts.getNamedItem("publicid");
434
              String target = nTargetPublicId.getFirstChild().getNodeValue();
435
              if(target.equals(targettype))
436
              { //we found the right target type
437
                NodeList nlTarget = nChild.getChildNodes();
438
                for(int k=0; k<nlTarget.getLength(); k++)
439
                {
440
                  Node nChildText = nlTarget.item(k);
441
                  if(nChildText.getNodeType() == Node.TEXT_NODE)
442
                  { //get the text from the target node
443
                    systemId = nChildText.getNodeValue();
444
                    breakflag = true;
445
                    break;
446
                  }
447
                }
448 832 jones
              }
449
            }
450 1716 berkley
451 906 berkley
            if(breakflag)
452
            {
453
              break;
454
            }
455 832 jones
          }
456
        }
457 1716 berkley
458 906 berkley
        if(breakflag)
459
        {
460
          break;
461
        }
462 832 jones
      }
463
    }
464 906 berkley
    catch(Exception e)
465
    {
466
      System.out.println("Error parsing style-set file: " + e.getMessage());
467
      e.printStackTrace();
468
    }
469 3725 tao
470
    //Check if the systemId is relative path, add a postfix - the contextULR to systemID.
471
    if (systemId != null && systemId.indexOf("http://" ) == -1)
472
    {
473
    	systemId = contextURL+systemId;
474
    }
475 832 jones
    // Return the system ID for this particular source document type
476 2663 sgarg
    logMetacat.info("style system id is: "+systemId);
477 832 jones
    return systemId;
478
  }
479
480 1896 tao
 /* Method to modified the system id of xml input -- make sure it
481
    points to system id in xml_catalog table
482
  */
483 2088 tao
  private void modifiedXmlStreamSource(StreamSource xml, String publicId)
484 1896 tao
                                       throws Exception
485
  {
486
    // make sure the xml is not null
487
    if (xml == null || publicId == null)
488
    {
489
      return;
490 87 jones
    }
491 2663 sgarg
    logMetacat.info("public id of input stream is " +publicId);
492 1896 tao
    // Get system id from xml_catalog table
493
    String systemId = DBEntityResolver.getDTDSystemID(publicId);
494 2663 sgarg
    logMetacat.info("system id of input stream from xml_catalog"
495
                               +"table is " +systemId);
496 1896 tao
    //set system id to input stream
497
    xml.setSystemId(systemId);
498 87 jones
  }
499 2088 tao
500 1903 tao
  /*
501
   * removes the DOCTYPE element and its contents from a Sting
502 2088 tao
   * used to avoid problems with incorrect SystemIDs
503 1903 tao
   */
504 2088 tao
  private String removeDOCTYPE(String in) {
505 1903 tao
    String ret = "";
506
    int startpos = in.indexOf("<!DOCTYPE");
507
    if (startpos>-1) {
508 2088 tao
      int stoppos = in.indexOf(">", startpos + 8);
509 1903 tao
      ret = in.substring(0,startpos) + in.substring(stoppos+1,in.length());
510
    } else {
511
      return in;
512
    }
513 2088 tao
    return ret;
514 1903 tao
  }
515 99 jones
516
  /**
517
   * the main routine used to test the transform utility.
518
   *
519 184 jones
   * Usage: java DBTransform
520 99 jones
   */
521
  static public void main(String[] args) {
522 1716 berkley
523 184 jones
     if (args.length > 0)
524 99 jones
     {
525
        System.err.println("Wrong number of arguments!!!");
526 184 jones
        System.err.println("USAGE: java DBTransform");
527 99 jones
        return;
528
     } else {
529
        try {
530 1716 berkley
531 99 jones
          // Open a connection to the database
532 1217 tao
          /*MetaCatUtil   util = new MetaCatUtil();
533
          Connection dbconn = util.openDBConnection();*/
534 99 jones
535
          // Create a test document
536
          StringBuffer testdoc = new StringBuffer();
537
          testdoc.append("<?xml version=\"1.0\"?>");
538
          testdoc.append("<eml-dataset><metafile_id>NCEAS-0001</metafile_id>");
539
          testdoc.append("<dataset_id>DS001</dataset_id>");
540
          testdoc.append("<title>My test doc</title></eml-dataset>");
541
542
          // Transform the document to the new doctype
543 1217 tao
          DBTransform dbt = new DBTransform();
544 1716 berkley
          dbt.transformXMLDocument(testdoc.toString(),
545
                                   "-//NCEAS//eml-dataset//EN",
546
                                   "-//W3C//HTML//EN",
547 832 jones
                                   "knb",
548 1664 tao
                                   new PrintWriter(System.out), null);
549 99 jones
550
        } catch (Exception e) {
551
          System.err.println("EXCEPTION HANDLING REQUIRED");
552
          System.err.println(e.getMessage());
553
          e.printStackTrace(System.err);
554
        }
555
     }
556
  }
557 1716 berkley
558 184 jones
  private void dbg(int position) {
559 99 jones
    System.err.println("Debug flag: " + position);
560
  }
561
562 87 jones
}