Java tutorial
/** * Copyright 2005-2015 Red Hat, Inc. * <p/> * Red Hat 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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 io.fabric8.camel.tooling.util; import de.pdark.decentxml.Attribute; import de.pdark.decentxml.Comment; import de.pdark.decentxml.Document; import de.pdark.decentxml.Element; import de.pdark.decentxml.Namespace; import de.pdark.decentxml.Node; import de.pdark.decentxml.NodeFilter; import de.pdark.decentxml.NodeWithChildren; import de.pdark.decentxml.Parent; import de.pdark.decentxml.Text; import de.pdark.decentxml.Token; import de.pdark.decentxml.XMLWriter; import org.apache.camel.spring.CamelEndpointFactoryBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.FileCopyUtils; import org.xml.sax.SAXException; import javax.xml.XMLConstants; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; public class CamelNamespaces { public static final String springNS = "http://camel.apache.org/schema/spring"; // All these statics are the sign, that Scala's "object" is not that excellent after all... public static final String blueprintNS = "http://camel.apache.org/schema/blueprint"; public static final String[] camelNamespaces = new String[] { springNS, blueprintNS }; public static final Namespace springNamespace = new Namespace("", "http://www.springframework.org/schema/beans"); public static final Namespace droolsNamespace = new Namespace("drools", "http://drools.org/schema/drools-spring"); public static Logger LOG = LoggerFactory.getLogger(CamelNamespaces.class); private static Schema _schema; private static Set<String> elementsWithDescription; public static Set<String> elementsWithDescription() { if (elementsWithDescription == null) { String file = "camelDescriptionElements.txt"; String text = ""; URL url = findResource(file, null); if (url != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { FileCopyUtils.copy(url.openStream(), baos); text = new String(baos.toByteArray(), "UTF-8"); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } } else { LOG.warn("Could not find file {} on the class path", file); } text += " camelContext"; String[] arr = text.split(" "); elementsWithDescription = new HashSet<String>(Arrays.asList(arr)); } return elementsWithDescription; } public static List<Node> nodesByNamespace(Document doc, final String namespaceUri, final String localName) { NodeFilter<Node> filter = new NodeFilter<Node>() { @Override public boolean matches(Node n) { if (n instanceof Element) { Namespace ns = ((Element) n).getNamespace(); // TODO this doesn't work with empty prefixes! if (!((Element) n).getName().equals(localName)) { return false; } else { String uri = getNamespaceURI(n); return ns != null;// && namespaceUri.equals(uri); // (!) } } return false; } }; return findNodes(doc, filter); } public static List<Node> findNodes(NodeWithChildren node, NodeFilter<Node> filter) { List<Node> answer = node.getNodes(filter); List<Node> children = node.getNodes(); for (Node child : children) { if (child instanceof Element) { List<Node> childMatched = findNodes((Element) child, filter); answer.addAll(childMatched); } } return answer; } public static String nodeWithNamespacesToText(Node parseNode, Element namespacesNode) throws IOException { // we need to add any namespace prefixes defined in the root directory Node copy = parseNode.copy(); if (copy instanceof Element && parseNode instanceof Element) { moveCommentsIntoDescriptionElements((Element) copy, (Element) parseNode); addParentNamespaces((Element) copy, namespacesNode.getParent()); } return xmlToText(copy); } public static void moveCommentsIntoDescriptionElements(Element e, Element root) { // lets iterate through finding all comments which are then added to a description node int idx = 0; List<Node> nodes = e.getNodes(); for (Node node : nodes.toArray(new Node[nodes.size()])) { if (node instanceof Comment) { Comment c = (Comment) node; Token token = c.getToken(); if (token != null) { String text = token.getText().trim().replace("<!--", "").replace("-->", "").trim(); Element descr = findOrCreateDescriptionOnNextElement(e, idx, root); if (descr == null) { // lets move the comment node to before the root element... LOG.warn("No description node found"); e.removeNode(c); Parent grandParent = root.getParent(); if (grandParent != null) { grandParent.addNode(grandParent.nodeIndexOf(root), c); } else { LOG.warn("Cannot save the comment '{}' as there's no parent in the DOM", text); } } else { if (descr.getNodes().size() > 0) { text = "\n" + text; } descr.addNode(new Text(text)); } } } else if (node instanceof Element) { moveCommentsIntoDescriptionElements((Element) node, root); } idx++; } } protected static Element findOrCreateDescriptionOnNextElement(Element element, int commentIndex, Parent root) { // lets find the next peer element node and if it can contain a description lets use that List<Node> nodes = element.getNodes(); Node[] array = nodes.toArray(new Node[nodes.size()]); for (int i = commentIndex + 1; i < array.length; i++) { if (array[i] instanceof Element) { if (elementsWithDescription().contains(element.getName())) { return findOrCreateDescrptionElement((Element) array[i], root); } } } return findOrCreateDescrptionElement(element, root); } protected static Element findOrCreateDescrptionElement(Element element, Parent root) { for (Node node : element.getNodes()) { if (node instanceof Element) { if ("description".equals(((Element) node).getName())) { return (Element) node; } } } Element parent = element.getParentElement(); if (element == root || parent == null || parent == root) { return null; } else if (elementsWithDescription.contains(element.getName())) { // lets check for a namespace prefix String ebn = element.getBeginName(); int idx = ebn.indexOf(":"); String name = idx > 0 ? ebn.substring(0, idx + 1) + "description" : "description"; Element description = new Element(name, element.getNamespace()); element.addNode(0, description); return description; } else { return findOrCreateDescrptionElement(parent, root); } } public static String xmlToText(Node node) throws IOException { StringWriter buffer = new StringWriter(); XMLWriter writer = new XMLWriter(buffer); node.toXML(writer); writer.close(); return buffer.toString(); } public static String getNamespaceURI(Node node) { if (node instanceof Element) { Namespace ns = ((Element) node).getNamespace(); if (ns != null) { String uri = ns.getURI(); if (uri == null || uri.length() == 0) { String uriAttr = ns.getPrefix().equals("") ? ((Element) node).getAttributeValue("xmlns") : null; if (uriAttr != null) { return uriAttr; } else { return getNamespaceURI(((Element) node).getParent()); } } else { return uri; } } } return null; } public static void addParentNamespaces(Element element, Parent parent) { if (parent instanceof Element) { for (Attribute attr : ((Element) parent).getAttributes()) { String name = attr.getName(); if (name.startsWith("xmlns") && element.getAttributeValue(name) == null) { element.setAttribute(name, attr.getValue()); } } addParentNamespaces(element, ((Element) parent).getParent()); } } public static Document getOwnerDocument(Node node) { if (node instanceof Element) { return ((Element) node).getDocument(); } else if (node instanceof Document) { return (Document) node; } return null; } public static void replaceChild(Parent parent, Node newChild, Node oldNode) { int idx = parent.nodeIndexOf(oldNode); if (idx < 0) { parent.addNode(newChild); } else { parent.removeNode(idx); parent.addNode(idx, newChild); } } public static URL findResource(String name, Iterable<ClassLoader> classLoaders) { if (classLoaders == null) { classLoaders = Arrays.asList(Thread.currentThread().getContextClassLoader(), CamelNamespaces.class.getClassLoader()); } for (ClassLoader cl : classLoaders) { URL resource = tryLoadClass(cl, name); if (resource != null) { return resource; } } return null; } private static URL tryLoadClass(ClassLoader classLoader, String name) { try { return classLoader.getResource(name); } catch (Exception e) { return null; } } private static void loadSchemas(SchemaFinder loader) throws SAXException, IOException { SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); XsdDetails[] xsds = new XsdDetails[] { new XsdDetails("camel-spring.xsd", "http://camel.apache.org/schema/spring/camel-spring.xsd", CamelEndpointFactoryBean.class), new XsdDetails("camel-blueprint.xsd", "http://camel.apache.org/schema/blueprint/camel-blueprint.xsd", org.apache.camel.blueprint.CamelEndpointFactoryBean.class) }; List<Source> sources = new ArrayList<Source>(xsds.length); for (XsdDetails xsdd : xsds) { URL url = loader.findSchema(xsdd); if (url != null) { sources.add(new StreamSource(url.openStream(), xsdd.getUri())); } else { System.out.println("Warning could not find local resource " + xsdd.getPath() + " on classpath"); sources.add(new StreamSource(xsdd.getUri())); } } _schema = factory.newSchema(sources.toArray(new Source[sources.size()])); } public static Schema camelSchemas() throws IOException, SAXException { if (_schema == null) { loadSchemas(new SchemaFinder() { @Override public URL findSchema(XsdDetails details) { return details.getClassLoader().getResource(details.getPath()); } }); } return _schema; } public void loadSchemasWith(final SchemaFinder finder) throws IOException, SAXException { loadSchemas(new SchemaFinder() { @Override public URL findSchema(XsdDetails xsd) { return finder.findSchema(xsd); } }); } }