blob: c5e70153645fece50eea2727373fea81f0d9a236 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tuscany.sca.common.xml.dom;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import org.apache.tuscany.sca.common.xml.dom.impl.SAX2DOMAdapter;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.core.LifeCycleListener;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
/**
* Helper for DOM
*
* @version $Rev$ $Date$
* @tuscany.spi.extension.asclient
*/
public class DOMHelper implements LifeCycleListener {
protected static final int INITIAL_POOL_SIZE = 8;
protected static final int MAX_POOL_SIZE = 64;
private DocumentBuilderFactory documentBuilderFactory;
private TransformerFactory transformerFactory;
protected ParserPool<DocumentBuilder> builderPool;
protected ParserPool<Transformer> transformerPool;
public static DOMHelper getInstance(ExtensionPointRegistry registry) {
UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
return utilities.getUtility(DOMHelper.class);
}
public DOMHelper(ExtensionPointRegistry registry) {
FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
documentBuilderFactory = factories.getFactory(DocumentBuilderFactory.class);
documentBuilderFactory.setNamespaceAware(true);
transformerFactory = factories.getFactory(TransformerFactory.class);
}
/**
* @param documentBuilderFactory
* @param transformerFactory
*/
public DOMHelper(DocumentBuilderFactory documentBuilderFactory, TransformerFactory transformerFactory) {
super();
this.documentBuilderFactory = documentBuilderFactory;
this.transformerFactory = transformerFactory;
}
public Document newDocument() {
DocumentBuilder builder = newDocumentBuilder();
try {
return builder.newDocument();
} finally {
returnDocumentBuilder(builder);
}
}
public DocumentBuilder newDocumentBuilder() {
return builderPool.borrowFromPool();
}
public void returnDocumentBuilder(DocumentBuilder builder) {
builderPool.returnToPool(builder);
}
private DocumentBuilder createDocumentBuilder() {
try {
return documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new IllegalArgumentException(e);
}
}
public Document load(String xmlString) throws IOException, SAXException {
DocumentBuilder builder = newDocumentBuilder();
try {
InputSource is = new InputSource(new StringReader(xmlString));
return builder.parse(is);
} finally {
returnDocumentBuilder(builder);
}
}
public Document load(Source source) {
Transformer transformer = newTransformer();
DOMResult result = new DOMResult(newDocument());
try {
transformer.transform(source, result);
} catch (TransformerException e) {
throw new IllegalArgumentException(e);
} finally {
transformerPool.returnToPool(transformer);
}
return (Document)result.getNode();
}
public NodeContentHandler createContentHandler(Node root) {
if (root == null) {
root = newDocument();
}
return new SAX2DOMAdapter(root);
}
public String saveAsString(Node node) {
Transformer transformer = newTransformer();
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
try {
transformer.transform(new DOMSource(node), result);
} catch (TransformerException e) {
throw new IllegalArgumentException(e);
} finally {
returnTransformer(transformer);
}
return result.getWriter().toString();
}
public Transformer newTransformer() {
return transformerPool.borrowFromPool();
}
public void returnTransformer(Transformer transformer) {
transformerPool.returnToPool(transformer);
}
private Transformer createTransformer() {
Transformer transformer = null;
try {
transformer = transformerFactory.newTransformer();
} catch (TransformerConfigurationException e) {
throw new IllegalArgumentException(e);
}
return transformer;
}
public void saveAsSAX(Node node, ContentHandler contentHandler) {
Transformer transformer = transformerPool.borrowFromPool();
SAXResult result = new SAXResult(contentHandler);
try {
transformer.transform(new DOMSource(node), result);
} catch (TransformerException e) {
throw new IllegalArgumentException(e);
} finally {
returnTransformer(transformer);
}
}
public static QName getQName(Node node) {
String ns = node.getNamespaceURI();
String prefix = node.getPrefix();
String localName = node.getLocalName();
if (localName == null) {
localName = node.getNodeName();
}
if (ns == null) {
ns = "";
}
if (prefix == null) {
prefix = "";
}
return new QName(ns, localName, prefix);
}
public static Element createElement(Document document, QName name) {
String prefix = name.getPrefix();
String qname =
(prefix != null && prefix.length() > 0) ? prefix + ":" + name.getLocalPart() : name.getLocalPart();
return document.createElementNS(name.getNamespaceURI(), qname);
}
/**
* Wrap an element as a DOM document
* @param node
* @return
*/
public static Document promote(Node node) {
if (node instanceof Document) {
return (Document)node;
}
Element element = (Element)node;
Document doc = element.getOwnerDocument();
if (doc.getDocumentElement() == element) {
return doc;
}
doc = (Document)element.getOwnerDocument().cloneNode(false);
Element schema = (Element)doc.importNode(element, true);
doc.appendChild(schema);
Node parent = element.getParentNode();
while (parent instanceof Element) {
Element root = (Element)parent;
NamedNodeMap nodeMap = root.getAttributes();
for (int i = 0; i < nodeMap.getLength(); i++) {
Attr attr = (Attr)nodeMap.item(i);
String name = attr.getName();
if ("xmlns".equals(name) || name.startsWith("xmlns:")) {
if (schema.getAttributeNode(name) == null) {
schema.setAttributeNodeNS((Attr)doc.importNode(attr, true));
}
}
}
parent = parent.getParentNode();
}
return doc;
}
public static String getPrefix(Element element, String namespace) {
if (element.isDefaultNamespace(namespace)) {
return XMLConstants.DEFAULT_NS_PREFIX;
}
return element.lookupPrefix(namespace);
}
public static String getNamespaceURI(Element element, String prefix) {
if (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) {
prefix = null;
}
return element.lookupNamespaceURI(prefix);
}
public static interface NodeContentHandler extends ContentHandler, LexicalHandler {
Node getNode();
}
@Override
public void start() {
builderPool = new ParserPool<DocumentBuilder>(MAX_POOL_SIZE, INITIAL_POOL_SIZE) {
@Override
protected DocumentBuilder newInstance() {
return createDocumentBuilder();
}
@Override
protected void resetInstance(DocumentBuilder obj) {
obj.reset();
}
};
transformerPool = new ParserPool<Transformer>(64, 8) {
@Override
protected Transformer newInstance() {
return createTransformer();
}
@Override
protected void resetInstance(Transformer obj) {
obj.reset();
}
};
}
@Override
public void stop() {
builderPool.clear();
transformerPool.clear();
}
}