Project

General

Profile

1
/**
2
 *  '$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
 *    Release: @release@
9
 *
10
 * '$Author: sgarg $'
11
 * '$Date: 2006-01-20 08:21:35 -0800 (Fri, 20 Jan 2006) $'
12
 * '$Revision: 2896 $'
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
 */
28

    
29
package edu.ucsb.nceas.metacat;
30

    
31
import java.io.*;
32
import java.net.URL;
33
import java.net.MalformedURLException;
34
import java.sql.*;
35
import java.util.Enumeration;
36
import java.util.Hashtable;
37
import java.util.Stack;
38

    
39
import javax.xml.transform.TransformerFactory;
40
import javax.xml.transform.Transformer;
41
import javax.xml.transform.stream.StreamSource;
42
import javax.xml.transform.stream.StreamResult;
43
import javax.xml.transform.TransformerException;
44
import javax.xml.transform.TransformerConfigurationException;
45

    
46
import org.apache.log4j.Logger;
47
import org.apache.xerces.parsers.DOMParser;
48
import org.w3c.dom.Attr;
49
import org.w3c.dom.NamedNodeMap;
50
import org.w3c.dom.NodeList;
51
import org.w3c.dom.Document;
52
import org.w3c.dom.Node;
53
import org.w3c.dom.NodeList;
54
import org.w3c.dom.DocumentType;
55
import org.xml.sax.SAXException;
56
import org.xml.sax.InputSource;
57
import org.apache.xerces.dom.DocumentTypeImpl;
58
import org.apache.xpath.XPathAPI;
59
import org.w3c.dom.NamedNodeMap;
60

    
61
/*
62
import oracle.xml.parser.v2.XSLStylesheet;
63
import oracle.xml.parser.v2.XSLException;
64
import oracle.xml.parser.v2.XMLParseException;
65
import oracle.xml.parser.v2.XSLProcessor;
66
import oracle.xml.parser.v2.XMLDocument;
67
import oracle.xml.parser.v2.DOMParser;
68
*/
69
import org.w3c.dom.Document;
70
import org.w3c.dom.Node;
71
import org.w3c.dom.Element;
72
import org.xml.sax.SAXException;
73

    
74
import java.util.Properties;
75

    
76
/**
77
 * A Class that transforms XML documents utitlizing XSL style sheets
78
 */
