summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom')
-rw-r--r--sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/DOMHelper.java302
-rw-r--r--sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/ParserPool.java102
-rw-r--r--sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/impl/SAX2DOMAdapter.java244
3 files changed, 648 insertions, 0 deletions
diff --git a/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/DOMHelper.java b/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/DOMHelper.java
new file mode 100644
index 0000000000..c5e7015364
--- /dev/null
+++ b/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/DOMHelper.java
@@ -0,0 +1,302 @@
+/*
+ * 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();
+ }
+
+}
diff --git a/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/ParserPool.java b/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/ParserPool.java
new file mode 100644
index 0000000000..e8187d481d
--- /dev/null
+++ b/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/ParserPool.java
@@ -0,0 +1,102 @@
+/*
+ * 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.util.IdentityHashMap;
+import java.util.Map;
+
+public abstract class ParserPool<V> {
+ private int maxSize;
+ private Map<V, Boolean> objects;
+
+ public ParserPool() {
+ this(32, 0);
+ }
+
+ public ParserPool(int maxSize, int initialSize) {
+ super();
+ this.maxSize = maxSize;
+ this.objects = new IdentityHashMap<V, Boolean>(maxSize);
+ for (int i = 0; i < Math.min(initialSize, maxSize); i++) {
+ objects.put(newInstance(), Boolean.FALSE);
+ }
+ }
+
+ public synchronized V borrowFromPool() {
+ while (true) {
+ for (Map.Entry<V, Boolean> e : objects.entrySet()) {
+ if (Boolean.FALSE.equals(e.getValue())) {
+ // setValue fails on some Harmony based JDKs, see https://issues.apache.org/jira/browse/HARMONY-6419
+ //e.setValue(Boolean.TRUE); // in use
+ V key = e.getKey();
+ objects.put(key, Boolean.TRUE); // in use
+ return key;
+ }
+ }
+ if (objects.size() < maxSize) {
+ V obj = newInstance();
+ objects.put(obj, Boolean.TRUE);
+ return obj;
+ }
+ try {
+ wait();
+ } catch (InterruptedException e1) {
+ throw new IllegalStateException(e1);
+ }
+ }
+ }
+
+ public synchronized void returnToPool(V obj) {
+ resetInstance(obj);
+ objects.put(obj, Boolean.FALSE);
+ notifyAll();
+ }
+
+ public synchronized void clear() {
+ objects.clear();
+ }
+
+ public synchronized int inUse() {
+ int size = 0;
+ for (Map.Entry<V, Boolean> e : objects.entrySet()) {
+ if (Boolean.TRUE.equals(e.getValue())) {
+ size++;
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Create a new instance
+ * @return
+ */
+ protected abstract V newInstance();
+
+ /**
+ * Reset the instance before returning to the pool
+ * @param obj
+ */
+ protected abstract void resetInstance(V obj);
+
+ // Expose it for testing purpose
+ public Map<V, Boolean> getObjects() {
+ return objects;
+ }
+}
diff --git a/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/impl/SAX2DOMAdapter.java b/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/impl/SAX2DOMAdapter.java
new file mode 100644
index 0000000000..11d692c81e
--- /dev/null
+++ b/sca-java-2.x/branches/2.0/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/dom/impl/SAX2DOMAdapter.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed 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.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import org.apache.tuscany.sca.common.xml.dom.DOMHelper;
+import org.apache.tuscany.sca.common.xml.dom.DOMHelper.NodeContentHandler;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * SAX2DOM adapter
+ *
+ * @version $Rev$ $Date$
+ */
+public class SAX2DOMAdapter implements DOMHelper.NodeContentHandler {
+ public static final String EMPTYSTRING = "";
+ public static final String XML_PREFIX = "xml";
+ public static final String XMLNS_PREFIX = "xmlns";
+ public static final String XMLNS_STRING = "xmlns:";
+ public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+
+ private Node root;
+
+ private Document document;
+
+ private Node nextSibling;
+
+ private Stack<Node> nodeStk = new Stack<Node>();
+
+ private List<String> namespaceDecls;
+
+ private Node lastSibling;
+
+ public SAX2DOMAdapter(ExtensionPointRegistry registry) {
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ DOMHelper domHelper = utilities.getUtility(DOMHelper.class);
+ this.document = domHelper.newDocument();
+ this.root = document;
+ }
+
+ public SAX2DOMAdapter(Node root, Node nextSibling) {
+ this.root = root;
+ if (root instanceof Document) {
+ this.document = (Document)root;
+ } else if (root != null) {
+ this.document = root.getOwnerDocument();
+ }
+
+ this.nextSibling = nextSibling;
+ }
+
+ public SAX2DOMAdapter(Node root) {
+ this(root, null);
+ }
+
+ public Node getNode() {
+ return root;
+ }
+
+ public void characters(char[] ch, int start, int length) {
+ final Node last = nodeStk.peek();
+
+ // No text nodes can be children of root (DOM006 exception)
+ if (last != document) {
+ final String text = new String(ch, start, length);
+ if (lastSibling != null && lastSibling.getNodeType() == Node.TEXT_NODE) {
+ ((Text)lastSibling).appendData(text);
+ } else if (last == root && nextSibling != null) {
+ lastSibling = last.insertBefore(document.createTextNode(text), nextSibling);
+ } else {
+ lastSibling = last.appendChild(document.createTextNode(text));
+ }
+
+ }
+ }
+
+ public void startDocument() {
+ nodeStk.push(root);
+ }
+
+ public void endDocument() {
+ nodeStk.pop();
+ }
+
+ public void startElement(String namespace, String localName, String qName, Attributes attrs) {
+ final Element tmp = document.createElementNS(namespace, qName);
+
+ // Add namespace declarations first
+ if (namespaceDecls != null) {
+ final int nDecls = namespaceDecls.size();
+ for (int i = 0; i < nDecls; i++) {
+ final String prefix = namespaceDecls.get(i++);
+
+ if (prefix == null || prefix.equals(EMPTYSTRING)) {
+ tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX, namespaceDecls.get(i));
+ } else {
+ tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, namespaceDecls.get(i));
+ }
+ }
+ namespaceDecls.clear();
+ }
+
+ // Add attributes to element
+ final int nattrs = attrs.getLength();
+ for (int i = 0; i < nattrs; i++) {
+ if (attrs.getLocalName(i) == null) {
+ tmp.setAttribute(attrs.getQName(i), attrs.getValue(i));
+ } else {
+ tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), attrs.getValue(i));
+ }
+ }
+
+ // Append this new node onto current stack node
+ Node last = nodeStk.peek();
+
+ // If the SAX2DOM is created with a non-null next sibling node,
+ // insert the result nodes before the next sibling under the root.
+ if (last == root && nextSibling != null) {
+ last.insertBefore(tmp, nextSibling);
+ } else {
+ last.appendChild(tmp);
+ }
+
+ // Push this node onto stack
+ nodeStk.push(tmp);
+ lastSibling = null;
+ }
+
+ public void endElement(String namespace, String localName, String qName) {
+ nodeStk.pop();
+ lastSibling = null;
+ }
+
+ public void startPrefixMapping(String prefix, String uri) {
+ if (namespaceDecls == null) {
+ namespaceDecls = new ArrayList<String>(2);
+ }
+ namespaceDecls.add(prefix);
+ namespaceDecls.add(uri);
+ }
+
+ public void endPrefixMapping(String prefix) {
+ // do nothing
+ }
+
+ /**
+ * This class is only used internally so this method should never be called.
+ */
+ public void ignorableWhitespace(char[] ch, int start, int length) {
+ }
+
+ /**
+ * adds processing instruction node to DOM.
+ */
+ public void processingInstruction(String target, String data) {
+ final Node last = nodeStk.peek();
+ ProcessingInstruction pi = document.createProcessingInstruction(target, data);
+ if (pi != null) {
+ if (last == root && nextSibling != null) {
+ last.insertBefore(pi, nextSibling);
+ } else {
+ last.appendChild(pi);
+ }
+
+ lastSibling = pi;
+ }
+ }
+
+ /**
+ * This class is only used internally so this method should never be called.
+ */
+ public void setDocumentLocator(Locator locator) {
+ }
+
+ /**
+ * This class is only used internally so this method should never be called.
+ */
+ public void skippedEntity(String name) {
+ }
+
+ /**
+ * Lexical Handler method to create comment node in DOM tree.
+ */
+ public void comment(char[] ch, int start, int length) {
+ final Node last = nodeStk.peek();
+ Comment comment = document.createComment(new String(ch, start, length));
+ if (comment != null) {
+ if (last == root && nextSibling != null) {
+ last.insertBefore(comment, nextSibling);
+ } else {
+ last.appendChild(comment);
+ }
+
+ lastSibling = comment;
+ }
+ }
+
+ // Lexical Handler methods- not implemented
+ public void startCDATA() {
+ }
+
+ public void endCDATA() {
+ }
+
+ public void startEntity(java.lang.String name) {
+ }
+
+ public void endDTD() {
+ }
+
+ public void endEntity(String name) {
+ }
+
+ public void startDTD(String name, String publicId, String systemId) throws SAXException {
+ }
+
+}