You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2013/01/09 11:18:47 UTC

svn commit: r1430764 - in /aries/trunk/blueprint/blueprint-noosgi/src: main/java/org/apache/aries/blueprint/container/ main/java/org/apache/aries/blueprint/ext/ main/java/org/apache/aries/blueprint/ext/impl/ main/java/org/apache/aries/blueprint/service...

Author: gnodet
Date: Wed Jan  9 10:18:46 2013
New Revision: 1430764

URL: http://svn.apache.org/viewvc?rev=1430764&view=rev
Log:
[ARIES-998] Add support for classpath:xxx on the property placeholder

Added:
    aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/PropertyPlaceholder.java
    aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/impl/
    aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java
    aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.properties
Modified:
    aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
    aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.java
    aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java
    aries/trunk/blueprint/blueprint-noosgi/src/test/java/org.apache.aries.blueprint/BlueprintContainerTest.java
    aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.xml

Modified: aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java?rev=1430764&r1=1430763&r2=1430764&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java (original)
+++ aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java Wed Jan  9 10:18:46 2013
@@ -26,6 +26,7 @@ import org.apache.aries.blueprint.di.Rep
 import org.apache.aries.blueprint.parser.ComponentDefinitionRegistryImpl;
 import org.apache.aries.blueprint.parser.Parser;
 import org.apache.aries.blueprint.reflect.MetadataUtil;
+import org.apache.aries.blueprint.reflect.PassThroughMetadataImpl;
 import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
 import org.osgi.service.blueprint.container.ComponentDefinitionException;
 import org.osgi.service.blueprint.container.Converter;
@@ -84,6 +85,8 @@ public class BlueprintContainerImpl impl
         if (unsupported.size() > 0) {
             throw new IllegalArgumentException("Unsupported namespaces: " + unsupported.toString());
         }
+        // Add predefined beans
+        componentDefinitionRegistry.registerComponentDefinition(new PassThroughMetadataImpl("blueprintContainer", this));
         // Validate
         parser.validate(handlerSet.getSchema());
         // Populate
@@ -113,6 +116,10 @@ public class BlueprintContainerImpl impl
         return loader.loadClass(name);
     }
 
+    public URL getResource(String name) {
+        return loader.getResource(name);
+    }
+
     public AccessControlContext getAccessControlContext() {
         return null;
     }

Modified: aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.java?rev=1430764&r1=1430763&r2=1430764&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.java (original)
+++ aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.java Wed Jan  9 10:18:46 2013
@@ -34,6 +34,7 @@ import org.apache.aries.blueprint.mutabl
 import org.apache.aries.blueprint.mutable.MutableMapEntry;
 import org.apache.aries.blueprint.mutable.MutableMapMetadata;
 import org.apache.aries.blueprint.mutable.MutablePropsMetadata;
+import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
 import org.osgi.service.blueprint.container.ComponentDefinitionException;
 import org.osgi.service.blueprint.reflect.BeanArgument;
 import org.osgi.service.blueprint.reflect.BeanMetadata;
@@ -58,6 +59,7 @@ public abstract class AbstractPropertyPl
 
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPropertyPlaceholder.class);
 
+    private ExtendedBlueprintContainer blueprintContainer;
     private String placeholderPrefix = "${";
     private String placeholderSuffix = "}";
     private Pattern pattern;
@@ -80,6 +82,14 @@ public abstract class AbstractPropertyPl
         this.placeholderSuffix = placeholderSuffix;
     }
 
