001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.aspectwerkz.definition;
005:
006: import org.w3c.dom.Document;
007: import org.xml.sax.EntityResolver;
008: import org.xml.sax.InputSource;
009: import org.xml.sax.SAXException;
010:
011: import com.tc.aspectwerkz.exception.WrappedRuntimeException;
012:
013: import java.io.IOException;
014: import java.io.InputStream;
015: import java.io.StringReader;
016: import java.net.URL;
017: import java.util.Set;
018:
019: import javax.xml.parsers.DocumentBuilder;
020: import javax.xml.parsers.DocumentBuilderFactory;
021: import javax.xml.parsers.ParserConfigurationException;
022:
023: /**
024: * Parses the XML definition file using <tt>dom4j</tt>.
025: *
026: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
027: */
028: public class XmlParser {
029: /**
030: * The current DTD public id. The matching dtd will be searched as a resource.
031: */
032: private final static String DTD_PUBLIC_ID = "-//AspectWerkz//DTD 2.0//EN";
033:
034: /**
035: * The DTD alias, for better user experience.
036: */
037: private final static String DTD_PUBLIC_ID_ALIAS = "-//AspectWerkz//DTD//EN";
038:
039: /**
040: * A handler to the DTD stream so that we are only using one file descriptor
041: */
042: private final static URL DTD_URL = XmlParser.class
043: .getResource("/aspectwerkz2.dtd");
044:
045: /**
046: * The AspectWerkz definitions.
047: */
048: private static Set s_definitions = null;
049:
050: /**
051: * Parses the XML definition file not using the cache.
052: *
053: * @param loader the current class loader
054: * @param url the URL to the definition file
055: * @return the definition object
056: */
057: public static Set parseNoCache(final ClassLoader loader,
058: final URL url) {
059: try {
060: // XXX: AspectJ aop.xml parsing is done like this:
061: // Definition definition = DocumentParser.parse(url);
062: // System.out.println("------------------> " + definition);
063:
064: s_definitions = DocumentParser.parse(loader,
065: createDocument(url));
066: return s_definitions;
067: } catch (Exception e) {
068: throw new WrappedRuntimeException(e);
069: }
070: }
071:
072: /**
073: * Merges two DOM documents.
074: *
075: * @param document1 the first document
076: * @param document2 the second document
077: * @return the definition merged document
078: */
079: // public static Document mergeDocuments(final Document document1, final Document document2) {
080: // if ((document2 == null) && (document1 != null)) {
081: // return document1;
082: // }
083: // if ((document1 == null) && (document2 != null)) {
084: // return document2;
085: // }
086: // if ((document1 == null) && (document2 == null)) {
087: // return null;
088: // }
089: // try {
090: // Element root1 = document1.getRootElement();
091: // Element root2 = document2.getRootElement();
092: // for (Iterator it1 = root2.elementIterator(); it1.hasNext();) {
093: // Element element = (Element) it1.next();
094: // element.setParent(null);
095: // root1.add(element);
096: // }
097: // } catch (Exception e) {
098: // throw new WrappedRuntimeException(e);
099: // }
100: // return document1;
101: // }
102: /**
103: * Creates a DOM document.
104: *
105: * @param url the URL to the file containing the XML
106: * @return the DOM document
107: *
108: * @throws IOException
109: * @throws SAXException
110: * @throws ParserConfigurationException
111: */
112: public static Document createDocument(final URL url)
113: throws IOException {
114: InputStream in = null;
115: try {
116: in = url.openStream();
117: return createDocument(new InputSource(in));
118: } finally {
119: try {
120: in.close();
121: } catch (Throwable t) {
122: // ignore
123: }
124: }
125: }
126:
127: /**
128: * Creates a DOM document.
129: *
130: * @param string the string containing the XML
131: * @return the DOM document
132: * @throws DocumentException
133: */
134: public static Document createDocument(final String string)
135: throws IOException {
136: return createDocument(new InputSource(new StringReader(string)));
137: }
138:
139: public static Document createDocument(InputSource in)
140: throws IOException {
141: try {
142: DocumentBuilderFactory factory = DocumentBuilderFactory
143: .newInstance();
144: DocumentBuilder builder = factory.newDocumentBuilder();
145: builder.setEntityResolver(getEntityResolver());
146: return builder.parse(in);
147: } catch (SAXException e) {
148: throw new IOException(e.toString());
149: } catch (ParserConfigurationException e) {
150: throw new IOException(e.toString());
151: }
152: }
153:
154: /**
155: * Sets the entity resolver which is created based on the DTD from in the root dir of the AspectWerkz distribution.
156: *
157: * @param reader the reader to set the resolver in
158: */
159: private static EntityResolver getEntityResolver() {
160: return new EntityResolver() {
161: public InputSource resolveEntity(String publicId,
162: String systemId) {
163: if (publicId.equals(DTD_PUBLIC_ID)
164: || publicId.equals(DTD_PUBLIC_ID_ALIAS)) {
165: try {
166: InputStream in = DTD_URL.openStream();
167: if (in != null)
168: return new InputSource(in);
169: } catch (IOException ioex) {
170: }
171: System.err
172: .println("AspectWerkz - WARN - could not open DTD");
173: return new InputSource(); // avoid null pointer exception }
174: } else {
175: System.err
176: .println("AspectWerkz - WARN - deprecated DTD "
177: + publicId
178: + " - consider upgrading to "
179: + DTD_PUBLIC_ID);
180: return new InputSource(); // avoid null pointer exception
181: }
182: }
183: };
184: }
185: }
|