/* * 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.felix.ipojo.manipulator.metadata.annotation.visitor; import org.apache.felix.ipojo.manipulator.Reporter; import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench; import org.apache.felix.ipojo.metadata.Attribute; import org.apache.felix.ipojo.metadata.Element; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Opcodes; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; /** * Parse the @HandlerDeclaration annotation. * @see org.apache.felix.ipojo.annotations.HandlerDeclaration * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> */ public class HandlerDeclarationVisitor extends AnnotationVisitor { /** * XML accepted by the handler. */ private String m_value; private DocumentBuilder builder; private ComponentWorkbench workbench; private Reporter reporter; public HandlerDeclarationVisitor(ComponentWorkbench workbench, DocumentBuilder builder, Reporter reporter) { super(Opcodes.ASM5); this.workbench = workbench; this.builder = builder; this.reporter = reporter; } /** * Parses the value attribute. * @param name 'value' * @param value the value * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object) */ public void visit(String name, Object value) { // there is only a 'value' attribute this.m_value = (String) value; } /** * End of the visit. * Builds the XML document. * @see org.objectweb.asm.AnnotationVisitor#visitEnd() */ public void visitEnd() { // The value is an XML document InputStream is = new ByteArrayInputStream(m_value.getBytes()); Document document = null; try { document = builder.parse(is); Element e = convertDOMElements(document.getDocumentElement()); workbench.getElements().put(e, null); } catch (Exception e) { reporter.warn("Cannot convert {} to iPOJO Elements.", m_value, e); } finally { try { is.close(); } catch (IOException e) { reporter.trace("Cannot close correctly the value input stream ({}).", m_value, e); } } } /** * Converts recursively the given XML Element into an iPOJO Element. * @param xmlElement DOM Element to be converted */ private static Element convertDOMElements(final org.w3c.dom.Element xmlElement) { // Create an equivalent iPOJO element Element converted = transformElement(xmlElement); convertDOMElements(converted, xmlElement); return converted; } /** * Converts recursively the given XML Element into an iPOJO Element. * @param root iPOJO root Element * @param xmlElement DOM Element to be converted */ private static void convertDOMElements(final Element root, final org.w3c.dom.Element xmlElement) { // Convert attributes if any if (xmlElement.hasAttributes()) { NamedNodeMap attributes = xmlElement.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Attr attr = (Attr) attributes.item(i); if (!"xmlns".equals(attr.getPrefix())) { root.addAttribute(transformAttribute(attr)); } } } // Convert child elements if any if (xmlElement.hasChildNodes()) { NodeList children = xmlElement.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { // Create an equivalent iPOJO element org.w3c.dom.Element child = (org.w3c.dom.Element) children.item(i); Element converted = transformElement(child); // Add converted element as a root's child root.addElement(converted); // Recursive call convertDOMElements(converted, child); } } } private static Attribute transformAttribute(Attr attr) { return new Attribute(attr.getLocalName(), attr.getNamespaceURI(), attr.getValue()); } private static Element transformElement(org.w3c.dom.Element xmlElement) { return new Element(xmlElement.getLocalName(), xmlElement.getNamespaceURI()); } }