You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by an...@apache.org on 2010/07/24 08:43:15 UTC

svn commit: r978812 - in /tuscany/sca-java-2.x/branches/2.0-Beta1: ./ modules/assembly-xml/ modules/assembly-xml/META-INF/ modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ modules/builder/src/main/java/org/apache/tuscany/sca/buil...

Author: antelder
Date: Sat Jul 24 06:43:15 2010
New Revision: 978812

URL: http://svn.apache.org/viewvc?rev=978812&view=rev
Log:
Merge r966650,966653,966658,966714 from trunk to beta1 branch for property source and writing fixes

Modified:
    tuscany/sca-java-2.x/branches/2.0-Beta1/   (props changed)
    tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/META-INF/MANIFEST.MF
    tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/pom.xml
    tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java
    tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java
    tuscany/sca-java-2.x/branches/2.0-Beta1/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/ComponentBuilderImpl.java

Propchange: tuscany/sca-java-2.x/branches/2.0-Beta1/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Jul 24 06:43:15 2010
@@ -1 +1 @@
-/tuscany/sca-java-2.x/trunk:966568,966629
+/tuscany/sca-java-2.x/trunk:966568,966629,966650-966658,966714

Modified: tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/META-INF/MANIFEST.MF?rev=978812&r1=978811&r2=978812&view=diff
==============================================================================
--- tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/META-INF/MANIFEST.MF (original)
+++ tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/META-INF/MANIFEST.MF Sat Jul 24 06:43:15 2010
@@ -38,7 +38,7 @@ Bundle-License: http://www.apache.org/li
 Bundle-Description: Apache Tuscany SCA XML Assembly Model
 Import-Package: javax.xml.namespace,
  javax.xml.parsers,
- javax.xml.stream,
+ javax.xml.stream;version="1.0.0",
  javax.xml.transform,
  javax.xml.transform.dom,
  javax.xml.transform.stream,
@@ -47,6 +47,7 @@ Import-Package: javax.xml.namespace,
  org.apache.tuscany.sca.assembly;version="2.0.0",
  org.apache.tuscany.sca.assembly.xml;version="2.0.0",
  org.apache.tuscany.sca.common.java.io;version="2.0.0",
+ org.apache.tuscany.sca.common.xml.stax;version="2.0.0",
  org.apache.tuscany.sca.common.xml.xpath;version="2.0.0",
  org.apache.tuscany.sca.contribution;version="2.0.0",
  org.apache.tuscany.sca.contribution.java;version="2.0.0",

Modified: tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/pom.xml
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/pom.xml?rev=978812&r1=978811&r2=978812&view=diff
==============================================================================
--- tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/pom.xml (original)
+++ tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/pom.xml Sat Jul 24 06:43:15 2010
@@ -45,6 +45,12 @@
             <groupId>org.apache.tuscany.sca</groupId>
             <artifactId>tuscany-xsd</artifactId>
             <version>2.0-Beta1-SNAPSHOT</version>
+        </dependency>    
+             
+        <dependency>
+            <groupId>org.apache.tuscany.sca</groupId>
+            <artifactId>tuscany-common-xml</artifactId>
+            <version>2.0-SNAPSHOT</version>
         </dependency>         
 
         <!-- 

Modified: tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java?rev=978812&r1=978811&r2=978812&view=diff
==============================================================================
--- tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java (original)
+++ tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java Sat Jul 24 06:43:15 2010
@@ -409,7 +409,7 @@ abstract class BaseAssemblyProcessor ext
      * @param element
      * @param type
      * @param reader
-     * @param context TODO
+     * @param context
      * @return
      * @throws XMLStreamException
      * @throws ContributionReadException

Modified: tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java?rev=978812&r1=978811&r2=978812&view=diff
==============================================================================
--- tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java (original)
+++ tuscany/sca-java-2.x/branches/2.0-Beta1/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java Sat Jul 24 06:43:15 2010
@@ -66,10 +66,12 @@ import java.util.List;
 import java.util.StringTokenizer;
 
 import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.dom.DOMSource;
 import javax.xml.xpath.XPathExpressionException;
 
 import org.apache.tuscany.sca.assembly.Binding;