+    public ExtendedBlueprintContainer getBlueprintContainer() {
+        return blueprintContainer;
+    }
+
+    public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
+        this.blueprintContainer = blueprintContainer;
+    }
+
     public void process(ComponentDefinitionRegistry registry) throws ComponentDefinitionException {
         try {
             for (String name : registry.getComponentDefinitionNames()) {

Added: aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/PropertyPlaceholder.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/PropertyPlaceholder.java?rev=1430764&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/PropertyPlaceholder.java (added)
+++ aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/PropertyPlaceholder.java Wed Jan  9 10:18:46 2013
@@ -0,0 +1,208 @@
+/**
+ * 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.aries.blueprint.ext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.aries.blueprint.ext.evaluator.PropertyEvaluator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Property placeholder that looks for properties in the System properties.
+ *
+ * @version $Rev$, $Date$
+ */
+public class PropertyPlaceholder extends AbstractPropertyPlaceholder {
+
+    public enum SystemProperties {
+        never,
+        fallback,
+        override
+    }
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PropertyPlaceholder.class);
+
+    private Map defaultProperties;
+    private Properties properties;
+    private List<String> locations;
+    private boolean ignoreMissingLocations;
+    private SystemProperties systemProperties = SystemProperties.fallback;
+    private PropertyEvaluator evaluator = null;
+
+    public Map getDefaultProperties() {
+        return defaultProperties;
+    }
+
+    public void setDefaultProperties(Map defaultProperties) {
+        this.defaultProperties = defaultProperties;
+    }
+
+    public List<String> getLocations() {
+        return locations;
+    }
+
+    public void setLocations(List<String> locations) {
+        this.locations = locations;
+    }
+
+    public boolean isIgnoreMissingLocations() {
+        return ignoreMissingLocations;
+    }
+
+    public void setIgnoreMissingLocations(boolean ignoreMissingLocations) {
+        this.ignoreMissingLocations = ignoreMissingLocations;
+    }
+
+    public SystemProperties getSystemProperties() {
+        return systemProperties;
+    }
+
+    public void setSystemProperties(SystemProperties systemProperties) {
+        this.systemProperties = systemProperties;
+    }
+
+    public PropertyEvaluator getEvaluator() {
+        return evaluator;
+    }
+
+    public void setEvaluator(PropertyEvaluator evaluator) {
+        this.evaluator = evaluator;
+    }
+
+    public void init() throws Exception {
+        properties = new Properties();
+        if (locations != null) {
+            for (String url : locations) {
+                InputStream is = null;
+                try {
+                    if (url.startsWith("classpath:")) {
+                        is = getBlueprintContainer().getResource(url.substring("classpath:".length())).openStream();
+                    } else {
+                        is = new URL(url).openStream();
+                    }
+                } catch (IOException e) {
+                    if (ignoreMissingLocations) {
+                        LOGGER.debug("Unable to load properties from url " + url + " while ignoreMissingLocations is set to true");
+                    } else {
+                        throw e;
+                    }
+                }
+                if (is != null) {
+                    try {
+                        properties.load(is);
+                    } finally {
+                        is.close();
+                    }
+                }
+            }
+        }
+    }
+
+    protected String getProperty(String val) {
+        LOGGER.debug("Retrieving property {}", val);
+        Object v = null;
+        if (v == null && systemProperties == SystemProperties.override) {
+            v = System.getProperty(val);
+            if (v != null) {
+                LOGGER.debug("Found system property {} with value {}", val, v);
+            }
+        }
+        if (v == null && properties != null) {
+            v = properties.getProperty(val);
+            if (v != null) {
+                LOGGER.debug("Found property {} from locations with value {}", val, v);
+            }
+        }
+        if (v == null && systemProperties == SystemProperties.fallback) {
+            v = System.getProperty(val);
+            if (v != null) {
+                LOGGER.debug("Found system property {} with value {}", val, v);
+            }
+        }
+        if (v == null && defaultProperties != null) {
+            v = defaultProperties.get(val);
+            if (v != null) {
+                LOGGER.debug("Retrieved property {} value from defaults {}", val, v);
+            }
+        }
+        if (v == null) {
+            LOGGER.debug("Property {} not found", val);
+        }
+        return v != null ? v.toString() : null;
+    }
+
+    @Override
+    protected String retrieveValue(String expression) {
+        LOGGER.debug("Retrieving Value from expression: {}", expression);
+
+        if (evaluator == null) {
+            return super.retrieveValue(expression);
+        } else {
+            return evaluator.evaluate(expression, new Dictionary<String, String>(){
+                @Override
+                public String get(Object key) {
+                    return getProperty((String) key);
+                }
+
+                // following are not important
+                @Override
+                public String put(String key, String value) {
+                    throw new UnsupportedOperationException();
+                }
+
+                @Override
+                public Enumeration<String> elements() {
+                    throw new UnsupportedOperationException();
+                }
+
+                @Override
+                public boolean isEmpty() {
+                    throw new UnsupportedOperationException();
+                }
+
+                @Override
+                public Enumeration<String> keys() {
+                    throw new UnsupportedOperationException();
+                }
+
+                @Override
+                public String remove(Object key) {
+                    throw new UnsupportedOperationException();
+                }
+
+                @Override
+                public int size() {
+                    throw new UnsupportedOperationException();
+                }
+
+            });
+        }
+
+    }
+
+
+}

Added: aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java?rev=1430764&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java (added)
+++ aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java Wed Jan  9 10:18:46 2013
@@ -0,0 +1,361 @@
+/**
+ * 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.aries.blueprint.ext.impl;
+
+import org.apache.aries.blueprint.ExtendedReferenceListMetadata;
+import org.apache.aries.blueprint.ParserContext;
+import org.apache.aries.blueprint.ext.PlaceholdersUtils;
+import org.apache.aries.blueprint.ext.PropertyPlaceholder;
+import org.apache.aries.blueprint.ext.evaluator.PropertyEvaluator;
+import org.apache.aries.blueprint.mutable.*;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+import org.osgi.service.blueprint.reflect.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.*;
+import org.w3c.dom.CharacterData;
+
+import java.net.URL;
+import java.util.*;
+
+/**
+ * A namespace handler for Aries blueprint extensions
+ *
+ * @version $Rev$, $Date$
+ */
+public class ExtNamespaceHandler implements org.apache.aries.blueprint.NamespaceHandler {
+
+    public static final String BLUEPRINT_NAMESPACE = "http://www.osgi.org/xmlns/blueprint/v1.0.0";
+    public static final String BLUEPRINT_EXT_NAMESPACE_V1_0 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0";
+    public static final String BLUEPRINT_EXT_NAMESPACE_V1_1 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.1.0";
+    public static final String BLUEPRINT_EXT_NAMESPACE_V1_2 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0";
+    
+    public static final String PROPERTY_PLACEHOLDER_ELEMENT = "property-placeholder";
+    public static final String DEFAULT_PROPERTIES_ELEMENT = "default-properties";
+    public static final String PROPERTY_ELEMENT = "property";
+    public static final String VALUE_ELEMENT = "value";
+    public static final String LOCATION_ELEMENT = "location";
+
+    public static final String ID_ATTRIBUTE = "id";
+    public static final String PLACEHOLDER_PREFIX_ATTRIBUTE = "placeholder-prefix";
+    public static final String PLACEHOLDER_SUFFIX_ATTRIBUTE = "placeholder-suffix";
+    public static final String DEFAULTS_REF_ATTRIBUTE = "defaults-ref";
+    public static final String IGNORE_MISSING_LOCATIONS_ATTRIBUTE = "ignore-missing-locations";
+    public static final String EVALUATOR_ATTRIBUTE = "evaluator";
+
+    public static final String SYSTEM_PROPERTIES_ATTRIBUTE = "system-properties";
+    public static final String SYSTEM_PROPERTIES_NEVER = "never";
+    public static final String SYSTEM_PROPERTIES_FALLBACK = "fallback";
+    public static final String SYSTEM_PROPERTIES_OVERRIDE = "override";
+
+    public static final String PROXY_METHOD_ATTRIBUTE = "proxy-method";
+    public static final String PROXY_METHOD_DEFAULT = "default";
+    public static final String PROXY_METHOD_CLASSES = "classes";
+    public static final String PROXY_METHOD_GREEDY = "greedy";
+
+    public static final String ROLE_ATTRIBUTE = "role";
+    public static final String ROLE_PROCESSOR = "processor";
+    
+    public static final String FIELD_INJECTION_ATTRIBUTE = "field-injection";
+    
+    public static final String DEFAULT_REFERENCE_BEAN = "default";
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ExtNamespaceHandler.class);
+
+    private int idCounter;
+    
+    public URL getSchemaLocation(String namespace) {
+        if (BLUEPRINT_EXT_NAMESPACE_V1_0.equals(namespace)) {
+          return getClass().getResource("blueprint-ext.xsd");
+        } else if (BLUEPRINT_EXT_NAMESPACE_V1_1.equals(namespace)) {
+          return getClass().getResource("blueprint-ext-1.1.xsd");
+        } else if (BLUEPRINT_EXT_NAMESPACE_V1_2.equals(namespace)) {
+          return getClass().getResource("blueprint-ext-1.2.xsd");
+        } else {
+          return null;
+        }
+    }
+
+    public Set<Class> getManagedClasses() {
+        return new HashSet<Class>(Arrays.asList(
+                PropertyPlaceholder.class
+        ));
+    }
+
+    public Metadata parse(Element element, ParserContext context) {
+        LOGGER.debug("Parsing element {{}}{}", element.getNamespaceURI(), element.getLocalName());
+        if (nodeNameEquals(element, PROPERTY_PLACEHOLDER_ELEMENT)) {
+            return parsePropertyPlaceholder(context, element);
+        } else {
+            throw new ComponentDefinitionException("Unsupported element: " + element.getNodeName());
+        }
+    }
+
+    public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) {
+        if (node instanceof Attr && nodeNameEquals(node, PROXY_METHOD_ATTRIBUTE)) {
+            return decorateProxyMethod(node, component, context);
+        } else if (node instanceof Attr && nodeNameEquals(node, ROLE_ATTRIBUTE)) {
+            return decorateRole(node, component, context);
+        } else if (node instanceof Attr && nodeNameEquals(node, FIELD_INJECTION_ATTRIBUTE)) {
+            return decorateFieldInjection(node, component, context);
+        } else if (node instanceof Attr && nodeNameEquals(node, DEFAULT_REFERENCE_BEAN)) {
+            return decorateDefaultBean(node, component, context);
+        } else {
+            throw new ComponentDefinitionException("Unsupported node: " + node.getNodeName());
+        }
+    }
+    
+    private ComponentMetadata decorateDefaultBean(Node node,
+        ComponentMetadata component, ParserContext context) 
+    {
+        if (!(component instanceof ReferenceMetadata)) {
+            throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <reference> element");
+        }
+      
+        if (!(component instanceof MutableReferenceMetadata)) {
+            throw new ComponentDefinitionException("Expected an instanceof MutableReferenceMetadata");
+        }
+        
+        String value = ((Attr) node).getValue();
+        ((MutableReferenceMetadata) component).setDefaultBean(value);
+        return component;
+    }
+
+    private ComponentMetadata decorateFieldInjection(Node node, ComponentMetadata component, ParserContext context) {
+        if (!(component instanceof BeanMetadata)) {
+            throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <bean> element");
+        }
+        
+        if (!(component instanceof MutableBeanMetadata)) {
+            throw new ComponentDefinitionException("Expected an instanceof MutableBeanMetadata");
+        }
+        
+        String value = ((Attr) node).getValue();
+        ((MutableBeanMetadata) component).setFieldInjection("true".equals(value) || "1".equals(value));
+        return component;
+    }
+
+    private ComponentMetadata decorateRole(Node node, ComponentMetadata component, ParserContext context) {
+        if (!(component instanceof BeanMetadata)) {
+            throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <bean> element");
+        }
+        if (!(component instanceof MutableBeanMetadata)) {
+            throw new ComponentDefinitionException("Expected an instance of MutableBeanMetadata");
+        }
+        boolean processor = false;
+        String value = ((Attr) node).getValue();
+        String[] flags = value.trim().split(" ");
+        for (String flag : flags) {
+            if (ROLE_PROCESSOR.equals(flag)) {
+                processor = true;
+            } else {
+                throw new ComponentDefinitionException("Unknown proxy method: " + flag);
+            }
+        }
+        ((MutableBeanMetadata) component).setProcessor(processor);
+        return component;
+    }
+
+    private ComponentMetadata decorateProxyMethod(Node node, ComponentMetadata component, ParserContext context) {
+        if (!(component instanceof ServiceReferenceMetadata)) {
+            throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <reference> or <reference-list> element");
+        }
+        if (!(component instanceof MutableServiceReferenceMetadata)) {
+            throw new ComponentDefinitionException("Expected an instance of MutableServiceReferenceMetadata");
+        }
+        int method = 0;
+        String value = ((Attr) node).getValue();
+        String[] flags = value.trim().split(" ");
+        for (String flag : flags) {
+            if (PROXY_METHOD_DEFAULT.equals(flag)) {
+                method += ExtendedReferenceListMetadata.PROXY_METHOD_DEFAULT;
+            } else if (PROXY_METHOD_CLASSES.equals(flag)) {
+                method += ExtendedReferenceListMetadata.PROXY_METHOD_CLASSES;
+            } else if (PROXY_METHOD_GREEDY.equals(flag)) {
+                method += ExtendedReferenceListMetadata.PROXY_METHOD_GREEDY;
+            } else {
+                throw new ComponentDefinitionException("Unknown proxy method: " + flag);
+            }
+        }
+        if ((method & ExtendedReferenceListMetadata.PROXY_METHOD_GREEDY) != 0 && !(component instanceof ReferenceListMetadata)) {
+            throw new ComponentDefinitionException("Greedy proxying is only available for <reference-list> element");
+        }
+        ((MutableServiceReferenceMetadata) component).setProxyMethod(method);
+        return component;
+    }
+
+    private Metadata parsePropertyPlaceholder(ParserContext context, Element element) {
+        MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
+        metadata.setProcessor(true);
+        metadata.setId(getId(context, element));
+        metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
+        metadata.setRuntimeClass(PropertyPlaceholder.class);
+        metadata.setInitMethod("init");
+        String prefix = element.hasAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
+                                    ? element.getAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
+                                    : "${";
+        metadata.addProperty("placeholderPrefix", createValue(context, prefix));
+        String suffix = element.hasAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
+                                    ? element.getAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
+                                    : "}";
+        metadata.addProperty("placeholderSuffix", createValue(context, suffix));
+        metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
+        String defaultsRef = element.hasAttribute(DEFAULTS_REF_ATTRIBUTE) ? element.getAttribute(DEFAULTS_REF_ATTRIBUTE) : null;
+        if (defaultsRef != null) {
+            metadata.addProperty("defaultProperties", createRef(context, defaultsRef));
+        }
+        String ignoreMissingLocations = element.hasAttribute(IGNORE_MISSING_LOCATIONS_ATTRIBUTE) ? element.getAttribute(IGNORE_MISSING_LOCATIONS_ATTRIBUTE) : null;
+        if (ignoreMissingLocations != null) {
+            metadata.addProperty("ignoreMissingLocations", createValue(context, ignoreMissingLocations));
+        }
+        String systemProperties = element.hasAttribute(SYSTEM_PROPERTIES_ATTRIBUTE) ? element.getAttribute(SYSTEM_PROPERTIES_ATTRIBUTE) : null;
+        if (systemProperties != null) {
+            metadata.addProperty("systemProperties", createValue(context, systemProperties));
+        }
+        String evaluator = element.hasAttribute(EVALUATOR_ATTRIBUTE) ? element.getAttribute(EVALUATOR_ATTRIBUTE) : null;
+        if (evaluator != null) {
+            throw new IllegalStateException("Evaluators are not supported outside OSGi");
+        }
+        // Parse elements
+        List<String> locations = new ArrayList<String>();
+        NodeList nl = element.getChildNodes();
+        for (int i = 0; i < nl.getLength(); i++) {
+            Node node = nl.item(i);
+            if (node instanceof Element) {
+                Element e = (Element) node;
+                if (BLUEPRINT_EXT_NAMESPACE_V1_0.equals(e.getNamespaceURI())
+                        || BLUEPRINT_EXT_NAMESPACE_V1_1.equals(e.getNamespaceURI())
+                        || BLUEPRINT_EXT_NAMESPACE_V1_2.equals(e.getNamespaceURI())) {
+                    if (nodeNameEquals(e, DEFAULT_PROPERTIES_ELEMENT)) {
+                        if (defaultsRef != null) {
+                            throw new ComponentDefinitionException("Only one of " + DEFAULTS_REF_ATTRIBUTE + " attribute or " + DEFAULT_PROPERTIES_ELEMENT + " element is allowed");
+                        }
+                        Metadata props = parseDefaultProperties(context, metadata, e);
+                        metadata.addProperty("defaultProperties", props);
+                    } else if (nodeNameEquals(e, LOCATION_ELEMENT)) {
+                        locations.add(getTextValue(e));
+                    }
+                }
+            }
+        }
+        if (!locations.isEmpty()) {
+            metadata.addProperty("locations", createList(context, locations));
+        }
+
+        PlaceholdersUtils.validatePlaceholder(metadata, context.getComponentDefinitionRegistry());
+
+        return metadata;
+    }
+
+    private Metadata parseDefaultProperties(ParserContext context, MutableBeanMetadata enclosingComponent, Element element) {
+        MutableMapMetadata props = context.createMetadata(MutableMapMetadata.class);
+        NodeList nl = element.getChildNodes();
+        for (int i = 0; i < nl.getLength(); i++) {
+            Node node = nl.item(i);
+            if (node instanceof Element) {
+                Element e = (Element) node;
+                if (BLUEPRINT_EXT_NAMESPACE_V1_0.equals(e.getNamespaceURI())
+                        || BLUEPRINT_EXT_NAMESPACE_V1_1.equals(e.getNamespaceURI())
+                        || BLUEPRINT_EXT_NAMESPACE_V1_2.equals(e.getNamespaceURI())) {
+                    if (nodeNameEquals(e, PROPERTY_ELEMENT)) {
+                        BeanProperty prop = context.parseElement(BeanProperty.class, enclosingComponent, e);
+                        props.addEntry(createValue(context, prop.getName(), String.class.getName()), prop.getValue());
+                    }
+                }
+            }
+        }
+        return props;
+    }
+
+    public String getId(ParserContext context, Element element) {
+        if (element.hasAttribute(ID_ATTRIBUTE)) {
+            return element.getAttribute(ID_ATTRIBUTE);
+        } else {
+            return generateId(context);
+        }
+    }
+
+    public void generateIdIfNeeded(ParserContext context, MutableComponentMetadata metadata) {
+        if (metadata.getId() == null) {
+            metadata.setId(generateId(context));
+        }
+    }
+
+    private String generateId(ParserContext context) {
+        String id;
+        do {
+            id = ".ext-" + ++idCounter;
+        } while (context.getComponentDefinitionRegistry().containsComponentDefinition(id));
+        return id;
+    }
+
+    private static ValueMetadata createValue(ParserContext context, String value) {
+        return createValue(context, value, null);
+    }
+
+    private static ValueMetadata createValue(ParserContext context, String value, String type) {
+        MutableValueMetadata m = context.createMetadata(MutableValueMetadata.class);
+        m.setStringValue(value);
+        m.setType(type);
+        return m;
+    }
+
+    private static RefMetadata createRef(ParserContext context, String value) {
+        MutableRefMetadata m = context.createMetadata(MutableRefMetadata.class);
+        m.setComponentId(value);
+        return m;
+    }
+
+    private static IdRefMetadata createIdRef(ParserContext context, String value) {
+        MutableIdRefMetadata m = context.createMetadata(MutableIdRefMetadata.class);
+        m.setComponentId(value);
+        return m;
+    }
+    
+    private static CollectionMetadata createList(ParserContext context, List<String> list) {
+        MutableCollectionMetadata m = context.createMetadata(MutableCollectionMetadata.class);
+        m.setCollectionClass(List.class);
+        m.setValueType(String.class.getName());
+        for (String v : list) {
+            m.addValue(createValue(context, v, String.class.getName()));
+        }
+        return m;
+    }
+
+    private static String getTextValue(Element element) {
+        StringBuffer value = new StringBuffer();
+        NodeList nl = element.getChildNodes();
+        for (int i = 0; i < nl.getLength(); i++) {
+            Node item = nl.item(i);
+            if ((item instanceof CharacterData && !(item instanceof Comment)) || item instanceof EntityReference) {
+                value.append(item.getNodeValue());
+            }
+        }
+        return value.toString();
+    }
+
+    private static boolean nodeNameEquals(Node node, String name) {
+        return (name.equals(node.getNodeName()) || name.equals(node.getLocalName()));
+    }
+
+    public static boolean isBlueprintNamespace(String ns) {
+        return BLUEPRINT_NAMESPACE.equals(ns);
+    }
+
+}

