From 0f3f9b59b310833f31ba234ee4aefa808649833c Mon Sep 17 00:00:00 2001 From: lresende Date: Wed, 11 Nov 2009 23:06:50 +0000 Subject: Moving 1.x branches git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835120 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/tuscany/api/annotation/LogLevel.java | 41 ++ .../org/apache/tuscany/api/annotation/Monitor.java | 34 ++ .../apache/tuscany/api/annotation/Resource.java | 49 ++ ...DefaultJavaClassIntrospectorExtensionPoint.java | 48 ++ .../introspect/DuplicatePropertyException.java | 32 + .../ExtensibleJavaClassIntrospector.java | 126 ++++ .../java/introspect/IllegalPropertyException.java | 38 ++ .../java/introspect/IntrospectionException.java | 60 ++ .../java/introspect/JavaClassIntrospector.java | 42 ++ .../JavaClassIntrospectorExtensionPoint.java | 49 ++ .../java/introspect/JavaClassVisitor.java | 125 ++++ .../introspect/impl/AbstractPropertyProcessor.java | 167 ++++++ .../impl/AllowsPassByReferenceProcessor.java | 50 ++ .../impl/AmbiguousConstructorException.java | 40 ++ .../java/introspect/impl/BaseJavaClassVisitor.java | 64 ++ .../java/introspect/impl/ConstructorProcessor.java | 81 +++ .../java/introspect/impl/ContextProcessor.java | 80 +++ .../introspect/impl/ConversationProcessor.java | 136 +++++ .../java/introspect/impl/DestroyProcessor.java | 57 ++ .../impl/DuplicateConstructorException.java | 41 ++ .../impl/DuplicateDestructorException.java | 35 ++ .../introspect/impl/DuplicateInitException.java | 35 ++ .../impl/DuplicateReferenceException.java | 35 ++ .../impl/DuplicateResourceException.java | 36 ++ .../java/introspect/impl/EagerInitProcessor.java | 56 ++ .../introspect/impl/HeuristicPojoProcessor.java | 658 +++++++++++++++++++++ .../impl/IllegalCallbackReferenceException.java | 40 ++ .../introspect/impl/IllegalContextException.java | 40 ++ .../impl/IllegalDestructorException.java | 40 ++ .../java/introspect/impl/IllegalInitException.java | 40 ++ .../introspect/impl/IllegalReferenceException.java | 40 ++ .../introspect/impl/IllegalResourceException.java | 40 ++ .../impl/IllegalServiceDefinitionException.java | 35 ++ .../java/introspect/impl/InitProcessor.java | 57 ++ .../impl/InvalidConstructorException.java | 36 ++ .../impl/InvalidConversationalImplementation.java | 39 ++ .../introspect/impl/InvalidPropertyException.java | 35 ++ .../introspect/impl/InvalidReferenceException.java | 42 ++ .../introspect/impl/InvalidResourceException.java | 40 ++ .../java/introspect/impl/InvalidServiceType.java | 48 ++ .../introspect/impl/JavaIntrospectionHelper.java | 448 ++++++++++++++ .../introspect/impl/NoConstructorException.java | 37 ++ .../java/introspect/impl/PolicyProcessor.java | 164 +++++ .../java/introspect/impl/PropertyProcessor.java | 44 ++ .../java/introspect/impl/ReferenceProcessor.java | 171 ++++++ .../java/introspect/impl/ResourceProcessor.java | 134 +++++ .../java/introspect/impl/ScopeProcessor.java | 60 ++ .../java/introspect/impl/ServiceProcessor.java | 159 +++++ .../impl/ServiceTypeNotFoundException.java | 35 ++ .../impl/UnknownContextTypeException.java | 33 ++ .../java/xml/JavaImplementationConstants.java | 31 + .../java/xml/JavaImplementationProcessor.java | 188 ++++++ 52 files changed, 4291 insertions(+) create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/LogLevel.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Monitor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Resource.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorExtensionPoint.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DuplicatePropertyException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/ExtensibleJavaClassIntrospector.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IllegalPropertyException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IntrospectionException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospector.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospectorExtensionPoint.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java create mode 100644 sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java (limited to 'sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org') diff --git a/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/LogLevel.java b/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/LogLevel.java new file mode 100644 index 0000000000..47e205f074 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Monitor.java b/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Monitor.java new file mode 100644 index 0000000000..dea9489e5b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Resource.java b/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/api/annotation/Resource.java new file mode 100644 index 0000000000..a7158ab6b8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DefaultJavaClassIntrospectorExtensionPoint.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 IntrospectionRegistry + * + * @version $Rev$ $Date$ + */ +public class DefaultJavaClassIntrospectorExtensionPoint implements JavaClassIntrospectorExtensionPoint { + + private List visitors = new ArrayList(); + + public DefaultJavaClassIntrospectorExtensionPoint() { + } + + public void addClassVisitor(JavaClassVisitor visitor) { + visitors.add(visitor); + } + + public void removeClassVisitor(JavaClassVisitor visitor) { + visitors.remove(visitor); + } + + public List getClassVisitors() { + return visitors; + } + +} diff --git a/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/DuplicatePropertyException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/ExtensibleJavaClassIntrospector.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 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: + *
    + *
  1. 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. + *
  2. 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. + *
  3. The interfaces implemented by a class never contribute annotations + * to the class itself or any of its members. + *
  4. 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. + *
  5. Member-level annotations on a hidden or overridden member are always + * ignored. + *
