001: /*
002: * Util.java
003: *
004: * Copyright (c) 2004,2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.xml;
010:
011: import javax.xml.transform.*;
012: import javax.xml.transform.stream.*;
013: import javax.xml.transform.sax.*;
014: import javax.xml.transform.dom.*;
015: import javax.xml.parsers.*;
016: import java.util.*;
017: import java.beans.*;
018: import java.io.*;
019: import java.net.*;
020: import java.lang.reflect.*;
021: import org.pnuts.lib.PathHelper;
022: import pnuts.lang.*;
023: import pnuts.beans.*;
024: import org.pnuts.util.LRUCacheMap;
025: import org.xml.sax.*;
026: import org.xml.sax.ContentHandler;
027: import org.xml.sax.helpers.DefaultHandler;
028: import org.w3c.dom.Node;
029:
030: public class Util {
031:
032: private static final String DOCUMENT_BUILDER_KEY = "pnuts$xml$documentBuilderPool"
033: .intern();
034: private static final String TRANSFORMER_KEY = "pnuts$xml$transformerPool"
035: .intern();
036: private static final String SAX_PARSER_KEY = "pnuts$xml$saxParserPool"
037: .intern();
038: private final static String JAVA_ADAPTER = "javaAdapter".intern();
039: final static Object KEY_SCHEMA = new Object();
040:
041: private static final Set documentBuilderFactoryProperties = new HashSet();
042: private static final Set documentBuilderProperties = new HashSet();
043: static {
044: String[] attributes = { "coalescing", "ignoringComments",
045: "expandEntityReferences",
046: "ignoringElementContentWhitespace", "validating",
047: "namespaceAware" };
048: for (int i = 0; i < attributes.length; i++) {
049: documentBuilderFactoryProperties.add(attributes[i]);
050: }
051: documentBuilderProperties.add("entityResolver");
052: documentBuilderProperties.add("errorHandler");
053: }
054:
055: private static final Set saxParserFactoryProperties = new HashSet();
056: static {
057: saxParserFactoryProperties.add("namespaceAware");
058: saxParserFactoryProperties.add("validating");
059: }
060:
061: static SAXParser createSAXParser(Map properties, Context context)
062: throws ParserConfigurationException,
063: FactoryConfigurationError, SAXException {
064: SAXParserFactory factory = SAXParserFactory.newInstance();
065: Object schema = null;
066: if (properties != null) {
067: schema = properties.get(KEY_SCHEMA);
068: if (schema != null) {
069: setSchema(schema, factory, context);
070: }
071: try {
072: BeanUtil.setProperties(factory, properties);
073: } catch (Exception e) {
074: // skip
075: }
076: }
077: SAXParser parser = factory.newSAXParser();
078: if (schema != null) {
079: setSchema(schema, parser, context);
080: }
081: return parser;
082: }
083:
084: static Transformer getTransformer(Map outputProperties)
085: throws TransformerConfigurationException {
086: Transformer t = TransformerFactory.newInstance()
087: .newTransformer();
088: if (outputProperties != null) {
089: for (Iterator it = outputProperties.entrySet().iterator(); it
090: .hasNext();) {
091: Map.Entry entry = (Map.Entry) it.next();
092: t.setOutputProperty((String) entry.getKey(),
093: (String) entry.getValue());
094: }
095: }
096: return t;
097: }
098:
099: static DocumentBuilder createDocumentBuilder(Map properties,
100: Context context) throws ParserConfigurationException {
101: DocumentBuilderFactory factory = DocumentBuilderFactory
102: .newInstance();
103: HashMap builderProperties = new HashMap();
104: if (properties != null) {
105: for (Iterator it = properties.entrySet().iterator(); it
106: .hasNext();) {
107: Map.Entry entry = (Map.Entry) it.next();
108: Object key = entry.getKey();
109: Object value = entry.getValue();
110: if (key == KEY_SCHEMA) {
111: setSchema(value, factory, context);
112: } else if (key instanceof String) {
113: String prop = (String) key;
114: if (documentBuilderFactoryProperties.contains(prop)) {
115: try {
116: BeanUtil.setProperty(factory, prop, value);
117: } catch (IllegalAccessException ea) {
118: // skip
119: } catch (InvocationTargetException ite) {
120: // skip
121: }
122: } else if (documentBuilderProperties.contains(prop)) {
123: builderProperties.put(prop, value);
124: } else {
125: factory.setAttribute(prop, value);
126: }
127: }
128: }
129: }
130: DocumentBuilder builder = factory.newDocumentBuilder();
131: try {
132: BeanUtil.setProperties(builder, builderProperties);
133: } catch (Exception e) {
134: // skip
135: }
136: return builder;
137: }
138:
139: static synchronized LRUCacheMap createSAXParserPool(int size,
140: final Context context) {
141: LRUCacheMap map = (LRUCacheMap) context.get(SAX_PARSER_KEY);
142: if (map == null) {
143: map = new LRUCacheMap(size) {
144: protected Object construct(Object key) {
145: try {
146: return createSAXParser((Map) key, context);
147: } catch (Exception e) {
148: throw new PnutsException(e, context);
149: }
150: }
151: };
152: context.set(SAX_PARSER_KEY, map);
153: }
154: return map;
155: }
156:
157: static synchronized LRUCacheMap createTransformerPool(int size,
158: final Context context) {
159: LRUCacheMap map = (LRUCacheMap) context.get(TRANSFORMER_KEY);
160: if (map == null) {
161: map = new LRUCacheMap(size) {
162: protected Object construct(Object key) {
163: try {
164: return getTransformer((Map) key);
165: } catch (Exception e) {
166: throw new PnutsException(e, context);
167: }
168: }
169: };
170: context.set(TRANSFORMER_KEY, map);
171: }
172: return map;
173: }
174:
175: static synchronized LRUCacheMap createDocumentBuilderPool(int size,
176: final Context context) {
177: LRUCacheMap map = (LRUCacheMap) context
178: .get(DOCUMENT_BUILDER_KEY);
179: if (map == null) {
180: map = new LRUCacheMap(size) {
181: protected Object construct(Object key) {
182: try {
183: return createDocumentBuilder((Map) key, context);
184: } catch (Exception e) {
185: throw new PnutsException(e, context);
186: }
187: }
188: };
189: context.set(DOCUMENT_BUILDER_KEY, map);
190: }
191: return map;
192: }
193:
194: static InputSource inputSource(Object in, Context context)
195: throws IOException {
196: if (in instanceof InputSource) {
197: return (InputSource) in;
198: } else if (in instanceof InputStream) {
199: return new InputSource((InputStream) in);
200: } else if (in instanceof Reader) {
201: return new InputSource((Reader) in);
202: } else if (in instanceof URL) {
203: return new InputSource(((URL) in).toString());
204: } else if (in instanceof File) {
205: return new InputSource(((File) in).toURL().toString());
206: } else if (in instanceof String) {
207: return new InputSource(PathHelper.getFile((String) in,
208: context).toURL().toString());
209: } else {
210: throw new IllegalArgumentException(String.valueOf(in));
211: }
212: }
213:
214: static ContentHandler contentHandler(Object handler, Context context) {
215: if (handler instanceof ContentHandler) {
216: return (ContentHandler) handler;
217: } else {
218: PnutsFunction javaAdapter = (PnutsFunction) context
219: .resolveSymbol(JAVA_ADAPTER);
220: if (javaAdapter != null) {
221: if (handler == null) {
222: handler = new HashMap();
223: }
224: return (ContentHandler) javaAdapter.call(new Object[] {
225: DefaultHandler.class, handler }, context);
226: } else {
227: throw new PnutsException("pnuts.lib module is missing",
228: context);
229: }
230: }
231: }
232:
233: static ErrorHandler errorHandler(Object handler, Context context) {
234: if (handler instanceof ErrorHandler) {
235: return (ErrorHandler) handler;
236: } else {
237: PnutsFunction javaAdapter = (PnutsFunction) context
238: .resolveSymbol(JAVA_ADAPTER);
239: if (javaAdapter != null) {
240: if (handler == null) {
241: handler = new HashMap();
242: }
243: return (ErrorHandler) javaAdapter.call(new Object[] {
244: ErrorHandler.class, handler }, context);
245: } else {
246: throw new PnutsException("pnuts.lib module is missing",
247: context);
248: }
249: }
250: }
251:
252: static DocumentBuilder getDocumentBuilder(Map properties,
253: Context context) {
254: LRUCacheMap map = createDocumentBuilderPool(
255: Constant.DOCUMENT_BUILDER_POOLSIZE, context);
256: if (properties == null) {
257: properties = new HashMap();
258: }
259: return (DocumentBuilder) map.get(properties);
260: }
261:
262: static Transformer getTransformer(Map properties, Context context) {
263: LRUCacheMap map = Util.createTransformerPool(
264: Constant.TRANSFORMER_POOLSIZE, context);
265: if (properties == null) {
266: properties = new HashMap();
267: }
268: return (Transformer) map.get(properties);
269: }
270:
271: static SAXParser getSAXParser(Map properties, Context context) {
272: LRUCacheMap map = Util.createSAXParserPool(
273: Constant.SAX_PARSER_POOLSIZE, context);
274: if (properties == null) {
275: properties = new HashMap();
276: }
277: return (SAXParser) map.get(properties);
278: }
279:
280: static DefaultHandler getDefaultErrorHandler(Context context) {
281: return new DefaultErrorHandler(context);
282: }
283:
284: static class DefaultErrorHandler extends DefaultHandler {
285: PrintWriter stream;
286:
287: DefaultErrorHandler(Context context) {
288: stream = context.getErrorWriter();
289: }
290:
291: public void warning(SAXParseException exception) {
292: stream.println(exception);
293: }
294:
295: public void error(SAXParseException exception)
296: throws SAXException {
297: throw exception;
298: }
299:
300: public void fatalError(SAXParseException exception)
301: throws SAXException {
302: throw exception;
303: }
304: }
305:
306: static Result getResult(Object out, Context context)
307: throws IOException {
308: if (out instanceof Result) {
309: return (Result) out;
310: } else if (out instanceof Writer) {
311: return new StreamResult((Writer) out);
312: } else if (out instanceof OutputStream) {
313: return new StreamResult((OutputStream) out);
314: } else if (out instanceof File) {
315: return new StreamResult(new FileOutputStream((File) out));
316: } else if (out instanceof String) {
317: return new StreamResult(new FileOutputStream(PathHelper
318: .getFile((String) out, context)));
319: } else if (out instanceof Node) {
320: return new DOMResult((Node) out);
321: } else {
322: throw new IllegalArgumentException(String.valueOf(out));
323: }
324: }
325:
326: static Source streamSource(Object in, Context context)
327: throws IOException {
328: if (in instanceof Source) {
329: return (Source) in;
330: } else if (in instanceof Reader) {
331: return new StreamSource((Reader) in);
332: } else if (in instanceof InputStream) {
333: return new StreamSource((InputStream) in);
334: } else if (in instanceof URL) {
335: return new StreamSource(((URL) in).openStream());
336: } else if (in instanceof InputSource) {
337: return new SAXSource((InputSource) in);
338: } else if (in instanceof Node) {
339: return new DOMSource((Node) in);
340: } else if (in instanceof File) {
341: return new StreamSource(new FileInputStream((File) in));
342: } else if (in instanceof String) {
343: return new StreamSource(new FileInputStream(PathHelper
344: .getFile((String) in, context)));
345: } else {
346: throw new IllegalArgumentException(String.valueOf(in));
347: }
348: }
349:
350: static Transformer getTransformerXSL(Object xsl, Context context) {
351: try {
352: return TransformerFactory.newInstance().newTemplates(
353: streamSource(xsl, context)).newTransformer();
354: } catch (Exception e) {
355: throw new PnutsException(e, context);
356: }
357: }
358:
359: static SchemaSetter schemaSetter;
360: static {
361: try {
362: Class.forName("javax.xml.validation.Schema");
363: schemaSetter = new TigerSchemaSetter();
364: } catch (ClassNotFoundException e) {
365: schemaSetter = new DefaultSchemaSetter();
366: }
367: }
368:
369: static void setSchema(Object schema, SAXParserFactory factory,
370: Context context) {
371: schemaSetter.setSchema(schema, factory, context);
372: }
373:
374: static void setSchema(Object schema,
375: DocumentBuilderFactory factory, Context context) {
376: schemaSetter.setSchema(schema, factory, context);
377: }
378:
379: static void setSchema(Object schema, SAXParser parser,
380: Context context) {
381: schemaSetter.setSchema(schema, parser, context);
382: }
383:
384: static interface SchemaSetter {
385: void setSchema(Object schema, SAXParserFactory factory,
386: Context context);
387:
388: void setSchema(Object schema, SAXParser parser, Context context);
389:
390: void setSchema(Object schema, DocumentBuilderFactory factory,
391: Context context);
392: }
393: }
|