79
public class DBTransform {
80

    
81
  //private Connection	conn = null;
82
  private MetaCatUtil   util = null;
83
  private String 	configDir = null;
84
  private String	defaultStyle = null;
85
  private Logger logMetacat = Logger.getLogger(DBTransform.class);
86
  
87
  /**
88
   * construct a DBTransform instance.
89
   *
90
   * Generally, one calls transformXMLDocument() after constructing the instance
91
   *
92
   * @param conn the database connection from which to lookup the public ids
93
   */
94
  public DBTransform()
95
                  throws IOException,
96
                         SQLException,
97
                         ClassNotFoundException
98
  {
99
    //this.conn = conn;
100
    util = new MetaCatUtil();
101
    configDir = util.getOption("config-dir");
102
    defaultStyle = util.getOption("default-style");
103
  }
104

    
105
  /**
106
   * @see transformXMLDocument(String doc, String sourceType,
107
   *            String targetType, String qformat, PrintWriter pw,
108
   *            String sessionid)
109
   */
110
  public void transformXMLDocument(String doc, String sourceType,
111
                String targetType, String qformat, PrintWriter pw,
112
                Hashtable param)
113
  {
114
    transformXMLDocument(doc, sourceType, targetType, qformat, pw, param, null);
115
  }
116

    
117
   /**
118
   * @see transformXMLDocument(String doc, String sourceType,
119
   *            String targetType, String qFormat, StringWriter pw
120
   *            String sessionid)
121
   */
122
  public void transformXMLDocument(String doc, String sourceType,
123
                String targetType, String qFormat, StringWriter pw)
124
  {
125
    transformXMLDocument(doc, sourceType, targetType, qFormat, pw, null);
126
  }
127

    
128

    
129
  /**
130
   * Transform an XML document using the stylesheet reference from the db
131
   *
132
   * @param doc the document to be transformed
133
   * @param sourcetype the document type of the source
134
   * @param targettype the target document type
135
   * @param qformat the name of the style set to use
136
   * @param pw the PrintWriter to which output is printed
137
   * @param params some parameters for eml2 transformation
138
   */
139
  public void transformXMLDocument(String doc, String sourceType,
140
                                   String targetType, String qformat,
141
                                   PrintWriter pw, Hashtable param,
142
                                   String sessionid)
143
 {
144

    
145
    // Look up the stylesheet for this type combination
146
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
147
    if (xslSystemId != null)
148
    {
149
      try
150
      {// Create a stylesheet from the system id that was found
151
        doc = removeDOCTYPE(doc);
152
        StringReader xml = new StringReader(doc);
153
        StreamResult result = new StreamResult(pw);
154
        doTransform(xml, result, xslSystemId, param, qformat, sessionid);
155

    
156
      }
157
      catch (Exception e)
158
      {
159
        pw.println(xslSystemId + "Error transforming document in " +
160
                   "DBTransform.transformXMLDocument: " +
161
                   e.getMessage());
162

    
163
      }
164
    }
165
    else
166
    {
167
      // No stylesheet registered form this document type, so just return the
168
      // XML stream we were passed
169
      pw.print(doc);
170
    }
171
  }
172

    
173
  /**
174
   * Transform an XML document to StringWriter using the stylesheet reference
175
   * from the db
176
   * @param doc the document to be transformed
177
   * @param sourceType the document type of the source
178
   * @param targetType the target document type
179
   * @param qFormat the name of the style set to use
180
   * @param pw the StringWriter to which output will be stored
181
   */
182
  public void transformXMLDocument(String doc, String sourceType,
183
                String targetType, String qFormat, StringWriter pw,
184
                String sessionid)
185
  {
186

    
187
    // Look up the stylesheet for this type combination
188
    String xslSystemId = getStyleSystemId(qFormat, sourceType, targetType);
189
    if (xslSystemId != null)
190
    {
191
      // Create a stylesheet from the system id that was found
192
      try
193
      {
194
        doc = removeDOCTYPE(doc);
195
        StringReader xml = new StringReader(doc);
196
        StreamResult result = new StreamResult(pw);
197
        doTransform(xml, result, xslSystemId, null, qFormat, sessionid);
198
      }
199
      catch (Exception e)
200
      {
201
        logMetacat.error(xslSystemId + "Error transforming document in " +
202
                   "DBTransform.transformXMLDocument: " +
203
                   e.getMessage());
204

    
205
      }
206
    }
207
    else
208
    {
209
      // No stylesheet registered form this document type, so just return the
210
      // XML stream we were passed
211
      pw.write(doc);
212
    }
213
  }
214

    
215
  /**
216
   * Method to do transform for a string reader
217
   * @param doc the document to be transformed
218
   * @param sourcetype the document type of the source
219
   * @param targettype the target document type
220
   * @param qformat the name of the style set to use
221
   * @param pw the PrintWriter to which output is printed
222
   * @param params some parameters for eml2 transformation
223
   */
224
   public void transformXMLDocument(StringReader docContent, String sourceType,
225
                                   String targetType, String qformat,
226
                                   PrintWriter pw, Hashtable param,
227
                                   String sessionid)
228
   {
229
     // Look up the stylesheet for this type combination
230
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
231
    if (xslSystemId != null)
232
    {
233
      try
234
      {// Create a stylesheet from the system id that was found
235
        StreamResult result = new StreamResult(pw);
236
        doTransform(docContent, result, xslSystemId, param, qformat, sessionid);
237

    
238
      }
239
      catch (Exception e)
240
      {
241
        pw.println(xslSystemId + "Error transforming document in " +
242
                   "DBTransform.transformXMLDocument: " +
243
                   e.getMessage());
244

    
245
      }
246
    }
247
    else
248
    {
249
      // No stylesheet registered form this document type, so just return the
250
      // XML stream we were passed
251
      pw.print(docContent);
252
    }
253
   }
254

    
255
  /*
256
   * Method to do transfer
257
   */
258
  private void doTransform(StringReader docContent, StreamResult resultOutput,
259
                           String xslSystemId, Hashtable param,
260
                           String qformat, String sessionid)
261
                          throws Exception
262
  {
263
    if (xslSystemId != null)
264
    {
265
        TransformerFactory tFactory = TransformerFactory.newInstance();
266
        Transformer transformer = tFactory.newTransformer(
267
                                  new StreamSource(xslSystemId));
268
        transformer.setParameter("qformat", qformat);
269
        logMetacat.warn("qformat: "+qformat);
270
        
271
        if (MetaCatUtil.skinconfigs.containsKey(qformat)){
272
        	Properties skinOptions = (Properties)MetaCatUtil.skinconfigs.get(qformat);
273
        	transformer.setParameter("lsidauthority", skinOptions.getProperty("lsidauthority"));
274
           	transformer.setParameter("registryurl", skinOptions.getProperty("registryurl"));
275
           	transformer.setParameter("registryname", skinOptions.getProperty("registryname"));
276
        }
277
        
278
        if(sessionid != null)
279
        {
280
          transformer.setParameter("sessid", sessionid);
281
        }
282
        // Set up parameter for transformation
283
        if ( param != null)
284
        {
285
          Enumeration en = param.keys();
286
          while (en.hasMoreElements())
287
          {
288
            String key =(String)en.nextElement();
289
            String value = ((String[])(param.get(key)))[0];
290
            logMetacat.info(key+" : "+value);
291
            transformer.setParameter(key, value);
292
          }
293
        }
294
        StreamSource xml = new StreamSource(docContent);
295
        transformer.transform(xml,resultOutput);
296
    }
297
  }//doTransform
298

    
299

    
300
  /**
301
   * gets the content of a tag in a given xml file with the given path
302
   * @param f the file to parse
303
   * @param path the path to get the content from
304
   */
305
  public static NodeList getPathContent(File f, String path)
306
  {
307
    if(f == null)
308
    {
309
      return null;
310
    }
311

    
312
    DOMParser parser = new DOMParser();
313
    InputSource in;
314
    FileInputStream fs;
315

    
316
    try
317
    {
318
      fs = new FileInputStream(f);
319
      in = new InputSource(fs);
320
    }
321
    catch(FileNotFoundException fnf)
322
    {
323
      fnf.printStackTrace();
324
      return null;
325
    }
326

    
327
    try
328
    {
329
      parser.parse(in);
330
      fs.close();
331
    }
332
    catch(Exception e1)
333
    {
334
      System.err.println("File: " + f.getPath() + " : parse threw: " +
335
                         e1.toString());
336
      return null;
337
    }
338

    
339
    Document doc = parser.getDocument();
340

    
341
    try
342
    {
343
      NodeList docNodeList = XPathAPI.selectNodeList(doc, path);
344
      return docNodeList;
345
    }
346
    catch(Exception se)
347
    {
348
      System.err.println("file: " + f.getPath() + " : parse threw: " +
349
                         se.toString());
350
      return null;
351
    }
352
  }
353

    
354
  /**
355
   * Lookup a stylesheet reference from the db catalog
356
   *
357
   * @param qformat    the named style-set format
358
   * @param sourcetype the document type of the source
359
   * @param targettype the document type of the target
360
   */
361
  public String getStyleSystemId(String qformat, String sourcetype,
362
                String targettype) {
363
    String systemId = null;
364

    
365
    if ((qformat == null) || (qformat.equals("html"))) {
366
      qformat = defaultStyle;
367
    }
368

    
369
    // Load the style-set map for this qformat into a DOM
370
    try {
371
      boolean breakflag = false;
372
      String filename = configDir + "/" + qformat + "/" + qformat + ".xml";
373
      logMetacat.warn("Trying style-set file: " + filename);
374
      File f = new File(filename);
375
      NodeList nlDoctype = getPathContent(f, "/style-set/doctype");
376
      NodeList nlDefault = getPathContent(f, "/style-set/default-style");
377
      Node nDefault = nlDefault.item(0);
378
      systemId = nDefault.getFirstChild().getNodeValue(); //set the default
379

    
380
      for(int i=0; i<nlDoctype.getLength(); i++)
381
      { //look for the right sourcetype
382
        Node nDoctype = nlDoctype.item(i);
383
        NamedNodeMap atts = nDoctype.getAttributes();
384
        Node nAtt = atts.getNamedItem("publicid");
385
        String doctype = nAtt.getFirstChild().getNodeValue();
386
        if(doctype.equals(sourcetype))
387
        { //found the right sourcetype now we need to get the target type
388
          NodeList nlChildren = nDoctype.getChildNodes();
389
          for(int j=0; j<nlChildren.getLength(); j++)
390
          {
391
            Node nChild = nlChildren.item(j);
392
            String childName = nChild.getNodeName();
393
            if(childName.equals("target"))
394
            {
395
              NamedNodeMap childAtts = nChild.getAttributes();
396
              Node nTargetPublicId = childAtts.getNamedItem("publicid");
397
              String target = nTargetPublicId.getFirstChild().getNodeValue();
398
              if(target.equals(targettype))
399
              { //we found the right target type
400
                NodeList nlTarget = nChild.getChildNodes();
401
                for(int k=0; k<nlTarget.getLength(); k++)
402
                {
403
                  Node nChildText = nlTarget.item(k);
404
                  if(nChildText.getNodeType() == Node.TEXT_NODE)
405
                  { //get the text from the target node
406
                    systemId = nChildText.getNodeValue();
407
                    breakflag = true;
408
                    break;
409
                  }
410
                }
411
              }
412
            }
413

    
414
            if(breakflag)
415
            {
416
              break;
417
            }
418
          }
419
        }
420

    
421
        if(breakflag)
422
        {
423
          break;
424
        }
425
      }
426
    }
427
    catch(Exception e)
428
    {
429
      System.out.println("Error parsing style-set file: " + e.getMessage());
430
      e.printStackTrace();
431
    }
432

    
433
    // Return the system ID for this particular source document type
434
    logMetacat.info("style system id is: "+systemId);
435
    return systemId;
436
  }
437

    
438
 /* Method to modified the system id of xml input -- make sure it
439
    points to system id in xml_catalog table
440
  */
441
  private void modifiedXmlStreamSource(StreamSource xml, String publicId)
442
                                       throws Exception
443
  {
444
    // make sure the xml is not null
445
    if (xml == null || publicId == null)
446
    {
447
      return;
448
    }
449
    logMetacat.info("public id of input stream is " +publicId);
450
    // Get system id from xml_catalog table
451
    String systemId = DBEntityResolver.getDTDSystemID(publicId);
452
    logMetacat.info("system id of input stream from xml_catalog"
453
                               +"table is " +systemId);
454
    //set system id to input stream
455
    xml.setSystemId(systemId);
456
  }
457

    
458
  /*
459
   * removes the DOCTYPE element and its contents from a Sting
460
   * used to avoid problems with incorrect SystemIDs
461
   */
462
  private String removeDOCTYPE(String in) {
463
    String ret = "";
464
    int startpos = in.indexOf("<!DOCTYPE");
465
    if (startpos>-1) {
466
      int stoppos = in.indexOf(">", startpos + 8);
467
      ret = in.substring(0,startpos) + in.substring(stoppos+1,in.length());
468
    } else {
469
      return in;
470
    }
471
    return ret;
472
  }
473

    
474
  /**
475
   * the main routine used to test the transform utility.
476
   *
477
   * Usage: java DBTransform
478
   */
479
  static public void main(String[] args) {
480

    
481
     if (args.length > 0)
482
     {
483
        System.err.println("Wrong number of arguments!!!");
484
        System.err.println("USAGE: java DBTransform");
485
        return;
486
     } else {
487
        try {
488

    
489
          // Open a connection to the database
490
          /*MetaCatUtil   util = new MetaCatUtil();
491
          Connection dbconn = util.openDBConnection();*/
492

    
493
          // Create a test document
494
          StringBuffer testdoc = new StringBuffer();
495
          testdoc.append("<?xml version=\"1.0\"?>");
496
          testdoc.append("<eml-dataset><metafile_id>NCEAS-0001</metafile_id>");
497
          testdoc.append("<dataset_id>DS001</dataset_id>");
498
          testdoc.append("<title>My test doc</title></eml-dataset>");
499

    
500
          // Transform the document to the new doctype
501
          DBTransform dbt = new DBTransform();
502
          dbt.transformXMLDocument(testdoc.toString(),
503
                                   "-//NCEAS//eml-dataset//EN",
504
                                   "-//W3C//HTML//EN",
505
                                   "knb",
506
                                   new PrintWriter(System.out), null);
507

    
508
        } catch (Exception e) {
509
          System.err.println("EXCEPTION HANDLING REQUIRED");
510
          System.err.println(e.getMessage());
511
          e.printStackTrace(System.err);
512
        }
513
     }
514
  }
515

    
516
  private void dbg(int position) {
517
    System.err.println("Debug flag: " + position);
518
  }
519

    
520
}
(25-25/64)