diff options
Diffstat (limited to 'sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca')
50 files changed, 3854 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java new file mode 100644 index 0000000000..a803311a78 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java @@ -0,0 +1,43 @@ +/* + * 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.context; + +import org.apache.tuscany.sca.scope.InstanceWrapper; + +/** + * Interface for a factory that returns an injected component instance. + * This is used by a Component implementation to create new instances of + * application implementation objects as determined by the component scope's + * lifecycle. + * <p/> + * The implementation of this interface may be supplied by the user, + * may be generated during deployment, or may be dynamic. + * + * @version $Rev$ $Date$ + * @param <T> Type of the instance generated by the factory. + */ +public interface InstanceFactory<T> { + /** + * Creates a new instance of the component. + * All injected values must be set but any @Init methods must not have been invoked. + * + * @return A wrapper for the created component instance. + */ + InstanceWrapper<T> newInstance(); +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.java new file mode 100644 index 0000000000..07f0f93690 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.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.context; + +import org.apache.tuscany.sca.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; + +/** + * @version $Rev$ $Date$ + */ +public interface InstanceFactoryProvider<T> { + /** + * Return the implementation class. + * + * @return the implementation class. + */ + Class<T> getImplementationClass(); + + /** + * Sets an object factory for an injection site + * + * @param element the injection site name + * @param objectFactory the object factory + */ + void setObjectFactory(JavaElementImpl element, ObjectFactory<?> objectFactory); + + /** + * Create an instance factory that can be used to create component instances. + * + * @return a new instance factory + */ + InstanceFactory<T> createFactory(); +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/JavaPropertyValueObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/JavaPropertyValueObjectFactory.java new file mode 100644 index 0000000000..e6176503f7 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/JavaPropertyValueObjectFactory.java @@ -0,0 +1,204 @@ +/*
+ * 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.context;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.databinding.Mediator;
+import org.apache.tuscany.sca.databinding.SimpleTypeMapper;
+import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl;
+import org.apache.tuscany.sca.databinding.xml.DOMDataBinding;
+import org.apache.tuscany.sca.factory.ObjectCreationException;
+import org.apache.tuscany.sca.factory.ObjectFactory;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.util.TypeInfo;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class JavaPropertyValueObjectFactory {
+ // protected DataBindingRegistry dbRegistry = new DataBindingRegistryImpl();
+ protected Mediator mediator = null;
+ protected SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl();
+ boolean isSimpleType;
+
+ public JavaPropertyValueObjectFactory(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+ public ObjectFactory createValueFactory(Property property, Object propertyValue, Class javaType) {
+ isSimpleType = isSimpleType(property);
+ Document doc = (Document)propertyValue;
+ Element rootElement = doc.getDocumentElement();
+ if (property.isMany()) {
+ if (isSimpleType) {
+ String value = "";
+ if (rootElement.getChildNodes().getLength() > 0) {
+ value = rootElement.getChildNodes().item(0).getTextContent();
+ }
+ List<String> values = getSimplePropertyValues(value, javaType);
+ return new ListObjectFactoryImpl(property, values, isSimpleType, javaType);
+ } else {
+ return new ListObjectFactoryImpl(property, getComplexPropertyValues(doc), isSimpleType, javaType);
+ }
+ } else {
+ if (isSimpleType) {
+ String value = "";
+ if (rootElement.getChildNodes().getLength() > 0) {
+ value = rootElement.getChildNodes().item(0).getTextContent();
+ }
+ return new ObjectFactoryImpl(property, value, isSimpleType, javaType);
+ } else {
+ List<Node> nodes = getComplexPropertyValues(doc);
+ Object value = null;
+ if (!nodes.isEmpty()) {
+ value = nodes.get(0);
+ }
+ return new ObjectFactoryImpl(property, value, isSimpleType, javaType);
+ }
+
+ }
+ }
+
+ private boolean isSimpleType(Property property) {
+ if (property.getXSDType() != null) {
+ return SimpleTypeMapperImpl.isSimpleXSDType(property.getXSDType());
+ } else {
+ if (property instanceof Document) {
+ Document doc = (Document)property;
+ Element element = doc.getDocumentElement();
+ if (element.getChildNodes().getLength() == 1 && element.getChildNodes().item(0).getNodeType() == Element.TEXT_NODE) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private List<String> getSimplePropertyValues(String concatenatedValue, Class javaType) {
+ List<String> propValues = new ArrayList<String>();
+ StringTokenizer st = null;
+ if (javaType.getName().equals("java.lang.String")) {
+ st = new StringTokenizer(concatenatedValue, "\"");
+ } else {
+ st = new StringTokenizer(concatenatedValue);
+ }
+ String aToken = null;
+ while (st.hasMoreTokens()) {
+ aToken = st.nextToken();
+ if (aToken.trim().length() > 0) {
+ propValues.add(aToken);
+ }
+ }
+ return propValues;
+ }
+
+ private List<Node> getComplexPropertyValues(Document document) {
+ Element rootElement = document.getDocumentElement();
+ List<Node> propValues = new ArrayList<Node>();
+ for (int count = 0; count < rootElement.getChildNodes().getLength(); ++count) {
+ if (rootElement.getChildNodes().item(count).getNodeType() == Document.ELEMENT_NODE) {
+ propValues.add(rootElement.getChildNodes().item(count));
+ }
+ }
+ return propValues;
+ }
+
+ public abstract class ObjectFactoryImplBase implements ObjectFactory {
+ protected SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl();
+ protected Property property;
+ protected Object propertyValue;
+ protected Class javaType;
+ protected DataType<XMLType> sourceDataType;
+ protected DataType<?> targetDataType;
+ boolean isSimpleType;
+
+ public ObjectFactoryImplBase(Property property, Object propertyValue, boolean isSimpleType, Class javaType) {
+ this.isSimpleType = isSimpleType;
+ this.property = property;
+ this.propertyValue = propertyValue;
+ this.javaType = javaType;
+ sourceDataType = new DataTypeImpl<XMLType>(DOMDataBinding.NAME, Node.class, new XMLType(null, this.property
+ .getXSDType()));
+ TypeInfo typeInfo = null;
+ if (this.property.getXSDType() != null) {
+ if (SimpleTypeMapperImpl.isSimpleXSDType(this.property.getXSDType())) {
+ typeInfo = new TypeInfo(property.getXSDType(), true, null);
+ } else {
+ typeInfo = new TypeInfo(property.getXSDType(), false, null);
+ }
+ } else {
+ typeInfo = new TypeInfo(property.getXSDType(), false, null);
+ }
+
+ XMLType xmlType = new XMLType(typeInfo);
+ String dataBinding = null; // (String)property.getExtensions().get(DataBinding.class.getName());
+ if (dataBinding != null) {
+ targetDataType = new DataTypeImpl<XMLType>(dataBinding, javaType, xmlType);
+ } else {
+ targetDataType = new DataTypeImpl<XMLType>(dataBinding, javaType, xmlType);
+ mediator.getDataBindings().introspectType(targetDataType, null);
+ }
+ }
+ }
+
+ public class ObjectFactoryImpl extends ObjectFactoryImplBase {
+ public ObjectFactoryImpl(Property property, Object propertyValue, boolean isSimpleType, Class javaType) {
+ super(property, propertyValue, isSimpleType, javaType);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getInstance() throws ObjectCreationException {
+ if (isSimpleType) {
+ return simpleTypeMapper.toJavaObject(property.getXSDType(), (String)propertyValue, null);
+ } else {
+ return mediator.mediate(propertyValue, sourceDataType, targetDataType, null);
+ // return null;
+ }
+ }
+ }
+
+ public class ListObjectFactoryImpl extends ObjectFactoryImplBase {
+ public ListObjectFactoryImpl(Property property, List<?> propertyValues, boolean isSimpleType, Class javaType) {
+ super(property, propertyValues, isSimpleType, javaType);
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<?> getInstance() throws ObjectCreationException {
+ if (isSimpleType) {
+ List<Object> values = new ArrayList<Object>();
+ for (String aValue : (List<String>)propertyValue) {
+ values.add(simpleTypeMapper.toJavaObject(property.getXSDType(), aValue, null));
+ }
+ return values;
+ } else {
+ List instances = new ArrayList();
+ for (Node aValue : (List<Node>)propertyValue) {
+ instances.add(mediator.mediate(aValue, sourceDataType, targetDataType, null));
+ }
+ return instances;
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java new file mode 100644 index 0000000000..d763c03545 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.context; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.EventInvoker; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.scope.InstanceWrapper; + +/** + * @version $Rev$ $Date$ + */ +public class ReflectiveInstanceFactory<T> implements InstanceFactory<T> { + private final Constructor<T> ctr; + private final ObjectFactory<?>[] ctrArgs; + private final Injector<T>[] injectors; + private final EventInvoker<T> initInvoker; + private final EventInvoker<T> destroyInvoker; + + public ReflectiveInstanceFactory(Constructor<T> ctr, + ObjectFactory<?>[] ctrArgs, + Injector<T>[] injectors, + EventInvoker<T> initInvoker, + EventInvoker<T> destroyInvoker) { + this.ctr = ctr; + this.ctrArgs = ctrArgs; + this.injectors = injectors; + this.initInvoker = initInvoker; + this.destroyInvoker = destroyInvoker; + } + + public InstanceWrapper<T> newInstance() { + T instance; + try { + if (ctrArgs != null) { + Object[] args = new Object[ctrArgs.length]; + for (int i = 0; i < args.length; i++) { + args[i] = ctrArgs[i].getInstance(); + } + instance = ctr.newInstance(args); + } else { + instance = ctr.newInstance(); + } + } catch (InstantiationException e) { + String name = ctr.getDeclaringClass().getName(); + throw new AssertionError("Class is not instantiable [" + name + "]"); + } catch (IllegalAccessException e) { + String name = ctr.getName(); + throw new AssertionError("Constructor is not accessible [" + name + "]"); + } catch ( + InvocationTargetException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } + + if (injectors != null) { + for (Injector<T> injector : injectors) { + //FIXME Injectors should never be null + if (injector != null) + injector.inject(instance); + } + } + + return new ReflectiveInstanceWrapper<T>(instance, initInvoker, destroyInvoker); + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java new file mode 100644 index 0000000000..31547b3e18 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.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.context; + +import org.apache.tuscany.sca.implementation.java.injection.EventInvoker; +import org.apache.tuscany.sca.scope.InstanceWrapper; +import org.apache.tuscany.sca.scope.TargetDestructionException; +import org.apache.tuscany.sca.scope.TargetInitializationException; + +/** + * @version $Rev$ $Date$ + */ +public class ReflectiveInstanceWrapper<T> implements InstanceWrapper<T> { + private final EventInvoker<T> initInvoker; + private final EventInvoker<T> destroyInvoker; + private final T instance; + + public ReflectiveInstanceWrapper(T instance, EventInvoker<T> initInvoker, EventInvoker<T> destroyInvoker) { + this.instance = instance; + this.initInvoker = initInvoker; + this.destroyInvoker = destroyInvoker; + } + + public T getInstance() { + return instance; + } + + public void start() throws TargetInitializationException { + if (initInvoker != null) { + initInvoker.invokeEvent(instance); + } + } + + + public void stop() throws TargetDestructionException { + if (destroyInvoker != null) { + destroyInvoker.invokeEvent(instance); + } + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/TargetMethodNotFoundException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/TargetMethodNotFoundException.java new file mode 100644 index 0000000000..d987489114 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/TargetMethodNotFoundException.java @@ -0,0 +1,45 @@ +/* + * 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.context; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.scope.TargetInvokerCreationException; + +/** + * @version $Rev$ $Date$ + */ +public class TargetMethodNotFoundException extends TargetInvokerCreationException { + /** + * + */ + private static final long serialVersionUID = -8565552977647191863L; + private Operation operation; + + /** + * @param operation + */ + public TargetMethodNotFoundException(Operation operation) { + super("Target method not found for operation"); + this.operation = operation; + } + + public Operation getOperation() { + return operation; + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java new file mode 100644 index 0000000000..963e5f6e7a --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java @@ -0,0 +1,54 @@ +/* + * 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.injection; + +import java.lang.reflect.Array; +import java.util.List; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; + +/** + * Resolves targets configured in a multiplicity by delegating to object factories and returning an <code>Array</code> + * containing object instances + * + * @version $Rev$ $Date$ + */ +public class ArrayMultiplicityObjectFactory implements ObjectFactory<Object> { + + private ObjectFactory[] factories; + + private Class interfaceType; + + public ArrayMultiplicityObjectFactory(Class interfaceType, List<ObjectFactory<?>> factories) { + assert interfaceType != null : "Interface type was null"; + assert factories != null : "Object factories were null"; + this.interfaceType = interfaceType; + this.factories = factories.toArray(new ObjectFactory[factories.size()]); + } + + public Object getInstance() throws ObjectCreationException { + Object array = Array.newInstance(interfaceType, factories.length); + for (int i = 0; i < factories.length; i++) { + Array.set(array, i, factories[i].getInstance()); + } + return array; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.java new file mode 100644 index 0000000000..aba8f1a901 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.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.injection; + +import org.apache.tuscany.sca.factory.ObjectCreationException; + +/** + * Implementations inject a pre-configured context type (interface) on an instance. + * + * @version $Rev$ $Date$ + */ +public interface ContextInjector<S, T> extends Injector<T> { + + void setContext(S context) throws ObjectCreationException; + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ConversationIDObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ConversationIDObjectFactory.java new file mode 100644 index 0000000000..62958c81de --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ConversationIDObjectFactory.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.injection;
+
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.factory.ObjectFactory;
+
+public class ConversationIDObjectFactory implements ObjectFactory<String> {
+
+ public ConversationIDObjectFactory() {
+ }
+
+ public String getInstance() {
+ return (String)ThreadMessageContext.getMessageContext().getConversationID();
+ }
+}
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/EventInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/EventInvoker.java new file mode 100644 index 0000000000..c2335163d6 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/EventInvoker.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.sca.implementation.java.injection; + +/** + * Performs an invocation on an instance + * + * @version $Rev$ $Date$ + */ +public interface EventInvoker<T> { + + /** + * Performs the invocation on a given instance + * + * @throws ObjectCallbackException + */ + void invokeEvent(T instance) throws ObjectCallbackException; +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.java new file mode 100644 index 0000000000..85caad103f --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.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.injection; + +import java.lang.reflect.Field; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.sca.factory.ObjectFactory} on a given field + * + * @version $Rev$ $Date$ + */ +public class FieldInjector<T> implements Injector<T> { + + private final Field field; + + private final ObjectFactory<?> objectFactory; + + /** + * Create an injector and have it use the given <code>ObjectFactory</code> to inject a value on the instance using + * the reflected <code>Field</code> + */ + public FieldInjector(Field field, ObjectFactory<?> objectFactory) { + this.field = field; + this.field.setAccessible(true); + this.objectFactory = objectFactory; + } + + /** + * Inject a new value on the given isntance + */ + public void inject(T instance) throws ObjectCreationException { + try { + field.set(instance, objectFactory.getInstance()); + } catch (IllegalAccessException e) { + throw new AssertionError("Field is not accessible [" + field + "]"); + } + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.java new file mode 100644 index 0000000000..4a8c8f31b8 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.java @@ -0,0 +1,45 @@ +/* + * 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.injection; + + +/** + * Root unchecked exception for the injection package + * + * @version $Rev$ $Date$ + */ +public abstract class InjectionRuntimeException extends RuntimeException { + + public InjectionRuntimeException() { + super(); + } + + public InjectionRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public InjectionRuntimeException(String message) { + super(message); + } + + public InjectionRuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.java new file mode 100644 index 0000000000..e580f5c2c4 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.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.injection; + +import org.apache.tuscany.sca.factory.ObjectCreationException; + +/** + * Implementations inject a pre-configured value on an instance + * + * @version $Rev$ $Date$ + */ +public interface Injector<T> { + + /** + * Inject a value on the given instance + */ + void inject(T instance) throws ObjectCreationException; + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.java new file mode 100644 index 0000000000..d157a1319f --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.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.injection; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class InvalidAccessorException extends InjectionRuntimeException { + + public InvalidAccessorException() { + super(); + } + + public InvalidAccessorException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidAccessorException(String message) { + super(message); + } + + public InvalidAccessorException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidResourceTypeException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidResourceTypeException.java new file mode 100644 index 0000000000..382925ed30 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidResourceTypeException.java @@ -0,0 +1,46 @@ +/* + * 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.injection; + +import org.apache.tuscany.sca.factory.ObjectCreationException; + +/** + * Denotes an invalid resource type, i.e. that is not a component + * + * @version $Rev$ $Date$ + */ +public class InvalidResourceTypeException extends ObjectCreationException { + + public InvalidResourceTypeException() { + super(); + } + + public InvalidResourceTypeException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidResourceTypeException(String message) { + super(message); + } + + public InvalidResourceTypeException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JNDIObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JNDIObjectFactory.java new file mode 100644 index 0000000000..750e9202a4 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JNDIObjectFactory.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.injection; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; + +/** + * An implementation of ObjectFactory that creates instances by looking them up in a JNDI context. + * + * @version $Rev$ $Date$ + */ +public class JNDIObjectFactory<T> implements ObjectFactory<T> { + private final Context context; + private final String name; + + public JNDIObjectFactory(Context context, String name) { + this.context = context; + this.name = name; + } + + + @SuppressWarnings("unchecked") + public T getInstance() throws ObjectCreationException { + try { + return (T) context.lookup(name); + } catch (NamingException e) { + throw new ObjectCreationException(e); + } + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.java new file mode 100644 index 0000000000..d474d9e781 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.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.injection; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; + +/** + * Resolves targets configured in a multiplicity by delegating to object factories and returning an <code>List</code> + * containing object instances + * + * @version $Rev$ $Date$ + */ +public class ListMultiplicityObjectFactory implements ObjectFactory<List> { + + private ObjectFactory[] factories; + + public ListMultiplicityObjectFactory(List<ObjectFactory<?>> factories) { + assert factories != null : "Object factories were null"; + this.factories = factories.toArray(new ObjectFactory[factories.size()]); + } + + public List getInstance() throws ObjectCreationException { + List<Object> list = new ArrayList<Object>(); + for (ObjectFactory factory : factories) { + list.add(factory.getInstance()); + } + return list; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvoker.java new file mode 100644 index 0000000000..0072d12a60 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvoker.java @@ -0,0 +1,55 @@ +/* + * 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.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Performs an wire on a method of a given instance + * + * @version $Rev$ $Date$ + */ +public class MethodEventInvoker<T> implements EventInvoker<T> { + private final Method method; + + /** + * Intantiates an invoker for the given method + */ + public MethodEventInvoker(Method method) { + assert method != null; + this.method = method; + } + + public void invokeEvent(T instance) throws ObjectCallbackException { + try { + method.invoke(instance, (Object[]) null); + } catch (IllegalArgumentException e) { + String name = method.getName(); + throw new ObjectCallbackException("Exception thrown by callback method [" + name + "]", e.getCause()); + } catch (IllegalAccessException e) { + String name = method.getName(); + throw new AssertionError("Method is not accessible [" + name + "]"); + } catch (InvocationTargetException e) { + String name = method.getName(); + throw new ObjectCallbackException("Exception thrown by callback method [" + name + "]", e.getCause()); + } + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java new file mode 100644 index 0000000000..1e22a0adce --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java @@ -0,0 +1,55 @@ +/* + * 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.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.sca.factory.ObjectFactory} using a given method + * + * @version $Rev$ $Date$ + */ +public class MethodInjector<T> implements Injector<T> { + private final Method method; + private final ObjectFactory<?> objectFactory; + + public MethodInjector(Method method, ObjectFactory<?> objectFactory) { + assert method != null; + assert objectFactory != null; + this.method = method; + this.method.setAccessible(true); + this.objectFactory = objectFactory; + } + + public void inject(T instance) throws ObjectCreationException { + try { + method.invoke(instance, objectFactory.getInstance()); + } catch (IllegalAccessException e) { + throw new AssertionError("Method is not accessible [" + method + "]"); + } catch (IllegalArgumentException e) { + throw new ObjectCreationException("Exception thrown by setter: " + method.getName(), e); + } catch (InvocationTargetException e) { + throw new ObjectCreationException("Exception thrown by setter: " + method.getName(), e); + } + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/NoAccessorException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/NoAccessorException.java new file mode 100644 index 0000000000..f45faa8b52 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/NoAccessorException.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.injection; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class NoAccessorException extends InjectionRuntimeException { + public NoAccessorException() { + } + + public NoAccessorException(String message) { + super(message); + } + + public NoAccessorException(String message, Throwable cause) { + super(message, cause); + } + + public NoAccessorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/NoMultiplicityTypeException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/NoMultiplicityTypeException.java new file mode 100644 index 0000000000..c1d998e811 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/NoMultiplicityTypeException.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.injection; + +/** + * @version $Rev$ $Date$ + */ +public class NoMultiplicityTypeException extends InjectionRuntimeException { + + public NoMultiplicityTypeException() { + super(); + } + + public NoMultiplicityTypeException(String message, Throwable cause) { + super(message, cause); + } + + public NoMultiplicityTypeException(String message) { + super(message); + } + + public NoMultiplicityTypeException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ObjectCallbackException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ObjectCallbackException.java new file mode 100644 index 0000000000..7d9e4e6615 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ObjectCallbackException.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.injection; + +/** + * Denotes an error when invoking on an object + * + * @version $Rev$ $Date$ + */ +public class ObjectCallbackException extends InjectionRuntimeException { + + public ObjectCallbackException() { + super(); + } + + public ObjectCallbackException(String message, Throwable cause) { + super(message, cause); + } + + public ObjectCallbackException(String message) { + super(message); + } + + public ObjectCallbackException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/PojoObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/PojoObjectFactory.java new file mode 100644 index 0000000000..ccf06cf569 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/PojoObjectFactory.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; + +/** + * Creates new instances of a Java class + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.sca.implementation.java.injection.Injector + */ +public class PojoObjectFactory<T> implements ObjectFactory<T> { + + private final Constructor<T> ctr; + private ObjectFactory[] initializerFactories; + + /** + * Creates the object factory + * + * @param ctr the constructor to use when instantiating a new object + */ + public PojoObjectFactory(Constructor<T> ctr) { + assert ctr != null; + this.ctr = ctr; + initializerFactories = new ObjectFactory[ctr.getParameterTypes().length]; + } + + /** + * Creates the object factory + * + * @param ctr the constructor to use when instantiating a new object + * @param factories an ordered list of <code>ObjectFactory</code>s to use for returning constructor parameters + */ + public PojoObjectFactory(Constructor<T> ctr, List<ObjectFactory> factories) { + assert ctr != null; + int params = ctr.getParameterTypes().length; + assert params == factories.size(); + this.ctr = ctr; + initializerFactories = new ObjectFactory[params]; + int i = 0; + for (ObjectFactory factory : factories) { + initializerFactories[i] = factory; + i++; + } + } + + /** + * Returns the ordered array of <code>ObjectFactory</code>s use in creating constructor parameters + */ + public ObjectFactory[] getInitializerFactories() { + return initializerFactories; + } + + /** + * Sets an <code>ObjectFactory</code>s to use in creating constructor parameter + * + * @param pos the constructor parameter position + * @param factory the object factory + */ + public void setInitializerFactory(int pos, ObjectFactory factory) { + assert pos < initializerFactories.length; + initializerFactories[pos] = factory; + } + + /** + * Creates a new instance of an object + */ + public T getInstance() throws ObjectCreationException { + int size = initializerFactories.length; + Object[] initargs = new Object[size]; + // create the constructor arg array + for (int i = 0; i < size; i++) { + ObjectFactory<?> objectFactory = initializerFactories[i]; + if (objectFactory == null) { + // this can happen if a reference is optional + initargs[i] = null; + } else { + initargs[i] = objectFactory.getInstance(); + } + } + try { + ctr.setAccessible(true); + return ctr.newInstance(initargs); + } catch (IllegalArgumentException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } catch (InstantiationException e) { + String name = ctr.getDeclaringClass().getName(); + throw new AssertionError("Class is not instantiable [" + name + "]"); + } catch (IllegalAccessException e) { + String name = ctr.getName(); + throw new AssertionError("Constructor is not accessible [" + name + "]"); + } catch (InvocationTargetException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.java new file mode 100644 index 0000000000..49424bb1d6 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.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.injection; + +import org.apache.tuscany.sca.core.component.RequestContextImpl; +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; +import org.osoa.sca.RequestContext; + +/** + * Creates instances of {@link org.apache.tuscany.sca.core.component.RequestContextImpl} for injection on + * component implementation instances + * + * @version $Rev$ $Date$ + */ +public class RequestContextObjectFactory implements ObjectFactory<RequestContext> { + + public RequestContextObjectFactory() { + } + + public RequestContext getInstance() throws ObjectCreationException { + return new RequestContextImpl(); + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java new file mode 100644 index 0000000000..70c368a0e6 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java @@ -0,0 +1,46 @@ +/* + * 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.injection; + +/** + * Interface implemented by host environments that allow for resolution of component implementation resources, e.g. + * items bound in a JNDI tree. + * + * @version $Rev$ $Date$ + */ +public interface ResourceHost { + + /** + * Resolve a resource matching the given type + * + * @param type the type of the resources + * @throws ResourceResolutionException if an error is encountered during resolution + */ + <T> T resolveResource(Class<T> type) throws ResourceResolutionException; + + /** + * Resolve a resource matching the given type and name + * + * @param type the type of the resources + * @param mappedName the mapped name of the resource + * @throws ResourceResolutionException if an error is encountered during resolution + */ + <T> T resolveResource(Class<T> type, String mappedName) throws ResourceResolutionException; + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java new file mode 100644 index 0000000000..c124f278da --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java @@ -0,0 +1,46 @@ +/* + * 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.injection; + +import org.apache.tuscany.sca.factory.ObjectCreationException; + +/** + * Denotes an exception thrown when a runtime resource is not found + * + * @version $Rev$ $Date$ + */ +public class ResourceNotFoundException extends ObjectCreationException { + + public ResourceNotFoundException() { + super(); + } + + public ResourceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ResourceNotFoundException(String message) { + super(message); + } + + public ResourceNotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.java new file mode 100644 index 0000000000..000b1eb533 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.java @@ -0,0 +1,87 @@ +/* + * 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.injection; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; + +/** + * Resolves a runtime resource to be injected on a field or method of a Java component type marked with {@link + * org.apache.tuscany.api.annotation.Resource}. If the mapped name of the resource is an absolute URI such as + * <code>sca://localhost</code> or <code>jndi://localhost</code> the host container namespace is searched; otherwise the + * URI is assumed to be relative and the parent composite is searched. If a mapped name is not provided, i.e. resolution + * is by type, the parent composite is first searched followed by the host namespace. + * + * @version $Rev$ $Date$ + */ +public class ResourceObjectFactory<T> implements ObjectFactory<T> { + + private Class<T> type; + private String mappedName; + private ResourceHost host; + private boolean optional; + + /** + * Instantiates a factory that resolves resources by type + * + * @param type the type of the resource to inject + * @param optional true if an error should be thrown if the resource is not found + * @param host the runtime resource provider + */ + public ResourceObjectFactory(Class<T> type, boolean optional, ResourceHost host) { + this(type, null, optional, host); + } + + /** + * Instantiates a factory that resolves resources by mapped name + * + * @param type the type of the resource to inject + * @param mappedName the resource name + * @param optional true if an error should be thrown if the resource is not found + * @param host the runtime resource provider + */ + public ResourceObjectFactory(Class<T> type, String mappedName, boolean optional, ResourceHost host) { + this.type = type; + this.host = host; + this.mappedName = mappedName; + this.optional = optional; + } + + @SuppressWarnings({"unchecked"}) + public T getInstance() throws ObjectCreationException { + try { + T resource; + if (mappedName == null) { + resource = host.resolveResource(type); + if (!optional && resource == null) { + throw new ResourceNotFoundException("Resource not found: " + type.getName()); + } + } else { + resource = host.resolveResource(type, mappedName); + if (!optional && resource == null) { + throw new ResourceNotFoundException("Resource not found: " + mappedName); + } + } + return resource; + } catch (ResourceResolutionException e) { + throw new ObjectCreationException(e); + } + + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.java new file mode 100644 index 0000000000..f94b24762a --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.java @@ -0,0 +1,43 @@ +/* + * 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.injection; + + +/** + * @version $Rev$ $Date$ + */ +public class ResourceResolutionException extends Exception { + private static final long serialVersionUID = 13421352711315479L; + + public ResourceResolutionException() { + super(); + } + + public ResourceResolutionException(String message, Throwable cause) { + super(message, cause); + } + + public ResourceResolutionException(String message) { + super(message); + } + + public ResourceResolutionException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.java new file mode 100644 index 0000000000..cc9e59b16d --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.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.injection; + +import org.apache.tuscany.sca.factory.ObjectFactory; + +/** + * Implementation of ObjectFactory that returns a single instance, typically an immutable type. + * + * @version $Rev$ $Date$ + */ +public class SingletonObjectFactory<T> implements ObjectFactory<T> { + private final T instance; + + public SingletonObjectFactory(T instance) { + this.instance = instance; + } + + public T getInstance() { + return instance; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java new file mode 100644 index 0000000000..eb8bf8d0c9 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java @@ -0,0 +1,45 @@ +/* + * 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.invocation; + +import org.apache.tuscany.sca.scope.TargetInvocationException; + +/** + * Denotes an unknown operation sequence in a conversation + * + * @version $Rev$ $Date$ + */ +public class InvalidConversationSequenceException extends TargetInvocationException { + + public InvalidConversationSequenceException() { + super(); + } + + public InvalidConversationSequenceException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidConversationSequenceException(String message) { + super(message); + } + + public InvalidConversationSequenceException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentInfo.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentInfo.java new file mode 100644 index 0000000000..b4cb9cb1a9 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentInfo.java @@ -0,0 +1,415 @@ +/* + * 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.invocation; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.core.component.ComponentContextImpl; +import org.apache.tuscany.sca.core.component.ComponentContextProvider; +import org.apache.tuscany.sca.core.component.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.invocation.CallbackWireObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.WireObjectFactory; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.context.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.context.TargetMethodNotFoundException; +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.injection.ArrayMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.ConversationIDObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.FieldInjector; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.injection.InvalidAccessorException; +import org.apache.tuscany.sca.implementation.java.injection.ListMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.MethodInjector; +import org.apache.tuscany.sca.implementation.java.injection.ObjectCallbackException; +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.scope.InstanceWrapper; +import org.apache.tuscany.sca.scope.PersistenceException; +import org.apache.tuscany.sca.scope.Scope; +import org.apache.tuscany.sca.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.scope.TargetDestructionException; +import org.apache.tuscany.sca.scope.TargetInvokerCreationException; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.annotations.ConversationID; + +/** + * The runtime instantiation of Java component implementations + * + * @version $Rev$ $Date$ + */ +public class JavaComponentInfo implements ComponentContextProvider { + private JavaPropertyValueObjectFactory propertyValueFactory; + private DataBindingExtensionPoint dataBindingRegistry; + + protected RuntimeComponent component; + protected PojoConfiguration<?> configuration; + protected Scope scope; + protected ProxyFactory proxyService; + protected URI groupId; + + private final ComponentContext componentContext; + + public JavaComponentInfo(RuntimeComponent component, PojoConfiguration configuration, + DataBindingExtensionPoint dataBindingExtensionPoint, + JavaPropertyValueObjectFactory propertyValueObjectFactory) { + super(); + this.configuration = configuration; + componentContext = new ComponentContextImpl(this); + this.groupId = configuration.getGroupId(); + this.component = component; + this.proxyService = configuration.getProxyFactory(); + this.dataBindingRegistry = dataBindingExtensionPoint; + this.propertyValueFactory = propertyValueObjectFactory; + } + + public void destroy(Object instance) throws TargetDestructionException { + if (configuration.getDestroyInvoker() != null) { + try { + configuration.getDestroyInvoker().invokeEvent(instance); + } catch (ObjectCallbackException e) { + throw new TargetDestructionException("Error destroying component instance : " + getUri().toString(), e); + } + } + } + + public InstanceWrapper<?> createInstanceWrapper() throws ObjectCreationException { + return configuration.createFactory().newInstance(); + } + + public void configureProperties(List<ComponentProperty> definedProperties) { + for (ComponentProperty p : definedProperties) { + configureProperty(p); + } + } + + public void configureProperty(ComponentProperty configuredProperty) { + JavaElementImpl element = configuration.getDefinition().getPropertyMembers().get(configuredProperty.getName()); + + if (element != null && !(element.getAnchor() instanceof Constructor) && configuredProperty.getValue() != null) { + configuration.getInjectionSites().add(element); + + Class propertyJavaType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + ObjectFactory<?> propertyObjectFactory = createPropertyValueFactory(configuredProperty, configuredProperty + .getValue(), propertyJavaType); + configuration.setObjectFactory(element, propertyObjectFactory); + } + } + + public void start() { + if (!configuration.getDefinition().getCallbackMembers().isEmpty()) { + Map<String, List<RuntimeWire>> callbackWires = new HashMap<String, List<RuntimeWire>>(); + for (ComponentService service : component.getServices()) { + + RuntimeComponentService componentService = (RuntimeComponentService)service; + if (!componentService.getCallbackWires().isEmpty()) { + callbackWires.put(componentService.getCallbackWires().get(0).getTarget().getInterfaceContract() + .getCallbackInterface().toString(), componentService.getCallbackWires()); + } + } + + for (Map.Entry<String, JavaElementImpl> entry : configuration.getDefinition().getCallbackMembers() + .entrySet()) { + List<RuntimeWire> wires = callbackWires.get(entry.getKey()); + if (wires == null) { + // this can happen when there are no client wires to a + // component that has a callback + continue; + } + JavaElementImpl element = entry.getValue(); + ObjectFactory<?> factory = new CallbackWireObjectFactory(element.getType(), proxyService, wires); + if (!(element.getAnchor() instanceof Constructor)) { + configuration.getInjectionSites().add(element); + } + configuration.setObjectFactory(element, factory); + } + } + for (Reference ref : configuration.getDefinition().getReferences()) { + JavaElementImpl element = configuration.getDefinition().getReferenceMembers().get(ref.getName()); + if (element != null) { + if (!(element.getAnchor() instanceof Constructor)) { + configuration.getInjectionSites().add(element); + } + List<RuntimeWire> wireList = null; + for (ComponentReference reference : component.getReferences()) { + if (reference.getName().equals(ref.getName())) { + wireList = ((RuntimeComponentReference)reference).getRuntimeWires(); + break; + } + } + if (ref.getMultiplicity() == Multiplicity.ONE_N || ref.getMultiplicity() == Multiplicity.ZERO_N) { + List<ObjectFactory<?>> factories = new ArrayList<ObjectFactory<?>>(); + Class<?> baseType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + for (int i = 0; i < wireList.size(); i++) { + ObjectFactory<?> factory = createWireFactory(baseType, wireList.get(i)); + factories.add(factory); + } + configuration.setObjectFactories(element, factories); + } else { + if (wireList == null && ref.getMultiplicity() == Multiplicity.ONE_ONE) { + throw new IllegalStateException("Required reference is missing: " + ref.getName()); + } + if (wireList != null && !wireList.isEmpty()) { + ObjectFactory<?> factory = createWireFactory(element.getType(), wireList.get(0)); + configuration.setObjectFactory(element, factory); + } + } + } + } + } + + public void addPropertyFactory(String name, ObjectFactory<?> factory) { + JavaElementImpl element = configuration.getDefinition().getPropertyMembers().get(name); + + if (element != null && !(element.getAnchor() instanceof Constructor)) { + configuration.getInjectionSites().add(element); + } + + configuration.setObjectFactory(element, factory); + } + + public void addResourceFactory(String name, ObjectFactory<?> factory) { + JavaResourceImpl resource = configuration.getDefinition() + .getResources().get(name); + + if (resource != null && !(resource.getElement().getAnchor() instanceof Constructor)) { + configuration.getInjectionSites().add(resource.getElement()); + } + + configuration.setObjectFactory(resource.getElement(), factory); + } + + public void addConversationIDFactory(Member member) { + ObjectFactory<String> factory = new ConversationIDObjectFactory(); + + if (member instanceof Field) { + JavaElementImpl element = new JavaElementImpl((Field)member); + element.setClassifer(ConversationID.class); + configuration.setObjectFactory(element, factory); + } else if (member instanceof Method) { + JavaElementImpl element = new JavaElementImpl((Method)member, 0); + element.setName(JavaIntrospectionHelper.toPropertyName(member.getName())); + element.setClassifer(ConversationID.class); + configuration.setObjectFactory(element, factory); + } else { + throw new InvalidAccessorException("Member must be a field or method: " + member.getName()); + } + } + + public boolean implementsCallback(Class callbackClass) { + Class<?>[] implementedInterfaces = configuration.getDefinition().getJavaClass().getInterfaces(); + for (Class<?> implementedInterface : implementedInterfaces) { + if (implementedInterface.isAssignableFrom(callbackClass)) { + return true; + } + } + + return false; + } + + protected Injector<Object> createInjector(Member member, RuntimeWire wire) { + if (member instanceof Field) { + Class<?> type = ((Field)member).getType(); + ObjectFactory<?> factory = createWireFactory(type, wire); + return new FieldInjector<Object>((Field)member, factory); + } else if (member instanceof Method) { + Class<?> type = ((Method)member).getParameterTypes()[0]; + ObjectFactory<?> factory = createWireFactory(type, wire); + return new MethodInjector<Object>((Method)member, factory); + } else if (member instanceof Constructor) { + return null; + } else { + throw new InvalidAccessorException("Member must be a field or method: " + member.getName()); + } + } + + protected Injector<Object> createMultiplicityInjector(Member member, + Class<?> interfaceType, + List<RuntimeWire> wireFactories) { + List<ObjectFactory<?>> factories = new ArrayList<ObjectFactory<?>>(); + for (RuntimeWire wire : wireFactories) { + factories.add(createWireFactory(interfaceType, wire)); + } + if (member instanceof Field) { + Field field = (Field)member; + if (field.getType().isArray()) { + return new FieldInjector<Object>(field, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new FieldInjector<Object>(field, new ListMultiplicityObjectFactory(factories)); + } + } else if (member instanceof Method) { + Method method = (Method)member; + if (method.getParameterTypes()[0].isArray()) { + return new MethodInjector<Object>(method, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new MethodInjector<Object>(method, new ListMultiplicityObjectFactory(factories)); + } + } else { + throw new InvalidAccessorException("Member must be a field or method: " + member.getName()); + } + } + + public ComponentContext getComponentContext() { + return componentContext; + } + + public <B> B getProperty(Class<B> type, String propertyName) { + JavaElementImpl element = configuration.getDefinition().getPropertyMembers().get(propertyName); + Object obj = configuration.getFactories().get(element); + if (obj instanceof ObjectFactory) { + return type.cast(((ObjectFactory<?>)obj).getInstance()); + } else if (obj instanceof List) { + List<ObjectFactory<?>> factories = (List<ObjectFactory<?>>)obj; + if (type.isArray()) { + Object array = Array.newInstance(type, factories.size()); + for (int i = 0; i < factories.size(); i++) { + Array.set(array, i, factories.get(i).getInstance()); + } + return type.cast(array); + } else { + List<Object> list = new ArrayList<Object>(); + for (ObjectFactory factory : factories) { + list.add(factory.getInstance()); + } + return type.cast(list); + } + } + return null; + + } + + public <B> B getService(Class<B> type, String name) { + List<RuntimeWire> referenceWires = getWiresForReference(name); + if (referenceWires == null || referenceWires.size() < 1) { + return null; + } else { + // TODO support multiplicity + RuntimeWire wire = referenceWires.get(0); + ObjectFactory<B> factory = createWireFactory(type, wire); + return factory.getInstance(); + } + } + + public <B> ServiceReference<B> getServiceReference(Class<B> type, String name) { + List<RuntimeWire> referenceWires = getWiresForReference(name); + if (referenceWires == null || referenceWires.size() < 1) { + return null; + } else { + // TODO support multiplicity + RuntimeWire wire = referenceWires.get(0); + ObjectFactory<B> factory = createWireFactory(type, wire); + return new ServiceReferenceImpl<B>(type, factory); + } + } + + private List<RuntimeWire> getWiresForReference(String name) { + for (ComponentReference ref : component.getReferences()) { + if (ref.getName().equals(name) || (name.equals("$self$.") && ref.getName().startsWith(name))) { + return ((RuntimeComponentReference)ref).getRuntimeWires(); + } + } + return null; + } + + public <B, R extends CallableReference<B>> R cast(B target) { + return (R)proxyService.cast(target); + } + + public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, String serviceName) { + return null; + } + + public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface) { + return null; + } + + public Object createInstance() throws ObjectCreationException { + return createInstanceWrapper().getInstance(); + } + + public PojoConfiguration<?> getConfiguration() { + return configuration; + } + + public void stop() { + } + + public void removeInstance() throws PersistenceException { + ((ScopedRuntimeComponent) component).getScopeContainer().remove(); + } + + public URI getUri() { + return URI.create(component.getURI()); + } + + public TargetInvoker createTargetInvoker(Operation operation) throws TargetInvokerCreationException { + Class<?> implClass = configuration.getImplementationClass(); + + try { + Method method = JavaInterfaceUtil.findMethod(implClass, operation); + boolean passByValue = operation.getInterface().isRemotable() && (!configuration.getDefinition() + .isAllowsPassByReference(method)); + + TargetInvoker invoker = new JavaTargetInvoker(method, component); + if (passByValue) { + return new PassByValueInvoker(dataBindingRegistry, operation, method, component); + } else { + return invoker; + } + } catch (NoSuchMethodException e) { + throw new TargetMethodNotFoundException(operation); + } + + } + + protected <B> ObjectFactory<B> createWireFactory(Class<B> interfaze, RuntimeWire wire) { + return new WireObjectFactory<B>(interfaze, wire, proxyService); + } + + protected ObjectFactory<?> createPropertyValueFactory(ComponentProperty property, + Object propertyValue, + Class javaType) { + return propertyValueFactory.createValueFactory(property, propertyValue, javaType); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java new file mode 100644 index 0000000000..61f44dd9b9 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java @@ -0,0 +1,174 @@ +/* + * 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.invocation; + +import java.net.URI; + +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.context.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; +import org.apache.tuscany.sca.implementation.java.injection.ResourceHost; +import org.apache.tuscany.sca.implementation.java.injection.ResourceObjectFactory; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.scope.InstanceWrapper; +import org.apache.tuscany.sca.scope.Scope; +import org.apache.tuscany.sca.scope.ScopedImplementationProvider; +import org.apache.tuscany.sca.scope.TargetInvokerCreationException; +import org.osoa.sca.ComponentContext; + +/** + * @version $Rev$ $Date$ + */ +public class JavaImplementationProvider implements ScopedImplementationProvider { + private JavaImplementation implementation; + private JavaComponentInfo atomicComponent; + + public JavaImplementationProvider( + RuntimeComponent component, + JavaImplementation implementation, + ProxyFactory proxyService, + DataBindingExtensionPoint dataBindingRegistry, + JavaPropertyValueObjectFactory propertyValueObjectFactory) { + super(); + this.implementation = implementation; + + try { + PojoConfiguration configuration = new PojoConfiguration(implementation); + configuration.setProxyFactory(proxyService); + // FIXME: Group id to be removed + configuration.setGroupId(URI.create("/")); + atomicComponent = new JavaComponentInfo(component, configuration, dataBindingRegistry, + propertyValueObjectFactory); + + Scope scope = getScope(); + + if (scope == Scope.SYSTEM || scope == Scope.COMPOSITE) { + // Nothing + } else { + // Check for conversational contract if conversational scope + if (scope == Scope.CONVERSATION) { + boolean hasConversationalContract = false; + for (Service serviceDef : implementation.getServices()) { + if (serviceDef.getInterfaceContract().getInterface().isConversational()) { + hasConversationalContract = true; + break; + } + } + if (!hasConversationalContract) { + String name = implementation.getJavaClass().getName(); + throw new NoConversationalContractException(name); + } + } + } + + if (implementation.getConversationIDMember() != null) { + atomicComponent.addConversationIDFactory(implementation.getConversationIDMember()); + } + + atomicComponent.configureProperties(component.getProperties()); + handleResources(implementation, atomicComponent); + } catch (Exception e) { + throw new IllegalStateException(e); + } + + } + + private void handleResources(JavaImplementation componentType, JavaComponentInfo component) { + for (JavaResourceImpl resource : componentType.getResources().values()) { + String name = resource.getName(); + + ObjectFactory<?> objectFactory = (ObjectFactory<?>)component.getConfiguration().getFactories().get(resource + .getElement()); + Class<?> type = resource.getElement().getType(); + if (ComponentContext.class.equals(type)) { + objectFactory = new PojoComponentContextFactory(component); + } else { + boolean optional = resource.isOptional(); + String mappedName = resource.getMappedName(); + objectFactory = createResourceObjectFactory(type, mappedName, optional, null); + } + component.addResourceFactory(name, objectFactory); + } + } + + private <T> ResourceObjectFactory<T> createResourceObjectFactory(Class<T> type, + String mappedName, + boolean optional, + ResourceHost host) { + return new ResourceObjectFactory<T>(type, mappedName, optional, host); + } + + public Object createInstance(RuntimeComponent component, ComponentService service) { + return atomicComponent.createInstance(); + } + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + try { + return new TargetInvokerInvoker(atomicComponent.createTargetInvoker(operation)); + } catch (TargetInvokerCreationException e) { + throw new IllegalArgumentException(e); + } + } + + public Invoker createCallbackInvoker(Operation operation) { + try { + return new TargetInvokerInvoker(atomicComponent.createTargetInvoker(operation)); + } catch (TargetInvokerCreationException e) { + throw new IllegalArgumentException(e); + } + } + + public Scope getScope() { + return new Scope(implementation.getJavaScope().getScope()); + } + + public void start() { + atomicComponent.start(); + } + + public void stop() { + atomicComponent.stop(); + } + + public InstanceWrapper createInstanceWrapper() { + return atomicComponent.createInstanceWrapper(); + } + + public boolean isEagerInit() { + return implementation.isEagerInit(); + } + + public long getMaxAge() { + return implementation.getMaxAge(); + } + + public long getMaxIdleTime() { + return implementation.getMaxIdleTime(); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.java new file mode 100644 index 0000000000..1be465cc51 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.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.invocation; + +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.context.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev$ $Date$ + */ +public class JavaImplementationProviderFactory implements ImplementationProviderFactory<JavaImplementation> { + private JavaPropertyValueObjectFactory propertyValueObjectFactory; + private DataBindingExtensionPoint dataBindingRegistry; + private ProxyFactory proxyService; + + public JavaImplementationProviderFactory(ProxyFactory proxyService, + DataBindingExtensionPoint dataBindingRegistry, + JavaPropertyValueObjectFactory propertyValueObjectFactory) { + super(); + this.proxyService = proxyService; + this.dataBindingRegistry = dataBindingRegistry; + this.propertyValueObjectFactory = propertyValueObjectFactory; + } + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, + JavaImplementation implementation) { + return new JavaImplementationProvider(component, implementation, proxyService, dataBindingRegistry, + propertyValueObjectFactory); + } + + public Class<JavaImplementation> getModelType() { + return JavaImplementation.class; + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaTargetInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaTargetInvoker.java new file mode 100644 index 0000000000..03eca2ff6b --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaTargetInvoker.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.invocation; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; + +import org.apache.tuscany.sca.core.invocation.ThreadMessageContext; +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.scope.InstanceWrapper; +import org.apache.tuscany.sca.scope.Scope; +import org.apache.tuscany.sca.scope.ScopeContainer; +import org.apache.tuscany.sca.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.scope.TargetResolutionException; + +/** + * Responsible for synchronously dispatching an invocation to a Java component + * implementation instance + * + * @version $Rev$ $Date$ + */ +public class JavaTargetInvoker implements TargetInvoker { + protected Method operation; + protected boolean stateless; + protected InstanceWrapper target; + protected boolean cacheable; + + private final RuntimeComponent component; + private final ScopeContainer scopeContainer; + + public JavaTargetInvoker(Method operation, RuntimeComponent component) { + assert operation != null : "Operation method cannot be null"; + this.operation = operation; + this.component = component; + this.scopeContainer = ((ScopedRuntimeComponent) component).getScopeContainer(); + stateless = Scope.STATELESS == this.scopeContainer.getScope(); + } + + @Override + public JavaTargetInvoker clone() throws CloneNotSupportedException { + try { + JavaTargetInvoker invoker = (JavaTargetInvoker)super.clone(); + invoker.target = null; + return invoker; + } catch (CloneNotSupportedException e) { + return null; // will not happen + } + } + + /** + * Resolves the target service instance or returns a cached one + */ + protected InstanceWrapper getInstance(ConversationSequence sequence, Object contextId) + throws TargetResolutionException, InvalidConversationSequenceException { + if (sequence == null) { + if (cacheable) { + if (target == null) { + target = scopeContainer.getWrapper(contextId); + } + return target; + } else { + return scopeContainer.getWrapper(contextId); + } + } else { + switch (sequence) { + case CONVERSATION_START: + assert !cacheable; + return scopeContainer.getWrapper(contextId); + case CONVERSATION_CONTINUE: + case CONVERSATION_END: + assert !cacheable; + return scopeContainer.getAssociatedWrapper(contextId); + default: + throw new InvalidConversationSequenceException("Unknown sequence type: " + String.valueOf(sequence)); + } + } + } + + public Object invokeTarget(final Object payload, final ConversationSequence sequence) + throws InvocationTargetException { + + // FIXME: How to deal with other scopes + Object contextId = ThreadMessageContext.getMessageContext().getConversationID(); + try { + InstanceWrapper wrapper = getInstance(sequence, contextId); + Object instance = wrapper.getInstance(); + Object ret; + if (payload != null && !payload.getClass().isArray()) { + ret = operation.invoke(instance, payload); + } else { + ret = operation.invoke(instance, (Object[])payload); + } + scopeContainer.returnWrapper(wrapper, contextId); + if (sequence == ConversationSequence.CONVERSATION_END) { + // if end conversation, remove resource + scopeContainer.remove(); + } + return ret; + } catch (InvocationTargetException e) { + throw e; + } catch (Exception e) { + throw new InvocationTargetException(e); + } + } + + public Message invoke(Message msg) { + try { + Object messageId = msg.getMessageID(); + Message workContext = ThreadMessageContext.getMessageContext(); + if (messageId != null) { + workContext.setCorrelationID(messageId); + } + Object resp = invokeTarget(msg.getBody(), msg.getConversationSequence()); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setFaultBody(e.getCause()); + } + return msg; + } + + public boolean isCacheable() { + return cacheable; + } + + public void setCacheable(boolean cacheable) { + this.cacheable = cacheable; + } + + protected InvocationChain getInvocationChain(List<InvocationChain> chains, Operation targetOperation) { + for (InvocationChain chain : chains) { + if (chain.getTargetOperation().equals(targetOperation)) { + return chain; + } + } + return null; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.java new file mode 100644 index 0000000000..a7b175cf9b --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.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.sca.implementation.java.invocation;
+
+
+/**
+ * Raised when a component has conversational scope but no conversational contract
+ *
+ * @version $Rev: 487877 $ $Date: 2006-12-16 15:32:16 -0500 (Sat, 16 Dec 2006) $
+ */
+public class NoConversationalContractException extends Exception {
+
+ private static final long serialVersionUID = -1157790036638157539L;
+
+ public NoConversationalContractException(String message) {
+ super(message);
+ }
+}
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PassByValueInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PassByValueInvoker.java new file mode 100644 index 0000000000..e9e12b9b7b --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PassByValueInvoker.java @@ -0,0 +1,117 @@ +/* + * 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.invocation; + +import java.lang.reflect.Method; +import java.util.IdentityHashMap; +import java.util.Map; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * An interceptor to enforce pass-by-value semantics for remotable interfaces + * + * @version $Rev$ $Date$ + */ +public class PassByValueInvoker extends JavaTargetInvoker { + private DataBindingExtensionPoint registry; + private Operation operation; + + /** + * @param registry + * @param operation + * @param method + * @param component + */ + public PassByValueInvoker(DataBindingExtensionPoint registry, + Operation operation, + Method method, + RuntimeComponent component) { + super(method, component); + this.registry = registry; + this.operation = operation; + } + + public Message invoke(Message msg) { + Object obj = msg.getBody(); + msg.setBody(copy((Object[])obj)); + + Message result = super.invoke(msg); + + if (!result.isFault() && operation.getOutputType() != null) { + String dataBindingId = operation.getOutputType().getDataBinding(); + DataBinding dataBinding = registry.getDataBinding(dataBindingId); + result.setBody(copy(result.getBody(), dataBinding)); + } + return result; + } + + public Object[] copy(Object[] args) { + if (args == null) { + return null; + } + Object[] copiedArgs = new Object[args.length]; + Map<Object, Object> map = new IdentityHashMap<Object, Object>(); + for (int i = 0; i < args.length; i++) { + if (args[i] == null) { + copiedArgs[i] = null; + } else { + Object copiedArg = map.get(args[i]); + if (copiedArg != null) { + copiedArgs[i] = copiedArg; + } else { + String dataBindingId = operation.getInputType().getLogical().get(i).getDataBinding(); + DataBinding dataBinding = registry.getDataBinding(dataBindingId); + copiedArg = copy(args[i], dataBinding); + map.put(args[i], copiedArg); + copiedArgs[i] = copiedArg; + } + } + } + return copiedArgs; + } + + public Object copy(Object arg, DataBinding argDataBinding) { + if (arg == null) { + return null; + } + Object copiedArg; + if (argDataBinding != null) { + copiedArg = argDataBinding.copy(arg); + } else { + copiedArg = arg; + DataType<?> dataType = registry.introspectType(arg); + if (dataType != null) { + DataBinding binding = registry.getDataBinding(dataType.getDataBinding()); + if (binding != null) { + copiedArg = binding.copy(arg); + } + } + // FIXME: What to do if it's not recognized? + } + return copiedArg; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PojoComponentContextFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PojoComponentContextFactory.java new file mode 100644 index 0000000000..612262ffb4 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PojoComponentContextFactory.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.invocation; + +import org.apache.tuscany.sca.factory.ObjectCreationException; +import org.apache.tuscany.sca.factory.ObjectFactory; +import org.osoa.sca.ComponentContext; + +/** + * @version $Rev$ $Date$ + */ +public class PojoComponentContextFactory implements ObjectFactory<ComponentContext> { + private final JavaComponentInfo component; + + + public PojoComponentContextFactory(JavaComponentInfo component) { + this.component = component; + } + + + public ComponentContext getInstance() throws ObjectCreationException { + return component.getComponentContext(); + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PojoConfiguration.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PojoConfiguration.java new file mode 100644 index 0000000000..bd8c66f914 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PojoConfiguration.java @@ -0,0 +1,218 @@ +/* + * 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.invocation; + +import java.lang.annotation.ElementType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.context.InstanceFactory; +import org.apache.tuscany.sca.implementation.java.context.InstanceFactoryProvider; +import org.apache.tuscany.sca.implementation.java.context.ReflectiveInstanceFactory; +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.injection.ArrayMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.EventInvoker; +import org.apache.tuscany.sca.implementation.java.injection.FieldInjector; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.injection.InvalidAccessorException; +import org.apache.tuscany.sca.implementation.java.injection.ListMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.MethodEventInvoker; +import org.apache.tuscany.sca.implementation.java.injection.MethodInjector; +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; + +/** + * Encapsulates confuration for a Java-based atomic component + * + * @version $Rev$ $Date$ + */ +public class PojoConfiguration<T> implements InstanceFactoryProvider<T> { + private JavaImplementation definition; + private ProxyFactory proxyService; + private URI groupId; + private URI name; + + private final List<JavaElementImpl> injectionSites; + private final EventInvoker<T> initInvoker; + private final EventInvoker<T> destroyInvoker; + private final Map<JavaElementImpl, Object> factories = new HashMap<JavaElementImpl, Object>(); + + public PojoConfiguration(JavaImplementation definition) { + this.definition = definition; + this.initInvoker = definition.getInitMethod() == null ? null : new MethodEventInvoker<T>(definition + .getInitMethod()); + this.destroyInvoker = definition.getDestroyMethod() == null ? null : new MethodEventInvoker<T>(definition + .getDestroyMethod()); + injectionSites = new ArrayList<JavaElementImpl>(); + } + + public URI getGroupId() { + return groupId; + } + + public void setGroupId(URI groupId) { + this.groupId = groupId; + } + + public EventInvoker<Object> getInitInvoker() { + if (definition.getInitMethod() != null) { + return new MethodEventInvoker<Object>(definition.getInitMethod()); + } else { + return null; + } + } + + public EventInvoker<Object> getDestroyInvoker() { + if (definition.getDestroyMethod() != null) { + return new MethodEventInvoker<Object>(definition.getDestroyMethod()); + } else { + return null; + } + } + + public ProxyFactory getProxyFactory() { + return proxyService; + } + + public void setProxyFactory(ProxyFactory proxyService) { + this.proxyService = proxyService; + } + + /** + * @return the constructor + */ + public JavaConstructorImpl<?> getConstructor() { + return definition.getConstructor(); + } + + /** + * @return the definition + */ + public JavaImplementation getDefinition() { + return definition; + } + + @SuppressWarnings("unchecked") + public InstanceFactory<T> createFactory() { + ObjectFactory<?>[] initArgs = getConstructorArgs(); + Injector<T>[] injectors = getInjectors(); + return new ReflectiveInstanceFactory<T>((Constructor<T>)definition.getConstructor().getConstructor(), + initArgs, injectors, initInvoker, destroyInvoker); + } + + protected ObjectFactory<?>[] getConstructorArgs() { + JavaConstructorImpl<?> constructor = definition.getConstructor(); + ObjectFactory<?>[] initArgs = new ObjectFactory<?>[constructor.getParameters().length]; + for (int i = 0; i < initArgs.length; i++) { + ObjectFactory<?> factory = (ObjectFactory<?>)factories.get(constructor.getParameters()[i]); + assert factory != null; + initArgs[i] = factory; + } + return initArgs; + } + + protected Injector<T>[] getInjectors() { + // work around JDK1.5 issue with allocating generic arrays + @SuppressWarnings("unchecked") + Injector<T>[] injectors = (Injector<T>[])new Injector[injectionSites.size()]; + + int i = 0; + for (JavaElementImpl element : injectionSites) { + Object obj = factories.get(element); + if (obj != null) { + if (obj instanceof ObjectFactory) { + ObjectFactory<?> factory = (ObjectFactory<?>)obj; + Member member = (Member)element.getAnchor(); + if (element.getElementType() == ElementType.FIELD) { + injectors[i++] = new FieldInjector<T>((Field)member, factory); + } else if (element.getElementType() == ElementType.PARAMETER && member instanceof Method) { + injectors[i++] = new MethodInjector<T>((Method)member, factory); + } else if (member instanceof Constructor) { + // Ignore + } else { + throw new AssertionError(String.valueOf(element)); + } + } else { + injectors[i++] = createMultiplicityInjector(element, (List<ObjectFactory<?>>)obj); + } + } + } + return injectors; + } + + protected Injector<T> createMultiplicityInjector(JavaElementImpl element, List<ObjectFactory<?>> factories) { + Class<?> interfaceType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + + if (element.getAnchor() instanceof Field) { + Field field = (Field)element.getAnchor(); + if (field.getType().isArray()) { + return new FieldInjector<T>(field, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new FieldInjector<T>(field, new ListMultiplicityObjectFactory(factories)); + } + } else if (element.getAnchor() instanceof Method) { + Method method = (Method)element.getAnchor(); + if (method.getParameterTypes()[0].isArray()) { + return new MethodInjector<T>(method, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new MethodInjector<T>(method, new ListMultiplicityObjectFactory(factories)); + } + } else { + throw new InvalidAccessorException("Member must be a field or method: " + element.getName()); + } + } + + @SuppressWarnings("unchecked") + public Class<T> getImplementationClass() { + return (Class<T>)definition.getJavaClass(); + } + + public void setObjectFactory(JavaElementImpl element, ObjectFactory<?> objectFactory) { + factories.put(element, objectFactory); + } + + public void setObjectFactories(JavaElementImpl element, List<ObjectFactory<?>> objectFactory) { + factories.put(element, objectFactory); + } + + /** + * @return the injectionSites + */ + public List<JavaElementImpl> getInjectionSites() { + return injectionSites; + } + + /** + * @return the factories + */ + public Map<JavaElementImpl, Object> getFactories() { + return factories; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/TargetInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/TargetInvoker.java new file mode 100644 index 0000000000..5e390f1c45 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/TargetInvoker.java @@ -0,0 +1,69 @@ +/* + * 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.invocation; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.invocation.Message; + +/** + * Implementations are responsible for resolving a target and performing the actual invocation on it, for example, a + * component implementation instance or a service client. + * + * @version $Rev$ $Date$ + * @Deprecated + */ +public interface TargetInvoker extends Cloneable { + + /** + * Invokes an operation on a target with the given payload. Used in optmized cases where messages do not need to be + * flowed such as in non-proxied wires. + * + * @param payload the invocation payload, typically an array of parameters + * @param sequence if the invocation is part of a conversation, the sequence. Valid values are {@link #NONE} for + * non-conversational, {@link #START} to begin a conversation, {@link #CONTINUE} to continue a + * conversation, or {@link #END} to end a conversation + * @return the result of the invocation + * @throws InvocationTargetException if there was a problem invoking the target + */ + Object invokeTarget(final Object payload, final ConversationSequence sequence) throws InvocationTargetException; + + /** + * Invokes an operation on a target with the given message + */ + Message invoke(Message msg); + + /** + * Determines whether the proxy can be cached on the client/source side + */ + boolean isCacheable(); + + /** + * Sets whether the target service instance may be cached by the invoker. This is a possible optimization when a + * wire is configured for a "down-scope" reference, i.e. a reference from a source of a shorter lifetime to a source + * of greater lifetime. + */ + void setCacheable(boolean cacheable); + + /** + * Implementations must support deep cloning + */ + Object clone() throws CloneNotSupportedException; +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/TargetInvokerInvoker.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/TargetInvokerInvoker.java new file mode 100644 index 0000000000..3842f0ba52 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/TargetInvokerInvoker.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.invocation; + +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.osoa.sca.ServiceRuntimeException; + + +/** + * Serves as a tail interceptor on a target wire chain. This implementation dispatches to the target invoker passed + * inside the wire message. Target invokers are passed from the source in order to allow for caching of target + * instances. + * + * @version $Rev$ $Date$ + * @Deprecated + * @see org.apache.tuscany.sca.implementation.java.invocation.TargetInvoker + */ +public class TargetInvokerInvoker implements Invoker { + private TargetInvoker invoker; + + public TargetInvokerInvoker(TargetInvoker invoker) { + this.invoker = invoker; + } + + public Message invoke(Message msg) { + if (invoker == null) { + throw new ServiceRuntimeException("No target invoker specified on message"); + } + return invoker.invoke(msg); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/module/JavaRuntimeModuleActivator.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/module/JavaRuntimeModuleActivator.java new file mode 100644 index 0000000000..626737ceb7 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/module/JavaRuntimeModuleActivator.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.module; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.core.invocation.JDKProxyService; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.impl.MediatorImpl; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.context.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.introspect.DefaultJavaClassIntrospectorExtensionPoint; +import org.apache.tuscany.sca.implementation.java.introspect.ExtensibleJavaClassIntrospector; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassIntrospector; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassIntrospectorExtensionPoint; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.AllowsPassByReferenceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.BaseJavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ConstructorProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ContextProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ConversationProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.DestroyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.EagerInitProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.HeuristicPojoProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.InitProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.PolicyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.PropertyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ReferenceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ResourceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ScopeProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ServiceProcessor; +import org.apache.tuscany.sca.implementation.java.invocation.JavaImplementationProviderFactory; +import org.apache.tuscany.sca.implementation.java.xml.JavaImplementationProcessor; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.introspect.ExtensibleJavaInterfaceIntrospector; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospector; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceIntrospectorExtensionPoint; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; + +/** + * @version $Rev$ $Date$ + */ +public class JavaRuntimeModuleActivator implements ModuleActivator { + + private JavaClassIntrospectorExtensionPoint classVisitors; + + public JavaRuntimeModuleActivator() { + } + + + public Object[] getExtensionPoints() { + classVisitors = new DefaultJavaClassIntrospectorExtensionPoint(); + return new Object[] { classVisitors }; + } + + public void start(ExtensionPointRegistry registry) { + + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = factories.getFactory(AssemblyFactory.class); + PolicyFactory policyFactory = factories.getFactory(PolicyFactory.class); + + JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory(); + + JDKProxyService proxyFactory = (JDKProxyService) registry.getExtensionPoint(ProxyFactory.class); + + JavaInterfaceIntrospectorExtensionPoint interfaceVisitors = registry.getExtensionPoint(JavaInterfaceIntrospectorExtensionPoint.class); + JavaInterfaceIntrospector interfaceIntrospector = new ExtensibleJavaInterfaceIntrospector(javaFactory, interfaceVisitors); + BaseJavaClassVisitor[] extensions = new BaseJavaClassVisitor[] { + new ConstructorProcessor(assemblyFactory), + new AllowsPassByReferenceProcessor(assemblyFactory), + new ContextProcessor(assemblyFactory), + new ConversationProcessor(assemblyFactory), + new DestroyProcessor(assemblyFactory), + new EagerInitProcessor(assemblyFactory), + new InitProcessor(assemblyFactory), + new PropertyProcessor(assemblyFactory), + new ReferenceProcessor(assemblyFactory, javaFactory, interfaceIntrospector), + new ResourceProcessor(assemblyFactory), + new ScopeProcessor(assemblyFactory), + new ServiceProcessor(assemblyFactory, javaFactory, interfaceIntrospector), + new HeuristicPojoProcessor(assemblyFactory, javaFactory, interfaceIntrospector), + new PolicyProcessor(assemblyFactory, policyFactory) + }; + for (JavaClassVisitor extension : extensions) { + classVisitors.addClassVisitor(extension); + } + JavaClassIntrospector classIntrospector = new ExtensibleJavaClassIntrospector(classVisitors); + + DataBindingExtensionPoint dataBindings = registry.getExtensionPoint(DataBindingExtensionPoint.class); + TransformerExtensionPoint transformers = registry.getExtensionPoint(TransformerExtensionPoint.class); + MediatorImpl mediator =new MediatorImpl(dataBindings, transformers); + JavaPropertyValueObjectFactory factory = new JavaPropertyValueObjectFactory(mediator); + + StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + JavaImplementationProcessor javaImplementationProcessor = + new JavaImplementationProcessor(assemblyFactory, policyFactory, javaImplementationFactory, classIntrospector); + processors.addArtifactProcessor(javaImplementationProcessor); + + JavaImplementationProviderFactory javaImplementationProviderFactory = + new JavaImplementationProviderFactory(proxyFactory, dataBindings, factory); + + ProviderFactoryExtensionPoint providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + providerFactories.addProviderFactory(javaImplementationProviderFactory); + } + + public void stop(ExtensionPointRegistry registry) { + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ExceptionFormatter.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ExceptionFormatter.java new file mode 100644 index 0000000000..dc34153389 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ExceptionFormatter.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.sca.implementation.java.monitor; + +import java.io.PrintWriter; + +/** + * Formats exception data during a monitor event + * + * @version $Rev$ $Date$ + */ +public interface ExceptionFormatter { + + boolean canFormat(Class<?> type); + + PrintWriter write(PrintWriter writer, Throwable exception); + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ExceptionFormatterImpl.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ExceptionFormatterImpl.java new file mode 100644 index 0000000000..3fa86109a0 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ExceptionFormatterImpl.java @@ -0,0 +1,43 @@ +/* + * 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.monitor; + +import java.io.PrintWriter; + +/** + * Performs basics formatting of exceptions for JDK logging + * + * @version $Rev$ $Date$ + */ +public class ExceptionFormatterImpl implements ExceptionFormatter { + + public ExceptionFormatterImpl() { + } + + public boolean canFormat(Class<?> type) { + return Throwable.class.isAssignableFrom(type); + } + + public PrintWriter write(PrintWriter writer, Throwable exception) { + writer.append(exception.getMessage()); + writer.append("\n"); + return writer; + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/FormatterRegistry.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/FormatterRegistry.java new file mode 100644 index 0000000000..91a8223385 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/FormatterRegistry.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.monitor; + +/** + * A registry for exception formatters + * + * @version $Rev$ $Date$ + */ +public interface FormatterRegistry { + + /** + * Registers the given formatter + * + * @param formatter the formatter to register + */ + void register(ExceptionFormatter formatter); + + /** + * De-registers the given formatter + * + * @param formatter the formatter to de-register + */ + void unregister(ExceptionFormatter formatter); + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/InvalidLevelException.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/InvalidLevelException.java new file mode 100644 index 0000000000..636451bc36 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/InvalidLevelException.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.monitor; + +/** + * Exception indicating an invalid log level has been passed. + * + * @version $Rev$ $Date$ + */ +public class InvalidLevelException extends IllegalArgumentException { + private static final long serialVersionUID = 7767234706427841915L; + private final String method; + private final String level; + + /** + * Constructor specifying the method name and the level affected. + * + * @param method the name of the method being monitored + * @param level the invalid log level value + */ + public InvalidLevelException(String method, String level) { + super(); + this.method = method; + this.level = level; + } + + /** + * Returns the name of the method being monitored. + * + * @return the name of the method being monitored + */ + public String getMethod() { + return method; + } + + /** + * Returns the invalid log level specified. + * + * @return the invalid log level that was specified + */ + public String getLevel() { + return level; + } + + public String getMessage() { + return "Invalid level for method " + method + " : " + level; + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/JavaLoggingMonitorFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/JavaLoggingMonitorFactory.java new file mode 100644 index 0000000000..fdfd43be95 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/JavaLoggingMonitorFactory.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.monitor; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import org.osoa.sca.annotations.Service; + + +/** + * A factory for monitors that forwards events to a {@link java.util.logging.Logger Java Logging (JSR47) Logger}. + * + * @version $Rev$ $Date$ + * @see java.util.logging + */ +@Service(interfaces = {MonitorFactory.class, FormatterRegistry.class}) +public class JavaLoggingMonitorFactory extends ProxyMonitorFactory { + + /** + * Construct a MonitorFactory that will monitor the specified methods at the specified levels and generate messages + * using java.util.logging. + * <p/> + * The supplied Properties can be used to specify custom log levels for specific monitor methods. The key should be + * the method name in form returned by <code>Class.getName() + '#' + Method.getName()</code> and the value the log + * level to use as defined by {@link java.util.logging.Level}. + * + * @param levels definition of custom levels for specific monitored methods, may be null or empty. + * @param defaultLevel the default log level to use + * @param bundleName the name of a resource bundle that will be passed to the logger + * @see java.util.logging.Logger + */ + public JavaLoggingMonitorFactory(Properties levels, Level defaultLevel, String bundleName) { + Map<String, Object> configProperties = new HashMap<String, Object>(); + configProperties.put("levels", levels); + configProperties.put("defaultLevel", defaultLevel); + configProperties.put("bundleName", bundleName); + initInternal(configProperties); + } + + /** + * Constructs a MonitorFactory that needs to be subsequently configured via a call to {@link #initialize}. + */ + public JavaLoggingMonitorFactory() { + } + + protected <T> InvocationHandler createInvocationHandler(Class<T> monitorInterface, + Map<String, Level> levels) { + ResourceBundle bundle = locateBundle(monitorInterface, bundleName); + Logger logger = Logger.getLogger(monitorInterface.getName()); + return new LoggingHandler(logger, levels, bundle); + } + + private class LoggingHandler implements InvocationHandler { + private final Logger logger; + private final Map<String, Level> methodLevels; + private final ResourceBundle bundle; + + public LoggingHandler(Logger logger, + Map<String, Level> methodLevels, + ResourceBundle bundle + ) { + this.logger = logger; + this.methodLevels = methodLevels; + this.bundle = bundle; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String sourceMethod = method.getName(); + Level level = methodLevels.get(sourceMethod); + if (level != null && logger.isLoggable(level)) { + // construct the key for the resource bundle + String className = logger.getName(); + String key = className + '#' + sourceMethod; + + LogRecord logRecord = new LogRecord(level, key); + logRecord.setLoggerName(className); + logRecord.setSourceClassName(className); + logRecord.setSourceMethodName(sourceMethod); + logRecord.setParameters(args); + if (args != null) { + for (Object o : args) { + if (o instanceof Throwable) { + logRecord.setMessage(formatException((Throwable) o)); + break; + } + } + } + logRecord.setResourceBundle(bundle); + logger.log(logRecord); + } + return null; + } + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/MonitorFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/MonitorFactory.java new file mode 100644 index 0000000000..9337e72dcb --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/MonitorFactory.java @@ -0,0 +1,51 @@ +/* + * 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.monitor; + +import java.util.Map; + + +/** + * A MonitorFactory creates implementations of components' monitor interfaces that interface with a its monitoring + * scheme. For example, a implementation may create versions that emit appropriate logging events or which send + * notifications to a management API. + * <p/> + * MonitorFactory implementations must provide a no-arg constructor and implement the {@link #initialize} method to + * perform configuration of instances created using that constructor. Additional constructors may be defined; typically + * their implementations delegate to {@link #initialize}. + * + * @version $Rev$ $Date$ + */ +public interface MonitorFactory extends FormatterRegistry { + /** + * Initializes MonitorFactory instances with implementation-specific configuration properties. + * + * @param configProperties a map of named configuration properties. May be null. + * @throws IllegalArgumentException if the instance can't be configured using the supplied properties + */ + void initialize(Map<String, Object> configProperties); + + /** + * Return a monitor for a component's monitor interface. + * + * @param monitorInterface the component's monitoring interface + * @return an implementation of the monitoring interface; will not be null + */ + <T> T getMonitor(Class<T> monitorInterface); +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/MonitorFactoryUtil.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/MonitorFactoryUtil.java new file mode 100644 index 0000000000..529ceee5ec --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/MonitorFactoryUtil.java @@ -0,0 +1,77 @@ +/* + * 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.monitor; + + +import java.util.Map; + +/** + * Helper for creating MonitorFactory instances. + * + * @version $$Rev$$ $$Date$$ + */ + +public final class MonitorFactoryUtil { + /** + * Hide the constructor + */ + private MonitorFactoryUtil() { + } + + /** + * Creates a MonitorFactory instance of the specified type. + * @param name fully qualified classname of the desired MonitorFactory type + * @param props collection of initialization properties + * @return a configured MonitorFactory instance, or null if the factory could not be instantiated. + */ + @SuppressWarnings("unchecked") + public static MonitorFactory createMonitorFactory(String name, Map<String, Object> props) { + Class<? extends MonitorFactory> clazz; + try { + clazz = (Class<? extends MonitorFactory>) Class.forName(name); + } catch (ClassNotFoundException cnfe) { + return null; + } catch (ClassCastException cce) { + return null; + } + + return createMonitorFactory(clazz, props); + } + + /** + * Creates a MonitorFactory instance of the specified type. + * @param mfc class of the desired MonitorFactory type + * @param props collection of initialization properties + * @return a configured MonitorFactory instance, or null if the factory could not be instantiated. + */ + public static MonitorFactory createMonitorFactory(Class<? extends MonitorFactory> mfc, Map<String, Object> props) { + MonitorFactory mf; + try { + mf = mfc.newInstance(); + mf.initialize(props); + } catch (InstantiationException e) { + throw new AssertionError(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + // allow IllegalArgumentException to propogate out + + return mf; + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/NullMonitorFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/NullMonitorFactory.java new file mode 100644 index 0000000000..efabb2ef9c --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/NullMonitorFactory.java @@ -0,0 +1,66 @@ +/* + * 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.monitor; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map; + +import org.osoa.sca.annotations.EagerInit; + + +/** + * Implementation of a {@link MonitorFactory} that produces implementations that simply return. + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class NullMonitorFactory implements MonitorFactory { + + /** + * Singleton hander that does nothing. + */ + private static final InvocationHandler NULL_MONITOR = new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) { + return null; + } + }; + + public void initialize(Map<String, Object> configProperties) { + } + + public <T> T getMonitor(Class<T> monitorInterface) { + /* + * This uses a reflection proxy to implement the monitor interface which + * is a simple but perhaps not very performant solution. Performance + * might be improved by code generating an implementation with empty methods. + */ + return monitorInterface.cast( + Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class<?>[]{monitorInterface}, NULL_MONITOR)); + } + + public void register(ExceptionFormatter formatter) { + + } + + public void unregister(ExceptionFormatter formatter) { + + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ProxyMonitorFactory.java b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ProxyMonitorFactory.java new file mode 100644 index 0000000000..b26ba6ca8b --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/monitor/ProxyMonitorFactory.java @@ -0,0 +1,231 @@ +/* + * 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.monitor; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.WeakHashMap; +import java.util.logging.Level; + +import org.apache.tuscany.api.annotation.LogLevel; + +/** + * @version $Rev$ $Date$ + */ +public abstract class ProxyMonitorFactory implements MonitorFactory, FormatterRegistry { + protected String bundleName; + protected final List<ExceptionFormatter> formatters = new ArrayList<ExceptionFormatter>(); + protected final ExceptionFormatter defaultFormatter = new ExceptionFormatterImpl(); + protected Level defaultLevel; + protected Map<String, Level> levels; + private final Map<Class<?>, WeakReference<?>> proxies = new WeakHashMap<Class<?>, WeakReference<?>>(); + + public void initialize(Map<String, Object> configProperties) { + if (configProperties == null) { + return; + } + initInternal(configProperties); + } + + protected void initInternal(Map<String, Object> configProperties) { + try { + this.defaultLevel = (Level) configProperties.get("defaultLevel"); + this.bundleName = (String) configProperties.get("bundleName"); + Properties levels = (Properties) configProperties.get("levels"); + + this.levels = new HashMap<String, Level>(); + if (levels != null) { + for (Map.Entry<Object, Object> entry : levels.entrySet()) { + String method = (String) entry.getKey(); + String level = (String) entry.getValue(); + try { + this.levels.put(method, Level.parse(level)); + } catch (IllegalArgumentException e) { + throw new InvalidLevelException(method, level); + } + } + } + } catch (ClassCastException cce) { + throw new IllegalArgumentException(cce.getLocalizedMessage()); + } + } + + public synchronized <T> T getMonitor(Class<T> monitorInterface) { + T proxy = getCachedMonitor(monitorInterface); + if (proxy == null) { + proxy = createMonitor(monitorInterface); + proxies.put(monitorInterface, new WeakReference<T>(proxy)); + } + return proxy; + } + + protected <T> T getCachedMonitor(Class<T> monitorInterface) { + WeakReference<?> ref = proxies.get(monitorInterface); + return (ref != null) ? monitorInterface.cast(ref.get()) : null; + } + + protected <T> T createMonitor(Class<T> monitorInterface) { + String className = monitorInterface.getName(); + Method[] methods = monitorInterface.getMethods(); + Map<String, Level> levels = new HashMap<String, Level>(methods.length); + for (Method method : methods) { + String key = className + '#' + method.getName(); + Level level = null; + if (this.levels != null) { + this.levels.get(key); + } + // if not specified the in config properties, look for an annotation on the method + if (level == null) { + LogLevel annotation = method.getAnnotation(LogLevel.class); + if (annotation != null && annotation.value() != null) { + try { + level = Level.parse(annotation.value()); + } catch (IllegalArgumentException e) { + // bad value, just use the default + level = defaultLevel; + } + } + } + if (level == null) { + level = defaultLevel; + } + levels.put(method.getName(), level); + } + + InvocationHandler handler = createInvocationHandler(monitorInterface, levels); + Object proxy = Proxy.newProxyInstance(monitorInterface.getClassLoader(), + new Class<?>[]{monitorInterface}, + handler); + return monitorInterface.cast(proxy); + } + + protected <T> ResourceBundle locateBundle(Class<T> monitorInterface, String bundleName) { + Locale locale = Locale.getDefault(); + ClassLoader cl = monitorInterface.getClassLoader(); + String packageName = monitorInterface.getPackage().getName(); + while (true) { + try { + return ResourceBundle.getBundle(packageName + '.' + bundleName, locale, cl); + } catch (MissingResourceException e) { + //ok + } + int index = packageName.lastIndexOf('.'); + if (index == -1) { + break; + } + packageName = packageName.substring(0, index); + } + try { + return ResourceBundle.getBundle(bundleName, locale, cl); + } catch (Exception e) { + return null; + } + } + + public void register(ExceptionFormatter formatter) { + formatters.add(formatter); + } + + public void unregister(ExceptionFormatter formatter) { + formatters.remove(formatter); + } + + protected abstract <T> InvocationHandler createInvocationHandler(Class<T> monitorInterface, + Map<String, Level> levels); + + protected String formatException(Throwable e) { + ExceptionFormatter formatter = defaultFormatter; + for (ExceptionFormatter candidate : formatters) { + if (candidate.canFormat(e.getClass())) { + formatter = candidate; + break; + } + } + StringWriter writer = new StringWriter(); + PrintWriter pw = new PrintWriter(writer); + formatter.write(pw, e); + format(pw, e); + pw.close(); + return writer.toString(); + } + + protected void format(PrintWriter writer, Throwable throwable) { + writer.println(throwable.getClass().getName()); + StackTraceElement[] trace = throwable.getStackTrace(); + for (StackTraceElement aTrace : trace) { + writer.println("\tat " + aTrace); + } + Throwable ourCause = throwable.getCause(); + + if (ourCause != null) { + printStackTraceAsCause(writer, ourCause, trace); + } + } + + protected void printStackTraceAsCause(PrintWriter pw, + Throwable throwable, + StackTraceElement[] causedTrace) { + + // Compute number of frames in common between this and caused + StackTraceElement[] trace = throwable.getStackTrace(); + int m = trace.length - 1; + int n = causedTrace.length - 1; + while (m >= 0 && n >= 0 && trace[m].equals(causedTrace[n])) { + m--; + n--; + } + int framesInCommon = trace.length - 1 - m; + + pw.println("Caused by: " + throwable.getClass().getName()); + + ExceptionFormatter formatter = defaultFormatter; + for (ExceptionFormatter candidate : formatters) { + if (candidate.canFormat(throwable.getClass())) { + formatter = candidate; + break; + } + } + formatter.write(pw, throwable); + + for (int i = 0; i <= m; i++) { + pw.println("\tat " + trace[i]); + } + if (framesInCommon != 0) { + pw.println("\t... " + framesInCommon + " more"); + } + + // Recurse if we have a cause + Throwable ourCause = throwable.getCause(); + if (ourCause != null) { + printStackTraceAsCause(pw, ourCause, trace); + } + } +} |