001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.xbean.blueprint.context.impl; 018 019 import java.beans.PropertyDescriptor; 020 import java.util.List; 021 022 import javax.xml.namespace.QName; 023 import org.apache.aries.blueprint.ParserContext; 024 import org.apache.aries.blueprint.mutable.MutableBeanMetadata; 025 import org.apache.aries.blueprint.mutable.MutableCollectionMetadata; 026 import org.apache.aries.blueprint.mutable.MutableValueMetadata; 027 import org.apache.commons.logging.Log; 028 import org.apache.commons.logging.LogFactory; 029 import org.osgi.service.blueprint.reflect.BeanProperty; 030 import org.osgi.service.blueprint.reflect.CollectionMetadata; 031 import org.osgi.service.blueprint.reflect.Metadata; 032 import org.osgi.service.blueprint.reflect.ValueMetadata; 033 import org.w3c.dom.Element; 034 import org.w3c.dom.Node; 035 036 /** 037 * 038 * @version $Revision: 1.1 $ 039 */ 040 public class QNameHelper { 041 private static final Log log = LogFactory.getLog(QNameHelper.class); 042 043 public static Metadata createQNameMetadata(Element element, String qualifiedName, ParserContext parserContext) { 044 MutableBeanMetadata beanMetadata = parserContext.createMetadata(MutableBeanMetadata.class); 045 beanMetadata.setClassName(QName.class.getName()); 046 int index = qualifiedName.indexOf(':'); 047 if (index >= 0) { 048 String prefix = qualifiedName.substring(0, index); 049 String localName = qualifiedName.substring(index + 1); 050 String uri = recursiveGetAttributeValue(element, "xmlns:" + prefix); 051 beanMetadata.addArgument(valueMetadata(uri, parserContext), String.class.getName(), 0); 052 beanMetadata.addArgument(valueMetadata(localName, parserContext), String.class.getName(), 1); 053 beanMetadata.addArgument(valueMetadata(prefix, parserContext), String.class.getName(), 2); 054 } 055 else { 056 String uri = recursiveGetAttributeValue(element, "xmlns"); 057 if (uri != null) { 058 beanMetadata.addArgument(valueMetadata(uri, parserContext), String.class.getName(), 0); 059 beanMetadata.addArgument(valueMetadata(qualifiedName, parserContext), String.class.getName(), 1); 060 } else { 061 beanMetadata.addArgument(valueMetadata(qualifiedName, parserContext), String.class.getName(), 0); 062 } 063 } 064 return beanMetadata; 065 } 066 067 private static Metadata valueMetadata(String stringValue, ParserContext parserContext) { 068 MutableValueMetadata value = parserContext.createMetadata(MutableValueMetadata.class); 069 value.setStringValue(stringValue); 070 return value; 071 } 072 073 /** 074 * Recursive method to find a given attribute value in an element or its parents (towards root of dom tree) 075 * @param element element to start searching for attribute in 076 * @param attributeName name of desired attribute 077 * @return value of found attribute 078 */ 079 public static String recursiveGetAttributeValue(Element element, String attributeName) { 080 String answer = null; 081 try { 082 answer = element.getAttribute(attributeName); 083 } 084 catch (Exception e) { 085 if (log.isTraceEnabled()) { 086 log.trace("Caught exception looking up attribute: " + attributeName + " on element: " + element + ". Cause: " + e, e); 087 } 088 } 089 if (answer == null || answer.length() == 0) { 090 Node parentNode = element.getParentNode(); 091 if (parentNode instanceof Element) { 092 return recursiveGetAttributeValue((Element) parentNode, attributeName); 093 } 094 } 095 return answer; 096 } 097 098 public static void coerceNamespaceAwarePropertyValues(MutableBeanMetadata bd, Element element, PropertyDescriptor descriptor, ParserContext parserContext) { 099 // When the property is an indexed property, the getPropertyType can return null. 100 if (descriptor.getPropertyType() == null) { 101 return; 102 } 103 if (descriptor.getPropertyType().isAssignableFrom(QName.class)) { 104 String name = descriptor.getName(); 105 BeanProperty propertyValue = XBeanNamespaceHandler.propertyByName(name, bd); 106 if (propertyValue != null) { 107 Metadata value = propertyValue.getValue(); 108 if (value instanceof ValueMetadata) { 109 bd.removeProperty(propertyValue); 110 Metadata valueMetadata = createQNameMetadata(element, ((ValueMetadata)value).getStringValue(), parserContext); 111 bd.addProperty(name, valueMetadata); 112 } 113 //else?? 114 } 115 } else if (descriptor.getPropertyType().isAssignableFrom(QName[].class)) { 116 String name = descriptor.getName(); 117 BeanProperty propertyValue = XBeanNamespaceHandler.propertyByName(name, bd); 118 if (propertyValue != null) { 119 Object value = propertyValue.getValue(); 120 if (value instanceof CollectionMetadata) { 121 List<Metadata> values = ((CollectionMetadata) value).getValues(); 122 MutableCollectionMetadata newValue = parserContext.createMetadata(MutableCollectionMetadata.class); 123 124 for (Metadata v : values) { 125 if (v instanceof ValueMetadata) { 126 newValue.addValue(createQNameMetadata(element, ((ValueMetadata)v).getStringValue(), parserContext)); 127 } else { 128 newValue.addValue(v); 129 } 130 } 131 bd.removeProperty(propertyValue); 132 bd.addProperty(name, newValue); 133 } 134 } 135 } 136 } 137 138 }