@@ -87,6 +89,7 @@ import org.apache.tuscany.sca.assembly.P
 import org.apache.tuscany.sca.assembly.Reference;
 import org.apache.tuscany.sca.assembly.Service;
 import org.apache.tuscany.sca.assembly.Wire;
+import org.apache.tuscany.sca.common.xml.stax.StAXHelper;
 import org.apache.tuscany.sca.common.xml.xpath.XPathHelper;
 import org.apache.tuscany.sca.contribution.Artifact;
 import org.apache.tuscany.sca.contribution.Contribution;
@@ -111,6 +114,8 @@ import org.apache.tuscany.sca.policy.Pol
 import org.apache.tuscany.sca.xsd.XSDFactory;
 import org.apache.tuscany.sca.xsd.XSDefinition;
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * A composite processor.
@@ -123,6 +128,8 @@ public class CompositeProcessor extends 
     private StAXAttributeProcessor<Object> extensionAttributeProcessor;
     private ContributionFactory contributionFactory;
     private XSDFactory xsdFactory;
+    
+    private StAXHelper staxHelper;
 
     /**
      * Construct a new composite processor
@@ -140,6 +147,9 @@ public class CompositeProcessor extends 
         this.extensionAttributeProcessor = extensionAttributeProcessor;
         
         this.xsdFactory = extensionPoints.getExtensionPoint(XSDFactory.class);
+        
+        // 
+        staxHelper = StAXHelper.getInstance(extensionPoints);
     }
 
     /**
@@ -354,23 +364,11 @@ public class CompositeProcessor extends 
                                 }
                                 componentProperty.setSource(source);
                                 if (source != null) {
-                                    // $<name>/...
-                                    if (source.charAt(0) == '$') {
-                                        int index = source.indexOf('/');
-                                        if (index == -1) {
-                                            // Tolerating $prop
-                                            source = "";
-                                        } else {
-                                            source = source.substring(index + 1);
-                                        }
-                                        if ("".equals(source)) {
-                                            source = ".";
-                                        }
-                                    }
-
+                                	String xPath = prepareSourceXPathString( source );
+                                    
                                     try {
                                         componentProperty.setSourceXPathExpression(xpathHelper.compile(reader
-                                            .getNamespaceContext(), source));
+                                            .getNamespaceContext(), xPath));
                                     } catch (XPathExpressionException e) {
                                         ContributionReadException ce = new ContributionReadException(e);
                                         error(monitor, "ContributionReadException", source, ce);
@@ -648,6 +646,51 @@ public class CompositeProcessor extends 
 
         return composite;
     }
+    
+    /**
+     * Prepares the property @source XPath expression
+     * 
+     * The form of the @source attribute in the composite file must take one of the forms
+     *   $propertyName
+     *   $propertyName/expression
+     *   $propertyName[n]
+     *   $propertyName[n]/expression
+     * Property values are stored as <sca:property> elements with one or more <sca:value> subelements or one or more
+     * global element subelements. The XPath constructed is designed to work against this XML structure and aims to
+     * retrieve one or more of the subelements or subportions of those subelements (eg some text content).
+     * Thus the XPath:
+     * - starts with "*", which means "all the child elements of the root" where root = the <property/> element
+     * - may then be followed by [xxx] (typically [n] to select one of the child elements) if the source string has [xxx]
+     *   following the propertyName
+     * - may then be followed by /expression, if the source contains an expression, which will typically select some subportion
+     *   of the child element(s)
+     * 
+     * @param source - the @source attribute string from a <sca:property> element
+     * @return the XPath string to use for the source property
+     */
+    private String prepareSourceXPathString( String source ) {
+    	String output = null;
+    	// Expression must begin with '$'
+    	if( source.charAt(0) != '$' ) return output;
+    	
+        int slash = source.indexOf('/');
+        int bracket = source.indexOf('[');
+        if (slash == -1) {
+            // Form is $propertyName or $propertyName[n]
+            output = "*";
+            if( bracket != -1 ) {
+            	output = "*" + source.substring(bracket);
+            }
+        } else {
+        	// Form is $propertyName/exp or $propertyName[n]/exp
+            output = "*/" + source.substring(slash + 1);
+            if( bracket != -1 && bracket < slash ) {
+            	output = "*"  + source.substring(bracket);
+            }
+        } // end if
+        
+    	return output;
+    } // end method prepareSourceXPathString( source )
 
     public void write(Composite composite, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException,
         XMLStreamException {
@@ -1088,6 +1131,77 @@ public class CompositeProcessor extends 
     public Class<Composite> getModelType() {
         return Composite.class;
     }
+    
+    /**
+     * Write the value of a property - override to use correct method of creating an XMLStreamReader
+     * @param document
+     * @param element
+     * @param type
+     * @param writer
+     * @throws XMLStreamException
+     */
+    @Override
+    protected void writePropertyValue(Object propertyValue, QName element, QName type, XMLStreamWriter writer)
+        throws XMLStreamException {
+
+        if (propertyValue instanceof Document) {
+            Document document = (Document)propertyValue;
+            NodeList nodeList = document.getDocumentElement().getChildNodes();
+
+            for (int item = 0; item < nodeList.getLength(); ++item) {
+                Node node = nodeList.item(item);
+                int nodeType = node.getNodeType();
+                if (nodeType == Node.ELEMENT_NODE) {
+                	// Correct way to create a reader for a node object...
+                	XMLStreamReader reader = staxHelper.createXMLStreamReader(node);
+
+                    while (reader.hasNext()) {
+                        switch (reader.next()) {
+                            case XMLStreamConstants.START_ELEMENT:
+                                QName name = reader.getName();
+                                writer.writeStartElement(name.getPrefix(), name.getLocalPart(), name.getNamespaceURI());
+
+                                int namespaces = reader.getNamespaceCount();
+                                for (int i = 0; i < namespaces; i++) {
+                                    String prefix = reader.getNamespacePrefix(i);
+                                    String ns = reader.getNamespaceURI(i);
+                                    writer.writeNamespace(prefix, ns);
+                                }
+
+                                if (!"".equals(name.getNamespaceURI())) {
+                                    writer.writeNamespace(name.getPrefix(), name.getNamespaceURI());
+                                }
+
+                                // add the attributes for this element
+                                namespaces = reader.getAttributeCount();
+                                for (int i = 0; i < namespaces; i++) {
+                                    String ns = reader.getAttributeNamespace(i);
+                                    String prefix = reader.getAttributePrefix(i);
+                                    String qname = reader.getAttributeLocalName(i);
+                                    String value = reader.getAttributeValue(i);
+
+                                    writer.writeAttribute(prefix, ns, qname, value);
+                                }
+
+                                break;
+                            case XMLStreamConstants.CDATA:
+                                writer.writeCData(reader.getText());
+                                break;
+                            case XMLStreamConstants.CHARACTERS:
+                                writer.writeCharacters(reader.getText());
+                                break;
+                            case XMLStreamConstants.END_ELEMENT:
+                                writer.writeEndElement();
+                                break;
+                        }
+                    }
+                } else {
+                    writer.writeCharacters(node.getTextContent());
+                }
+            }
+        }
+    } // end method writePropertyValue
+
 
     /**
      * Returns the model factory extension point to use.

Modified: tuscany/sca-java-2.x/branches/2.0-Beta1/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/ComponentBuilderImpl.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/branches/2.0-Beta1/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/ComponentBuilderImpl.java?rev=978812&r1=978811&r2=978812&view=diff
==============================================================================
--- tuscany/sca-java-2.x/branches/2.0-Beta1/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/ComponentBuilderImpl.java (original)
+++ tuscany/sca-java-2.x/branches/2.0-Beta1/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/ComponentBuilderImpl.java Sat Jul 24 06:43:15 2010
@@ -18,6 +18,7 @@
  */
 package org.apache.tuscany.sca.builder.impl;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringReader;
 import java.net.URI;
@@ -266,7 +267,7 @@ public class ComponentBuilderImpl {
             calculateServiceInterfaceContract(component, componentService, componentTypeService, monitor);
 
             // bindings
-            calculateBindings(component, componentService, componentTypeService, monitor);
+            calculateBindings(component, componentService, componentTypeService, context);
 
             // add callback reference model objects
             createCallbackReference(component, componentService);
@@ -807,138 +808,257 @@ public class ComponentBuilderImpl {
                                                 Monitor monitor) {
         String source = componentProperty.getSource();
 
-        if (source != null) {
-            // $<name>/...
-            int index = source.indexOf('/');
-            if (index == -1) {
-                // Tolerating $prop
-                source = source + "/";
-                index = source.length() - 1;
-            }
-            if (source.charAt(0) == '$') {
-                String name = source.substring(1, index);
-                Property sourceProp = null;
-                if (outerComponent != null) {
-                    sourceProp = outerComponent.getProperty(name);
-                } else {
-                    sourceProp = parentComposite.getProperty(name);
-                }
-                if (sourceProp == null) {
-                    Monitor.error(monitor,
-                                  this,
-                                  Messages.ASSEMBLY_VALIDATION,
-                                  "PropertySourceNotFound",
-                                  source,
-                                  componentProperty.getName(),
-                                  component.getName());
-                }
-
-                Document sourcePropValue = (Document)sourceProp.getValue();
+        if (source == null) return;
+        
+        try {
+            String sourceName = extractSourcePropertyName( source );
 
-                try {
-                    // FIXME: How to deal with namespaces?
-                    Document node =
-                        evaluateXPath(sourcePropValue,
-                                      componentProperty.getSourceXPathExpression(),
-                                      documentBuilderFactory);
-
-                    if (node != null) {
-                        componentProperty.setValue(node);
-                    } else {
-                        Monitor.warning(monitor,
-                                        this,
-                                        Messages.ASSEMBLY_VALIDATION,
-                                        "PropertyXpathExpressionReturnedNull",
-                                        component.getName(),
-                                        componentProperty.getName(),
-                                        componentProperty.getSource());
-                    }
-                } catch (Exception ex) {
-                    Monitor.error(monitor,
-                                  this,
-                                  Messages.ASSEMBLY_VALIDATION,
-                                  "PropertySourceXpathInvalid",
-                                  source,
-                                  componentProperty.getName(),
-                                  component.getName(),
-                                  ex);
-                }
+            Property sourceProp = null;
+            if (outerComponent != null) {
+                sourceProp = outerComponent.getProperty(sourceName);
             } else {
+                sourceProp = parentComposite.getProperty(sourceName);
+            }
+            if (sourceProp == null) {
                 Monitor.error(monitor,
                               this,
                               Messages.ASSEMBLY_VALIDATION,
-                              "PropertySourceValueInvalid",
+                              "PropertySourceNotFound",
                               source,
                               componentProperty.getName(),
                               component.getName());
-            }
-        }
-    }
+            } else {
 
+	            Document sourcePropValue = (Document)sourceProp.getValue();
+	
+	            try {
+	                // FIXME: How to deal with namespaces?
+	                Document node =
+	                    evaluateXPath2(sourcePropValue,
+	                                  componentProperty.getSourceXPathExpression(),
+	                                  documentBuilderFactory);
+	
+	                if (node != null) {
+	                    componentProperty.setValue(node);
+	                } else {
+	                    Monitor.warning(monitor,
+	                                    this,
+	                                    Messages.ASSEMBLY_VALIDATION,
+	                                    "PropertyXpathExpressionReturnedNull",
+	                                    component.getName(),
+	                                    componentProperty.getName(),
+	                                    componentProperty.getSource());
+	                } // end if
+	           
+	            } catch (Exception ex) {
+	                Monitor.error(monitor,
+	                              this,
+	                              Messages.ASSEMBLY_VALIDATION,
+	                              "PropertySourceXpathInvalid",
+	                              source,
+	                              componentProperty.getName(),
+	                              component.getName(),
+	                              ex);
+	            } // end try
+            } // end if
+        } catch (IllegalArgumentException e ) {
+            Monitor.error(monitor,
+                          this,
+                          Messages.ASSEMBLY_VALIDATION,
+                          "PropertySourceValueInvalid",
+                          source,
+                          componentProperty.getName(),
+                          component.getName());
+        } // end try 
+    } // end method
+    
     /**
-     * If the property has a file attribute use this to retrieve the value from a 
-     * local file
+     * Extracts the name of the source property from the value of an @source attribute string
+     * @param source - the value of the @source attribute
+     * @return - the source property name as a String
+     */
+    private String extractSourcePropertyName( String source ) throws IllegalArgumentException {
+    	String propertyName = null;
+    	
+        // Possible values for the source string:
+    	// a) $name
+    	// b) $name/expression
+    	// c) $name[xx]
+    	// d) $name[xx]/expression
+    	// ...and note that the expression MAY contain '/' and '[' characters
+    	if( source.charAt(0) != '$' ) throw new IllegalArgumentException("Source value does not start with '$'");	
+    	
+        int index = source.indexOf('/');
+        int bracket = source.indexOf('[');
+        
+        if( index == -1 && bracket == -1 ) {
+        	// Format a) - simply remove the '$'
+        	propertyName = source.substring(1);
+        } else if ( bracket == -1 ) {
+        	// Format b) - remove the '$' and the '/' and everything following it
+        	propertyName = source.substring(1, index);
+        } else if ( index == -1 ) {
+        	// Format c) - remove the '$' and the '[' and everything following it
+        	propertyName = source.substring(1, bracket);
+        } else {
+        	// Format d) - but need to ensure that the '[' is BEFORE the '/'
+        	if( bracket < index ) {
+        		// Format d) - remove the '$' and the '[' and everything following it
+        		propertyName = source.substring(1, bracket);
+        	} else {
+        		// Format b) variant where there is a '[' in the expression...
+        		propertyName = source.substring(1, index);
+        	} // end if
+        } // end if
+        
+    	return propertyName;
+    } // end method extractSourcePropertyName( source, monitor )
 
+    /**
+     * If the property has a file attribute use this to retrieve the property value from a local file
+     * Format of the property value file is defined in the SCA Assembly specification in ASM50046
      * 
-     * @param parentCompoent the composite that contains the component
-     * @param component
+     * @param component the component holding the property
+     * @param componentProperty - the property 
+     * @param monitor - a Monitor object for reporting problems
+     */
+    /**
+     * Property file format:
+     * MUST contain a <sca:values/> element
+     * - either contains one or more <sca:value/> subelements (mandatory for property with a simple XML type)
+     * - or contains one or more global elements of the type of the property
+     * 
+     * eg.
+     * 	<?xml version="1.0" encoding="UTF-8"?>
+     *  <values>
+     *     <value>MyValue</value>
+     *  </values>
+     *  
+     *  <?xml version="1.0" encoding="UTF-8"?>
+     *  <values>
+     *     <foo:fooElement>
+     *        <foo:a>AValue</foo:a>
+     *        <foo:b>InterestingURI</foo:b>
+     *     </foo:fooElement>
+     *  </values/>
      */
     private void processPropertyFileAttribute(Component component, ComponentProperty componentProperty, Monitor monitor) {
         String file = componentProperty.getFile();
-        if (file != null) {
+        if (file == null) return;
+        try {
+/*        	
+            URI uri = URI.create(file);
+            // URI resolution for relative URIs is done when the composite is resolved.
+            URL url = uri.toURL();
+            URLConnection connection = url.openConnection();
+            connection.setUseCaches(false);
+            InputStream is = null;           
             try {
-                URI uri = URI.create(file);
-                // URI resolution for relative URIs is done when the composite is resolved.
-                URL url = uri.toURL();
-                URLConnection connection = url.openConnection();
-                connection.setUseCaches(false);
-                InputStream is = null;
-                try {
-                    is = connection.getInputStream();
 
-                    Source streamSource = new SAXSource(new InputSource(is));
-                    DOMResult result = new DOMResult();
-                    javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
-                    transformer.transform(streamSource, result);
-
-                    Document document = (Document)result.getNode();
-
-                    // TUSCANY-2377, Add a fake value element so it's consistent with
-                    // the DOM tree loaded from inside SCDL
-                    if (!document.getDocumentElement().getLocalName().equals("value")){
-                        Element root = document.createElementNS(null, "value");
-                        root.appendChild(document.getDocumentElement());
-                        
-                        // remove all the child nodes as they will be replaced by 
-                        // the "value" node
-                        NodeList children = document.getChildNodes();
-                        for (int i=0; i < children.getLength(); i++){
-                            document.removeChild(children.item(i));
-                        }
-                        
-                        // add the value node back in
-                        document.appendChild(root);
-                    }
+                is = connection.getInputStream();
+
+                Source streamSource = new SAXSource(new InputSource(is));
+                DOMResult result = new DOMResult();
+                javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
+                transformer.transform(streamSource, result);
+
+                Document document = (Document)result.getNode();
+*/                
+                Document document = readPropertyFileData( file );
+                
+                Element docElement = document.getDocumentElement();
+                if( docElement == null ) throw new Exception("Property File has no XML document element");
+                
+                if( !"values".equals( docElement.getLocalName() ) ) {
+                	throw new Exception("Property File does not start with <values/> element");
+                } // end if
+                
+                // The property value is the subelement(s) of the <values/> element
+                NodeList values = docElement.getChildNodes();
+                
+                Document newdoc = documentBuilderFactory.newDocumentBuilder().newDocument();
+                Element newProperty = newdoc.createElementNS(SCA11_NS, "property");
+                newdoc.appendChild( newProperty );
+                
+                int count = 0;
+                
+                // Copy the property values under the new <property/> element
+                for( int i = 0 ; i < values.getLength() ; i++ ) {
+                	Node valueNode = values.item(i);
+                	// Only <value/> elements or global elements are valid values...
+                	if( valueNode.getNodeType() == Node.ELEMENT_NODE ) {
+                		newProperty.appendChild(newdoc.importNode(values.item(i), true));
+                		count++;
+                	} // end if
+                } // end for
+                
+                if( count == 0 ) {
+                	throw new Exception("Property File has no property values");
+                } // end if 
+                
+                componentProperty.setValue(newdoc);
+                
+/*
+                // TUSCANY-2377, Add a fake value element so it's consistent with
+                // the DOM tree loaded from inside SCDL
+                if (!document.getDocumentElement().getLocalName().equals("value")){
+                    Element root = document.createElementNS(null, "value");
+                    root.appendChild(document.getDocumentElement());
                     
-                    componentProperty.setValue(document);
-                } finally {
-                    if (is != null) {
-                        is.close();
+                    // remove all the child nodes as they will be replaced by the "value" node
+                    NodeList children = document.getChildNodes();
+                    for (int i=0; i < children.getLength(); i++){
+                        document.removeChild(children.item(i));
                     }
-                }
-            } catch (Exception ex) {
-                Monitor.error(monitor,
-                              this,
-                              Messages.ASSEMBLY_VALIDATION,
-                              "PropertyFileValueInvalid",
-                              file,
-                              componentProperty.getName(),
-                              component.getName(),
-                              ex);
+                    
+                    // add the value node back in
+                    document.appendChild(root);
+                }               
+                componentProperty.setValue(document);               
+            } finally {
+                if (is != null) {
+                    is.close();
+                }  
+            } // end try
+*/                
+        } catch (Exception ex) {
+            Monitor.error(monitor,
+                          this,
+                          Messages.ASSEMBLY_VALIDATION,
+                          "PropertyFileValueInvalid",
+                          file,
+                          componentProperty.getName(),
+                          component.getName(),
+                          ex);
+        } // end try
+    } // end method processPropertyFileAttribute
+    
+    private Document readPropertyFileData( String file ) throws Exception {
+    	Document doc = null;
+    	
+    	URI uri = URI.create(file);
+        // URI resolution for relative URIs is done when the composite is resolved.
+        URL url = uri.toURL();
+        URLConnection connection = url.openConnection();
+        connection.setUseCaches(false);
+        InputStream is = null;
+        try {
+	        is = connection.getInputStream();
+	
+	        Source streamSource = new SAXSource(new InputSource(is));
+	        DOMResult result = new DOMResult();
+	        javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
+	        transformer.transform(streamSource, result);
+	        
+	        doc = (Document)result.getNode();
+        } finally {
+            if (is != null) {
+                is.close();
             }
-        }
+        } // end try
 
-    }
+        return doc;
+    } // end method readPropertyFileData
 
     /**
      * Evaluate an XPath expression against a Property value, returning the result as a Property value
@@ -984,6 +1104,51 @@ public class ComponentBuilderImpl {
             return document;
         }
     }
+    
+    /**
+     * Evaluate an XPath expression against a Property value, returning the result as a Property value
+     * - deals with multi-valued input property values and with multi-valued output property values
+     * @param node - the document root element of a Property value
+     * @param expression - the XPath expression
+     * @param documentBuilderFactory - a DOM document builder factory
+     * @return - a DOM Document representing the result of the evaluation as a Property value
+     * @throws XPathExpressionException
+     * @throws ParserConfigurationException
+     */
+    private Document evaluateXPath2(Document node,
+                                   XPathExpression expression,
+                                   DocumentBuilderFactory documentBuilderFactory) throws XPathExpressionException,
+        ParserConfigurationException {
+
+        // The document element is a <sca:property/> element
+        Element property = node.getDocumentElement();
+
+        NodeList result = (NodeList)expression.evaluate(property, XPathConstants.NODESET);
+        if (result == null || result.getLength() == 0) return null;
+
+        if (result instanceof Document) {
+            return (Document)result;
+        } else {
+            Document document = documentBuilderFactory.newDocumentBuilder().newDocument();
+            Element newProperty = document.createElementNS(SCA11_NS, "property");
+            
+            for( int i = 0 ; i < result.getLength() ; i++ ) {
+		        if (result.item(i).getNodeType() == Node.ELEMENT_NODE) {
+		            // If the result is an element, use it directly in the result
+		            newProperty.appendChild(document.importNode(result.item(i), true));
+		        } else {
+		            // If the result is not an element, create a <value/> element to contain the result
+		            Element newValue = document.createElementNS(SCA11_NS, "value");
+		            newValue.appendChild(document.importNode(result.item(i), true));
+		            newProperty.appendChild(newValue);
+		        } // end if
+            } // end for
+            
+            document.appendChild(newProperty);
+
+            return document;
+        } // end if
+    } // end method
 
     /**
      * Create a callback reference for a component service
@@ -1404,14 +1569,16 @@ public class ComponentBuilderImpl {
      * @param componentService the top service 
      * @param componentTypeService the bottom service
      */
-    private void calculateBindings(Component component, Service componentService, Service componentTypeService, Monitor monitor) {
+    private void calculateBindings(Component component, Service componentService, Service componentTypeService, BuilderContext context) {
+    	Monitor monitor = context.getMonitor();
+    	
         // forward bindings
         if (componentService.getBindings().isEmpty()) {
             componentService.getBindings().addAll(componentTypeService.getBindings());
         }
 
         if (componentService.getBindings().isEmpty()) {
-            createSCABinding(componentService, null);
+            createSCABinding(componentService, context.getDefinitions());
         }
 
         // callback bindings