blob: 2c5278362dd51e50479960238bf98a9fb6f92860 [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.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());
}
}