summaryrefslogtreecommitdiffstats
path: root/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader')
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java360
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java86
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java105
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java67
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java179
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java195
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java98
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PropertyUtils.java119
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java107
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java99
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java191
-rw-r--r--sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/WireLoader.java122
12 files changed, 1728 insertions, 0 deletions
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java
new file mode 100644
index 0000000000..b289e74a9b
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java
@@ -0,0 +1,360 @@
+/*
+ * 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.tuscany.core.loader;
+
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import static org.osoa.sca.Constants.SCA_NS;
+
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.core.binding.local.LocalBindingDefinition;
+import org.apache.tuscany.core.deployer.ChildDeploymentContext;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.InvalidReferenceException;
+import org.apache.tuscany.spi.loader.InvalidValueException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.loader.MissingImplementationException;
+import org.apache.tuscany.spi.loader.MissingReferenceException;
+import org.apache.tuscany.spi.loader.MissingRequiredPropertyException;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+import org.apache.tuscany.spi.loader.ReferenceMultiplicityViolationException;
+import org.apache.tuscany.spi.loader.UndefinedPropertyException;
+import org.apache.tuscany.spi.loader.UndefinedReferenceException;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.BindingDefinition;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Multiplicity;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.PropertyValue;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ReferenceTarget;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+import org.w3c.dom.Document;
+
+/**
+ * Loads a component definition from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class ComponentLoader extends LoaderExtension<ComponentDefinition<?>> {
+ private static final QName COMPONENT = new QName(SCA_NS, "component");
+ private static final QName PROPERTY = new QName(SCA_NS, "property");
+ private static final QName REFERENCE = new QName(SCA_NS, "reference");
+
+ private static final String PROPERTY_FILE_ATTR = "file";
+ private static final String PROPERTY_NAME_ATTR = "name";
+ private static final String PROPERTY_SOURCE_ATTR = "source";
+
+ private PropertyObjectFactory propertyFactory;
+
+ @Constructor
+ public ComponentLoader(@Reference LoaderRegistry registry, @Reference PropertyObjectFactory propertyFactory) {
+ super(registry);
+ this.propertyFactory = propertyFactory;
+ }
+
+ public QName getXMLType() {
+ return COMPONENT;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ComponentDefinition<?> load(ModelObject object, XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ assert COMPONENT.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String initLevel = reader.getAttributeValue(null, "initLevel");
+ String autowireAttr = reader.getAttributeValue(null, "autowire");
+ boolean autowire;
+ if (autowireAttr == null) {
+ autowire = context.isAutowire();
+ } else {
+ autowire = Boolean.parseBoolean(autowireAttr);
+ }
+ String runtimeAttr = reader.getAttributeValue(null, "runtimeId");
+ URI runtimeId;
+ if (runtimeAttr != null) {
+ try {
+ runtimeId = new URI(runtimeAttr);
+ } catch (URISyntaxException e) {
+ throw new InvalidValueException(runtimeAttr, "runtimeId", e);
+ }
+ } else {
+ runtimeId = null;
+ }
+
+ URI componentId = URI.create(context.getComponentId() + "/").resolve(name);
+ ClassLoader loader = context.getClassLoader();
+ URL location = context.getScdlLocation();
+ // xcv test
+ DeploymentContext childContext = new ChildDeploymentContext(context, loader, location, componentId, autowire);
+ Implementation<?> impl = loadImplementation(reader, childContext);
+ registry.loadComponentType(impl, childContext);
+
+ ComponentDefinition<Implementation<?>> componentDefinition =
+ new ComponentDefinition<Implementation<?>>(componentId, impl);
+ componentDefinition.setAutowire(autowire);
+ componentDefinition.setRuntimeId(runtimeId);
+ if (initLevel != null) {
+ if (initLevel.length() == 0) {
+ componentDefinition.setInitLevel(0);
+ } else {
+ try {
+ componentDefinition.setInitLevel(Integer.valueOf(initLevel));
+ } catch (NumberFormatException e) {
+ throw new InvalidValueException(initLevel, "initValue", e);
+ }
+ }
+ }
+
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (PROPERTY.equals(qname)) {
+ loadProperty(reader, componentDefinition, childContext);
+ } else if (REFERENCE.equals(qname)) {
+ loadReference(reader, componentDefinition, childContext);
+ } else {
+ throw new UnrecognizedElementException(qname);
+ }
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(COMPONENT)) {
+ populatePropertyValues(componentDefinition);
+ ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> type =
+ (ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>) componentDefinition
+ .getImplementation().getComponentType();
+
+ for (ReferenceDefinition ref : type.getReferences().values()) {
+ // add reference target definitions if autowire is enabled for references that are not
+ // explicitly configured with autowire by the component
+ if (!componentDefinition.getReferenceTargets().containsKey(ref.getUri().getFragment())) {
+ if (autowire) {
+ ReferenceTarget referenceTarget = new ReferenceTarget();
+ String compName = componentDefinition.getUri().toString();
+ URI refName = URI.create(compName + ref.getUri().toString());
+ referenceTarget.setReferenceName(refName);
+ referenceTarget.setAutowire(autowire);
+ componentDefinition.add(referenceTarget);
+ }
+ }
+ }
+ validate(componentDefinition);
+ return componentDefinition;
+ }
+ break;
+ }
+ }
+ }
+
+ protected Implementation<?> loadImplementation(XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ reader.nextTag();
+ ModelObject o = registry.load(null, reader, context);
+ if (!(o instanceof Implementation)) {
+ throw new MissingImplementationException();
+ }
+ return (Implementation<?>) o;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void loadProperty(XMLStreamReader reader, ComponentDefinition<?> definition, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR);
+ Implementation<?> implementation = definition.getImplementation();
+ ComponentType<?, ?, ?> componentType = implementation.getComponentType();
+ Property<Type> property = (Property<Type>) componentType.getProperties().get(name);
+ if (property == null) {
+ throw new UndefinedPropertyException(name);
+ }
+ PropertyValue<Type> propertyValue;
+ String source = reader.getAttributeValue(null, PROPERTY_SOURCE_ATTR);
+ String file = reader.getAttributeValue(null, PROPERTY_FILE_ATTR);
+ if (source != null || file != null) {
+ propertyValue = new PropertyValue<Type>(name, source, file);
+ propertyValue.setValue(property.getDefaultValue());
+ LoaderUtil.skipToEndElement(reader);
+ } else {
+ try {
+ DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ Document value = PropertyUtils.createPropertyValue(reader, property.getXmlType(), documentBuilder);
+ propertyValue = new PropertyValue<Type>(name, value);
+ } catch (ParserConfigurationException e) {
+ throw new LoaderException(e);
+ }
+ }
+ ObjectFactory<Type> objectFactory = propertyFactory.createObjectFactory(property, propertyValue);
+ propertyValue.setValueFactory(objectFactory);
+ definition.add(propertyValue);
+ }
+
+ protected void loadReference(XMLStreamReader reader,
+ ComponentDefinition<?> componentDefinition,
+ DeploymentContext context) throws XMLStreamException, LoaderException {
+ String name = reader.getAttributeValue(null, "name");
+ if (name == null) {
+ throw new InvalidReferenceException("No name specified");
+ }
+ String target = reader.getAttributeValue(null, "target");
+ boolean autowire = Boolean.parseBoolean(reader.getAttributeValue(null, "autowire"));
+ URI componentId = context.getComponentId();
+ List<URI> uris = new ArrayList<URI>();
+ if (target != null) {
+ StringTokenizer tokenizer = new StringTokenizer(target);
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ QualifiedName qName = new QualifiedName(token);
+ uris.add(componentId.resolve(qName.getFragment()));
+ }
+ }
+
+ Implementation<?> impl = componentDefinition.getImplementation();
+ ComponentType<?, ?, ?> componentType = impl.getComponentType();
+ if (!componentType.getReferences().containsKey(name)) {
+ throw new UndefinedReferenceException(name);
+ }
+ if (componentType instanceof CompositeComponentType) {
+ if (uris.size() != 1) {
+ // FIXME not yet implemented
+ throw new UnsupportedOperationException();
+ }
+ ReferenceDefinition definition = componentType.getReferences().get(name);
+ if (definition.getBindings().isEmpty()) {
+ // TODO JFM allow selection of a default binding
+ LocalBindingDefinition binding = new LocalBindingDefinition(uris.get(0));
+ definition.addBinding(binding);
+ } else {
+ for (BindingDefinition binding : definition.getBindings()) {
+ binding.setTargetUri(uris.get(0));
+ }
+ }
+ } else {
+ ReferenceTarget referenceTarget = componentDefinition.getReferenceTargets().get(name);
+ if (referenceTarget == null) {
+ referenceTarget = new ReferenceTarget();
+ referenceTarget.setReferenceName(componentId.resolve('#' + name));
+ referenceTarget.setAutowire(autowire);
+ componentDefinition.add(referenceTarget);
+ }
+ for (URI uri : uris) {
+ referenceTarget.addTarget(uri);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void populatePropertyValues(ComponentDefinition<Implementation<?>> componentDefinition)
+ throws MissingRequiredPropertyException {
+ ComponentType componentType = componentDefinition.getImplementation().getComponentType();
+ if (componentType != null) {
+ Map<String, Property<?>> properties = componentType.getProperties();
+ Map<String, PropertyValue<?>> propertyValues = componentDefinition.getPropertyValues();
+
+ for (Property<?> aProperty : properties.values()) {
+ if (propertyValues.get(aProperty.getName()) == null) {
+ if (aProperty.isRequired()) {
+ throw new MissingRequiredPropertyException(aProperty.getName());
+ } else if (aProperty.getDefaultValue() != null) {
+ PropertyValue propertyValue = new PropertyValue();
+ propertyValue.setName(aProperty.getName());
+ propertyValue.setValue(aProperty.getDefaultValue());
+// propertyValue.setValueFactory(new SimplePropertyObjectFactory(aProperty,
+// propertyValue.getValue()));
+ propertyValues.put(aProperty.getName(), propertyValue);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Validates a component definition, ensuring all component type configuration elements are satisfied
+ */
+ protected void validate(ComponentDefinition<Implementation<?>> definition) throws LoaderException {
+ // validate refererences
+ Implementation<?> implementation = definition.getImplementation();
+ ComponentType<?, ?, ?> type = implementation.getComponentType();
+ if (type == null) {
+ return;
+ }
+ for (ReferenceDefinition referenceDef : type.getReferences().values()) {
+ if (!referenceDef.isRequired()) {
+ continue;
+ }
+ String name = referenceDef.getUri().getFragment();
+ ReferenceTarget target = definition.getReferenceTargets().get(name);
+ if (target == null) {
+ throw new MissingReferenceException(name);
+ }
+ if (target.isAutowire()) {
+ // autowire targets are not set yet
+ continue;
+ }
+ int count = target.getTargets().size();
+ Multiplicity multiplicity = referenceDef.getMultiplicity();
+ switch (multiplicity) {
+ case ZERO_N:
+ break;
+ case ZERO_ONE:
+ if (count > 1) {
+ throw new ReferenceMultiplicityViolationException(name, multiplicity, count);
+ }
+ break;
+ case ONE_ONE:
+ if (count != 1) {
+ throw new ReferenceMultiplicityViolationException(name, multiplicity, count);
+ }
+ break;
+ case ONE_N:
+ if (count < 1) {
+ throw new ReferenceMultiplicityViolationException(name, multiplicity, count);
+ }
+ break;
+ }
+
+ }
+ }
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java
new file mode 100644
index 0000000000..beb0bc2731
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java
@@ -0,0 +1,86 @@
+/*
+ * 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.tuscany.core.loader;
+
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ComponentTypeElementLoader extends LoaderExtension<ComponentType> {
+ public static final QName COMPONENT_TYPE = new QName(SCA_NS, "componentType");
+
+ @Constructor
+ public ComponentTypeElementLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return COMPONENT_TYPE;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ComponentType load(ModelObject object, XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ assert COMPONENT_TYPE.equals(reader.getName());
+ ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> componentType;
+ if (object != null) {
+ assert object instanceof ComponentType;
+ // a specialized component type was passed in
+ componentType = (ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>) object;
+ } else {
+ componentType = new ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>();
+ }
+
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject o = registry.load(componentType, reader, context);
+ if (o instanceof ServiceDefinition) {
+ componentType.add((ServiceDefinition) o);
+ } else if (o instanceof ReferenceDefinition) {
+ componentType.add((ReferenceDefinition) o);
+ } else if (o instanceof Property) {
+ componentType.add((Property<?>) o);
+ }
+ break;
+ case END_ELEMENT:
+ return componentType;
+ }
+ }
+ }
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java
new file mode 100644
index 0000000000..e10a93bbc0
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java
@@ -0,0 +1,105 @@
+/*
+ * 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.tuscany.core.loader;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.loader.MissingIncludeException;
+import org.apache.tuscany.spi.loader.MissingResourceException;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Include;
+import org.apache.tuscany.spi.model.ModelObject;
+
+import org.apache.tuscany.core.deployer.ChildDeploymentContext;
+
+/**
+ * Loader that handles &lt;include&gt; elements.
+ *
+ * @version $Rev$ $Date$
+ */
+public class IncludeLoader extends LoaderExtension<Include> {
+ private static final QName INCLUDE = new QName(SCA_NS, "include");
+
+ @Constructor
+ public IncludeLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return INCLUDE;
+ }
+
+ public Include load(ModelObject object, XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+
+ assert INCLUDE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String scdlLocation = reader.getAttributeValue(null, "scdlLocation");
+ String scdlResource = reader.getAttributeValue(null, "scdlResource");
+ LoaderUtil.skipToEndElement(reader);
+
+ ClassLoader cl = deploymentContext.getClassLoader();
+ URL url;
+ if (scdlLocation != null) {
+ try {
+ url = new URL(deploymentContext.getScdlLocation(), scdlLocation);
+ } catch (MalformedURLException e) {
+ throw new MissingResourceException(scdlLocation, name, e);
+ }
+ } else if (scdlResource != null) {
+ url = cl.getResource(scdlResource);
+ if (url == null) {
+ throw new MissingResourceException(scdlResource, name);
+ }
+ } else {
+ throw new MissingIncludeException("No SCDL location or resource specified", name);
+ }
+
+ // when we include, the componentId remains that of the parent
+ URI componentId = deploymentContext.getComponentId();
+ boolean autowire = deploymentContext.isAutowire();
+ DeploymentContext childContext = new ChildDeploymentContext(deploymentContext, cl, url, componentId, autowire);
+ CompositeComponentType composite;
+ composite = loadFromSidefile(url, childContext);
+
+ Include include = new Include();
+ include.setName(name);
+ include.setScdlLocation(url);
+ include.setIncluded(composite);
+ return include;
+ }
+
+ protected CompositeComponentType loadFromSidefile(URL url, DeploymentContext context) throws LoaderException {
+ return registry.load(null, url, CompositeComponentType.class, context);
+ }
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java
new file mode 100644
index 0000000000..26ec72ecb6
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.tuscany.core.loader;
+
+import java.io.PrintWriter;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.loader.LoaderException;
+
+import org.apache.tuscany.host.monitor.ExceptionFormatter;
+import org.apache.tuscany.host.monitor.FormatterRegistry;
+
+/**
+ * Formats {@link org.apache.tuscany.spi.loader.LoaderException} events
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class LoaderExceptionFormatter implements ExceptionFormatter {
+ private FormatterRegistry factory;
+
+ public LoaderExceptionFormatter(@Reference FormatterRegistry factory) {
+ this.factory = factory;
+ factory.register(this);
+ }
+
+ public boolean canFormat(Class<?> type) {
+ return LoaderException.class.isAssignableFrom(type);
+ }
+
+ @Destroy
+ public void destroy() {
+ factory.unregister(this);
+ }
+
+ public PrintWriter write(PrintWriter writer, Throwable exception) {
+ assert exception instanceof LoaderException;
+ LoaderException e = (LoaderException) exception;
+ e.appendBaseMessage(writer);
+ if (e.getLine() != LoaderException.UNDEFINED) {
+ writer.write("\nLine: " + e.getLine() + "\n");
+ writer.write("Column: " + e.getColumn() + "\n");
+ } else {
+ writer.write("\n");
+ }
+ return writer;
+ }
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java
new file mode 100644
index 0000000000..57fd1da870
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java
@@ -0,0 +1,179 @@
+/*
+ * 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.tuscany.core.loader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.loader.ComponentTypeLoader;
+import org.apache.tuscany.spi.loader.InvalidConfigurationException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.StAXElementLoader;
+import org.apache.tuscany.spi.loader.UnrecognizedComponentTypeException;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.ModelObject;
+
+/**
+ * The default implementation of a loader registry
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class LoaderRegistryImpl implements LoaderRegistry {
+ private Monitor monitor;
+ private final Map<QName, StAXElementLoader<? extends ModelObject>> loaders =
+ new HashMap<QName, StAXElementLoader<? extends ModelObject>>();
+ private final Map<Class<? extends Implementation<?>>,
+ ComponentTypeLoader<? extends Implementation<?>>> componentTypeLoaders =
+ new HashMap<Class<? extends Implementation<?>>, ComponentTypeLoader<? extends Implementation<?>>>();
+
+ public LoaderRegistryImpl(@org.apache.tuscany.api.annotation.Monitor Monitor monitor) {
+ this.monitor = monitor;
+ }
+
+ public <T extends ModelObject> void registerLoader(QName element, StAXElementLoader<T> loader) {
+ monitor.registeringLoader(element);
+ loaders.put(element, loader);
+ }
+
+ public <T extends ModelObject> void unregisterLoader(QName element, StAXElementLoader<T> loader) {
+ monitor.unregisteringLoader(element);
+ loaders.remove(element);
+ }
+
+ public ModelObject load(
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ QName name = reader.getName();
+ monitor.elementLoad(name);
+ StAXElementLoader<? extends ModelObject> loader = loaders.get(name);
+ if (loader == null) {
+ throw new UnrecognizedElementException(name);
+ }
+ return loader.load(object, reader, deploymentContext);
+ }
+
+ public <MO extends ModelObject> MO load(
+ ModelObject object,
+ URL url,
+ Class<MO> type,
+ DeploymentContext ctx) throws LoaderException {
+ try {
+ XMLStreamReader reader;
+ InputStream is;
+ is = url.openStream();
+ try {
+ XMLInputFactory factory = ctx.getXmlFactory();
+ reader = factory.createXMLStreamReader(is);
+ try {
+ reader.nextTag();
+ QName name = reader.getName();
+ ModelObject mo = load(object, reader, ctx);
+ if (type.isInstance(mo)) {
+ return type.cast(mo);
+ } else {
+ UnrecognizedElementException e = new UnrecognizedElementException(name);
+ e.setResourceURI(url.toString());
+ throw e;
+ }
+ } catch (LoaderException e) {
+ Location location = reader.getLocation();
+ e.setLine(location.getLineNumber());
+ e.setColumn(location.getColumnNumber());
+ throw e;
+ } finally {
+ try {
+ reader.close();
+ } catch (XMLStreamException e) {
+ // ignore
+ }
+ }
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ } catch (IOException e) {
+ LoaderException sfe = new LoaderException(e);
+ sfe.setResourceURI(url.toString());
+ throw sfe;
+ } catch (XMLStreamException e) {
+ throw new InvalidConfigurationException("Invalid or missing resource", url.toString(), e);
+ }
+ }
+
+ public <I extends Implementation<?>> void registerLoader(Class<I> key, ComponentTypeLoader<I> loader) {
+ componentTypeLoaders.put(key, loader);
+ }
+
+ public <I extends Implementation<?>> void unregisterLoader(Class<I> key) {
+ componentTypeLoaders.remove(key);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <I extends Implementation<?>> void loadComponentType(I implementation,
+ DeploymentContext deploymentContext)
+ throws LoaderException {
+ Class<I> key = (Class<I>) implementation.getClass();
+ ComponentTypeLoader<I> loader = (ComponentTypeLoader<I>) componentTypeLoaders.get(key);
+ if (loader == null) {
+ throw new UnrecognizedComponentTypeException(key);
+ }
+ loader.load(implementation, deploymentContext);
+ }
+
+ public static interface Monitor {
+ /**
+ * Event emitted when a StAX element loader is registered.
+ *
+ * @param xmlType the QName of the element the loader will handle
+ */
+ void registeringLoader(QName xmlType);
+
+ /**
+ * Event emitted when a StAX element loader is unregistered.
+ *
+ * @param xmlType the QName of the element the loader will handle
+ */
+ void unregisteringLoader(QName xmlType);
+
+ /**
+ * Event emitted when a request is made to load an element.
+ *
+ * @param xmlType the QName of the element that should be loaded
+ */
+ void elementLoad(QName xmlType);
+ }
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java
new file mode 100644
index 0000000000..66d2a87593
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java
@@ -0,0 +1,195 @@
+/*
+ * 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.tuscany.core.loader;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.model.IntentMap;
+import org.apache.tuscany.spi.model.IntentName;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.PolicySet;
+import org.apache.tuscany.spi.model.PolicySetReference;
+import org.apache.tuscany.spi.model.Qualifier;
+import org.apache.tuscany.spi.model.WSPolicyAttachment;
+
+/**
+ * Loads a PolicySet definition from an SCDL file.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PolicySetLoader extends LoaderExtension<PolicySet> {
+
+ private static final String WSPOLICY_NAMESPACE = "http://schemas.xmlsoap.org/ws/2004/09/policy";
+
+ private static final QName POLICYSET = new QName(SCA_NS, "policySet");
+
+ private static final QName INTENTMAP = new QName(SCA_NS, "intentMap");
+
+ private static final QName QUALIFIER = new QName(SCA_NS, "qualifier");
+
+ private static final QName POLICYSETREFERENCE = new QName(SCA_NS, "policySetReference");
+
+ private static final QName WSPOLICYATTACHMENT = new QName(WSPOLICY_NAMESPACE, "PolicyAttachment");
+
+ @Constructor
+ public PolicySetLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+
+ }
+
+ @Override
+ public QName getXMLType() {
+ return POLICYSET;
+ }
+
+ public PolicySet load(ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ assert POLICYSET.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String provides = reader.getAttributeValue(null, "provides");
+ String appliesTo = reader.getAttributeValue(null, "appliesTo");
+ PolicySet policySet = new PolicySet(new QName(SCA_NS, name), parseIntentName(provides));
+ String[] appliesToArtifact = split(appliesTo);
+ for (String artifact : appliesToArtifact) {
+ policySet.addAppliedArtifacts(new QName(SCA_NS, artifact));
+ }
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (INTENTMAP.equals(qname)) {
+ policySet.addIntentMap(loadIntentMap(reader, deploymentContext));
+ } else if (POLICYSETREFERENCE.equals(qname)) {
+ policySet.addPolicySetReference(loadPolicyReference(reader, deploymentContext));
+ } else if (WSPOLICYATTACHMENT.equals(qname)) {
+ policySet.addWsPolicyAttachment(loadWSPolicyAttachment(reader, deploymentContext));
+ }
+
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(POLICYSET)) {
+ return policySet;
+ }
+ break;
+ }
+ }
+
+ }
+
+ private PolicySetReference loadPolicyReference(XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ assert POLICYSETREFERENCE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ LoaderUtil.skipToEndElement(reader);
+ return new PolicySetReference(new QName(SCA_NS, name));
+ }
+
+ private IntentMap loadIntentMap(XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ assert INTENTMAP.equals(reader.getName());
+ String defaultIntentAttr = reader.getAttributeValue(null, "default");
+ String provides = reader.getAttributeValue(null, "provides");
+ IntentMap intentMap = new IntentMap(defaultIntentAttr, java.util.Arrays.asList(split(provides)));
+ //parentPolicySet.addIntentMap(intentMap);
+
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (QUALIFIER.equals(qname)) {
+ intentMap.addQualifier(loadQualifier(reader, deploymentContext));
+ }
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(INTENTMAP)) {
+ return intentMap;
+ }
+ }
+ }
+
+ }
+
+ private Qualifier loadQualifier(XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ assert QUALIFIER.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ Qualifier qualifier = new Qualifier(name);
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (INTENTMAP.equals(qname)) {
+ qualifier.setIntentMap(loadIntentMap(reader, deploymentContext));
+ } else if (WSPOLICYATTACHMENT.equals(qname)) {
+ qualifier.addWsPolicyAttachment(loadWSPolicyAttachment(reader, deploymentContext));
+ }
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(QUALIFIER)) {
+ return qualifier;
+ }
+ }
+ }
+
+ }
+
+ private WSPolicyAttachment loadWSPolicyAttachment(XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ return new WSPolicyAttachment();
+ }
+
+ /**
+ * Split a string to string array separated by " "
+ */
+ private static String[] split(String string) {
+ if (string == null) {
+ return new String[0];
+ }
+ String[] intents = string.split("[ ]+");
+ return intents;
+ }
+
+ private static List<IntentName> parseIntentName(String attributes) {
+ String[] intents = split(attributes);
+ List<IntentName> result = new ArrayList<IntentName>(intents.length);
+ for (String intent : intents) {
+ result.add(new IntentName(intent));
+ }
+ return result;
+ }
+
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java
new file mode 100644
index 0000000000..ac39c135d9
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java
@@ -0,0 +1,98 @@
+/*
+ * 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.tuscany.core.loader;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.w3c.dom.Document;
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Property;
+
+/**
+ * Loads a property from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class PropertyLoader extends LoaderExtension<Property> {
+ public static final String PROPERTY_NAME_ATTR = "name";
+ public static final String PROPERTY_TYPE_ATTR = "type";
+ public static final String PROPERTY_MANY_ATTR = "many";
+ public static final String REQUIRED_ATTR = "override";
+
+ public static final QName PROPERTY = new QName(SCA_NS, "property");
+ private final DocumentBuilder documentBuilder;
+
+ @Constructor
+ public PropertyLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ try {
+ documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ // we should be able to construct the default DocumentBuilder
+ throw new AssertionError(e);
+ }
+ }
+
+ public QName getXMLType() {
+ return PROPERTY;
+ }
+
+ public Property<?> load(ModelObject object, XMLStreamReader reader,
+ DeploymentContext ctx)
+ throws XMLStreamException, LoaderException {
+ assert PROPERTY.equals(reader.getName());
+ String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR);
+ String typeName = reader.getAttributeValue(null, PROPERTY_TYPE_ATTR);
+ QName xmlType = null;
+ if (typeName != null) {
+ int index = typeName.indexOf(':');
+ if (index != -1) {
+ String prefix = typeName.substring(0, index);
+ String localName = typeName.substring(index + 1);
+ String ns = reader.getNamespaceURI(prefix);
+ xmlType = new QName(ns, localName, prefix);
+ }
+ }
+ boolean many = Boolean.parseBoolean(reader.getAttributeValue(null, PROPERTY_MANY_ATTR));
+ String required = reader.getAttributeValue(null, REQUIRED_ATTR);
+ Document value = PropertyUtils.createPropertyValue(reader, xmlType, documentBuilder);
+
+ Property<?> property = new Property();
+ property.setRequired(Boolean.parseBoolean(required));
+ property.setName(name);
+ property.setXmlType(xmlType);
+ property.setMany(many);
+
+ property.setDefaultValue(value);
+ return property;
+ }
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PropertyUtils.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PropertyUtils.java
new file mode 100644
index 0000000000..57c1e1b5f4
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/PropertyUtils.java
@@ -0,0 +1,119 @@
+/*
+ * 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.tuscany.core.loader;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public final class PropertyUtils {
+
+ private PropertyUtils() {
+ }
+
+ public static Document createPropertyValue(XMLStreamReader reader, QName type, DocumentBuilder builder)
+ throws XMLStreamException {
+ Document doc = builder.newDocument();
+
+ // root element has no namespace and local name "value"
+ Element root = doc.createElementNS(null, "value");
+ if (type != null) {
+ Attr xsi = doc.createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xsi");
+ xsi.setValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
+ root.setAttributeNodeNS(xsi);
+
+ String prefix = type.getPrefix();
+ if (prefix == null || prefix.length() == 0) {
+ prefix = "ns";
+ }
+ Attr typeXmlns = doc.createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:" + prefix);
+ typeXmlns.setValue(type.getNamespaceURI());
+ root.setAttributeNodeNS(typeXmlns);
+
+ Attr xsiType = doc.createAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:type");
+ xsiType.setValue(prefix + ":" + type.getLocalPart());
+ root.setAttributeNodeNS(xsiType);
+ }
+ doc.appendChild(root);
+
+ loadPropertyValue(reader, root);
+ return doc;
+ }
+
+ /**
+ * Load a property value specification from an StAX stream into a DOM Document. Only elements, text and attributes
+ * are processed; all comments and other whitespace are ignored.
+ *
+ * @param reader the stream to read from
+ * @param root the DOM node to load
+ * @throws javax.xml.stream.XMLStreamException
+ *
+ */
+ public static void loadPropertyValue(XMLStreamReader reader, Node root) throws XMLStreamException {
+ Document document = root.getOwnerDocument();
+ Node current = root;
+ while (true) {
+ switch (reader.next()) {
+ case XMLStreamConstants.START_ELEMENT:
+ QName name = reader.getName();
+ Element child = document.createElementNS(name.getNamespaceURI(), name.getLocalPart());
+
+ // add the attributes for this element
+ int count = reader.getAttributeCount();
+ for (int i = 0; i < count; i++) {
+ String ns = reader.getAttributeNamespace(i);
+ String localPart = reader.getAttributeLocalName(i);
+ String value = reader.getAttributeValue(i);
+ child.setAttributeNS(ns, localPart, value);
+ }
+
+ // push the new element and make it the current one
+ current.appendChild(child);
+ current = child;
+ break;
+ case XMLStreamConstants.CDATA:
+ current.appendChild(document.createCDATASection(reader.getText()));
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ current.appendChild(document.createTextNode(reader.getText()));
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ // if we are back at the root then we are done
+ if (current == root) {
+ return;
+ }
+
+ // pop the element off the stack
+ current = current.getParentNode();
+ }
+ }
+ }
+
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java
new file mode 100644
index 0000000000..54183d1c72
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java
@@ -0,0 +1,107 @@
+/*
+ * 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.tuscany.core.loader;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.BindingDefinition;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Multiplicity;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+/**
+ * Loads a reference from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReferenceLoader extends LoaderExtension<ReferenceDefinition> {
+ public static final QName REFERENCE = new QName(SCA_NS, "reference");
+ private static final Map<String, Multiplicity> MULTIPLICITY = new HashMap<String, Multiplicity>(4);
+
+ static {
+ MULTIPLICITY.put("0..1", Multiplicity.ZERO_ONE);
+ MULTIPLICITY.put("1..1", Multiplicity.ONE_ONE);
+ MULTIPLICITY.put("0..n", Multiplicity.ZERO_N);
+ MULTIPLICITY.put("1..n", Multiplicity.ONE_N);
+ }
+
+ @Constructor
+ public ReferenceLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return REFERENCE;
+ }
+
+ public ReferenceDefinition load(ModelObject object, XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ assert REFERENCE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String multiplicityVal = reader.getAttributeValue(null, "multiplicity");
+ Multiplicity multiplicity = multiplicity(multiplicityVal, Multiplicity.ONE_ONE);
+ ReferenceDefinition referenceDefinition = new ReferenceDefinition();
+ referenceDefinition.setMultiplicity(multiplicity);
+ referenceDefinition.setUri(context.getComponentId().resolve('#' + name));
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject o = registry.load(null, reader, context);
+ if (o instanceof ServiceContract) {
+ referenceDefinition.setServiceContract((ServiceContract) o);
+ } else if (o instanceof BindingDefinition) {
+ referenceDefinition.addBinding((BindingDefinition) o);
+ } else {
+ throw new UnrecognizedElementException(reader.getName());
+ }
+ break;
+ case END_ELEMENT:
+ return referenceDefinition;
+ }
+ }
+ }
+
+ /**
+ * Convert a "multiplicity" attribute to the equivalent enum value.
+ *
+ * @param multiplicity the attribute to convert
+ * @param def the default value
+ * @return the enum equivalent
+ */
+ private static Multiplicity multiplicity(String multiplicity, Multiplicity def) {
+ return multiplicity == null ? def : MULTIPLICITY.get(multiplicity);
+ }
+
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java
new file mode 100644
index 0000000000..c5be797cda
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java
@@ -0,0 +1,99 @@
+/*
+ * 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.tuscany.core.loader;
+
+import java.net.URI;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.BindingDefinition;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+/**
+ * Loads a service definition from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServiceLoader extends LoaderExtension<ServiceDefinition> {
+ private static final QName SERVICE = new QName(SCA_NS, "service");
+
+ @Constructor
+ public ServiceLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return SERVICE;
+ }
+
+ public ServiceDefinition load(ModelObject object, XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ assert SERVICE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ URI compositeId = context.getComponentId();
+ URI componentBase = URI.create(compositeId + "/");
+ ServiceDefinition def = new ServiceDefinition();
+ def.setUri(compositeId.resolve('#' + name));
+
+ URI targetUri = null;
+ String promote = reader.getAttributeValue(null, "promote");
+ if (promote != null) {
+ QualifiedName qName = new QualifiedName(promote);
+ targetUri = componentBase.resolve(qName.getFragment());
+ }
+ while (true) {
+ int i = reader.next();
+ switch (i) {
+ case START_ELEMENT:
+ ModelObject o = registry.load(null, reader, context);
+ if (o instanceof ServiceContract) {
+ def.setServiceContract((ServiceContract) o);
+ } else if (o instanceof BindingDefinition) {
+ def.addBinding((BindingDefinition) o);
+ } else {
+ throw new UnrecognizedElementException(reader.getName());
+ }
+ break;
+ case END_ELEMENT:
+ if (SERVICE.equals(reader.getName())) {
+ if (targetUri != null) {
+ def.setTarget(targetUri);
+ }
+ return def;
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java
new file mode 100644
index 0000000000..eda09d6f11
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java
@@ -0,0 +1,191 @@
+/*
+ * 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.tuscany.core.loader;
+
+import java.beans.PropertyEditor;
+import java.beans.PropertyEditorManager;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.PropertyValue;
+
+import org.apache.tuscany.core.injection.SingletonObjectFactory;
+
+/**
+ * Implementation of StAXPropertyFactory that interprets the XML as
+ *
+ * @version $Rev$ $Date$
+ */
+public class StringParserPropertyFactory implements PropertyObjectFactory {
+
+ public <T> ObjectFactory<T> createObjectFactory(Property<T> property, PropertyValue<T> value)
+ throws LoaderException {
+ String text = value.getValue().getDocumentElement().getTextContent();
+ return new SingletonObjectFactory<T>(createInstance(text, property.getJavaType()));
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T createInstance(String text, Class<T> type) throws LoaderException {
+ // Class<T> type = property.getJavaType();
+ assert type != null : "property type is null";
+
+ // degenerate case where property type is a String
+ if (String.class.equals(type)) {
+ return type.cast(text);
+ }
+
+ // special handler to convert hexBinary to a byte[]
+ if (byte[].class.equals(type)) {
+ byte[] instance = new byte[text.length() >> 1];
+ for (int i = 0; i < instance.length; i++) {
+ instance[i] =
+ (byte) (Character.digit(text.charAt(i << 1), 16) << 4 | Character.digit(text
+ .charAt((i << 1) + 1), 16));
+ }
+ return type.cast(instance);
+ }
+
+ // does this type have a static valueOf(String) method?
+ try {
+ Method valueOf = type.getMethod("valueOf", String.class);
+ if (Modifier.isStatic(valueOf.getModifiers())) {
+ try {
+ return type.cast(valueOf.invoke(null, text));
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("getMethod returned an inaccessible method");
+ } catch (InvocationTargetException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e.getCause());
+ }
+ }
+ } catch (NoSuchMethodException e) {
+ // try something else
+ }
+
+ // does this type have a constructor that takes a String?
+ try {
+ Constructor<T> ctr = type.getConstructor(String.class);
+ return ctr.newInstance(text);
+ } catch (NoSuchMethodException e) {
+ // try something else
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("getConstructor returned an inaccessible method");
+ } catch (InstantiationException e) {
+ throw new LoaderException("Property type cannot be instantiated: " + type.getName());
+ } catch (InvocationTargetException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e.getCause());
+ }
+
+ // do we have a property editor for it?
+ PropertyEditor editor = PropertyEditorManager.findEditor(type);
+ if (editor != null) {
+ try {
+ editor.setAsText(text);
+ return (T) editor.getValue();
+ } catch (IllegalArgumentException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e);
+
+ }
+ }
+
+ // FIXME we should throw something better
+ throw new LoaderException("Do not have a way to parse a String into a " + type.getName());
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> ObjectFactory<T> createObjectFactory(String text, Property<T> property)
+ throws XMLStreamException, LoaderException {
+ Class<T> type = property.getJavaType();
+ assert type != null : "property type is null";
+
+ // degenerate case where property type is a String
+ if (String.class.equals(type)) {
+ return new SingletonObjectFactory<T>(type.cast(text));
+ }
+
+ // special handler to convert hexBinary to a byte[]
+ if (byte[].class.equals(type)) {
+ byte[] instance = new byte[text.length() >> 1];
+ for (int i = 0; i < instance.length; i++) {
+ instance[i] =
+ (byte) (Character.digit(text.charAt(i << 1), 16) << 4 | Character.digit(text
+ .charAt((i << 1) + 1), 16));
+ }
+ return new SingletonObjectFactory<T>(type.cast(instance));
+ }
+
+ // does this type have a static valueOf(String) method?
+ try {
+ Method valueOf = type.getMethod("valueOf", String.class);
+ if (Modifier.isStatic(valueOf.getModifiers())) {
+ try {
+ return new SingletonObjectFactory<T>(type.cast(valueOf.invoke(null, text)));
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("getMethod returned an inaccessible method");
+ } catch (InvocationTargetException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e.getCause());
+ }
+ }
+ } catch (NoSuchMethodException e) {
+ // try something else
+ }
+
+ // does this type have a constructor that takes a String?
+ try {
+ Constructor<T> ctr = type.getConstructor(String.class);
+ return new SingletonObjectFactory<T>(ctr.newInstance(text));
+ } catch (NoSuchMethodException e) {
+ // try something else
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("getConstructor returned an inaccessible method");
+ } catch (InstantiationException e) {
+ throw new LoaderException("Property type cannot be instantiated: " + type.getName());
+ } catch (InvocationTargetException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e.getCause());
+ }
+
+ // do we have a property editor for it?
+ PropertyEditor editor = PropertyEditorManager.findEditor(type);
+ if (editor != null) {
+ try {
+ editor.setAsText(text);
+ return new SingletonObjectFactory<T>((T) editor.getValue());
+ } catch (IllegalArgumentException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e);
+
+ }
+ }
+
+ // FIXME we should throw something better
+ throw new LoaderException("Do not have a way to parse a String into a " + type.getName());
+ }
+}
diff --git a/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/WireLoader.java b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/WireLoader.java
new file mode 100644
index 0000000000..9c60790111
--- /dev/null
+++ b/sandbox/rfeng/minicore/src/main/java/org/apache/tuscany/core/loader/WireLoader.java
@@ -0,0 +1,122 @@
+/*
+ * 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.tuscany.core.loader;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.InvalidWireException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.WireDefinition;
+
+/**
+ * Loads a wire from an XML-based assembly file
+ *
+ * @version $Rev: 465084 $ $Date: 2006-10-18 04:00:49 +0530 (Wed, 18 Oct 2006) $
+ */
+public class WireLoader extends LoaderExtension<WireDefinition> {
+ private static final QName WIRE = new QName(SCA_NS, "wire");
+ private static final QName SOURCE_URI = new QName(SCA_NS, "source.uri");
+ private static final QName TARGET_URI = new QName(SCA_NS, "target.uri");
+
+ @Constructor
+ public WireLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return WIRE;
+ }
+
+ public WireDefinition load(
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ assert WIRE.equals(reader.getName());
+ WireDefinition wireDefn;
+ URI sourceURI = null;
+ URI targetURI = null;
+ String uriString;
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ try {
+ if (reader.getName().equals(SOURCE_URI)) {
+ uriString = reader.getElementText();
+ if (uriString != null && uriString.trim().length() > 0) {
+ QualifiedName name = new QualifiedName(uriString);
+ if (name.getPortName() == null) {
+ sourceURI = new URI(uriString);
+ } else {
+ sourceURI = new URI(name.getPartName() + "#" + name.getPortName());
+ }
+ } else {
+ throw new InvalidWireException("Wire source not defined");
+ }
+ } else if (reader.getName().equals(TARGET_URI)) {
+ uriString = reader.getElementText();
+ if (uriString != null && uriString.trim().length() > 0) {
+ QualifiedName name = new QualifiedName(uriString);
+ if (name.getPortName() == null) {
+ targetURI = new URI(uriString);
+ } else {
+ targetURI = new URI(name.getPartName() + "#" + name.getPortName());
+ }
+ } else {
+ throw new InvalidWireException("Wire target not defined");
+ }
+ } else {
+ QName name = reader.getName();
+ throw new InvalidWireException("Unrecognized element in wire ", name.toString());
+ }
+ } catch (URISyntaxException e) {
+ throw new InvalidWireException("Invalid wire uri", e);
+ }
+
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(WIRE)) {
+ if (sourceURI != null && targetURI != null) {
+ wireDefn = new WireDefinition();
+ wireDefn.setSource(sourceURI);
+ wireDefn.setTarget(targetURI);
+ } else {
+ throw new InvalidWireException("Incomplete wire definition");
+ }
+ return wireDefn;
+ }
+ }
+ }
+ }
+}