001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.tools.patternmetaengine;
051:
052: import javax.xml.bind.Marshaller;
053: import java.io.OutputStream;
054: import java.io.IOException;
055: import java.io.StringWriter;
056: import java.io.PrintStream;
057: import org.apache.log4j.Logger;
058: import javax.xml.bind.JAXBException;
059: import javax.xml.bind.Element;
060: import javax.xml.bind.util.ValidationEventCollector;
061: import javax.xml.bind.ValidationEvent;
062:
063: /** This contains functions that augment the capability of the JAXB Marshalling
064: * framework
065: *
066: * @author PaulE
067: */
068: public class JAXBHelper {
069: /** Set up Logging for Log4J */
070: private static Logger log = Logger.getLogger(JAXBHelper.class);
071:
072: private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
073:
074: /** This does the same job as javax.xml.bind.Marshaller.marshal(object, OutputStream)
075: * except it allows a DOCTYPE to be included in the output, so the XML can be validated
076: * using a DTD with a regular SAX parser. It also overrides the JAB generated <?xml ..?>
077: * declaration, as the DOCTYPE reference no longer makes the XML standalone!. The encoding
078: * is also set to UTF-8, the same as the JAXB default.
079: *
080: * Future enchanments could be
081: * 1) Support SYSTEM doctypes, this is only doing PUBLIC right now
082: * 2) Allow the encoding scheme to be passed in
083: * 3) Infer the root node from the XML, and remove it as an input parameter
084: * @param m Marshaller to use
085: * @param source Source Element to be Marshalled
086: * @param out OutputStream to write XML to
087: * @param rootNode Name of the root tag in the XML for the DOCTYPE declaration
088: * @param publicId Public Id for the DOCTYPE declaration
089: * @param systemId System Id for the DOCTYPE declaration
090: * @throws JAXBException Thrown if a Marshalling error occurs
091: */
092: public static void marshalWithDocType(Marshaller m, Element source,
093: OutputStream out, String rootNode, String publicId,
094: String systemId) throws /*IOException,*/JAXBException {
095:
096: // Marshal out to a string
097: StringWriter w = new StringWriter();
098: m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
099: m.marshal(source, w);
100: String unprocessed = w.toString();
101: StringBuffer processed = new StringBuffer();
102:
103: // Replace the <?xml ... ?> tag
104: FindSection s = new FindSection(unprocessed, "<?", "?>");
105: if (s.found() && s.getSection().startsWith("xml")) {
106: // Got an existing xml definition, write a new one...
107: if (s.getSectionHead() != null)
108: processed.append(s.getSectionHead());
109: unprocessed = s.getSectionTail();
110: //log.debug("Replaced XML Header");
111: } else {
112: //log.debug("Insert XML Header");
113: // No XML header, add one in!
114: }
115: processed.append(XML_HEADER);
116:
117: // Replace the <!DOCTYPE ... > tag
118: s = new FindSection(unprocessed, "<!DOCTYPE", ">");
119: if (s.found()) {
120: // Got an existing xml definition, write a new one...
121: if (s.getSectionHead() != null)
122: processed.append(s.getSectionHead());
123: unprocessed = s.getSectionTail();
124: //log.debug("Replaced DOCTYPE");
125: } else {
126: // No DOCTYPE, add one in!
127: //log.debug("Inserted DOCTYPE");
128: }
129: processed.append("<!DOCTYPE ");
130: processed.append(rootNode);
131: processed.append(" PUBLIC \"");
132: processed.append(publicId);
133: processed.append("\" \"");
134: processed.append(systemId);
135: processed.append("\">\n");
136:
137: // Add the rest of the stream in...
138: processed.append(unprocessed);
139:
140: // Now write out the string to the output stream
141: PrintStream pout = new PrintStream(out);
142: pout.print(processed.toString());
143: pout.flush();
144: pout.close();
145: }
146:
147: /** Write a JAXB Validation Error Out to the Logger
148: * @param log Logger to output errors to
149: * @param vec Validation Event Collection generated by JAXB
150: */
151: public static void showErrors(Logger log,
152: ValidationEventCollector vec) {
153: if (vec.hasEvents()) {
154: ValidationEvent[] events = vec.getEvents();
155: for (int i = 0; i < events.length; i++) {
156: ValidationEvent event = events[i];
157: String err = event.getMessage();
158: if (event.getLocator().getLineNumber() != -1)
159: err += " (" + event.getLocator().getURL() + "["
160: + event.getLocator().getLineNumber() + ":"
161: + event.getLocator().getColumnNumber()
162: + "] )";
163: if (event.getLocator().getNode() != null)
164: err += " (Node=" + event.getLocator().getNode()
165: + ")";
166: if (event.getLocator().getObject() != null)
167: err += " (Object=" + event.getLocator().getObject()
168: + ")";
169: switch (event.getSeverity()) {
170: case ValidationEvent.FATAL_ERROR:
171: log.fatal(err);
172: break;
173: case ValidationEvent.ERROR:
174: log.error(err);
175: break;
176: case ValidationEvent.WARNING:
177: log.warn(err);
178: break;
179: default:
180: log.info(err);
181: break;
182: }
183:
184: }
185: }
186:
187: }
188:
189: }
|