+ */ + 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 methods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(clazz); + for (Method method : methods) { + for (JavaClassVisitor processor : visitors) { + processor.visitMethod(method, type); + } + } + + Set 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IllegalPropertyException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/IntrospectionException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospector.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassIntrospectorExtensionPoint.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 getClassVisitors(); + +} diff --git a/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 ComponentType. 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. + *

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 + */ + void visitClass(Class 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 + */ + void visitSuperClass(Class 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 + */ + void visitConstructor(Constructor 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 + */ + void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException; + +} diff --git a/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 extends BaseJavaClassVisitor { + private final Class annotationClass; + + protected AbstractPropertyProcessor(AssemblyFactory assemblyFactory, Class 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 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 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 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 void visitClass(Class 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 void visitClass(Class clazz, JavaImplementation type) throws IntrospectionException { + } + + public void visitSuperClass(Class clazz, JavaImplementation type) throws IntrospectionException { + } + + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + } + + public void visitConstructor(Constructor constructor, JavaImplementation type) throws IntrospectionException { + } + + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + } + + public void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException { + } + + public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type) throws IntrospectionException { + } +} diff --git a/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 void visitClass(Class 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 void visitConstructor(Constructor 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 void visitClass(Class 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 void visitClass(Class 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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

TODO + * Implement:

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 void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException { + List services = type.getServices(); + if (services.isEmpty()) { + // heuristically determine the service + // TODO finish algorithm + Set 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 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 void calcPropRefs(Set methods, + List services, + JavaImplementation type, + Class clazz) throws IntrospectionException { + // heuristically determine the properties references + // make a first pass through all public methods with one param + Set setters = new HashSet(); + 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 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 void evaluateConstructor(JavaImplementation type, Class 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 selected = null; + int sites = type.getPropertyMembers().size() + type.getReferenceMembers().size(); + for (Constructor 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 props = type.getPropertyMembers(); + Map 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 props, + Map 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 set = new HashSet(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 props, Collection 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 props, + Map 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: + *

    + *
  1. If its type is simple, then it is a property. + *
  2. 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. + *
  3. 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. + *
+ *

+ * 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 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 methods) + throws IntrospectionException { + List nonPropRefMethods = new ArrayList(); + // Map services = type.getServices(); + Map references = type.getReferenceMembers(); + Map 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 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 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 set = new HashSet(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 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 getAllPublicAndProtectedFields(Class clazz) { + return getAllPublicAndProtectedFields(clazz, new HashSet()); + } + + /** + * Recursively evaluates the type hierachy to return all fields that are + * public or protected + */ + private static Set getAllPublicAndProtectedFields(Class clazz, Set 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).

+ * 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 getAllUniquePublicProtectedMethods(Class clazz) { + return getAllUniqueMethods(clazz, new HashSet()); + } + + /** + * Recursively evaluates the type hierarchy to return all unique methods + */ + private static Set getAllUniqueMethods(Class pClass, Set 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 temp = new ArrayList(); + 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 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 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 Constructor getDefaultConstructor(Class 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 + * foo is returned as getFoo + */ + 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, setFoo(var) + * is returned as property foo + */ + 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 + 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 + * foo is returned as setFoo(var) + */ + 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: + * JavaIntrospectionHelper.getGenerics(field.getGenericType()); + *

+ * JavaIntrospectionHelper.getGenerics(m.getGenericParameterTypes()[0];); + * + * @return the generic types in order of declaration or an empty array if + * the type is not genericized + */ + public static List getGenerics(Type genericType) { + List classes = new ArrayList(); + 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:

public class Foo{ //.. } + *

+ * JavaIntrospectionHelper.introspectGeneric(Foo.class,1); + *

+ * 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 getAllInterfaces(Class clazz) { + Set implemented = new HashSet(); + getAllInterfaces(clazz, implemented); + return implemented; + } + + private static void getAllInterfaces(Class clazz, Set 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 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 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 void visitClass(Class 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 { + + 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 void visitClass(Class 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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 void visitClass(Class 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 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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/modules/implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java b/sca-java-1.x/branches/sca-java-0.91/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/sca-java-1.x/branches/sca-java-0.91/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, 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 + 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 + 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 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 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 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; + } + } + +} -- cgit v1.2.3