001: /*
002: Loader - tool for transfering data from one JDBC source to another and
003: doing transformations during copy.
004: Copyright (C) 2002 Together
005: This library is free software; you can redistribute it and/or
006: modify it under the terms of the GNU Lesser General Public
007: License as published by the Free Software Foundation; either
008: version 2.1 of the License, or (at your option) any later version.
009: This library is distributed in the hope that it will be useful,
010: but WITHOUT ANY WARRANTY; without even the implied warranty of
011: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: Lesser General Public License for more details.
013: You should have received a copy of the GNU Lesser General Public
014: License along with this library; if not, write to the Free Software
015: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
016: LoaderXIncluder.java
017: Date: 22.09.2001.
018: @version 1.0
019: @author:
020: Milosevic Sinisa
021: */
022:
023: package org.webdocwf.util.loader;
024:
025: import java.io.BufferedInputStream;
026: import java.io.BufferedReader;
027: import java.io.File;
028: import java.io.IOException;
029: import java.io.InputStream;
030: import java.io.InputStreamReader;
031: import java.io.OutputStream;
032: import java.io.OutputStreamWriter;
033: import java.io.UnsupportedEncodingException;
034: import java.io.Writer;
035: import java.net.MalformedURLException;
036: import java.net.URL;
037: import java.net.URLConnection;
038:
039: import org.apache.xerces.parsers.SAXParser;
040: import org.webdocwf.util.loader.logging.Logger;
041: import org.xml.sax.AttributeList;
042: import org.xml.sax.HandlerBase;
043: import org.xml.sax.InputSource;
044: import org.xml.sax.SAXException;
045: import org.xml.sax.SAXParseException;
046:
047: /**
048: * LoaderXIncluder.java
049: * This class parses a document (text or xml file) and writes the documents
050: * contents back to standard output.
051: */
052: public class LoaderXIncluder extends HandlerBase {
053: private Writer out;
054: private String encoding;
055: private int level = 0;
056: //counter for dtd file
057: private int counter1 = 1;
058:
059: //counter for sql files
060: private int counter2 = 0;
061:
062: //counter for xml (import definition) file
063: private int counter3 = 0;
064:
065: //counter for line before dtd file
066: private int counter4 = 0;
067:
068: //counter for LoaderJob.xml (part) file
069: private int counter5 = 0;
070:
071: //for create and drop database
072: private int counter6 = 0;
073:
074: private boolean firstPartXml = true;
075:
076: private String loaderJobPath = "";
077:
078: /** Main program entry point.
079: * @param argv represents input parmeters
080: */
081: public static void main(String argv[]) {
082: if (argv.length == 0) {
083: System.out.println("Usage: java LoaderXIncluder uri");
084: System.out
085: .println(" where uri is the URI of your XML document.");
086: System.out
087: .println(" Sample: java LoaderXIncluder demo.xml");
088: System.exit(1);
089: }
090: LoaderXIncluder s1 = new LoaderXIncluder();
091: s1.parseURI(argv[0]);
092: }
093:
094: /**
095: * Constructor of class without parameters.
096: */
097: public LoaderXIncluder() {
098: }
099:
100: /**
101: * Construct object LoaderXIncluder with associated outputStream and encoding.
102: * @param out - OutputStream where will be written final XML.
103: * @param encoding - encoding String representation of encoding.
104: * @throws UnsupportedEncodingException
105: */
106: public LoaderXIncluder(OutputStream out, String encoding)
107: throws UnsupportedEncodingException {
108: this .out = new OutputStreamWriter(out, encoding);
109: this .encoding = encoding;
110: }
111:
112: /**
113: * Construct object LoaderXIncluder with associated outputStream.
114: * Class uses default "UTF-8" encoding.
115: * @param out - OutputStream where will be written final XML.
116: */
117: public LoaderXIncluder(OutputStream out) {
118: try {
119: this .out = new OutputStreamWriter(out, "UTF8");
120: this .encoding = "UTF-8";
121: } catch (UnsupportedEncodingException e) {
122: }
123: }
124:
125: /**
126: * Method parseUri parses a file "uri" and writes the file
127: * contents back to standard output including contents of 'include' files .
128: * @param uri - Name of XML file.
129: */
130: public void parseURI(String uri) {
131: try {
132: SAXParser parser = new SAXParser();
133: parser.setDocumentHandler(this );
134: parser.setEntityResolver(this );
135: parser.setFeature("http://xml.org/sax/features/validation",
136: false);
137: parser.setErrorHandler(this );
138: // System.out.println("Loader loads XML file : "+ uri+"\n");
139: Logger.getCentralLogger().write("normal",
140: "Loader loads XML file : " + uri);
141:
142: File f = new File(uri);
143: this .loaderJobPath = f.getCanonicalFile().getParent();
144: URL xml = f.toURL();
145:
146: InputStreamReader xmlStream = new InputStreamReader(xml
147: .openStream());
148: BufferedReader reader = new BufferedReader(xmlStream);
149: String intro = "";
150: while ((intro = reader.readLine()) != null) {
151: if (intro.indexOf("include") == -1)
152: counter6++;
153: else
154: break;
155: }
156: counter6 = counter6 - 4;
157: LocationOfException.setJdbcNumber(counter6);
158: reader.close();
159: xmlStream.close();
160: parser.parse(uri);
161: } catch (Exception e) {
162: // System.err.println();
163: e.printStackTrace();
164: Logger.getCentralLogger().write("normal", e.getMessage());
165: }
166: }
167:
168: boolean hasDTD = false;
169:
170: /** Processing DOCTYPE deklaration
171: * @param publicId is public ID of document
172: * @param systemId is system ID of document
173: * @return null
174: */
175: public InputSource resolveEntity(String publicId, String systemId) {
176: hasDTD = true;
177: try {
178: if (systemId != null) {
179: out.write("<!DOCTYPE loaderJob SYSTEM \"" + systemId
180: + "\">" + "\n");
181: counter4++;
182: } else if (publicId != null) {
183: out.write("<!DOCTYPE loaderJob PUBLIC \"" + publicId
184: + "\">" + "\n");
185: counter4++;
186: }
187: } catch (Exception e) {
188: System.err.println(e);
189: }
190: return null;
191: }
192:
193: /** Processing instruction.
194: *@param target is target
195: *@param data is target data
196: */
197: public void processingInstruction(String target, String data) {
198: try {
199: out.write("<?");
200: out.write(target);
201: if (data != null && data.length() > 0) {
202: out.write(' ');
203: out.write(data);
204: }
205: out.write("?>");
206: counter4++;
207: } catch (IOException e) {
208: System.err.println(e);
209: }
210: }
211:
212: /** Start document. */
213: public void startDocument() {
214: if (level == 0) {
215: try {
216: out.write("<?xml version=\"1.0\"?>\r\n");
217: counter4++;
218: } catch (IOException e) {
219: System.err.println(e);
220: }
221: LocationOfException.setIntroNumber(counter4);
222: }
223: }
224:
225: /** Start element.
226: * @param name is name of the tag
227: * @param atts is attributes of the tag
228: */
229: public void startElement(String name, AttributeList atts) {
230: try {
231: //if DTD or SCHEMA is not defined use default
232: if (name.equalsIgnoreCase("loaderJob")) {
233: /*
234: if (!hasDTD) {
235: String OCTOPUS_HOME = System.getProperty("OCTOPUS_HOME");
236: if (OCTOPUS_HOME != null) {
237: if (! (OCTOPUS_HOME.endsWith("\\") || OCTOPUS_HOME.endsWith("/")))
238: OCTOPUS_HOME += "/";
239: String url = "file:///" + OCTOPUS_HOME + "XmlTransform/xml/dtd/loaderJob.dtd";
240: out.write("<!DOCTYPE loaderJob SYSTEM \"" + url + "\">" + "\n");
241: } else {
242: URL dtdURL = this.getClass().getClassLoader().getResource("xml/dtd/loaderJob.dtd");
243: InputStreamReader dtdStream = new InputStreamReader(dtdURL.openStream());
244: BufferedReader reader = new BufferedReader(dtdStream);
245: StringBuffer sb = new StringBuffer();
246: String nextLine = "";
247: boolean firstLine = true;
248: while ( (nextLine = reader.readLine()) != null) {
249: if (!firstLine) {
250: sb.append(nextLine + "\n");
251: counter1++;
252: } else
253: firstLine = false;
254: }
255: out.write("<!DOCTYPE loaderJob [" + sb.toString() + "\n]>");
256: counter1++;
257: LocationOfException.setDtdNumber(counter1);
258: }
259: }
260: */
261: }
262: if (name.equalsIgnoreCase("include")) {
263: String href = atts.getValue("href");
264: if (href == null) {
265: System.out
266: .println("Missing href attribute in include Element");
267: System.exit(1);
268: }
269:
270: File file = new File(href);
271: if (!file.isAbsolute()) {
272: String tmp = this .loaderJobPath
273: + System.getProperty("file.separator")
274: + href;
275: File fileHref = new File(tmp);
276: href = fileHref.getCanonicalPath();
277: }
278:
279: String parse = atts.getValue("parse");
280: if (parse == null)
281: parse = "xml";
282: if (parse.equals("text")) {
283: String encoding = atts.getValue("encoding");
284: includeTextDocument(href, encoding);
285: } else if (parse.equals("xml")) {
286: level++;
287: includeXMLDocument(href);
288: level--;
289: } else {
290: System.out
291: .println("Illegal value for parse attribute: "
292: + parse);
293: Logger.getCentralLogger().write(
294: "normal",
295: "Illegal value for parse attribute: "
296: + parse);
297: System.exit(1);
298: }
299: } else if (name.equalsIgnoreCase("definitionInclude")) {
300: } else {
301: out.write("<" + name);
302: if (name.equals("loaderJob")) {
303: out.write(" xmlns='http://www.objectweb.org'");
304: out
305: .write(" xmlns:xsi=\'http://www.w3.org/2001/XMLSchema-instance\'");
306: out
307: .write(" xsi:schemaLocation='http://www.objectweb.org http://octopus.objectweb.org/doc/XmlTransform/xml/xmlschema/loaderJob.xsd'");
308: out.write(" ");
309: }
310: // if(name.startsWith("jdbc"))
311: // counter5++;
312: // if(!name.startsWith("jdbc") && counter5!=0 && firstPartXml==true){
313: // LocationOfException.setJdbcNumber(counter5);
314: // firstPartXml=false;
315: // counter5=0;
316: // }
317: //System.out.println("atts="+atts);
318: for (int i = 0; i < atts.getLength(); i++) {
319: out.write(" ");
320: out.write(atts.getName(i));
321: out.write("='");
322: String value = atts.getValue(i);
323: // + 4 allows space for one entitiy reference.
324: // If there's more than that, then the StringBuffer
325: // will automatically expand
326: // Need to use character references if the encoding
327: // can't support the character
328: StringBuffer encodedValue = new StringBuffer(value
329: .length() + 4);
330: for (int j = 0; j < value.length(); j++) {
331: char c = value.charAt(j);
332: if (c == '&')
333: encodedValue.append("&");
334: else if (c == '<')
335: encodedValue.append("<");
336: else if (c == '>')
337: encodedValue.append(">");
338: else if (c == '\'')
339: encodedValue.append("'");
340: else
341: encodedValue.append(c);
342: }
343: out.write(encodedValue.toString());
344: out.write("'");
345: }
346: out.write(">");
347: }
348: } catch (IOException e) {
349: System.err.println(e);
350: Logger.getCentralLogger().write("normal", e.getMessage());
351: } catch (SAXException ex) {
352: System.err.println(ex);
353: Logger.getCentralLogger().write("normal", ex.getMessage());
354: }
355: }
356:
357: /** Characters.
358: * @param ch is array of characters
359: * @param start is int
360: * @param length is length of the input parameters
361: * @throws SAXException
362: */
363: public void characters(char ch[], int start, int length)
364: throws SAXException {
365: try {
366: for (int i = 0; i < length; i++) {
367: char c = ch[start + i];
368: if (c == '&')
369: out.write("&");
370: else if (c == '<')
371: out.write("<");
372: else if (c == '\n') {
373: counter2++;
374: out.write(c);
375: } else
376: out.write(c);
377: }
378: } catch (IOException e) {
379: System.err.println(e);
380: Logger.getCentralLogger().write("normal", e.getMessage());
381: }
382: }
383:
384: /** Ignorable whitespace.
385: * @param ch is array of characters
386: * @param start is int
387: * @param length is length of the input parameters
388: */
389: public void ignorableWhitespace(char ch[], int start, int length) {
390: try {
391: this .characters(ch, start, length);
392: } catch (SAXException e) {
393: System.err.println(e);
394: Logger.getCentralLogger().write("normal", e.getMessage());
395: }
396: }
397:
398: /** End element.
399: * @param name is name of the tag
400: */
401: public void endElement(String name) {
402: if (!name.equalsIgnoreCase("include")
403: && !name.equalsIgnoreCase("definitionInclude")) {
404: // if(name.startsWith("jdbc")&&name.endsWith("s"))
405: // counter5++;
406: try {
407: out.write("</");
408: out.write(name);
409: out.write(">");
410: } catch (IOException e) {
411: System.err.println(e);
412: Logger.getCentralLogger().write("normal",
413: e.getMessage());
414: }
415: }
416: }
417:
418: /** End document. */
419: public void endDocument() {
420: try {
421: out.flush();
422: } catch (IOException e) {
423: System.err.println(e);
424: Logger.getCentralLogger().write("normal", e.getMessage());
425: }
426: }
427:
428: //
429: // ErrorHandler methods
430: //
431: /** Warning.
432: * @param ex is SAXParseException exception
433: */
434: public void warning(SAXParseException ex) {
435: System.err.println("[Warning] " + getLocationString(ex) + ": "
436: + ex.getMessage());
437: Logger.getCentralLogger().write(
438: "normal",
439: "[Warning] " + getLocationString(ex) + ": "
440: + ex.getMessage());
441: }
442:
443: /** Error.
444: * @param ex is SAXParseException exception
445: */
446: public void error(SAXParseException ex) {
447: System.err.println("[Error] " + getLocationString(ex) + ": "
448: + ex.getMessage());
449: Logger.getCentralLogger().write(
450: "normal",
451: "[Error] " + getLocationString(ex) + ": "
452: + ex.getMessage());
453: }
454:
455: /** Fatal error.
456: * @param ex is SAXParseException exception
457: * @throws SAXException
458: */
459: public void fatalError(SAXParseException ex) throws SAXException {
460: System.err.println("[Fatal Error] " + getLocationString(ex)
461: + ": " + ex.getMessage());
462: Logger.getCentralLogger().write(
463: "normal",
464: "[Fatal Error] " + getLocationString(ex) + ": "
465: + ex.getMessage());
466: throw ex;
467: }
468:
469: /** Returns a string of the location.
470: * @param ex is SAXParseException exception
471: * @return string
472: */
473: private String getLocationString(SAXParseException ex) {
474: StringBuffer str = new StringBuffer();
475: String systemId = ex.getSystemId();
476: if (systemId != null) {
477: int index = systemId.lastIndexOf('/');
478: if (index != -1)
479: systemId = systemId.substring(index + 1);
480: str.append(systemId);
481: }
482: str.append(':');
483: str.append(ex.getLineNumber());
484: str.append(':');
485: str.append(ex.getColumnNumber());
486: return str.toString();
487: }
488:
489: /**
490: * <p>
491: * This utility method reads a document at a specified URL
492: * and fires off calls to <code>characters()</code>.
493: * It's used to include files with <code>parse="text"</code>
494: * </p>
495: *
496: * @param url URL of the document that will be read
497: * @param encoding Encoding of the document; e.g. UTF-8,
498: * ISO-8859-1, etc.
499: * @throws SAXException if the requested document cannot
500: * be downloaded from the specified URL
501: * or if the encoding is not recognized
502: */
503: private void includeTextDocument(String url, String encoding)
504: throws SAXException {
505: if (encoding == null || encoding.trim().equals(""))
506: encoding = "UTF-8";
507: File sourceXml = new File(url);
508: URL source;
509: counter2 = 1;
510: try {
511: source = sourceXml.toURL();
512: } catch (MalformedURLException e) {
513: Logger.getCentralLogger().write("normal",
514: "Unresolvable URL :" + e.getMessage());
515: throw new SAXException("Unresolvable URL :", e);
516: }
517: try {
518: URLConnection uc = source.openConnection();
519: String encodingFromHeader = uc.getContentEncoding();
520: if (encodingFromHeader != null)
521: encoding = encodingFromHeader;
522: InputStream in = new BufferedInputStream(uc
523: .getInputStream());
524: InputStreamReader reader = new InputStreamReader(in,
525: encoding);
526: char[] c = new char[1024];
527: while (true) {
528: int charsRead = reader.read(c, 0, 1024);
529: if (charsRead == -1)
530: break;
531: if (charsRead > 0)
532: this .characters(c, 0, charsRead);
533: }
534: counter2 = counter2 + 4;
535: LocationOfException.setFileLineNumber(counter2, url);
536: // System.out.println("Sql file "+url+"ima broj linija :"+counter2);
537: counter2 = 0;
538: } catch (UnsupportedEncodingException e) {
539: Logger.getCentralLogger().write("normal",
540: "Unsupported encoding: " + encoding);
541: throw new SAXException("Unsupported encoding: " + encoding,
542: e);
543: } catch (IOException e) {
544: Logger.getCentralLogger().write("normal",
545: "Document not found: " + source.toExternalForm());
546: throw new SAXException("Document not found: "
547: + source.toExternalForm(), e);
548: }
549: }
550:
551: /**
552: * <p>
553: * This utility method reads a document at a specified URL
554: * and fires off calls to various <code>DocumentHandler</code> methods.
555: * It's used to include files with <code>parse="xml"</code>
556: * </p>
557: *
558: * @param url URL of the document that will be read
559: * @throws SAXException if the requested document cannot
560: be downloaded from the specified URL.
561: */
562: private void includeXMLDocument(String url) throws SAXException {
563: File sourceXml = new File(url);
564: URL source;
565: InputStream includeXML = null;
566: // int counter3=0;
567: try {
568: source = sourceXml.toURL();
569: includeXML = source.openStream();
570: InputStreamReader isr = new InputStreamReader(includeXML);
571: BufferedReader br = new BufferedReader(isr);
572: while (br.readLine() != null)
573: counter3++;
574: counter3 = counter3 + 2;
575: LocationOfException.setFileLineNumber(counter3, url);
576: // System.out.println("xml file " + url+" ima broj linija :"+counter3);
577: counter3 = 0;
578: // LocationOfException.setJdbcNumber(counter2);
579:
580: } catch (MalformedURLException e) {
581: Logger.getCentralLogger().write("normal",
582: "Unresolvable URL :" + e.getMessage());
583: throw new SAXException("Unresolvable URL :", e);
584: } catch (IOException e) {
585: Logger.getCentralLogger().write("normal",
586: "Error in opening input stream :" + e.getMessage());
587: throw new SAXException("Error in opening input stream :", e);
588: }
589:
590: SAXParser includeParser = new SAXParser();
591: includeParser.setDocumentHandler(this );
592: includeParser.setEntityResolver(this );
593: includeParser.setErrorHandler(this );
594: try {
595: includeParser.parse(url);
596: } catch (Exception e) {
597: System.err.println(e);
598: Logger.getCentralLogger().write("normal", e.getMessage());
599: }
600: }
601:
602: }
|