summaryrefslogtreecommitdiffstats
path: root/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src
diff options
context:
space:
mode:
authordims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
committerdims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
commitbdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch)
tree38a92061c0793434c4be189f1d70c3458b6bc41d /tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src')
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/LogLevel.java41
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Monitor.java34
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Resource.java49
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorExtensionPoint.java48
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DuplicatePropertyException.java32
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/ExtensibleJavaClassIntrospector.java126
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IllegalPropertyException.java38
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IntrospectionException.java60
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospector.java42
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospectorExtensionPoint.java49
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java125
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java167
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java50
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java40
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java64
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java81
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java80
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java136
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java57
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java41
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java35
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java35
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java35
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java36
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java56
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java658
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java40
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java40
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java40
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java40
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java40
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java40
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java35
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java57
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java36
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java39
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java35
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java42
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java40
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java48
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java448
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java37
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java164
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java44
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java171
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java134
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java60
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java159
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java35
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java33
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java31
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java188
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/AddService.java25
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/AddServiceImpl.java35
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/CalculatorService.java34
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/CalculatorServiceImpl.java71
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/DivideService.java25
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/DivideServiceImpl.java33
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/MultiplyService.java25
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/MultiplyServiceImpl.java33
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/SubtractService.java25
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/SubtractServiceImpl.java33
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorTestCase.java95
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractProcessorTest.java80
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessorTestCase.java168
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessorTestCase.java70
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessorTestCase.java197
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorPropertyTestCase.java158
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorReferenceTestCase.java166
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorResourceTestCase.java153
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessorTestCase.java188
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessorTestCase.java144
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConvertTimeMillisTestCase.java116
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessorTestCase.java99
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessorTestCase.java59
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicAndPropertyTestCase.java75
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicConstructorTestCase.java315
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java411
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeutisticExtensibleConstructorTestCase.java153
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessorTestCase.java99
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ModelHelper.java99
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java406
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessorTestCase.java213
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessorTestCase.java224
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessorTestCase.java118
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessorTestCase.java116
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceCallbackTestCase.java169
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java152
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/ReadTestCase.java120
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/TestModelResolver.java88
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/WriteTestCase.java97
-rw-r--r--tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/Calculator.composite53
92 files changed, 9231 insertions, 0 deletions
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/LogLevel.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/LogLevel.java
new file mode 100644
index 0000000000..47e205f074
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/LogLevel.java
@@ -0,0 +1,41 @@
+/*
+ * 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.api.annotation;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation that can be applied to methods in a monitoring interface to indicate to logging frameworks the severity of
+ * the event.
+ *
+ * @version $Rev$ $Date$
+ */
+@Target({METHOD})
+@Retention(RUNTIME)
+public @interface LogLevel {
+
+ /**
+ * The log level as specified by {@link java.util.logging.Level}.
+ */
+ @SuppressWarnings({"JavaDoc"}) String value();
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Monitor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Monitor.java
new file mode 100644
index 0000000000..dea9489e5b
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Monitor.java
@@ -0,0 +1,34 @@
+/*
+ * 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.api.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A system annotation to inject a monitor
+ *
+ * @version $Rev$ $Date$
+ */
+@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Monitor {
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Resource.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Resource.java
new file mode 100644
index 0000000000..a7158ab6b8
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Resource.java
@@ -0,0 +1,49 @@
+/*
+ * 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.api.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to indicate a resource should be provided to an implementation by the runtime.
+ *
+ * @version $Rev$ $Date$
+ */
+@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Resource {
+
+ /**
+ * Denotes the name of the resource declared by the implementation.
+ */
+ String name() default "";
+
+ /**
+ * Denotes if the resource is optional
+ */
+ boolean optional() default false;
+
+ /**
+ * Denotes the default name of the resource provided by the runtime environment.
+ */
+ String mappedName() default "";
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorExtensionPoint.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorExtensionPoint.java
new file mode 100644
index 0000000000..5442bdd377
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorExtensionPoint.java
@@ -0,0 +1,48 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Default implementation of the <code>IntrospectionRegistry</code>
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultJavaClassIntrospectorExtensionPoint implements JavaClassIntrospectorExtensionPoint {
+
+ private List<JavaClassVisitor> visitors = new ArrayList<JavaClassVisitor>();
+
+ public DefaultJavaClassIntrospectorExtensionPoint() {
+ }
+
+ public void addClassVisitor(JavaClassVisitor visitor) {
+ visitors.add(visitor);
+ }
+
+ public void removeClassVisitor(JavaClassVisitor visitor) {
+ visitors.remove(visitor);
+ }
+
+ public List<JavaClassVisitor> getClassVisitors() {
+ return visitors;
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DuplicatePropertyException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DuplicatePropertyException.java
new file mode 100644
index 0000000000..43ebf79b91
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DuplicatePropertyException.java
@@ -0,0 +1,32 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+/**
+ * Thrown when an implementation has more than one property injection site with the same name
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicatePropertyException extends IntrospectionException {
+ private static final long serialVersionUID = 5536415875694904037L;
+
+ public DuplicatePropertyException(String message) {
+ super(message);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/ExtensibleJavaClassIntrospector.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/ExtensibleJavaClassIntrospector.java
new file mode 100644
index 0000000000..332eb96206
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/ExtensibleJavaClassIntrospector.java
@@ -0,0 +1,126 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper;
+
+/**
+ * An extensible Java class introspector implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleJavaClassIntrospector implements JavaClassIntrospector {
+
+ private List<JavaClassVisitor> visitors;
+
+ public ExtensibleJavaClassIntrospector(JavaClassIntrospectorExtensionPoint visitors) {
+ this.visitors = visitors.getClassVisitors();
+ }
+
+ /**
+ * JSR-250 PFD recommends the following guidelines for how annotations
+ * interact with inheritance in order to keep the resulting complexity in
+ * control:
+ * <ol>
+ * <li>Class-level annotations only affect the class they annotate and
+ * their members, that is, its methods and fields. They never affect a
+ * member declared by a superclass, even if it is not hidden or overridden
+ * by the class in question.
+ * <li>In addition to affecting the annotated class, class-level
+ * annotations may act as a shorthand for member-level annotations. If a
+ * member carries a specific member-level annotation, any annotations of the
+ * same type implied by a class-level annotation are ignored. In other
+ * words, explicit member-level annotations have priority over member-level
+ * annotations implied by a class-level annotation.
+ * <li>The interfaces implemented by a class never contribute annotations
+ * to the class itself or any of its members.
+ * <li>Members inherited from a superclass and which are not hidden or
+ * overridden maintain the annotations they had in the class that declared
+ * them, including member-level annotations implied by class-level ones.
+ * <li>Member-level annotations on a hidden or overridden member are always
+ * ignored.
+ * </ol>
+ */
+ public JavaImplementation introspect(Class<?> clazz, JavaImplementation type)
+ throws IntrospectionException {
+ for (JavaClassVisitor extension : visitors) {
+ extension.visitClass(clazz, type);
+ }
+
+ for (Constructor<?> constructor : clazz.getConstructors()) {
+ for (JavaClassVisitor extension : visitors) {
+ extension.visitConstructor(constructor, type);
+ // Assuming the visitClass or visitConstructor will populate the
+ // type.getConstructors
+ JavaConstructorImpl<?> definition = type.getConstructors().get(constructor);
+ if (definition != null) {
+ for (JavaParameterImpl p : definition.getParameters()) {
+ extension.visitConstructorParameter(p, type);
+ }
+ }
+ }
+ }
+
+ Set<Method> methods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(clazz);
+ for (Method method : methods) {
+ for (JavaClassVisitor processor : visitors) {
+ processor.visitMethod(method, type);
+ }
+ }
+
+ Set<Field> fields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(clazz);
+ for (Field field : fields) {
+ for (JavaClassVisitor extension : visitors) {
+ extension.visitField(field, type);
+ }
+ }
+
+ Class superClass = clazz.getSuperclass();
+ if (superClass != null) {
+ visitSuperClass(superClass, type);
+ }
+
+ for (JavaClassVisitor extension : visitors) {
+ extension.visitEnd(clazz, type);
+ }
+ return type;
+ }
+
+ private void visitSuperClass(Class<?> clazz, JavaImplementation type) throws IntrospectionException {
+ if (!Object.class.equals(clazz)) {
+ for (JavaClassVisitor extension : visitors) {
+ extension.visitSuperClass(clazz, type);
+ }
+ clazz = clazz.getSuperclass();
+ if (clazz != null) {
+ visitSuperClass(clazz, type);
+ }
+ }
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IllegalPropertyException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IllegalPropertyException.java
new file mode 100644
index 0000000000..c6494b3d74
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IllegalPropertyException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+import java.lang.reflect.Member;
+
+/**
+ * Denotes an illegal property definition in a component type
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalPropertyException extends IntrospectionException {
+ private static final long serialVersionUID = -2836849110706758494L;
+
+ public IllegalPropertyException(String message) {
+ super(message);
+ }
+
+ public IllegalPropertyException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IntrospectionException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IntrospectionException.java
new file mode 100644
index 0000000000..45eaf0235b
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IntrospectionException.java
@@ -0,0 +1,60 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+import java.lang.reflect.Member;
+
+/**
+ * Denotes a problem processing annotations on a POJO implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class IntrospectionException extends Exception {
+ private static final long serialVersionUID = -361025119035104470L;
+ private Member member;
+
+ public IntrospectionException() {
+ }
+
+ public IntrospectionException(String message) {
+ super(message);
+ }
+
+ public IntrospectionException(String message, Member member) {
+ super(message);
+ this.member = member;
+ }
+
+ public IntrospectionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public IntrospectionException(Throwable cause) {
+ super(cause);
+ }
+
+ public Member getMember() {
+ return member;
+ }
+
+ public void setMember(Member member) {
+ this.member = member;
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospector.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospector.java
new file mode 100644
index 0000000000..7fec71a709
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospector.java
@@ -0,0 +1,42 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+
+/**
+ * Implementations are responsible for walking a component implementation class,
+ * adding additional component type information as appropriate
+ *
+ * @version $Rev$ $Date$
+ */
+public interface JavaClassIntrospector {
+
+ /**
+ * Walks the given component implementation class
+ *
+ * @param clazz the component implementation class
+ * @param type the component type associated with the implementation class
+ * @return the updated component type
+ * @throws IntrospectionException if an error is encountered evaluating the
+ * implementation class
+ */
+ JavaImplementation introspect(Class<?> clazz, JavaImplementation type) throws IntrospectionException;
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospectorExtensionPoint.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospectorExtensionPoint.java
new file mode 100644
index 0000000000..5da3c1ff11
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospectorExtensionPoint.java
@@ -0,0 +1,49 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+import java.util.List;
+
+/**
+ * An extension point for Java class visitors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface JavaClassIntrospectorExtensionPoint {
+
+ /**
+ * Registers the given visitor.
+ *
+ * @param visitor
+ */
+ void addClassVisitor(JavaClassVisitor visitor);
+
+ /**
+ * Deregisters the given visitor.
+ */
+ void removeClassVisitor(JavaClassVisitor visitor);
+
+ /**
+ * Returns the list of visitors.
+ *
+ * @return
+ */
+ List<JavaClassVisitor> getClassVisitors();
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java
new file mode 100644
index 0000000000..f4b7446225
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java
@@ -0,0 +1,125 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+
+/**
+ * Implementations process class-level metadata, typically parsing annotations
+ * and updating the corresponding <code>ComponentType</code>. A processor
+ * may, for example, create a Property which is responsible for injecting a
+ * complex type on a component implementation instance when it is instantiated.
+ * <p/> Processors will receive callbacks as the implementation class is walked
+ * while evalauting an assembly. It is the responsibility of the parser to
+ * determine whether to perform an action during the callback.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface JavaClassVisitor {
+
+ /**
+ * A callback received when the component implementation class is first
+ * loaded
+ *
+ * @param clazz the component implementation class
+ * @param type the incomplete component type associated with the
+ * implementation class
+ * @throws IntrospectionException if an error is encountered while processing
+ * metadata
+ */
+ <T> void visitClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException;
+
+ /**
+ * A callback received as the component implementation class hierarchy is
+ * evaluated
+ *
+ * @param clazz the superclass in the component implmentation's class
+ * hierarchy
+ * @param type the incomplete component type associated with the
+ * implementation class
+ * @throws IntrospectionException if an error is encountered while processing
+ * metadata
+ */
+ <T> void visitSuperClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException;
+
+ /**
+ * A callback received as the component implementation's public and
+ * protected methods are evaluated
+ *
+ * @param method the current public or protected method being evaluated
+ * @param type the incomplete component type associated with the
+ * implementation class
+ * @throws IntrospectionException if an error is encountered while processing
+ * metadata
+ */
+ void visitMethod(Method method, JavaImplementation type) throws IntrospectionException;
+
+ /**
+ * A callback received as the component implementation's constructor used
+ * for instantiation by the runtime is evaluated. If an implementation
+ * contains more than one constructor, the constructor passed to the
+ * callback will be chosen according to the algorithm described in the SCA
+ * Java Client and Implementation Model Specification.
+ *
+ * @param constructor the constructor used for instantiating component
+ * implementation instances
+ * @param type the incomplete component type associated with the
+ * implementation class
+ * @throws IntrospectionException if an error is encountered while processing
+ * metadata
+ */
+ <T> void visitConstructor(Constructor<T> constructor, JavaImplementation type) throws IntrospectionException;
+
+ /**
+ * @param parameter
+ * @param type
+ * @throws IntrospectionException
+ */
+ void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type) throws IntrospectionException;
+
+ /**
+ * A callback received as the component implementation's public and
+ * protected fields are evaluated
+ *
+ * @param field the current public or protected field being evaluated
+ * @param type the incomplete component type associated with the
+ * implementation class
+ * @throws IntrospectionException if an error is encountered while processing
+ * metadata
+ */
+ void visitField(Field field, JavaImplementation type) throws IntrospectionException;
+
+ /**
+ * The final callback received when all other callbacks during evaluation of
+ * the component implementation have been issued
+ *
+ * @param clazz the component implementation class
+ * @param type the incomplete component type associated with the
+ * implementation class
+ * @throws IntrospectionException if an error is encountered while processing
+ * metadata
+ */
+ <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException;
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java
new file mode 100644
index 0000000000..f4c78d34ca
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java
@@ -0,0 +1,167 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.DuplicatePropertyException;
+import org.apache.tuscany.sca.implementation.java.introspect.IllegalPropertyException;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
+
+/**
+ * Base class for ImplementationProcessors that handle annotations that add
+ * Properties.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractPropertyProcessor<A extends Annotation> extends BaseJavaClassVisitor {
+ private final Class<A> annotationClass;
+
+ protected AbstractPropertyProcessor(AssemblyFactory assemblyFactory, Class<A> annotationClass) {
+ super(assemblyFactory);
+ this.annotationClass = annotationClass;
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+ A annotation = method.getAnnotation(annotationClass);
+ if (annotation == null) {
+ return;
+ }
+
+ if (!Void.TYPE.equals(method.getReturnType())) {
+ throw new IllegalPropertyException("Method does not have void return type", method);
+ }
+ Class[] paramTypes = method.getParameterTypes();
+ if (paramTypes.length != 1) {
+ throw new IllegalPropertyException("Method must have a single parameter", method);
+ }
+
+ String name = getName(annotation);
+ if (name == null || "".equals(name)) {
+ name = method.getName();
+ if (name.startsWith("set")) {
+ name = JavaIntrospectionHelper.toPropertyName(method.getName());
+ }
+ }
+
+ Map<String, JavaElementImpl> properties = type.getPropertyMembers();
+ if (properties.containsKey(name)) {
+ throw new DuplicatePropertyException(name);
+ }
+
+ JavaElementImpl element = new JavaElementImpl(method, 0);
+ Property property = createProperty(name, element);
+
+ // add databinding available as annotations, as extensions
+
+ initProperty(property, annotation);
+ type.getProperties().add(property);
+ properties.put(name, element);
+ }
+
+ public void visitField(Field field, JavaImplementation type) throws IntrospectionException {
+
+ A annotation = field.getAnnotation(annotationClass);
+ if (annotation == null) {
+ return;
+ }
+
+ String name = getName(annotation);
+ if (name == null) {
+ name = "";
+ }
+ if ("".equals(name) || name.equals(field.getType().getName())) {
+ name = field.getName();
+ }
+
+ Map<String, JavaElementImpl> properties = type.getPropertyMembers();
+ if (properties.containsKey(name)) {
+ throw new DuplicatePropertyException(name);
+ }
+
+ JavaElementImpl element = new JavaElementImpl(field);
+ Property property = createProperty(name, element);
+ initProperty(property, annotation);
+ type.getProperties().add(property);
+ properties.put(name, element);
+ }
+
+ public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type)
+ throws IntrospectionException {
+
+ Map<String, JavaElementImpl> properties = type.getPropertyMembers();
+ A annotation = parameter.getAnnotation(annotationClass);
+ if (annotation != null) {
+ String name = getName(annotation);
+ if (name == null) {
+ name = parameter.getType().getName();
+ }
+ if (!"".equals(name) && !"".equals(parameter.getName()) && !name.equals(parameter.getName())) {
+ throw new InvalidConstructorException("Mismatched property name: " + parameter);
+ }
+ if ("".equals(name) && "".equals(parameter.getName())) {
+ throw new InvalidPropertyException("Missing property name: " + parameter);
+ }
+ if ("".equals(name)) {
+ name = parameter.getName();
+ }
+
+ if (properties.containsKey(name)) {
+ throw new DuplicatePropertyException("Duplication property: " + name);
+ }
+ parameter.setName(name);
+ parameter.setClassifer(annotationClass);
+ Property property = createProperty(name, parameter);
+ initProperty(property, annotation);
+ type.getProperties().add(property);
+ properties.put(name, parameter);
+ }
+ }
+
+ protected abstract String getName(A annotation);
+
+ protected abstract void initProperty(Property property, A annotation) throws IntrospectionException;
+
+ @SuppressWarnings("unchecked")
+ protected Property createProperty(String name, JavaElementImpl element) throws IntrospectionException {
+
+ Property property = assemblyFactory.createProperty();
+ property.setName(name);
+ Class<?> baseType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType());
+ property.setXSDType(JavaXMLMapper.getXMLType(baseType));
+
+ Class<?> javaType = element.getType();
+ if (javaType.isArray() || Collection.class.isAssignableFrom(javaType)) {
+ property.setMany(true);
+ }
+ return property;
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java
new file mode 100644
index 0000000000..ab39106521
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java
@@ -0,0 +1,50 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.osoa.sca.annotations.AllowsPassByReference;
+
+/**
+ * Processes {@link AllowsPassByReference} on an implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class AllowsPassByReferenceProcessor extends BaseJavaClassVisitor {
+
+ public AllowsPassByReferenceProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public <T> void visitClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ type.setAllowsPassByReference(clazz.isAnnotationPresent(AllowsPassByReference.class));
+ }
+
+ @Override
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+ boolean pbr = method.isAnnotationPresent(AllowsPassByReference.class);
+ if (pbr) {
+ type.getAllowsPassByReferenceMethods().add(method);
+ }
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java
new file mode 100644
index 0000000000..329a4ae4be
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when constructor parameters cannot be unambiguously resolved to a property or reference
+ *
+ * @version $Rev$ $Date$
+ */
+public class AmbiguousConstructorException extends IntrospectionException {
+ private static final long serialVersionUID = 3662860753837091880L;
+
+ public AmbiguousConstructorException(String message) {
+ super(message);
+ }
+
+ public AmbiguousConstructorException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java
new file mode 100644
index 0000000000..cdc9e68996
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java
@@ -0,0 +1,64 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor;
+
+/**
+ * A convenience class for annotation processors which alleviates the need to
+ * implement unused callbacks
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class BaseJavaClassVisitor implements JavaClassVisitor {
+ protected AssemblyFactory assemblyFactory;
+
+ protected BaseJavaClassVisitor(AssemblyFactory factory) {
+ this.assemblyFactory = factory;
+ }
+
+ public <T> void visitClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ }
+
+ public <T> void visitSuperClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+ }
+
+ public <T> void visitConstructor(Constructor<T> constructor, JavaImplementation type) throws IntrospectionException {
+ }
+
+ public void visitField(Field field, JavaImplementation type) throws IntrospectionException {
+ }
+
+ public <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ }
+
+ public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type) throws IntrospectionException {
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java
new file mode 100644
index 0000000000..e28bf21d81
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java
@@ -0,0 +1,81 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Constructor;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Handles processing of a constructor decorated with
+ * {@link org.osoa.sca.annotations.Constructor}
+ *
+ * @version $Rev$ $Date$
+ */
+@SuppressWarnings("unchecked")
+public class ConstructorProcessor extends BaseJavaClassVisitor {
+
+ public ConstructorProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public <T> void visitClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ Constructor[] ctors = clazz.getConstructors();
+ boolean found = false;
+ for (Constructor constructor : ctors) {
+ JavaConstructorImpl<?> definition = new JavaConstructorImpl(constructor);
+ type.getConstructors().put(constructor, definition);
+ if (constructor.getAnnotation(org.osoa.sca.annotations.Constructor.class) != null) {
+ if (found) {
+ throw new DuplicateConstructorException("Multiple constructors marked with @Constructor", constructor);
+ }
+ found = true;
+ type.setConstructor(definition);
+ }
+ }
+ }
+
+ public <T> void visitConstructor(Constructor<T> constructor, JavaImplementation type)
+ throws IntrospectionException {
+ org.osoa.sca.annotations.Constructor annotation = constructor
+ .getAnnotation(org.osoa.sca.annotations.Constructor.class);
+ if (annotation == null) {
+ return;
+ }
+ JavaConstructorImpl<?> definition = type.getConstructor();
+ if (definition == null) {
+ definition = new JavaConstructorImpl(constructor);
+ type.setConstructor(definition);
+ }
+ JavaParameterImpl[] parameters = definition.getParameters();
+ String[] value = annotation.value();
+ boolean isDefault = value.length == 0 || (value.length == 1 && "".equals(value[0]));
+ if (!isDefault && value.length != parameters.length) {
+ throw new InvalidConstructorException("Invalid Nubmer of names in @Constructor");
+ }
+ for (int i = 0; i < parameters.length; i++) {
+ parameters[i].setName(i < value.length ? value[i] : "");
+ }
+ type.setConstructor(definition);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java
new file mode 100644
index 0000000000..823f4c6bda
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java
@@ -0,0 +1,80 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.osoa.sca.ComponentContext;
+import org.osoa.sca.RequestContext;
+import org.osoa.sca.annotations.Context;
+
+/**
+ * Processes {@link @Context} annotations on a component implementation and adds
+ * a {@link JavaMappedProperty} to the component type which will be used to
+ * inject the appropriate context
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContextProcessor extends BaseJavaClassVisitor {
+
+ public ContextProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+ if (method.getAnnotation(Context.class) == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalContextException("Context setter must have one parameter", method);
+ }
+ Class<?> paramType = method.getParameterTypes()[0];
+ String name = JavaIntrospectionHelper.toPropertyName(method.getName());
+ if (ComponentContext.class.equals(paramType) || RequestContext.class.equals(paramType)) {
+ JavaElementImpl element = new JavaElementImpl(method, 0);
+ element.setName(name);
+ element.setClassifer(org.apache.tuscany.api.annotation.Resource.class);
+ JavaResourceImpl resource = new JavaResourceImpl(element);
+ type.getResources().put(resource.getName(), resource);
+ } else {
+ throw new UnknownContextTypeException(paramType.getName());
+ }
+ }
+
+ public void visitField(Field field, JavaImplementation type) throws IntrospectionException {
+ if (field.getAnnotation(Context.class) == null) {
+ return;
+ }
+ Class<?> paramType = field.getType();
+ if (ComponentContext.class.equals(paramType) || RequestContext.class.equals(paramType)) {
+ JavaElementImpl element = new JavaElementImpl(field);
+ element.setClassifer(org.apache.tuscany.api.annotation.Resource.class);
+ JavaResourceImpl resource = new JavaResourceImpl(element);
+ type.getResources().put(resource.getName(), resource);
+ } else {
+ throw new UnknownContextTypeException(paramType.getName());
+ }
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java
new file mode 100644
index 0000000000..adc3802e99
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java
@@ -0,0 +1,136 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.osoa.sca.annotations.ConversationAttributes;
+import org.osoa.sca.annotations.ConversationID;
+import org.osoa.sca.annotations.Scope;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConversationProcessor extends BaseJavaClassVisitor {
+ private static final String SECONDS = " SECONDS";
+ private static final String MINUTES = " MINUTES";
+ private static final String HOURS = " HOURS";
+ private static final String DAYS = " DAYS";
+ private static final String YEARS = " YEARS";
+
+ public ConversationProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public <T> void visitClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+
+ ConversationAttributes conversation = clazz.getAnnotation(ConversationAttributes.class);
+ if (conversation == null) {
+ return;
+ }
+ Scope scope = clazz.getAnnotation(Scope.class);
+ if (scope == null) {
+ // implicitly assume conversation
+ type.setJavaScope(org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl.CONVERSATION);
+ } else if (scope != null && !"CONVERSATION".equals(scope.value().toUpperCase())) {
+ throw new InvalidConversationalImplementation(
+ "Service is marked with @ConversationAttributes but the scope is not @Scope(\"CONVERSATION\")"
+ );
+ } else if (conversation != null) {
+ long maxAge;
+ long maxIdleTime;
+ String maxAgeVal = conversation.maxAge();
+ String maxIdleTimeVal = conversation.maxIdleTime();
+ if (maxAgeVal.length() > 0 && maxIdleTimeVal.length() > 0) {
+ throw new InvalidConversationalImplementation("Max idle time and age both specified");
+ }
+ try {
+ if (maxAgeVal.length() > 0) {
+ maxAge = convertTimeMillis(maxAgeVal);
+ type.setMaxAge(maxAge);
+ }
+ } catch (NumberFormatException e) {
+ throw new InvalidConversationalImplementation("Invalid maximum age", e);
+ }
+ try {
+ if (maxIdleTimeVal.length() > 0) {
+ maxIdleTime = convertTimeMillis(maxIdleTimeVal);
+ type.setMaxIdleTime(maxIdleTime);
+ }
+ } catch (NumberFormatException e) {
+ throw new InvalidConversationalImplementation("Invalid maximum idle time", e);
+ }
+ }
+
+ }
+
+ public void visitMethod(Method method,
+ JavaImplementation type) throws IntrospectionException {
+ ConversationID conversationID = method.getAnnotation(ConversationID.class);
+ if (conversationID == null) {
+ return;
+ }
+ type.setConversationIDMember(method);
+ }
+
+ public void visitField(Field field,
+ JavaImplementation type) throws IntrospectionException {
+ ConversationID conversationID = field.getAnnotation(ConversationID.class);
+ if (conversationID == null) {
+ return;
+ }
+ type.setConversationIDMember(field);
+ }
+
+ protected long convertTimeMillis(String expr) throws NumberFormatException {
+ expr = expr.trim().toUpperCase();
+ int i = expr.lastIndexOf(SECONDS);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 1000;
+ }
+ i = expr.lastIndexOf(MINUTES);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 60000;
+ }
+
+ i = expr.lastIndexOf(HOURS);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 3600000;
+ }
+ i = expr.lastIndexOf(DAYS);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 86400000;
+ }
+ i = expr.lastIndexOf(YEARS);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 31556926000L;
+ }
+ return Long.parseLong(expr) * 1000; // assume seconds if no suffix
+ // specified
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java
new file mode 100644
index 0000000000..bd6ae041a9
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java
@@ -0,0 +1,57 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.osoa.sca.annotations.Destroy;
+
+/**
+ * Processes the {@link @Destroy} annotation on a component implementation and
+ * updates the component type with the decorated destructor method
+ *
+ * @version $Rev$ $Date$
+ */
+public class DestroyProcessor extends BaseJavaClassVisitor {
+
+ public DestroyProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+ Destroy annotation = method.getAnnotation(Destroy.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 0) {
+ throw new IllegalDestructorException("Destructor must not have argments", method);
+ }
+ if (type.getDestroyMethod() != null) {
+ throw new DuplicateDestructorException("More than one destructor found on implementation");
+ }
+ if (Modifier.isProtected(method.getModifiers())) {
+ method.setAccessible(true);
+ }
+ type.setDestroyMethod(method);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java
new file mode 100644
index 0000000000..46f1556b7e
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when more than one component implementation constructor is annotated with {@link
+ * org.osoa.sca.annotations.Constructor}
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateConstructorException extends IntrospectionException {
+ private static final long serialVersionUID = -5926763756570552986L;
+
+ public DuplicateConstructorException(String message) {
+ super(message);
+ }
+
+ public DuplicateConstructorException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java
new file mode 100644
index 0000000000..e32a3a3d5b
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when an implementation is annotated multiple times with {@link org.osoa.sca.annotations.Destroy}
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateDestructorException extends IntrospectionException {
+ private static final long serialVersionUID = -7474912510114895203L;
+
+ public DuplicateDestructorException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java
new file mode 100644
index 0000000000..0967ef6309
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when an implementation is annotated multiple times with {@link @org.osoa.sca.annotations.Init}
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateInitException extends IntrospectionException {
+ private static final long serialVersionUID = -6282935288115512057L;
+
+ public DuplicateInitException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java
new file mode 100644
index 0000000000..72f417244c
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when an implementation has more than one reference injection site with the same name
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateReferenceException extends IntrospectionException {
+ private static final long serialVersionUID = 907910648213477158L;
+
+ public DuplicateReferenceException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java
new file mode 100644
index 0000000000..db1b81e556
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when an implementation has more than one resource injection site with the same name
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateResourceException extends IntrospectionException {
+
+ private static final long serialVersionUID = 1619276459330463299L;
+
+ public DuplicateResourceException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java
new file mode 100644
index 0000000000..6f4d0d5194
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.osoa.sca.annotations.EagerInit;
+
+/**
+ * Handles processing of {@link org.osoa.sca.annotations.EagerInit}
+ *
+ * @version $Rev$ $Date$
+ */
+public class EagerInitProcessor extends BaseJavaClassVisitor {
+
+ public EagerInitProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public <T> void visitClass(Class<T> clazz,
+ JavaImplementation type) throws IntrospectionException {
+ super.visitClass(clazz, type);
+ EagerInit annotation = clazz.getAnnotation(EagerInit.class);
+ if (annotation == null) {
+ Class<?> superClass = clazz.getSuperclass();
+ while (!Object.class.equals(superClass)) {
+ annotation = superClass.getAnnotation(EagerInit.class);
+ if (annotation != null) {
+ break;
+ }
+ superClass = superClass.getSuperclass();
+ }
+ if (annotation == null) {
+ return;
+ }
+ }
+ type.setEagerInit(true);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java
new file mode 100644
index 0000000000..7a12d833c2
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java
@@ -0,0 +1,658 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllInterfaces;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllPublicAndProtectedFields;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.toPropertyName;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tuscany.api.annotation.Monitor;
+import org.apache.tuscany.api.annotation.Resource;
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Context;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Remotable;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * Heuristically evaluates an un-annotated Java implementation type to determine
+ * services, references, and properties according to the algorithm described in
+ * the SCA Java Client and Implementation Model Specification <p/> TODO
+ * Implement: <p/> When no service inteface is annotated, need to calculate a
+ * single service comprising all public methods that are not reference or
+ * property injection sites. If that service can be exactly mapped to an
+ * interface implemented by the class then the service interface will be defined
+ * in terms of that interface.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeuristicPojoProcessor extends BaseJavaClassVisitor {
+ private JavaInterfaceFactory javaFactory;
+ private JavaInterfaceIntrospector interfaceIntrospector;
+
+ public HeuristicPojoProcessor(AssemblyFactory assemblyFactory,
+ JavaInterfaceFactory javaFactory,
+ JavaInterfaceIntrospector interfaceIntrospector) {
+ super(assemblyFactory);
+ this.interfaceIntrospector = interfaceIntrospector;
+ this.javaFactory = javaFactory;
+ }
+
+ public <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ List<org.apache.tuscany.sca.assembly.Service> services = type.getServices();
+ if (services.isEmpty()) {
+ // heuristically determine the service
+ // TODO finish algorithm
+ Set<Class> interfaces = getAllInterfaces(clazz);
+ if (interfaces.size() == 0) {
+ // class is the interface
+ addService(type, clazz);
+ } else if (interfaces.size() == 1) {
+ // Only one interface, take it
+ addService(type, interfaces.iterator().next());
+ }
+ }
+ Set<Method> methods = getAllUniquePublicProtectedMethods(clazz);
+ if (!type.getReferenceMembers().isEmpty() || !type.getPropertyMembers().isEmpty()) {
+ // references and properties have been explicitly defined
+ if (type.getServices().isEmpty()) {
+ calculateServiceInterface(clazz, type, methods);
+ if (type.getServices().isEmpty()) {
+ throw new ServiceTypeNotFoundException(clazz.getName());
+ }
+ }
+ evaluateConstructor(type, clazz);
+ return;
+ }
+ calcPropRefs(methods, services, type, clazz);
+ evaluateConstructor(type, clazz);
+ }
+
+ private void addService(JavaImplementation type, Class<?> clazz) throws IntrospectionException {
+ try {
+ org.apache.tuscany.sca.assembly.Service service = createService(clazz);
+ type.getServices().add(service);
+ } catch (InvalidInterfaceException e) {
+ throw new IntrospectionException(e);
+ }
+ }
+
+ private boolean isPublicSetter(Method method) {
+ return method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())
+ && method.getName().startsWith("set")
+ && method.getReturnType() == void.class;
+ }
+
+ private boolean isProtectedSetter(Method method) {
+ return method.getParameterTypes().length == 1 && Modifier.isProtected(method.getModifiers())
+ && method.getName().startsWith("set")
+ && method.getReturnType() == void.class;
+ }
+
+ private <T> void calcPropRefs(Set<Method> methods,
+ List<org.apache.tuscany.sca.assembly.Service> services,
+ JavaImplementation type,
+ Class<T> clazz) throws IntrospectionException {
+ // heuristically determine the properties references
+ // make a first pass through all public methods with one param
+ Set<String> setters = new HashSet<String>();
+ for (Method method : methods) {
+ if (!isPublicSetter(method)) {
+ continue;
+ }
+ if (method.isAnnotationPresent(Callback.class) || method.isAnnotationPresent(Context.class)) {
+ continue;
+ }
+ if (!isInServiceInterface(method, services)) {
+ // Not part of the service interface
+ String name = toPropertyName(method.getName());
+ setters.add(name);
+ // avoid duplicate property or ref names
+ if (!type.getPropertyMembers().containsKey(name) && !type.getReferenceMembers().containsKey(name)) {
+ Class<?> param = method.getParameterTypes()[0];
+ Type genericType = method.getGenericParameterTypes()[0];
+ if (isReferenceType(param, genericType)) {
+ type.getReferences().add(createReference(name, param));
+ type.getReferenceMembers().put(name, new JavaElementImpl(method, 0));
+ } else {
+ type.getProperties().add(createProperty(name, param));
+ type.getPropertyMembers().put(name, new JavaElementImpl(method, 0));
+ }
+ }
+ }
+ }
+ // second pass for protected methods with one param
+ for (Method method : methods) {
+ if (!isProtectedSetter(method)) {
+ continue;
+ }
+ if (method.isAnnotationPresent(Callback.class) || method.isAnnotationPresent(Context.class)) {
+ continue;
+ }
+ Class<?> param = method.getParameterTypes()[0];
+ String name = toPropertyName(method.getName());
+ setters.add(name);
+ // avoid duplicate property or ref names
+ if (!type.getPropertyMembers().containsKey(name) && !type.getReferenceMembers().containsKey(name)) {
+ if (isReferenceType(param, method.getGenericParameterTypes()[0])) {
+ type.getReferences().add(createReference(name, param));
+ type.getReferenceMembers().put(name, new JavaElementImpl(method, 0));
+ } else {
+ type.getProperties().add(createProperty(name, param));
+ type.getPropertyMembers().put(name, new JavaElementImpl(method, 0));
+ }
+ }
+ }
+
+ // Public or protected fields unless there is a public or protected
+ // setter method
+ // for the same name
+ Set<Field> fields = getAllPublicAndProtectedFields(clazz);
+ for (Field field : fields) {
+ if (field.isAnnotationPresent(Callback.class) || field.isAnnotationPresent(Context.class)) {
+ continue;
+ }
+ if (setters.contains(field.getName())) {
+ continue;
+ }
+ String name = field.getName();
+ Class<?> paramType = field.getType();
+ if (isReferenceType(paramType, field.getGenericType())) {
+ type.getReferences().add(createReference(name, paramType));
+ type.getReferenceMembers().put(name, new JavaElementImpl(field));
+ } else {
+ type.getProperties().add(createProperty(name, paramType));
+ type.getPropertyMembers().put(name, new JavaElementImpl(field));
+ }
+ }
+ }
+
+ /**
+ * Determines the constructor to use based on the component type's
+ * references and properties
+ *
+ * @param type the component type
+ * @param clazz the implementation class corresponding to the component type
+ * @throws NoConstructorException if no suitable constructor is found
+ * @throws AmbiguousConstructorException if the parameters of a constructor
+ * cannot be unambiguously mapped to references and properties
+ */
+ @SuppressWarnings("unchecked")
+ private <T> void evaluateConstructor(JavaImplementation type, Class<T> clazz) throws IntrospectionException {
+ // determine constructor if one is not annotated
+ JavaConstructorImpl<?> definition = type.getConstructor();
+ Constructor constructor;
+ boolean explict = false;
+ if (definition != null && definition.getConstructor()
+ .isAnnotationPresent(org.osoa.sca.annotations.Constructor.class)) {
+ // the constructor was already defined explicitly
+ return;
+ } else if (definition != null) {
+ explict = true;
+ constructor = definition.getConstructor();
+ } else {
+ // no definition, heuristically determine constructor
+ Constructor[] constructors = clazz.getConstructors();
+ if (constructors.length == 0) {
+ throw new NoConstructorException("No public constructor for class");
+ } else if (constructors.length == 1) {
+ // Only one constructor, take it
+ constructor = constructors[0];
+ } else {
+ // FIXME multiple constructors, none yet done
+ Constructor<T> selected = null;
+ int sites = type.getPropertyMembers().size() + type.getReferenceMembers().size();
+ for (Constructor<T> ctor : constructors) {
+ if (ctor.getParameterTypes().length == 0) {
+ selected = ctor;
+ }
+ if (ctor.getParameterTypes().length == sites) {
+ // TODO finish
+ // selected = constructor;
+ // select constructor
+ // break;
+ }
+ }
+ if (selected == null) {
+ throw new NoConstructorException();
+ }
+ constructor = selected;
+ definition = type.getConstructors().get(selected);
+ type.setConstructor(definition);
+ // return;
+ }
+ definition = type.getConstructors().get(constructor);
+ type.setConstructor(definition);
+ }
+ JavaParameterImpl[] parameters = definition.getParameters();
+ if (parameters.length == 0) {
+ return;
+ }
+ Map<String, JavaElementImpl> props = type.getPropertyMembers();
+ Map<String, JavaElementImpl> refs = type.getReferenceMembers();
+ Annotation[][] annotations = constructor.getParameterAnnotations();
+ if (!explict) {
+ // the constructor wasn't defined by an annotation, so check to see
+ // if any of the params have an annotation
+ // which we can impute as explicitly defining the constructor, e.g.
+ // @Property, @Reference, or @Autowire
+ explict = injectionAnnotationsPresent(annotations);
+ }
+ if (explict) {
+ for (int i = 0; i < parameters.length; i++) {
+ if (isAnnotated(parameters[i])) {
+ continue;
+ } else if (!findReferenceOrProperty(parameters[i], props, refs)) {
+ throw new AmbiguousConstructorException(parameters[i].toString());
+ }
+ }
+ } else {
+ if (!areUnique(parameters)) {
+ throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor");
+ }
+ if (!calcPropRefUniqueness(props.values(), refs.values())) {
+ throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor");
+ }
+ if (!(props.isEmpty() && refs.isEmpty())) {
+ calcParamNames(parameters, props, refs);
+ } else {
+ heuristicParamNames(type, parameters);
+
+ }
+ }
+ }
+
+ private void calcParamNames(JavaParameterImpl[] parameters,
+ Map<String, JavaElementImpl> props,
+ Map<String, JavaElementImpl> refs) throws AmbiguousConstructorException {
+ // the constructor param types must unambiguously match defined
+ // reference or property types
+ for (JavaParameterImpl param : parameters) {
+ if (!findReferenceOrProperty(param, props, refs)) {
+ throw new AmbiguousConstructorException(param.getName());
+ }
+ }
+ }
+
+ private void heuristicParamNames(JavaImplementation type, JavaParameterImpl[] parameters)
+ throws IntrospectionException {
+ // heuristically determine refs and props from the parameter types
+ for (JavaParameterImpl p : parameters) {
+ String name = p.getType().getSimpleName().toLowerCase();
+ if (isReferenceType(p.getType(), p.getGenericType())) {
+ type.getReferences().add(createReference(name, p.getType()));
+ p.setClassifer(Reference.class);
+ type.getReferenceMembers().put(name, p);
+ } else {
+ type.getProperties().add(createProperty(name, p.getType()));
+ p.setClassifer(Property.class);
+ type.getPropertyMembers().put(name, p);
+ }
+ p.setName(name);
+ }
+ }
+
+ private static boolean areUnique(Class[] collection) {
+ Set<Class> set = new HashSet<Class>(Arrays.asList(collection));
+ return set.size() == collection.length;
+ }
+
+ /**
+ * Returns true if the union of the given collections of properties and
+ * references have unique Java types
+ */
+ private boolean calcPropRefUniqueness(Collection<JavaElementImpl> props, Collection<JavaElementImpl> refs) {
+
+ Class[] classes = new Class[props.size() + refs.size()];
+ int i = 0;
+ for (JavaElementImpl property : props) {
+ classes[i] = property.getType();
+ i++;
+ }
+ for (JavaElementImpl reference : refs) {
+ classes[i] = reference.getType();
+ i++;
+ }
+ return areUnique(classes);
+ }
+
+ /**
+ * Unambiguously finds the reference or property associated with the given
+ * type
+ *
+ * @return the name of the reference or property if found, null if not
+ * @throws AmbiguousConstructorException if the constructor parameter cannot
+ * be resolved to a property or reference
+ */
+ private boolean findReferenceOrProperty(JavaParameterImpl parameter,
+ Map<String, JavaElementImpl> props,
+ Map<String, JavaElementImpl> refs) throws AmbiguousConstructorException {
+
+ boolean found = false;
+ if (!"".equals(parameter.getName())) {
+ // Match by name
+ JavaElementImpl prop = props.get(parameter.getName());
+ if (prop != null && prop.getType() == parameter.getType()) {
+ parameter.setClassifer(Property.class);
+ return true;
+ }
+ JavaElementImpl ref = refs.get(parameter.getName());
+ if (ref != null && ref.getType() == parameter.getType()) {
+ parameter.setClassifer(Reference.class);
+ return true;
+ }
+ }
+ for (JavaElementImpl property : props.values()) {
+ if (property.getType() == parameter.getType()) {
+ if (found) {
+ throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type",
+ (Member)parameter.getAnchor());
+ }
+ parameter.setClassifer(Property.class);
+ parameter.setName(property.getName());
+ found = true;
+ // do not break since ambiguities must be checked, i.e. more
+ // than one prop or ref of the same type
+ }
+ }
+ for (JavaElementImpl reference : refs.values()) {
+ if (reference.getType() == parameter.getType()) {
+ if (found) {
+ throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type",
+ (Member)parameter.getAnchor());
+ }
+ parameter.setClassifer(Reference.class);
+ parameter.setName(reference.getName());
+ found = true;
+ // do not break since ambiguities must be checked, i.e. more
+ // than one prop or ref of the same type
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Returns true if a given type is reference according to the SCA
+ * specification rules for determining reference types The following rules
+ * are used to determine whether an unannotated field or setter method is a
+ * property or reference:
+ * <ol>
+ * <li>If its type is simple, then it is a property.
+ * <li>If its type is complex, then if the type is an interface marked by
+ *
+ * @Remotable, then it is a reference; otherwise, it is a property.
+ * <li>Otherwise, if the type associated with the member is an
+ * array or a java.util.Collection, the basetype is the element
+ * type of the array or the parameterized type of the
+ * Collection; otherwise the basetype is the member type. If the
+ * basetype is an interface with an
+ * @Remotable or
+ * @Service annotation then the memberis defined as a reference. Otherwise,
+ * it is defined as a property.
+ * </ol>
+ * <p>
+ * The name of the reference or of the property is derived from the
+ * name found on the setter method or on the field.
+ */
+ private boolean isReferenceType(Class<?> cls, Type genericType) {
+ Class<?> baseType = JavaIntrospectionHelper.getBaseType(cls, genericType);
+ return baseType.isInterface() && (baseType.isAnnotationPresent(Remotable.class) || baseType
+ .isAnnotationPresent(Service.class));
+ }
+
+ /**
+ * Returns true if the given operation is defined in the collection of
+ * service interfaces
+ */
+ private boolean isInServiceInterface(Method operation, List<org.apache.tuscany.sca.assembly.Service> services) {
+ for (org.apache.tuscany.sca.assembly.Service service : services) {
+ Interface interface1 = service.getInterfaceContract().getInterface();
+ if (interface1 instanceof JavaInterface) {
+ Class<?> clazz = ((JavaInterface)interface1).getJavaClass();
+ if (isMethodMatched(clazz, operation)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Test if the class declares a method which matches the signature of the
+ * given method
+ *
+ * @param clazz
+ * @param method
+ * @return
+ */
+ private boolean isMethodMatched(Class<?> clazz, Method method) {
+ if (method.getDeclaringClass() == clazz) {
+ return true;
+ }
+ Method[] methods = clazz.getMethods();
+ for (Method m : methods) {
+ if (JavaIntrospectionHelper.exactMethodMatch(method, m)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Creates a mapped property
+ *
+ * @param name the property name
+ * @param member the injection site the reference maps to
+ * @param paramType the property type
+ */
+ private org.apache.tuscany.sca.assembly.Property createProperty(String name, Class<?> paramType) {
+ org.apache.tuscany.sca.assembly.Property property = assemblyFactory.createProperty();
+ property.setName(name);
+ property.setXSDType(JavaXMLMapper.getXMLType(paramType));
+ return property;
+ }
+
+ /**
+ * Populates a component type with a service whose interface type is
+ * determined by examining all implemented interfaces of the given class and
+ * chosing one whose operations match all of the class's non-property and
+ * non-reference methods
+ *
+ * @param clazz the class to examine
+ * @param type the component type
+ * @param methods all methods in the class to examine
+ */
+ private void calculateServiceInterface(Class<?> clazz, JavaImplementation type, Set<Method> methods)
+ throws IntrospectionException {
+ List<Method> nonPropRefMethods = new ArrayList<Method>();
+ // Map<String, Service> services = type.getServices();
+ Map<String, JavaElementImpl> references = type.getReferenceMembers();
+ Map<String, JavaElementImpl> properties = type.getPropertyMembers();
+ // calculate methods that are not properties or references
+ for (Method method : methods) {
+ String name = toPropertyName(method.getName());
+ if (!references.containsKey(name) && !properties.containsKey(name)) {
+ nonPropRefMethods.add(method);
+ }
+ }
+ // determine if an implemented interface matches all of the non-property
+ // and non-reference methods
+ Class[] interfaces = clazz.getInterfaces();
+ if (interfaces.length == 0) {
+ return;
+ }
+ for (Class interfaze : interfaces) {
+ if (analyzeInterface(interfaze, nonPropRefMethods)) {
+ org.apache.tuscany.sca.assembly.Service service;
+ try {
+ service = createService(interfaze);
+ } catch (InvalidInterfaceException e) {
+ throw new IntrospectionException(e);
+ }
+ type.getServices().add(service);
+ }
+ }
+ }
+
+ /**
+ * Determines if the methods of a given interface match the given list of
+ * methods
+ *
+ * @param interfaze the interface to examine
+ * @param nonPropRefMethods the list of methods to match against
+ * @return true if the interface matches
+ */
+ private boolean analyzeInterface(Class<?> interfaze, List<Method> nonPropRefMethods) {
+ Method[] interfaceMethods = interfaze.getMethods();
+ if (nonPropRefMethods.size() != interfaceMethods.length) {
+ return false;
+ }
+ for (Method method : nonPropRefMethods) {
+ boolean found = isMethodMatched(interfaze, method);
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isAnnotated(JavaParameterImpl parameter) {
+ for (Annotation annotation : parameter.getAnnotations()) {
+ Class<? extends Annotation> annotType = annotation.annotationType();
+ if (annotType.equals(Property.class) || annotType.equals(Reference.class)
+ || annotType.equals(Resource.class)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean areUnique(JavaParameterImpl[] parameters) {
+ Set<Class> set = new HashSet<Class>(parameters.length);
+ for (JavaParameterImpl p : parameters) {
+ if (!set.add(p.getType())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public org.apache.tuscany.sca.assembly.Reference createReference(String name, Class<?> paramType)
+ throws IntrospectionException {
+ org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference();
+ reference.setName(name);
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ reference.setInterfaceContract(interfaceContract);
+ try {
+ JavaInterface callInterface = interfaceIntrospector.introspect(paramType);
+ reference.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = interfaceIntrospector.introspect(callInterface.getCallbackClass());
+ reference.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ reference.setMultiplicity(Multiplicity.ZERO_ONE);
+ } catch (InvalidInterfaceException e1) {
+ throw new IntrospectionException(e1);
+ }
+ try {
+ processCallback(paramType, reference);
+ } catch (InvalidServiceType e) {
+ throw new IntrospectionException(e);
+ }
+ return reference;
+ }
+
+ public org.apache.tuscany.sca.assembly.Service createService(Class<?> interfaze) throws InvalidInterfaceException {
+ org.apache.tuscany.sca.assembly.Service service = assemblyFactory.createService();
+ service.setName(interfaze.getSimpleName());
+
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ service.setInterfaceContract(interfaceContract);
+
+ JavaInterface callInterface = interfaceIntrospector.introspect(interfaze);
+ service.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = interfaceIntrospector.introspect(callInterface.getCallbackClass());
+ service.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+
+ Interface javaInterface = service.getInterfaceContract().getInterface();
+ javaInterface.setRemotable(interfaze.getAnnotation(Remotable.class) != null);
+ service.getInterfaceContract().setInterface(javaInterface);
+ return service;
+ }
+
+ public void processCallback(Class<?> interfaze, Contract contract) throws InvalidServiceType {
+ Callback callback = interfaze.getAnnotation(Callback.class);
+ if (callback != null && !Void.class.equals(callback.value())) {
+ Class<?> callbackClass = callback.value();
+ JavaInterface javaInterface = javaFactory.createJavaInterface();
+ javaInterface.setJavaClass(callbackClass);
+ contract.getInterfaceContract().setCallbackInterface(javaInterface);
+ } else if (callback != null && Void.class.equals(callback.value())) {
+ throw new InvalidServiceType("No callback interface specified on annotation", interfaze);
+ }
+ }
+
+ public boolean injectionAnnotationsPresent(Annotation[][] annots) {
+ for (Annotation[] annotations : annots) {
+ for (Annotation annotation : annotations) {
+ Class<? extends Annotation> annotType = annotation.annotationType();
+ if (annotType.equals(Property.class) || annotType.equals(Reference.class)
+ || annotType.equals(Resource.class)
+ || annotType.equals(Monitor.class)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java
new file mode 100644
index 0000000000..fd8df4e838
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an illegcal use of {@link org.osoa.sca.annotations.Callback} on a reference
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalCallbackReferenceException extends IntrospectionException {
+ private static final long serialVersionUID = -8932525723147700591L;
+
+ public IllegalCallbackReferenceException(String message) {
+ super(message);
+ }
+
+ public IllegalCallbackReferenceException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java
new file mode 100644
index 0000000000..9b548159db
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Context}
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalContextException extends IntrospectionException {
+ private static final long serialVersionUID = -6946383136750117008L;
+
+ public IllegalContextException(String message) {
+ super(message);
+ }
+
+ public IllegalContextException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java
new file mode 100644
index 0000000000..4e5620119b
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Destroy}
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalDestructorException extends IntrospectionException {
+ private static final long serialVersionUID = 365719353107446326L;
+
+ public IllegalDestructorException(String message) {
+ super(message);
+ }
+
+ public IllegalDestructorException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java
new file mode 100644
index 0000000000..bec7c29c54
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an illegal signature for a method decorated with {@link @org.osoa.sca.annotations.Init}
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalInitException extends IntrospectionException {
+ private static final long serialVersionUID = -3690763271986854701L;
+
+ public IllegalInitException(String message) {
+ super(message);
+ }
+
+ public IllegalInitException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java
new file mode 100644
index 0000000000..94ea3d1c0b
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an illegal reference definition in a component type
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalReferenceException extends IntrospectionException {
+ private static final long serialVersionUID = 4612984122225271395L;
+
+ public IllegalReferenceException(String message) {
+ super(message);
+ }
+
+ public IllegalReferenceException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java
new file mode 100644
index 0000000000..44ba25c460
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an illegal resource definition in a component type
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalResourceException extends IntrospectionException {
+ private static final long serialVersionUID = -1100936539412435579L;
+
+ public IllegalResourceException(String message) {
+ super(message);
+ }
+
+ public IllegalResourceException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java
new file mode 100644
index 0000000000..14079b2b1d
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an illegal use of the {@link @org.osoa.sca.annotations.Service} annotation
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalServiceDefinitionException extends IntrospectionException {
+ private static final long serialVersionUID = -7151534258405092548L;
+
+ public IllegalServiceDefinitionException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java
new file mode 100644
index 0000000000..0d2ac820a1
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java
@@ -0,0 +1,57 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.osoa.sca.annotations.Init;
+
+/**
+ * Processes the {@link @Init} annotation on a component implementation and
+ * updates the component type with the decorated initializer method
+ *
+ * @version $Rev$ $Date$
+ */
+public class InitProcessor extends BaseJavaClassVisitor {
+
+ public InitProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+ Init annotation = method.getAnnotation(Init.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 0) {
+ throw new IllegalInitException("Initializer must not have argments", method);
+ }
+ if (type.getInitMethod() != null) {
+ throw new DuplicateInitException("More than one initializer found on implementaton");
+ }
+ if (Modifier.isProtected(method.getModifiers())) {
+ method.setAccessible(true);
+ }
+ type.setInitMethod(method);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java
new file mode 100644
index 0000000000..0435cdee67
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an invalid constructor definition, e.g. when the number of injection names specified in {@link
+ * org.osoa.sca.annotations.Constructor} do not match the number of actual constructor parameters
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidConstructorException extends IntrospectionException {
+ private static final long serialVersionUID = 1411492435210741512L;
+
+ public InvalidConstructorException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java
new file mode 100644
index 0000000000..fdc6f1dd34
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java
@@ -0,0 +1,39 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Raised when an implementation specifies improper conversational metadata
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidConversationalImplementation extends IntrospectionException {
+ private static final long serialVersionUID = -5487291552769408149L;
+
+ public InvalidConversationalImplementation(String message) {
+ super(message);
+ }
+
+ public InvalidConversationalImplementation(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java
new file mode 100644
index 0000000000..dc1cc2e0e9
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an invalid usage of {@link org.osoa.sca.annotations.Property}
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidPropertyException extends IntrospectionException {
+ private static final long serialVersionUID = -2682862652069727948L;
+
+ public InvalidPropertyException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java
new file mode 100644
index 0000000000..79b81afcb7
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java
@@ -0,0 +1,42 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an invalid usage of {@link org.osoa.sca.annotations.Reference}
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidReferenceException extends IntrospectionException {
+ private static final long serialVersionUID = -3285246635989254165L;
+
+ public InvalidReferenceException(String message) {
+ super(message);
+ }
+
+ public InvalidReferenceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InvalidReferenceException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java
new file mode 100644
index 0000000000..1b47090e55
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Member;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Denotes an invalid usage of {@link @org.apache.tuscany.api.annotation.Resource}
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidResourceException extends IntrospectionException {
+ private static final long serialVersionUID = 511728001735534934L;
+
+ public InvalidResourceException(String message) {
+ super(message);
+ }
+
+ public InvalidResourceException(String message, Member member) {
+ super(message, member);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java
new file mode 100644
index 0000000000..a7e4b0d827
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java
@@ -0,0 +1,48 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when a service type specified by an {@link org.osoa.sca.annotations.Service} annotation is invalid, e.g. it is
+ * not an interface
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidServiceType extends IntrospectionException {
+ private static final long serialVersionUID = -1076466639416644386L;
+ private Class<?> serviceType;
+
+ public InvalidServiceType(String message) {
+ super(message);
+ }
+
+ public InvalidServiceType(String message, Class<?> clazz) {
+ super(message);
+ this.serviceType = clazz;
+ }
+
+ /**
+ * @return the serviceType
+ */
+ public Class<?> getServiceType() {
+ return serviceType;
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java
new file mode 100644
index 0000000000..e0f1a0d52a
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java
@@ -0,0 +1,448 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.beans.Introspector;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Implements various reflection-related operations
+ *
+ * @version $Rev$ $Date$
+ */
+public final class JavaIntrospectionHelper {
+
+ private static final Class[] EMPTY_CLASS_ARRY = new Class[0];
+
+ /**
+ * Hide the constructor
+ */
+ private JavaIntrospectionHelper() {
+ }
+
+ /**
+ * Returns a collection of public, and protected fields declared by a class
+ * or one of its supertypes
+ */
+ public static Set<Field> getAllPublicAndProtectedFields(Class clazz) {
+ return getAllPublicAndProtectedFields(clazz, new HashSet<Field>());
+ }
+
+ /**
+ * Recursively evaluates the type hierachy to return all fields that are
+ * public or protected
+ */
+ private static Set<Field> getAllPublicAndProtectedFields(Class clazz, Set<Field> fields) {
+ if (clazz == null || clazz.isArray() || Object.class.equals(clazz)) {
+ return fields;
+ }
+ fields = getAllPublicAndProtectedFields(clazz.getSuperclass(), fields);
+ Field[] declaredFields = clazz.getDeclaredFields();
+ for (Field field : declaredFields) {
+ int modifiers = field.getModifiers();
+ if ((Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) && !Modifier.isStatic(modifiers)) {
+ field.setAccessible(true); // ignore Java accessibility
+ fields.add(field);
+ }
+ }
+ return fields;
+ }
+
+ /**
+ * Returns a collection of public and protected methods declared by a class
+ * or one of its supertypes. Note that overriden methods will not be
+ * returned in the collection (i.e. only the method override will be). <p/>
+ * This method can potentially be expensive as reflection information is not
+ * cached. It is assumed that this method will be used during a
+ * configuration phase.
+ */
+ public static Set<Method> getAllUniquePublicProtectedMethods(Class clazz) {
+ return getAllUniqueMethods(clazz, new HashSet<Method>());
+ }
+
+ /**
+ * Recursively evaluates the type hierarchy to return all unique methods
+ */
+ private static Set<Method> getAllUniqueMethods(Class pClass, Set<Method> methods) {
+ if (pClass == null || pClass.isArray() || Object.class.equals(pClass)) {
+ return methods;
+ }
+ // we first evaluate methods of the subclass and then move to the parent
+ Method[] declaredMethods = pClass.getDeclaredMethods();
+ for (Method declaredMethod : declaredMethods) {
+ int modifiers = declaredMethod.getModifiers();
+ if ((!Modifier.isPublic(modifiers) && !Modifier.isProtected(modifiers)) || Modifier.isStatic(modifiers)) {
+ continue;
+ }
+ if (methods.size() == 0) {
+ methods.add(declaredMethod);
+ } else {
+ List<Method> temp = new ArrayList<Method>();
+ boolean matched = false;
+ for (Method method : methods) {
+ // only add if not already in the set from a supclass (i.e.
+ // the
+ // method is not overrided)
+ if (exactMethodMatch(declaredMethod, method)) {
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ // TODO ignore Java accessibility
+ declaredMethod.setAccessible(true);
+ temp.add(declaredMethod);
+ }
+ methods.addAll(temp);
+ temp.clear();
+ }
+ }
+ // evaluate class hierarchy - this is done last to track inherited
+ // methods
+ methods = getAllUniqueMethods(pClass.getSuperclass(), methods);
+ return methods;
+ }
+
+ /**
+ * Finds the closest matching field with the given name, that is, a field of
+ * the exact specified type or, alternately, of a supertype.
+ *
+ * @param name the name of the field
+ * @param type the field type
+ * @param fields the collection of fields to search
+ * @return the matching field or null if not found
+ */
+ public static Field findClosestMatchingField(String name, Class type, Set<Field> fields) {
+ Field candidate = null;
+ for (Field field : fields) {
+ if (field.getName().equals(name)) {
+ if (field.getType().equals(type)) {
+ return field; // exact match
+ } else if (field.getType().isAssignableFrom(type)
+ || (field.getType().isPrimitive() && primitiveAssignable(field.getType(), type))) {
+ // We could have the situation where a field parameter is a
+ // primitive and the demarshalled value is
+ // an object counterpart (e.g. Integer and int)
+ // @spec issue
+ // either an interface or super class, so keep a reference
+ // until
+ // we know there are no closer types
+ candidate = field;
+ }
+ }
+ }
+ if (candidate != null) {
+ return candidate;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Finds the closest matching method with the given name, that is, a method
+ * taking the exact parameter types or, alternately, parameter supertypes.
+ *
+ * @param name the name of the method
+ * @param types the method parameter types
+ * @param methods the collection of methods to search
+ * @return the matching method or null if not found
+ */
+ public static Method findClosestMatchingMethod(String name, Class[] types, Set<Method> methods) {
+ if (types == null) {
+ types = EMPTY_CLASS_ARRY;
+ }
+ Method candidate = null;
+ for (Method method : methods) {
+ if (method.getName().equals(name) && method.getParameterTypes().length == types.length) {
+ Class<?>[] params = method.getParameterTypes();
+ boolean disqualify = false;
+ boolean exactMatch = true;
+ for (int i = 0; i < params.length; i++) {
+ if (!params[i].equals(types[i]) && !params[i].isAssignableFrom(types[i])) {
+ // no match
+ disqualify = true;
+ exactMatch = false;
+ break;
+ } else if (!params[i].equals(types[i]) && params[i].isAssignableFrom(types[i])) {
+ // not exact match
+ exactMatch = false;
+ }
+ }
+ if (disqualify) {
+ continue;
+ } else if (exactMatch) {
+ return method;
+ } else {
+ candidate = method;
+ }
+ }
+ }
+ if (candidate != null) {
+ return candidate;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Determines if two methods "match" - that is, they have the same method
+ * names and exact parameter types (one is not a supertype of the other)
+ */
+ public static boolean exactMethodMatch(Method method1, Method method2) {
+ if (!method1.getName().equals(method2.getName())) {
+ return false;
+ }
+ Class<?>[] types1 = method1.getParameterTypes();
+ Class<?>[] types2 = method2.getParameterTypes();
+ if (types1.length != types2.length) {
+ return false;
+ }
+ boolean matched = true;
+ for (int i = 0; i < types1.length; i++) {
+ if (types1[i] != types2[i]) {
+ matched = false;
+ break;
+ }
+ }
+ return matched;
+ }
+
+ public static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) throws NoSuchMethodException {
+ return clazz.getConstructor((Class[])null);
+ }
+
+ /**
+ * Returns the simple name of a class - i.e. the class name devoid of its
+ * package qualifier
+ *
+ * @param implClass the implmentation class
+ */
+ public static String getBaseName(Class<?> implClass) {
+ return implClass.getSimpleName();
+ }
+
+ public static boolean isImmutable(Class clazz) {
+ return String.class == clazz || clazz.isPrimitive()
+ || Number.class.isAssignableFrom(clazz)
+ || Boolean.class.isAssignableFrom(clazz)
+ || Character.class.isAssignableFrom(clazz)
+ || Byte.class.isAssignableFrom(clazz);
+ }
+
+ /**
+ * Takes a property name and converts it to a getter method name according
+ * to JavaBean conventions. For example, property
+ * <code>foo<code> is returned as <code>getFoo</code>
+ */
+ public static String toGetter(String name) {
+ return "get" + name.toUpperCase().substring(0, 1) + name.substring(1);
+ }
+
+ /**
+ * Takes a setter or getter method name and converts it to a property name
+ * according to JavaBean conventions. For example, <code>setFoo(var)</code>
+ * is returned as property <code>foo<code>
+ */
+ public static String toPropertyName(String name) {
+ if (!name.startsWith("set")) {
+ return name;
+ }
+ return Introspector.decapitalize(name.substring(3));
+ }
+
+ public static Class<?> getErasure(Type type) {
+ if (type instanceof Class) {
+ return (Class)type;
+ } else if (type instanceof GenericArrayType) {
+ // FIXME: How to deal with the []?
+ GenericArrayType arrayType = (GenericArrayType)type;
+ return getErasure(arrayType.getGenericComponentType());
+ } else if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType)type;
+ return getErasure(pType.getRawType());
+ } else if (type instanceof WildcardType) {
+ WildcardType wType = (WildcardType)type;
+ Type[] types = wType.getUpperBounds();
+ return getErasure(types[0]);
+ } else if (type instanceof TypeVariable) {
+ TypeVariable var = (TypeVariable)type;
+ Type[] types = var.getBounds();
+ return getErasure(types[0]);
+ }
+ return null;
+ }
+
+ public static Class<?> getBaseType(Class<?> cls, Type genericType) {
+ if (cls.isArray()) {
+ return cls.getComponentType();
+ } else if (Collection.class.isAssignableFrom(cls)) {
+ if (genericType instanceof ParameterizedType) {
+ // Collection<BaseType>
+ ParameterizedType parameterizedType = (ParameterizedType)genericType;
+ Type baseType = parameterizedType.getActualTypeArguments()[0];
+ if (baseType instanceof GenericArrayType) {
+ // Base is array
+ return cls;
+ } else {
+ return getErasure(baseType);
+ }
+ } else {
+ return cls;
+ }
+ } else {
+ return cls;
+ }
+ }
+
+ /**
+ * Takes a property name and converts it to a setter method name according
+ * to JavaBean conventions. For example, the property
+ * <code>foo<code> is returned as <code>setFoo(var)</code>
+ */
+ public static String toSetter(String name) {
+ return "set" + name.toUpperCase().substring(0, 1) + name.substring(1);
+ }
+
+ /**
+ * Compares a two types, assuming one is a primitive, to determine if the
+ * other is its object counterpart
+ */
+ private static boolean primitiveAssignable(Class memberType, Class param) {
+ if (memberType == Integer.class) {
+ return param == Integer.TYPE;
+ } else if (memberType == Double.class) {
+ return param == Double.TYPE;
+ } else if (memberType == Float.class) {
+ return param == Float.TYPE;
+ } else if (memberType == Short.class) {
+ return param == Short.TYPE;
+ } else if (memberType == Character.class) {
+ return param == Character.TYPE;
+ } else if (memberType == Boolean.class) {
+ return param == Boolean.TYPE;
+ } else if (memberType == Byte.class) {
+ return param == Byte.TYPE;
+ } else if (param == Integer.class) {
+ return memberType == Integer.TYPE;
+ } else if (param == Double.class) {
+ return memberType == Double.TYPE;
+ } else if (param == Float.class) {
+ return memberType == Float.TYPE;
+ } else if (param == Short.class) {
+ return memberType == Short.TYPE;
+ } else if (param == Character.class) {
+ return memberType == Character.TYPE;
+ } else if (param == Boolean.class) {
+ return memberType == Boolean.TYPE;
+ } else if (param == Byte.class) {
+ return memberType == Byte.TYPE;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the generic types represented in the given type. Usage as
+ * follows: <code>
+ * JavaIntrospectionHelper.getGenerics(field.getGenericType());
+ * <p/>
+ * JavaIntrospectionHelper.getGenerics(m.getGenericParameterTypes()[0];); </code>
+ *
+ * @return the generic types in order of declaration or an empty array if
+ * the type is not genericized
+ */
+ public static List<? extends Type> getGenerics(Type genericType) {
+ List<Type> classes = new ArrayList<Type>();
+ if (genericType instanceof ParameterizedType) {
+ ParameterizedType ptype = (ParameterizedType)genericType;
+ // get the type arguments
+ Type[] targs = ptype.getActualTypeArguments();
+ for (Type targ : targs) {
+ classes.add(targ);
+ }
+ }
+ return classes;
+ }
+
+ /**
+ * Returns the generic type specified by the class at the given position as
+ * in: <p/> <code> public class Foo<Bar,Baz>{ //.. }
+ * <p/>
+ * JavaIntrospectionHelper.introspectGeneric(Foo.class,1); <code>
+ * <p/>
+ * will return Baz.
+ */
+ public static Class introspectGeneric(Class<?> clazz, int pos) {
+ assert clazz != null : "No class specified";
+ Type type = clazz.getGenericSuperclass();
+ if (type instanceof ParameterizedType) {
+ Type[] args = ((ParameterizedType)type).getActualTypeArguments();
+ if (args.length <= pos) {
+ throw new IllegalArgumentException("Invalid index value for generic class " + clazz.getName());
+ }
+ return (Class)((ParameterizedType)type).getActualTypeArguments()[pos];
+ } else {
+ Type[] interfaces = clazz.getGenericInterfaces();
+ for (Type itype : interfaces) {
+ if (!(itype instanceof ParameterizedType)) {
+ continue;
+ }
+ ParameterizedType interfaceType = (ParameterizedType)itype;
+ return (Class)interfaceType.getActualTypeArguments()[0];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the set of interfaces implemented by the given class and its
+ * ancestors or a blank set if none
+ */
+ public static Set<Class> getAllInterfaces(Class clazz) {
+ Set<Class> implemented = new HashSet<Class>();
+ getAllInterfaces(clazz, implemented);
+ return implemented;
+ }
+
+ private static void getAllInterfaces(Class clazz, Set<Class> implemented) {
+ Class[] interfaces = clazz.getInterfaces();
+ for (Class interfaze : interfaces) {
+ implemented.add(interfaze);
+ }
+ Class<?> superClass = clazz.getSuperclass();
+ // Object has no superclass so check for null
+ if (superClass != null && !superClass.equals(Object.class)) {
+ getAllInterfaces(superClass, implemented);
+ }
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java
new file mode 100644
index 0000000000..2caa4b8bde
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when a suitable constructor for a component implementation cannot be found
+ *
+ * @version $Rev$ $Date$
+ */
+public class NoConstructorException extends IntrospectionException {
+ private static final long serialVersionUID = 3086706387280694424L;
+
+ public NoConstructorException() {
+ }
+
+ public NoConstructorException(String message) {
+ super(message);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java
new file mode 100644
index 0000000000..a674197b6f
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java
@@ -0,0 +1,164 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Callback;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.PolicyFactory;
+import org.osoa.sca.annotations.Requires;
+
+/**
+ * Processes an {@link org.osoa.sca.annotations.Requires} annotation
+ *
+ * @version $Rev:
+ */
+public class PolicyProcessor extends BaseJavaClassVisitor {
+
+ private PolicyFactory policyFactory;
+
+ public PolicyProcessor(AssemblyFactory assemblyFactory, PolicyFactory policyFactory) {
+ super(assemblyFactory);
+ this.policyFactory = policyFactory;
+ }
+
+ private QName getQName(String intentName) {
+ QName qname;
+ if (intentName.startsWith("{")) {
+ int i = intentName.indexOf('}');
+ if (i != -1) {
+ qname = new QName(intentName.substring(1, i), intentName.substring(i + 1));
+ } else {
+ qname = new QName("", intentName);
+ }
+ } else {
+ qname = new QName("", intentName);
+ }
+ return qname;
+ }
+
+ /**
+ * Read policy intents on the given interface or class
+ * @param clazz
+ * @param requiredIntents
+ */
+ private void readIntents(Class<?> clazz, List<Intent> requiredIntents) {
+ Requires intentAnnotation = clazz.getAnnotation(Requires.class);
+ if (intentAnnotation != null) {
+ String[] intentNames = intentAnnotation.value();
+ if (intentNames.length != 0) {
+ for (String intentName : intentNames) {
+
+ // Add each intent to the list
+ Intent intent = policyFactory.createIntent();
+ intent.setName(getQName(intentName));
+ requiredIntents.add(intent);
+ }
+ }
+ }
+ }
+
+ private void readIntents(Method method, List<Intent> requiredIntents) {
+ Requires intentAnnotation = method.getAnnotation(Requires.class);
+ if (intentAnnotation != null) {
+ String[] intentNames = intentAnnotation.value();
+ if (intentNames.length != 0) {
+ Operation operation = assemblyFactory.createOperation();
+ operation.setName(method.getName());
+ operation.setUnresolved(true);
+ for (String intentName : intentNames) {
+
+ // Add each intent to the list, associated with the
+ // operation corresponding to the annotated method
+ Intent intent = policyFactory.createIntent();
+ intent.setName(getQName(intentName));
+ intent.getOperations().add(operation);
+ requiredIntents.add(intent);
+ }
+ }
+ }
+ }
+
+ public <T> void visitClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+
+ // Read intents on the Java implementation class
+ readIntents(clazz, type.getRequiredIntents());
+
+ // Process annotations on the service interfaces
+ //TODO This will have to move to a JavaInterface introspector later
+ for (Service service: type.getServices()) {
+ InterfaceContract interfaceContract = service.getInterfaceContract();
+ if (interfaceContract instanceof JavaInterfaceContract) {
+ JavaInterfaceContract javaInterfaceContract = (JavaInterfaceContract)interfaceContract;
+
+ // Read intents on the service interface
+ if (javaInterfaceContract.getInterface() != null) {
+ JavaInterface javaInterface = (JavaInterface)javaInterfaceContract.getInterface();
+ if (javaInterface.getJavaClass() != null) {
+ readIntents(javaInterface.getJavaClass(), service.getRequiredIntents());
+
+ // Read intents on the service interface methods
+ Method[] methods = javaInterface.getJavaClass().getMethods();
+ for (Method method: methods) {
+ readIntents(method, service.getRequiredIntents());
+ }
+ }
+
+ }
+
+ // Read intents on the callback interface
+ if (javaInterfaceContract.getCallbackInterface() != null) {
+ JavaInterface javaCallbackInterface = (JavaInterface)javaInterfaceContract.getCallbackInterface();
+ if (javaCallbackInterface.getJavaClass() != null) {
+ Callback callback = service.getCallback();
+ if (callback == null) {
+ callback = assemblyFactory.createCallback();
+ service.setCallback(callback);
+ }
+ readIntents(javaCallbackInterface.getJavaClass(), callback.getRequiredIntents());
+
+ // Read intents on the callback interface methods
+ Method[] methods = javaCallbackInterface.getJavaClass().getMethods();
+ for (Method method: methods) {
+ readIntents(method, callback.getRequiredIntents());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+
+ // Read the intents specified on the given implementation method
+ readIntents(method, type.getRequiredIntents());
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java
new file mode 100644
index 0000000000..e3c7ad03df
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.osoa.sca.annotations.Property;
+
+/**
+ * Processes an {@link @Property} annotation, updating the component type with
+ * corresponding {@link JavaMappedProperty}
+ *
+ * @version $Rev$ $Date$
+ */
+public class PropertyProcessor extends AbstractPropertyProcessor<Property> {
+
+ public PropertyProcessor(AssemblyFactory assemblyFactory) {
+ super(assemblyFactory, Property.class);
+ }
+
+ protected String getName(Property annotation) {
+ return annotation.name();
+ }
+
+ protected void initProperty(org.apache.tuscany.sca.assembly.Property property, Property annotation) {
+ property.setMustSupply(annotation.required());
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java
new file mode 100644
index 0000000000..2bd6ce20ba
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java
@@ -0,0 +1,171 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getBaseType;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospector;
+import org.osoa.sca.annotations.Reference;
+
+/**
+ * Processes an {@link @Reference} annotation, updating the component type with
+ * corresponding {@link
+ * org.apache.tuscany.spi.implementation.java.JavaMappedReference}
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReferenceProcessor extends BaseJavaClassVisitor {
+ private JavaInterfaceIntrospector interfaceIntrospector;
+ private JavaInterfaceFactory javaFactory;
+
+ public ReferenceProcessor(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory, JavaInterfaceIntrospector interfaceIntrospector) {
+ super(assemblyFactory);
+ this.javaFactory = javaFactory;
+ this.interfaceIntrospector = interfaceIntrospector;
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+ Reference annotation = method.getAnnotation(Reference.class);
+ if (annotation == null) {
+ return; // Not a reference annotation.
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalReferenceException("Setter must have one parameter", method);
+ }
+ String name = annotation.name();
+ if ("".equals(name)) {
+ name = JavaIntrospectionHelper.toPropertyName(method.getName());
+ }
+ if (type.getReferenceMembers().get(name) != null) {
+ throw new DuplicateReferenceException(name);
+ }
+
+ JavaElementImpl element = new JavaElementImpl(method, 0);
+ org.apache.tuscany.sca.assembly.Reference reference = createReference(element, name);
+ type.getReferences().add(reference);
+ type.getReferenceMembers().put(name, element);
+ }
+
+ public void visitField(Field field, JavaImplementation type) throws IntrospectionException {
+ Reference annotation = field.getAnnotation(Reference.class);
+ if (annotation == null) {
+ return;
+ }
+ String name = annotation.name();
+ if ("".equals(name)) {
+ name = field.getName();
+ }
+ if (type.getReferenceMembers().get(name) != null) {
+ throw new DuplicateReferenceException(name);
+ }
+ JavaElementImpl element = new JavaElementImpl(field);
+ org.apache.tuscany.sca.assembly.Reference reference = createReference(element, name);
+ type.getReferences().add(reference);
+ type.getReferenceMembers().put(name, element);
+ }
+
+ public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type)
+ throws IntrospectionException {
+ Reference refAnnotation = parameter.getAnnotation(Reference.class);
+ if (refAnnotation == null) {
+ return;
+ }
+ String paramName = parameter.getName();
+ String name = getReferenceName(paramName, parameter.getIndex(), refAnnotation.name());
+ if (type.getReferenceMembers().get(name) != null) {
+ throw new DuplicateReferenceException(name);
+ }
+ org.apache.tuscany.sca.assembly.Reference reference = createReference(parameter, name);
+ type.getReferences().add(reference);
+ type.getReferenceMembers().put(name, parameter);
+ parameter.setClassifer(Reference.class);
+ parameter.setName(name);
+ }
+
+ private String getReferenceName(String paramName, int pos, String name) throws InvalidConstructorException {
+ if ("".equals(name)) {
+ name = paramName;
+ }
+ if ("".equals(name)) {
+ return "_ref" + pos;
+ }
+ if (!"".equals(paramName) && !name.equals(paramName)) {
+ throw new InvalidConstructorException("Mismatching names specified for reference parameter " + pos);
+ } else {
+ return name;
+ }
+ }
+
+ private org.apache.tuscany.sca.assembly.Reference createReference(JavaElementImpl element, String name) throws IntrospectionException {
+ org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference();
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ reference.setInterfaceContract(interfaceContract);
+
+ // reference.setMember((Member)element.getAnchor());
+ boolean required = true;
+ Reference ref = element.getAnnotation(Reference.class);
+ if (ref != null) {
+ required = ref.required();
+ }
+ // reference.setRequired(required);
+ reference.setName(name);
+ Class<?> rawType = element.getType();
+ if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) {
+ if (required) {
+ reference.setMultiplicity(Multiplicity.ONE_N);
+ } else {
+ reference.setMultiplicity(Multiplicity.ZERO_N);
+ }
+ } else {
+ if (required) {
+ reference.setMultiplicity(Multiplicity.ONE_ONE);
+ } else {
+ reference.setMultiplicity(Multiplicity.ZERO_ONE);
+ }
+ }
+ Type genericType = element.getGenericType();
+ Class<?> baseType = getBaseType(rawType, genericType);
+ try {
+ JavaInterface callInterface = interfaceIntrospector.introspect(baseType);
+ reference.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = interfaceIntrospector.introspect(callInterface.getCallbackClass());
+ reference.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ } catch (InvalidInterfaceException e) {
+ throw new IntrospectionException(e);
+ }
+ return reference;
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java
new file mode 100644
index 0000000000..2930e5f8d9
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java
@@ -0,0 +1,134 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Processes an {@link @Resource} annotation, updating the component type with
+ * corresponding {@link org.apache.tuscany.spi.implementation.java.JavaResourceImpl}
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceProcessor extends BaseJavaClassVisitor {
+
+ public ResourceProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+ org.apache.tuscany.api.annotation.Resource annotation = method
+ .getAnnotation(org.apache.tuscany.api.annotation.Resource.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalResourceException("Resource setter must have one parameter", method);
+ }
+ String name = annotation.name();
+ if (name.length() < 1) {
+ name = JavaIntrospectionHelper.toPropertyName(method.getName());
+ }
+ if (type.getResources().get(name) != null) {
+ throw new DuplicateResourceException(name);
+ }
+
+ String mappedName = annotation.mappedName();
+ JavaResourceImpl resource = createResource(name, new JavaElementImpl(method, 0));
+ resource.setOptional(annotation.optional());
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.getResources().put(resource.getName(), resource);
+ }
+
+ public void visitField(Field field, JavaImplementation type) throws IntrospectionException {
+
+ org.apache.tuscany.api.annotation.Resource annotation = field
+ .getAnnotation(org.apache.tuscany.api.annotation.Resource.class);
+ if (annotation == null) {
+ return;
+ }
+ String name = annotation.name();
+ if (name.length() < 1) {
+ name = field.getName();
+ }
+ if (type.getResources().get(name) != null) {
+ throw new DuplicateResourceException(name);
+ }
+
+ String mappedName = annotation.mappedName();
+
+ JavaResourceImpl resource = createResource(name, new JavaElementImpl(field));
+ resource.setOptional(annotation.optional());
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.getResources().put(resource.getName(), resource);
+ }
+
+ @SuppressWarnings("unchecked")
+ public JavaResourceImpl createResource(String name, JavaElementImpl element) {
+ element.setClassifer(org.apache.tuscany.api.annotation.Resource.class);
+ element.setName(name);
+ return new JavaResourceImpl(element);
+ }
+
+ public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type)
+ throws IntrospectionException {
+ org.apache.tuscany.api.annotation.Resource resourceAnnotation = parameter
+ .getAnnotation(org.apache.tuscany.api.annotation.Resource.class);
+ if (resourceAnnotation != null) {
+ String name = resourceAnnotation.name();
+ if ("".equals(name)) {
+ name = parameter.getName();
+ }
+ if ("".equals(name)) {
+ throw new InvalidResourceException("Missing resource name", (Member)parameter.getAnchor());
+ }
+
+ if (!"".equals(parameter.getName()) && !name.equals(parameter.getName())) {
+ throw new InvalidConstructorException("Mismatched resource name: " + parameter);
+ }
+
+ if (type.getResources().get(name) != null) {
+ throw new DuplicateResourceException(name);
+ }
+
+ String mappedName = resourceAnnotation.mappedName();
+
+ JavaResourceImpl resource = createResource(name, parameter);
+ resource.setOptional(resourceAnnotation.optional());
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.getResources().put(resource.getName(), resource);
+ }
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java
new file mode 100644
index 0000000000..592a65b4b3
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java
@@ -0,0 +1,60 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Processes the {@link JavaScopeImpl} annotation and updates the component type with the corresponding implmentation scope
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScopeProcessor extends BaseJavaClassVisitor {
+
+ public ScopeProcessor(AssemblyFactory factory) {
+ super(factory);
+ }
+
+ public <T> void visitClass(Class<T> clazz,
+ JavaImplementation type)
+ throws IntrospectionException {
+ org.osoa.sca.annotations.Scope annotation = clazz.getAnnotation(org.osoa.sca.annotations.Scope.class);
+ if (annotation == null) {
+ type.setJavaScope(JavaScopeImpl.STATELESS);
+ return;
+ }
+ String name = annotation.value();
+ JavaScopeImpl scope;
+ if ("COMPOSITE".equals(name)) {
+ scope = JavaScopeImpl.COMPOSITE;
+ } else if ("SESSION".equals(name)) {
+ scope = JavaScopeImpl.SESSION;
+ } else if ("CONVERSATION".equals(name)) {
+ scope = JavaScopeImpl.CONVERSATION;
+ } else if ("REQUEST".equals(name)) {
+ scope = JavaScopeImpl.REQUEST;
+ } else {
+ scope = new JavaScopeImpl(name);
+ }
+ type.setJavaScope(scope);
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java
new file mode 100644
index 0000000000..0ca1aefba0
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java
@@ -0,0 +1,159 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllInterfaces;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospector;
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Remotable;
+
+/**
+ * Processes an {@link org.osoa.sca.annotations.Service} annotation and updates
+ * the component type with corresponding {@link Service}s. Also processes
+ * related {@link org.osoa.sca.annotations.Callback} annotations.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServiceProcessor extends BaseJavaClassVisitor {
+ private JavaInterfaceIntrospector interfaceIntrospector;
+ private JavaInterfaceFactory javaFactory;
+
+ public ServiceProcessor(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory, JavaInterfaceIntrospector interfaceIntrospector) {
+ super(assemblyFactory);
+ this.javaFactory = javaFactory;
+ this.interfaceIntrospector = interfaceIntrospector;
+ }
+
+ public <T> void visitClass(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ org.osoa.sca.annotations.Service annotation = clazz.getAnnotation(org.osoa.sca.annotations.Service.class);
+ if (annotation == null) {
+ // scan intefaces for remotable
+ Set<Class> interfaces = getAllInterfaces(clazz);
+ for (Class<?> interfaze : interfaces) {
+ if (interfaze.isAnnotationPresent(Remotable.class) || interfaze.isAnnotationPresent(Callback.class)) {
+ Service service;
+ try {
+ service = createService(interfaze);
+ } catch (InvalidInterfaceException e) {
+ throw new IntrospectionException(e);
+ }
+ type.getServices().add(service);
+ }
+ }
+ return;
+ }
+ Class<?>[] interfaces = annotation.interfaces();
+ if (interfaces.length == 0) {
+ Class<?> interfaze = annotation.value();
+ if (Void.class.equals(interfaze)) {
+ throw new IllegalServiceDefinitionException("No interfaces specified");
+ } else {
+ interfaces = new Class<?>[1];
+ interfaces[0] = interfaze;
+ }
+ }
+ for (Class<?> interfaze : interfaces) {
+ if (!interfaze.isInterface()) {
+ throw new InvalidServiceType("Service must be an interface", interfaze);
+ }
+ Service service;
+ try {
+ service = createService(interfaze);
+ } catch (InvalidInterfaceException e) {
+ throw new IntrospectionException(e);
+ }
+ type.getServices().add(service);
+ }
+ }
+
+ public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException {
+
+ Callback annotation = method.getAnnotation(Callback.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalCallbackReferenceException("Setter must have one parameter", method);
+ }
+ Service callbackService = null;
+ Class<?> callbackClass = method.getParameterTypes()[0];
+ for (Service service : type.getServices()) {
+ JavaInterface javaInterface = (JavaInterface)service.getInterfaceContract().getCallbackInterface();
+ if (callbackClass == javaInterface.getJavaClass()) {
+ callbackService = service;
+ }
+ }
+ if (callbackService == null) {
+ throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface");
+ }
+ type.getCallbackMembers().put(callbackClass.getName(), new JavaElementImpl(method, 0));
+ }
+
+ public void visitField(Field field, JavaImplementation type) throws IntrospectionException {
+
+ Callback annotation = field.getAnnotation(Callback.class);
+ if (annotation == null) {
+ return;
+ }
+ Service callbackService = null;
+ Class<?> callbackClass = field.getType();
+ for (Service service : type.getServices()) {
+ JavaInterface javaInterface = (JavaInterface)service.getInterfaceContract().getCallbackInterface();
+ if (callbackClass == javaInterface.getJavaClass()) {
+ callbackService = service;
+ }
+ }
+ if (callbackService == null) {
+ throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface");
+ }
+ type.getCallbackMembers().put(callbackClass.getName(), new JavaElementImpl(field));
+ }
+
+ public Service createService(Class<?> interfaze) throws InvalidInterfaceException {
+ Service service = assemblyFactory.createService();
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ service.setInterfaceContract(interfaceContract);
+
+ // create a relative URI
+ service.setName(interfaze.getSimpleName());
+
+ JavaInterface callInterface = interfaceIntrospector.introspect(interfaze);
+ service.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = interfaceIntrospector.introspect(callInterface.getCallbackClass());
+ service.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ return service;
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java
new file mode 100644
index 0000000000..30b9af2ed5
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+
+/**
+ * Thrown when a service interface cannot be determined based on a heuristic evaluation of an implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServiceTypeNotFoundException extends IntrospectionException {
+ private static final long serialVersionUID = -5124437274726947007L;
+
+ public ServiceTypeNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java
new file mode 100644
index 0000000000..57d224b2bf
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+/**
+ * Thrown when a method or field marked with {@link org.osoa.sca.annotations.Context} takes an unknown type
+ *
+ * @version $Rev$ $Date$
+ */
+public class UnknownContextTypeException extends IllegalContextException {
+ private static final long serialVersionUID = 8125863714365422419L;
+
+ public UnknownContextTypeException(String message) {
+ super(message);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java
new file mode 100644
index 0000000000..0e14a2a689
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java
@@ -0,0 +1,31 @@
+/*
+ * 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.sca.implementation.java.xml;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.xml.Constants;
+
+public interface JavaImplementationConstants {
+
+ String IMPLEMENTATION_JAVA = "implementation.java";
+ QName IMPLEMENTATION_JAVA_QNAME = new QName(Constants.SCA10_NS, "implementation.java");
+ String CLASS = "class";
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java
new file mode 100644
index 0000000000..e702a3f682
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java
@@ -0,0 +1,188 @@
+/*
+ * 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.sca.implementation.java.xml;
+
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.xml.Constants;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.service.ContributionWriteException;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.implementation.java.introspect.JavaClassIntrospector;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.PolicyFactory;
+import org.apache.tuscany.sca.policy.PolicySet;
+import org.apache.tuscany.sca.policy.PolicySetAttachPoint;
+
+public class JavaImplementationProcessor implements
+ StAXArtifactProcessor<JavaImplementation>, JavaImplementationConstants {
+
+ private JavaImplementationFactory javaFactory;
+ private JavaClassIntrospector introspector;
+ private AssemblyFactory assemblyFactory;
+ private PolicyFactory policyFactory;
+
+ public JavaImplementationProcessor(AssemblyFactory assemblyFactory,
+ PolicyFactory policyFactory,
+ JavaImplementationFactory javaFactory,
+ JavaClassIntrospector introspector) {
+ this.assemblyFactory = assemblyFactory;
+ this.policyFactory = policyFactory;
+ this.javaFactory = javaFactory;
+ this.introspector = introspector;
+ }
+
+ public JavaImplementation read(XMLStreamReader reader) throws ContributionReadException {
+
+ try {
+
+ // Read an <implementation.java>
+ JavaImplementation javaImplementation = javaFactory.createJavaImplementation();
+ javaImplementation.setUnresolved(true);
+ javaImplementation.setName(reader.getAttributeValue(null, CLASS));
+
+ // Read policies
+ readPolicies(javaImplementation, reader);
+
+ // Skip to end element
+ while (reader.hasNext()) {
+ if (reader.next() == END_ELEMENT && IMPLEMENTATION_JAVA_QNAME.equals(reader.getName())) {
+ break;
+ }
+ }
+ return javaImplementation;
+
+ } catch (XMLStreamException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ public void write(JavaImplementation javaImplementation, XMLStreamWriter writer) throws ContributionWriteException {
+ try {
+ // Write an <interface.java>
+ writer.writeStartElement(Constants.SCA10_NS, IMPLEMENTATION_JAVA);
+ if (javaImplementation.getName() != null) {
+ writer.writeAttribute(CLASS, javaImplementation.getName());
+ }
+ writer.writeEndElement();
+
+ } catch (XMLStreamException e) {
+ throw new ContributionWriteException(e);
+ }
+ }
+
+ public void resolve(JavaImplementation javaImplementation, ModelResolver resolver)
+ throws ContributionResolveException {
+
+ ClassReference classReference = new ClassReference(javaImplementation.getName());
+ classReference = resolver.resolveModel(ClassReference.class, classReference);
+ Class javaClass = classReference.getJavaClass();
+ if (javaClass == null) {
+ throw new ContributionResolveException(new ClassNotFoundException(javaImplementation.getName()));
+ }
+ javaImplementation.setJavaClass(javaClass);
+ javaImplementation.setUnresolved(false);
+
+ try {
+ introspector.introspect(javaImplementation.getJavaClass(), javaImplementation);
+ } catch (IntrospectionException e) {
+ throw new ContributionResolveException(e);
+ }
+
+ // FIXME the introspector should always create at least one service
+ if (javaImplementation.getServices().isEmpty()) {
+ javaImplementation.getServices().add(assemblyFactory.createService());
+ }
+ }
+
+ public QName getArtifactType() {
+ return IMPLEMENTATION_JAVA_QNAME;
+ }
+
+ public Class<JavaImplementation> getModelType() {
+ return JavaImplementation.class;
+ }
+
+ /**
+ * Reads policy intents and policy sets.
+ * @param attachPoint
+ * @param reader
+ */
+ private void readPolicies(PolicySetAttachPoint attachPoint, XMLStreamReader reader) {
+ String value = reader.getAttributeValue(null, Constants.REQUIRES);
+ if (value != null) {
+ List<Intent> requiredIntents = attachPoint.getRequiredIntents();
+ for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) {
+ QName qname = getQNameValue(reader, tokens.nextToken());
+ Intent intent = policyFactory.createIntent();
+ intent.setName(qname);
+ requiredIntents.add(intent);
+ }
+ }
+
+ value = reader.getAttributeValue(null, Constants.POLICY_SETS);
+ if (value != null) {
+ List<PolicySet> policySets = attachPoint.getPolicySets();
+ for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) {
+ QName qname = getQNameValue(reader, tokens.nextToken());
+ PolicySet policySet = policyFactory.createPolicySet();
+ policySet.setName(qname);
+ policySets.add(policySet);
+ }
+ }
+ }
+
+ /**
+ * Returns a qname from a string.
+ * @param reader
+ * @param value
+ * @return
+ */
+ private QName getQNameValue(XMLStreamReader reader, String value) {
+ if (value != null) {
+ int index = value.indexOf(':');
+ String prefix = index == -1 ? "" : value.substring(0, index);
+ String localName = index == -1 ? value : value.substring(index + 1);
+ String ns = reader.getNamespaceContext().getNamespaceURI(prefix);
+ if (ns == null) {
+ ns = "";
+ }
+ return new QName(ns, localName, prefix);
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/AddService.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/AddService.java
new file mode 100644
index 0000000000..4eeb30a9c2
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/AddService.java
@@ -0,0 +1,25 @@
+/*
+ * 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 calculator;
+
+public interface AddService {
+
+ double add(double n1, double n2);
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/AddServiceImpl.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/AddServiceImpl.java
new file mode 100644
index 0000000000..ea3e5341d5
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/AddServiceImpl.java
@@ -0,0 +1,35 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Scope;
+
+/**
+ * An implementation of the Add service
+ */
+@Scope("COMPOSITE")
+@EagerInit
+public class AddServiceImpl implements AddService {
+
+ public double add(double n1, double n2) {
+ return n1 + n2;
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/CalculatorService.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/CalculatorService.java
new file mode 100644
index 0000000000..c89043276e
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/CalculatorService.java
@@ -0,0 +1,34 @@
+/*
+ * 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 calculator;
+
+/**
+ * The Calculator service interface.
+ */
+public interface CalculatorService {
+
+ double add(double n1, double n2);
+
+ double subtract(double n1, double n2);
+
+ double multiply(double n1, double n2);
+
+ double divide(double n1, double n2);
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/CalculatorServiceImpl.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/CalculatorServiceImpl.java
new file mode 100644
index 0000000000..11e8974657
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/CalculatorServiceImpl.java
@@ -0,0 +1,71 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Scope;
+
+/**
+ * An implementation of the Calculator service.
+ */
+@Scope("COMPOSITE")
+public class CalculatorServiceImpl implements CalculatorService {
+
+ private AddService addService;
+ private SubtractService subtractService;
+ private MultiplyService multiplyService;
+ private DivideService divideService;
+
+ @Reference
+ public void setAddService(AddService addService) {
+ this.addService = addService;
+ }
+
+ @Reference
+ public void setSubtractService(SubtractService subtractService) {
+ this.subtractService = subtractService;
+ }
+
+ @Reference
+ public void setDivideService(DivideService divideService) {
+ this.divideService = divideService;
+ }
+
+ @Reference
+ public void setMultiplyService(MultiplyService multiplyService) {
+ this.multiplyService = multiplyService;
+ }
+
+ public double add(double n1, double n2) {
+ return addService.add(n1, n2);
+ }
+
+ public double subtract(double n1, double n2) {
+ return subtractService.subtract(n1, n2);
+ }
+
+ public double multiply(double n1, double n2) {
+ return multiplyService.multiply(n1, n2);
+ }
+
+ public double divide(double n1, double n2) {
+ return divideService.divide(n1, n2);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/DivideService.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/DivideService.java
new file mode 100644
index 0000000000..131c5a8014
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/DivideService.java
@@ -0,0 +1,25 @@
+/*
+ * 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 calculator;
+
+public interface DivideService {
+
+ double divide(double n1, double n2);
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/DivideServiceImpl.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/DivideServiceImpl.java
new file mode 100644
index 0000000000..9c7e96a668
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/DivideServiceImpl.java
@@ -0,0 +1,33 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.Scope;
+
+/**
+ * An implementation of the Divide service.
+ */
+@Scope("COMPOSITE")
+public class DivideServiceImpl implements DivideService {
+
+ public double divide(double n1, double n2) {
+ return n1 / n2;
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/MultiplyService.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/MultiplyService.java
new file mode 100644
index 0000000000..a917896aeb
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/MultiplyService.java
@@ -0,0 +1,25 @@
+/*
+ * 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 calculator;
+
+public interface MultiplyService {
+
+ double multiply(double n1, double n2);
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/MultiplyServiceImpl.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/MultiplyServiceImpl.java
new file mode 100644
index 0000000000..4892481203
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/MultiplyServiceImpl.java
@@ -0,0 +1,33 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.Scope;
+
+/**
+ * An implementation of the Multiply service.
+ */
+@Scope("COMPOSITE")
+public class MultiplyServiceImpl implements MultiplyService {
+
+ public double multiply(double n1, double n2) {
+ return n1 * n2;
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/SubtractService.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/SubtractService.java
new file mode 100644
index 0000000000..e328f024ea
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/SubtractService.java
@@ -0,0 +1,25 @@
+/*
+ * 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 calculator;
+
+public interface SubtractService {
+
+ double subtract(double n1, double n2);
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/SubtractServiceImpl.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/SubtractServiceImpl.java
new file mode 100644
index 0000000000..ee1d7c3457
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/calculator/SubtractServiceImpl.java
@@ -0,0 +1,33 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.Scope;
+
+/**
+ * An implementation of the subtract service.
+ */
+@Scope("COMPOSITE")
+public class SubtractServiceImpl implements SubtractService {
+
+ public double subtract(double n1, double n2) {
+ return n1 - n2;
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorTestCase.java
new file mode 100644
index 0000000000..9ecd439611
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorTestCase.java
@@ -0,0 +1,95 @@
+/*
+ * 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.sca.implementation.java.introspect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.easymock.EasyMock;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class DefaultJavaClassIntrospectorTestCase extends TestCase {
+
+ public void testRegister() throws Exception {
+ DefaultJavaClassIntrospectorExtensionPoint visitors = new DefaultJavaClassIntrospectorExtensionPoint();
+ JavaClassVisitor extension = EasyMock.createNiceMock(JavaClassVisitor.class);
+ visitors.addClassVisitor(extension);
+ }
+
+ public void testUnegister() throws Exception {
+ DefaultJavaClassIntrospectorExtensionPoint visitors = new DefaultJavaClassIntrospectorExtensionPoint();
+ JavaClassVisitor extension = EasyMock.createNiceMock(JavaClassVisitor.class);
+ visitors.addClassVisitor(extension);
+ visitors.removeClassVisitor(extension);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testWalk() throws Exception {
+ DefaultJavaClassIntrospectorExtensionPoint visitors = new DefaultJavaClassIntrospectorExtensionPoint();
+ JavaClassVisitor extension = EasyMock.createMock(JavaClassVisitor.class);
+ extension.visitClass(EasyMock.eq(Bar.class), EasyMock.isA(JavaImplementation.class));
+ extension.visitConstructor(EasyMock.isA(Constructor.class), EasyMock.isA(JavaImplementation.class));
+ extension.visitMethod(EasyMock.isA(Method.class), EasyMock.isA(JavaImplementation.class));
+ extension.visitField(EasyMock.isA(Field.class), EasyMock.isA(JavaImplementation.class));
+ extension.visitSuperClass(EasyMock.isA(Class.class), EasyMock.isA(JavaImplementation.class));
+ extension.visitEnd(EasyMock.isA(Class.class), EasyMock.isA(JavaImplementation.class));
+
+ // mock.expects(once()).method("visitClass");
+ // mock.expects(once()).method("visitMethod");
+ // mock.expects(once()).method("visitField");
+ // mock.expects(once()).method("visitConstructor");
+ // mock.expects(once()).method("visitSuperClass");
+ // mock.expects(once()).method("visitEnd");
+ EasyMock.replay(extension);
+ visitors.addClassVisitor(extension);
+ JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+ ExtensibleJavaClassIntrospector introspector = new ExtensibleJavaClassIntrospector(visitors);
+ introspector.introspect(Bar.class, javaImplementationFactory.createJavaImplementation());
+ EasyMock.verify(extension);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ private class Baz {
+
+ }
+
+ private class Bar extends Baz {
+
+ protected String bar;
+
+ public Bar() {
+ }
+
+ public void bar() {
+ }
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractProcessorTest.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractProcessorTest.java
new file mode 100644
index 0000000000..adefc4f7fc
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractProcessorTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Constructor;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+
+
+/**
+ * Base class to simulate the processor sequences
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractProcessorTest extends TestCase {
+ protected AssemblyFactory factory;
+ protected JavaInterfaceFactory javaFactory;
+ protected ConstructorProcessor constructorProcessor;
+ private ReferenceProcessor referenceProcessor;
+ private PropertyProcessor propertyProcessor;
+ private ResourceProcessor resourceProcessor;
+
+
+ protected AbstractProcessorTest() {
+ factory = new DefaultAssemblyFactory();
+ javaFactory = new DefaultJavaInterfaceFactory();
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ referenceProcessor = new ReferenceProcessor(factory, javaFactory, new ExtensibleJavaInterfaceIntrospector(javaFactory, visitors));
+ propertyProcessor = new PropertyProcessor(factory);
+ resourceProcessor = new ResourceProcessor(factory);
+ constructorProcessor = new ConstructorProcessor(factory);
+ referenceProcessor = new ReferenceProcessor(factory, javaFactory, new ExtensibleJavaInterfaceIntrospector(javaFactory, visitors));
+ propertyProcessor = new PropertyProcessor(factory);
+ }
+
+ protected <T> void visitConstructor(Constructor<T> constructor,
+ JavaImplementation type) throws IntrospectionException {
+ constructorProcessor.visitConstructor(constructor, type);
+ JavaConstructorImpl<?> definition = type.getConstructor();
+ if (definition == null) {
+ definition = new JavaConstructorImpl<T>(constructor);
+ type.getConstructors().put(constructor, definition);
+ }
+ JavaParameterImpl[] parameters = definition.getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ referenceProcessor.visitConstructorParameter(parameters[i], type);
+ propertyProcessor.visitConstructorParameter(parameters[i], type);
+ resourceProcessor.visitConstructorParameter(parameters[i], type);
+ // monitorProcessor.visitConstructorParameter(parameters[i], type);
+ }
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessorTestCase.java
new file mode 100644
index 0000000000..df316b3623
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessorTestCase.java
@@ -0,0 +1,168 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty;
+
+import java.lang.annotation.Retention;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.DuplicatePropertyException;
+import org.apache.tuscany.sca.implementation.java.introspect.IllegalPropertyException;
+import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor;
+
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AbstractPropertyProcessorTestCase extends TestCase {
+
+ private JavaClassVisitor extension;
+ private JavaImplementationFactory javaImplementationFactory;
+
+ public void testVisitMethod() throws Exception {
+ Method method = Foo.class.getMethod("setBar", String.class);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ extension.visitMethod(method, type);
+ Property prop = getProperty(type, "test");
+ assertNotNull(prop);
+ }
+
+ public void testVisitNoParamsMethod() throws Exception {
+ Method method = Foo.class.getMethod("setNoParamsBar");
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ extension.visitMethod(method, type);
+ fail();
+ } catch (IllegalPropertyException e) {
+ // expected
+ }
+ }
+
+ public void testVisitNonVoidMethod() throws Exception {
+ Method method = Foo.class.getMethod("setBadBar", String.class);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ extension.visitMethod(method, type);
+ fail();
+ } catch (IllegalPropertyException e) {
+ // expected
+ }
+ }
+
+ public void testDuplicateMethod() throws Exception {
+ Method method = Foo.class.getMethod("setBar", String.class);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ extension.visitMethod(method, type);
+ try {
+ extension.visitMethod(method, type);
+ fail();
+ } catch (DuplicatePropertyException e) {
+ // expected
+ }
+ }
+
+ public void testVisitField() throws Exception {
+ Field field = Foo.class.getDeclaredField("d");
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ extension.visitField(field, type);
+ Property prop = getProperty(type, "test");
+ assertNotNull(prop);
+ }
+
+ public void testVisitConstructor() throws Exception {
+ Constructor<Foo> ctor = Foo.class.getConstructor(String.class);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ JavaConstructorImpl<Foo> def = new JavaConstructorImpl<Foo>(ctor);
+ JavaParameterImpl parameter = def.getParameters()[0];
+ extension.visitConstructorParameter(parameter, type);
+ assertEquals("test", def.getParameters()[0].getName());
+ assertNotNull(getProperty(type, "test"));
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void setUp() throws Exception {
+ super.setUp();
+ extension = new TestProcessor();
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ }
+
+ @Retention(RUNTIME)
+ private @interface Bar {
+
+ }
+
+ private class TestProcessor extends AbstractPropertyProcessor<Bar> {
+
+ public TestProcessor() {
+ super(new DefaultAssemblyFactory(), Bar.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void initProperty(Property property, Bar annotation) {
+ // property.setDefaultValueFactory(EasyMock.createMock(ObjectFactory.class));
+ property.setName("test");
+ }
+
+ protected String getName(Bar annotation) {
+ return "test";
+ }
+ }
+
+ private static class Foo {
+
+ @Bar
+ protected String d;
+
+ public Foo(String a, @Bar
+ String b) {
+ }
+
+ public Foo(@Bar
+ String d) {
+ this.d = d;
+ }
+
+ @Bar
+ public void setBar(String d) {
+ this.d = d;
+ }
+
+ @Bar
+ public void setNoParamsBar() {
+ }
+
+ @Bar
+ public String setBadBar(String d) {
+ return null;
+ }
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessorTestCase.java
new file mode 100644
index 0000000000..9b3437b07a
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessorTestCase.java
@@ -0,0 +1,70 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.osoa.sca.annotations.AllowsPassByReference;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AllowsPassByReferenceProcessorTestCase extends TestCase {
+
+ JavaImplementation type;
+ AllowsPassByReferenceProcessor processor;
+ private JavaImplementationFactory javaImplementationFactory;
+
+ public void testClassAnnotation() throws Exception {
+ processor.visitClass(Foo.class, type);
+ assertEquals(true, type.isAllowsPassByReference());
+
+ processor.visitClass(Bar.class, type);
+ assertEquals(false, type.isAllowsPassByReference());
+
+ Method m1 = Bar.class.getMethod("m1", new Class[] {});
+ processor.visitMethod(m1, type);
+ assertTrue(type.isAllowsPassByReference(m1));
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ type = javaImplementationFactory.createJavaImplementation();
+ processor = new AllowsPassByReferenceProcessor(new DefaultAssemblyFactory());
+ }
+
+ @AllowsPassByReference
+ private class Foo {
+ }
+
+ // no annotation
+ private class Bar {
+ @AllowsPassByReference
+ public void m1() {
+
+ }
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessorTestCase.java
new file mode 100644
index 0000000000..ce236c1d10
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessorTestCase.java
@@ -0,0 +1,197 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getReference;
+
+import java.lang.reflect.Constructor;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConstructorProcessorTestCase extends TestCase {
+ private ConstructorProcessor processor = new ConstructorProcessor(new DefaultAssemblyFactory());
+
+ private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+
+ public void testDuplicateConstructor() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ processor.visitClass(BadFoo.class, type);
+ fail();
+ } catch (DuplicateConstructorException e) {
+ // expected
+ }
+ }
+
+ public void testConstructorAnnotation() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor1 = Foo.class.getConstructor(String.class);
+ processor.visitConstructor(ctor1, type);
+ assertEquals("foo", type.getConstructor().getParameters()[0].getName());
+ }
+
+ public void testNoAnnotation() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<NoAnnotation> ctor1 = NoAnnotation.class.getConstructor();
+ processor.visitConstructor(ctor1, type);
+ assertNull(type.getConstructor());
+ }
+
+ public void testBadAnnotation() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadAnnotation> ctor1 = BadAnnotation.class.getConstructor(String.class, Foo.class);
+ try {
+ processor.visitConstructor(ctor1, type);
+ fail();
+ } catch (InvalidConstructorException e) {
+ // expected
+ }
+ }
+
+ public void testMixedParameters() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Mixed> ctor1 = Mixed.class.getConstructor(String.class, String.class, String.class);
+ processor.visitConstructor(ctor1, type);
+
+ AssemblyFactory assemblyFactory = new DefaultAssemblyFactory();
+ JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory();
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ ReferenceProcessor referenceProcessor = new ReferenceProcessor(assemblyFactory, javaFactory, new ExtensibleJavaInterfaceIntrospector(javaFactory, visitors));
+ PropertyProcessor propertyProcessor = new PropertyProcessor(assemblyFactory);
+ JavaParameterImpl[] parameters = type.getConstructor().getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ referenceProcessor.visitConstructorParameter(parameters[i], type);
+ propertyProcessor.visitConstructorParameter(parameters[i], type);
+ }
+
+ assertEquals("_ref0", parameters[0].getName());
+ assertEquals("foo", parameters[1].getName());
+ assertEquals("bar", parameters[2].getName());
+ }
+
+ private static class BadFoo {
+
+ @org.osoa.sca.annotations.Constructor("foo")
+ public BadFoo(String foo) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor( {"foo", "bar"})
+ public BadFoo(String foo, String bar) {
+
+ }
+ }
+
+ private static class Foo {
+ @org.osoa.sca.annotations.Constructor("foo")
+ public Foo(String foo) {
+
+ }
+ }
+
+ private static class NoAnnotation {
+ public NoAnnotation() {
+ }
+ }
+
+ private static class BadAnnotation {
+ @org.osoa.sca.annotations.Constructor("foo")
+ public BadAnnotation(String foo, Foo ref) {
+ }
+ }
+
+ public static final class Mixed {
+ @org.osoa.sca.annotations.Constructor
+ public Mixed(@Reference
+ String param1, @Property(name = "foo")
+ String param2, @Reference(name = "bar")
+ String param3) {
+ }
+ }
+
+ public static final class Multiple {
+ @org.osoa.sca.annotations.Constructor
+ public Multiple(@Reference
+ Collection<String> param1, @Property(name = "foo")
+ String[] param2, @Reference(name = "bar", required = true)
+ List<String> param3, @Property(name = "abc")
+ Set<String> param4, @Reference(name = "xyz")
+ String[] param5) {
+ }
+ }
+
+ public void testMultiplicity() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Multiple> ctor1 = Multiple.class.getConstructor(Collection.class,
+ String[].class,
+ List.class,
+ Set.class,
+ String[].class);
+ processor.visitConstructor(ctor1, type);
+ AssemblyFactory assemblyFactory = new DefaultAssemblyFactory();
+ JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory();
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ ReferenceProcessor referenceProcessor = new ReferenceProcessor(assemblyFactory, javaFactory, new ExtensibleJavaInterfaceIntrospector(javaFactory, visitors));
+ PropertyProcessor propertyProcessor = new PropertyProcessor(assemblyFactory);
+ JavaParameterImpl[] parameters = type.getConstructor().getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ referenceProcessor.visitConstructorParameter(parameters[i], type);
+ propertyProcessor.visitConstructorParameter(parameters[i], type);
+ }
+
+ org.apache.tuscany.sca.assembly.Reference ref0 = getReference(type, "_ref0");
+ assertNotNull(ref0);
+ assertEquals(Multiplicity.ONE_N, ref0.getMultiplicity());
+ org.apache.tuscany.sca.assembly.Reference ref1 = getReference(type, "bar");
+ assertNotNull(ref1);
+ assertEquals(Multiplicity.ONE_N, ref1.getMultiplicity());
+ org.apache.tuscany.sca.assembly.Reference ref2 = getReference(type, "xyz");
+ assertNotNull(ref2);
+ assertEquals(Multiplicity.ONE_N, ref2.getMultiplicity());
+ org.apache.tuscany.sca.assembly.Property prop1 = getProperty(type, "foo");
+ assertNotNull(prop1);
+ assertTrue(prop1.isMany());
+ org.apache.tuscany.sca.assembly.Property prop2 = getProperty(type, "abc");
+ assertNotNull(prop2);
+ assertTrue(prop2.isMany());
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorPropertyTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorPropertyTestCase.java
new file mode 100644
index 0000000000..aef565b3e4
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorPropertyTestCase.java
@@ -0,0 +1,158 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.introspect.DuplicatePropertyException;
+import org.osoa.sca.annotations.Property;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConstructorPropertyTestCase extends AbstractProcessorTest {
+
+ private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+
+ public void testProperty() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(String.class);
+ visitConstructor(ctor, type);
+ org.apache.tuscany.sca.assembly.Property property = getProperty(type, "myProp");
+ assertTrue(property.isMustSupply());
+ assertEquals("myProp", property.getName());
+ }
+
+ public void testTwoPropertiesSameType() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(String.class, String.class);
+ visitConstructor(ctor, type);
+ assertNotNull(getProperty(type, "myProp1"));
+ assertNotNull(getProperty(type, "myProp2"));
+ }
+
+ public void testDuplicateProperty() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadFoo> ctor = BadFoo.class.getConstructor(String.class, String.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (DuplicatePropertyException e) {
+ // expected
+ }
+ }
+
+ public void testNoName() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadFoo> ctor = BadFoo.class.getConstructor(String.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (InvalidPropertyException e) {
+ // expected
+ }
+ }
+
+ public void testNamesOnConstructor() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(Integer.class);
+ visitConstructor(ctor, type);
+ assertNotNull(getProperty(type, "myProp"));
+ }
+
+ public void testInvalidNumberOfNames() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadFoo> ctor = BadFoo.class.getConstructor(Integer.class, Integer.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (InvalidConstructorException e) {
+ // expected
+ }
+ }
+
+ public void testNoMatchingNames() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadFoo> ctor = BadFoo.class.getConstructor(List.class, List.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (InvalidConstructorException e) {
+ // expected
+ }
+ }
+
+// public void testMultiplicityRequired() throws Exception {
+ // TODO multiplicity
+// }
+
+ private static class Foo {
+
+ @org.osoa.sca.annotations.Constructor()
+ public Foo(@Property(name = "myProp", required = true)String prop) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor("myProp")
+ public Foo(@Property Integer prop) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor()
+ public Foo(@Property(name = "myProp1")String prop1, @Property(name = "myProp2")String prop2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor()
+ public Foo(@Property List prop) {
+
+ }
+ }
+
+ private static class BadFoo {
+
+ @org.osoa.sca.annotations.Constructor()
+ public BadFoo(@Property(name = "myProp")String prop1, @Property(name = "myProp")String prop2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor()
+ public BadFoo(@Property String prop) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor("myProp")
+ public BadFoo(@Property Integer prop, @Property Integer prop2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor({"myRef", "myRef2"})
+ public BadFoo(@Property List ref, @Property(name = "myOtherRef")List ref2) {
+
+ }
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorReferenceTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorReferenceTestCase.java
new file mode 100644
index 0000000000..9d4204d114
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorReferenceTestCase.java
@@ -0,0 +1,166 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getReference;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.osoa.sca.annotations.Reference;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConstructorReferenceTestCase extends AbstractProcessorTest {
+
+ private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+
+ public void testReference() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(String.class);
+ visitConstructor(ctor, type);
+ org.apache.tuscany.sca.assembly.Reference reference = getReference(type, "myRef");
+ assertEquals(Multiplicity.ONE_ONE, reference.getMultiplicity());
+ assertEquals("myRef", reference.getName());
+ }
+
+ public void testTwoReferencesSameType() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(String.class, String.class);
+ visitConstructor(ctor, type);
+ assertNotNull(getReference(type, "myRef1"));
+ assertNotNull(getReference(type, "myRef2"));
+ }
+
+ public void testDuplicateProperty() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadFoo> ctor = BadFoo.class.getConstructor(String.class, String.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (DuplicateReferenceException e) {
+ // expected
+ }
+ }
+
+ public void testNoName() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<NoNameFoo> ctor = NoNameFoo.class.getConstructor(String.class);
+ visitConstructor(ctor, type);
+ assertNotNull(getReference(type, "_ref0"));
+ }
+
+ public void testNamesOnConstructor() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(Integer.class);
+ visitConstructor(ctor, type);
+ assertNotNull(getReference(type, "myRef"));
+ }
+
+ public void testInvalidNumberOfNames() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadFoo> ctor = BadFoo.class.getConstructor(Integer.class, Integer.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (InvalidConstructorException e) {
+ // expected
+ }
+ }
+
+ public void testNoMatchingNames() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadFoo> ctor = BadFoo.class.getConstructor(List.class, List.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (InvalidConstructorException e) {
+ // expected
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+// public void testMultiplicityRequired() throws Exception {
+ // TODO multiplicity
+// }
+
+ private static class Foo {
+
+ @org.osoa.sca.annotations.Constructor()
+ public Foo(@Reference(name = "myRef", required = true)String prop) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor()
+ public Foo(@Reference(name = "myRef1")String prop1, @Reference(name = "myRef2")String prop2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor("myRef")
+ public Foo(@Reference Integer prop) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor()
+ public Foo(@Reference List prop) {
+
+ }
+ }
+
+ private static class NoNameFoo {
+
+ @org.osoa.sca.annotations.Constructor
+ public NoNameFoo(@Reference String prop) {
+
+ }
+ }
+
+ private static class BadFoo {
+
+ @org.osoa.sca.annotations.Constructor
+ public BadFoo(@Reference(name = "myRef")String prop1, @Reference(name = "myRef")String prop2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor
+ public BadFoo(@Reference String prop) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor("myRef")
+ public BadFoo(@Reference Integer ref, @Reference Integer ref2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor({"myRef", "myRef2"})
+ public BadFoo(@Reference List ref, @Reference(name = "myOtherRef")List ref2) {
+
+ }
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorResourceTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorResourceTestCase.java
new file mode 100644
index 0000000000..2e56a2a812
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorResourceTestCase.java
@@ -0,0 +1,153 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import org.apache.tuscany.api.annotation.Resource;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConstructorResourceTestCase extends AbstractProcessorTest {
+
+ private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+
+ public void testResource() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(String.class);
+ visitConstructor(ctor, type);
+ org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl resource = type.getResources().get("myResource");
+ assertFalse(resource.isOptional());
+ }
+
+ public void testTwoResourcesSameType() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(String.class, String.class);
+ visitConstructor(ctor, type);
+ assertNotNull(type.getResources().get("myResource1"));
+ assertNotNull(type.getResources().get("myResource2"));
+ }
+
+ public void testDuplicateResource() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<BadFoo> ctor = BadFoo.class.getConstructor(String.class, String.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (DuplicateResourceException e) {
+ // expected
+ }
+ }
+
+ public void testNoName() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<ConstructorResourceTestCase.BadFoo> ctor =
+ ConstructorResourceTestCase.BadFoo.class.getConstructor(String.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (InvalidResourceException e) {
+ // expected
+ }
+ }
+
+ public void testNamesOnConstructor() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(Integer.class);
+ visitConstructor(ctor, type);
+ assertNotNull(type.getResources().get("myResource"));
+ }
+
+ public void testInvalidNumberOfNames() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<ConstructorResourceTestCase.BadFoo> ctor =
+ ConstructorResourceTestCase.BadFoo.class.getConstructor(Integer.class, Integer.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (InvalidConstructorException e) {
+ // expected
+ }
+ }
+
+ public void testNoMatchingNames() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<ConstructorResourceTestCase.BadFoo> ctor =
+ ConstructorResourceTestCase.BadFoo.class.getConstructor(List.class, List.class);
+ try {
+ visitConstructor(ctor, type);
+ fail();
+ } catch (InvalidConstructorException e) {
+ // expected
+ }
+ }
+
+ private static class Foo {
+
+ @org.osoa.sca.annotations.Constructor
+ public Foo(@Resource(name = "myResource") String resource) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor("myResource")
+ public Foo(@Resource Integer resource) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor
+ public Foo(@Resource(name = "myResource1") String res1, @Resource(name = "myResource2") String res2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor
+ public Foo(@Resource List res) {
+
+ }
+ }
+
+ private static class BadFoo {
+
+ @org.osoa.sca.annotations.Constructor
+ public BadFoo(@Resource(name = "myResource") String res1, @Resource(name = "myResource") String res2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor
+ public BadFoo(@Resource String res) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor("myProp")
+ public BadFoo(@Resource Integer res, @Resource Integer res2) {
+
+ }
+
+ @org.osoa.sca.annotations.Constructor({"myRes", "myRes2"})
+ public BadFoo(@Resource List res, @Resource(name = "myOtherRes") List res2) {
+
+ }
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessorTestCase.java
new file mode 100644
index 0000000000..5f0e189f69
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessorTestCase.java
@@ -0,0 +1,188 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.easymock.EasyMock;
+import org.osoa.sca.ComponentContext;
+import org.osoa.sca.RequestContext;
+import org.osoa.sca.annotations.Context;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ContextProcessorTestCase extends TestCase {
+ private ContextProcessor processor;
+ private Component composite;
+ private JavaImplementationFactory javaImplementationFactory;
+
+ // FIXME: resurrect to test ComponentContext injection
+/*
+ public void testCompositeContextMethod() throws Exception {
+ Method method = Foo.class.getMethod("setContext", ComponentContext.class);
+ JavaImplementationDefinition type =
+ new JavaImplementationDefinition();
+ processor.visitMethod(composite, method, type);
+ assertNotNull(type.getResources().get("context"));
+ }
+*/
+
+ // FIXME: resurrect to test ComponentContext injection
+/*
+ public void testCompositeContextField() throws Exception {
+ Field field = Foo.class.getDeclaredField("context");
+ JavaImplementationDefinition type =
+ new JavaImplementationDefinition();
+ processor.visitField(composite, field, type);
+ assertNotNull(type.getResources().get("context"));
+ }
+*/
+
+ public void testRequestContextMethod() throws Exception {
+ Method method = Foo.class.getMethod("setRequestContext", RequestContext.class);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitMethod(method, type);
+ assertNotNull(type.getResources().get("requestContext"));
+ }
+
+ public void testRequestContextField() throws Exception {
+ Field field = Foo.class.getDeclaredField("requestContext");
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitField(field, type);
+ assertNotNull(type.getResources().get("requestContext"));
+ }
+
+ public void testInvalidParamType() throws Exception {
+ Method method = Foo.class.getMethod("setContext", String.class);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ processor.visitMethod(method, type);
+ fail();
+ } catch (UnknownContextTypeException e) {
+ // expected
+ }
+ }
+
+ public void testInvalidParamTypeField() throws Exception {
+ Field field = Foo.class.getDeclaredField("badContext");
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ processor.visitField(field, type);
+ fail();
+ } catch (UnknownContextTypeException e) {
+ // expected
+ }
+ }
+
+
+ public void testInvalidParamNum() throws Exception {
+ Method method = Foo.class.getMethod("setContext", ComponentContext.class, String.class);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ processor.visitMethod(method, type);
+ fail();
+ } catch (IllegalContextException e) {
+ // expected
+ }
+ }
+
+ public void testInvalidNoParams() throws Exception {
+ Method method = Foo.class.getMethod("setContext");
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ processor.visitMethod(method, type);
+ fail();
+ } catch (IllegalContextException e) {
+ // expected
+ }
+ }
+
+ public void testNoContext() throws Exception {
+ Method method = Foo.class.getMethod("noContext", ComponentContext.class);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitMethod(method, type);
+ assertEquals(0, type.getResources().size());
+ }
+
+ public void testNoContextField() throws Exception {
+ Field field = Foo.class.getDeclaredField("noContext");
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitField(field, type);
+ assertEquals(0, type.getResources().size());
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ processor = new ContextProcessor(new DefaultAssemblyFactory());
+ // processor.setWorkContext(EasyMock.createNiceMock(WorkContext.class));
+ composite = EasyMock.createNiceMock(Component.class);
+ }
+
+ private class Foo {
+ @Context
+ protected ComponentContext context;
+
+ @Context
+ protected Object badContext;
+
+ protected ComponentContext noContext;
+
+ @Context
+ protected RequestContext requestContext;
+
+ @Context
+ public void setContext(ComponentContext context) {
+
+ }
+
+ @Context
+ public void setContext(String context) {
+
+ }
+
+ @Context
+ public void setContext(ComponentContext context, String string) {
+
+ }
+
+ @Context
+ public void setContext() {
+
+ }
+
+ public void noContext(ComponentContext context) {
+
+ }
+
+ @Context
+ public void setRequestContext(RequestContext requestContext) {
+ this.requestContext = requestContext;
+ }
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessorTestCase.java
new file mode 100644
index 0000000000..239012d468
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessorTestCase.java
@@ -0,0 +1,144 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.osoa.sca.annotations.ConversationAttributes;
+import org.osoa.sca.annotations.ConversationID;
+import org.osoa.sca.annotations.Scope;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConversationProcessorTestCase extends TestCase {
+ private ConversationProcessor processor = new ConversationProcessor(new DefaultAssemblyFactory());
+ private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+
+ public void testMaxIdleTime() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(FooMaxIdle.class, type);
+ assertEquals(10000L, type.getMaxIdleTime());
+ assertEquals(-1, type.getMaxAge());
+ }
+
+ public void testMaxAge() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(FooMaxAge.class, type);
+ assertEquals(10000L, type.getMaxAge());
+ assertEquals(-1, type.getMaxIdleTime());
+ }
+
+ public void testBadFooBoth() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ processor.visitClass(BadFooBoth.class, type);
+ fail();
+ } catch (InvalidConversationalImplementation e) {
+ // expected
+ }
+ }
+
+ public void testImplicitScope() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(ImplicitFooScope.class, type);
+ assertEquals(org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl.CONVERSATION, type.getJavaScope());
+ }
+
+ public void testBadFooScope() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ processor.visitClass(BadFooScope.class, type);
+ fail();
+ } catch (InvalidConversationalImplementation e) {
+ // expected
+ }
+ }
+
+ public void testJustConversation() throws Exception {
+ // TODO do we want these semantics
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(FooJustConversation.class, type);
+ assertEquals(org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl.CONVERSATION, type.getJavaScope());
+ assertEquals(-1, type.getMaxAge());
+ assertEquals(-1, type.getMaxIdleTime());
+ }
+
+ public void testSetConversationIDField() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Field field = FooWithConversationIDField.class.getDeclaredField("conversationID");
+ processor.visitField(field, type);
+ assertNotNull(type.getConversationIDMember());
+ assertEquals(field, type.getConversationIDMember());
+ }
+
+ public void testSetConversationIDMethod() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Method method = FooWithConversationIDMethod.class.getDeclaredMethods()[0];
+ processor.visitMethod(method, type);
+ assertNotNull(type.getConversationIDMember());
+ assertEquals(method, type.getConversationIDMember());
+ }
+
+ @Scope("CONVERSATION")
+ @ConversationAttributes(maxIdleTime = "10 seconds")
+ private class FooMaxIdle {
+ }
+
+ @Scope("CONVERSATION")
+ @ConversationAttributes(maxAge = "10 seconds")
+ private class FooMaxAge {
+ }
+
+ @Scope("CONVERSATION")
+ @ConversationAttributes(maxAge = "10 seconds", maxIdleTime = "10 seconds")
+ private class BadFooBoth {
+ }
+
+ @ConversationAttributes(maxAge = "10 seconds")
+ private class ImplicitFooScope {
+ }
+
+ @Scope("STATELESS")
+ @ConversationAttributes(maxAge = "10 seconds")
+ private class BadFooScope {
+ }
+
+ @ConversationAttributes
+ private class FooJustConversation {
+ }
+
+ private class FooWithConversationIDField {
+ @ConversationID
+ private String conversationID;
+ }
+
+ private class FooWithConversationIDMethod {
+ @ConversationID
+ void setConversationID(String conversationID) {
+ }
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConvertTimeMillisTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConvertTimeMillisTestCase.java
new file mode 100644
index 0000000000..1c00df8e04
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConvertTimeMillisTestCase.java
@@ -0,0 +1,116 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConvertTimeMillisTestCase extends TestCase {
+ private MockProcessor registy;
+
+ public void testConvertSeconds() throws Exception {
+ assertEquals(10000L, registy.convertTimeMillis("10 seconds"));
+ assertEquals(10000L, registy.convertTimeMillis("10 SECONDS"));
+ try {
+ registy.convertTimeMillis("10seconds");
+ fail();
+ } catch (NumberFormatException e) {
+ // expected
+ }
+ }
+
+ public void testConvertMinutes() throws Exception {
+ assertEquals(600000L, registy.convertTimeMillis("10 minutes"));
+ assertEquals(600000L, registy.convertTimeMillis("10 MINUTES"));
+ try {
+ registy.convertTimeMillis("10minutes");
+ fail();
+ } catch (NumberFormatException e) {
+ // expected
+ }
+ }
+
+ public void testConvertHours() throws Exception {
+ assertEquals(36000000L, registy.convertTimeMillis("10 hours"));
+ assertEquals(36000000L, registy.convertTimeMillis("10 HOURS"));
+ try {
+ registy.convertTimeMillis("10hours");
+ fail();
+ } catch (NumberFormatException e) {
+ // expected
+ }
+ }
+
+ public void testConvertDays() throws Exception {
+ assertEquals(864000000L, registy.convertTimeMillis("10 days"));
+ assertEquals(864000000L, registy.convertTimeMillis("10 DAYS"));
+ try {
+ registy.convertTimeMillis("10days");
+ fail();
+ } catch (NumberFormatException e) {
+ // expected
+ }
+ }
+
+ public void testConvertYears() throws Exception {
+ assertEquals(315569260000L, registy.convertTimeMillis("10 years"));
+ assertEquals(315569260000L, registy.convertTimeMillis("10 YEARS"));
+ try {
+ registy.convertTimeMillis("10years");
+ fail();
+ } catch (NumberFormatException e) {
+ // expected
+ }
+ }
+
+ public void testConvertDefault() throws Exception {
+ assertEquals(10000L, registy.convertTimeMillis("10 "));
+ assertEquals(10000L, registy.convertTimeMillis("10"));
+ }
+
+ public void testInvalid() throws Exception {
+ try {
+ registy.convertTimeMillis("foo");
+ fail();
+ } catch (NumberFormatException e) {
+ // expected
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ registy = new MockProcessor();
+ }
+
+ private class MockProcessor extends ConversationProcessor {
+
+ public MockProcessor() {
+ super(new DefaultAssemblyFactory());
+ }
+
+ @Override
+ protected long convertTimeMillis(String expr) throws NumberFormatException {
+ return super.convertTimeMillis(expr);
+ }
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessorTestCase.java
new file mode 100644
index 0000000000..657ad757e5
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessorTestCase.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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.osoa.sca.annotations.Destroy;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class DestroyProcessorTestCase extends TestCase {
+
+ private AssemblyFactory assemblyFactory = new DefaultAssemblyFactory();
+ private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+
+ public void testDestroy() throws Exception {
+ DestroyProcessor processor = new DestroyProcessor(assemblyFactory);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Method method = Foo.class.getMethod("destroy");
+ processor.visitMethod(method, type);
+ assertNotNull(type.getDestroyMethod());
+ }
+
+ public void testBadDestroy() throws Exception {
+ DestroyProcessor processor = new DestroyProcessor(assemblyFactory);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Method method = Bar.class.getMethod("badDestroy", String.class);
+ try {
+ processor.visitMethod(method, type);
+ fail();
+ } catch (IllegalDestructorException e) {
+ // expected
+ }
+ }
+
+ public void testTwoDestroy() throws Exception {
+ DestroyProcessor processor = new DestroyProcessor(assemblyFactory);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Method method = Bar.class.getMethod("destroy");
+ Method method2 = Bar.class.getMethod("destroy2");
+ processor.visitMethod(method, type);
+ try {
+ processor.visitMethod(method2, type);
+ fail();
+ } catch (DuplicateDestructorException e) {
+ // expected
+ }
+ }
+
+
+ private class Foo {
+
+ @Destroy
+ public void destroy() {
+ }
+ }
+
+
+ private class Bar {
+
+ @Destroy
+ public void destroy() {
+ }
+
+ @Destroy
+ public void destroy2() {
+ }
+
+ @Destroy
+ public void badDestroy(String foo) {
+ }
+
+
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessorTestCase.java
new file mode 100644
index 0000000000..9ece6cd164
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessorTestCase.java
@@ -0,0 +1,59 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.osoa.sca.annotations.EagerInit;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class EagerInitProcessorTestCase extends TestCase {
+
+ private AssemblyFactory assemblyFactory = new DefaultAssemblyFactory();
+ private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+
+ public void testNoLevel() throws IntrospectionException {
+ EagerInitProcessor processor = new EagerInitProcessor(assemblyFactory);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(Level.class, type);
+ }
+
+ public void testSubclass() throws IntrospectionException {
+ EagerInitProcessor processor = new EagerInitProcessor(assemblyFactory);
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(SubClass.class, type);
+ }
+
+ @EagerInit
+ private class Level {
+ }
+
+ private class SubClass extends Level {
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicAndPropertyTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicAndPropertyTestCase.java
new file mode 100644
index 0000000000..d125366707
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicAndPropertyTestCase.java
@@ -0,0 +1,75 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Constructor;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+import org.osoa.sca.annotations.Property;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class HeuristicAndPropertyTestCase extends TestCase {
+
+ private PropertyProcessor propertyProcessor;
+ private HeuristicPojoProcessor heuristicProcessor;
+ private AssemblyFactory assemblyFactory = new DefaultAssemblyFactory();
+ private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+
+ /**
+ * Verifies the property and heuristic processors don't collide
+ */
+ @SuppressWarnings("unchecked")
+ public void testPropertyProcessorWithHeuristicProcessor() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor ctor = Foo.class.getConstructor(String.class);
+ type.setConstructor(new JavaConstructorImpl(ctor));
+ propertyProcessor.visitConstructorParameter(type.getConstructor().getParameters()[0], type);
+ heuristicProcessor.visitEnd(Foo.class, type);
+ assertEquals(1, type.getProperties().size());
+ assertEquals("foo", type.getProperties().get(0).getName());
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ ExtensibleJavaInterfaceIntrospector introspector = new ExtensibleJavaInterfaceIntrospector(new DefaultJavaInterfaceFactory(), visitors);
+ propertyProcessor = new PropertyProcessor(assemblyFactory);
+ heuristicProcessor = new HeuristicPojoProcessor(assemblyFactory, new DefaultJavaInterfaceFactory(), introspector);
+ }
+
+ public static class Foo {
+ public Foo(@Property(name = "foo")
+ String prop) {
+ }
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicConstructorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicConstructorTestCase.java
new file mode 100644
index 0000000000..de90130295
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicConstructorTestCase.java
@@ -0,0 +1,315 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty;
+
+import java.lang.reflect.Constructor;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Remotable;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class HeuristicConstructorTestCase extends AbstractProcessorTest {
+
+ private AssemblyFactory factory;
+ private JavaInterfaceFactory javaFactory;
+ private HeuristicPojoProcessor processor;
+ private JavaImplementationFactory javaImplementationFactory;
+
+ public HeuristicConstructorTestCase() {
+ factory = new DefaultAssemblyFactory();
+ javaFactory = new DefaultJavaInterfaceFactory();
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ ExtensibleJavaInterfaceIntrospector introspector = new ExtensibleJavaInterfaceIntrospector(javaFactory, visitors);
+ processor = new HeuristicPojoProcessor(factory, javaFactory, introspector);
+ }
+
+ private <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ for (Constructor<T> constructor : clazz.getConstructors()) {
+ visitConstructor(constructor, type);
+ }
+ processor.visitEnd(clazz, type);
+ }
+
+ /**
+ * Verifies a single constructor is chosen with a parameter as the type
+ */
+ public void testSingleConstructorWithParam() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ org.apache.tuscany.sca.assembly.Property prop = factory.createProperty();
+ prop.setName("foo");
+ type.getProperties().add(prop);
+ // Hack to add a property member
+ JavaElementImpl element = new JavaElementImpl("foo", String.class, null);
+ type.getPropertyMembers().put("foo", element);
+ visitEnd(Foo1.class, type);
+ assertNotNull(type.getConstructor().getConstructor());
+ assertEquals("foo", type.getConstructor().getParameters()[0].getName());
+ }
+
+ /**
+ * Verifies a single constructor is chosen with a reference as the type
+ */
+ public void testSingleConstructorWithRef() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ org.apache.tuscany.sca.assembly.Reference ref = factory.createReference();
+ ref.setName("foo");
+ type.getReferences().add(ref);
+ type.getReferenceMembers().put("foo", new JavaElementImpl("foo", String.class, null));
+ visitEnd(Foo1.class, type);
+ assertNotNull(type.getConstructor().getConstructor());
+ assertEquals("foo", type.getConstructor().getParameters()[0].getName());
+ }
+
+ /**
+ * Verifies a single constructor is chosen with a property and a reference
+ * as the type
+ */
+ public void testSingleConstructorWithPropRef() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+
+ org.apache.tuscany.sca.assembly.Property prop = factory.createProperty();
+ prop.setName("foo");
+ type.getProperties().add(prop);
+ // Hack to add a property member
+ JavaElementImpl element = new JavaElementImpl("foo", String.class, null);
+ type.getPropertyMembers().put("foo", element);
+
+ org.apache.tuscany.sca.assembly.Reference ref = ModelHelper.createReference(factory, javaFactory, "ref", Foo1.class);
+ type.getReferences().add(ref);
+ type.getReferenceMembers().put("ref", new JavaElementImpl("ref", Foo1.class, null));
+ visitEnd(Foo2.class, type);
+ assertNotNull(type.getConstructor().getConstructor());
+ assertEquals(2, type.getConstructor().getParameters().length);
+ }
+
+ public void testSingleConstructorResolvableParam() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ visitEnd(Foo5.class, type);
+ assertEquals(String.class, type.getPropertyMembers().get("string").getType());
+ }
+
+ public void testSingleConstructorResolvableRef() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ visitEnd(Foo6.class, type);
+ assertTrue(ModelHelper.matches(ModelHelper.getReference(type, "ref"), Ref.class));
+ }
+
+ public void testSingleConstructorAmbiguousRef() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ org.apache.tuscany.sca.assembly.Reference ref = ModelHelper.createReference(factory, javaFactory, "ref", Foo1.class);
+ type.getReferences().add(ref);
+ type.getReferenceMembers().put("ref", new JavaElementImpl("ref", Foo1.class, null));
+ org.apache.tuscany.sca.assembly.Reference ref2 = ModelHelper.createReference(factory, javaFactory, "ref2", Foo1.class);
+ type.getReferences().add(ref2);
+ type.getReferenceMembers().put("ref2", new JavaElementImpl("ref2", Foo1.class, null));
+ try {
+ visitEnd(Foo4.class, type);
+ fail();
+ } catch (AmbiguousConstructorException e) {
+ // expected
+ }
+ }
+
+ public void testConstructorPropertyAnnotatedParamsOnly() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ visitEnd(Foo7.class, type);
+ assertNotNull(getProperty(type, "myProp"));
+ }
+
+ public void testConstructorReferenceAnnotatedParamsOnly() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ visitEnd(Foo8.class, type);
+ assertNotNull(ModelHelper.getReference(type, "myRef"));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testDefaultConstructor() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ visitEnd(Foo3.class, type);
+ assertNotNull(type.getConstructor().getConstructor());
+ }
+
+ public void testSameTypesButAnnotated() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ visitEnd(Foo12.class, type);
+ assertEquals(2, type.getProperties().size());
+ assertNotNull(getProperty(type, "prop1"));
+ assertNotNull(getProperty(type, "prop2"));
+ }
+
+ /**
+ * Verifies processing executes with additional extension annotations
+ */
+ public void testRandomAnnotation() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ visitEnd(Foo11.class, type);
+ assertEquals(1, type.getProperties().size());
+ assertNotNull(getProperty(type, "prop1"));
+ }
+
+ public void testPrivateConstructor() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ visitEnd(Foo14.class, type);
+ fail();
+ } catch (NoConstructorException e) {
+ // expected
+ }
+ }
+
+ public void testMultipleConstructors() throws Exception {
+ // throw new UnsupportedOperationException("Finish heuristic multiple
+ // constructors - Foo10");
+ }
+
+ public static class Foo1 {
+ public Foo1(String val) {
+ }
+ }
+
+ public static class Foo2 {
+ public Foo2(String val, Foo1 ref) {
+ }
+ }
+
+ public static class Foo3 {
+ }
+
+ public static class Foo4 {
+ public Foo4(Foo1 ref) {
+ }
+ }
+
+ public static class Prop {
+
+ }
+
+ @Remotable
+ public static interface Ref {
+
+ }
+
+ public static class Foo5 {
+ public Foo5(String val) {
+ }
+ }
+
+ public static class Foo6 {
+ public Foo6(Ref ref) {
+ }
+ }
+
+ public static class Foo7 {
+ public Foo7(@Property(name = "myProp")
+ String prop) {
+ }
+ }
+
+ public static class Foo8 {
+ public Foo8(@Reference(name = "myRef")
+ String ref) {
+ }
+ }
+
+ public static class Foo9 {
+ public Foo9(@Reference(name = "myRef")
+ String ref) {
+ }
+ }
+
+ public static class Foo10 {
+
+ public Foo10() {
+ }
+
+ public Foo10(String prop) {
+ }
+
+ public Foo10(@Property(name = "prop1")
+ String prop1, @Property(name = "prop2")
+ String prop2) {
+
+ }
+ }
+
+ public static class Foo11 {
+
+ public Foo11(@Property(name = "prop1")
+ String prop, @Baz
+ String baz) {
+ }
+ }
+
+ public static class Foo12 {
+
+ public Foo12(@Property(name = "prop1")
+ String prop, @Property(name = "prop2")
+ String baz) {
+ }
+ }
+
+ public @interface Baz {
+
+ }
+
+ public static class Foo13 {
+ public Foo13(@Reference
+ String foo) {
+ }
+ }
+
+ public static final class Foo14 {
+ private Foo14() {
+ }
+ }
+
+ public static final class Foo15 {
+ public Foo15(@Reference
+ String param1, @Reference
+ String param2) {
+ }
+ }
+
+ public static final class Foo16 {
+ public Foo16(@Reference
+ String param1, @Property(name = "foo")
+ String param2, @Reference(name = "bar")
+ String param3) {
+ }
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java
new file mode 100644
index 0000000000..323daf52d0
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java
@@ -0,0 +1,411 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Constructor;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Remotable;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * Verfies component type information is properly introspected from an unadorned
+ * POJO according to the SCA Java Client and Implementation Model Specification
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeuristicPojoProcessorTestCase extends AbstractProcessorTest {
+
+ private org.apache.tuscany.sca.implementation.java.introspect.impl.HeuristicPojoProcessor processor;
+ private JavaImplementationFactory javaImplementationFactory;
+
+ public HeuristicPojoProcessorTestCase() {
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ ExtensibleJavaInterfaceIntrospector introspector = new ExtensibleJavaInterfaceIntrospector(new DefaultJavaInterfaceFactory(), visitors);
+ processor = new HeuristicPojoProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory(), introspector);
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ }
+
+ private <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ for (Constructor<T> constructor : clazz.getConstructors()) {
+ visitConstructor(constructor, type);
+ }
+ processor.visitEnd(clazz, type);
+ }
+
+ /**
+ * Verifies a single service interface is computed when only one interface
+ * is implemented
+ */
+ public void testSingleInterface() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<SingleInterfaceImpl> ctor = SingleInterfaceImpl.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<SingleInterfaceImpl>(ctor));
+ processor.visitEnd(SingleInterfaceImpl.class, type);
+ assertEquals(1, type.getServices().size());
+ assertTrue(ModelHelper.matches(ModelHelper.getService(type, PropertyInterface.class.getSimpleName()),
+ PropertyInterface.class));
+ assertTrue(type.getProperties().isEmpty());
+ assertTrue(type.getReferences().isEmpty());
+ }
+
+ /**
+ * Verifies property and reference setters are computed
+ */
+ public void testPropertyReference() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<SingleInterfaceWithPropertyReferenceImpl> ctor = SingleInterfaceWithPropertyReferenceImpl.class
+ .getConstructor();
+ type.setConstructor(new JavaConstructorImpl<SingleInterfaceWithPropertyReferenceImpl>(ctor));
+ processor.visitEnd(SingleInterfaceWithPropertyReferenceImpl.class, type);
+ assertEquals(1, type.getServices().size());
+ assertTrue(ModelHelper
+ .matches(ModelHelper.getService(type, Interface1.class.getSimpleName()), Interface1.class));
+ assertEquals(1, type.getProperties().size());
+ org.apache.tuscany.sca.assembly.Property prop = ModelHelper.getProperty(type, "property");
+ assertNotNull(prop);
+ assertEquals(ComplexProperty.class, type.getPropertyMembers().get("property").getType());
+ assertEquals(1, type.getReferences().size());
+ assertTrue(ModelHelper.matches(ModelHelper.getReference(type, "reference"), Ref.class));
+ }
+
+ /**
+ * Verifies that a property setter is not introspected if an analogous
+ * operation is in the service interface
+ */
+ public void testPropertySetterInInterface() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<SingleInterfaceImpl> ctor = SingleInterfaceImpl.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<SingleInterfaceImpl>(ctor));
+ processor.visitEnd(SingleInterfaceImpl.class, type);
+ assertEquals(0, type.getProperties().size());
+ }
+
+ /**
+ * Verifies that a reference setter is not introspected if an analogous
+ * operation is in the service interface
+ */
+ public void testReferenceSetterInInterface() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<RefInterfaceImpl> ctor = RefInterfaceImpl.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<RefInterfaceImpl>(ctor));
+ processor.visitEnd(RefInterfaceImpl.class, type);
+ assertEquals(0, type.getReferences().size());
+ }
+
+ /**
+ * Verifies collection generic types or array types are introspected as
+ * references according to spec rules
+ */
+ public void testReferenceCollectionType() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<ReferenceCollectionImpl> ctor = ReferenceCollectionImpl.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<ReferenceCollectionImpl>(ctor));
+ processor.visitEnd(ReferenceCollectionImpl.class, type);
+ assertEquals(1, type.getProperties().size());
+ assertEquals(3, type.getReferences().size());
+ }
+
+ /**
+ * Verifies collection generic types or array types are introspected as
+ * properties according to spec rules
+ */
+ public void testPropertyCollectionType() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<PropertyCollectionImpl> ctor = PropertyCollectionImpl.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<PropertyCollectionImpl>(ctor));
+ processor.visitEnd(PropertyCollectionImpl.class, type);
+ assertEquals(0, type.getReferences().size());
+ assertEquals(4, type.getProperties().size());
+ }
+
+ /**
+ * Verifies references are calculated when the type marked with is
+ *
+ * @Remotable
+ */
+ public void testRemotableRef() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<RemotableRefImpl> ctor = RemotableRefImpl.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<RemotableRefImpl>(ctor));
+ processor.visitEnd(RemotableRefImpl.class, type);
+ assertEquals(2, type.getReferences().size());
+ assertEquals(0, type.getProperties().size());
+ }
+
+ public void testParentInterface() throws IntrospectionException, NoSuchMethodException {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Child> ctor = Child.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<Child>(ctor));
+ processor.visitEnd(Child.class, type);
+ assertNotNull(ModelHelper.getService(type, Interface1.class.getSimpleName()));
+ }
+
+ /**
+ * Verifies a service inteface is calculated when only props and refs are
+ * given
+ */
+ public void testExcludedPropertyAndReference() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ org.apache.tuscany.sca.assembly.Reference ref = factory.createReference();
+ ref.setName("reference");
+ type.getReferences().add(ref);
+ type.getReferenceMembers().put("reference", new JavaElementImpl("reference", Ref.class, null));
+ org.apache.tuscany.sca.assembly.Reference ref2 = factory.createReference();
+ ref2.setName("reference2");
+ type.getReferences().add(ref2);
+ type.getReferenceMembers().put("reference2", new JavaElementImpl("reference2", Ref.class, null));
+ org.apache.tuscany.sca.assembly.Property prop1 = factory.createProperty();
+ prop1.setName("string1");
+ type.getProperties().add(prop1);
+ type.getPropertyMembers().put("string1", new JavaElementImpl("string1", String.class, null));
+ org.apache.tuscany.sca.assembly.Property prop2 = factory.createProperty();
+ prop2.setName("string2");
+ type.getProperties().add(prop2);
+ type.getPropertyMembers().put("string2", new JavaElementImpl("string2", String.class, null));
+ visitEnd(MockService.class, type);
+ assertEquals(1, type.getServices().size());
+ }
+
+ public void testProtectedRemotableRefField() throws IntrospectionException, NoSuchMethodException {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<ProtectedRemotableRefFieldImpl> ctor = ProtectedRemotableRefFieldImpl.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<ProtectedRemotableRefFieldImpl>(ctor));
+ processor.visitEnd(ProtectedRemotableRefFieldImpl.class, type);
+ assertNotNull(ModelHelper.getReference(type, "otherRef"));
+ }
+
+ public void testProtectedRemotableRefMethod() throws IntrospectionException, NoSuchMethodException {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<ProtectedRemotableRefMethodImpl> ctor = ProtectedRemotableRefMethodImpl.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<ProtectedRemotableRefMethodImpl>(ctor));
+ processor.visitEnd(ProtectedRemotableRefMethodImpl.class, type);
+ assertNotNull(ModelHelper.getReference(type, "otherRef"));
+ }
+
+ public void testSetDataTypes() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<PropertyIntTypeOnConstructor> ctor = PropertyIntTypeOnConstructor.class.getConstructor();
+ type.setConstructor(new JavaConstructorImpl<PropertyIntTypeOnConstructor>(ctor));
+ processor.visitEnd(PropertyIntTypeOnConstructor.class, type);
+ org.apache.tuscany.sca.assembly.Property foo = ModelHelper.getProperty(type, "foo");
+ assertEquals(int.class, type.getPropertyMembers().get("foo").getType());
+ assertEquals(new QName(JavaXMLMapper.URI_2001_SCHEMA_XSD, "int"), foo.getXSDType());
+ }
+
+ private static class PropertyIntTypeOnConstructor {
+ protected int foo;
+
+ public PropertyIntTypeOnConstructor() {
+ }
+
+ public int getFoo() {
+ return foo;
+ }
+ }
+
+ private interface PropertyInterface {
+ void setString1(String val);
+ }
+
+ private interface Interface1 {
+ }
+
+ private static class Parent implements Interface1 {
+
+ }
+
+ private static class Child extends Parent {
+ public Child() {
+ }
+
+ }
+
+ private static class SingleInterfaceImpl implements PropertyInterface {
+ public SingleInterfaceImpl() {
+ }
+
+ public void setString1(String val) {
+ }
+
+ }
+
+ private interface HeuristicServiceInterface {
+ void fooOperation(String ref);
+
+ void setInvalid1(); // No parameter
+
+ void setInvalid2(String str, int i); // More than one parameter
+
+ String setInvalid3(String str); // return should be void
+ }
+
+ public static class MockService implements PropertyInterface, RefInterface, HeuristicServiceInterface {
+
+ @Property
+ public void setString1(String val) {
+ }
+
+ @Property
+ public void setString2(String val) {
+ }
+
+ @Reference
+ public void setReference(Ref ref) {
+ }
+
+ @Reference
+ public void setReference2(Ref ref) {
+ }
+
+ public void fooOperation(String ref) {
+
+ }
+
+ public void setInvalid1() {
+ }
+
+ public void setInvalid2(String str, int i) {
+ }
+
+ public String setInvalid3(String str) {
+ return null;
+ }
+
+ }
+
+ @Service
+ private interface Ref {
+ }
+
+ private class ComplexProperty {
+ }
+
+ private interface RefInterface {
+ void setReference(Ref ref);
+ }
+
+ private static class RefInterfaceImpl implements RefInterface {
+ public RefInterfaceImpl() {
+ }
+
+ public void setReference(Ref ref) {
+ }
+ }
+
+ private static class SingleInterfaceWithPropertyReferenceImpl implements Interface1 {
+ public SingleInterfaceWithPropertyReferenceImpl() {
+ }
+
+ public void setReference(Ref ref) {
+ }
+
+ public void setProperty(ComplexProperty prop) {
+ }
+ }
+
+ private static class ReferenceCollectionImpl implements Interface1 {
+ public ReferenceCollectionImpl() {
+ }
+
+ public void setCollectionReference(Collection<Ref> ref) {
+ }
+
+ public void setNonGenericCollectionReference(Collection ref) {
+ // [rfeng] By the SCA spec, this should be classified as property
+ }
+
+ public void setListReference(List<Ref> ref) {
+ }
+
+ public void setArrayReference(Ref[] ref) {
+ }
+ }
+
+ private static class PropertyCollectionImpl implements Interface1 {
+ public PropertyCollectionImpl() {
+ }
+
+ public void setCollectionProperty(Collection<ComplexProperty> prop) {
+ }
+
+ public void setCollectionProperty2(Collection<String> prop) {
+ }
+
+ public void setArrayProperty(ComplexProperty[] prop) {
+ }
+
+ public void setArrayProperty2(String[] prop) {
+ }
+ }
+
+ @Remotable
+ private interface RemotableRef {
+ }
+
+ private static class RemotableRefImpl implements Interface1 {
+ protected RemotableRef otherRef;
+
+ public RemotableRefImpl() {
+ }
+
+ public void setRef(RemotableRef ref) {
+
+ }
+ }
+
+ private static class ProtectedRemotableRefFieldImpl implements Interface1 {
+ protected RemotableRef otherRef;
+
+ public ProtectedRemotableRefFieldImpl() {
+ }
+
+ public ProtectedRemotableRefFieldImpl(RemotableRef otherRef) {
+ this.otherRef = otherRef;
+ }
+
+ }
+
+ private static class ProtectedRemotableRefMethodImpl implements Interface1 {
+ public ProtectedRemotableRefMethodImpl() {
+ }
+
+ protected void setOtherRef(RemotableRef otherRef) {
+ }
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeutisticExtensibleConstructorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeutisticExtensibleConstructorTestCase.java
new file mode 100644
index 0000000000..8499e344ce
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeutisticExtensibleConstructorTestCase.java
@@ -0,0 +1,153 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Constructor;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+
+/**
+ * Verifies constructors that have extensible annotation types, i.e. that have
+ * parameters marked by annotations which are themselves processed by some other
+ * implementation processor
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeutisticExtensibleConstructorTestCase extends AbstractProcessorTest {
+
+ private org.apache.tuscany.sca.implementation.java.introspect.impl.HeuristicPojoProcessor processor;
+ private JavaImplementationFactory javaImplementationFactory;
+
+ public HeutisticExtensibleConstructorTestCase() {
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ ExtensibleJavaInterfaceIntrospector introspector = new ExtensibleJavaInterfaceIntrospector(new DefaultJavaInterfaceFactory(), visitors);
+ processor = new HeuristicPojoProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory(), introspector);
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ }
+
+ private <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ for (Constructor<T> constructor : clazz.getConstructors()) {
+ visitConstructor(constructor, type);
+ }
+ processor.visitEnd(clazz, type);
+ }
+
+ /**
+ * Verifies heuristic processing can be called priot to an extension
+ * annotation processors being called.
+ */
+ public void testBarAnnotationProcessedFirst() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo> ctor = Foo.class.getConstructor(String.class, String.class);
+ JavaConstructorImpl<Foo> definition = new JavaConstructorImpl<Foo>(ctor);
+ type.setConstructor(definition);
+ Property property = factory.createProperty();
+ property.setName("myBar");
+ definition.getParameters()[0].setName("myBar");
+ type.getProperties().add(property);
+ visitEnd(Foo.class, type);
+ assertEquals(2, type.getProperties().size());
+ }
+
+ /**
+ * Verifies heuristic processing can be called before an extension
+ * annotation processors is called. <p/> For example, given:
+ *
+ * <pre>
+ * Foo(@Bar String prop, @org.osoa.sca.annotations.Property(name = &quot;foo&quot;) String prop2)
+ * </pre>
+ *
+ * <p/> Heuristic evaluation of
+ * @Property can occur prior to another implementation processor evaluating
+ * @Bar
+ * @throws Exception
+ */
+ public void testBarAnnotationProcessedLast() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ visitEnd(Foo.class, type);
+
+ // now simulate process the bar impl
+ JavaConstructorImpl<?> definition = type.getConstructor();
+ definition.getParameters()[0].setName("myBar");
+ Property property = factory.createProperty();
+ property.setName("myBar");
+ type.getProperties().add(property);
+
+ assertEquals(2, type.getProperties().size());
+ assertEquals("foo", definition.getParameters()[1].getName());
+ }
+
+ /**
+ * Verifies heuristic processing can be called before an extension
+ * annotation processors is called with the extension parameter in a middle
+ * position. Specifically, verifies that the heuristic processor updates
+ * injection names and preserves their ordering.
+ */
+ public void testBarAnnotationProcessedFirstInMiddle() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Constructor<Foo2> ctor = Foo2.class.getConstructor(String.class, String.class, String.class);
+ JavaConstructorImpl<Foo2> definition = new JavaConstructorImpl<Foo2>(ctor);
+ type.setConstructor(definition);
+ // insert placeholder for first param, which would be done by a
+ // processor
+ definition.getParameters()[0].setName("");
+ Property property = factory.createProperty();
+ // Hack to add a property member
+ JavaElementImpl element = new JavaElementImpl("myBar", String.class, null);
+ type.getPropertyMembers().put("myBar", element);
+ property.setName("myBar");
+ definition.getParameters()[1].setName("myBar");
+ type.getProperties().add(property);
+ visitEnd(Foo2.class, type);
+ assertEquals("baz", definition.getParameters()[0].getName());
+ assertEquals(2, type.getProperties().size());
+ assertEquals(1, type.getReferences().size());
+ }
+
+ public @interface Bar {
+
+ }
+
+ public static class Foo {
+ public Foo(@Bar
+ String prop, @org.osoa.sca.annotations.Property(name = "foo")
+ String prop2) {
+ }
+ }
+
+ public static class Foo2 {
+ public Foo2(@org.osoa.sca.annotations.Reference(name = "baz")
+ String prop1, @Bar
+ String prop2, @org.osoa.sca.annotations.Property(name = "foo")
+ String prop3) {
+ }
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessorTestCase.java
new file mode 100644
index 0000000000..be2b5aa56e
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessorTestCase.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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.osoa.sca.annotations.Init;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class InitProcessorTestCase extends TestCase {
+
+ private JavaImplementationFactory javaImplementationFactory;
+
+ public InitProcessorTestCase() {
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ }
+
+ public void testInit() throws Exception {
+ InitProcessor processor = new InitProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Method method = InitProcessorTestCase.Foo.class.getMethod("init");
+ processor.visitMethod(method, type);
+ assertNotNull(type.getInitMethod());
+ }
+
+ public void testBadInit() throws Exception {
+ InitProcessor processor = new InitProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Method method = InitProcessorTestCase.Bar.class.getMethod("badInit", String.class);
+ try {
+ processor.visitMethod(method, type);
+ fail();
+ } catch (IllegalInitException e) {
+ // expected
+ }
+ }
+
+ public void testTwoInit() throws Exception {
+ InitProcessor processor = new InitProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ Method method = InitProcessorTestCase.Bar.class.getMethod("init");
+ Method method2 = InitProcessorTestCase.Bar.class.getMethod("init2");
+ processor.visitMethod(method, type);
+ try {
+ processor.visitMethod(method2, type);
+ fail();
+ } catch (DuplicateInitException e) {
+ // expected
+ }
+ }
+
+
+ private class Foo {
+ @Init
+ public void init() {
+ }
+ }
+
+
+ private class Bar {
+ @Init
+ public void init() {
+ }
+
+ @Init
+ public void init2() {
+ }
+
+ @Init
+ public void badInit(String foo) {
+ }
+
+
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ModelHelper.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ModelHelper.java
new file mode 100644
index 0000000000..aad6b96cf9
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ModelHelper.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.sca.implementation.java.introspect.impl;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ModelHelper {
+
+ public static Property getProperty(JavaImplementation type, String name) {
+ for (Property prop : type.getProperties()) {
+ if (prop.getName().equals(name)) {
+ return prop;
+ }
+ }
+ return null;
+ }
+
+ public static Reference getReference(JavaImplementation type, String name) {
+ for (Reference ref : type.getReferences()) {
+ if (ref.getName().equals(name)) {
+ return ref;
+ }
+ }
+ return null;
+ }
+
+ public static Service getService(JavaImplementation type, String name) {
+ for (Service svc : type.getServices()) {
+ if (svc.getName().equals(name)) {
+ return svc;
+ }
+ }
+ return null;
+ }
+
+ public static boolean matches(Contract contract, Class<?> type) {
+ Interface interface1 = contract.getInterfaceContract().getInterface();
+ if (interface1 instanceof JavaInterface) {
+ return type == ((JavaInterface)interface1).getJavaClass();
+ } else {
+ return false;
+ }
+ }
+
+ public static ComponentService createService(AssemblyFactory factory,
+ JavaInterfaceFactory javaFactory, Class<?> type) {
+ org.apache.tuscany.sca.assembly.ComponentService ref = factory.createComponentService();
+ ref.setName(type.getSimpleName());
+ JavaInterface i = javaFactory.createJavaInterface();
+ i.setJavaClass(type);
+ JavaInterfaceContract ic = javaFactory.createJavaInterfaceContract();
+ ic.setInterface(i);
+ ref.setInterfaceContract(ic);
+ return ref;
+ }
+
+ public static Reference createReference(AssemblyFactory factory,
+ JavaInterfaceFactory javaFactory, String name, Class<?> type) {
+ org.apache.tuscany.sca.assembly.Reference ref = factory.createReference();
+ ref.setName(name);
+ JavaInterface i = javaFactory.createJavaInterface();
+ i.setJavaClass(type);
+ JavaInterfaceContract ic = javaFactory.createJavaInterfaceContract();
+ ic.setInterface(i);
+ ref.setInterfaceContract(ic);
+ return ref;
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java
new file mode 100644
index 0000000000..25d37a6eca
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java
@@ -0,0 +1,406 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.policy.DefaultPolicyFactory;
+import org.apache.tuscany.sca.policy.Intent;
+import org.osoa.sca.annotations.Requires;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class PolicyProcessorTestCase extends TestCase {
+ private ServiceProcessor serviceProcessor;
+ private PolicyProcessor policyProcessor;
+ private JavaImplementation type;
+
+ // This actually is a test for PolicyJavaInterfaceProcessor. It will get
+ // invoked via the call to ImplementationProcessorServiceImpl.createService in
+ // ServiceProcessor. Of course ServiceProcessor class has to be working.
+ public void testSingleInterfaceWithIntentsOnInterfaceAtInterfaceLevel() throws Exception {
+ serviceProcessor.visitClass(Service1.class, type);
+ policyProcessor.visitClass(Service1.class, type);
+ verifyIntents(Service1.class, type);
+ }
+
+ public void testMultipleInterfacesWithIntentsOnInterfaceAtInterfaceLevel() throws Exception {
+ serviceProcessor.visitClass(Service2.class, type);
+ policyProcessor.visitClass(Service2.class, type);
+ verifyIntents(Service2.class, type);
+ }
+
+ public void testSingleInterfaceWithIntentsOnImplAtClassLevel() throws Exception {
+ serviceProcessor.visitClass(Service3.class, type);
+ policyProcessor.visitClass(Service3.class, type);
+ verifyIntents(Service3.class, type);
+ }
+
+ public void testMultipleInterfacesWithIntentsOnImplAtClassLevel() throws Exception {
+ serviceProcessor.visitClass(Service4.class, type);
+ policyProcessor.visitClass(Service4.class, type);
+ verifyIntents(Service4.class, type);
+ }
+
+ public void testSingleInterfaceWithIntentsOnInterfaceAtMethodLevel() throws Exception {
+ serviceProcessor.visitClass(Service5.class, type);
+ policyProcessor.visitClass(Service5.class, type);
+ verifyIntents(Service5.class, type);
+ }
+
+ public void testSingleInterfaceWithIntentsOnServiceAndInterfaceAtImplAndInertfaceAndMethodLevel() throws Exception {
+ serviceProcessor.visitClass(Service6.class, type);
+ policyProcessor.visitClass(Service6.class, type);
+ for (Method method : Service6.class.getDeclaredMethods()) {
+ policyProcessor.visitMethod(method, type);
+ }
+ verifyIntents(Service6.class, type);
+ }
+
+ private void verifyIntents(Class serviceImplClass, JavaImplementation type) {
+
+ Requires serviceImplIntentAnnotation = (Requires)serviceImplClass.getAnnotation(Requires.class);
+ if (serviceImplIntentAnnotation != null) {
+ String[] serviceImplIntents = serviceImplIntentAnnotation.value();
+ List<Intent> requiredIntents = type.getRequiredIntents();
+ if (serviceImplIntents.length > 0) {
+ if (requiredIntents == null || requiredIntents.size() == 0) {
+ fail("No Intents on the service ");
+ }
+ Map<String, Intent> intentMap = new HashMap<String, Intent>();
+ for (Intent intent : requiredIntents) {
+ intentMap.put(intent.getName().getLocalPart(), intent);
+ }
+ for (String intent : serviceImplIntents) {
+ assertTrue("ComponentType for Service class " + serviceImplClass.getName()
+ + " did not contain Service Implementation intent "
+ + intent, intentMap.containsKey(intent));
+ }
+ }
+ }
+
+ // This should match what was specified on @Service for a Service Implementation
+ // If we use these to get the Service names and we get a null Service
+ // name then it would seem that wrong values were put on the @Service annotation
+ // or the wrong interfaces were specified on the implements list of the class
+ // statement?
+ Map<String, org.apache.tuscany.sca.assembly.Service> serviceMap = new HashMap<String, org.apache.tuscany.sca.assembly.Service>();
+ for (org.apache.tuscany.sca.assembly.Service service: type.getServices()) {
+ serviceMap.put(service.getName(), service);
+ }
+ for (Class interfaceClass : serviceImplClass.getInterfaces()) {
+ Requires interfaceIntentAnnotation = (Requires)interfaceClass.getAnnotation(Requires.class);
+ org.apache.tuscany.sca.assembly.Service service = serviceMap.get(interfaceClass.getSimpleName());
+ if (service == null) {
+ fail("No service defined for interface " + interfaceClass.getSimpleName()
+ + " on Service Implementation "
+ + serviceImplClass.getName());
+ }
+
+ if (interfaceIntentAnnotation != null) {
+ String[] interfaceIntents = interfaceIntentAnnotation.value();
+ List<Intent> requiredIntents = service.getRequiredIntents();
+ if (interfaceIntents.length > 0) {
+ if (requiredIntents == null || requiredIntents.size() == 0) {
+ fail("No Intents on the service " + service.getName());
+ }
+ Map<String, Intent> intentMap = new HashMap<String, Intent>();
+ for (Intent intent : requiredIntents) {
+ intentMap.put(intent.getName().getLocalPart(), intent);
+ }
+ for (String intent : interfaceIntents) {
+ assertTrue("Interface " + service.getName()
+ + " did not contain Service Interface intent "
+ + intent, intentMap.containsKey(intent));
+ }
+ }
+ }
+
+ for (Method method : interfaceClass.getDeclaredMethods()) {
+ Requires methodIntentAnnotation = method.getAnnotation(Requires.class);
+
+ // Verify that each of the Intents on each of the Service
+ // Interface Methods exist on their associated operation.
+ if (methodIntentAnnotation != null) {
+ String[] methodIntents = methodIntentAnnotation.value();
+ if (methodIntents.length > 0) {
+ List<Intent> requiredIntents = service.getRequiredIntents();
+ if (requiredIntents.size() == 0) {
+ fail("No Intents on operation " + method.getName());
+ }
+ for (String intent : methodIntents) {
+ boolean found = false;
+ for (Intent requiredIntent: requiredIntents) {
+ if (requiredIntent.getName().getLocalPart().equals(intent)) {
+ for (Operation operation: requiredIntent.getOperations()) {
+ if (operation.getName().equals(method.getName())) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ break;
+ }
+ assertTrue("Operation " + method.getName()
+ + " did not contain Service Interface method intent "
+ + intent, found);
+ }
+ }
+ }
+ }
+
+ for (Method method : serviceImplClass.getDeclaredMethods()) {
+ Requires methodIntentAnnotation = method.getAnnotation(Requires.class);
+
+ // Verify that each of the Intents on each of the Service
+ // Implementation Methods exist on their associated
+ // operation.
+ if (methodIntentAnnotation != null) {
+ String[] methodIntents = methodIntentAnnotation.value();
+ if (methodIntents.length > 0) {
+ List<Intent> requiredIntents = type.getRequiredIntents();
+ if (requiredIntents.size() == 0) {
+ fail("No Intents on operation " + method.getName());
+ }
+ for (String intent : methodIntents) {
+ boolean found = false;
+ for (Intent requiredIntent: requiredIntents) {
+ if (requiredIntent.getName().getLocalPart().equals(intent)) {
+ for (Operation operation: requiredIntent.getOperations()) {
+ if (operation.getName().equals(method.getName())) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ break;
+ }
+ assertTrue("Operation " + method.getName()
+ + " did not contain Service Interface method intent "
+ + intent, found);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ ExtensibleJavaInterfaceIntrospector introspector = new ExtensibleJavaInterfaceIntrospector(new DefaultJavaInterfaceFactory(), visitors);
+ serviceProcessor = new ServiceProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory(), introspector);
+ policyProcessor = new PolicyProcessor(new DefaultAssemblyFactory(), new DefaultPolicyFactory());
+ JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+ type = javaImplementationFactory.createJavaImplementation();
+ }
+
+ // @Remotable
+ @Requires( {"transaction.global"})
+ private interface Interface1 {
+ int method1();
+
+ int method2();
+
+ int method3();
+
+ int method4();
+ }
+
+ @Service(Interface1.class)
+ private class Service1 implements Interface1 {
+ public int method1() {
+ return 0;
+ }
+
+ public int method2() {
+ return 0;
+ }
+
+ public int method3() {
+ return 0;
+ }
+
+ public int method4() {
+ return 0;
+ }
+ }
+
+ // @Remotable
+ @Requires( {"transaction.local"})
+ private interface Interface2 {
+ int method5();
+
+ int method6();
+ }
+
+ @Service(interfaces = {Interface1.class, Interface2.class})
+ private class Service2 implements Interface1, Interface2 {
+ public int method1() {
+ return 0;
+ }
+
+ public int method2() {
+ return 0;
+ }
+
+ public int method3() {
+ return 0;
+ }
+
+ public int method4() {
+ return 0;
+ }
+
+ public int method5() {
+ return 0;
+ }
+
+ public int method6() {
+ return 0;
+ }
+ }
+
+ // @Remotable
+ private interface Interface3 {
+ int method1();
+
+ int method2();
+
+ int method3();
+
+ int method4();
+ }
+
+ @Service(Interface3.class)
+ @Requires( {"transaction.global"})
+ private class Service3 implements Interface3 {
+ public int method1() {
+ return 0;
+ }
+
+ public int method2() {
+ return 0;
+ }
+
+ public int method3() {
+ return 0;
+ }
+
+ public int method4() {
+ return 0;
+ }
+ }
+
+ // @Remotable
+ private interface Interface4 {
+ int method5();
+
+ int method6();
+ }
+
+ @Service(interfaces = {Interface3.class, Interface4.class})
+ @Requires( {"transaction.local"})
+ private class Service4 implements Interface3, Interface4 {
+ public int method1() {
+ return 0;
+ }
+
+ public int method2() {
+ return 0;
+ }
+
+ public int method3() {
+ return 0;
+ }
+
+ public int method4() {
+ return 0;
+ }
+
+ public int method5() {
+ return 0;
+ }
+
+ public int method6() {
+ return 0;
+ }
+ }
+
+ private interface Interface5 {
+ @Requires( {"transaction.global"})
+ int method1();
+
+ @Requires( {"transaction.local"})
+ int method2();
+ }
+
+ @Service(Interface5.class)
+ private class Service5 implements Interface5 {
+ public int method1() {
+ return 0;
+ }
+
+ public int method2() {
+ return 0;
+ }
+ }
+
+ @Requires( {"transaction.global.Interface6"})
+ private interface Interface6 {
+ @Requires( {"transaction.global.Interface6.method1"})
+ int method1();
+
+ @Requires( {"transaction.local.Interface6.method2"})
+ int method2();
+ }
+
+ @Service(Interface6.class)
+ @Requires( {"transaction.global.Service6"})
+ private class Service6 implements Interface6 {
+ @Requires( {"transaction.global.Service6.method1"})
+ public int method1() {
+ return 0;
+ }
+
+ @Requires( {"transaction.global.Service6.method1"})
+ public int method2() {
+ return 0;
+ }
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessorTestCase.java
new file mode 100644
index 0000000000..ccac012138
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessorTestCase.java
@@ -0,0 +1,213 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty;
+
+import java.util.Collection;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.DuplicatePropertyException;
+import org.apache.tuscany.sca.implementation.java.introspect.IllegalPropertyException;
+import org.osoa.sca.annotations.Property;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class PropertyProcessorTestCase extends TestCase {
+
+ JavaImplementation type;
+ PropertyProcessor processor;
+
+ public void testMethodAnnotation() throws Exception {
+ processor.visitMethod(Foo.class.getMethod("setFoo", String.class), type);
+ assertNotNull(getProperty(type, "foo"));
+ }
+
+ public void testMethodRequired() throws Exception {
+ processor.visitMethod(Foo.class.getMethod("setFooRequired", String.class), type);
+ org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "fooRequired");
+ assertNotNull(prop);
+ assertTrue(prop.isMustSupply());
+ }
+
+ public void testMethodName() throws Exception {
+ processor.visitMethod(Foo.class.getMethod("setBarMethod", String.class), type);
+ assertNotNull(getProperty(type, "bar"));
+ }
+
+ public void testFieldAnnotation() throws Exception {
+ processor.visitField(Foo.class.getDeclaredField("baz"), type);
+ assertNotNull(getProperty(type, "baz"));
+ }
+
+ public void testFieldRequired() throws Exception {
+ processor.visitField(Foo.class.getDeclaredField("bazRequired"), type);
+ org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "bazRequired");
+ assertNotNull(prop);
+ assertTrue(prop.isMustSupply());
+ }
+
+ public void testFieldName() throws Exception {
+ processor.visitField(Foo.class.getDeclaredField("bazField"), type);
+ assertNotNull(getProperty(type, "theBaz"));
+ }
+
+ public void testDuplicateFields() throws Exception {
+ processor.visitField(Bar.class.getDeclaredField("dup"), type);
+ try {
+ processor.visitField(Bar.class.getDeclaredField("baz"), type);
+ fail();
+ } catch (DuplicatePropertyException e) {
+ // expected
+ }
+ }
+
+ public void testDuplicateMethods() throws Exception {
+ processor.visitMethod(Bar.class.getMethod("dupMethod", String.class), type);
+ try {
+ processor.visitMethod(Bar.class.getMethod("dupSomeMethod", String.class), type);
+ fail();
+ } catch (DuplicatePropertyException e) {
+ // expected
+ }
+ }
+
+ public void testInvalidProperty() throws Exception {
+ try {
+ processor.visitMethod(Bar.class.getMethod("badMethod"), type);
+ fail();
+ } catch (IllegalPropertyException e) {
+ // expected
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+ type = javaImplementationFactory.createJavaImplementation();
+ processor = new PropertyProcessor(new DefaultAssemblyFactory());
+ }
+
+ private class Foo {
+
+ @Property
+ protected String baz;
+ @Property(required = true)
+ protected String bazRequired;
+ @Property(name = "theBaz")
+ protected String bazField;
+
+ @Property
+ public void setFoo(String string) {
+ }
+
+ @Property(required = true)
+ public void setFooRequired(String string) {
+ }
+
+ @Property(name = "bar")
+ public void setBarMethod(String string) {
+ }
+
+ }
+
+ private class Bar {
+
+ @Property
+ protected String dup;
+
+ @Property(name = "dup")
+ protected String baz;
+
+ @Property
+ public void dupMethod(String s) {
+ }
+
+ @Property(name = "dupMethod")
+ public void dupSomeMethod(String s) {
+ }
+
+ @Property
+ public void badMethod() {
+ }
+
+ }
+
+ private class Multiple {
+ @Property
+ protected List<String> refs1;
+
+ @Property
+ protected String[] refs2;
+
+ @Property
+ public void setRefs3(String[] refs) {
+ }
+
+ @Property
+ public void setRefs4(Collection<String> refs) {
+ }
+
+ }
+
+ private Class<?> getBaseType(JavaElementImpl element) {
+ return JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType());
+ }
+
+ public void testMultiplicityCollection() throws Exception {
+ processor.visitField(Multiple.class.getDeclaredField("refs1"), type);
+ org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "refs1");
+ assertNotNull(prop);
+ assertSame(String.class, getBaseType(type.getPropertyMembers().get(prop.getName())));
+ assertTrue(prop.isMany());
+ }
+
+ public void testMultiplicityArray() throws Exception {
+ processor.visitField(Multiple.class.getDeclaredField("refs2"), type);
+ org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "refs2");
+ assertNotNull(prop);
+ assertSame(String.class, getBaseType(type.getPropertyMembers().get(prop.getName())));
+ assertTrue(prop.isMany());
+ }
+
+ public void testMultiplicityArrayMethod() throws Exception {
+ processor.visitMethod(Multiple.class.getMethod("setRefs3", String[].class), type);
+ org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "refs3");
+ assertNotNull(prop);
+ assertSame(String.class, getBaseType(type.getPropertyMembers().get(prop.getName())));
+ assertTrue(prop.isMany());
+ }
+
+ public void testMultiplicityCollectionMethod() throws Exception {
+ processor.visitMethod(Multiple.class.getMethod("setRefs4", Collection.class), type);
+ org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "refs4");
+ assertNotNull(prop);
+ assertSame(String.class, getBaseType(type.getPropertyMembers().get(prop.getName())));
+ assertTrue(prop.isMany());
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessorTestCase.java
new file mode 100644
index 0000000000..f70cef6090
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessorTestCase.java
@@ -0,0 +1,224 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getReference;
+
+import java.util.Collection;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+import org.osoa.sca.annotations.Reference;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ReferenceProcessorTestCase extends TestCase {
+
+ private JavaImplementation type;
+ private ReferenceProcessor processor;
+
+ public void testMethodAnnotation() throws Exception {
+ processor.visitMethod(ReferenceProcessorTestCase.Foo.class.getMethod("setFoo", Ref.class), type);
+ org.apache.tuscany.sca.assembly.Reference reference = getReference(type, "foo");
+ assertNotNull(reference);
+ assertEquals(Ref.class, ((JavaInterface)reference.getInterfaceContract().getInterface()).getJavaClass());
+ }
+
+ public void testMethodRequired() throws Exception {
+ processor.visitMethod(ReferenceProcessorTestCase.Foo.class.getMethod("setFooRequired", Ref.class), type);
+ org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "fooRequired");
+ assertNotNull(ref);
+ assertEquals(Multiplicity.ONE_ONE, ref.getMultiplicity());
+ }
+
+ public void testMethodName() throws Exception {
+ processor.visitMethod(ReferenceProcessorTestCase.Foo.class.getMethod("setBarMethod", Ref.class), type);
+ assertNotNull(getReference(type, "bar"));
+ }
+
+ public void testFieldAnnotation() throws Exception {
+ processor.visitField(ReferenceProcessorTestCase.Foo.class.getDeclaredField("baz"), type);
+ org.apache.tuscany.sca.assembly.Reference reference = getReference(type, "baz");
+ assertNotNull(reference);
+ assertEquals(Ref.class, ((JavaInterface)reference.getInterfaceContract().getInterface()).getJavaClass());
+ }
+
+ public void testFieldRequired() throws Exception {
+ processor.visitField(ReferenceProcessorTestCase.Foo.class.getDeclaredField("bazRequired"), type);
+ org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "bazRequired");
+ assertNotNull(ref);
+ assertEquals(Multiplicity.ONE_ONE, ref.getMultiplicity());
+ }
+
+ public void testFieldName() throws Exception {
+ processor.visitField(ReferenceProcessorTestCase.Foo.class.getDeclaredField("bazField"), type);
+ assertNotNull(getReference(type, "theBaz"));
+ }
+
+ public void testDuplicateFields() throws Exception {
+ processor.visitField(ReferenceProcessorTestCase.Bar.class.getDeclaredField("dup"), type);
+ try {
+ processor.visitField(ReferenceProcessorTestCase.Bar.class.getDeclaredField("baz"), type);
+ fail();
+ } catch (DuplicateReferenceException e) {
+ // expected
+ }
+ }
+
+ public void testDuplicateMethods() throws Exception {
+ processor.visitMethod(ReferenceProcessorTestCase.Bar.class.getMethod("dupMethod", Ref.class), type);
+ try {
+ processor.visitMethod(ReferenceProcessorTestCase.Bar.class.getMethod("dupSomeMethod", Ref.class), type);
+ fail();
+ } catch (DuplicateReferenceException e) {
+ // expected
+ }
+ }
+
+ public void testInvalidProperty() throws Exception {
+ try {
+ processor.visitMethod(ReferenceProcessorTestCase.Bar.class.getMethod("badMethod"), type);
+ fail();
+ } catch (IllegalReferenceException e) {
+ // expected
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+ type = javaImplementationFactory.createJavaImplementation();
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ processor = new ReferenceProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory(), new ExtensibleJavaInterfaceIntrospector(new DefaultJavaInterfaceFactory(), visitors));
+ }
+
+ private interface Ref {
+ }
+
+ private class Foo {
+
+ @Reference
+ protected Ref baz;
+ @Reference(required = true)
+ protected Ref bazRequired;
+ @Reference(name = "theBaz")
+ protected Ref bazField;
+
+ @Reference
+ public void setFoo(Ref ref) {
+ }
+
+ @Reference(required = true)
+ public void setFooRequired(Ref ref) {
+ }
+
+ @Reference(name = "bar")
+ public void setBarMethod(Ref ref) {
+ }
+
+ }
+
+ private class Bar {
+
+ @Reference
+ protected Ref dup;
+
+ @Reference(name = "dup")
+ protected Ref baz;
+
+ @Reference
+ public void dupMethod(Ref s) {
+ }
+
+ @Reference(name = "dupMethod")
+ public void dupSomeMethod(Ref s) {
+ }
+
+ @Reference
+ public void badMethod() {
+ }
+
+ }
+
+ private class Multiple {
+ @Reference(required = true)
+ protected List<Ref> refs1;
+
+ @Reference(required = false)
+ protected Ref[] refs2;
+
+ @Reference(required = true)
+ public void setRefs3(Ref[] refs) {
+ }
+
+ @Reference(required = false)
+ public void setRefs4(Collection<Ref> refs) {
+ }
+
+ }
+
+ public void testMultiplicity1ToN() throws Exception {
+ processor.visitField(Multiple.class.getDeclaredField("refs1"), type);
+ org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "refs1");
+ assertNotNull(ref);
+ assertSame(Ref.class, ((JavaInterface)ref.getInterfaceContract().getInterface()).getJavaClass());
+ assertEquals(Multiplicity.ONE_N, ref.getMultiplicity());
+ // assertEquals(Multiplicity.ONE_ONE, ref.getMultiplicity());
+ }
+
+ public void testMultiplicityTo0ToN() throws Exception {
+ processor.visitField(Multiple.class.getDeclaredField("refs2"), type);
+ org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "refs2");
+ assertNotNull(ref);
+ assertSame(Ref.class, ((JavaInterface)ref.getInterfaceContract().getInterface()).getJavaClass());
+ assertEquals(Multiplicity.ZERO_N, ref.getMultiplicity());
+ // assertFalse(ref.isMustSupply());
+ }
+
+ public void testMultiplicity1ToNMethod() throws Exception {
+ processor.visitMethod(Multiple.class.getMethod("setRefs3", Ref[].class), type);
+ org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "refs3");
+ assertNotNull(ref);
+ assertSame(Ref.class, ((JavaInterface)ref.getInterfaceContract().getInterface()).getJavaClass());
+ assertEquals(Multiplicity.ONE_N, ref.getMultiplicity());
+ // assertEquals(Multiplicity.ONE_ONE, ref.getMultiplicity());
+ }
+
+ public void testMultiplicity0ToNMethod() throws Exception {
+ processor.visitMethod(Multiple.class.getMethod("setRefs4", Collection.class), type);
+ org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "refs4");
+ assertNotNull(ref);
+ assertSame(Ref.class, ((JavaInterface)ref.getInterfaceContract().getInterface()).getJavaClass());
+ assertEquals(Multiplicity.ZERO_N, ref.getMultiplicity());
+ // assertFalse(ref.isMustSupply());
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessorTestCase.java
new file mode 100644
index 0000000000..87ac37fea9
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessorTestCase.java
@@ -0,0 +1,118 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ResourceProcessorTestCase extends TestCase {
+
+ JavaImplementation type;
+ ResourceProcessor processor = new ResourceProcessor(new DefaultAssemblyFactory());
+
+ public void testVisitField() throws Exception {
+ Field field = Foo.class.getDeclaredField("bar");
+ processor.visitField(field, type);
+ JavaResourceImpl resource = type.getResources().get("bar");
+ assertFalse(resource.isOptional());
+ assertNull(resource.getMappedName());
+ assertEquals(field.getType(), resource.getElement().getType());
+ }
+
+ public void testVisitMethod() throws Exception {
+ Method method = Foo.class.getMethod("setBar", Bar.class);
+ processor.visitMethod(method, type);
+ JavaResourceImpl resource = type.getResources().get("bar");
+ assertFalse(resource.isOptional());
+ assertNull(resource.getMappedName());
+ assertEquals(method.getParameterTypes()[0], resource.getElement().getType());
+ }
+
+ public void testVisitNamedMethod() throws Exception {
+ Method method = Foo.class.getMethod("setBar2", Bar.class);
+ processor.visitMethod(method, type);
+ JavaResourceImpl resource = type.getResources().get("someName");
+ assertFalse(resource.isOptional());
+ assertEquals("mapped", resource.getMappedName());
+ }
+
+ public void testVisitBadMethod() throws Exception {
+ Method method = Foo.class.getMethod("setBad");
+ try {
+ processor.visitMethod(method, type);
+ fail();
+ } catch (IllegalResourceException e) {
+ // expected
+ }
+ }
+
+ public void testDuplicateResources() throws Exception {
+ Field field = Foo.class.getDeclaredField("bar");
+ processor.visitField(field, type);
+ try {
+ processor.visitField(field, type);
+ fail();
+ } catch (DuplicateResourceException e) {
+ //expected
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+ type = javaImplementationFactory.createJavaImplementation();
+ }
+
+ private class Foo {
+
+ @org.apache.tuscany.api.annotation.Resource
+ protected Bar bar;
+
+ @org.apache.tuscany.api.annotation.Resource(optional = true)
+ protected Bar barNotRequired;
+
+ @org.apache.tuscany.api.annotation.Resource
+ public void setBar(Bar bar) {
+ }
+
+ @org.apache.tuscany.api.annotation.Resource(name = "someName", mappedName = "mapped")
+ public void setBar2(Bar bar) {
+ }
+
+ @org.apache.tuscany.api.annotation.Resource
+ public void setBad() {
+ }
+
+ }
+
+ private interface Bar {
+
+ }
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessorTestCase.java
new file mode 100644
index 0000000000..8faaf6949f
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessorTestCase.java
@@ -0,0 +1,116 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.easymock.EasyMock;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ScopeProcessorTestCase extends TestCase {
+
+ Component parent;
+ private JavaImplementationFactory javaImplementationFactory;
+
+ public void testCompositeScope() throws IntrospectionException {
+ ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+
+ processor.visitClass(Composite.class, type);
+ assertEquals(JavaScopeImpl.COMPOSITE, type.getJavaScope());
+ }
+
+ public void testSessionScope() throws IntrospectionException {
+ ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(Session.class, type);
+ assertEquals(JavaScopeImpl.SESSION, type.getJavaScope());
+ }
+
+ public void testConversationalScope() throws IntrospectionException {
+ ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(Conversation.class, type);
+ assertEquals(JavaScopeImpl.CONVERSATION, type.getJavaScope());
+ }
+
+ public void testRequestScope() throws IntrospectionException {
+ ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(Request.class, type);
+ assertEquals(JavaScopeImpl.REQUEST, type.getJavaScope());
+ }
+
+ public void testStatelessScope() throws IntrospectionException {
+ ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(Stateless.class, type);
+ assertEquals(JavaScopeImpl.STATELESS, type.getJavaScope());
+ }
+
+ public void testNoScope() throws IntrospectionException {
+ ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory());
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(None.class, type);
+ assertEquals(JavaScopeImpl.STATELESS, type.getJavaScope());
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ parent = EasyMock.createNiceMock(Component.class);
+ }
+
+ @org.osoa.sca.annotations.Scope("COMPOSITE")
+ private class Composite {
+ }
+
+ @org.osoa.sca.annotations.Scope("SESSION")
+ private class Session {
+ }
+
+ @org.osoa.sca.annotations.Scope("CONVERSATION")
+ private class Conversation {
+ }
+
+ @org.osoa.sca.annotations.Scope("REQUEST")
+ private class Request {
+ }
+
+ @org.osoa.sca.annotations.Scope("SYSTEM")
+ private class System {
+ }
+
+ @org.osoa.sca.annotations.Scope("STATELESS")
+ private class Stateless {
+ }
+
+ private class None {
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceCallbackTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceCallbackTestCase.java
new file mode 100644
index 0000000000..0c98c0655e
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceCallbackTestCase.java
@@ -0,0 +1,169 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getService;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.introspect.IntrospectionException;
+import org.apache.tuscany.sca.interfacedef.InvalidCallbackException;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ServiceCallbackTestCase extends TestCase {
+ private ServiceProcessor processor;
+ private JavaImplementationFactory javaImplementationFactory;
+
+ @Override
+ protected void setUp() throws Exception {
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ processor = new ServiceProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory(), new ExtensibleJavaInterfaceIntrospector(new DefaultJavaInterfaceFactory(), visitors));
+ javaImplementationFactory = new DefaultJavaImplementationFactory();
+ }
+
+ public void testMethodCallbackInterface() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(FooImpl.class, type);
+ org.apache.tuscany.sca.assembly.Service service = getService(type, Foo.class.getSimpleName());
+ assertNotNull(service);
+ Method method = FooImpl.class.getMethod("setCallback", FooCallback.class);
+ processor.visitMethod(method, type);
+ assertEquals(method, type.getCallbackMembers().get(FooCallback.class.getName()).getAnchor());
+ }
+
+ public void testFieldCallbackInterface() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(FooImpl.class, type);
+ org.apache.tuscany.sca.assembly.Service service = getService(type, Foo.class.getSimpleName());
+ assertNotNull(service);
+ Field field = FooImpl.class.getDeclaredField("callback");
+ processor.visitField(field, type);
+ assertEquals(field, type.getCallbackMembers().get(FooCallback.class.getName()).getAnchor());
+ }
+
+ public void testMethodDoesNotMatchCallback() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(BadBarImpl.class, type);
+ Method method = BadBarImpl.class.getMethod("setWrongInterfaceCallback", String.class);
+ try {
+ processor.visitMethod(method, type);
+ fail();
+ } catch (IllegalCallbackReferenceException e) {
+ // expected
+ }
+ }
+
+ public void testNoParamCallback() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(BadBarImpl.class, type);
+ Method method = BadBarImpl.class.getMethod("setNoParamCallback");
+ try {
+ processor.visitMethod(method, type);
+ fail();
+ } catch (IllegalCallbackReferenceException e) {
+ // expected
+ }
+ }
+
+ public void testFieldDoesNotMatchCallback() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ processor.visitClass(BadBarImpl.class, type);
+ Field field = BadBarImpl.class.getDeclaredField("wrongInterfaceCallback");
+ try {
+ processor.visitField(field, type);
+ fail();
+ } catch (IllegalCallbackReferenceException e) {
+ // expected
+ }
+ }
+
+ public void testBadCallbackInterfaceAnnotation() throws Exception {
+ JavaImplementation type = javaImplementationFactory.createJavaImplementation();
+ try {
+ processor.visitClass(BadFooImpl.class, type);
+ fail();
+ } catch (IntrospectionException e) {
+ // expected
+ assertTrue(e.getCause() instanceof InvalidCallbackException);
+ }
+ }
+
+ @Callback(FooCallback.class)
+ private interface Foo {
+
+ }
+
+ private interface FooCallback {
+
+ }
+
+ @Service(Foo.class)
+ private static class FooImpl implements Foo {
+
+ @Callback
+ protected FooCallback callback;
+
+ @Callback
+ public void setCallback(FooCallback cb) {
+
+ }
+ }
+
+ private static class BadBarImpl implements Foo {
+ @Callback
+ protected String wrongInterfaceCallback;
+
+ @Callback
+ public void setWrongInterfaceCallback(String cb) {
+
+ }
+
+ @Callback
+ public void setNoParamCallback() {
+
+ }
+
+ }
+
+ @Callback
+ private interface BadFoo {
+
+ }
+
+ @Service(BadFoo.class)
+ private static class BadFooImpl implements BadFoo {
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java
new file mode 100644
index 0000000000..f905be7dc8
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java
@@ -0,0 +1,152 @@
+/*
+ * 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.sca.implementation.java.introspect.impl;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.introspect.DefaultJavaInterfaceIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector;
+import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint;
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Remotable;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ServiceProcessorTestCase extends TestCase {
+ private ServiceProcessor processor;
+ private JavaImplementation type;
+
+ public void testMultipleInterfaces() throws Exception {
+ processor.visitClass(FooMultiple.class, type);
+ assertEquals(2, type.getServices().size());
+ org.apache.tuscany.sca.assembly.Service service = ModelHelper.getService(type, Baz.class.getSimpleName());
+ assertEquals(Baz.class, ((JavaInterface)service.getInterfaceContract().getInterface()).getJavaClass());
+ assertEquals(Bar.class, ((JavaInterface)service.getInterfaceContract().getCallbackInterface()).getJavaClass());
+ assertNotNull(ModelHelper.getService(type, Bar.class.getSimpleName()));
+ }
+
+ public void testSingleInterfaces() throws Exception {
+ processor.visitClass(FooSingle.class, type);
+ assertEquals(1, type.getServices().size());
+ assertNotNull(ModelHelper.getService(type, Baz.class.getSimpleName()));
+ }
+
+ public void testMultipleNoService() throws Exception {
+ processor.visitClass(FooMultipleNoService.class, type);
+ assertEquals(0, type.getServices().size());
+ }
+
+ /**
+ * Verifies a service with a callback annotation is recognized
+ */
+ public void testMultipleWithCallbackAnnotation() throws Exception {
+ processor.visitClass(FooMultipleWithCalback.class, type);
+ assertEquals(1, type.getServices().size());
+ }
+
+ public void testRemotableNoService() throws Exception {
+ processor.visitClass(FooRemotableNoService.class, type);
+ assertEquals(1, type.getServices().size());
+ org.apache.tuscany.sca.assembly.Service service = ModelHelper.getService(type, BazRemotable.class.getSimpleName());
+ assertEquals(BazRemotable.class, ((JavaInterface)service.getInterfaceContract().getInterface()).getJavaClass());
+ }
+
+ public void testNonInterface() throws Exception {
+ try {
+ processor.visitClass(BadImpl.class, type);
+ fail();
+ } catch (InvalidServiceType e) {
+ //expected
+ }
+ }
+
+ public void testNoInterfaces() throws Exception {
+ try {
+ processor.visitClass(BadDefinition.class, type);
+ fail();
+ } catch (IllegalServiceDefinitionException e) {
+ //expected
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ JavaInterfaceIntrospectorExtensionPoint visitors = new DefaultJavaInterfaceIntrospectorExtensionPoint();
+ ExtensibleJavaInterfaceIntrospector introspector = new ExtensibleJavaInterfaceIntrospector(new DefaultJavaInterfaceFactory(), visitors);
+ processor = new ServiceProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory(), introspector);
+ JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+ type = javaImplementationFactory.createJavaImplementation();
+ }
+
+ @Callback(Bar.class)
+ private interface Baz {
+ }
+
+ private interface Bar {
+ }
+
+ private interface Bar2 {
+ }
+
+ @Remotable
+ private interface BazRemotable {
+ }
+
+ @Service(interfaces = {Baz.class, Bar.class})
+ private class FooMultiple implements Baz, Bar {
+
+ }
+
+ @Service(Baz.class)
+ private class FooSingle implements Baz, Bar {
+
+ }
+
+ private class FooMultipleNoService implements Bar, Bar2 {
+
+ }
+
+ private class FooMultipleWithCalback implements Baz, Bar {
+
+ }
+
+ private class FooRemotableNoService implements BazRemotable, Bar {
+
+ }
+
+ @Service(FooSingle.class)
+ private class BadImpl extends FooSingle {
+
+ }
+
+
+ @Service()
+ private class BadDefinition extends FooSingle {
+
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/ReadTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/ReadTestCase.java
new file mode 100644
index 0000000000..64ba0667f5
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/ReadTestCase.java
@@ -0,0 +1,120 @@
+/*
+ * 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.sca.implementation.java.xml;
+
+import java.io.InputStream;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.assembly.DefaultSCABindingFactory;
+import org.apache.tuscany.sca.assembly.SCABindingFactory;
+import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl;
+import org.apache.tuscany.sca.assembly.xml.CompositeProcessor;
+import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.introspect.DefaultJavaClassIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.implementation.java.introspect.ExtensibleJavaClassIntrospector;
+import org.apache.tuscany.sca.implementation.java.introspect.JavaClassIntrospector;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl;
+import org.apache.tuscany.sca.policy.DefaultPolicyFactory;
+import org.apache.tuscany.sca.policy.PolicyFactory;
+
+/**
+ * Test reading Java implementations.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReadTestCase extends TestCase {
+
+ XMLInputFactory inputFactory;
+ DefaultStAXArtifactProcessorExtensionPoint staxProcessors;
+ ExtensibleStAXArtifactProcessor staxProcessor;
+ private AssemblyFactory assemblyFactory;
+ private SCABindingFactory scaBindingFactory;
+ private PolicyFactory policyFactory;
+ private InterfaceContractMapper mapper;
+
+ public void setUp() throws Exception {
+ assemblyFactory = new DefaultAssemblyFactory();
+ scaBindingFactory = new DefaultSCABindingFactory();
+ policyFactory = new DefaultPolicyFactory();
+ mapper = new InterfaceContractMapperImpl();
+ inputFactory = XMLInputFactory.newInstance();
+ staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint();
+ staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance());
+
+ JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+ JavaClassIntrospector classIntrospector = new ExtensibleJavaClassIntrospector(new DefaultJavaClassIntrospectorExtensionPoint());
+
+ CompositeProcessor compositeProcessor = new CompositeProcessor(assemblyFactory, policyFactory, mapper, staxProcessor);
+ staxProcessors.addArtifactProcessor(compositeProcessor);
+
+ JavaImplementationProcessor javaProcessor = new JavaImplementationProcessor(assemblyFactory, policyFactory, javaImplementationFactory, classIntrospector);
+ staxProcessors.addArtifactProcessor(javaProcessor);
+ }
+
+ public void tearDown() throws Exception {
+ inputFactory = null;
+ staxProcessors = null;
+ policyFactory = null;
+ assemblyFactory = null;
+ mapper = null;
+ }
+
+ public void testReadComposite() throws Exception {
+ CompositeProcessor compositeProcessor = new CompositeProcessor(assemblyFactory, policyFactory, mapper, staxProcessor);
+ InputStream is = getClass().getResourceAsStream("Calculator.composite");
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(is);
+ Composite composite = compositeProcessor.read(reader);
+ assertNotNull(composite);
+
+ CompositeBuilderImpl compositeUtil = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, mapper, null);
+ compositeUtil.build(composite);
+
+ }
+
+ public void testReadAndResolveComposite() throws Exception {
+ CompositeProcessor compositeProcessor = new CompositeProcessor(assemblyFactory, policyFactory, mapper, staxProcessor);
+ InputStream is = getClass().getResourceAsStream("Calculator.composite");
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(is);
+ Composite composite = compositeProcessor.read(reader);
+ assertNotNull(composite);
+
+ ModelResolver resolver = new TestModelResolver(getClass().getClassLoader());
+ staxProcessor.resolve(composite, resolver);
+
+ CompositeBuilderImpl compositeUtil = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, mapper, null);
+ compositeUtil.build(composite);
+
+ //new PrintUtil(System.out).print(composite);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/TestModelResolver.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/TestModelResolver.java
new file mode 100644
index 0000000000..a19c7def04
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/TestModelResolver.java
@@ -0,0 +1,88 @@
+/*
+ * 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.sca.implementation.java.xml;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+
+/**
+ * A default implementation of an artifact resolver, based on a map.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TestModelResolver implements ModelResolver {
+ private static final long serialVersionUID = -7826976465762296634L;
+
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+
+ private WeakReference<ClassLoader> classLoader;
+
+ public TestModelResolver(ClassLoader classLoader) {
+ this.classLoader = new WeakReference<ClassLoader>(classLoader);
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ Object resolved = map.get(unresolved);
+ if (resolved != null) {
+
+ // Return the resolved object
+ return modelClass.cast(resolved);
+
+ } else if (unresolved instanceof ClassReference) {
+
+ // Load a class on demand
+ ClassReference classReference = (ClassReference)unresolved;
+ Class clazz;
+ try {
+ clazz = Class.forName(classReference.getClassName(), true, classLoader.get());
+ } catch (ClassNotFoundException e) {
+
+ // Return the unresolved object
+ return unresolved;
+ }
+
+ // Store a new ClassReference wrappering the loaded class
+ resolved = new ClassReference(clazz);
+ map.put(resolved, resolved);
+
+ // Return the resolved ClassReference
+ return modelClass.cast(resolved);
+
+ } else {
+
+ // Return the unresolved object
+ return unresolved;
+ }
+ }
+
+ public void addModel(Object resolved) {
+ map.put(resolved, resolved);
+ }
+
+ public Object removeModel(Object resolved) {
+ return map.remove(resolved);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/WriteTestCase.java b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/WriteTestCase.java
new file mode 100644
index 0000000000..bbac819bc9
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/WriteTestCase.java
@@ -0,0 +1,97 @@
+/*
+ * 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.sca.implementation.java.xml;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.assembly.xml.ComponentTypeProcessor;
+import org.apache.tuscany.sca.assembly.xml.CompositeProcessor;
+import org.apache.tuscany.sca.assembly.xml.ConstrainingTypeProcessor;
+import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory;
+import org.apache.tuscany.sca.implementation.java.introspect.DefaultJavaClassIntrospectorExtensionPoint;
+import org.apache.tuscany.sca.implementation.java.introspect.ExtensibleJavaClassIntrospector;
+import org.apache.tuscany.sca.implementation.java.introspect.JavaClassIntrospector;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl;
+import org.apache.tuscany.sca.policy.DefaultPolicyFactory;
+import org.apache.tuscany.sca.policy.PolicyFactory;
+
+/**
+ * Test writing Java implementations.
+ *
+ * @version $Rev$ $Date$
+ */
+public class WriteTestCase extends TestCase {
+
+ XMLInputFactory inputFactory;
+ DefaultStAXArtifactProcessorExtensionPoint staxProcessors;
+ ExtensibleStAXArtifactProcessor staxProcessor;
+ private AssemblyFactory factory;
+ private PolicyFactory policyFactory;
+ private InterfaceContractMapper mapper;
+
+ public void setUp() throws Exception {
+ factory = new DefaultAssemblyFactory();
+ policyFactory = new DefaultPolicyFactory();
+ mapper = new InterfaceContractMapperImpl();
+ inputFactory = XMLInputFactory.newInstance();
+ staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint();
+ staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance());
+
+ JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory();
+ JavaClassIntrospector classIntrospector = new ExtensibleJavaClassIntrospector(new DefaultJavaClassIntrospectorExtensionPoint());
+
+ staxProcessors.addArtifactProcessor(new CompositeProcessor(factory, policyFactory, mapper, staxProcessor));
+ staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(factory, policyFactory, staxProcessor));
+ staxProcessors.addArtifactProcessor(new ConstrainingTypeProcessor(factory, policyFactory, staxProcessor));
+
+ JavaImplementationProcessor javaProcessor = new JavaImplementationProcessor(factory, policyFactory, javaImplementationFactory, classIntrospector);
+ staxProcessors.addArtifactProcessor(javaProcessor);
+ }
+
+ public void tearDown() throws Exception {
+ inputFactory = null;
+ staxProcessors = null;
+ policyFactory = null;
+ factory = null;
+ mapper = null;
+ }
+
+ public void testReadWriteComposite() throws Exception {
+ InputStream is = getClass().getResourceAsStream("Calculator.composite");
+ Composite composite = staxProcessor.read(is, Composite.class);
+ assertNotNull(composite);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ staxProcessor.write(composite, bos);
+ }
+
+}
diff --git a/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/Calculator.composite b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/Calculator.composite
new file mode 100644
index 0000000000..7d2f71176b
--- /dev/null
+++ b/tags/java/sca/0.91-rc2-incubating/modules/implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/Calculator.composite
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ xmlns:calc="http://sample.calculator"
+ targetNamespace="http://sample.calculator"
+ name="Calculator">
+
+ <service name="CalculatorService" promote="CalculatorServiceComponent">
+ <interface.java interface="calculator.CalculatorService"/>
+ </service>
+
+ <component name="CalculatorServiceComponent">
+ <implementation.java class="calculator.CalculatorServiceImpl"/>
+ <reference name="addService" target="AddServiceComponent"/>
+ <reference name="subtractService" target="SubtractServiceComponent"/>
+ <reference name="multiplyService" target="MultiplyServiceComponent"/>
+ <reference name="divideService" target="DivideServiceComponent"/>
+ </component>
+
+ <component name="AddServiceComponent">
+ <implementation.java class="calculator.AddServiceImpl"/>
+ </component>
+
+ <component name="SubtractServiceComponent">
+ <implementation.java class="calculator.SubtractServiceImpl"/>
+ </component>
+
+ <component name="MultiplyServiceComponent">
+ <implementation.java class="calculator.MultiplyServiceImpl"/>
+ </component>
+
+ <component name="DivideServiceComponent">
+ <implementation.java class="calculator.DivideServiceImpl"/>
+ </component>
+
+</composite>