Modified: aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java?rev=1430764&r1=1430763&r2=1430764&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java (original)
+++ aries/trunk/blueprint/blueprint-noosgi/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java Wed Jan  9 10:18:46 2013
@@ -23,6 +23,7 @@ import org.apache.aries.blueprint.Proces
 import org.osgi.service.blueprint.container.BlueprintContainer;
 import org.osgi.service.blueprint.container.Converter;
 
+import java.net.URL;
 import java.security.AccessControlContext;
 import java.util.List;
 
@@ -32,6 +33,8 @@ public interface ExtendedBlueprintContai
 
     Class loadClass(String name) throws ClassNotFoundException;
 
+    URL getResource(String name);
+
     AccessControlContext getAccessControlContext();
 
     ComponentDefinitionRegistry getComponentDefinitionRegistry();

Modified: aries/trunk/blueprint/blueprint-noosgi/src/test/java/org.apache.aries.blueprint/BlueprintContainerTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-noosgi/src/test/java/org.apache.aries.blueprint/BlueprintContainerTest.java?rev=1430764&r1=1430763&r2=1430764&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-noosgi/src/test/java/org.apache.aries.blueprint/BlueprintContainerTest.java (original)
+++ aries/trunk/blueprint/blueprint-noosgi/src/test/java/org.apache.aries.blueprint/BlueprintContainerTest.java Wed Jan  9 10:18:46 2013
@@ -35,9 +35,10 @@ public class BlueprintContainerTest {
         BlueprintContainerImpl container = new BlueprintContainerImpl(getClass().getClassLoader(), Arrays.asList(url));
 
         Foo foo = (Foo) container.getComponentInstance("foo");
+        System.out.println(foo);
         assertNotNull(foo);
         assertEquals(5, foo.getA());
-        assertEquals(-1, foo.getB());
+        assertEquals(1, foo.getB());
 
         container.destroy();
     }

Added: aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.properties
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.properties?rev=1430764&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.properties (added)
+++ aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.properties Wed Jan  9 10:18:46 2013
@@ -0,0 +1 @@
+key.b=1

Modified: aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.xml
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.xml?rev=1430764&r1=1430763&r2=1430764&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.xml (original)
+++ aries/trunk/blueprint/blueprint-noosgi/src/test/resources/test.xml Wed Jan  9 10:18:46 2013
@@ -38,6 +38,7 @@
             <ext:property name="key.b" value="-1" />
         </ext:default-properties>
         <ext:location>file:///url</ext:location>
+        <ext:location>classpath:test.properties</ext:location>
     </ext:property-placeholder>
 
     <bean id="foo" class="org.apache.aries.blueprint.sample.Foo"