001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005: package com.sun.portal.rewriter.util.xml;
006:
007: import com.sun.portal.rewriter.rom.InvalidXMLException;
008: import com.sun.portal.rewriter.util.Constants;
009: import com.sun.portal.rewriter.util.Debug;
010: import com.sun.portal.rewriter.util.Resource;
011: import com.sun.portal.rewriter.util.StringHelper;
012: import com.sun.portal.rewriter.util.uri.URI;
013:
014: import org.w3c.dom.NodeList;
015: import org.xml.sax.InputSource;
016: import org.xml.sax.SAXException;
017: import org.xml.sax.SAXParseException;
018: import org.xml.sax.helpers.DefaultHandler;
019:
020: import javax.xml.parsers.DocumentBuilder;
021: import javax.xml.parsers.DocumentBuilderFactory;
022: import javax.xml.parsers.ParserConfigurationException;
023: import java.io.ByteArrayInputStream;
024: import java.io.StringReader;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: /**
029: * wrapper to w3c XML Document object
030: *
031: * @version 1.0 12/15/2001
032: * @author Raja Nagendra Kumar, Nagendra.Raja@sun.com
033: */
034: public final class Document {
035: private org.w3c.dom.Document w3cDocument;
036:
037: public Document(final org.w3c.dom.Document aDocument) {
038: w3cDocument = aDocument;
039: }//constructor
040:
041: public Node getRootNode() {
042: return new Node(w3cDocument.getDocumentElement());
043: }//getRootNode()
044:
045: public static String parseEncoding(final String aXMLData) {
046: String result = System.getProperty("file.encoding");
047:
048: String lHeadder = parseHeadder(aXMLData);
049: if (lHeadder.length() != 0) {
050: Tag lTag = TagParser.parse(lHeadder.substring(2, lHeadder
051: .length() - 2));
052:
053: if (lTag.getName().equalsIgnoreCase("xml")) {
054: String encoding = lTag.get("encoding");
055: if (encoding != null) {
056: result = encoding;
057: }
058: }
059: }
060: //default to system file encoding
061: return result;
062: }//parseEncoding()
063:
064: public static String parseEncoding(final byte[] aXMLData) {
065: //first line <xml?.. is always be valid in all encoding except the symboles font etc..
066: return parseEncoding(new String(aXMLData));
067: }//parseEncoding()
068:
069: public static String parseHeadder(String aXMLData) {
070: aXMLData = StringHelper.normalize(aXMLData);
071: int i = aXMLData.indexOf("<?");
072: int j = aXMLData.indexOf("?>");
073: if (i != -1 && j != -1) {
074: return aXMLData.substring(i, j + 2);
075: }
076:
077: return "";
078: }//parseHeadder()
079:
080: public static Document create(final byte[] aXMLBytes)
081: throws Exception {
082: return create(aXMLBytes, true, true);
083: }//create()
084:
085: public static Document create(final byte[] aXMLBytes,
086: final boolean aDTDCheck, final boolean aNSAware)
087: throws Exception {
088: if (aXMLBytes.length == 0) {
089: throw new InvalidXMLException(
090: "Key May not exist in the Store or Zero length XML Bytes supplied ",
091: new String(aXMLBytes), null,
092: InvalidXMLException.KEY_DOES_NOT_EXIST);
093: }
094:
095: DocumentBuilder lDBuilder = getXMLBuilder(aDTDCheck, aNSAware,
096: true);
097:
098: org.w3c.dom.Document lDocument = lDBuilder
099: .parse(new InputSource(new ByteArrayInputStream(
100: aXMLBytes)));
101:
102: return new Document(lDocument);
103: }//create()
104:
105: public static Document create(final String aXMLString)
106: throws Exception {
107: return create(aXMLString, true, true, true);
108: }//create()
109:
110: public static Document create(final String aXMLString,
111: final boolean aDTDCheck, final boolean aNSAware,
112: final boolean aExpandEntities) throws Exception {
113: final String check = StringHelper.normalize(aXMLString);
114:
115: if (check.length() < 1) {
116: throw new InvalidXMLException(
117: "Key May not exist in the Store or null XML String supplied ",
118: aXMLString, null,
119: InvalidXMLException.KEY_DOES_NOT_EXIST);
120: }
121:
122: DocumentBuilder lDBuilder = getXMLBuilder(aDTDCheck, aNSAware,
123: aExpandEntities);
124: org.w3c.dom.Document lDocument = lDBuilder
125: .parse(new InputSource(new StringReader(aXMLString
126: .toString())));
127: return new Document(lDocument);
128: }//create()
129:
130: private static DocumentBuilder getXMLBuilder(
131: final boolean aDTDCheck, final boolean aNSAware,
132: final boolean aExpandEntities)
133: throws ParserConfigurationException {
134: final DocumentBuilderFactory lDBFactory = DocumentBuilderFactory
135: .newInstance();
136: lDBFactory.setNamespaceAware(aNSAware);
137: lDBFactory.setValidating(aDTDCheck);
138: lDBFactory.setExpandEntityReferences(aExpandEntities);//BugNo:4778676, 4837830
139:
140: /*
141: http://xml.org/sax/features/external-general-entities,
142: http://xml.org/sax/features/external-parameter-entities,
143: http://apache.org/xml/features/dom/create-entity-ref-nodes
144: lDBFactory.setAttribute( "http://apache.org/xml/features/nonvalidating/load-dtd-grammar",
145: Boolean.FALSE );
146: lDBFactory.setAttribute( "http://apache.org/xml/features/nonvalidating/load-external-dtd",
147: Boolean.FALSE );
148: */
149:
150: final DocumentBuilder lDBuilder = lDBFactory
151: .newDocumentBuilder();
152:
153: final DefaultHandler customHandler = new CustomErrorHandler();
154: lDBuilder.setErrorHandler(customHandler);
155: lDBuilder.setEntityResolver(customHandler);
156: return lDBuilder;
157: }//getXMLBuilder()
158:
159: /**
160: * XPath array should be of length 4 and element 0 will
161: * allways contain RULESET
162: */
163: public static Node[] selectNodes(final Document aDocument,
164: String aXPath) {
165: aXPath = aXPath.trim();
166: String[] arrayPath;
167: if (aXPath.startsWith("\\")) {
168: arrayPath = StringHelper.tokenize(aXPath.substring(2),
169: "\\", true);
170: if ((aDocument != null) && (aDocument.w3cDocument != null)) {
171: org.w3c.dom.Document w3cDocument = aDocument.w3cDocument;
172: List lNodes = new ArrayList();
173: NodeList nodeList = w3cDocument
174: .getElementsByTagName(arrayPath[arrayPath.length - 1]);
175: for (int i = 0; i < nodeList.getLength(); i++) {
176: org.w3c.dom.Node childNode = nodeList.item(i);
177: org.w3c.dom.Node parentNode;
178: for (int j = arrayPath.length - 2; j >= 0; j--) {
179: parentNode = childNode.getParentNode();
180: if (parentNode.getNodeName().equals(
181: arrayPath[j])) {
182: if (j != 0) {
183: childNode = parentNode;
184: } else //if ( j == 0 )
185: {
186: lNodes.add(new Node(nodeList.item(i)));
187: }
188: }
189: }
190: }
191: if (lNodes.size() > 0) {
192: return (Node[]) lNodes
193: .toArray(Constants.EMPTY_NODE_ARRAY);
194: }
195: }//if (document)
196: } else {
197: //Debug.error( "bug - in Document.java" );
198: Debug.error("PSRW_CSPR_0036");
199: //write later
200: }
201:
202: return Constants.EMPTY_NODE_ARRAY;
203: }//selectNodes()
204:
205: public static void main(String[] args) throws Exception {
206: create(Resource.read(args[0]));
207: }//main()
208:
209: private static class CustomErrorHandler extends DefaultHandler {
210: /**
211: * Returns a string describing parse exception details
212: */
213: private String getParseExceptionInfo(final SAXParseException spe) {
214: String systemId = spe.getSystemId();
215: if (systemId == null) {
216: systemId = "null";
217: }
218:
219: final String info = "URI = " + systemId + " Line = "
220: + spe.getLineNumber() + ": " + spe.getMessage();
221: return info;
222: }//getParseExceptionInfo()
223:
224: public void fatalError(final SAXParseException spe)
225: throws SAXException {
226: final String message = "Fatal Error: "
227: + getParseExceptionInfo(spe);
228: doRest(message, spe);
229: }//fatalError()
230:
231: public void error(final SAXParseException spe)
232: throws SAXException {
233: final String message = "Error: "
234: + getParseExceptionInfo(spe);
235: doRest(message, spe);
236: }//error()
237:
238: public void warning(final SAXParseException spe)
239: throws SAXException {
240: final String message = "Warning: "
241: + getParseExceptionInfo(spe);
242: doRest(message, spe);
243: }//warning()
244:
245: private void doRest(final String aMsg,
246: final SAXException aException) throws SAXException {
247: Debug.warning(aMsg, aException);
248: throw aException;
249: }//doRest()
250:
251: public InputSource resolveEntity(final String aPublicID,
252: final String aSystemID) {
253: if (aSystemID != null
254: && StringHelper.startsWithIgnoreCase(aSystemID,
255: "jar://")) {
256: try {
257: String resourcePath = StringHelper
258: .normalize(new URI(aSystemID).getPath());
259: //check if the path does exist
260: if (resourcePath.length() != 0) {
261: String dtdValue = StringHelper
262: .normalize(Resource.read(resourcePath));
263: //check if the dtd file content is of zero length
264: if (dtdValue.length() != 0) {
265: if (Debug.isMessageEnabled()) {
266: Debug.message(" System ID: "
267: + aSystemID + "Public ID: "
268: + aPublicID);
269: Object[] param = { aSystemID, aPublicID };
270: Debug.message("PSRW_CSPR_0037", param);
271: }
272:
273: return new InputSource(new StringReader(
274: dtdValue));
275: }
276: }
277: } catch (Exception e) {
278: if (Debug.isMessageEnabled()) {
279: //Debug.warning( "Error while reading the DTD..", e );
280: Debug.warning("PSRW_CSPR_0038", e);
281: }
282: }
283: }
284:
285: // use the default behaviour
286: return null;
287: }//resolveEntity()
288: }//class CustomErrorHandler
289:
290: }//class Document
|