diff options
author | dims <dims@13f79535-47bb-0310-9956-ffa450edef68> | 2008-06-17 00:23:01 +0000 |
---|---|---|
committer | dims <dims@13f79535-47bb-0310-9956-ffa450edef68> | 2008-06-17 00:23:01 +0000 |
commit | bdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch) | |
tree | 38a92061c0793434c4be189f1d70c3458b6bc41d /tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany |
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany')
152 files changed, 12857 insertions, 0 deletions
diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/AddressingConstants.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/AddressingConstants.java new file mode 100644 index 0000000000..8154ad4709 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/AddressingConstants.java @@ -0,0 +1,33 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.addressing; + +/** + */ +public interface AddressingConstants { + + String NS_URI = "http://schemas.xmlsoap.org/ws/2004/08/addressing"; + String TO_HEADER_NAME = NS_URI + "#To"; + String FROM_HEADER_NAME = NS_URI + "#From"; + String MESSAGE_ID_HEADER_NAME = NS_URI + "#MessageID"; + String ACTION_HEADER_NAME = NS_URI + "#Action"; + String REPLY_TO_HEADER_NAME = NS_URI + "#ReplyTo"; + String RELATES_TO_HEADER_NAME = NS_URI + "#RelatesTo"; + String FAULT_TO_HEADER_NAME = NS_URI + "#FaultTo"; + String ENDPOINT_REFERENCE_HEADER_NAME = NS_URI + "#EndpointReference"; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/AddressingFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/AddressingFactory.java new file mode 100644 index 0000000000..878322bc6e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/AddressingFactory.java @@ -0,0 +1,37 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.addressing; + + +/** + * The <b>Factory</b> for the model. + */ +public interface AddressingFactory { + + /** + * Returns a new object of class '<em>Endpoint Reference</em>'. + */ + EndpointReference createEndpointReference(); + + /** + * Create a new message ID + * + * @return + */ + String createMessageID(); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/EndpointReference.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/EndpointReference.java new file mode 100644 index 0000000000..f8ecd34354 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/EndpointReference.java @@ -0,0 +1,120 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.addressing; + +import java.util.Map; + +import org.apache.tuscany.core.invocation.MessageHandler; +import org.apache.tuscany.model.assembly.ConfiguredPort; + +/** + * A representation of the model object '<em><b>Endpoint Reference</b></em>'. + */ +public interface EndpointReference extends org.osoa.sca.ServiceReference, MessageHandler { + + /** + * Returns the endpoint address. + * + * @return The address. + */ + String getAddress(); + + /** + * Sets the endpoint address. + * + * @param address The address. + */ + void setAddress(String address); + + /** + * Returns the QName of the WSDL portType associated with this endpoint reference. + * + * @return The QName of the portType. + */ + String getPortTypeName(); + + /** + * Sets the QName of the WSDL portType associated with this endpoint reference. + * + * @param qname The QName of the portType. + */ + void setPortTypeName(String qname); + + /** + * Returns the QName of the WSDL service associated with this endpoint reference. + * + * @return The QName of the service. + */ + String getServiceName(); + + /** + * Sets the QName of the WSDL service associated with this endpoint reference. + * + * @param qname The QName of the service. + */ + void setServiceName(String qname); + + /** + * Returns the name of the WSDL port associated with this endpoint reference. + * + * @return The name of the port. + */ + String getPortName(); + + /** + * Sets the name of the WSDL port associated with this endpoint reference. + * + * @param name The name of the port. + */ + void setPortName(String name); + + /** + * Returns the endpoint reference parameters.. + * + * @return The collection of reference parameters. + */ + Map<String, Object> getReferenceParameters(); + + /** + * Returns the configured port corresponding to this endpoint reference. + * + * @return + */ + ConfiguredPort getConfiguredPort(); + + /** + * Returns the configured port corresponding to this endpoint reference. + * + * @return + */ + void setConfiguredPort(ConfiguredPort configuredPort); + + /** + * Returns the message handler associated with this endpoint reference + * + * @return + */ + MessageHandler getMessageHandler(); + + /** + * Sets the message handler associated with this endpoint reference + * + * @param messageHandler + */ + void setMessageHandler(MessageHandler messageHandler); + +} // EndpointReference diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/impl/AddressingFactoryImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/impl/AddressingFactoryImpl.java new file mode 100644 index 0000000000..882e3157c2 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/impl/AddressingFactoryImpl.java @@ -0,0 +1,50 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.addressing.impl; + +import org.eclipse.emf.ecore.util.EcoreUtil; + +import org.apache.tuscany.core.addressing.AddressingFactory; +import org.apache.tuscany.core.addressing.EndpointReference; + +/** + * A factory for endpoint references. + * + */ +public class AddressingFactoryImpl implements AddressingFactory { + + /** + * Constructor + */ + public AddressingFactoryImpl() { + super(); + } + + /** + * @see org.apache.tuscany.core.addressing.AddressingFactory#createEndpointReference() + */ + public EndpointReference createEndpointReference() { + return new EndpointReferenceImpl(); + } + + /** + * @see org.apache.tuscany.core.addressing.AddressingFactory#createMessageID() + */ + public String createMessageID() { + return EcoreUtil.generateUUID(); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/impl/EndpointReferenceImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/impl/EndpointReferenceImpl.java new file mode 100644 index 0000000000..f4fbd2036b --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/addressing/impl/EndpointReferenceImpl.java @@ -0,0 +1,182 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.addressing.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.addressing.EndpointReference; +import org.apache.tuscany.core.invocation.MessageHandler; +import org.apache.tuscany.core.message.Message; +import org.apache.tuscany.model.assembly.ConfiguredPort; + +/** + * An implementation of EndpointReference. + */ +public class EndpointReferenceImpl implements EndpointReference { + + private ConfiguredPort configuredPort; + private MessageHandler messageHandler; + private String address; + private String portTypeName; + private String portName; + private String serviceName; + private Map<String, Object> referenceParameters; + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#getAddress() + */ + public String getAddress() { + return address; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#setAddress(java.lang.String) + */ + public void setAddress(String value) { + this.address=value; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#getPortTypeName() + */ + public String getPortTypeName() { + return portTypeName; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#setPortTypeName(java.lang.String) + */ + public void setPortTypeName(String value) { + this.portTypeName=value; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#getServiceName() + */ + public String getServiceName() { + return serviceName; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#getPortName() + */ + public String getPortName() { + return portName; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#setServiceName(java.lang.String) + */ + public void setServiceName(String value) { + this.serviceName=value; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#setPortName(java.lang.String) + */ + public void setPortName(String portName) { + this.portName=portName; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#getReferenceParameters() + */ + public Map<String, Object> getReferenceParameters() { + if (referenceParameters==null) + referenceParameters=new HashMap<String, Object>(); + return referenceParameters; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#getConfiguredPort() + */ + public ConfiguredPort getConfiguredPort() { + return configuredPort; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#setConfiguredPort(org.apache.tuscany.model.assembly.ConfiguredPort) + */ + public void setConfiguredPort(ConfiguredPort configuredPort) { + this.configuredPort = configuredPort; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#getMessageHandler() + */ + public MessageHandler getMessageHandler() { + return messageHandler; + } + + /** + * @see org.apache.tuscany.core.addressing.EndpointReference#setMessageHandler(org.apache.tuscany.core.invocation.MessageHandler) + */ + public void setMessageHandler(MessageHandler messageHandler) { + this.messageHandler = messageHandler; + } + + /** + * @see org.osoa.sca.ServiceReference#getSessionID() + */ + public Object getSessionID() { + throw new UnsupportedOperationException(); + } + + /** + * @see org.osoa.sca.ServiceReference#endSession() + */ + public void endSession() { + throw new UnsupportedOperationException(); + } + + /** + * @see org.osoa.sca.ServiceReference#getCallbackID() + */ + public Object getCallbackID() { + throw new UnsupportedOperationException(); + } + + /** + * @see org.osoa.sca.ServiceReference#setCallbackID(java.lang.Object) + */ + public void setCallbackID(Object callbackID) { + throw new UnsupportedOperationException(); + } + + /** + * @see org.osoa.sca.ServiceReference#getCallback() + */ + public Object getCallback() { + throw new UnsupportedOperationException(); + } + + /** + * @see org.osoa.sca.ServiceReference#setCallback(java.lang.Object) + */ + public void setCallback(Object callback) { + throw new UnsupportedOperationException(); + } + + /** + * @see org.apache.tuscany.core.invocation.MessageHandler#processMessage(org.apache.tuscany.core.message.Message) + */ + public boolean processMessage(Message message) { + return messageHandler.processMessage(message); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderConfigException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderConfigException.java new file mode 100644 index 0000000000..04b7b69cf5 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderConfigException.java @@ -0,0 +1,26 @@ +package org.apache.tuscany.core.builder; + +/** + * Represents an error processing a logical configuration model + * + * @version $Rev$ $Date$ + */ +public class BuilderConfigException extends BuilderException { + + public BuilderConfigException() { + super(); + } + + public BuilderConfigException(String message) { + super(message); + } + + public BuilderConfigException(String message, Throwable cause) { + super(message, cause); + } + + public BuilderConfigException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderException.java new file mode 100644 index 0000000000..246f188988 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderException.java @@ -0,0 +1,41 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.core.context.CoreRuntimeException; + +/** + * The root exception for the builder package. Builder exceptions denote a non-recoverable failure. + * + * @version $Rev$ $Date$ + */ +public abstract class BuilderException extends CoreRuntimeException { + + public BuilderException() { + super(); + } + + public BuilderException(String message) { + super(message); + } + + public BuilderException(String message, Throwable cause) { + super(message, cause); + } + + public BuilderException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderInitException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderInitException.java new file mode 100644 index 0000000000..cd57eaf7ab --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/BuilderInitException.java @@ -0,0 +1,39 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder; + +/** + * Denotes an exception initializing a builder + * + * @version $Rev$ $Date$ + */ +public class BuilderInitException extends BuilderException { + + public BuilderInitException() { + super(); + } + + public BuilderInitException(String message, Throwable cause) { + super(message, cause); + } + + public BuilderInitException(String message) { + super(message); + } + + public BuilderInitException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ConfigurationException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ConfigurationException.java new file mode 100644 index 0000000000..70a31c34c6 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ConfigurationException.java @@ -0,0 +1,26 @@ +package org.apache.tuscany.core.builder; + +/** + * Represents an error processing a logical configuration model + * + * @version $Rev$ $Date$ + */ +public class ConfigurationException extends BuilderException { + + public ConfigurationException() { + super(); + } + + public ConfigurationException(String message) { + super(message); + } + + public ConfigurationException(String message, Throwable cause) { + super(message, cause); + } + + public ConfigurationException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ContextCreationException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ContextCreationException.java new file mode 100644 index 0000000000..24b526371d --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ContextCreationException.java @@ -0,0 +1,41 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder; + + +/** + * Denotes an exception creating an instance context + * + * @version $Rev$ $Date$ + */ +public class ContextCreationException extends BuilderException { + + public ContextCreationException() { + super(); + } + + public ContextCreationException(String message) { + super(message); + } + + public ContextCreationException(String message, Throwable cause) { + super(message, cause); + } + + public ContextCreationException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/HierarchicalWireBuilder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/HierarchicalWireBuilder.java new file mode 100644 index 0000000000..ace34a1ad5 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/HierarchicalWireBuilder.java @@ -0,0 +1,29 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder; + +/** + * A wire builder that delegates to child wire builders + * + * @version $Rev$ $Date$ + */ +public interface HierarchicalWireBuilder extends WireBuilder{ + + /** + * Registers a child wire builder + */ + public void addWireBuilder(WireBuilder builder); + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/NoAccessorException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/NoAccessorException.java new file mode 100644 index 0000000000..34b6294638 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/NoAccessorException.java @@ -0,0 +1,39 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder; + +/** + * Denotes an attempt to access a non-existent field or method + * + * @version $Rev$ $Date$ + */ +public class NoAccessorException extends BuilderException { + + public NoAccessorException() { + super(); + } + + public NoAccessorException(String message) { + super(message); + } + + public NoAccessorException(String message, Throwable cause) { + super(message, cause); + } + + public NoAccessorException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ObjectFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ObjectFactory.java new file mode 100644 index 0000000000..7d27df4ebd --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/ObjectFactory.java @@ -0,0 +1,19 @@ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.core.injection.ObjectCreationException; + +/** + * Implementations create new instances of a particular type + * + * @version $Rev$ $Date$ + */ +public interface ObjectFactory<T> { + + /** + * Return a instance of the type that this factory creates. + * + * @return a instance from this factory + */ + T getInstance() throws ObjectCreationException; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/RuntimeConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/RuntimeConfiguration.java new file mode 100644 index 0000000000..79396e6052 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/RuntimeConfiguration.java @@ -0,0 +1,69 @@ +package org.apache.tuscany.core.builder; + +import java.util.Map; + +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implementations create instances of {@link org.apache.tuscany.core.context.Context} based on a compiled + * configuration, such as a logical assembly model. For example, implementations of + * {@link org.apache.tuscany.core.builder.RuntimeConfigurationBuilder} analyze an + * {@link org.apache.tuscany.model.assembly.AssemblyModelObject} to create implementations of + * <tt>RuntimeConfiguration</tt>. + * + * @version $Rev$ $Date$ + */ +public interface RuntimeConfiguration<T extends Context> { + + /** + * Creates an instance context based on the current runtime configuration + * + * @return a new instance context + * @throws ContextCreationException if an error occurs creating the context + */ + public T createInstanceContext() throws ContextCreationException; + + /** + * Returns the scope identifier associated with the type of contexts produced by the current configuration + */ + public Scope getScope(); + + /** + * Returns the name of the contexts produced by the current configuration + */ + public String getName(); + + public void prepare(); + + /** + * Adds a target-side proxy factory for the given service name to the configuration. Target-side proxy factories + * contain the invocation chains associated with the destination service of a wire and are responsible for + * generating proxies + */ + public void addTargetProxyFactory(String serviceName, ProxyFactory factory); + + /** + * Returns the target-side proxy factory associated with the given service name + */ + public ProxyFactory getTargetProxyFactory(String serviceName); + + /** + * Returns a collection of target-side proxy factories for the configuration keyed by service name + */ + public Map<String, ProxyFactory> getTargetProxyFactories(); + + /** + * Adds a source-side proxy factory for the given reference. Source-side proxy factories contain the invocation + * chains for a reference in the component implementation associated with the instance context created by this + * configuration. Source-side proxy factories also produce proxies that are injected on a reference in a component + * implementation. + */ + public void addSourceProxyFactory(String referenceName, ProxyFactory factory); + + public ProxyFactory getSourceProxyFactory(String referenceName); + + public Map<String, ProxyFactory> getSourceProxyFactories(); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/RuntimeConfigurationBuilder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/RuntimeConfigurationBuilder.java new file mode 100644 index 0000000000..d797253520 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/RuntimeConfigurationBuilder.java @@ -0,0 +1,24 @@ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.model.assembly.AssemblyModelObject; + +/** + * Implementations are responsible for generating a runtime configuration model from a logical configuration model. The + * logical configuration model (LCM) is decorated with the runtime configuration model (RCM). + * + * @version $Rev$ $Date$ + * @see RuntimeConfiguration + */ +public interface RuntimeConfigurationBuilder<Y extends Context> { + + /** + * Builds a runtime configuration for the supplied model object for registration under the supplied context. + * + * @param object the logical configuration model node + * @param context the context that will be the parent of the built context + * @throws BuilderException + */ + public void build(AssemblyModelObject object, Y context) throws BuilderException; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/UnknownTypeException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/UnknownTypeException.java new file mode 100644 index 0000000000..015b0ba342 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/UnknownTypeException.java @@ -0,0 +1,26 @@ +package org.apache.tuscany.core.builder; + +/** + * Denotes an unknown configuration parameter type + * + * @version $Rev$ $Date$ + */ +public class UnknownTypeException extends BuilderException { + + public UnknownTypeException() { + super(); + } + + public UnknownTypeException(String message) { + super(message); + } + + public UnknownTypeException(String message, Throwable cause) { + super(message, cause); + } + + public UnknownTypeException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/WireBuilder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/WireBuilder.java new file mode 100644 index 0000000000..6f0cf9ce14 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/WireBuilder.java @@ -0,0 +1,60 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; + +/** + * Responsible for finalizing target-side proxy factories and bridging + * {@link org.apache.tuscany.core.invocation.InvocationConfiguration}s held by source- and target-side proxy factories. + * <p> + * Wire builders may optimize the invocation chains based on certain characteristics of th wire, such as source and + * target scopes. + * + * @version $Rev$ $Date$ + */ +public interface WireBuilder { + + /** + * Connects invocation configurations of the source proxy factory to corresponding ones in the target proxy to + * factory + * + * @param sourceFactory the proxy factory used in constructing the source side of the invocation chain + * @param targetFactory the proxy factory used in constructing the target side of the invocation chain + * @param targetType the context type of the target. Used to determine if a paricular wire builder should construct + * the wire + * @param downScope true if the component containing the reference (source side) is of a lesser scope than the + * target service + * @param targetScopeContext the scope context responsible for managing intance contexts of the target component + * type + * @throws BuilderConfigException if an error occurs during the wire build process + */ + public void connect(ProxyFactory sourceFactory, ProxyFactory targetFactory, Class targetType, boolean downScope, + ScopeContext targetScopeContext) throws BuilderConfigException; + + /** + * Finishes processing the target side invocation chain. For example, a + * {@link org.apache.tuscany.core.invocation.TargetInvoker} used by target-side proxies is usually set during this + * phase. + * + * @param targetFactory the target-side proxy factory + * @param targetType the target context type + * @param targetScopeContext the target scope + * @throws BuilderConfigException if an error occurs during the wire build process + */ + public void completeTargetChain(ProxyFactory targetFactory, Class targetType, ScopeContext targetScopeContext) + throws BuilderConfigException; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/AssemblyVisitor.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/AssemblyVisitor.java new file mode 100644 index 0000000000..20e9143537 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/AssemblyVisitor.java @@ -0,0 +1,62 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder.impl; + +import java.util.List; + +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.model.assembly.AssemblyModelObject; +import org.apache.tuscany.model.assembly.AssemblyModelVisitor; + +/** + * Decorates an assembly object graph with runtime configurations using a set of builders + * + * @version $Rev$ $Date$ + */ +public class AssemblyVisitor implements AssemblyModelVisitor { + + private AggregateContext parent; + + List<RuntimeConfigurationBuilder> builders; + + /** + * Constructs a visitor + * + * @param parent the parent context for the object graph + * @param builders the collection of builders for creating runtime configurations + */ + public AssemblyVisitor(AggregateContext parent, List<RuntimeConfigurationBuilder> builders) { + this.parent = parent; + this.builders = builders; + } + + /** + * Initiate walking the object graph + */ + public boolean start(AssemblyModelObject modelObject) { + return modelObject.accept(this); + } + + /** + * Callback when walking the graph + */ + public boolean visit(AssemblyModelObject modelObject) { + for (RuntimeConfigurationBuilder builder : builders) { + builder.build(modelObject, parent); + } + return true; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/BaseExternalServiceRuntimeConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/BaseExternalServiceRuntimeConfiguration.java new file mode 100644 index 0000000000..ce092a7d34 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/BaseExternalServiceRuntimeConfiguration.java @@ -0,0 +1,106 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.builder.ContextCreationException; +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.ExternalServiceContext; +import org.apache.tuscany.core.context.impl.ExternalServiceContextImpl; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.model.assembly.Scope; + +/** + * A template implementation that creates instances of {@link org.apache.tuscany.core.context.ExternalServiceContext} + * configured with the appropriate invocation chains and bindings. This class is intended to be subclassed when + * contributing new bindings to the runtime. The subclass serves as a marker so the binding {@link WireBuilder} + * responsible for setting the proper {@link org.apache.tuscany.core.invocation.TargetInvoker} on the invocation chains + * can be notified. + * + * @version $Rev$ $Date$ + */ +public abstract class BaseExternalServiceRuntimeConfiguration implements RuntimeConfiguration<ExternalServiceContext> { + + private String name; + + private ProxyFactory proxyFactory; + + private ObjectFactory objectFactory; + + private String targetServiceName; + + private Map<String,ProxyFactory> targetProxyFactories; + + public BaseExternalServiceRuntimeConfiguration(String name, ObjectFactory objectFactory) { + assert (name != null) : "Name was null"; + assert (objectFactory != null) : "Object factory was null"; + this.name = name; + this.objectFactory = objectFactory; + } + + public ExternalServiceContext createInstanceContext() throws ContextCreationException { + return new ExternalServiceContextImpl(name, proxyFactory, objectFactory); + } + + public Scope getScope() { + return Scope.MODULE; + } + + public String getName() { + return name; + } + + public void prepare() { + } + + public void addTargetProxyFactory(String serviceName, ProxyFactory factory) { + assert (serviceName != null) : "No service name specified"; + assert (factory != null) : "Proxy factory was null"; + this.targetServiceName = serviceName; // external services are configured with only one service + this.proxyFactory = factory; + } + + public ProxyFactory getTargetProxyFactory(String serviceName) { + if (this.targetServiceName.equals(serviceName)) { + return proxyFactory; + } else { + return null; + } + } + + public Map<String,ProxyFactory> getTargetProxyFactories() { + if (targetProxyFactories == null) { + targetProxyFactories = new HashMap(1); + targetProxyFactories.put(targetServiceName, proxyFactory); + } + return targetProxyFactories; + } + + public void addSourceProxyFactory(String referenceName, ProxyFactory factory) { + // no wires inside an aggregate from an external service + } + + public ProxyFactory getSourceProxyFactory(String referenceName) { + return null; + } + + public Map getSourceProxyFactories() { + return Collections.EMPTY_MAP; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/DefaultWireBuilder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/DefaultWireBuilder.java new file mode 100644 index 0000000000..6ed5472a64 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/DefaultWireBuilder.java @@ -0,0 +1,110 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder.impl; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.builder.HierarchicalWireBuilder; +import org.apache.tuscany.core.builder.WireBuilder; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.invocation.InvocationConfiguration; +import org.apache.tuscany.core.invocation.impl.InvokerInterceptor; +import org.apache.tuscany.core.invocation.impl.MessageChannelImpl; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; + +/** + * The top-most wire builder configured in a runtime. Responsible for constructing wires from source and target chains, + * this implementation first bridges the chains and then delegates to any other wire builders. + * + * @version $Rev$ $Date$ + */ +public class DefaultWireBuilder implements HierarchicalWireBuilder { + + // collection configured wire builders + private List<WireBuilder> builders = new ArrayList(); + + public DefaultWireBuilder() { + } + + /** + * Adds a wire builder to delegate to + */ + public void addWireBuilder(WireBuilder builder) { + builders.add(builder); + } + + public void setWireBuilders(List<WireBuilder> builders) { + builders.addAll(builders); + } + + public void connect(ProxyFactory sourceFactory, ProxyFactory targetFactory, Class targetType, boolean downScope, + ScopeContext targetScopeContext) { + QualifiedName targetName = sourceFactory.getProxyConfiguration().getTargetName(); + // get the proxy chain for the target + if (targetFactory != null) { + // if null, the target side has no interceptors or handlers + Map<Method, InvocationConfiguration> targetInvocationConfigs = targetFactory.getProxyConfiguration() + .getInvocationConfigurations(); + for (InvocationConfiguration sourceInvocationConfig : sourceFactory.getProxyConfiguration() + .getInvocationConfigurations().values()) { + // match invocation chains + InvocationConfiguration targetInvocationConfig = targetInvocationConfigs.get(sourceInvocationConfig.getMethod()); + // if handler is configured, add that + if (targetInvocationConfig.getRequestHandlers() != null) { + sourceInvocationConfig.setTargetRequestChannel(new MessageChannelImpl(targetInvocationConfig + .getRequestHandlers())); + sourceInvocationConfig.setTargetResponseChannel(new MessageChannelImpl(targetInvocationConfig + .getResponseHandlers())); + } else { + // no handlers, just connect interceptors + if (targetInvocationConfig.getTargetInterceptor() == null) { + BuilderConfigException e = new BuilderConfigException("No target handler or interceptor for operation"); + e.setIdentifier(targetInvocationConfig.getMethod().getName()); + throw e; + } + if (!(sourceInvocationConfig.getLastTargetInterceptor() instanceof InvokerInterceptor && targetInvocationConfig + .getTargetInterceptor() instanceof InvokerInterceptor)) { + // check that we do not have the case where the only interceptors are invokers since we just need one + sourceInvocationConfig.addTargetInterceptor(targetInvocationConfig.getTargetInterceptor()); + } + } + } + } + // delegate to other wire builders + for (WireBuilder builder : builders) { + builder.connect(sourceFactory, targetFactory, targetType, downScope, targetScopeContext); + } + // signal that wire build process is complete + boolean optimizable = true; + for (InvocationConfiguration sourceInvocationConfig : sourceFactory.getProxyConfiguration().getInvocationConfigurations() + .values()) { + sourceInvocationConfig.build(); + // TODO optimize if no proxy needed using NullProxyFactory + } + } + + public void completeTargetChain(ProxyFactory targetFactory, Class targetType, ScopeContext targetScopeContext) + throws BuilderConfigException { + // delegate to other wire builders + for (WireBuilder builder : builders) { + builder.completeTargetChain(targetFactory, targetType, targetScopeContext); + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/EntryPointRuntimeConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/EntryPointRuntimeConfiguration.java new file mode 100644 index 0000000000..108cc2d366 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/EntryPointRuntimeConfiguration.java @@ -0,0 +1,104 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.builder.ContextCreationException; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.EntryPointContext; +import org.apache.tuscany.core.context.impl.EntryPointContextImpl; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.message.MessageFactory; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Produces entry point contexts + * + * @version $Rev$ $Date$ + */ +public abstract class EntryPointRuntimeConfiguration implements RuntimeConfiguration<EntryPointContext> { + + private String name; + + private ProxyFactory proxyFactory; + + private String referenceName; + + private MessageFactory msgFactory; + + private Map<String, ProxyFactory> sourceProxyFactories; + + public EntryPointRuntimeConfiguration(String name, String referenceName, MessageFactory msgFactory) { + assert (name != null) : "Entry point name was null"; + assert (msgFactory != null) : "Message factory was null"; + this.name = name; + this.referenceName = referenceName; + this.msgFactory = msgFactory; + } + + public EntryPointContext createInstanceContext() throws ContextCreationException { + return new EntryPointContextImpl(name, proxyFactory, msgFactory); + } + + public Scope getScope() { + return Scope.MODULE; + } + + public String getName() { + return name; + } + + public void prepare() { + } + + public void addTargetProxyFactory(String serviceName, ProxyFactory factory) { + // no wires to an entry point from with an aggregate + } + + public ProxyFactory getTargetProxyFactory(String serviceName) { + // no wires to an entry point from with an aggregate + return null; + } + + public Map<String, ProxyFactory> getTargetProxyFactories() { + // no wires to an entry point from with an aggregate + return Collections.EMPTY_MAP; + } + + public void addSourceProxyFactory(String refName, ProxyFactory factory) { + assert (refName != null) : "No reference name specified"; + assert (factory != null) : "Proxy factory was null"; + this.referenceName = refName; // entry points are configured with only one reference + this.proxyFactory = factory; + } + + public ProxyFactory getSourceProxyFactory(String refName) { + if (this.referenceName.equals(refName)) { + return proxyFactory; + } else { + return null; + } + } + + public Map<String, ProxyFactory> getSourceProxyFactories() { + if (sourceProxyFactories == null) { + sourceProxyFactories = new HashMap(1); + sourceProxyFactories.put(referenceName, proxyFactory); + } + return sourceProxyFactories; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/HierarchicalBuilder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/HierarchicalBuilder.java new file mode 100644 index 0000000000..41f56c1bf0 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/HierarchicalBuilder.java @@ -0,0 +1,58 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder.impl; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.tuscany.core.builder.BuilderException; +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.model.assembly.AssemblyModelObject; + +/** + * A builder that contains nested builders. Used for synchronizing parts of the build process, such as references. + * + * @version $Rev$ $Date$ + */ +public class HierarchicalBuilder implements RuntimeConfigurationBuilder { + private List<RuntimeConfigurationBuilder> builders = new CopyOnWriteArrayList(); + + private List<RuntimeConfigurationBuilder> readOnlyBuilders = Collections.unmodifiableList(builders); + + public HierarchicalBuilder() { + } + + public void addBuilder(RuntimeConfigurationBuilder builder) { + builders.add(builder); + } + + public void removeBuilder(RuntimeConfigurationBuilder builder){ + builders.remove(builder); + } + + public List getBuilders(){ + return readOnlyBuilders; + } + + public void build(AssemblyModelObject object, Context context) throws BuilderException { + for (RuntimeConfigurationBuilder builder : builders) { + builder.build(object, context); + } + + } + + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/ProxyObjectFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/ProxyObjectFactory.java new file mode 100644 index 0000000000..c5d3b56034 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/builder/impl/ProxyObjectFactory.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.builder.impl; + +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.injection.ObjectCreationException; +import org.apache.tuscany.core.invocation.spi.ProxyCreationException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; + +/** + * Uses a proxy factory to return an object instance + * + * @version $Rev$ $Date$ + */ +public class ProxyObjectFactory implements ObjectFactory { + + private ProxyFactory factory; + + public ProxyObjectFactory(ProxyFactory factory) { + this.factory = factory; + } + + public Object getInstance() throws ObjectCreationException { + try { + return factory.createProxy(); + } catch (ProxyCreationException e) { + throw new ObjectCreationException(e); + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/client/TuscanyRuntime.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/client/TuscanyRuntime.java new file mode 100644 index 0000000000..629f3ac0c2 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/client/TuscanyRuntime.java @@ -0,0 +1,204 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.client; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.common.monitor.impl.NullMonitorFactory; +import org.apache.tuscany.common.resource.ResourceLoader; +import org.apache.tuscany.common.resource.impl.ResourceLoaderImpl; +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.builder.impl.DefaultWireBuilder; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.config.ModuleComponentConfigurationLoader; +import org.apache.tuscany.core.config.impl.ModuleComponentConfigurationLoaderImpl; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.runtime.RuntimeContext; +import org.apache.tuscany.core.runtime.RuntimeContextImpl; +import org.apache.tuscany.core.system.builder.SystemComponentContextBuilder; +import org.apache.tuscany.core.system.builder.SystemEntryPointBuilder; +import org.apache.tuscany.core.system.builder.SystemExternalServiceBuilder; +import org.apache.tuscany.core.system.loader.SystemSCDLModelLoader; +import org.apache.tuscany.model.assembly.AssemblyFactory; +import org.apache.tuscany.model.assembly.AssemblyModelContext; +import org.apache.tuscany.model.assembly.ModuleComponent; +import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl; +import org.apache.tuscany.model.assembly.impl.AssemblyModelContextImpl; +import org.apache.tuscany.model.assembly.loader.AssemblyModelLoader; +import org.apache.tuscany.model.scdl.loader.SCDLModelLoader; +import org.apache.tuscany.model.scdl.loader.impl.SCDLAssemblyModelLoaderImpl; +import org.osoa.sca.ModuleContext; +import org.osoa.sca.SCA; +import org.osoa.sca.ServiceRuntimeException; + +/** + * Create and initialize a Tuscany SCA runtime environment. + * + * @version $Rev$ $Date$ + */ +public class TuscanyRuntime extends SCA { + private final Monitor monitor; + private final Object sessionKey = new Object(); + + private final RuntimeContext runtimeContext; + private AggregateContext systemModuleComponentContext; + private AggregateContext moduleContext; + + private final static String SYSTEM_MODULE_COMPONENT = "org.apache.tuscany.core.system"; + + /** + * Construct a runtime using a null MonitorFactory. + * + * @param name the name of the module component + * @param uri the URI to assign to the module component + * @throws ConfigurationException if there was a problem loading the SCA configuration + * @see TuscanyRuntime#TuscanyRuntime(String, String, org.apache.tuscany.common.monitor.MonitorFactory) + */ + public TuscanyRuntime(String name, String uri) throws ConfigurationException { + this(name, uri, new NullMonitorFactory()); + } + + /** + * Construct a runtime containing a single module component with the + * specified name. The module definition is loaded from a "/sca.module" + * resource found on the classpath of the current Thread context classloader. + * + * @param name the name of the module component + * @param uri the URI to assign to the module component + * @param monitorFactory the MonitorFactory for this runtime + * @throws ConfigurationException if there was a problem loading the SCA configuration + */ + public TuscanyRuntime(String name, String uri, MonitorFactory monitorFactory) throws ConfigurationException { + this.monitor = monitorFactory.getMonitor(Monitor.class); + + // Create a resource loader from the current classloader + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + ResourceLoader resourceLoader = new ResourceLoaderImpl(classLoader); + + // Create an assembly model factory + AssemblyFactory modelFactory=new AssemblyFactoryImpl(); + + // Create an assembly model loader + List<SCDLModelLoader> scdlLoaders=new ArrayList<SCDLModelLoader>(); + scdlLoaders.add(new SystemSCDLModelLoader()); + AssemblyModelLoader modelLoader=new SCDLAssemblyModelLoaderImpl(scdlLoaders); + + // Create an assembly model context + AssemblyModelContext modelContext = new AssemblyModelContextImpl(modelFactory, modelLoader, resourceLoader); + + // Create system configuration builders + List<RuntimeConfigurationBuilder> configBuilders = new ArrayList(); + configBuilders.add((new SystemComponentContextBuilder())); + configBuilders.add(new SystemEntryPointBuilder()); + configBuilders.add(new SystemExternalServiceBuilder()); + + // Create a runtime context and start it + runtimeContext = new RuntimeContextImpl(monitorFactory, scdlLoaders, configBuilders,new DefaultWireBuilder()); + runtimeContext.start(); + monitor.started(runtimeContext); + + // Get the system context + AggregateContext systemContext = runtimeContext.getSystemContext(); + + // Load the system module component + ModuleComponentConfigurationLoader loader = new ModuleComponentConfigurationLoaderImpl(modelContext); + ModuleComponent systemModuleComponent = loader.loadSystemModuleComponent(SYSTEM_MODULE_COMPONENT, SYSTEM_MODULE_COMPONENT); + + // Register it with the system context + systemContext.registerModelObject(systemModuleComponent); + + // Get the aggregate context representing the system module component + systemModuleComponentContext = (AggregateContext) systemContext.getContext(SYSTEM_MODULE_COMPONENT); + systemModuleComponentContext.registerModelObject(systemModuleComponent.getComponentImplementation()); + systemModuleComponentContext.fireEvent(EventContext.MODULE_START, null); + + // Load the SCDL configuration of the application module + ModuleComponent moduleComponent = loader.loadModuleComponent(name, uri); + + // Register it under the root application context + runtimeContext.getRootContext().registerModelObject(moduleComponent); + moduleContext=(AggregateContext)runtimeContext.getContext(moduleComponent.getName()); + moduleContext.registerModelObject(moduleComponent.getComponentImplementation()); + + } + + /** + * Start the runtime and associate the module context with the calling thread. + */ + @Override + public void start() { + setModuleContext((ModuleContext)moduleContext); + try { + //moduleContext.start(); + moduleContext.fireEvent(EventContext.MODULE_START, null); + moduleContext.fireEvent(EventContext.REQUEST_START, null); + moduleContext.fireEvent(EventContext.SESSION_NOTIFY, sessionKey); + monitor.started(moduleContext); + } catch (CoreRuntimeException e) { + setModuleContext(null); + monitor.startFailed(moduleContext, e); + //FIXME throw a better exception + throw new ServiceRuntimeException(e); + } + } + + /** + * Disassociate the module context from the current thread and shut down the runtime. + */ + @Override + public void stop() { + setModuleContext(null); + moduleContext.fireEvent(EventContext.REQUEST_END, null); + moduleContext.fireEvent(EventContext.SESSION_END, sessionKey); + moduleContext.fireEvent(EventContext.MODULE_STOP, null); + moduleContext.stop(); + monitor.stopped(moduleContext); + runtimeContext.stop(); + monitor.stopped(runtimeContext); + } + + /** + * Monitor interface for a TuscanyRuntime. + */ + public static interface Monitor { + /** + * Event emitted after the runtime has been started. + * + * @param ctx the runtime's module component context + */ + void started(AggregateContext ctx); + + /** + * Event emitted when an attempt to start the runtime failed. + * + * @param ctx the runtime's module component context + * @param e the exception that caused the failure + */ + void startFailed(AggregateContext ctx, CoreRuntimeException e); + + /** + * Event emitted after the runtime has been stopped. + * + * @param ctx the runtime's module component context + */ + void stopped(AggregateContext ctx); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ComponentTypeIntrospector.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ComponentTypeIntrospector.java new file mode 100644 index 0000000000..c80a8f31ba --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ComponentTypeIntrospector.java @@ -0,0 +1,37 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config; + +import org.apache.tuscany.model.assembly.ComponentType; + +/** + * Interface for implementations that are able create SCA definitions + * by inspecting Java classes. + * + * @version $Rev$ $Date$ + */ +public interface ComponentTypeIntrospector { + /** + * Create a componentType definition by introspecting a Java Class. + * + * @param implClass the class to inspect + * @return a componentType definition + * @throws ConfigurationException if the Class does not define a valid component type + */ + ComponentType introspect(Class<?> implClass) throws ConfigurationException; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ConfigurationException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ConfigurationException.java new file mode 100644 index 0000000000..96365311f2 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ConfigurationException.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config; + +import org.apache.tuscany.common.TuscanyException; + + +/** + * Base class for exceptions that pertain to configuration. + * + * @version $Rev$ $Date$ + */ +public class ConfigurationException extends TuscanyException { + public ConfigurationException() { + } + + public ConfigurationException(String message) { + super(message); + } + + public ConfigurationException(String message, Throwable cause) { + super(message, cause); + } + + public ConfigurationException(Throwable cause) { + super(cause); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ConfigurationLoadException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ConfigurationLoadException.java new file mode 100644 index 0000000000..3055dc2fd2 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ConfigurationLoadException.java @@ -0,0 +1,47 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config; + +import java.io.IOException; + +/** + * Exception indicating that there was a problem loading a configuration resource. + * + * @version $Rev$ $Date$ + */ +public class ConfigurationLoadException extends ConfigurationException { + + /** + * Constructor specifying the resource that was being loaded and the IOException that resulted. + * These are returned as the message and cause respectively. + * + * @param resource the resource being loaded + * @param cause the IOException that occurred + */ + public ConfigurationLoadException(String resource, IOException cause) { + super(resource, cause); + } + + /** + * Constructor specifying the resource that was being loaded. + * + * @param resource the resource being loaded + */ + public ConfigurationLoadException(String resource) { + super(resource); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ImplementationCache.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ImplementationCache.java new file mode 100644 index 0000000000..595f499797 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ImplementationCache.java @@ -0,0 +1,46 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.model.assembly.ComponentImplementation; + +/** + * Cache of introspected implementations. + * + * @version $Rev$ $Date$ + */ +public interface ImplementationCache { + /** + * Return an implementation from a given namespace. + * + * @param type the namespace that defines the type of implementation + * @param name the name of an implementation in that namespace + * @return the implementation or null if it is not present in the cache + */ + ComponentImplementation get(QName type, String name); + + /** + * Add an implementation to the cache + * + * @param type the namespace that defines the type of implementation + * @param name the name of an implementation in that namespace + * @param implementation the introspected implementation + */ + void put(QName type, String name, ComponentImplementation implementation); +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/InvalidRootElementException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/InvalidRootElementException.java new file mode 100644 index 0000000000..19df4784cd --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/InvalidRootElementException.java @@ -0,0 +1,51 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config; + +/** + * Configuration exception that indicates the root element in an XML file was not the one expected. + * + * @version $Rev$ $Date$ + */ +public class InvalidRootElementException extends ConfigurationException { + private final String resource; + private final String element; + + /** + * Constructor specifying the location of the resource and the element that was expected. + * + * @param resource the resource + * @param element the expected root element + */ + public InvalidRootElementException(String resource, String element) { + super(); + this.resource = resource; + this.element = element; + } + + public String getMessage() { + return "XML document element in resource " + resource + " is not a " + element; + } + + public String getResource() { + return resource; + } + + public String getElement() { + return element; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/JavaIntrospectionHelper.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/JavaIntrospectionHelper.java new file mode 100644 index 0000000000..c10ff82310 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/JavaIntrospectionHelper.java @@ -0,0 +1,349 @@ +package org.apache.tuscany.core.config; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Implements various reflection-related operations + * + * @version $Rev$ $Date$ + */ +public class JavaIntrospectionHelper { + + private static final Class[] EMPTY_CLASS_ARRY = new Class[0]; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + /** + * Hide the constructor + */ + private JavaIntrospectionHelper() { + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + /** + * Returns a collection of public, private, protected, or default fields declared by a class or one of its + * supertypes + */ + public static Set<Field> getAllFields(Class pClass) { + return getAllFields(pClass, new HashSet<Field>()); + } + + /** + * Recursively evaluates the type hierachy to return all fields on a given type + * + * @spec This raises an interesting issue - do we allow injection on private supertype fields in a subtype even if + * they are annotated? + */ + private static Set<Field> getAllFields(Class pClass, Set<Field> fields) { + if (pClass == null || pClass.isArray() || Object.class.equals(pClass)) { + return fields; + } + fields = getAllFields(pClass.getSuperclass(), fields); + Field[] declaredFields = pClass.getDeclaredFields(); + for (int i = 0; i < declaredFields.length; i++) { + declaredFields[i].setAccessible(true); // ignore Java accessibility + fields.add(declaredFields[i]); + } + return fields; + } + + /** + * Returns a collection of public, private, protected, or default methods declared by a class or one of its + * supertypes. Note that overriden methods will not be returned in the collection (i.e. only the method override + * will be). <p/> This method can potentially be expensive as reflection information is not cached. It is assumed + * that this method will be used during a configuration phase. + */ + public static Set<Method> getAllUniqueMethods(Class pClass) { + return getAllUniqueMethods(pClass, new HashSet<Method>()); + } + + /** + * Recursively evaluates the type hierarchy to return all unique methods + */ + private static Set<Method> getAllUniqueMethods(Class pClass, Set<Method> methods) { + if (pClass == null || pClass.isArray() || Object.class.equals(pClass)) { + return methods; + } + // we first evaluate methods of the subclass and then move to the parent + Method[] declaredMethods = pClass.getDeclaredMethods(); + for (int i = 0; i < declaredMethods.length; i++) { + if (methods.size() == 0) { + methods.add(declaredMethods[i]); + } else { + List temp = new ArrayList(); + boolean matched = false; + for (Method method : methods) { + // only add if not already in the set from a supclass (i.e. the + // method is not overrided) + if (exactMethodMatch(declaredMethods[i], method)) { + matched = true; + break; + } + } + if (!matched) { + // TODO ignore Java accessibility + declaredMethods[i].setAccessible(true); + temp.add(declaredMethods[i]); + + } + methods.addAll(temp); + temp.clear(); + } + } + // evaluate class hierarchy - this is done last to track inherited methods + methods = getAllUniqueMethods(pClass.getSuperclass(), methods); + return methods; + } + + /** + * Finds the closest matching field with the given name, that is, a field of the exact specified type or, + * alternately, of a supertype. + * + * @param name the name of the field + * @param type the field type + * @param fields the collection of fields to search + * @return the matching field or null if not found + * @throws NoSuchFieldException if no field found + */ + public static Field findClosestMatchingField(String name, Class type, Set<Field> fields) { + Field candidate = null; + for (Field field : fields) { + if (field.getName().equals(name)) { + if (field.getType().equals(type)) { + return field; // exact match + } else if (field.getType().isAssignableFrom(type) + || (field.getType().isPrimitive() && primitiveAssignable(field.getType(), type))) { + // We could have the situation where a field parameter is a primitive and the demarshalled value is + // an object counterpart (e.g. Integer and int) + // @spec issue + // either an interface or super class, so keep a reference until + // we know there are no closer types + candidate = field; + } + } + } + if (candidate != null) { + return candidate; + } else { + return null; + } + } + + /** + * Finds the closest matching method with the given name, that is, a method taking the exact parameter types or, + * alternately, parameter supertypes. + * + * @param name the name of the method + * @param types the method parameter types + * @param methods the collection of methods to search + * @return the matching method or null if not found + * @throws NoSuchFieldException if no field found + */ + public static Method findClosestMatchingMethod(String name, Class[] types, Set<Method> methods) { + if (types == null) { + types = EMPTY_CLASS_ARRY; + } + Method candidate = null; + for (Method method : methods) { + if (method.getName().equals(name) && method.getParameterTypes().length == types.length) { + Class[] params = method.getParameterTypes(); + boolean disqualify = false; + boolean exactMatch = true; + for (int i = 0; i < params.length; i++) { + if (!params[i].equals(types[i]) && !params[i].isAssignableFrom(types[i])) { + // no match + disqualify = true; + exactMatch = false; + break; + } else if (!params[i].equals(types[i]) && params[i].isAssignableFrom(types[i])) { + // not exact match + exactMatch = false; + } + } + if (disqualify) { + continue; + } else if (exactMatch) { + return method; + } else { + candidate = method; + } + } + } + if (candidate != null) { + return candidate; + } else { + return null; + } + } + + /** + * Returns a field or method defined in the given class or its superclasses matching a literal name and parameter + * types <p/> This method can potentially be expensive as reflection information is not cached. It is assumed that + * this method will be used during a configuration phase. + * + * @param clazz the class to introspect + * @param propertName the literal name of the property (i.e. JavaBean conventions are not applied) + * @param paramTypes the parameter types for a method or null for fields or methods with no parameters + * @return the field, method or null + */ + public static AccessibleObject getBeanProperty(Class clazz, String propertName, Class[] paramTypes) { + + Set<Method> methods = getAllUniqueMethods(clazz); + for (Method method : methods) { + if (method.getName().equals(propertName)) { + Class[] types = method.getParameterTypes(); + if (types.length == 0 && paramTypes == null) { + return method; + } else if (types.length != 0 && paramTypes == null) { + break; + } else if (types.length == paramTypes.length) { + for (int n = 0; n < types.length - 1; n++) { + if (!types[n].equals(paramTypes[n]) || !types[n].isAssignableFrom(paramTypes[n])) { + break; + } + } + return method; + } + } + } + + Set<Field> fields = getAllFields(clazz); + for (Field field : fields) { + if (field.getName().equals(propertName)) { + return field; + } + } + return null; + } + + /** + * Determines if two methods "match" - that is, they have the same method names and exact parameter types (one is + * not a supertype of the other) + */ + public static boolean exactMethodMatch(Method method1, Method method2) { + if (!method1.getName().equals(method2.getName())) { + return false; + } + Class[] types1 = method1.getParameterTypes(); + Class[] types2 = method2.getParameterTypes(); + if (types1.length == 0 && types2.length == 0) { + return true; + } else if (types1.length == types2.length) { + for (int n = 0; n < types1.length; n++) { + if (!types1[n].equals(types2[n])) { + return false; + } + } + return true; + } + return false; + } + + public static Constructor getDefaultConstructor(Class clazz) throws NoSuchMethodException { + return clazz.getConstructor((Class[]) null); + } + + /** + * Loads a class corresponding to the class name using the current context class loader. + * + * @throws ClassNotFoundException if the class was not found on the classpath + */ + public static Class loadClass(String pName) throws ClassNotFoundException { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + return Class.forName(pName, true, loader); + } + + /** + * Returns the simple name of a class - i.e. the class name devoid of its package qualifier + * + * @param implClass + * @return + */ + public static String getBaseName(Class<?> implClass) { + String baseName = implClass.getName(); + int lastDot = baseName.lastIndexOf('.'); + if (lastDot != -1) { + baseName = baseName.substring(lastDot + 1); + } + return baseName; + } + + public static boolean isImmutable(Class clazz) { + return (String.class == clazz || clazz.isPrimitive() || Number.class.isAssignableFrom(clazz) + || Boolean.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz) || Byte.class + .isAssignableFrom(clazz)); + } + + /** + * Takes a property name and converts it to a getter method name according to JavaBean conventions. For example, + * property <code>foo<code> is returned as <code>getFoo</code> + */ + public static String toGetter(String name) { + return "get" + name.toUpperCase().substring(0, 1) + name.substring(1); + } + + /** + * Takes a setter or getter method name and converts it to a property name according to JavaBean conventions. For + * example, <code>setFoo(var)</code> is returned as property <code>foo<code> + */ + public static String toPropertyName(String name) { + return name.substring(3, 4).toLowerCase() + name.substring(4); + } + + /** + * Takes a property name and converts it to a setter method name according to JavaBean conventions. For example, the + * property <code>foo<code> is returned as <code>setFoo(var)</code> + */ + public static String toSetter(String name) { + return "set" + name.toUpperCase().substring(0, 1) + name.substring(1); + } + + /** + * Compares a two types, assuming one is a primitive, to dtermine if the other is its object counterpart + */ + private static boolean primitiveAssignable(Class memberType, Class param) { + if (memberType == Integer.class) { + return (param == Integer.TYPE); + } else if (memberType == Double.class) { + return (param == Double.TYPE); + } else if (memberType == Float.class) { + return (param == Float.TYPE); + } else if (memberType == Short.class) { + return (param == Short.TYPE); + } else if (memberType == Character.class) { + return (param == Character.TYPE); + } else if (memberType == Boolean.class) { + return (param == Boolean.TYPE); + } else if (memberType == Byte.class) { + return (param == Byte.TYPE); + } else if (param == Integer.class) { + return (memberType == Integer.TYPE); + } else if (param == Double.class) { + return (memberType == Double.TYPE); + } else if (param == Float.class) { + return (memberType == Float.TYPE); + } else if (param == Short.class) { + return (memberType == Short.TYPE); + } else if (param == Character.class) { + return (memberType == Character.TYPE); + } else if (param == Boolean.class) { + return (memberType == Boolean.TYPE); + } else if (param == Byte.class) { + return (memberType == Byte.TYPE); + } else { + return false; + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/MissingResourceException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/MissingResourceException.java new file mode 100644 index 0000000000..7b40ccbefa --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/MissingResourceException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config; + +/** + * Exception that indicates an expected resource could not be found. + * + * @version $Rev$ $Date$ + */ +public class MissingResourceException extends ConfigurationException { + /** + * Constructor that indicates which resource could not be found. + * The supplied parameter is also returned as the message. + * + * @param resource the resource that could not be found + */ + public MissingResourceException(String resource) { + super(resource); + } + + /** + * Return the name of the expected resource. + * + * @return the name of the expected resource + */ + public String getResource() { + return getMessage(); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ModuleComponentConfigurationLoader.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ModuleComponentConfigurationLoader.java new file mode 100644 index 0000000000..a8e2718222 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/ModuleComponentConfigurationLoader.java @@ -0,0 +1,74 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config; + +import java.util.Collection; + +import org.apache.tuscany.model.assembly.ModuleComponent; + +/** + * Interface for loading configuration information from some external + * form into a Tuscany logical model. + * + * @version $Rev: 368822 $ $Date: 2006-01-13 10:54:38 -0800 (Fri, 13 Jan 2006) $ + */ +public interface ModuleComponentConfigurationLoader { + + /** + * Load a SCDL module component. + * + * @param name the name of the module component + * @param uri + * @return a new module component definition + * @throws ConfigurationException if there was a problem loading the module component. + */ + ModuleComponent loadModuleComponent(String name, String uri) throws ConfigurationLoadException; + + /** + * Load a System SCDL module component. + * + * @param name the name of the module component + * @param uri + * @return a new module component definition + * @throws ConfigurationException if there was a problem loading the module component. + */ + ModuleComponent loadSystemModuleComponent(String name, String uri) throws ConfigurationLoadException; + + /** + * Load a SCDL module component. + * + * @param name the name of the module component + * @param uri + * @param url + * @return a new module component definition + * @throws ConfigurationException if there was a problem loading the module component. + */ + ModuleComponent loadModuleComponent(String name, String uri, String url) throws ConfigurationLoadException; + + /** + * Load a SCDL module component. + * + * @param name the name of the module component + * @param uri + * @param url + * @param urls + * @return a new module component definition + * @throws ConfigurationException if there was a problem loading the module component. + */ + ModuleComponent loadModuleComponent(String name, String uri, String url, Collection<String> urls) throws ConfigurationLoadException; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/impl/Java5ComponentTypeIntrospector.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/impl/Java5ComponentTypeIntrospector.java new file mode 100644 index 0000000000..8799969028 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/impl/Java5ComponentTypeIntrospector.java @@ -0,0 +1,423 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Remotable; + +import org.apache.tuscany.core.config.ComponentTypeIntrospector; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.config.JavaIntrospectionHelper; +import org.apache.tuscany.model.assembly.AssemblyFactory; +import org.apache.tuscany.model.assembly.ComponentType; +import org.apache.tuscany.model.assembly.Multiplicity; +import org.apache.tuscany.model.assembly.Property; +import org.apache.tuscany.model.assembly.Reference; +import org.apache.tuscany.model.assembly.Scope; +import org.apache.tuscany.model.assembly.Service; +import org.apache.tuscany.model.assembly.ServiceContract; +import org.apache.tuscany.model.types.java.JavaServiceContract; + +/** + * Introspects Java annotation-based metata data + * + * @version $Rev$ $Date$ + */ +public class Java5ComponentTypeIntrospector implements ComponentTypeIntrospector { + private final AssemblyFactory factory; + + public Java5ComponentTypeIntrospector(AssemblyFactory factory) { + this.factory = factory; + } + + /** + * Returns a component type for the given class + * + * @throws ConfigurationException + */ + public ComponentType introspect(Class<?> implClass) throws ConfigurationException { + ComponentType compType = factory.createComponentType(); + introspectServices(compType, implClass); + introspectAnnotatedMembers(compType, implClass); + + // if implementation is not annotated and no annotated members were found, add public fields and setters + if (!implClass.isAnnotationPresent(org.osoa.sca.annotations.Service.class) && compType.getProperties().isEmpty() + && compType.getReferences().isEmpty()) { + introspectMembers(compType, implClass); + } + + // FIXME scopes should be handled at the interface level + if (compType != null) { + Scope scope = getScope(implClass); + for (Iterator<Service> i = compType.getServices().iterator(); i.hasNext();) { + ServiceContract intf = i.next().getServiceContract(); + if (intf != null) + intf.setScope(scope); + } + } + + return compType; + } + + /** + * Returns the scope for a given class + * + */ + private static Scope getScope(Class<?> implClass) { + org.osoa.sca.annotations.Scope scope = implClass.getAnnotation(org.osoa.sca.annotations.Scope.class); + if (scope == null) { + // scope was not defined on the implementation class, look for annotated interfaces + Class<?>[] interfaces = implClass.getInterfaces(); + for (int i = 0; i < interfaces.length; i++) { + scope = interfaces[i].getAnnotation(org.osoa.sca.annotations.Scope.class); + } + } + if (scope == null) { + return Scope.INSTANCE; + } + + if ("MODULE".equalsIgnoreCase(scope.value())) { + return (Scope.MODULE); + } else if ("SESSION".equalsIgnoreCase(scope.value())) { + return (Scope.SESSION); + } else if ("REQUEST".equalsIgnoreCase(scope.value())) { + return (Scope.REQUEST); + } else { + return (Scope.INSTANCE); + } + } + + /** + * Adds the supported services for a component implementation type to its component type + * + * @param compType the component type being generated + * @param implClass the component implementation type class + * @throws ConfigurationException + */ + protected void introspectServices(ComponentType compType, Class<?> implClass) throws ConfigurationException { + List<Service> services = compType.getServices(); + assert services.isEmpty() : "componentType already has services defined"; + + // add services defined in an @Service annotation + org.osoa.sca.annotations.Service serviceAnnotation = implClass.getAnnotation(org.osoa.sca.annotations.Service.class); + if (serviceAnnotation != null) { + Class<?>[] interfaces = serviceAnnotation.interfaces(); + Class<?> value = serviceAnnotation.value(); + if (interfaces.length > 0) { + if (!Void.class.equals(value)) { + throw new IllegalArgumentException("Both interfaces and value specified in @Service on " + + implClass.getName()); + } + for (int i = 0; i < interfaces.length; i++) { + Class<?> intf = interfaces[i]; + addService(services, intf); + } + return; + } else if (!Void.class.equals(value)) { + addService(services, value); + return; + } + } + + // no @Service annotation, add all implemented interfaces with an @Remotable annotation + Class[] interfaces = implClass.getInterfaces(); + for (int i = 0; i < interfaces.length; i++) { + Class<?> intf = interfaces[i]; + if (intf.isAnnotationPresent(Remotable.class)) { + addService(services, intf); + } + } + + // if no Remotable interfaces were specified, the class itself is the service + if (services.isEmpty()) { + addService(services, implClass); + } + } + + /** + * Recursively adds supported services to a component type by walking the class hierarchy + * + * @throws ConfigurationException + */ + protected void addService(List<Service> services, Class<?> serviceClass) throws ConfigurationException { + JavaServiceContract javaInterface = factory.createJavaServiceContract(); + javaInterface.setInterface(serviceClass); + Callback callback = serviceClass.getAnnotation(Callback.class); + if (callback != null && !Void.class.equals(callback.value())) { + javaInterface.setCallbackInterface(callback.value()); + } + + String name = JavaIntrospectionHelper.getBaseName(serviceClass); + Service service = factory.createService(); + service.setName(name); + service.setServiceContract(javaInterface); + services.add(service); + } + + /** + * Root method for determining public field and method metadata + * + * @throws ConfigurationException + */ + protected void introspectAnnotatedMembers(ComponentType compType, Class<?> implClass) throws ConfigurationException { + + introspectPublicFields(compType, implClass); + introspectPrivateFields(compType, implClass); + + introspectPublicMethods(compType, implClass); + introspectPrivateMethods(compType, implClass); + } + + /** + * Introspects metdata for all public fields and methods for a class hierarchy + * + * @throws ConfigurationException + */ + protected void introspectMembers(ComponentType compType, Class<?> implClass) throws ConfigurationException { + List<Property> properties = compType.getProperties(); + List<Reference> references = compType.getReferences(); + + // inspect public fields from class and all superclasses + Field[] fields = implClass.getFields(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + if (field.getType().isAnnotationPresent(Remotable.class)) { + addReference(references, field); + } else { + addProperty(properties, field); + } + } + + // add public methods from class and all superclasses + Method[] methods = implClass.getMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (Void.class.equals(method.getReturnType()) && method.getName().startsWith("set") + && method.getParameterTypes().length == 1 + && !method.getParameterTypes()[0].isAnnotationPresent(Remotable.class)) { + String name = method.getName(); + name = Character.toLowerCase(name.charAt(3)) + name.substring(4); + Class<?> type = method.getParameterTypes()[0]; + if (type.isAnnotationPresent(Remotable.class)) { + addReference(references, name, type, false); + } else { + addProperty(properties, name, type, false); + } + } + } + } + + private void introspectPublicFields(ComponentType compType, Class<?> implClass) throws ConfigurationException { + List<Property> properties = compType.getProperties(); + List<Reference> references = compType.getReferences(); + + // inspect public fields from class and all superclasses + Field[] fields = implClass.getFields(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + if (field.isAnnotationPresent(org.osoa.sca.annotations.Property.class)) { + addProperty(properties, field); + } else if (field.isAnnotationPresent(org.osoa.sca.annotations.Reference.class)) { + addReference(references, field); + } + } + } + + private void introspectPrivateFields(ComponentType compType, Class<?> implClass) throws ConfigurationException { + List<Property> properties = compType.getProperties(); + List<Reference> references = compType.getReferences(); + + // inspect private fields declared in class + Field[] fields = implClass.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + if (!Modifier.isPrivate(field.getModifiers())) { + continue; + } + if (field.isAnnotationPresent(org.osoa.sca.annotations.Property.class)) { + addProperty(properties, field); + } else if (field.isAnnotationPresent(org.osoa.sca.annotations.Reference.class)) { + addReference(references, field); + } + } + } + + private void introspectPublicMethods(ComponentType compType, Class<?> implClass) throws ConfigurationException { + List<Property> properties = compType.getProperties(); + List<Reference> references = compType.getReferences(); + + // add public methods from class and all superclasses + Method[] methods = implClass.getMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (method.isAnnotationPresent(org.osoa.sca.annotations.Property.class)) { + addProperty(properties, method); + } else if (method.isAnnotationPresent(org.osoa.sca.annotations.Reference.class)) { + addReference(references, method); + } + } + } + + private void introspectPrivateMethods(ComponentType compType, Class<?> implClass) throws ConfigurationException { + List<Property> properties = compType.getProperties(); + List<Reference> references = compType.getReferences(); + + // add private methods declared on class + Method[] methods = implClass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (!Modifier.isPrivate(method.getModifiers())) { + continue; + } + if (method.isAnnotationPresent(org.osoa.sca.annotations.Property.class)) { + addProperty(properties, method); + } else if (method.isAnnotationPresent(org.osoa.sca.annotations.Reference.class)) { + addReference(references, method); + } + } + } + + protected void addProperty(List<Property> properties, Field field) throws ConfigurationException { + String name; + boolean required; + org.osoa.sca.annotations.Property annotation = field.getAnnotation(org.osoa.sca.annotations.Property.class); + if (annotation != null) { + name = annotation.name(); + if (name.length() == 0) { + name = field.getName(); + } + required = annotation.required(); + } else { + name = field.getName(); + required = false; + } + addProperty(properties, name, field.getType(), required); + } + + protected void addProperty(List<Property> properties, Method method) throws ConfigurationException { + if (!Void.class.equals(method.getReturnType())) { + throw new ConfigurationException("Property setter method does not return void: " + method.toString()); + } + Class<?>[] params = method.getParameterTypes(); + if (params.length != 1) { + throw new ConfigurationException("Property setter method does not have 1 parameter: " + method.toString()); + } + + String name; + boolean required; + org.osoa.sca.annotations.Property annotation = method.getAnnotation(org.osoa.sca.annotations.Property.class); + if (annotation != null) { + name = annotation.name(); + required = annotation.required(); + } else { + name = ""; + required = false; + } + if (name.length() == 0) { + name = method.getName(); + if (name.length() > 3 && name.startsWith("set")) { + name = Character.toLowerCase(name.charAt(3)) + name.substring(4); + } + } + addProperty(properties, name, params[0], required); + } + + protected void addProperty(List<Property> properties, String name, Class<?> type, boolean required) + throws ConfigurationException { + Property prop = factory.createProperty(); + prop.setName(name); + prop.setType(type); + prop.setRequired(required); + + // a java.util.Map is not a "many" + prop.setMany(type.isArray() || Collection.class.isAssignableFrom(type)); + + // todo how is the default specified using annotations? + prop.setDefaultValue(null); + + properties.add(prop); + } + + protected void addReference(List<Reference> references, Field field) throws ConfigurationException { + String name; + boolean required; + org.osoa.sca.annotations.Reference annotation = field.getAnnotation(org.osoa.sca.annotations.Reference.class); + if (annotation != null) { + name = annotation.name(); + if (name.length() == 0) { + name = field.getName(); + } + required = annotation.required(); + } else { + name = field.getName(); + required = false; + } + addReference(references, name, field.getType(), required); + } + + protected void addReference(List<Reference> references, Method method) throws ConfigurationException { + if (!Void.TYPE.equals(method.getReturnType())) { + throw new ConfigurationException("Reference setter method does not return void: " + method.toString()); + } + Class<?>[] params = method.getParameterTypes(); + if (params.length != 1) { + throw new ConfigurationException("Reference setter method does not have 1 parameter: " + method.toString()); + } + + String name; + boolean required; + org.osoa.sca.annotations.Reference annotation = method.getAnnotation(org.osoa.sca.annotations.Reference.class); + if (annotation != null) { + name = annotation.name(); + required = annotation.required(); + } else { + name = ""; + required = false; + } + if (name.length() == 0) { + name = method.getName(); + if (name.length() > 3 && name.startsWith("set")) { + name = Character.toLowerCase(name.charAt(3)) + name.substring(4); + } + } + addReference(references, name, params[0], required); + } + + protected void addReference(List<Reference> references, String name, Class<?> type, boolean required) + throws ConfigurationException { + Reference ref = factory.createReference(); + ref.setName(name); + boolean many = type.isArray() || Collection.class.isAssignableFrom(type); + Multiplicity multiplicity; + if (required) + multiplicity = many ? Multiplicity.ONE_N : Multiplicity.ONE_ONE; + else + multiplicity = many ? Multiplicity.ZERO_N : Multiplicity.ZERO_ONE; + ref.setMultiplicity(multiplicity); + ServiceContract javaInterface = factory.createJavaServiceContract(); + javaInterface.setInterface(type); + ref.setServiceContract(javaInterface); + references.add(ref); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/impl/ModuleComponentConfigurationLoaderImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/impl/ModuleComponentConfigurationLoaderImpl.java new file mode 100644 index 0000000000..bed4b0ac40 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/config/impl/ModuleComponentConfigurationLoaderImpl.java @@ -0,0 +1,142 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.config.impl; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.common.resource.ResourceLoader; +import org.apache.tuscany.core.config.ConfigurationLoadException; +import org.apache.tuscany.core.config.ModuleComponentConfigurationLoader; +import org.apache.tuscany.model.assembly.AssemblyFactory; +import org.apache.tuscany.model.assembly.AssemblyModelContext; +import org.apache.tuscany.model.assembly.Module; +import org.apache.tuscany.model.assembly.ModuleComponent; +import org.apache.tuscany.model.assembly.ModuleFragment; +import org.apache.tuscany.model.assembly.loader.AssemblyModelLoader; + +/** + */ +public class ModuleComponentConfigurationLoaderImpl implements ModuleComponentConfigurationLoader { + + private static final String SCA_MODULE_FILE_NAME = "sca.module"; + //FIXME can fragments have a variable prefix name? + private static final String SCA_FRAGMENT_FILE_NAME = "sca.fragment"; + private static final String SYSTEM_MODULE_FILE_NAME = "system.module"; + //FIXME can fragments have a variable prefix name? + private static final String SYSTEM_FRAGMENT_FILE_NAME = "system.fragment"; + + private AssemblyModelContext modelContext; + private ResourceLoader resourceLoader; + private AssemblyFactory assemblyFactory; + private AssemblyModelLoader modelLoader; + + /** + * Constructor + */ + public ModuleComponentConfigurationLoaderImpl(AssemblyModelContext modelContext) { + this.modelContext=modelContext; + this.modelLoader=this.modelContext.getAssemblyLoader(); + this.assemblyFactory=this.modelContext.getAssemblyFactory(); + this.resourceLoader=this.modelContext.getApplicationResourceLoader(); + } + + /** + * @see org.apache.tuscany.model.assembly.loader.AssemblyModelLoader#loadModuleComponent(java.lang.String, java.lang.String) + */ + public ModuleComponent loadSystemModuleComponent(String name, String uri) throws ConfigurationLoadException { + return loadModuleComponent(SYSTEM_MODULE_FILE_NAME, SYSTEM_FRAGMENT_FILE_NAME, name, uri); + } + + /** + * @see org.apache.tuscany.model.assembly.loader.AssemblyModelLoader#loadModuleComponent(java.lang.String, java.lang.String) + */ + public ModuleComponent loadModuleComponent(String name, String uri) throws ConfigurationLoadException { + return loadModuleComponent(SCA_MODULE_FILE_NAME, SCA_FRAGMENT_FILE_NAME, name, uri); + } + + /** + * Load a module component. + */ + private ModuleComponent loadModuleComponent(String moduleFileName, String fragmentFileName, String name, String uri) throws ConfigurationLoadException { + + // Load the sca.module file + URL moduleUrl; + try { + moduleUrl = resourceLoader.getResource(moduleFileName); + } catch (IOException e) { + throw new ConfigurationLoadException(moduleFileName, e); + } + if (moduleUrl == null) { + throw new ConfigurationLoadException(moduleFileName); + } + String moduleUri=moduleUrl.toString(); + + // Load the sca.fragment files + Iterator<URL> i; + try { + i = resourceLoader.getAllResources(fragmentFileName); + } catch (IOException e) { + throw new ConfigurationLoadException(fragmentFileName, e); + } + List<String> moduleFragmentUris=new ArrayList<String>(); + for (; i.hasNext(); ) { + URL url=i.next(); + moduleFragmentUris.add(url.toString()); + } + + return loadModuleComponent(name, uri, moduleUri, moduleFragmentUris); + } + + /** + * @see org.apache.tuscany.core.config.ModuleComponentConfigurationLoader#loadModuleComponent(java.lang.String, java.lang.String, java.lang.String) + */ + public ModuleComponent loadModuleComponent(String name, String uri, String url) throws ConfigurationLoadException { + return loadModuleComponent( name, uri, url, (Collection)null); + } + + /** + * @see org.apache.tuscany.core.config.ModuleComponentConfigurationLoader#loadModuleComponent(java.lang.String, java.lang.String, java.lang.String, java.util.Collection) + */ + public ModuleComponent loadModuleComponent(String name, String uri, String moduleUri, Collection<String> moduleFragmentUris) throws ConfigurationLoadException { + + // Load the module file + Module module=modelLoader.loadModule(moduleUri); + + // Load the sca.fragment files + if (moduleFragmentUris!=null) { + for (String moduleFragmentUri : moduleFragmentUris) { + ModuleFragment moduleFragment=modelLoader.loadModuleFragment(moduleFragmentUri); + module.getModuleFragments().add(moduleFragment); + } + } + + // Create the module component + ModuleComponent moduleComponent=assemblyFactory.createModuleComponent(); + moduleComponent.setName(name); + moduleComponent.setURI(uri); + moduleComponent.setComponentImplementation(module); + moduleComponent.initialize(modelContext); + + return moduleComponent; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AbstractContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AbstractContext.java new file mode 100644 index 0000000000..c1abcb3c03 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AbstractContext.java @@ -0,0 +1,89 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Functionality common to all <code>Context<code> implementations + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractContext implements Context { + + public AbstractContext() { + } + + public AbstractContext(String name) { + this.name = name; + } + + protected String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + protected int lifecycleState = UNINITIALIZED; + + public int getLifecycleState() { + return lifecycleState; + } + + public void setLifecycleState(int state) { + lifecycleState = state; + } + + protected List<LifecycleEventListener> contextListener = new CopyOnWriteArrayList(); + + public void addContextListener(LifecycleEventListener listener) { + contextListener.add(listener); + } + + public void removeContextListener(LifecycleEventListener listener) { + contextListener.remove(listener); + } + + public String toString() { + switch (lifecycleState) { + case (CONFIG_ERROR): + return "Context [" + name + "] in state [CONFIG_ERROR]"; + case (ERROR): + return "Context [" + name + "] in state [ERROR]"; + case (INITIALIZING): + return "Context [" + name + "] in state [INITIALIZING]"; + case (INITIALIZED): + return "Context [" + name + "] in state [INITIALIZED]"; + case (RUNNING): + return "Context [" + name + "] in state [RUNNING]"; + case (STOPPING): + return "Context [" + name + "] in state [STOPPING]"; + case (STOPPED): + return "Context [" + name + "] in state [STOPPED]"; + case (UNINITIALIZED): + return "Context [" + name + "] in state [UNINITIALIZED]"; + default: + return "Context [" + name + "] in state [UNKNOWN]"; + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AggregateContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AggregateContext.java new file mode 100644 index 0000000000..0fab87358f --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AggregateContext.java @@ -0,0 +1,85 @@ +package org.apache.tuscany.core.context; + +import java.util.List; + +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.model.assembly.Aggregate; +import org.apache.tuscany.model.assembly.Extensible; +import org.apache.tuscany.model.assembly.AggregatePart; + +/** + * A context which contains child component contexts. + * + * @version $Rev$ $Date$ + */ +public interface AggregateContext extends InstanceContext { + + /** + * Propagates an event to registered listeners. All lifecycle events will be propagated to children in the order + * that they were registered. Listeners are expected to be well-behaved and if an exception is thrown the + * notification process will be aborted. + * + * @param pEventType the type of event. Basic types are defined in {@link EventContext} + * @param pMessage the message associated with the event or null + * @throws EventException if an error occurs while sending the event + */ + public void fireEvent(int pEventType, Object pMessage) throws EventException; + + /** + * Registers a listener to receive notifications for the context + * + * @throws ContextRuntimeException if an error occurs during registration + */ + public void registerListener(RuntimeEventListener listener) throws ContextRuntimeException; + + /** + * Adds runtime artifacts represented by the set of model objects to the aggregate context by merging them with + * existing artifacts. Implementing classes may support only a subset of {@link AggregatePart} types. + * + * @see org.apache.tuscany.model.assembly.Component + * @see org.apache.tuscany.model.assembly.ModuleComponent + * @see org.apache.tuscany.model.assembly.SimpleComponent + * @see org.apache.tuscany.model.assembly.EntryPoint + * @see org.apache.tuscany.model.assembly.ExternalService + */ + public void registerModelObjects(List<Extensible> models) throws ConfigurationException; + + /** + * Adds a runtime artifact represented by the model object to the aggregate context by merging it with existing + * artifacts. Implementing classes may support only a subset of {@link AggregatePart} types. + * + * @see org.apache.tuscany.model.assembly.Component + * @see org.apache.tuscany.model.assembly.ModuleComponent + * @see org.apache.tuscany.model.assembly.SimpleComponent + * @see org.apache.tuscany.model.assembly.EntryPoint + * @see org.apache.tuscany.model.assembly.ExternalService + */ + public void registerModelObject(Extensible model) throws ConfigurationException; + + /** + * Returns the child context associated with a given name + */ + public InstanceContext getContext(String name); + + /** + * Returns the parent context, or null if the context does not have one + */ + public AggregateContext getParent(); + + /** + * Intended for internal use by the runtime, returns an implementation instance for the given context name, which + * may be a compound component/service form. Unlike {@link InstanceContext#getInstance(QualifiedName)}, which for aggregate contexts only returns + * entry point proxies, this method will return any type of contained implementation instance. + * + * @throws TargetException if there was an error returning the instance + */ + public Object locateInstance(String name) throws TargetException; + + /** + * Returns the aggregate managed by this aggregate context + * @return + */ + @Deprecated + public Aggregate getAggregate(); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireContext.java new file mode 100644 index 0000000000..5f3973f358 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireContext.java @@ -0,0 +1,35 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * A specialization of an AggregateContext that is able to automatically resolve references + * for its children using EntryPoint or Service interfaces exposed by it or, recursively, any + * of it parents. + * + * @version $Rev$ $Date$ + */ +public interface AutowireContext extends AggregateContext { + + /** + * Returns an reference to the requested service. + * + * @param instanceInterface the type of service being requested + * @return a reference to the requested service or null if none can be found + * @throws AutowireResolutionException if an error occurs attempting to resolve an autowire + */ + <T> T resolveInstance(Class<T> instanceInterface) throws AutowireResolutionException; + + // todo add additional methods that allow other qualifications to be supplied +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireResolutionException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireResolutionException.java new file mode 100644 index 0000000000..4da4206a94 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireResolutionException.java @@ -0,0 +1,40 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an exception while resolving an automatic wire + * + * @version $Rev$ $Date$ + */ +public class AutowireResolutionException extends TargetException { + + public AutowireResolutionException() { + super(); + } + + public AutowireResolutionException(String message) { + super(message); + } + + public AutowireResolutionException(String message, Throwable cause) { + super(message, cause); + } + + public AutowireResolutionException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ConfigurationContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ConfigurationContext.java new file mode 100644 index 0000000000..a57ed03ffd --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ConfigurationContext.java @@ -0,0 +1,66 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.model.assembly.Extensible; + +/** + * Offers configuration services in the runtime. A ConfigurationContext is able to configure a model and then build the + * runtime representation corresponding to that model in the live system. <p/> Configuration contexts will typically be + * hierarchical, delegating to their parent <b>after</b> performing an operation. The parent ConfigurationContext will + * typically be injected into an implementation of this interface during registration. + * + * @version $Rev$ $Date$ + */ +public interface ConfigurationContext { + + /** + * Adds additional configuration information to a model object. + * + * @param model the model object to be configured + * @throws ConfigurationException + */ + public void configure(Extensible model) throws ConfigurationException; + + /** + * Decorates the supplied model object with a {@link org.apache.tuscany.core.builder.RuntimeConfiguration} that can + * be used to create the runtime context corresponding to the model. + * + * @param parent an AggregrateContext that will ultimately become the parent of the runtime context + * @param model the model object that defines the configuration to be built + * @throws BuilderConfigException + * @see org.apache.tuscany.core.builder.RuntimeConfiguration + */ + public void build(AggregateContext parent, Extensible model) throws BuilderConfigException; + + /** + * Constructs a wire from a source proxy factory to a corresponding target, potentially performing optimizations + * + * @param sourceFactory the proxy factory that will be used to create the injected proxy for a reference + * @param targetFactory the proxy factory that contains the invocation chains for the target side of the wire + * @param targetType the {@link org.apache.tuscany.core.builder.RuntimeConfiguration} implementation type for the + * wire target + * @param downScope whether the source is a shorter lived scope than the target. Used in optimization. + * @param targetScopeContext the scope context of the target service + * @throws BuilderConfigException + */ + public void wire(ProxyFactory sourceFactory, ProxyFactory targetFactory, Class targetType, boolean downScope, + ScopeContext targetScopeContext) throws BuilderConfigException; + + public void wire(ProxyFactory targetFactory, Class targetType, ScopeContext targetScopeContext) throws BuilderConfigException; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/Context.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/Context.java new file mode 100644 index 0000000000..2eb70e8711 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/Context.java @@ -0,0 +1,106 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * An entity that provides an execution context for a runtime artifact + * + * @version $Rev$ $Date$ + */ +public interface Context { + + /* A configuration error state */ + public static final int CONFIG_ERROR = -1; + + /* Has not been initialized */ + public static final int UNINITIALIZED = 0; + + /* In the process of being configured and initialized */ + public static final int INITIALIZING = 1; + + /* Instantiated and configured */ + public static final int INITIALIZED = 2; + + /* Configured and initialized */ + public static final int RUNNING = 4; + + /* In the process of being shutdown */ + public static final int STOPPING = 5; + + /* Has been shutdown and removed from the module */ + public static final int STOPPED = 6; + + /* In an error state */ + public static final int ERROR = 7; + + /** + * Returns the name of the context + */ + public String getName(); + + /** + * Sets the name of the context + */ + public void setName(String name); + + /** + * Returns the lifecycle state + * + * @see #UNINITIALIZED + * @see #INITIALIZING + * @see #INITIALIZED + * @see #RUNNING + * @see #STOPPING + * @see #STOPPED + */ + public int getLifecycleState(); + + /** + * Sets the lifecycle state + * + * @see #UNINITIALIZED + * @see #INITIALIZING + * @see #INITIALIZED + * @see #RUNNING + * @see #STOPPING + * @see #STOPPED + */ + public void setLifecycleState(int state); + + /** + * Starts the container + * + * @throws CoreRuntimeException + */ + public void start() throws CoreRuntimeException; + + /** + * Stops the container + * + * @throws CoreRuntimeException + */ + public void stop() throws CoreRuntimeException; + + /** + * Registers a listener for context events + */ + public void addContextListener(LifecycleEventListener listener); + + /** + * Deregisters a context event listener + */ + public void removeContextListener(LifecycleEventListener listener); + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextInitException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextInitException.java new file mode 100644 index 0000000000..e024a98b0e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextInitException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an error encountered while initializing an instance context + * + * @version $Rev$ $Date$ + */ +public class ContextInitException extends ContextRuntimeException { + + public ContextInitException() { + super(); + } + + public ContextInitException(String message) { + super(message); + } + + public ContextInitException(String message, Throwable cause) { + super(message, cause); + } + + public ContextInitException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextRuntimeException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextRuntimeException.java new file mode 100644 index 0000000000..0d35f145dc --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextRuntimeException.java @@ -0,0 +1,39 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * An unchecked exception encountered by an {@link org.apache.tuscany.core.context.Context} + * + * @version $Rev$ $Date$ + */ +public class ContextRuntimeException extends CoreRuntimeException { + + public ContextRuntimeException() { + super(); + } + + public ContextRuntimeException(String message) { + super(message); + } + + public ContextRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public ContextRuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/CoreRuntimeException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/CoreRuntimeException.java new file mode 100644 index 0000000000..a46d35c22c --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/CoreRuntimeException.java @@ -0,0 +1,27 @@ +package org.apache.tuscany.core.context; + +import org.apache.tuscany.common.TuscanyRuntimeException; + +/** + * The root exception for the runtime package. Exceptions occurring in the runtime are generally non-recoverable + * + * @version $Rev$ $Date$ + */ +public abstract class CoreRuntimeException extends TuscanyRuntimeException { + + public CoreRuntimeException() { + super(); + } + + public CoreRuntimeException(String message) { + super(message); + } + + public CoreRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public CoreRuntimeException(Throwable cause) { + super(cause); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/DuplicateNameException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/DuplicateNameException.java new file mode 100644 index 0000000000..81a334d3c8 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/DuplicateNameException.java @@ -0,0 +1,39 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an attempt to add a context with a name equal to an existing context + * + * @version $Rev$ $Date$ + */ +public class DuplicateNameException extends ContextRuntimeException { + + public DuplicateNameException() { + super(); + } + + public DuplicateNameException(String message) { + super(message); + } + + public DuplicateNameException(String message, Throwable cause) { + super(message, cause); + } + + public DuplicateNameException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EntryPointContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EntryPointContext.java new file mode 100644 index 0000000000..aef2840f9a --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EntryPointContext.java @@ -0,0 +1,57 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * The runtime artifact representing an entry point, <code>EntryPointContext</code> manages invocation handler + * instances that expose service operations offered by a component in the parent aggregate. The invocation handler + * instance is responsible for dispatching the request down an invocation chain to the target instance. The invocation + * chain may contain {@link org.apache.tuscany.core.invocation.Interceptor}s and + * {@link org.apache.tuscany.core.invocation.MessageHandler}s that implement policies or perform mediations on the + * invocation. + * <p> + * Entry point contexts are used by transport binding artifacts to invoke an operation on a service. The transport + * binding uses an {@link java.lang.reflect.InvocationHandler} instance obtained from the <code>EntryPointContext</code> + * to perform the invocation as in: + * + * <pre> + * AggregateContext aggregateContext = ... + * EntryPointContext ctx = (EntryPointContext) aggregateContext.getContext("source"); + * Assert.assertNotNull(ctx); + * InvocationHandler handler = (InvocationHandler) ctx.getImplementationInstance(); + * Object response = handler.invoke(null, operation, new Object[] { param }); + * </pre> + * + * The <code>Proxy</code> instance passed to <code>InvocationHandler</code> may be null as the client is invoking + * directly on the handler. + * <p> + * Alternatively, the following will return a proxy implementing the service interface exposed by the entry point: + * + * <pre> + * AggregateContext aggregateContext = ... + * EntryPointContext ctx = (EntryPointContext) aggregateContext.getContext("source"); + * Assert.assertNotNull(ctx); + * HelloWorld proxy = (Helloworld) ctx.getInstance(null); // service name not necessary + * </pre> + * + * The proxy returned will be backed by the entry point invocation chain. + * + * @version $Rev$ $Date$ + */ +public interface EntryPointContext extends InstanceContext { + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventContext.java new file mode 100644 index 0000000000..9f7c98200a --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventContext.java @@ -0,0 +1,66 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Implementations are responsible for tracking scope keys associated with the current request. + * + * @version $Rev$ $Date$ + */ +public interface EventContext { + + /* An event type fired when a request is first serviced in the runtime */ + public static final int REQUEST_START = 1; + + /* An event type fired when the runtime finishes servicing a request */ + public static final int REQUEST_END = 2; + + /* An event type fired when a session is set for the current context */ + public static final int SESSION_NOTIFY = 3; + + /* An event type fired when a session is invalidated in the runtime */ + public static final int SESSION_END = 4; + + /* An event type fired when the current deployment unit is initialized */ + public static final int MODULE_START = 5; + + /* An event type fired when the current deployment unit is quiesced */ + public static final int MODULE_STOP = 6; + + public static final int SYSTEM_START = 7; + + public static final int SYSTEM_STOP = 8; + + /* An identifier type associated with an HTTP session */ + public static final Object HTTP_SESSION = new Object(); + + /** + * Returns the unique key for the given identifier, e.g a session + */ + public Object getIdentifier(Object type); + + /** + * Sets the unique key for the given identifier, e.g a session + */ + public void setIdentifier(Object type, Object identifier); + + /** + * Clears the unique key for the given identifier, e.g a session + */ + public void clearIdentifier(Object type); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventException.java new file mode 100644 index 0000000000..aaf26aee69 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an error encountered while firing a module event + * + * @version $Rev$ $Date$ + */ +public class EventException extends CoreRuntimeException { + + public EventException(String message, Throwable cause) { + super(message, cause); + } + + public EventException(String message) { + super(message); + } + + public EventException(Throwable cause) { + super(cause); + } + + public EventException() { + super(); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ExternalServiceContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ExternalServiceContext.java new file mode 100644 index 0000000000..298246dc81 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ExternalServiceContext.java @@ -0,0 +1,24 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Manages an external service + * + * @version $Rev$ $Date$ + */ +public interface ExternalServiceContext extends InstanceContext { + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InstanceContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InstanceContext.java new file mode 100644 index 0000000000..473762b6b0 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InstanceContext.java @@ -0,0 +1,75 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Manages instances of a runtime artifact. An <code>InstanceContext</code> may contain child contexts which + * themselves manage implementation instances or it may be a leaf context. + * + * @see org.apache.tuscany.core.context.SimpleComponentContext + * @see org.apache.tuscany.core.context.AggregateContext + * @see org.apache.tuscany.core.context.EntryPointContext + * @see org.apache.tuscany.core.context.ExternalServiceContext + * + * @version $Rev$ $Date$ + */ +public interface InstanceContext extends Context { + + /** + * Returns the instance associated with the requested name, which may be in a simple or compound form. Simple (i.e. + * leaf) contexts will return an instance associated with the service name part of the compound name, which may be + * null. + * <p> + * Aggregate contexts will return an instance (likely a proxy) of a contained entry point context. In this case, the + * port name on the qualified name will correspond to the aggregate context name and the part name will be used to + * retrieve the contained entry point context. The latter may be null. If the contained context is not an entry + * point context, an exception will be thrown. + * + * @param qName a qualified name of the requested instance + * @return the implementation instance or a proxy to it + * @throws TargetException if an error occurs retrieving the instance or the requested component is not an entry + * point. + * + * @see AggregateContext + * @see org.apache.tuscany.model.assembly.EntryPoint + */ + public Object getInstance(QualifiedName qName) throws TargetException; + + /** + * Returns an instance associated with the requested name without notifying <code>ContextEventListener</code>s + * that may be registered with this context on instance creation. Note that {@link #getInstance(QualifiedName)} + * should generally be called and this method is only provided as an optimization for particular circumstances. + * + * @param qName a qualified name of the requested instance + * @param notify whether to notify <code>ContextEventListener</code>s + * @return the instance or a proxy to it + * @throws TargetException if an error occurs retrieving the instance or proxy + * @see LifecycleEventListener + */ + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException; + + /** + * Returns the implementation instance associated witht he component. An implementation instance does not + * have a proxy invocation chainXXX + * @return + * @throws TargetException + */ + public Object getImplementationInstance() throws TargetException; + + public Object getImplementationInstance(boolean notify) throws TargetException; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InvalidNameException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InvalidNameException.java new file mode 100644 index 0000000000..65c709e569 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InvalidNameException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an invalid name + * + * @version $Rev$ $Date$ + */ +public class InvalidNameException extends ContextRuntimeException { + + public InvalidNameException() { + super(); + } + + public InvalidNameException(String message) { + super(message); + } + + public InvalidNameException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidNameException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/LifecycleEventListener.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/LifecycleEventListener.java new file mode 100644 index 0000000000..78962b53b4 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/LifecycleEventListener.java @@ -0,0 +1,32 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.EventListener; + +/** + * Callback interface for receiving instance context lifecycle events + * + * @version $Rev$ $Date$ + */ +public interface LifecycleEventListener extends EventListener { + + /** + * Notifies the listener that a new component context was created + */ + public void onInstanceCreate(Context component); +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/QualifiedName.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/QualifiedName.java new file mode 100644 index 0000000000..ad71721b75 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/QualifiedName.java @@ -0,0 +1,83 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * An evaluated name consisting of a part/port pair. In the runtime, a part generally 'contains' or 'provides' ports + * such as a module component/entry point or a component/service pair. + * + * @version $Rev$ $Date$ + */ +public class QualifiedName { + + private String qName; + + private String partName; + + private String portName; + + public static final String NAME_SEPARATOR = "/"; + + /** + * Constructs a new qualified name + * + * @throws InvalidNameException if the name is in an invalid format + */ + public QualifiedName(String qualifiedName) throws InvalidNameException { + assert (qualifiedName != null) : "Name was null"; + int pos = qualifiedName.indexOf(QualifiedName.NAME_SEPARATOR); + switch (pos) { + case -1: + partName = qualifiedName; + break; + case 0: + throw new InvalidNameException(qualifiedName); + default: + partName = qualifiedName.substring(0, pos); + portName = qualifiedName.substring(pos + 1); + break; + } + qName = qualifiedName; + } + + /** + * Returns the parsed part name + */ + public String getPartName() { + return partName; + } + + /** + * Returns the parsed port name if the original is of the compound for part/port + */ + public String getPortName() { + return portName; + } + + /** + * Returns the full part/port name pair + * + * @return + */ + public String getQualifiedName() { + return qName; + } + + public String toString() { + return qName; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/RuntimeEventListener.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/RuntimeEventListener.java new file mode 100644 index 0000000000..e90f30b9cc --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/RuntimeEventListener.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.EventListener; + +/** + * Listeners observe events fired in the SCA runtime. + * + * @version $Rev$ $Date$ + */ +public interface RuntimeEventListener extends EventListener { + + /** + * A method called when an event for which the <tt>Listener</tt> class is registered to observe is fired in the runtime + * + * @param type the event type identifier + * @param message the event message + * @throws EventException if an error occurs processing the event + */ + public void onEvent(int type, Object message) throws EventException; +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeAwareContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeAwareContext.java new file mode 100644 index 0000000000..565d7b49a6 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeAwareContext.java @@ -0,0 +1,31 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.Map; + +import org.apache.tuscany.model.assembly.Scope; + +/** + * Denotes an aggregate context that supports scopes + * + * @version $Rev$ $Date$ + */ +public interface ScopeAwareContext extends AggregateContext { + + /** + * Returns an immutable collection of scopes keyed by type for the aggregate context + */ + public Map<Scope, ScopeContext> getScopeContexts(); +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeContext.java new file mode 100644 index 0000000000..abda942c88 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeContext.java @@ -0,0 +1,72 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.List; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; + +/** + * Manages the lifecycle and visibility of <code>InstanceContext</code>s. + * + * @see org.apache.tuscany.core.context.InstanceContext + * + * @version $Rev$ $Date$ + */ +public interface ScopeContext extends InstanceContext, RuntimeEventListener { + + /** + * Returns whether implementation instances may be held for the duration of an invocation + */ + public boolean isCacheable(); + + /** + * Registers the runtime configurations used to construct instance contexts for the scope + */ + public void registerConfigurations(List<RuntimeConfiguration<InstanceContext>> configurations); + + /** + * Adds a runtime configuration to the scope + */ + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration); + + /** + * Returns a context bound to the given name or null if the component does not exist. The returned context is bound + * to a key determined from the thread context. + */ + public InstanceContext getContext(String name); + + /** + * Returns a context bound to the given name and scoped to the given key or null if the context does not exist + */ + public InstanceContext getContextByKey(String name, Object key); + + /** + * Removes a context with the given name, determining the scope key from the thread context + * + * @throws ScopeRuntimeException + */ + public void removeContext(String name) throws ScopeRuntimeException; + + /** + * Removes a context bound to the given name and scope key + * + * @throws ScopeRuntimeException + */ + public void removeContextByKey(String name, Object key) throws ScopeRuntimeException; + +}
\ No newline at end of file diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeIdentifier.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeIdentifier.java new file mode 100644 index 0000000000..38a847295c --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeIdentifier.java @@ -0,0 +1,33 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Implementations enable lazy retrieval of a scope id associated with a request, i.e. an id (and presumably a context) do not + * have to be generated if the scope is never accessed. Identifiers are associated with the current request thread and keyed on + * scope type. + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.container.module.EventContext + */ +public interface ScopeIdentifier { + + /** + * Returns the scope id for the request. + */ + public Object getIdentifier(); +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeInitializationException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeInitializationException.java new file mode 100644 index 0000000000..6ef5bfe9dd --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeInitializationException.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an initialization exception thrown by a scope container + * + * @version $Rev$ $Date$ + */ +public class ScopeInitializationException extends ScopeRuntimeException { + + public ScopeInitializationException() { + super(); + } + + public ScopeInitializationException(String message) { + super(message); + } + + public ScopeInitializationException(String message, Throwable cause) { + super(message, cause); + } + + public ScopeInitializationException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeRuntimeException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeRuntimeException.java new file mode 100644 index 0000000000..5022f7589d --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeRuntimeException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes a general runtime exception encountered by a scope container + * + * @version $Rev$ $Date$ + */ +public class ScopeRuntimeException extends CoreRuntimeException { + + public ScopeRuntimeException() { + super(); + } + + public ScopeRuntimeException(String message) { + super(message); + } + + public ScopeRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public ScopeRuntimeException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeStrategy.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeStrategy.java new file mode 100644 index 0000000000..b648fc2dcc --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeStrategy.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.Map; + +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implementations provide scope container creation facilities and scope semantics to the runtime + * + * @version $Rev$ $Date$ + */ +public interface ScopeStrategy { + + /* Denotes an undefined scope */ + public static final int SCOPE_NOT_FOUND = -3; + + /** + * Creates and returns new instances of configured scope containers + */ + public Map<Scope, ScopeContext> createScopes(EventContext eventContext); + + /** + * Determines whether a wire proceeds from a source of higher scope to a target of lesser scope + */ + public boolean downScopeReference(Scope sourceScope, Scope targetScope); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ServiceNotFoundException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ServiceNotFoundException.java new file mode 100644 index 0000000000..253909d7fa --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ServiceNotFoundException.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +import org.osoa.sca.ServiceUnavailableException; + +/** + * Denotes the specific case where a service was not found at runtime + * + * @version $Rev$ $Date$ + */ +public class ServiceNotFoundException extends ServiceUnavailableException { + + public ServiceNotFoundException() { + super(); + } + + public ServiceNotFoundException(String message) { + super(message); + } + + public ServiceNotFoundException(Throwable cause) { + super(cause); + } + + public ServiceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SimpleComponentContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SimpleComponentContext.java new file mode 100644 index 0000000000..d35a3712a0 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SimpleComponentContext.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * A runtime entity that manages a non-aggregate (i.e. leaf-type) instance. + * + * @version $Rev$ $Date$ + */ +public interface SimpleComponentContext extends InstanceContext { + + /** + * Returns whether a the context should be eagerly initialized + */ + public boolean isEagerInit(); + + /** + * Returns whether a the context should be called back when its scope ends + */ + public boolean isDestroyable(); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SystemAggregateContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SystemAggregateContext.java new file mode 100644 index 0000000000..afb8499104 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SystemAggregateContext.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +import org.apache.tuscany.core.config.ConfigurationException; + +/** + * Marker type for system aggregate contexts + * + * @version $Rev$ $Date$ + */ +public interface SystemAggregateContext extends AutowireContext, ScopeAwareContext, ConfigurationContext { + + /** + * Register a simple Java Object as a system component. + * This is primarily intended for use by bootstrap code to create the initial + * configuration components. + * + * @param name the name of the resulting component + * @param instance the Object that will become the component's implementation + * @throws ConfigurationException + */ + void registerJavaObject(String name, Object instance) throws ConfigurationException; +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/TargetException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/TargetException.java new file mode 100644 index 0000000000..dd39d06aa1 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/TargetException.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an error while performing an operation on a target component implementation instance or proxy + * + * @version $Rev$ $Date$ + */ +public class TargetException extends CoreRuntimeException { + + public TargetException() { + super(); + } + + public TargetException(String message) { + super(message); + } + + public TargetException(String message, Throwable cause) { + super(message, cause); + } + + public TargetException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AbstractAggregateContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AbstractAggregateContext.java new file mode 100644 index 0000000000..9ee1878625 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AbstractAggregateContext.java @@ -0,0 +1,652 @@ +package org.apache.tuscany.core.context.impl; + +import static org.apache.tuscany.core.context.EventContext.HTTP_SESSION; +import static org.apache.tuscany.core.context.EventContext.REQUEST_END; +import static org.apache.tuscany.core.context.EventContext.SESSION_NOTIFY; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.wsdl.Part; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.context.ConfigurationContext; +import org.apache.tuscany.core.context.ContextInitException; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.DuplicateNameException; +import org.apache.tuscany.core.context.EntryPointContext; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.EventException; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.ScopeAwareContext; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.ScopeRuntimeException; +import org.apache.tuscany.core.context.ScopeStrategy; +import org.apache.tuscany.core.context.SimpleComponentContext; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.context.scope.DefaultScopeStrategy; +import org.apache.tuscany.core.invocation.InvocationConfiguration; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.invocation.spi.ProxyInitializationException; +import org.apache.tuscany.core.system.annotation.Autowire; +import org.apache.tuscany.core.system.annotation.ParentContext; +import org.apache.tuscany.model.assembly.Aggregate; +import org.apache.tuscany.model.assembly.Component; +import org.apache.tuscany.model.assembly.EntryPoint; +import org.apache.tuscany.model.assembly.Extensible; +import org.apache.tuscany.model.assembly.ExternalService; +import org.apache.tuscany.model.assembly.Module; +import org.apache.tuscany.model.assembly.Scope; +import org.apache.tuscany.model.assembly.ComponentImplementation; +import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl; + +/** + * The base implementation of an aggregate context + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractAggregateContext extends AbstractContext implements AutowireContext, ScopeAwareContext { + + public static final int DEFAULT_WAIT = 1000 * 60; + + // ---------------------------------- + // Fields + // ---------------------------------- + + // The parent context, if one exists + @ParentContext + protected AggregateContext parentContext; + + // The parent configuration context, if one exists + @Autowire(required = false) + protected ConfigurationContext configurationContext; + + // The system monitor factory + @Autowire(required = false) + protected MonitorFactory monitorFactory; + + // The logical model representing the module assembly + // protected ModuleComponent moduleComponent; + protected Module module; + + protected Map<String, RuntimeConfiguration<InstanceContext>> configurations = new HashMap(); + + // Factory for scope contexts + @Autowire(required = false) + protected ScopeStrategy scopeStrategy; + + // The event context for associating context events to threads + protected EventContext eventContext; + + // The scopes for this context + protected Map<Scope, ScopeContext> scopeContexts; + + protected Map<Scope, ScopeContext> immutableScopeContexts; + + // A component context name to scope context index + protected Map<String, ScopeContext> scopeIndex; + + // Listeners for context events + protected List<RuntimeEventListener> listeners = new CopyOnWriteArrayList(); + + // Blocking latch to ensure the module is initialized exactly once prior to servicing requests + protected CountDownLatch initializeLatch = new CountDownLatch(1); + + // Indicates whether the module context has been initialized + protected boolean initialized; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public AbstractAggregateContext() { + scopeIndex = new ConcurrentHashMap(); + // FIXME the factory should be injected + module = new AssemblyFactoryImpl().createModule(); + } + + public AbstractAggregateContext(String name, AggregateContext parent, ScopeStrategy strategy, EventContext ctx, + ConfigurationContext configCtx, MonitorFactory factory) { + super(name); + this.scopeStrategy = strategy; + this.eventContext = ctx; + this.configurationContext = configCtx; + this.monitorFactory = factory; + scopeIndex = new ConcurrentHashMap(); + parentContext = parent; + // FIXME the factory should be injected + module = new AssemblyFactoryImpl().createModule(); + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public void start() { + synchronized (initializeLatch) { + try { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Context not in UNINITIALIZED state"); + } + lifecycleState = INITIALIZING; + initializeScopes(); + + Map<Scope, List<RuntimeConfiguration<SimpleComponentContext>>> configurationsByScope = new HashMap(); + if (configurations != null) { + for (RuntimeConfiguration source : configurations.values()) { + // FIXME scopes are defined at the interface level + Scope sourceScope = source.getScope(); + wireSource(source); + buildTarget(source); + scopeIndex.put(source.getName(), scopeContexts.get(sourceScope)); + List<RuntimeConfiguration<SimpleComponentContext>> list = configurationsByScope.get(sourceScope); + if (list == null) { + list = new ArrayList(); + configurationsByScope.put(sourceScope, list); + } + list.add(source); + } + } + for (EntryPoint ep : module.getEntryPoints()) { + registerAutowire(ep); + } + for (Component component : module.getComponents()) { + registerAutowire(component); + } + for (ExternalService es : module.getExternalServices()) { + registerAutowire(es); + } + for (Map.Entry entries : configurationsByScope.entrySet()) { + // register configurations with scope contexts + ScopeContext scope = scopeContexts.get(entries.getKey()); + scope.registerConfigurations((List<RuntimeConfiguration<InstanceContext>>) entries.getValue()); + } + initializeProxies(); + for (ScopeContext scope : scopeContexts.values()) { + // register scope contexts as a listeners for events in the aggregate context + registerListener(scope); + scope.start(); + } + lifecycleState = RUNNING; + } catch (ProxyInitializationException e) { + lifecycleState = ERROR; + ContextInitException cie = new ContextInitException(e); + cie.addContextName(getName()); + throw cie; + } catch (ConfigurationException e) { + lifecycleState = ERROR; + throw new ContextInitException(e); + } catch (CoreRuntimeException e) { + lifecycleState = ERROR; + e.addContextName(getName()); + throw e; + } finally { + initialized = true; + // release the latch and allow requests to be processed + initializeLatch.countDown(); + } + } + } + + public void stop() { + if (lifecycleState == STOPPED) { + return; + } + // need to block a start until reset is complete + initializeLatch = new CountDownLatch(2); + lifecycleState = STOPPING; + initialized = false; + if (scopeContexts != null) { + for (ScopeContext scope : scopeContexts.values()) { + try { + if (scope.getLifecycleState() == ScopeContext.RUNNING) { + scope.stop(); + } + } catch (ScopeRuntimeException e) { + // log.error("Error stopping scope container [" + scopeContainers[i].getName() + "]", e); + } + } + } + scopeContexts = null; + scopeIndex.clear(); + // allow initialized to be called + initializeLatch.countDown(); + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void setModule(Module module) { + assert (module != null) : "Module cannot be null"; + name = module.getName(); + this.module = module; + } + + public void setScopeStrategy(ScopeStrategy scopeStrategy) { + this.scopeStrategy = scopeStrategy; + } + + public void setEventContext(EventContext eventContext) { + this.eventContext = eventContext; + } + + public void setMonitorFactory(MonitorFactory factory) { + this.monitorFactory = factory; + } + + public AggregateContext getParent() { + return parentContext; + } + + public void registerModelObjects(List<Extensible> models) throws ConfigurationException { + assert (models != null) : "Model object collection was null"; + for (Extensible model : models) { + registerModelObject(model); + } + } + + public void registerModelObject(Extensible model) throws ConfigurationException { + assert (model != null) : "Model object was null"; + initializeScopes(); + if (configurationContext != null) { + try { + configurationContext.configure(model); + configurationContext.build(this, model); + } catch (ConfigurationException e) { + e.addContextName(getName()); + throw e; + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + RuntimeConfiguration<InstanceContext> configuration = null; + if (model instanceof Module) { + // merge new module definition with the existing one + Module oldModule = module; + Module newModule = (Module) model; + module = newModule; + for (Component component : newModule.getComponents()) { + ComponentImplementation componentImplementation = component.getComponentImplementation(); + if (componentImplementation == null) { + ConfigurationException e = new ConfigurationException("Component implementation not set"); + e.addContextName(component.getName()); + e.addContextName(getName()); + throw e; + } + configuration = (RuntimeConfiguration<InstanceContext>) componentImplementation.getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.addContextName(component.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(component); + } + for (EntryPoint ep : newModule.getEntryPoints()) { + configuration = (RuntimeConfiguration<InstanceContext>) ep.getConfiguredReference().getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.setIdentifier(ep.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(ep); + } + for (ExternalService service : newModule.getExternalServices()) { + configuration = (RuntimeConfiguration<InstanceContext>) service.getConfiguredService().getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.setIdentifier(service.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(service); + } + if (lifecycleState == RUNNING) { + for (Component component : newModule.getComponents()) { + RuntimeConfiguration<InstanceContext> config = (RuntimeConfiguration<InstanceContext>) component + .getComponentImplementation().getRuntimeConfiguration(); + wireSource(config); + buildTarget(config); + try { + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory sourceProxyFactory : (Collection<ProxyFactory>) config.getSourceProxyFactories() + .values()) { + sourceProxyFactory.initialize(); + } + } + if (config.getTargetProxyFactories() != null) { + for (ProxyFactory targetProxyFactory : (Collection<ProxyFactory>) config.getTargetProxyFactories() + .values()) { + targetProxyFactory.initialize(); + } + } + } catch (ProxyInitializationException e) { + throw new ConfigurationException(e); + } + + } + for (EntryPoint ep : newModule.getEntryPoints()) { + RuntimeConfiguration<InstanceContext> config = (RuntimeConfiguration<InstanceContext>) ep + .getConfiguredReference().getRuntimeConfiguration(); + wireSource(config); + buildTarget(config); + try { + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory sourceProxyFactory : (Collection<ProxyFactory>) config.getSourceProxyFactories() + .values()) { + sourceProxyFactory.initialize(); + } + } + if (config.getTargetProxyFactories() != null) { + for (ProxyFactory targetProxyFactory : (Collection<ProxyFactory>) config.getTargetProxyFactories() + .values()) { + targetProxyFactory.initialize(); + } + } + } catch (ProxyInitializationException e) { + throw new ConfigurationException(e); + } + + } + for (ExternalService es : newModule.getExternalServices()) { + RuntimeConfiguration<InstanceContext> config = (RuntimeConfiguration<InstanceContext>) es + .getConfiguredService().getRuntimeConfiguration(); + buildTarget(config); + try { + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory sourceProxyFactory : (Collection<ProxyFactory>) config.getSourceProxyFactories() + .values()) { + sourceProxyFactory.initialize(); + } + } + if (config.getTargetProxyFactories() != null) { + for (ProxyFactory targetProxyFactory : (Collection<ProxyFactory>) config.getTargetProxyFactories() + .values()) { + targetProxyFactory.initialize(); + } + } + } catch (ProxyInitializationException e) { + throw new ConfigurationException(e); + } + + } + + } + // merge existing module component assets + module.getComponents().addAll(oldModule.getComponents()); + module.getEntryPoints().addAll(oldModule.getEntryPoints()); + module.getExternalServices().addAll(oldModule.getExternalServices()); + } else { + if (model instanceof Component) { + Component component = (Component) model; + module.getComponents().add(component); + configuration = (RuntimeConfiguration<InstanceContext>) component.getComponentImplementation() + .getRuntimeConfiguration(); + } else if (model instanceof EntryPoint) { + EntryPoint ep = (EntryPoint) model; + module.getEntryPoints().add(ep); + configuration = (RuntimeConfiguration<InstanceContext>) ep.getConfiguredReference().getRuntimeConfiguration(); + } else if (model instanceof ExternalService) { + ExternalService service = (ExternalService) model; + module.getExternalServices().add(service); + configuration = (RuntimeConfiguration<InstanceContext>) service.getConfiguredService().getRuntimeConfiguration(); + } else { + BuilderConfigException e = new BuilderConfigException("Unknown model type"); + e.setIdentifier(model.getClass().getName()); + e.addContextName(getName()); + throw e; + } + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + if (model instanceof Part) { + e.setIdentifier(((Part) model).getName()); + } + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(model); + } + } + + protected void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) throws ConfigurationException { + if (lifecycleState == RUNNING) { + if (scopeIndex.get(configuration.getName()) != null) { + throw new DuplicateNameException(configuration.getName()); + } + ScopeContext scope = scopeContexts.get(configuration.getScope()); + if (scope == null) { + ConfigurationException e = new ConfigurationException("Component has an unknown scope"); + e.addContextName(configuration.getName()); + e.addContextName(getName()); + throw e; + } + scope.registerConfiguration(configuration); + scopeIndex.put(configuration.getName(), scope); + configurations.put(configuration.getName(), configuration); // xcv + } else { + if (configurations.get(configuration.getName()) != null) { + throw new DuplicateNameException(configuration.getName()); + } + configurations.put(configuration.getName(), configuration); + } + + } + + public void registerListener(RuntimeEventListener listener) { + assert (listener != null) : "Listener cannot be null"; + listeners.add(listener); + } + + public void fireEvent(int eventType, Object message) throws EventException { + checkInit(); + if (eventType == SESSION_NOTIFY) { + // update context + eventContext.setIdentifier(HTTP_SESSION, message); + } else if (eventType == REQUEST_END) { + // be very careful with pooled threads, ensuring threadlocals are cleaned up + eventContext.clearIdentifier(HTTP_SESSION); + } + for (RuntimeEventListener listener : listeners) { + listener.onEvent(eventType, message); + } + } + + public InstanceContext getContext(String componentName) { + checkInit(); + assert (componentName != null) : "Name was null"; + ScopeContext scope = scopeIndex.get(componentName); + if (scope == null) { + return null; + } + return scope.getContext(componentName); + + } + + public Object getInstance(QualifiedName qName) throws TargetException { + return getInstance(qName, true); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + assert (qName != null) : "Name was null "; + // use the port name to get the context since entry points ports + ScopeContext scope = scopeIndex.get(qName.getPortName()); + if (scope == null) { + return null; + } + InstanceContext ctx = scope.getContext(qName.getPortName()); + if (!(ctx instanceof EntryPointContext)) { + TargetException e = new TargetException("Target not an entry point"); + e.setIdentifier(qName.getQualifiedName()); + e.addContextName(name); + throw e; + } + return ctx.getInstance(null, notify); + } + + public Object locateInstance(String qualifiedName) throws TargetException { + checkInit(); + QualifiedName qName = new QualifiedName(qualifiedName); + ScopeContext scope = scopeIndex.get(qName.getPartName()); + if (scope == null) { + TargetException e = new TargetException("Component not found"); + e.setIdentifier(qualifiedName); + e.addContextName(getName()); + throw e; + } + InstanceContext ctx = scope.getContext(qName.getPartName()); + try { + return ctx.getInstance(qName, true); + } catch (TargetException e) { + e.addContextName(getName()); + throw e; + } + } + + public Map<Scope, ScopeContext> getScopeContexts() { + initializeScopes(); + return immutableScopeContexts; + } + + // ---------------------------------- + // Abstract methods + // ---------------------------------- + + /** + * Registers a model object as autowirable + * + * @throws ContextInitException + */ + protected abstract void registerAutowire(Extensible model) throws ConfigurationException; + + // ---------------------------------- + // Protected methods + // ---------------------------------- + + /** + * Blocks until the module context has been initialized + */ + protected void checkInit() { + if (!initialized) { + try { + /* block until the module has initialized */ + boolean success = initializeLatch.await(DEFAULT_WAIT, TimeUnit.MILLISECONDS); + if (!success) { + throw new ContextInitException("Timeout waiting for module context to initialize"); + } + } catch (InterruptedException e) { // should not happen + } + } + + } + + protected void initializeScopes() { + if (scopeContexts == null) { + if (scopeStrategy == null) { + scopeStrategy = new DefaultScopeStrategy(); + } + scopeContexts = scopeStrategy.createScopes(eventContext); + immutableScopeContexts = Collections.unmodifiableMap(scopeContexts); + } + } + + /** + * Iterates through references and delegates to the configuration context to wire them to their targets + */ + protected void wireSource(RuntimeConfiguration source) { + Scope sourceScope = source.getScope(); + if (source.getSourceProxyFactories() != null) { + for (ProxyFactory sourceFactory : ((Map<String, ProxyFactory>) source.getSourceProxyFactories()).values()) { + QualifiedName targetName = sourceFactory.getProxyConfiguration().getTargetName(); + RuntimeConfiguration target = configurations.get(targetName.getPartName()); + if (target == null) { + ContextInitException e = new ContextInitException("Target not found"); + e.setIdentifier(targetName.getPartName()); + e.addContextName(source.getName()); + e.addContextName(name); + throw e; + } + // get the proxy chain for the target + ProxyFactory targetFactory = target.getTargetProxyFactory(sourceFactory.getProxyConfiguration().getTargetName() + .getPortName()); + if (targetFactory == null) { + ContextInitException e = new ContextInitException("No proxy factory found for service"); + e.setIdentifier(sourceFactory.getProxyConfiguration().getTargetName().getPortName()); + e.addContextName(target.getName()); + e.addContextName(source.getName()); + e.addContextName(name); + throw e; + } + boolean downScope = scopeStrategy.downScopeReference(sourceScope, target.getScope()); + configurationContext.wire(sourceFactory, targetFactory, target.getClass(), downScope, scopeContexts.get(target + .getScope())); + } + } + // wire invokers when the proxy only contains the target chain + if (source.getTargetProxyFactories() != null) { + for (ProxyFactory targetFactory : ((Map<String, ProxyFactory>) source.getTargetProxyFactories()).values()) { + configurationContext.wire(targetFactory, source.getClass(), scopeContexts.get(sourceScope)); + } + } + source.prepare(); + } + + /** + * Signals to target side of reference configurations to initialize + */ + protected void buildTarget(RuntimeConfiguration target) { + if (target.getTargetProxyFactories() != null) { + for (ProxyFactory targetFactory : ((Map<String, ProxyFactory>) target.getTargetProxyFactories()).values()) { + for (InvocationConfiguration iConfig : (Collection<InvocationConfiguration>) targetFactory + .getProxyConfiguration().getInvocationConfigurations().values()) { + iConfig.build(); + } + } + } + } + + protected void initializeProxies() throws ProxyInitializationException { + for (RuntimeConfiguration config : configurations.values()) { + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory sourceProxyFactory : (Collection<ProxyFactory>) config.getSourceProxyFactories().values()) { + sourceProxyFactory.initialize(); + } + } + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory targetProxyFactory : (Collection<ProxyFactory>) config.getTargetProxyFactories().values()) { + targetProxyFactory.initialize(); + } + } + } + } + + /** + * @see org.apache.tuscany.core.context.AggregateContext#getAggregate() + */ + public Aggregate getAggregate() { + return module; + } +}
\ No newline at end of file diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AggregateContextImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AggregateContextImpl.java new file mode 100644 index 0000000000..69e0b8edfc --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AggregateContextImpl.java @@ -0,0 +1,222 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.impl; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.context.AutowireResolutionException; +import org.apache.tuscany.core.context.ConfigurationContext; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.ScopeStrategy; +import org.apache.tuscany.core.context.ServiceNotFoundException; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.system.annotation.Autowire; +import org.apache.tuscany.model.assembly.Extensible; +import org.osoa.sca.ModuleContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceUnavailableException; + +/** + * The standard implementation of an aggregate context. Autowiring is performed by delegating to the parent context. + * + * @version $Rev$ $Date$ + */ +public class AggregateContextImpl extends AbstractAggregateContext implements ConfigurationContext, ModuleContext { + + // ---------------------------------- + // Fields + // ---------------------------------- + + @Autowire(required = false) + private AutowireContext autowireContext; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public AggregateContextImpl() { + super(); + eventContext = new EventContextImpl(); + } + + public AggregateContextImpl(String name, AggregateContext parent, ScopeStrategy strategy, EventContext ctx, + ConfigurationContext configCtx, MonitorFactory factory) { + super(name, parent, strategy, ctx, configCtx, factory); + } + + public AggregateContextImpl(String name, AggregateContext parent, AutowireContext autowireContext, ScopeStrategy strategy, + EventContext ctx, ConfigurationContext configCtx, MonitorFactory factory) { + super(name, parent, strategy, ctx, configCtx, factory); + this.autowireContext = autowireContext; + } + + // ---------------------------------- + // ModuleContext methods + // ---------------------------------- + + private String uri; + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public Object locateService(String qualifiedName) throws ServiceUnavailableException { + checkInit(); + QualifiedName qName = new QualifiedName(qualifiedName); + ScopeContext scope = scopeIndex.get(qName.getPartName()); + if (scope == null) { + throw new ServiceNotFoundException(qualifiedName); + } + InstanceContext ctx = scope.getContext(qName.getPartName()); + try { + Object o = ctx.getInstance(qName, true); + if (o == null) { + throw new ServiceUnavailableException(qualifiedName); + } + return o; + } catch (TargetException e) { + e.addContextName(getName()); + throw new ServiceUnavailableException(e); + } + } + + public ServiceReference createServiceReference(String serviceName) { + throw new UnsupportedOperationException(); + } + + public RequestContext getRequestContext() { + throw new UnsupportedOperationException(); + } + + public ServiceReference createServiceReferenceForSession(Object self) { + throw new UnsupportedOperationException(); + } + + public ServiceReference createServiceReferenceForSession(Object self, String serviceName) { + throw new UnsupportedOperationException(); + } + + public ServiceReference newSession(String serviceName) { + throw new UnsupportedOperationException(); + } + + public ServiceReference newSession(String serviceName, Object sessionId) { + throw new UnsupportedOperationException(); + } + + // ---------------------------------- + // AutowireContext methods + // ---------------------------------- + + public <T> T resolveInstance(Class<T> instanceInterface) throws AutowireResolutionException { + if (MonitorFactory.class.equals(instanceInterface)) { + return instanceInterface.cast(monitorFactory); + } else if (ConfigurationContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } else if (AutowireContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } + if (autowireContext != null) { + try { + return autowireContext.resolveInstance(instanceInterface); + } catch (AutowireResolutionException e) { + e.addContextName(getName()); + throw e; + } + } + return null; + } + + @Override + protected void registerAutowire(Extensible model) { + // this context only delegates autowiring + } + + // ---------------------------------- + // ConfigurationContext methods + // ---------------------------------- + + public void configure(Extensible model) throws ConfigurationException { + if (configurationContext != null) { + try { + configurationContext.configure(model); + } catch (ConfigurationException e) { + e.addContextName(getName()); + throw e; + } + } + } + + public void build(AggregateContext parent, Extensible model) throws BuilderConfigException { + if (configurationContext != null) { + try { + configurationContext.build(parent, model); + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + } + + public void wire(ProxyFactory sourceFactory, ProxyFactory targetFactory, Class targetType, boolean downScope, + ScopeContext targetScopeContext) throws BuilderConfigException { + if (configurationContext != null) { + try { + configurationContext.wire(sourceFactory, targetFactory, targetType, downScope, targetScopeContext); + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + } + + public void wire(ProxyFactory targetFactory, Class targetType, ScopeContext targetScopeContext) throws BuilderConfigException { + if (configurationContext != null) { + try { + configurationContext.wire(targetFactory, targetType, targetScopeContext); + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + } + + // ---------------------------------- + // InstanceContext methods + // ---------------------------------- + + public Object getImplementationInstance() throws TargetException { + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return this; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EntryPointContextImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EntryPointContextImpl.java new file mode 100644 index 0000000000..791ce6b8a5 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EntryPointContextImpl.java @@ -0,0 +1,112 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context.impl; + +import java.lang.reflect.InvocationHandler; + +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.ContextInitException; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EntryPointContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.invocation.jdk.JDKInvocationHandler; +import org.apache.tuscany.core.invocation.spi.ProxyCreationException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.message.MessageFactory; + +/** + * The default implementation of an entry point context + * + * @version $Rev$ $Date$ + */ +public class EntryPointContextImpl extends AbstractContext implements EntryPointContext { + + private MessageFactory messageFactory; + + private ProxyFactory proxyFactory; + + private Object target; + + private InvocationHandler invocationHandler; + + // a proxy implementing the service exposed by the entry point backed by the invocation handler + private Object proxy; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + /** + * Creates a new entry point + * + * @param name the entry point name + * @param proxyFactory the proxy factory containing the invocation chains for the entry point + * @param parentContext the containing aggregate of the entry point + * @param messageFactory a factory for generating invocation messages + * @throws ContextInitException if an error occurs creating the entry point + */ + public EntryPointContextImpl(String name, ProxyFactory proxyFactory, MessageFactory messageFactory) + throws ContextInitException { + super(name); + assert (proxyFactory != null) : "Proxy factory was null"; + assert (messageFactory != null) : "Message factory was null"; + this.proxyFactory = proxyFactory; + this.messageFactory = messageFactory; + invocationHandler = new JDKInvocationHandler(messageFactory, proxyFactory.getProxyConfiguration() + .getInvocationConfigurations()); + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public Object getInstance(QualifiedName qName) throws TargetException { + if (proxy == null) { + try { + proxy = proxyFactory.createProxy(); + } catch (ProxyCreationException e) { + TargetException te = new TargetException(e); + te.addContextName(getName()); + throw te; + } + } + return proxy; + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + public void start() throws ContextInitException { + lifecycleState = RUNNING; + } + + public void stop() throws CoreRuntimeException { + lifecycleState = STOPPED; + } + + // ---------------------------------- + // InstanceContext methods + // ---------------------------------- + + public Object getImplementationInstance() throws TargetException { + return invocationHandler; + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return getImplementationInstance(); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EventContextImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EventContextImpl.java new file mode 100644 index 0000000000..accf6b3030 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EventContextImpl.java @@ -0,0 +1,77 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.ScopeIdentifier; + +/** + * An implementation of an {@link org.apache.tuscany.core.context.EventContext} that handles event-to-thread associations using an + * <code>InheritableThreadLocal</code> + * + * @version $Rev$ $Date$ + */ +public class EventContextImpl implements EventContext { + + // @TODO design a proper propagation strategy for creating new threads + /* + * a map ( associated with the current thread) of scope identifiers keyed on the event context id type. the scope identifier + * may be a {@link ScopeIdentifier} or an opaque id + */ + private ThreadLocal<Map> eventContext = new InheritableThreadLocal(); + + public Object getIdentifier(Object type) { + Map map = eventContext.get(); + if (map == null) { + return null; + } + Object currentId = map.get(type); + if (currentId instanceof ScopeIdentifier) { + currentId = ((ScopeIdentifier) currentId).getIdentifier(); + // once we have accessed the id, replace the lazy wrapper + map.put(type, currentId); + } + return currentId; + } + + public void setIdentifier(Object type, Object identifier) { + Map map = eventContext.get(); + if (map == null) { + map = new HashMap(); + eventContext.set(map); + } + map.put(type, identifier); + } + + public void clearIdentifier(Object type) { + if (type == null) { + return; + } + Map map = eventContext.get(); + if (map != null) { + map.remove(type); + } + } + + public EventContextImpl() { + super(); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/ExternalServiceContextImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/ExternalServiceContextImpl.java new file mode 100644 index 0000000000..a73081ef66 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/ExternalServiceContextImpl.java @@ -0,0 +1,92 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context.impl; + +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.ExternalServiceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.invocation.spi.ProxyCreationException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; + +/** + * The default implementation of an external service context + * + * @version $Rev$ $Date$ + */ +public class ExternalServiceContextImpl extends AbstractContext implements ExternalServiceContext { + + private ProxyFactory targetProxyFactory; + + private ObjectFactory targetInstanceFactory; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + /** + * Creates an external service context + * + * @param name the name of the external service + * @param targetProxyFactory the factory which creates proxies implementing the configured service interface for the + * external service. There is always only one proxy factory as an external service is configured with one + * service + * @param targetInstanceFactory the object factory that creates an artifact capabile of communicating over the + * binding transport configured on the external service. The object factory may implement a caching strategy. + */ + public ExternalServiceContextImpl(String name, ProxyFactory targetProxyFactory, ObjectFactory targetInstanceFactory) { + super(name); + assert (targetProxyFactory != null) : "Target proxy factory was null"; + assert (targetInstanceFactory != null) : "Target instance factory was null"; + this.targetProxyFactory = targetProxyFactory; + this.targetInstanceFactory = targetInstanceFactory; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public Object getInstance(QualifiedName qName) throws TargetException { + try { + return targetProxyFactory.createProxy(); + // TODO do we cache the proxy, (assumes stateful capabilities will be provided in an interceptor) + } catch (ProxyCreationException e) { + TargetException te = new TargetException(e); + te.addContextName(getName()); + throw te; + } + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + public void start() throws CoreRuntimeException { + lifecycleState = RUNNING; + } + + public void stop() throws CoreRuntimeException { + lifecycleState = STOPPED; + } + + public Object getImplementationInstance() throws TargetException { + return targetInstanceFactory.getInstance(); + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return getImplementationInstance(); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeContext.java new file mode 100644 index 0000000000..449af4bdf8 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeContext.java @@ -0,0 +1,158 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.TargetException; + +/** + * Implements functionality common to scope contexts. + * <p> + * <b>NB: </b>Minimal synchronization is performed, particularly for initializing and destroying scopes, and it is + * assumed the scope container will block requests until these operations have completed. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractScopeContext extends AbstractContext implements ScopeContext{ + // ---------------------------------- + // Fields + // ---------------------------------- + + // The collection of runtime configurations for the scope + protected Map<String, RuntimeConfiguration<InstanceContext>> runtimeConfigurations = new ConcurrentHashMap(); + + // The event context the scope container is associated with + protected EventContext eventContext; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public AbstractScopeContext(EventContext eventContext) { + assert (eventContext != null) : "Event context was null"; + this.eventContext = eventContext; + } + + // ---------------------------------- + // Lifecycle methods + // --------------------------_-------- + + public synchronized void start() { + } + + public synchronized void stop() { + } + + + // ---------------------------------- + // Scope methods + // ---------------------------------- + + public void registerConfigurations(List<RuntimeConfiguration<InstanceContext>> configurations) { + for (RuntimeConfiguration<InstanceContext> configuration : configurations) { + runtimeConfigurations.put(configuration.getName(), configuration); + } + } + + public Object getInstance(QualifiedName qName) throws TargetException { + Object instance = null; + InstanceContext context = getContext(qName.getPartName()); + if (context == null) { + TargetException e = new TargetException("Target not found"); + e.setIdentifier(qName.getQualifiedName()); + throw e; + } + return context.getInstance(qName); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + //---------------------------------- + // InstanceContext methods + //---------------------------------- + + public Object getImplementationInstance() throws TargetException{ + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException{ + return this; + } + + // ---------------------------------- + // Protected methods + // ---------------------------------- + + protected EventContext getEventContext() { + return eventContext; + } + + /** + * Notfies instances that are associated with a context and configured to receive callbacks that the context is + * being destroyed in reverse order + * + * @param key the context key + */ + protected void notifyInstanceShutdown(Object key) { + InstanceContext[] contexts = getShutdownContexts(key); + if ((contexts == null) || (contexts.length < 1)) { + return; + } + // shutdown destroyable instances in reverse instantiation order + for (int i = contexts.length - 1; i >= 0; i--) { + InstanceContext context = contexts[i]; + + if (context.getLifecycleState() == Context.RUNNING) { + synchronized (context) { + context.setLifecycleState(Context.STOPPING); + removeContextByKey(context.getName(), key); + try { + context.stop(); + } catch (TargetException e) { + // TODO send a monitoring event + // log.error("Error releasing instance [" + context.getName() + "]",e); + } + } + } + } + } + + protected void checkInit() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope not running [" + lifecycleState + "]"); + } + } + + /** + * Returns an array of contexts that need to be notified of scope shutdown. The array must be in the order in which + * component contexts were created + */ + protected abstract InstanceContext[] getShutdownContexts(Object key); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeStrategy.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeStrategy.java new file mode 100644 index 0000000000..f89d09196d --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeStrategy.java @@ -0,0 +1,67 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import org.apache.tuscany.core.context.ScopeStrategy; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implements basic scope strategy functionality + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractScopeStrategy implements ScopeStrategy { + + public AbstractScopeStrategy() { + } + + /** + * Determines legal scope references according to standard SCA scope rules + * + * @param pReferrer the scope of the component making the reference + * @param pReferee the scope of the component being referred to + */ + public boolean downScopeReference(Scope pReferrer, Scope pReferee) { + if (pReferrer == Scope.UNDEFINED || pReferee == Scope.UNDEFINED) { + return false; + } + if (pReferee == pReferrer){ + return false; + }else if(pReferrer == Scope.INSTANCE){ + return false; + }else if(pReferee == Scope.INSTANCE){ + return true; + }else if (pReferrer == Scope.REQUEST && pReferee == Scope.SESSION){ + return false; + }else if (pReferrer == Scope.REQUEST && pReferee == Scope.MODULE){ + return false; +// }else if (pReferrer == Scope.SESSION && pReferee == Scope.REQUEST){ +// return true; + }else if (pReferrer == Scope.SESSION && pReferee == Scope.MODULE){ + return false; +// }else if (pReferrer == Scope.MODULE){ +// return true; + }else{ + return true; + } + //FIXME Jim this does not work with enumerations, what does it mean to have a scope <0? +// } else if ((pReferrer < 0) || (pReferee < 0)) { +// return false; +// } +// +// return (pReferrer > pReferee); +// return pReferrer != pReferee; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AggregateScopeContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AggregateScopeContext.java new file mode 100644 index 0000000000..19f554a625 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AggregateScopeContext.java @@ -0,0 +1,184 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.EventException; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.ScopeInitializationException; +import org.apache.tuscany.core.context.ScopeRuntimeException; +import org.apache.tuscany.core.context.TargetException; + +/** + * Manages the lifecycle of aggregate component contexts, i.e. contexts which contain child contexts + * + * @see org.apache.tuscany.core.context.AggregateContext + * @version $Rev$ $Date$ + */ +public class AggregateScopeContext extends AbstractContext implements ScopeContext { + + // ---------------------------------- + // Fields + // ---------------------------------- + + private EventContext eventContext; + + private List<RuntimeConfiguration<InstanceContext>> configs = new ArrayList(); + + // Aggregate component contexts in this scope keyed by name + private Map<String, AggregateContext> contexts = new ConcurrentHashMap(); + + // indicates if a module start event has been previously propagated so child contexts added after can be notified + private boolean moduleScopeStarted; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public AggregateScopeContext(EventContext eventContext) { + assert (eventContext != null) : "Event context was null"; + this.eventContext = eventContext; + name = "Aggregate Scope"; + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public void start() throws ScopeInitializationException { + for (RuntimeConfiguration<InstanceContext> configuration : configs) { + InstanceContext context = configuration.createInstanceContext(); + if (!(context instanceof AggregateContext)) { + ScopeInitializationException e = new ScopeInitializationException("Context not an aggregate type"); + e.addContextName(context.getName()); + throw e; + } + AggregateContext aggregateCtx = (AggregateContext) context; + aggregateCtx.start(); + contexts.put(aggregateCtx.getName(), aggregateCtx); + } + lifecycleState = RUNNING; + } + + public void stop() throws ScopeRuntimeException { + for (AggregateContext context : contexts.values()) { + context.stop(); + } + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void registerConfigurations(List<RuntimeConfiguration<InstanceContext>> configurations) { + this.configs = configurations; + } + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + assert (configuration != null) : "Configuration was null"; + configs.add(configuration); + if (lifecycleState == RUNNING) { + InstanceContext context = configuration.createInstanceContext(); + if (!(context instanceof AggregateContext)) { + ScopeInitializationException e = new ScopeInitializationException("Context not an aggregate type"); + e.setIdentifier(context.getName()); + throw e; + } + AggregateContext aggregateCtx = (AggregateContext) context; + aggregateCtx.start(); + if (moduleScopeStarted) { + aggregateCtx.fireEvent(EventContext.MODULE_START, null); + } + contexts.put(aggregateCtx.getName(), aggregateCtx); + } + } + + public boolean isCacheable() { + return false; + } + + public Object getInstance(QualifiedName qName) throws TargetException { + Object instance = null; + InstanceContext context = getContext(qName.getPartName()); + if (context == null) { + TargetException e = new TargetException("Component not found"); + e.setIdentifier(qName.getQualifiedName()); + throw e; + } + return context.getInstance(qName); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + public InstanceContext getContext(String ctxName) { + checkInit(); + return contexts.get(ctxName); + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + return getContext(ctxName); + } + + public void removeContext(String ctxName) throws ScopeRuntimeException { + InstanceContext context = contexts.remove(ctxName); + if (context != null) { + context.stop(); + } + } + + public void removeContextByKey(String ctxName, Object key) throws ScopeRuntimeException { + } + + public void onEvent(int type, Object message) throws EventException { + if (type == EventContext.MODULE_START) { + // track module starting so that aggregate contexts registered after the event are notified properly + moduleScopeStarted = true; + } else if (type == EventContext.MODULE_STOP) { + moduleScopeStarted = false; + } + // propagate events to child contexts + for (AggregateContext context : contexts.values()) { + context.fireEvent(type, message); + } + } + + public Object getImplementationInstance() throws TargetException{ + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException{ + return this; + } + + private void checkInit() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope not running [" + lifecycleState + "]"); + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/DefaultScopeStrategy.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/DefaultScopeStrategy.java new file mode 100644 index 0000000000..509eb7941f --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/DefaultScopeStrategy.java @@ -0,0 +1,52 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implements a {@link org.apache.tuscany.core.context.ScopeStrategy} for the default module scopes: stateless, request, session, + * and module. + * + * @version $Rev$ $Date$ + */ +public class DefaultScopeStrategy extends AbstractScopeStrategy { + + public DefaultScopeStrategy() { + } + + public Map<Scope,ScopeContext> createScopes(EventContext eventContext) { + ScopeContext moduleScope = new ModuleScopeContext(eventContext); + ScopeContext sessionScope = new HttpSessionScopeContext(eventContext); + ScopeContext requestScope = new RequestScopeContext(eventContext); + ScopeContext statelessScope = new StatelessScopeContext(eventContext); + ScopeContext aggregrateScope = new AggregateScopeContext(eventContext); + Map<Scope,ScopeContext> scopes = new HashMap(); + scopes.put(Scope.MODULE,moduleScope); + scopes.put(Scope.SESSION,sessionScope); + scopes.put(Scope.REQUEST,requestScope); + scopes.put(Scope.INSTANCE,statelessScope); + scopes.put(Scope.AGGREGATE,aggregrateScope); + return scopes; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/HttpSessionScopeContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/HttpSessionScopeContext.java new file mode 100644 index 0000000000..e1fcc4ab70 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/HttpSessionScopeContext.java @@ -0,0 +1,254 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.ScopeRuntimeException; +import org.apache.tuscany.core.context.SimpleComponentContext; + +/** + * An implementation of an HTTP session-scoped component container where each HTTP session is mapped to a context in the scope + * + * @version $Rev$ $Date$ + */ +public class HttpSessionScopeContext extends AbstractScopeContext implements RuntimeEventListener, LifecycleEventListener { + + // The collection of service component contexts keyed by session + private Map<Object, Map<String, InstanceContext>> contexts; + + // Stores ordered lists of contexts to shutdown keyed by session + private Map<Object, Queue<InstanceContext>> destroyableContexts; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public HttpSessionScopeContext(EventContext eventContext) { + super(eventContext); + setName("Http Session Scope"); + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED) { + throw new IllegalStateException("Scope container must be in UNINITIALIZED state"); + } + super.start(); + contexts = new ConcurrentHashMap(); + destroyableContexts = new ConcurrentHashMap(); + lifecycleState = RUNNING; + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope container in wrong state"); + } + super.stop(); + contexts = null; + contexts = null; + destroyableContexts = null; + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Listener methods + // ---------------------------------- + + public void onEvent(int type, Object key) { + checkInit(); + if (key == null) { + return; + } + if (type == EventContext.SESSION_END) { + notifyInstanceShutdown(key); + destroyComponentContext(key); + } + } + + // ---------------------------------- + // Scope methods + // ---------------------------------- + + public boolean isCacheable() { + return true; + } + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + runtimeConfigurations.put(configuration.getName(), configuration); + } + + public InstanceContext getContext(String ctxName) { + checkInit(); + if (ctxName == null) { + return null; + } + // try{ + Map<String, InstanceContext> ctxs = getSessionContext(); + if (ctxs == null) { + return null; + } + InstanceContext ctx = ctxs.get(ctxName); + if (ctx == null) { + // the configuration was added after the session had started, so create a context now and start it + RuntimeConfiguration<InstanceContext> configuration = runtimeConfigurations.get(ctxName); + if (configuration != null) { + ctx = configuration.createInstanceContext(); + ctx.addContextListener(this); + ctx.start(); + ctxs.put(ctx.getName(), ctx); + } + } + return ctx; + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + checkInit(); + if (key == null && ctxName == null) { + return null; + } + Map components = (Map) contexts.get(key); + if (components == null) { + return null; + } + return (InstanceContext) components.get(ctxName); + } + + public void removeContext(String ctxName) { + checkInit(); + Object key = getEventContext().getIdentifier(EventContext.HTTP_SESSION); + removeContextByKey(ctxName, key); + } + + public void removeContextByKey(String ctxName, Object key) { + checkInit(); + if (key == null || ctxName == null) { + return; + } + Map components = (Map) contexts.get(key); + if (components == null) { + return; + } + components.remove(ctxName); + Map definitions = contexts.get(key); + InstanceContext meta = (InstanceContext) definitions.get(ctxName); + destroyableContexts.get(key).remove(meta); + definitions.remove(ctxName); + } + + public void onInstanceCreate(Context context) throws ScopeRuntimeException { + checkInit(); + if (context instanceof SimpleComponentContext) { + // if destroyable, queue the context to have its component implementation instance released + if (((SimpleComponentContext) context).isDestroyable()) { + Object key = getEventContext().getIdentifier(EventContext.HTTP_SESSION); + Queue comps = destroyableContexts.get(key); + if (comps == null) { + ScopeRuntimeException e = new ScopeRuntimeException("Shutdown queue not found for key"); + e.setIdentifier(key.toString()); + throw e; + } + comps.add(context); + } + } + } + + /** + * Returns an array of {@link SimpleComponentContext}s representing components that need to be notified of scope shutdown or + * null if none found. + */ + protected InstanceContext[] getShutdownContexts(Object key) { + /* + * This method will be called from the Listener which is associated with a different thread than the request. So, just + * grab the key directly + */ + Queue queue = destroyableContexts.get(key); + if (queue != null) { + // create 0-length array since Queue.size() has O(n) traversal + return (InstanceContext[]) queue.toArray(new InstanceContext[0]); + } else { + return null; + } + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + /** + * Returns and, if necessary, creates a context for the current sesion + */ + private Map<String, InstanceContext> getSessionContext() throws CoreRuntimeException { + Object key = getEventContext().getIdentifier(EventContext.HTTP_SESSION); + if (key == null) { + throw new ScopeRuntimeException("Session key not set in request context"); + } + Map m = contexts.get(key); + if (m != null) { + return m; // already created, return + } + Map<String, InstanceContext> sessionContext = new ConcurrentHashMap(runtimeConfigurations.size()); + for (RuntimeConfiguration<InstanceContext> config : runtimeConfigurations.values()) { + InstanceContext context = null; + context = config.createInstanceContext(); + context.addContextListener(this); + context.start(); + sessionContext.put(context.getName(), context); + } + + Queue shutdownQueue = new ConcurrentLinkedQueue(); + contexts.put(key, sessionContext); + destroyableContexts.put(key, shutdownQueue); + // initialize eager components. Note this cannot be done when we initially create each context since a component may + // contain a forward reference to a component which has not been instantiated + for (InstanceContext context : sessionContext.values()) { + if (context instanceof SimpleComponentContext) { + SimpleComponentContext simpleCtx = (SimpleComponentContext) context; + if (simpleCtx.isEagerInit()) { + // Get the instance and perform manual shutdown registration to avoid a map lookup + context.getInstance(null, false); + if (simpleCtx.isDestroyable()) { + shutdownQueue.add(context); + } + } + } + } + return sessionContext; + } + + /** + * Removes the components associated with an expiring context + */ + private void destroyComponentContext(Object key) { + contexts.remove(key); + destroyableContexts.remove(key); + } + +}
\ No newline at end of file diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/ModuleScopeContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/ModuleScopeContext.java new file mode 100644 index 0000000000..00f2747fae --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/ModuleScopeContext.java @@ -0,0 +1,182 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.SimpleComponentContext; + +/** + * Manages component contexts whose implementations are module scoped + * + * @version $Rev$ $Date$ + */ +public class ModuleScopeContext extends AbstractScopeContext implements RuntimeEventListener, LifecycleEventListener { + + // ---------------------------------- + // Fields + // ---------------------------------- + + // Component contexts in this scope keyed by name + private Map<String, InstanceContext> componentContexts; + + private Queue<SimpleComponentContext> destroyableContexts; + + // ---------------------------------- + // Constructor + // ---------------------------------- + + public ModuleScopeContext(EventContext eventContext) { + super(eventContext); + setName("Module Scope"); + } + + // ---------------------------------- + // Listener methods + // ---------------------------------- + + public void onEvent(int type, Object key) { + if (type == EventContext.MODULE_START) { + lifecycleState = RUNNING; + initComponentContexts(); + } else if (type == EventContext.MODULE_STOP) { + notifyInstanceShutdown(key); + } + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED state [" + lifecycleState + "]"); + } + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + super.stop(); + componentContexts = null; + destroyableContexts = null; + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public boolean isCacheable() { + return true; + } + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + runtimeConfigurations.put(configuration.getName(), configuration); + if (lifecycleState == RUNNING) { + componentContexts.put(configuration.getName(), configuration.createInstanceContext()); + } + } + + public InstanceContext getContext(String ctxName) { + checkInit(); + return componentContexts.get(ctxName); + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + checkInit(); + return componentContexts.get(ctxName); + } + + public void removeContext(String ctxName) { + checkInit(); + Object component = componentContexts.remove(ctxName); + if (component != null) { + destroyableContexts.remove(component); + } + } + + public void removeContextByKey(String ctxName, Object key) { + checkInit(); + removeContext(ctxName); + } + + public void onInstanceCreate(Context context) { + checkInit(); + if (context instanceof SimpleComponentContext) { + SimpleComponentContext serviceContext = (SimpleComponentContext) context; + // Queue the context to have its implementation instance released if destroyable + if (serviceContext.isDestroyable()) { + destroyableContexts.add(serviceContext); + } + } + } + + /** + * Returns an array of {@link SimpleComponentContext}s representing components that need to be notified of scope shutdown. + */ + protected InstanceContext[] getShutdownContexts(Object key) { + if (destroyableContexts != null) { + // create 0-length array since Queue.size() has O(n) traversal + return (InstanceContext[]) destroyableContexts.toArray(new InstanceContext[0]); + } else { + return null; + } + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + private synchronized void initComponentContexts() throws CoreRuntimeException { + if (componentContexts == null) { + componentContexts = new ConcurrentHashMap(); + destroyableContexts = new ConcurrentLinkedQueue(); + for (RuntimeConfiguration<InstanceContext> config : runtimeConfigurations.values()) { + InstanceContext context = config.createInstanceContext(); + context.addContextListener(this); + context.start(); + componentContexts.put(context.getName(), context); + } + // Initialize eager contexts. Note this cannot be done when we initially create each context since a component may + // contain a forward reference to a component which has not been instantiated + for (InstanceContext context : componentContexts.values()) { + if (context instanceof SimpleComponentContext) { + SimpleComponentContext simpleCtx = (SimpleComponentContext) context; + if (simpleCtx.isEagerInit()) { + // perform silent creation and manual shutdown registration + simpleCtx.getInstance(null, false); + if (simpleCtx.isDestroyable()) { + destroyableContexts.add(simpleCtx); + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/RequestScopeContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/RequestScopeContext.java new file mode 100644 index 0000000000..deed3e2dee --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/RequestScopeContext.java @@ -0,0 +1,224 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.SimpleComponentContext; + +/** + * An implementation of a request-scoped component container. + * + * @version $Rev$ $Date$ + */ +public class RequestScopeContext extends AbstractScopeContext implements RuntimeEventListener, LifecycleEventListener { + + // ---------------------------------- + // Fields + // ---------------------------------- + + // A collection of service component contexts keyed by thread. Note this could have been implemented with a ThreadLocal but + // using a Map allows finer-grained concurrency. + private Map<Object, Map<String, InstanceContext>> contextMap; + + // stores ordered lists of contexts to shutdown for each thread. + private Map<Object, Queue> destroyComponents; + + // ---------------------------------- + // Constructor + // ---------------------------------- + + public RequestScopeContext(EventContext eventContext) { + super(eventContext); + setName("Request Scope"); + } + + // ---------------------------------- + // Listener methods + // ---------------------------------- + + public void onEvent(int type, Object key) { + checkInit(); + /* clean up current context for pooled threads */ + if (type == EventContext.REQUEST_END) { + getEventContext().clearIdentifier(EventContext.HTTP_SESSION); + notifyInstanceShutdown(Thread.currentThread()); + destroyContext(); + } + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED state [" + lifecycleState + "]"); + } + super.start(); + contextMap = new ConcurrentHashMap(); + destroyComponents = new ConcurrentHashMap(); + lifecycleState = RUNNING; + + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + super.stop(); + contextMap = null; + destroyComponents = null; + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public boolean isCacheable() { + return true; + } + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + runtimeConfigurations.put(configuration.getName(), configuration); + } + + public InstanceContext getContext(String ctxName) { + checkInit(); + Map<String, InstanceContext> contexts = getComponentContexts(); + InstanceContext ctx = contexts.get(ctxName); + if (ctx == null){ + // check to see if the configuration was added after the request was started + RuntimeConfiguration<InstanceContext> configuration = runtimeConfigurations.get(ctxName); + if (configuration != null) { + ctx = configuration.createInstanceContext(); + ctx.addContextListener(this); + ctx.start(); + contexts.put(ctx.getName(), ctx); + } + } + return ctx; + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + checkInit(); + if (key == null) { + return null; + } + Map<String, InstanceContext> components = (Map) contextMap.get(key); + if (components == null) { + return null; + } + return components.get(ctxName); + } + + public void removeContext(String ctxName) { + checkInit(); + removeContextByKey(ctxName, Thread.currentThread()); + } + + public void removeContextByKey(String ctxName, Object key) { + checkInit(); + if (key == null || ctxName == null) { + return; + } + Map components = (Map) contextMap.get(key); + if (components == null) { + return; + } + components.remove(ctxName); + Map<String, InstanceContext> contexts = (Map) contextMap.get(key); + // no synchronization for the following two operations since the request + // context will not be shutdown before the second call is processed + InstanceContext context = contexts.get(ctxName); + destroyComponents.get(key).remove(context); + } + + public void onInstanceCreate(Context context) { + checkInit(); + if (context instanceof SimpleComponentContext) { + // Queue the context to have its implementation instance released if destroyable + if (((SimpleComponentContext) context).isDestroyable()) { + Queue collection = destroyComponents.get(Thread.currentThread()); + collection.add(context); + } + } + } + + /** + * Returns an array of {@link SimpleComponentContext}s representing components that need to be notified of scope shutdown. + */ + protected InstanceContext[] getShutdownContexts(Object key) { + checkInit(); + Queue queue = destroyComponents.get(Thread.currentThread()); + if (queue != null) { + // create 0-length array since Queue.size() has O(n) traversal + return (InstanceContext[]) queue.toArray(new InstanceContext[0]); + } else { + return null; + } + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + private void destroyContext() { + // TODO uninitialize all request-scoped components + contextMap.remove(Thread.currentThread()); + destroyComponents.remove(Thread.currentThread()); + } + + /** + * Initializes ServiceComponentContexts for the current request. + * <p> + * TODO This eagerly creates all component contexts, even if the component is never accessed during the request. This method + * should be profiled to determine if lazy initialization is more performant + * <p> + * TODO Eager initialization is not performed for request-scoped components + */ + + private Map<String, InstanceContext> getComponentContexts() throws CoreRuntimeException { + Map contexts = (Map) contextMap.get(Thread.currentThread()); + if (contexts == null) { + contexts = new ConcurrentHashMap(); + Queue shutdownQueue = new ConcurrentLinkedQueue(); + for (RuntimeConfiguration<InstanceContext> config : runtimeConfigurations.values()) { + InstanceContext context = null; + context = config.createInstanceContext(); + context.addContextListener(this); + context.start(); + contexts.put(context.getName(), context); + } + contextMap.put(Thread.currentThread(), contexts); + destroyComponents.put(Thread.currentThread(), shutdownQueue); + } + return contexts; + } + +}
\ No newline at end of file diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/StatelessScopeContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/StatelessScopeContext.java new file mode 100644 index 0000000000..8b12f8b183 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/StatelessScopeContext.java @@ -0,0 +1,145 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.RuntimeEventListener; + +/** + * A container that manages stateless components. + * + * @version $Rev$ $Date$ + */ +public class StatelessScopeContext extends AbstractScopeContext implements RuntimeEventListener, LifecycleEventListener { + + // ---------------------------------- + // Fields + // ---------------------------------- + + // Component contexts keyed by name + private Map<String, InstanceContext> contextMap; + + // ---------------------------------- + // Constructor + // ---------------------------------- + + public StatelessScopeContext(EventContext eventContext) { + super(eventContext); + setName("Stateless Scope"); + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED state [" + lifecycleState + "]"); + } + super.start(); + lifecycleState = RUNNING; + prepare(); + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + super.stop(); + contextMap = null; + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + runtimeConfigurations.put(configuration.getName(), configuration); + if (lifecycleState == RUNNING) { + contextMap.put(configuration.getName(), configuration.createInstanceContext()); + } + + } + + public void onEvent(int type, Object key) { + // do nothing + } + + public boolean isCacheable() { + return true; + } + + public InstanceContext getContext(String ctxName) { + return contextMap.get(ctxName); + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + return getContext(ctxName); + } + + public void removeContext(String ctxName) { + removeContextByKey(ctxName, null); + } + + public void removeContextByKey(String ctxName, Object key) { + contextMap.remove(ctxName); + } + + /** + * Always returns null since stateless components cannot be shutdown + */ + protected InstanceContext[] getShutdownContexts(Object key) { + return null; + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + public void onInstanceCreate(Context component) { + // do nothing + } + + private void prepare() throws CoreRuntimeException { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope not in INITIALIZED state [" + lifecycleState + "]"); + } + if (contextMap == null) { + contextMap = new ConcurrentHashMap(); + for (RuntimeConfiguration<InstanceContext> config : runtimeConfigurations.values()) { + for (int i = 0; i < runtimeConfigurations.size(); i++) { + InstanceContext context = null; + context = config.createInstanceContext(); + context.addContextListener(this); + context.start(); + contextMap.put(context.getName(), context); + } + + } + } + } + +}
\ No newline at end of file diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/HTTPSessionExpirationListener.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/HTTPSessionExpirationListener.java new file mode 100644 index 0000000000..923b9fb941 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/HTTPSessionExpirationListener.java @@ -0,0 +1,62 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.webapp; + +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.EventContext; + +/** + * Cleans up resources used by expired sessions + * + * @version $Rev$ $Date$ + */ +public class HTTPSessionExpirationListener implements HttpSessionListener { + // ---------------------------------- + // Constructors + // ---------------------------------- + + public HTTPSessionExpirationListener() { + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void sessionCreated(HttpSessionEvent event) { + // do nothing since sessions are lazily created in {@link + // org.apache.tuscany.tomcat.webapp.listener.RequestFilter} + } + + public void sessionDestroyed(HttpSessionEvent event) { + TuscanyWebAppRuntime tuscanyRuntime = null; + try { + tuscanyRuntime = (TuscanyWebAppRuntime) event.getSession().getServletContext().getAttribute( + TuscanyWebAppRuntime.class.getName()); + tuscanyRuntime.start(); + + // End the session + AggregateContext context = tuscanyRuntime.getModuleComponentContext(); + context.fireEvent(EventContext.SESSION_END, event.getSession()); + } finally { + if (tuscanyRuntime != null) + tuscanyRuntime.stop(); + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/LazyHTTPSessionId.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/LazyHTTPSessionId.java new file mode 100644 index 0000000000..186f35df14 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/LazyHTTPSessionId.java @@ -0,0 +1,56 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.webapp; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.tuscany.core.context.ScopeIdentifier; + +/** + * Implements a <code>ScopeIdentifier</code> for a Servlet-based transport. + * Wraps an <code>HttpServletRequest</code> so that the session id associated + * with the current request may be lazily retrieved by the module context - i.e. + * if a session context or session-scoped component is not accessed, no session + * is created. + * + * @version $Rev$ $Date$ + */ +public class LazyHTTPSessionId implements ScopeIdentifier { + + private HttpServletRequest request; + + //---------------------------------- + // Constructors + //---------------------------------- + + public LazyHTTPSessionId(HttpServletRequest request) { + this.request = request; + } + + //---------------------------------- + // Methods + //---------------------------------- + + /** + * Returns the session identifier + * + * @see org.apache.tuscany.core.context.ScopeIdentifier#getIdentifier() + */ + public Object getIdentifier() { + return request.getSession(true); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyRequestFilter.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyRequestFilter.java new file mode 100644 index 0000000000..8e92c9ebd4 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyRequestFilter.java @@ -0,0 +1,107 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.webapp; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.EventContext; + +/** + * Notifies the {@link org.apache.tuscany.core.context.AggregateContext} of web request start and end events as well as setting up the + * current session context. The latter is done using lazy Servlet-based session retrieval. The filter fires a session + * start event, passing a <tt>LazyServletSessionId</tt> as the session id. The <tt>LazyServletSessionId</tt> is a + * wrapper for the servlet request which may be called by the <tt>ModuleContext</tt> to retrieve the session id + * lazily. + * + * @version $Rev$ $Date$ + */ +public class TuscanyRequestFilter implements Filter { + private TuscanyWebAppRuntime tuscanyRuntime; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public TuscanyRequestFilter() { + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void init(FilterConfig filterConfig) throws ServletException { + + // Get the Tuscany runtime from the servlet context + tuscanyRuntime = (TuscanyWebAppRuntime) filterConfig.getServletContext().getAttribute( + TuscanyWebAppRuntime.class.getName()); + } + + public void destroy() { + } + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, + IOException { + // Get the module component context from the tuscany runtime + AggregateContext context = tuscanyRuntime.getModuleComponentContext(); + try { + + // Start the SCA implementation + tuscanyRuntime.start(); + + // Handle a request + if (request instanceof HttpServletRequest) { + if (((HttpServletRequest) request).getSession(false) != null) { + + // A session is already active + context.fireEvent(EventContext.SESSION_NOTIFY, ((HttpServletRequest) request).getSession(true)); + } else { + // Create a lazy wrapper since a session is not yet active + context.fireEvent(EventContext.SESSION_NOTIFY, new LazyHTTPSessionId((HttpServletRequest) request)); + } + } else { + context.fireEvent(EventContext.SESSION_NOTIFY, request); + } + // Start processing the request + context.fireEvent(EventContext.REQUEST_START, request); + // Dispatch to the next filter + filterChain.doFilter(request, response); + } catch (Exception e) { + throw new ServletException(e); + + } finally { + try { + // End processing the request + context.fireEvent(EventContext.REQUEST_END, request); + // Stop the SCA implementation + tuscanyRuntime.stop(); + } catch (Exception e) { + throw new ServletException(e); + } + } + + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyWebAppRuntime.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyWebAppRuntime.java new file mode 100644 index 0000000000..3b9801a811 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyWebAppRuntime.java @@ -0,0 +1,59 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.webapp; + +import org.apache.tuscany.core.context.AggregateContext; +import org.osoa.sca.ModuleContext; +import org.osoa.sca.SCA; + +/** + * An implementation of the SCA runtime for use in a Web app + * + * @version $Rev$ $Date$ + */ +public class TuscanyWebAppRuntime extends SCA { + private AggregateContext moduleComponentContext; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public TuscanyWebAppRuntime(AggregateContext moduleComponentContext) { + this.moduleComponentContext = moduleComponentContext; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + /** + * Returns the module component context associated with this runtime + */ + public AggregateContext getModuleComponentContext() { + return moduleComponentContext; + } + + public void start() { + // Associate it with the current thread + setModuleContext((ModuleContext) moduleComponentContext); + } + + public void stop() { + setModuleContext(null); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java new file mode 100644 index 0000000000..d2b95ae70e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java @@ -0,0 +1,17 @@ +package org.apache.tuscany.core.injection; + +/** + * Performs an invocation on an instance + * + * @version $Rev$ $Date$ + * @see MethodEventInvoker + */ +public interface EventInvoker<T> { + + /** + * Performs the invocation on a given instance + * + * @throws ObjectCallbackException + */ + void invokeEvent(T instance) throws ObjectCallbackException; +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/FactoryInitException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/FactoryInitException.java new file mode 100644 index 0000000000..e9573d4a4e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/FactoryInitException.java @@ -0,0 +1,27 @@ +package org.apache.tuscany.core.injection; + +/** + * Denotes an exception initializing an object factory + * + * @version $Rev$ $Date$ + */ +public class FactoryInitException extends InjectionRuntimeException { + + public FactoryInitException(String message, Throwable cause) { + super(message, cause); + } + + public FactoryInitException(String message) { + super(message); + } + + public FactoryInitException(Throwable cause) { + super(cause); + } + + public FactoryInitException() { + super(); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java new file mode 100644 index 0000000000..c48f620a3f --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java @@ -0,0 +1,45 @@ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.Field; + +import org.apache.tuscany.core.builder.ObjectFactory; + +/** + * Injects a value created by an {@link ObjectFactory} on a given field + * + * @version $Rev$ $Date$ + */ +public class FieldInjector<T> implements Injector<T> { + + private final Field field; + + private final ObjectFactory<?> objectFactory; + + // //---------------------------------- + // Constructors + // ---------------------------------- + + /** + * 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.objectFactory = objectFactory; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + /** + * 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/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java new file mode 100644 index 0000000000..ac8b09eab2 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java @@ -0,0 +1,29 @@ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.common.TuscanyRuntimeException; + +/** + * Root unchecked exception for the injection package + * + * @version $Rev$ $Date$ + */ +public abstract class InjectionRuntimeException extends TuscanyRuntimeException { + + public InjectionRuntimeException() { + super(); + } + + public InjectionRuntimeException(String message) { + super(message); + } + + public InjectionRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public InjectionRuntimeException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/Injector.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/Injector.java new file mode 100644 index 0000000000..013b1c5874 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/Injector.java @@ -0,0 +1,17 @@ +package org.apache.tuscany.core.injection; + +/** + * Implementations inject a pre-configured value on an instance + * + * @version $Rev$ $Date$ + * @see MethodInjector + * @see FieldInjector + */ +public interface Injector<T> { + + /** + * Inject a value on the given instance + */ + void inject(T instance) throws ObjectCreationException; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java new file mode 100644 index 0000000000..08dd4cd124 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java @@ -0,0 +1,39 @@ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Performs an invocation on a method of a given instance + * + * @version $Rev$ $Date$ + */ +public class MethodEventInvoker<T> implements EventInvoker<T> { + private final Method method; + + //---------------------------------- + // Constructors + //---------------------------------- + + /** + * Intantiates an invoker for the given method + */ + public MethodEventInvoker(Method method) { + this.method = method; + } + + //---------------------------------- + // Methods + //---------------------------------- + + public void invokeEvent(T instance) throws ObjectCallbackException { + try { + method.invoke(instance, (Object[]) null); + } catch (IllegalAccessException e) { + throw new AssertionError("Method is not accessible [" + method + "]"); + } catch (InvocationTargetException e) { + throw new ObjectCallbackException("Exception thrown by callback method [" + method + "]", e); + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java new file mode 100644 index 0000000000..55ea7bae5f --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java @@ -0,0 +1,30 @@ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.core.builder.ObjectFactory; + +/** + * Injects a value created by an {@link 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) { + this.method = method; + this.objectFactory = objectFactory; + } + + public void inject(T instance) throws ObjectCreationException { + try { + method.invoke(instance, new Object[]{objectFactory.getInstance()}); + } catch (IllegalAccessException e) { + throw new AssertionError("Method is not accessible [" + method + "]"); + } catch (InvocationTargetException e) { + throw new ObjectCreationException("Exception thrown by setter [" + method + "]", e); + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/NullEventInvoker.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/NullEventInvoker.java new file mode 100644 index 0000000000..23599bae0e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/NullEventInvoker.java @@ -0,0 +1,14 @@ +package org.apache.tuscany.core.injection; + +/** + * A no-op invoker + * + * @version $Rev$ $Date$ + */ +public final class NullEventInvoker<T> implements EventInvoker<T> { + public static final EventInvoker<?> NULL_INVOKER = new NullEventInvoker(); + + public void invokeEvent(T instance) { + // does nothing + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java new file mode 100644 index 0000000000..b428c31f4f --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java @@ -0,0 +1,26 @@ +package org.apache.tuscany.core.injection; + +/** + * Denotes an error when invoking on an object + * + * @version $Rev$ $Date$ + */ +public class ObjectCallbackException extends InjectionRuntimeException { + + public ObjectCallbackException() { + super(); + } + + public ObjectCallbackException(String message) { + super(message); + } + + public ObjectCallbackException(String message, Throwable cause) { + super(message, cause); + } + + public ObjectCallbackException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ObjectCreationException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ObjectCreationException.java new file mode 100644 index 0000000000..338b841c49 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ObjectCreationException.java @@ -0,0 +1,27 @@ +package org.apache.tuscany.core.injection; + +/** + * Denotes an error creating a new object instance + * + * @version $Rev$ $Date$ + */ +public class ObjectCreationException extends InjectionRuntimeException { + + public ObjectCreationException() { + super(); + } + + public ObjectCreationException(String message) { + super(message); + } + + public ObjectCreationException(String message, Throwable cause) { + super(message, cause); + } + + public ObjectCreationException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java new file mode 100644 index 0000000000..e3e1874b1e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java @@ -0,0 +1,75 @@ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.List; + +import org.apache.tuscany.core.builder.ObjectFactory; + +/** + * Creates new instances of a Java class, calling a given set of injectors to configure the instance + * + * @version $Rev$ $Date$ + * @see Injector + */ +public class PojoObjectFactory<T> implements ObjectFactory<T> { + + // ---------------------------------- + // Constants + // ---------------------------------- + + private static final ObjectFactory[] NO_INIT_PARAM = {}; + + private static final List<Injector> NO_SETTER_PARAM = Collections.EMPTY_LIST; + + // ---------------------------------- + // Fields + // ---------------------------------- + + private final Constructor<T> ctr; + + private final ObjectFactory<?>[] initParamsArray; + + private final List<Injector> setters; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public PojoObjectFactory(Constructor<T> ctr, List<ObjectFactory> initParams, List<Injector> setters) { + this.ctr = ctr; + if (initParams != null && initParams.size() > 0) { + initParamsArray = initParams.toArray(new ObjectFactory[initParams.size()]); + } else { + initParamsArray = NO_INIT_PARAM; + } + this.setters = setters != null ? setters : NO_SETTER_PARAM; + } // ---------------------------------- + + // Methods + // ---------------------------------- + + public T getInstance() throws ObjectCreationException { + Object[] initargs = new Object[initParamsArray.length]; + // create the constructor arg array + for (int i = 0; i < initParamsArray.length; i++) { + ObjectFactory<?> objectFactory = initParamsArray[i]; + initargs[i] = objectFactory.getInstance(); + } + try { + T instance = ctr.newInstance(initargs); + // interate through the injectors and inject the instance + for (Injector setter : setters) { + setter.inject(instance); + } + return instance; + } catch (InstantiationException e) { + throw new AssertionError("Class is not instantiable [" + ctr.getDeclaringClass().getName() + "]"); + } catch (IllegalAccessException e) { + throw new AssertionError("Constructor is not accessible [" + ctr + "]"); + } catch (InvocationTargetException e) { + throw new ObjectCreationException("Exception thrown by constructor [" + ctr + "]", e); + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ReferenceTargetFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ReferenceTargetFactory.java new file mode 100644 index 0000000000..f84c5b7ed1 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/ReferenceTargetFactory.java @@ -0,0 +1,133 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.model.assembly.Component; +import org.apache.tuscany.model.assembly.ConfiguredReference; +import org.apache.tuscany.model.assembly.ConfiguredService; +import org.apache.tuscany.model.assembly.EntryPoint; +import org.apache.tuscany.model.assembly.ExternalService; + +/** + * Returns a direct reference to a target service, i.e. the factory avoids creating proxies and returns the actual + * target instance + * + * @version $Rev$ $Date$ + */ +public class ReferenceTargetFactory<T> implements ObjectFactory<T> { + + private AggregateContext parentContext; + + // the SCDL name of the target component/service for this reference + private String targetName; + + private QualifiedName targetComponentName; + + // the reference target is in another module + private boolean interModule; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + /** + * Constructs a reference object factory from a configured reference on a type + */ + public ReferenceTargetFactory(ConfiguredReference reference, AggregateContext parentContext) + throws FactoryInitException { + // FIXME how to handle a reference that is a list - may take different proxy factories for each entry + assert (reference != null) : "Reference was null"; + assert (parentContext != null) : "Parent context was null"; + + this.parentContext = parentContext; + // targetName = reference.getReference().getName(); + ConfiguredService targetService = reference.getTargetConfiguredServices().get(0); + if (targetService.getAggregatePart() instanceof ExternalService) { + targetName = ((ExternalService) targetService.getAggregatePart()).getName(); + } else if (targetService.getAggregatePart() instanceof Component) { + Component targetComponent = (Component) targetService.getAggregatePart(); + targetName = targetComponent.getName(); + } else if (targetService.getAggregatePart() instanceof EntryPoint) { + targetName = ((EntryPoint) targetService.getAggregatePart()).getName(); + } else if (targetService.getAggregatePart() == null) { + // FIXME not correct + if (targetService.getService() == null) { + throw new FactoryInitException("No target service specified"); + } + targetName = targetService.getService().getName(); + } else { + FactoryInitException fie = new FactoryInitException("Unknown reference target type"); + fie.setIdentifier(reference.getReference().getName()); + throw fie; + } + } + + /** + * Reference source is an external service, target is in another module + * + * @param service + * @param parentContext + * @throws FactoryInitException + */ + public ReferenceTargetFactory(String targetName, AggregateContext parentContext) throws FactoryInitException { + //assert (service != null) : "Service was null"; + assert (parentContext != null) : "Parent context was null"; + interModule = true; // an external service with a reference target in another module + this.targetName = targetName;// service.getAggregatePart().getName(); + targetComponentName = new QualifiedName(targetName); + this.parentContext = parentContext; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public T getInstance() throws ObjectCreationException { + if (interModule) { + // only return entry points since this is an inter-module wire + Object o = parentContext.getInstance(targetComponentName); + if (o != null) { + return (T) o; + } else { + // walk up the hierarchy of aggregate contexts + AggregateContext ctx = parentContext; + do { + if (ctx == null) { + break; // reached top of context hierarchy + } + InstanceContext compContext = ctx.getContext(targetComponentName.getPartName()); + if (compContext != null) { + o = compContext.getInstance(targetComponentName); + if (o != null) { + return (T) o; + } + } + ctx = ctx.getParent(); + } while (ctx != null); + TargetException e= new TargetException("Target reference not found"); + e.setIdentifier(targetName); + throw e; + } + } else { + // the target is in the same module, so just locate it + return (T) parentContext.locateInstance(targetName); + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/SDOObjectFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/SDOObjectFactory.java new file mode 100644 index 0000000000..8147fa0d51 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/SDOObjectFactory.java @@ -0,0 +1,37 @@ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.core.builder.ObjectFactory; + +import commonj.sdo.DataObject; +import commonj.sdo.helper.CopyHelper; + +/** + * Creates new instances of an SDO + * + * @version $Rev$ $Date$ + */ +public class SDOObjectFactory implements ObjectFactory<DataObject> { + + private DataObject dataObject; + + //---------------------------------- + // Constructors + //---------------------------------- + + public SDOObjectFactory(DataObject dataObject) { + this.dataObject = dataObject; + } + + //---------------------------------- + // Methods + //---------------------------------- + + public DataObject getInstance() throws ObjectCreationException { + return CopyHelper.INSTANCE.copy(dataObject); + } + + public void releaseInstance(DataObject instance) { + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java new file mode 100644 index 0000000000..9f46357086 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java @@ -0,0 +1,29 @@ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.core.builder.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; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SingletonObjectFactory(T instance) { + this.instance = instance; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public T getInstance() { + return instance; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/Interceptor.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/Interceptor.java new file mode 100644 index 0000000000..40137f9b10 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/Interceptor.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation; + +import org.apache.tuscany.core.message.Message; + +/** + * Synchronous, around-style mediation associated with a client- or target- side invocation. + * + * @version $Rev$ $Date$ + */ +public interface Interceptor { + + /** + * Process a synchronous invocation. + * + * @param msg the request Message for the invocation + * @return the response Message from the invocation + */ + Message invoke(Message msg); + + /** + * Sets the next interceptor. + * + * @param next + */ + void setNext(Interceptor next); +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationConfiguration.java new file mode 100644 index 0000000000..2c5e61a8a1 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationConfiguration.java @@ -0,0 +1,279 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.core.invocation.impl.MessageChannelImpl; +import org.apache.tuscany.core.invocation.impl.MessageDispatcher; +import org.apache.tuscany.core.invocation.impl.RequestResponseInterceptor; + +/** + * Contains a source- or target-side invocation pipeline for a service operation. Source and target invocation pipelines + * are "bridged" together by a set of wire builders with the source-side holding references to the target. + * <p> + * A set of invocation configurations are used by a {@link org.apache.tuscany.core.invocation.spi.ProxyFactory} to + * create service proxies. + * <p> + * Invocation configurations must contain at least one interceptor and may have 0 to N handlers. Handlers process an + * invocation request or response in a one-way fashion. A typical invocation sequence where interceptors and handlers + * are configured for both the source and target-side will proceed as follows: + * <ol> + * <li>The first source interceptor will be called with a message, which will in turn invoke the next interceptor in + * the chain + * <li>The last source interceptor, which must be of type + * {@link org.apache.tuscany.core.invocation.impl.RequestResponseInterceptor} if there are handlers present, will be + * invoked. The RR interceptor will in turn pass the message to a + * {@link org.apache.tuscany.core.invocation.MessageChannel} which will invoke all source-side request handlers. + * <li> The RR interceptor will then invoke the target-side request <tt>MessageChannel</tt>. + * <li> The last source-side handler, an instance of + * {@link org.apache.tuscany.core.invocation.impl.MessageDispatcher}, will invoke the first source-side + * interceptor, which in turn will pass the message down the target-side interceptor chain. + * <li> If the target is a component instance the last target-side interceptor, an instance of + * {@link org.apache.tuscany.core.invocation.impl.InvokerInterceptor} will retrieve the + * {@link org.apache.tuscany.core.invocation.TargetInvoker} from the message and call it to invoke the operation on a + * target instance. <tt>TargetInvoker</tt>s are help by the source proxy to enable optimizations such as caching of + * target instances. + * <li> The response is returned up the invocation stack until it reaches the source-side + * <tt>RequestResponseInterceptor</tt>, which invokes the target and source-side response channels respectively. + * <li> The response is then passed back up the rest of the invocation stack. + * </ol> + * <p> + * The source-to-target bridge may be constructed in any of the following ways: + * <ul> + * <li>Source handler-to-target handler + * <li>Source handler-to-target interceptor + * <li>Source interceptor-to-target handler + * <li>Source interceptor-to-target interceptor + * </ul> + * <p> + * In some scenarios, a service proxy may only contain target-side invocaton chains, for example, when a service is + * resolved through a locate operation by a non-component client. In this case, there will be no source-side invocation + * chains and the target invoker will be held by the target-side and passed down the pipeline. + * + * @see org.apache.tuscany.core.builder.WireBuilder + * @see org.apache.tuscany.core.invocation.spi.ProxyFactory + * @see org.apache.tuscany.core.invocation.TargetInvoker + * @see org.apache.tuscany.core.invocation.impl.MessageDispatcher + * + * @version $Rev$ $Date$ + */ +public class InvocationConfiguration { + + // the operation on the target that will utlimately be invoked + private Method operation; + + // responsible for invoking a target instance + private TargetInvoker targetInvoker; + + private Interceptor sourceInterceptorChainHead; + + private Interceptor sourceInterceptorChainTail; + + private Interceptor targetInterceptorChainHead; + + private Interceptor targetInterceptorChainTail; + + private List<MessageHandler> requestHandlers; + + private List<MessageHandler> responseHandlers; + + // a source-side pointer to target request handlers, if the exist + private MessageChannel targetRequestChannel; + + // a source-side pointer to target response handlers, if the exist + private MessageChannel targetResponseChannel; + + /** + * Creates an new invocation configuration for the given target operation + */ + public InvocationConfiguration(Method operation) { + assert (operation != null) : "No operation type specified"; + this.operation = operation; + } + + /** + * Returns the target operation for the invocation configuration + */ + public Method getMethod() { + return operation; + } + + /** + * Used by source-side configurations, sets a pointer to the target-side request channel. This may be null when no + * target request handlers exist. + */ + public void setTargetRequestChannel(MessageChannel channel) { + targetRequestChannel = channel; + } + + /** + * Used by source-side configurations, sets a pointer to the target-side response channel. This may be null when no + * target response handlers exist. + */ + public void setTargetResponseChannel(MessageChannel channel) { + targetResponseChannel = channel; + } + + /** + * Adds an interceptor to the invocation chain for source-side configurations + */ + public void addSourceInterceptor(Interceptor interceptor) { + if (sourceInterceptorChainHead == null) { + sourceInterceptorChainHead = interceptor; + } else { + sourceInterceptorChainTail.setNext(interceptor); + } + sourceInterceptorChainTail = interceptor; + } + + /** + * Adds an interceptor to the invocation chain for target-side configurations + */ + public void addTargetInterceptor(Interceptor interceptor) { + if (targetInterceptorChainHead == null) { + targetInterceptorChainHead = interceptor; + } else { + targetInterceptorChainTail.setNext(interceptor); + } + targetInterceptorChainTail = interceptor; + } + + /** + * Adds an request handler to the invocation chain for either a source- or target-side configuration + */ + public void addRequestHandler(MessageHandler handler) { + if (requestHandlers == null) { + requestHandlers = new ArrayList<MessageHandler>(); + } + requestHandlers.add(handler); + } + + /** + * Adds an response handler to the invocation chain for either a source- or target-side configuration + */ + public void addResponseHandler(MessageHandler handler) { + if (responseHandlers == null) { + responseHandlers = new ArrayList<MessageHandler>(); + } + responseHandlers.add(handler); + } + + /** + * Returns the request handler chain for either a source- or target-side configuration + */ + public List<MessageHandler> getRequestHandlers() { + return requestHandlers; + } + + /** + * Returns the response handler chain for either a source- or target-side configuration + */ + public List<MessageHandler> getResponseHandlers() { + return responseHandlers; + } + + /** + * Returns the head source-side interceptor. This will be null for target-side configurations + */ + public Interceptor getSourceInterceptor() { + return sourceInterceptorChainHead; + } + + /** + * Returns the head target-side interceptor. On source-side configurations, this will be the head interceptor of the + * "bridged" target configuration. + */ + public Interceptor getTargetInterceptor() { + return targetInterceptorChainHead; + } + + + public Interceptor getLastTargetInterceptor() { + return targetInterceptorChainTail; + } + + /** + * Sets the target invoker to pass down the invocation pipeline. When a service proxy represents a wire, + * the target invoker is set on the source-side. + */ + public void setTargetInvoker(TargetInvoker invoker) { + this.targetInvoker = invoker; + } + + /** + * Returns the target invoker that is passed down the invocation pipeline. When a service proxy represents a wire, + * the target invoker is cached on the source-side. + */ + public TargetInvoker getTargetInvoker() { + return targetInvoker; + } + + /** + * Prepares the configuration by linking interceptors and handlers + */ + public void build() { + + if (requestHandlers != null && targetInterceptorChainHead != null) { + // on target-side, connect existing handlers and interceptors + MessageHandler messageDispatcher = new MessageDispatcher(targetInterceptorChainHead); + requestHandlers.add(messageDispatcher); + } + + if (requestHandlers != null) { + MessageChannel requestChannel = new MessageChannelImpl(requestHandlers); + MessageChannel responseChannel = new MessageChannelImpl(responseHandlers); + Interceptor channelInterceptor = new RequestResponseInterceptor(requestChannel, targetRequestChannel, + responseChannel, targetResponseChannel); + + if (sourceInterceptorChainHead != null) { + sourceInterceptorChainTail.setNext(channelInterceptor); + } else { + sourceInterceptorChainHead = channelInterceptor; + } + + } else { + // no request handlers + if (sourceInterceptorChainHead != null) { + if (targetInterceptorChainHead != null) { + // Connect source interceptor chain directly to target interceptor chain + sourceInterceptorChainTail.setNext(targetInterceptorChainHead); + // sourceInterceptorChainTail = targetInterceptorChainHead; + } else { + // Connect source interceptor chain to the target request channel + Interceptor channelInterceptor = new RequestResponseInterceptor(null, targetRequestChannel, null, + targetResponseChannel); + sourceInterceptorChainTail.setNext(channelInterceptor); + } + } else { + // no source interceptor chain or source handlers, conntect to target interceptor chain or channel + if (targetInterceptorChainHead != null) { + sourceInterceptorChainHead = targetInterceptorChainHead; + sourceInterceptorChainTail = targetInterceptorChainHead; + } else { + Interceptor channelInterceptor = new RequestResponseInterceptor(null, targetRequestChannel, null, + targetResponseChannel); + sourceInterceptorChainHead = channelInterceptor; + sourceInterceptorChainTail = channelInterceptor; + } + } + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationException.java new file mode 100644 index 0000000000..d089b45d76 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationException.java @@ -0,0 +1,29 @@ +package org.apache.tuscany.core.invocation; + +import org.apache.tuscany.common.TuscanyException; + +/** + * The root checked exception for the invocation framework + * + * @version $Rev$ $Date$ + */ +public abstract class InvocationException extends TuscanyException { + + public InvocationException() { + super(); + } + + public InvocationException(String message) { + super(message); + } + + public InvocationException(String message, Throwable cause) { + super(message, cause); + } + + public InvocationException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationRuntimeException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationRuntimeException.java new file mode 100644 index 0000000000..ddb7b5f74b --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/InvocationRuntimeException.java @@ -0,0 +1,44 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation; + +import org.osoa.sca.ServiceRuntimeException; + +/** + * Denotes an exception thrown during invocation processing + * + * @version $Rev$ $Date$ + */ +public class InvocationRuntimeException extends ServiceRuntimeException { + + public InvocationRuntimeException() { + super(); + } + + public InvocationRuntimeException(String message) { + super(message); + } + + public InvocationRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public InvocationRuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MessageChannel.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MessageChannel.java new file mode 100644 index 0000000000..4a5e8a1f87 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MessageChannel.java @@ -0,0 +1,33 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation; + +import org.apache.tuscany.core.message.Message; + +/** + * Represents a one-way pipeline through which messages are sent during an invocation + * + * @see org.apache.tuscany.core.message.Message + */ +public interface MessageChannel { + + /** + * Sends a message + */ + void send(Message message); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MessageHandler.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MessageHandler.java new file mode 100644 index 0000000000..4719fbae81 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MessageHandler.java @@ -0,0 +1,34 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation; + +import org.apache.tuscany.core.message.Message; + + +/** + * Performs a uni-directional mediation on a message + * + * @see org.apache.tuscany.core.message.Message + */ +public interface MessageHandler { + + /** + * Process a message. + */ + boolean processMessage(Message message); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MethodHashMap.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MethodHashMap.java new file mode 100644 index 0000000000..183cb5ecbb --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/MethodHashMap.java @@ -0,0 +1,53 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation; + +import java.lang.reflect.Method; +import java.util.HashMap; + +import org.apache.tuscany.core.config.JavaIntrospectionHelper; + +/** + * A HashMap keyed by method + */ +public class MethodHashMap extends HashMap { + + /** + * Constructs a new MethodHashMap. + */ + public MethodHashMap() { + super(); + } + + /** + * Constructs a new MethodHashMap. + */ + public MethodHashMap(int size) { + super(size); + } + + /** + * @see java.util.HashMap#get(java.lang.Object) + */ + public Object get(Object key) { + Method method=(Method)key; + //FIXME find a more efficient way to find a matching method + Method closestMethod=JavaIntrospectionHelper.findClosestMatchingMethod(method.getName(), method.getParameterTypes(), super.keySet()); + return super.get(closestMethod); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/ProxyConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/ProxyConfiguration.java new file mode 100644 index 0000000000..11fc4768f3 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/ProxyConfiguration.java @@ -0,0 +1,101 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation; + +import java.lang.reflect.Method; +import java.util.Map; + +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.message.MessageFactory; + +/** + * Represents configuration information for creating a service proxy. When a client component implementation is injected + * with a service proxy representing a wire, source- and target-side proxy configurations are "bridged" together. This + * concatenated configuration may then be used to generate a proxy implemented a particular business interface required + * by the client. + * + * @version $Rev$ $Date$ + */ +public class ProxyConfiguration { + + private Map<Method, InvocationConfiguration> configurations; + + private ClassLoader proxyClassLoader; + + private MessageFactory messageFactory; + + private QualifiedName serviceName; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + /** + * Creates a configuration used to generate proxies representing a service. + * + * @param serviceName the qualified name of the service represented by this configuration + * @param invocationConfigs a collection of operation-to-invocation configuration mappings for the service + * @param proxyClassLoader the classloader to use when creating a proxy + * @param messageFactory the factory used to create invocation messages + */ + public ProxyConfiguration(QualifiedName serviceName, Map<Method, InvocationConfiguration> invocationConfigs, + ClassLoader proxyClassLoader, MessageFactory messageFactory) { + assert (invocationConfigs != null) : "No invocation configuration map specified"; + this.serviceName = serviceName; + configurations = invocationConfigs; + this.messageFactory = messageFactory; + if (proxyClassLoader == null) { + this.proxyClassLoader = Thread.currentThread().getContextClassLoader(); + } else { + this.proxyClassLoader = proxyClassLoader; + } + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + /** + * Returns the qualified service name the configuration is associated with + */ + public QualifiedName getTargetName() { + return serviceName; + } + + /** + * Returns a collection of operation types to {@link InvocationConfiguration} mappings that represent the specific + * proxy configuration information for particular operations + */ + public Map<Method, InvocationConfiguration> getInvocationConfigurations() { + return configurations; + } + + /** + * Returns the classloader to use in creating proxies + */ + public ClassLoader getProxyClassLoader() { + return proxyClassLoader; + } + + /** + * Returns the factory used to create invocation messages + */ + public MessageFactory getMessageFactory() { + return messageFactory; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/TargetInvoker.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/TargetInvoker.java new file mode 100644 index 0000000000..e0a85d0b6e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/TargetInvoker.java @@ -0,0 +1,44 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation; + +import java.lang.reflect.InvocationTargetException; + +/** + * Implementations are responsible for resolving a target and performing the actual invocation on it, for example, a + * service component implementation instance or an external service client. + * + * @version $Rev$ $Date$ + */ +public interface TargetInvoker extends Interceptor, Cloneable{ + + /** + * Responsible for invoking an operation on a target with the given payload + * + * @param payload the parameters of the target operation or null + * @throws InvocationTargetException if the target operation itself throws an exception. The root cause will be set + * to that exception + */ + public Object invokeTarget(Object payload) throws InvocationTargetException; + + /** + * Determines whether the proxy can be cached on the client/source side + */ + public boolean isCacheable(); + + public Object clone(); +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/InvokerInterceptor.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/InvokerInterceptor.java new file mode 100644 index 0000000000..7b9dc1c86f --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/InvokerInterceptor.java @@ -0,0 +1,46 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.invocation.impl; + +import org.apache.tuscany.core.invocation.Interceptor; +import org.apache.tuscany.core.invocation.InvocationRuntimeException; +import org.apache.tuscany.core.invocation.TargetInvoker; +import org.apache.tuscany.core.message.Message; + +/** + * Serves as a tail interceptor on a target invocation chain. This implementation dispatches to the target invoker + * passed inside the invocation message. Target invokers are passed from the source in order to allow for caching of + * target instances. + * + * @see org.apache.tuscany.core.invocation.TargetInvoker + * @version $Rev$ $Date$ + */ +public class InvokerInterceptor implements Interceptor { + + public InvokerInterceptor() { + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + TargetInvoker invoker = msg.getTargetInvoker(); + if (invoker == null) { + throw new InvocationRuntimeException("No target invoker specified on message"); + } + return invoker.invoke(msg); + } + + public void setNext(Interceptor next) { + throw new IllegalStateException("This interceptor must be the last one in an target interceptor chain"); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/MessageChannelImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/MessageChannelImpl.java new file mode 100644 index 0000000000..6c0b15a823 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/MessageChannelImpl.java @@ -0,0 +1,68 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.impl; + +import java.util.List; + +import org.apache.tuscany.core.invocation.MessageChannel; +import org.apache.tuscany.core.invocation.MessageHandler; +import org.apache.tuscany.core.message.Message; + +/** + * A channel comprising an ordered collection of message handlers. + * + *@see org.apache.tuscany.core.message.Message + * @version $Rev$ $Date$ + */ +public class MessageChannelImpl implements MessageChannel { + + private final List<MessageHandler> pipeline; + + //---------------------------------- + // Constructors + //---------------------------------- + + /** + * Construct a new channel comprising the supplied list of handlers. + * + * @param pipeline the Handlers in the channel + */ + public MessageChannelImpl(List<MessageHandler> pipeline) { + this.pipeline = pipeline; + } + + //---------------------------------- + // Methods + //---------------------------------- + + /** + * Send a message down the channel. The message will be processed by all handlers + * in order until one returns false to indicate processing is complete or all + * handlers have been called. + * + * @param msg a Message to send down the channel + */ + public void send(Message msg) { + if (pipeline!=null) { + for (MessageHandler handler : pipeline) { + if (!handler.processMessage(msg)) { + break; + } + } + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/MessageDispatcher.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/MessageDispatcher.java new file mode 100644 index 0000000000..a162962717 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/MessageDispatcher.java @@ -0,0 +1,46 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.impl; + +import org.apache.tuscany.core.invocation.Interceptor; +import org.apache.tuscany.core.invocation.MessageHandler; +import org.apache.tuscany.core.message.Message; + +/** + * A message handler that dispatches the message through an interceptor stack and the uses the response channel to + * return the invocation result. + * + * @version $Rev$ $Date$ + */ +public class MessageDispatcher implements MessageHandler { + private final Interceptor head; + + /** + * Construct a handler that dispatches messages to an Interceptor stack. + * + * @param head the interceptor at the head of the stack + */ + public MessageDispatcher(Interceptor head) { + this.head = head; + } + + public boolean processMessage(Message msg) { + Message resp = head.invoke(msg); + msg.getCallbackChannel().send(resp); + return false; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/NullProxyFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/NullProxyFactory.java new file mode 100644 index 0000000000..fa4297ef00 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/NullProxyFactory.java @@ -0,0 +1,57 @@ +package org.apache.tuscany.core.invocation.impl; + +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.invocation.ProxyConfiguration; +import org.apache.tuscany.core.invocation.spi.ProxyCreationException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.invocation.spi.ProxyInitializationException; + +/** + * Returns an actual implementation instance as opposed to a proxy. Used in cases where proxying may be optimized away. + * + * @version $Rev: 379957 $ $Date: 2006-02-22 14:58:24 -0800 (Wed, 22 Feb 2006) $ + */ +public class NullProxyFactory implements ProxyFactory { + + private AggregateContext parentContext; + + private String targetName; + + public NullProxyFactory(String componentName, AggregateContext parentContext) { + assert (parentContext != null) : "Parent context was null"; + this.targetName = componentName; + this.parentContext = parentContext; + } + + public void initialize(Class businessInterface, ProxyConfiguration config) throws ProxyInitializationException { + } + + public Object createProxy() throws ProxyCreationException { + return parentContext.getContext(targetName); + } + + public void initialize() throws ProxyInitializationException { + } + + public ProxyConfiguration getProxyConfiguration() { + return null; + } + + public void setProxyConfiguration(ProxyConfiguration config) { + } + + public void setBusinessInterface(Class interfaze) { + } + + public Class getBusinessInterface() { + return null; + } + + public void addInterface(Class claz) { + } + + public Class[] getImplementatedInterfaces() { + return null; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/OneWayInterceptor.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/OneWayInterceptor.java new file mode 100644 index 0000000000..71d324e032 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/OneWayInterceptor.java @@ -0,0 +1,48 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.impl; + +import org.apache.tuscany.core.invocation.Interceptor; +import org.apache.tuscany.core.invocation.MessageChannel; +import org.apache.tuscany.core.message.Message; + +/** + * An interceptor that sends the invocation Message down its request channel and does not expect a response. + * + * @version $Rev$ $Date$ + */ +public class OneWayInterceptor implements Interceptor { + private MessageChannel requestChannel; + + /** + * Construct an interceptor that sends messages down the supplied channel. + * + * @param requestChannel the channel to send messages down + */ + public OneWayInterceptor(MessageChannel requestChannel) { + this.requestChannel = requestChannel; + } + + public Message invoke(Message message) { + requestChannel.send(message); + return null; + } + + public void setNext(Interceptor next) { + throw new IllegalStateException("This interceptor must be the last one in an interceptor chain"); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/RequestResponseInterceptor.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/RequestResponseInterceptor.java new file mode 100644 index 0000000000..03122f0992 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/impl/RequestResponseInterceptor.java @@ -0,0 +1,73 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.impl; + +import org.apache.tuscany.core.invocation.Interceptor; +import org.apache.tuscany.core.invocation.MessageChannel; +import org.apache.tuscany.core.message.Message; + +/** + * An interceptor that first sends the invocation Message down its request channel then extracts the response from the + * message and sends it down the response channel before returning it up the interceptor stack. + * + * @version $Rev$ $Date$ + */ +public class RequestResponseInterceptor implements Interceptor { + + private MessageChannel sourceRequestChannel; + + private MessageChannel sourceResponseChannel; + + private MessageChannel targetRequestChannel; + + private MessageChannel targetResponseChannel; + + /** + * Construct an interceptor that sends messages down the supplied channels. + * + * @param targetRequestChannel the channel to send request messages down + * @param targetResponseChannel the channel to sent response messages down + */ + public RequestResponseInterceptor(MessageChannel sourceRequestChannel, MessageChannel targetRequestChannel, + MessageChannel sourceResponseChannel, MessageChannel targetResponseChannel) { + this.sourceRequestChannel = sourceRequestChannel; + this.sourceResponseChannel = sourceResponseChannel; + this.targetRequestChannel = targetRequestChannel; + this.targetResponseChannel = targetResponseChannel; + } + + public Message invoke(Message requestMessage) { + if (sourceRequestChannel != null) { + sourceRequestChannel.send(requestMessage); + } + if (targetRequestChannel != null) { + targetRequestChannel.send(requestMessage); + } + Message responseMessage = requestMessage.getRelatedCallbackMessage(); + if (targetResponseChannel != null) { + targetResponseChannel.send(responseMessage); + } + if (sourceResponseChannel != null) { + sourceResponseChannel.send(responseMessage); + } + return responseMessage; + } + + public void setNext(Interceptor next) { + throw new IllegalStateException("This interceptor must be the last one in an interceptor chain"); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKInvocationHandler.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKInvocationHandler.java new file mode 100644 index 0000000000..2f27698d6b --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKInvocationHandler.java @@ -0,0 +1,143 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.jdk; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.invocation.Interceptor; +import org.apache.tuscany.core.invocation.InvocationConfiguration; +import org.apache.tuscany.core.invocation.TargetInvoker; +import org.apache.tuscany.core.message.Message; +import org.apache.tuscany.core.message.MessageFactory; + +/** + * Receives a request from a JDK proxy and dispatches it to a target invoker or source interceptor stack + * + * @version $Rev$ $Date$ + */ +public class JDKInvocationHandler implements InvocationHandler { + + private MessageFactory messageFactory; + + /* + * an association of an operation to configuration holder. The holder contains the master invocation configuration + * and a locale clone of the master TargetInvoker. TargetInvokers will be cloned by the handler and placed in the + * holder if they are cacheable. This allows optimizations such as avoiding target resolution when a source refers + * to a target of greater scope since the target reference can be maintained by the invoker. When a target invoker + * is not cacheable, the master associated with the invocation configuration will be used. + */ + private Map<Method, ConfigHolder> configuration; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public JDKInvocationHandler(MessageFactory messageFactory, Map<Method, InvocationConfiguration> configuration) { + assert (configuration != null) : "Configuration not specified"; + this.configuration = new HashMap(configuration.size()); + for (Map.Entry<Method, InvocationConfiguration> entry : configuration.entrySet()) { + this.configuration.put(entry.getKey(), new ConfigHolder(entry.getValue())); + } + // this.configuration = configuration; + this.messageFactory = messageFactory; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + /** + * Dispatches a client request made on a proxy + */ + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Interceptor headInterceptor = null; + ConfigHolder holder = configuration.get(method); + if (holder == null) { + TargetException e = new TargetException("Operation not configured"); + e.setIdentifier(method.getName()); + throw e; + } + InvocationConfiguration config = holder.config; + if (config != null) { + headInterceptor = config.getSourceInterceptor(); + } + + TargetInvoker invoker = null; + + if (holder.cachedInvoker == null) { + if(config.getTargetInvoker() == null){ + TargetException e= new TargetException("No target invoker configured for operation"); + e.setIdentifier(config.getMethod().getName()); + throw e; + } + if (config.getTargetInvoker().isCacheable()) { + // clone and store the invoker locally + holder.cachedInvoker = (TargetInvoker) config.getTargetInvoker().clone(); + invoker = holder.cachedInvoker; + } else { + invoker = config.getTargetInvoker(); + } + } else { + invoker = config.getTargetInvoker(); + } + if (headInterceptor == null) { + try { + // short-circuit the dispatch and invoke the target directly + if (config.getTargetInvoker() == null) { + throw new AssertionError("No target invoker [" + method.getName() + "]"); + } + return config.getTargetInvoker().invokeTarget(args); + } catch (InvocationTargetException e) { + // the cause was thrown by the target so throw it + throw e.getCause(); + } + } else { + Message msg = messageFactory.createMessage(); + msg.setTargetInvoker(invoker);// config.getTargetInvoker()); + msg.setBody(args); + // dispatch the invocation down the chain and get the response + Message resp = headInterceptor.invoke(msg); + + Object body = resp.getBody(); + if (body instanceof Throwable) { + throw (Throwable) body; + } + return body; + } + } + + /** + * A holder used to associate an invocation configuration with a local copy of a target invoker that was previously + * cloned from the configuration master + */ + private class ConfigHolder { + + public ConfigHolder(InvocationConfiguration config) { + this.config = config; + } + + InvocationConfiguration config; + + TargetInvoker cachedInvoker; + } + +}
\ No newline at end of file diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKProxyFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKProxyFactory.java new file mode 100644 index 0000000000..75137ffa36 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKProxyFactory.java @@ -0,0 +1,96 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.jdk; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map; + +import org.apache.tuscany.core.invocation.InvocationConfiguration; +import org.apache.tuscany.core.invocation.MethodHashMap; +import org.apache.tuscany.core.invocation.ProxyConfiguration; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.invocation.spi.ProxyInitializationException; + +/** + * Creates proxies for handling invocations using JDK dynamic proxies + * + * @version $Rev$ $Date$ + */ +public class JDKProxyFactory implements ProxyFactory { + + private static final int UNINITIALIZED = 0; + + private static final int INITIALIZED = 1; + + private static final int ERROR = -1; + + private int state = UNINITIALIZED; + + private Class[] businessInterfaceArray; + + private Map<Method, InvocationConfiguration> methodToInvocationConfig; + + private ProxyConfiguration configuration; + + public void initialize() throws ProxyInitializationException { + if (state != UNINITIALIZED) { + throw new IllegalStateException("Proxy factory in wrong state [" + state + "]"); + } + Map<Method, InvocationConfiguration> invocationConfigs = configuration.getInvocationConfigurations(); + methodToInvocationConfig = new MethodHashMap(invocationConfigs.size()); + for (Map.Entry entry : invocationConfigs.entrySet()) { + Method method = (Method) entry.getKey(); + methodToInvocationConfig.put(method, (InvocationConfiguration) entry.getValue()); + } + state = INITIALIZED; + } + + public Object createProxy() { + if (state != INITIALIZED) { + throw new IllegalStateException("Proxy factory not INITIALIZED [" + state + "]"); + } + InvocationHandler handler = new JDKInvocationHandler(configuration.getMessageFactory(), methodToInvocationConfig); + return Proxy.newProxyInstance(configuration.getProxyClassLoader(), businessInterfaceArray, handler); + } + + public ProxyConfiguration getProxyConfiguration() { + return configuration; + } + + public void setProxyConfiguration(ProxyConfiguration config) { + configuration = config; + } + + public void setBusinessInterface(Class interfaze) { + businessInterfaceArray = new Class[] { interfaze }; + } + + public Class getBusinessInterface() { + return businessInterfaceArray[0]; + } + + public void addInterface(Class claz) { + throw new UnsupportedOperationException("Additional proxy interfaces not yet supported"); + } + + public Class[] getImplementatedInterfaces() { + return businessInterfaceArray; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKProxyFactoryFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKProxyFactoryFactory.java new file mode 100644 index 0000000000..81458e4178 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/jdk/JDKProxyFactoryFactory.java @@ -0,0 +1,52 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.invocation.jdk; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; + +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.invocation.spi.ProxyFactoryFactory; + +/** + * Creates JDK Dynamic Proxy-based proxy factories + * + * @version $Rev$ $Date$ + */ +public class JDKProxyFactoryFactory implements ProxyFactoryFactory { + + public JDKProxyFactoryFactory() { + } + + public ProxyFactory createProxyFactory() { + return new JDKProxyFactory(); + } + + public boolean isProxy(Object object) { + if (object == null) { + return false; + } else { + return Proxy.isProxyClass(object.getClass()); + } + } + + public InvocationHandler getHandler(Object proxy) { + if (proxy == null) { + return null; + } else { + return Proxy.getInvocationHandler(proxy); + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyCreationException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyCreationException.java new file mode 100644 index 0000000000..2a97975bf9 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyCreationException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.spi; + +/** + * Denotes an error creating a proxy instance + * + * @version $Rev$ $Date$ + */ +public class ProxyCreationException extends ProxyException { + + public ProxyCreationException() { + super(); + } + + public ProxyCreationException(String message, Throwable cause) { + super(message, cause); + } + + public ProxyCreationException(String message) { + super(message); + } + + public ProxyCreationException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyException.java new file mode 100644 index 0000000000..843a90d341 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyException.java @@ -0,0 +1,40 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.spi; + +import org.apache.tuscany.core.invocation.InvocationException; + +public class ProxyException extends InvocationException { + + public ProxyException() { + super(); + } + + public ProxyException(String message) { + super(message); + } + + public ProxyException(String message, Throwable cause) { + super(message, cause); + } + + public ProxyException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyFactory.java new file mode 100644 index 0000000000..aef98a0b4c --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyFactory.java @@ -0,0 +1,79 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.spi; + +import org.apache.tuscany.core.invocation.ProxyConfiguration; + +/** + * Implementations are responsible for creating service proxies using a particular proxy strategy. Service proxies may + * represent a wire between two components or a reference to a service resolved through a locate operation. When + * representing a wire, a proxy is injected on reference in a component implementation. In this case the proxy will + * implement the interface required by the reference and pass invocation messages down source- and target-side + * invocation chains for processing. These source- and target-side invocation chains will be derived from metadata + * decorating the source reference and target service definition and implementation respectively. + * <p> + * The second type of proxy will be generated when non-component client code (such as a JSP) locates a service. In this + * case, the proxy will implement the requested service interface but will only contain a target-side invocation chain. + * + * @version $Rev$ $Date$ + */ +public interface ProxyFactory<T> { + + /** + * Prepares the factory for generating the proxy of a particular reference type. This will typically be called when + * construction of the proxy configuration is complete, including linking of source and target invocation chains. + * + * @throws ProxyInitializationException if an error is encountered during initialization + */ + public void initialize() throws ProxyInitializationException; + + /** + * Returns a proxy for a service reference + */ + public T createProxy() throws ProxyCreationException; + + /** + * Returns the configuration information used to create a proxy + */ + public ProxyConfiguration getProxyConfiguration(); + + /** + * Sets the configuration information used to create a proxy + */ + public void setProxyConfiguration(ProxyConfiguration config); + + /** + * Sets the primary interface type generated proxies should implement + */ + public void setBusinessInterface(Class interfaze); + + /** + * Returns the primary interface type implemented by generated proxies + */ + public Class getBusinessInterface(); + + /** + * Adds an interface type generated proxies should implement + */ + public void addInterface(Class claz); + + /** + * Returns an array of all interfaces implemented by generated proxies + */ + public Class[] getImplementatedInterfaces(); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyFactoryFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyFactoryFactory.java new file mode 100644 index 0000000000..8e4c2ee589 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyFactoryFactory.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.invocation.spi; + +import java.lang.reflect.InvocationHandler; + +/** + * Creates proxy factories which may be subsequently configured to generate proxies + * + * @version $Rev$ $Date$ + */ +public interface ProxyFactoryFactory { + + /** + * Returns a new proxy factory + */ + public ProxyFactory createProxyFactory(); + + /** + * Determines whether the given object is a proxy + */ + public boolean isProxy(Object object); + + /** + * Returns an invocation handler fronting the invocation chains used by the proxy. Note that should SCA define a + * DII, this could return such an interface. + * + * @throws IllegalArgumentException if the class is not a proxy + */ + public InvocationHandler getHandler(Object proxy) throws IllegalArgumentException; +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyInitializationException.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyInitializationException.java new file mode 100644 index 0000000000..d8c8e64614 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/invocation/spi/ProxyInitializationException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.invocation.spi; + +/** + * Denotes an error initializing a proxy factory + * + * @version $Rev$ $Date$ + */ +public class ProxyInitializationException extends ProxyException { + + public ProxyInitializationException() { + super(); + } + + public ProxyInitializationException(String message) { + super(message); + } + + public ProxyInitializationException(String message, Throwable cause) { + super(message, cause); + } + + public ProxyInitializationException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/loader/SCDLModelLoaderRegistry.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/loader/SCDLModelLoaderRegistry.java new file mode 100644 index 0000000000..0205c1350e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/loader/SCDLModelLoaderRegistry.java @@ -0,0 +1,51 @@ +/** + * + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.loader; + +import java.util.List; + +import org.apache.tuscany.model.scdl.loader.SCDLModelLoader; + +/** + * A ModelLoaderRegistry maintains a list of SCDLModelLoaders that have been contributed + * to the system by various extension components (such as implementations or bindings). + * + * + * @version $Rev$ $Date$ + */ +public interface SCDLModelLoaderRegistry { + /** + * Returns the list of registered model loaders. + * + * @return the list of registered model loaders + */ + List<SCDLModelLoader> getLoaders(); + + /** + * Register a model loader. + * + * @param loader the loader being contributed by the extension component + */ + void registerLoader(SCDLModelLoader loader); + + /** + * Unregister a model loader. + * + * @param loader the loader previously contributed by the extension component + */ + void unregisterLoader(SCDLModelLoader loader); +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/loader/impl/SCDLModelLoaderRegistryImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/loader/impl/SCDLModelLoaderRegistryImpl.java new file mode 100644 index 0000000000..2f0ba73252 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/loader/impl/SCDLModelLoaderRegistryImpl.java @@ -0,0 +1,49 @@ +/** + * + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.loader.impl; + +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; + +import org.apache.tuscany.core.loader.SCDLModelLoaderRegistry; +import org.apache.tuscany.model.scdl.loader.SCDLModelLoader; + +/** + * @version $Rev$ $Date$ + */ +public class SCDLModelLoaderRegistryImpl implements SCDLModelLoaderRegistry { + private final List<SCDLModelLoader> loaders; + private final List<SCDLModelLoader> registry; + + public SCDLModelLoaderRegistryImpl() { + registry = new ArrayList<SCDLModelLoader>(); + loaders = Collections.unmodifiableList(registry); + } + + public List<SCDLModelLoader> getLoaders() { + return loaders; + } + + public void registerLoader(SCDLModelLoader loader) { + registry.add(loader); + } + + public void unregisterLoader(SCDLModelLoader loader) { + registry.remove(loader); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/Message.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/Message.java new file mode 100644 index 0000000000..e316050511 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/Message.java @@ -0,0 +1,182 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.message; + +import java.util.Map; + +import org.apache.tuscany.core.addressing.EndpointReference; +import org.apache.tuscany.core.invocation.MessageChannel; +import org.apache.tuscany.core.invocation.TargetInvoker; + +/** + * Represents a request, response, or exception for an invocation + */ +public interface Message { + + /** + * Return any message headers associated with the invocation. + */ + Map<String, Object> getHeaders(); + + /** + * Returns the body of the message, which will be the payload or parameters + * associated with the invocation + * FIXME what is different w/ getPayload()? + */ + Object getBody(); + + /** + * Sets the body of the message. + */ + void setBody(Object body); + + /** + * Returns true if the message is a request message + * FIXME is this still used? + */ + boolean isRequest(); + + /** + * Returns true if the message is an inbound message + * FIXME is this still used? + */ + boolean isResponse(); + + /** + * Sets the To header + * FIXME Javadoc + */ + void setTo(EndpointReference to); + + /** + * Returns the To header + * FIXME Javadoc + */ + EndpointReference getTo(); + + /** + * Sets the From header + * FIXME Javadoc + */ + void setFrom(EndpointReference from); + + /** + * Returns the From header + * FIXME Javadoc + */ + EndpointReference getFrom(); + + /** + * Sets the message ID + */ + void setMessageID(String messageID); + + /** + * Returns the message ID + */ + String getMessageID(); + + /** + * Sets the Action header + * FIXME Javadoc + */ + void setAction(String action); + + /** + * Returns the Action header + * FIXME Javadoc + */ + String getAction(); + + /** + * Sets the ReplyTo header + * FIXME Javadoc + */ + void setReplyTo(EndpointReference replyTo); + + /** + * Returns the ReplyTo header + * FIXME Javadoc + */ + EndpointReference getReplyTo(); + + /** + * Sets the RelatesTo header + * FIXME Javadoc + */ + void setRelatesTo(String relatesTo); + + /** + * Returns the RelatesTo header + * FIXME Javadoc + */ + String getRelatesTo(); + + /** + * Sets the FaultTo header + * FIXME Javadoc + */ + void setFaultTo(EndpointReference faultTo); + + /** + * Returns the FaultTo header + * FIXME Javadoc + */ + EndpointReference getFaultTo(); + + /** + * Sets the EndpointReference header + * FIXME Javadoc + */ + void setEndpointReference(EndpointReference endpointReference); + + /** + * Returns the EndpointReference header + * FIXME Javadoc + */ + EndpointReference getEndpointReference(); + + /** + * Sets the operation name + * FIXME Javadoc + */ + void setOperationName(String operationName); + + /** + * Returns the operation name + * FIXME Javadoc + */ + String getOperationName(); + + /** + * Returns the callback channel + * FIXME Javadoc + */ + MessageChannel getCallbackChannel(); + + /** + * Returns the related callback message + * FIXME Javadoc + */ + Message getRelatedCallbackMessage(); + + //ADDED + public void setTargetInvoker(TargetInvoker invoker); + + public TargetInvoker getTargetInvoker(); + +} // Message diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/MessageFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/MessageFactory.java new file mode 100644 index 0000000000..74b0e85848 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/MessageFactory.java @@ -0,0 +1,31 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.message; + +/** + * The <b>Factory</b> for messages + * + * @see org.apache.tuscany.core.message.Message + */ +public interface MessageFactory { + + /** + * Returns a new message. + */ + Message createMessage(); + +} // MessageFactory diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/impl/MessageFactoryImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/impl/MessageFactoryImpl.java new file mode 100644 index 0000000000..43787bbe67 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/impl/MessageFactoryImpl.java @@ -0,0 +1,40 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.message.impl; + +import org.apache.tuscany.core.message.Message; +import org.apache.tuscany.core.message.MessageFactory; + +/** + * The default message factory + * + * @version $Rev$ $Date$ + */ +public class MessageFactoryImpl implements MessageFactory { + + /** + * Constructor + */ + public MessageFactoryImpl() { + super(); + } + + public Message createMessage() { + return new MessageImpl(); + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/impl/MessageImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/impl/MessageImpl.java new file mode 100644 index 0000000000..b67c7e227e --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/message/impl/MessageImpl.java @@ -0,0 +1,249 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.message.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.addressing.EndpointReference; +import org.apache.tuscany.core.invocation.MessageChannel; +import org.apache.tuscany.core.invocation.TargetInvoker; +import org.apache.tuscany.core.message.Message; + +/** + */ +public class MessageImpl implements Message, MessageChannel { + + private String action; + private Object body; + private EndpointReference endpointReference; + private EndpointReference faultTo; + private EndpointReference from; + private Map<String, Object> headers; + private String messageID; + private String operationName; + private Message relatedCallbackMessage; + private String relatesTo; + private EndpointReference replyTo; + private TargetInvoker invoker; + private EndpointReference to; + + /** + * Constructor + */ + protected MessageImpl() { + super(); + } + + /** + * @see org.apache.tuscany.core.message.Message#getAction() + */ + public String getAction() { + return action; + } + + /** + * @see org.apache.tuscany.core.message.Message#getBody() + */ + public Object getBody() { + return body; + } + + /** + * @see org.apache.tuscany.core.message.Message#getEndpointReference() + */ + public EndpointReference getEndpointReference() { + return endpointReference; + } + + /** + * @see org.apache.tuscany.core.message.Message#getFaultTo() + */ + public EndpointReference getFaultTo() { + return faultTo; + } + + /** + * @see org.apache.tuscany.core.message.Message#getFrom() + */ + public EndpointReference getFrom() { + return from; + } + + /** + * @see org.apache.tuscany.core.message.Message#getHeaders() + */ + public Map<String, Object> getHeaders() { + if (headers==null) + headers=new HashMap<String, Object>(); + return headers; + } + + /** + * @see org.apache.tuscany.core.message.Message#getMessageID() + */ + public String getMessageID() { + return messageID; + } + + /** + * @see org.apache.tuscany.core.message.Message#getOperationName() + */ + public String getOperationName() { + return operationName; + } + + /** + * @see org.apache.tuscany.core.message.Message#getRelatesTo() + */ + public String getRelatesTo() { + return relatesTo; + } + + /** + * @see org.apache.tuscany.core.message.Message#getReplyTo() + */ + public EndpointReference getReplyTo() { + return replyTo; + } + + /** + * @see org.apache.tuscany.core.message.Message#getTo() + */ + public EndpointReference getTo() { + return to; + } + + /** + * @see org.apache.tuscany.core.message.Message#isRequest() + */ + public boolean isRequest() { + return relatesTo==null; + } + + /** + * @see org.apache.tuscany.core.message.Message#isResponse() + */ + public boolean isResponse() { + return relatesTo!=null; + } + + /** + * @see org.apache.tuscany.core.message.Message#setAction(java.lang.String) + */ + public void setAction(String action) { + this.action=action; + } + + /** + * @see org.apache.tuscany.core.message.Message#setBody(java.lang.Object) + */ + public void setBody(Object body) { + this.body=body; + } + + /** + * @see org.apache.tuscany.core.message.Message#setEndpointReference(org.apache.tuscany.core.client.runtime.addressing.sdo.EndpointReference) + */ + public void setEndpointReference(EndpointReference endpointReference) { + this.endpointReference=endpointReference; + } + + /** + * @see org.apache.tuscany.core.message.Message#setFaultTo(org.apache.tuscany.core.client.runtime.addressing.sdo.EndpointReference) + */ + public void setFaultTo(EndpointReference faultTo) { + this.faultTo=faultTo; + } + + /** + * @see org.apache.tuscany.core.message.Message#setFrom(org.apache.tuscany.core.client.runtime.addressing.sdo.EndpointReference) + */ + public void setFrom(EndpointReference from) { + this.from=from; + } + + /** + * @see org.apache.tuscany.core.message.Message#setMessageID(java.lang.String) + */ + public void setMessageID(String messageID) { + this.messageID=messageID; + } + + /** + * @see org.apache.tuscany.core.message.Message#setOperationName(java.lang.String) + */ + public void setOperationName(String operationName) { + this.operationName=operationName; + } + + /** + * @see org.apache.tuscany.core.message.Message#setRelatesTo(java.lang.String) + */ + public void setRelatesTo(String relatesTo) { + this.relatesTo=relatesTo; + } + + /** + * @see org.apache.tuscany.core.message.Message#setReplyTo(org.apache.tuscany.core.client.runtime.addressing.sdo.EndpointReference) + */ + public void setReplyTo(EndpointReference replyTo) { + this.replyTo=replyTo; + } + + /** + * @see org.apache.tuscany.core.message.Message#setTo(org.apache.tuscany.core.client.runtime.addressing.sdo.EndpointReference) + */ + public void setTo(EndpointReference to) { + this.to=to; + } + + /** + * @see org.apache.tuscany.core.message.Message#getCallbackChannel() + */ + public MessageChannel getCallbackChannel() { + return this; + } + + /** + * @see org.apache.tuscany.core.invocation.MessageChannel#send(org.apache.tuscany.core.message.Message) + */ + public void send(Message message) { + relatedCallbackMessage = message; + } + + /** + * @see org.apache.tuscany.core.message.Message#getRelatedCallbackMessage() + */ + public Message getRelatedCallbackMessage() { + return relatedCallbackMessage; + } + + /** + * @see org.apache.tuscany.core.message.Message#setTargetInvoker(org.apache.tuscany.core.invocation.TargetInvoker) + */ + public void setTargetInvoker(TargetInvoker invoker){ + this.invoker = invoker; + } + + /** + * @see org.apache.tuscany.core.message.Message#getTargetInvoker() + */ + public TargetInvoker getTargetInvoker(){ + return invoker; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeContext.java new file mode 100644 index 0000000000..5bf71a09f9 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeContext.java @@ -0,0 +1,83 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.runtime; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.builder.WireBuilder; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.context.ConfigurationContext; +import org.apache.tuscany.core.context.SystemAggregateContext; +import org.apache.tuscany.model.scdl.loader.SCDLModelLoader; + +/** + * Represents a top-level component context in the runtime, that is the bootstrap context. + * This context serves as the ultimate root of the context hierarchy. Under it are two + * separate trees: the rootContext for user components and the systemContext for + * system components (those that comprise the runtime itself). + * + * @version $Rev$ $Date$ + */ +public interface RuntimeContext extends AutowireContext, ConfigurationContext { + + /* the symbolic name of the runtime bootstrap context */ + public static final String RUNTIME = "tuscany.runtime"; + + /* the symbolic name of the aggregate context containing all system components in the runtime */ + public static final String SYSTEM = "tuscany.system"; + + /* the symbolic name of the aggregate context containing all user components in the runtime */ + public static final String ROOT = "tuscany.root"; + + /** + * Returns the context that forms the root of the user component tree. + * All user components will managed by contexts that are children of this root. + * @return the root of the user component tree + */ + public AggregateContext getRootContext(); + + /** + * Returns the context that forms the root of the system component tree. + * All system components, components that provide system services needed by the + * Tuscany runtime itself, will be managed by contexts that are children of this root. + * @return the root of the system component tree + */ + public SystemAggregateContext getSystemContext(); + + /** + * Adds a configuration builder to the runtime + */ + @Deprecated + public void addBuilder(RuntimeConfigurationBuilder builder); + + /** + * Adds a wire builder to the runtime + */ + @Deprecated + public void addBuilder(WireBuilder builder); + + /** + * Adds an SCDL model loader to the runtime + */ + @Deprecated + public void addLoader(SCDLModelLoader loader); + + /** + * Returns the monitor factory in use by the runtime + */ + @Deprecated + public MonitorFactory getMonitorFactory(); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeContextImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeContextImpl.java new file mode 100644 index 0000000000..044958b9bf --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeContextImpl.java @@ -0,0 +1,286 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.runtime; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.common.monitor.impl.NullMonitorFactory; +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.builder.HierarchicalWireBuilder; +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.builder.WireBuilder; +import org.apache.tuscany.core.builder.impl.AssemblyVisitor; +import org.apache.tuscany.core.builder.impl.DefaultWireBuilder; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.context.AutowireResolutionException; +import org.apache.tuscany.core.context.ConfigurationContext; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventException; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.SystemAggregateContext; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.context.impl.AggregateContextImpl; +import org.apache.tuscany.core.context.impl.EventContextImpl; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.system.context.SystemAggregateContextImpl; +import org.apache.tuscany.core.system.context.SystemScopeStrategy; +import org.apache.tuscany.model.assembly.Aggregate; +import org.apache.tuscany.model.assembly.Extensible; +import org.apache.tuscany.model.scdl.loader.SCDLModelLoader; + +/** + * Implementation of a RuntimeContext that forms the foundation for a Tuscany environment. + * + * @version $Rev$ $Date$ + */ +public class RuntimeContextImpl extends AbstractContext implements RuntimeContext { + + private final List<RuntimeConfigurationBuilder> builders; + + private final List<SCDLModelLoader> loaders; + + // the top-level wire builder in the runtime + private final HierarchicalWireBuilder wireBuilder; + + private final List<RuntimeEventListener> listeners = new ArrayList(1); + + private final AggregateContext rootContext; + + private final SystemAggregateContext systemContext; + + private final MonitorFactory monitorFactory; + + /** + * Default constructor that creates a runtime with a NullMonitorFactory and no builders. + */ + public RuntimeContextImpl() { + this(new NullMonitorFactory(), null, null, null); + } + + /** + * Constructor for creating a runtime with a specified MonitorFactory and pre-defined builders. + * + * @param monitorFactory the default {@link MonitorFactory} for this runtime + * @param builders a list of builders automatically made available; may be null + * @param wireBuilder the top-level hierarchical wire builder for the runtime; if not specified, a default + * implementation will be used + */ + public RuntimeContextImpl(MonitorFactory monitorFactory, List<SCDLModelLoader> loaders, + List<RuntimeConfigurationBuilder> builders, HierarchicalWireBuilder wireBuilder) { + super(RUNTIME); + this.monitorFactory = monitorFactory; + this.builders = (builders == null) ? new ArrayList(1) : builders; + this.loaders = (loaders == null) ? new ArrayList(1) : loaders; + this.wireBuilder = (wireBuilder == null) ? new DefaultWireBuilder() : wireBuilder; + + rootContext = new AggregateContextImpl(ROOT, this, this, new RuntimeScopeStrategy(), new EventContextImpl(), this, monitorFactory); + systemContext = new SystemAggregateContextImpl(SYSTEM, this, this, new SystemScopeStrategy(), new EventContextImpl(), this, monitorFactory); + } + + /** + * Specialized constructor that allows the default implementations of the root and system contexts to be + * overridden. + * + * @param monitorFactory the default {@link MonitorFactory} for this runtime + * @param rootContext the context to use for the root of the user context tree + * @param systemContext the context to use for the root of the system context tree + * @param builders a list of builders automatically made available; may be null + * @param wireBuilder the top-level hierarchical wire builder for the runtime; if not specified, a default + * implementation will be used + */ + public RuntimeContextImpl(MonitorFactory monitorFactory, AggregateContext rootContext, SystemAggregateContext systemContext, + List<SCDLModelLoader> loaders, List<RuntimeConfigurationBuilder> builders, HierarchicalWireBuilder wireBuilder) { + super(RUNTIME); + this.rootContext = rootContext; + this.systemContext = systemContext; + this.monitorFactory = monitorFactory; + this.loaders = (loaders == null) ? new ArrayList(1) : loaders; + this.builders = (builders == null) ? new ArrayList(1) : builders; + this.wireBuilder = (wireBuilder == null) ? new DefaultWireBuilder() : wireBuilder; + } + + public void start() throws CoreRuntimeException { + if (lifecycleState == RUNNING) { + return; + } + systemContext.start(); + rootContext.start(); + lifecycleState = RUNNING; + } + + public void stop() throws CoreRuntimeException { + if (lifecycleState == STOPPED) { + return; + } + rootContext.stop(); + systemContext.stop(); + lifecycleState = STOPPED; + } + + public void addBuilder(RuntimeConfigurationBuilder builder) { + assert (builder != null) : "Builder was null"; + builders.add(builder); + } + + public void addBuilder(WireBuilder builder) { + assert (builder != null) : "Builder was null"; + wireBuilder.addWireBuilder(builder); + } + + public void addLoader(SCDLModelLoader loader) { + assert (loader != null) : "Loader was null"; + loaders.add(loader); + } + + public AggregateContext getContext(String ctxName) { + checkRunning(); + if (ROOT.equals(ctxName)) { + return rootContext; + } else if (SYSTEM.equals(ctxName)) { + return systemContext; + } + return (AggregateContext) rootContext.getContext(ctxName); + } + + public AggregateContext getRootContext() { + checkRunning(); + return rootContext; + } + + public SystemAggregateContext getSystemContext() { + checkRunning(); + return systemContext; + } + + public MonitorFactory getMonitorFactory() { + return monitorFactory; + } + + public void registerModelObject(Extensible model) throws ConfigurationException { + assert (model != null) : "Model was null"; + // note do not configure or build model object since the root context will perform a call back + rootContext.registerModelObject(model); + } + + public void registerModelObjects(List<Extensible> models) throws ConfigurationException { + for (Extensible model : models) { + registerModelObject(model); + } + } + + public void registerListener(RuntimeEventListener listener) { + assert (listener != null) : "Listener cannot be null"; + listeners.add(listener); + } + + public void fireEvent(int eventType, Object message) throws EventException { + checkRunning(); + for (RuntimeEventListener listener : listeners) { + listener.onEvent(eventType, message); + } + } + + public AggregateContext getParent() { + return null; // there is no parent + } + + public Object locateService(String serviceName) { + return null; + } + + public Object locateInstance(String serviceName) { + return null; + } + + public Object getInstance(QualifiedName qName) throws TargetException { + return getSystemContext().getInstance(qName); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + // ---------------------------------- + // ConfigurationContext methods + // ---------------------------------- + + public synchronized void build(AggregateContext parent, Extensible model) throws BuilderConfigException { + AssemblyVisitor visitor = new AssemblyVisitor(parent, builders); + visitor.start(model); + } + + public void configure(Extensible model) throws ConfigurationException { + } + + public void wire(ProxyFactory sourceFactory, ProxyFactory targetFactory, Class targetType, boolean downScope, + ScopeContext targetScopeContext) throws BuilderConfigException { + wireBuilder.connect(sourceFactory, targetFactory, targetType, downScope, targetScopeContext); + } + + public void wire(ProxyFactory targetFactory, Class targetType, ScopeContext targetScopeContext) throws BuilderConfigException { + wireBuilder.completeTargetChain(targetFactory, targetType, targetScopeContext); + } + + // ---------------------------------- + // AutowireContext methods + // ---------------------------------- + + public <T> T resolveInstance(Class<T> instanceInterface) throws AutowireResolutionException { + if (MonitorFactory.class.equals(instanceInterface)) { + return instanceInterface.cast(monitorFactory); + } else if (ConfigurationContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } else if (AutowireContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } else if (RuntimeContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } else { + // autowire to system components + return instanceInterface.cast(getSystemContext().resolveInstance(instanceInterface)); + } + } + + // ---------------------------------- + // InstanceContext methods + // ---------------------------------- + + public Object getImplementationInstance() throws TargetException { + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return this; + } + + public Aggregate getAggregate() { + return systemContext.getAggregate(); + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + private void checkRunning() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Context must be in RUNNING state"); + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeMonitor.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeMonitor.java new file mode 100644 index 0000000000..c1b87d6a13 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeMonitor.java @@ -0,0 +1,32 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.runtime; + +import org.apache.tuscany.common.TuscanyException; +import org.apache.tuscany.common.TuscanyRuntimeException; + + +/** + * Serves as a top-level error logging monitor + * + * @version $Rev$ $Date$ + */ +public interface RuntimeMonitor { + + public void log(TuscanyRuntimeException e); + + public void log(TuscanyException e); + +} + diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeScopeStrategy.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeScopeStrategy.java new file mode 100644 index 0000000000..77ddd78d15 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/runtime/RuntimeScopeStrategy.java @@ -0,0 +1,46 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.runtime; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.scope.AbstractScopeStrategy; +import org.apache.tuscany.core.context.scope.AggregateScopeContext; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implements a {@link org.apache.tuscany.core.context.ScopeStrategy} for a runtime context. Specifically, a runtime + * context has only one scope, {@link org.apache.tuscany.model.assembly.Scope#AGGREGATE} + * + * @version $Rev$ $Date$ + */ +public class RuntimeScopeStrategy extends AbstractScopeStrategy { + + public RuntimeScopeStrategy() { + } + + public Map<Scope, ScopeContext> createScopes(EventContext eventContext) { + ScopeContext aggregrateScope = new AggregateScopeContext(eventContext); + Map<Scope, ScopeContext> scopes = new HashMap(); + scopes.put(Scope.AGGREGATE, aggregrateScope); + return scopes; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/annotation/Autowire.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/annotation/Autowire.java new file mode 100644 index 0000000000..bcb06812e8 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/annotation/Autowire.java @@ -0,0 +1,21 @@ +package org.apache.tuscany.core.system.annotation; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * A system annotation to inject an autowired instance + * + * @version $Rev$ $Date$ + */ +@Target( { METHOD, FIELD }) +@Retention(RUNTIME) +public @interface Autowire { + + public boolean required() default true; + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/annotation/ParentContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/annotation/ParentContext.java new file mode 100644 index 0000000000..f3d2c0216b --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/annotation/ParentContext.java @@ -0,0 +1,33 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.annotation; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * A system annotation to inject the parent context + * + * @version $Rev$ $Date$ + */ + +@Target( { METHOD, FIELD }) +@Retention(RUNTIME) +public @interface ParentContext { + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemAssemblyFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemAssemblyFactory.java new file mode 100644 index 0000000000..d230df8dd7 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemAssemblyFactory.java @@ -0,0 +1,38 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.assembly; + +import org.apache.tuscany.model.assembly.AssemblyFactory; + +/** + * A factory for building system assembly model artifacts + * + * @version $Rev$ $Date$ + */ +public interface SystemAssemblyFactory extends AssemblyFactory { + + /** + * Returns an assembly model artifact representing a system component implementation + */ + SystemImplementation createSystemImplementation(); + + /** + * Returns an assembly model artifact representing a system binding + */ + SystemBinding createSystemBinding(); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemBinding.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemBinding.java new file mode 100644 index 0000000000..edc7c87c85 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemBinding.java @@ -0,0 +1,37 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.assembly; + +import org.apache.tuscany.model.assembly.Binding; + +/** + * Represents a system binding + * + * @version $Rev$ $Date$ + */ +public interface SystemBinding extends Binding { + + /** + * Returns the qualified name of the wire target the binding is associated with in component/service form + */ + public String getTargetName(); + + /** + * Sets the qualified name of the wire target the binding is associated with in component/service form + */ + public void setTargetName(String name); +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemImplementation.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemImplementation.java new file mode 100644 index 0000000000..7fae0ebad3 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/SystemImplementation.java @@ -0,0 +1,38 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.assembly; + +import org.apache.tuscany.model.assembly.ComponentImplementation; + +/** + * Represents a system component implementation + * + * @version $Rev$ $Date$ + */ +public interface SystemImplementation extends ComponentImplementation { + + /** + * Returns the implementation class of the system component + */ + Class getImplementationClass(); + + /** + * Sets the implementation class of the system component + */ + void setImplementationClass(Class value); + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemAssemblyFactoryImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemAssemblyFactoryImpl.java new file mode 100644 index 0000000000..668b7dd8b1 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemAssemblyFactoryImpl.java @@ -0,0 +1,41 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.assembly.impl; + +import org.apache.tuscany.core.system.assembly.SystemAssemblyFactory; +import org.apache.tuscany.core.system.assembly.SystemBinding; +import org.apache.tuscany.core.system.assembly.SystemImplementation; +import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl; + +/** + * The default implementation of the system assembly factory + * + * @version $Rev$ $Date$ + */ +public class SystemAssemblyFactoryImpl extends AssemblyFactoryImpl implements SystemAssemblyFactory { + + public SystemAssemblyFactoryImpl() { + } + + public SystemImplementation createSystemImplementation() { + return new SystemImplementationImpl(); + } + + public SystemBinding createSystemBinding() { + return new SystemBindingImpl(); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemBindingImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemBindingImpl.java new file mode 100644 index 0000000000..a9996065e2 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemBindingImpl.java @@ -0,0 +1,41 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.assembly.impl; + +import org.apache.tuscany.core.system.assembly.SystemBinding; +import org.apache.tuscany.model.assembly.impl.BindingImpl; + +/** + * The default implementation of the system binding assembly artifact + * + * @version $Rev$ $Date$ + */ +public class SystemBindingImpl extends BindingImpl implements SystemBinding { + + protected SystemBindingImpl() { + } + + private String name; + + public String getTargetName() { + return name; + } + + public void setTargetName(String name) { + this.name = name; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemImplementationImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemImplementationImpl.java new file mode 100644 index 0000000000..5d54132464 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/assembly/impl/SystemImplementationImpl.java @@ -0,0 +1,94 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.assembly.impl; + +import java.net.URL; + +import org.apache.tuscany.core.config.ComponentTypeIntrospector; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.config.JavaIntrospectionHelper; +import org.apache.tuscany.core.config.impl.Java5ComponentTypeIntrospector; +import org.apache.tuscany.core.system.assembly.SystemImplementation; +import org.apache.tuscany.model.assembly.AssemblyFactory; +import org.apache.tuscany.model.assembly.AssemblyModelContext; +import org.apache.tuscany.model.assembly.ComponentType; +import org.apache.tuscany.model.assembly.Scope; +import org.apache.tuscany.model.assembly.Service; +import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl; +import org.apache.tuscany.model.assembly.impl.ComponentImplementationImpl; + +/** + * The default implementation of the system implementation assembly artifact + * + * @version $Rev$ $Date$ + */ +public class SystemImplementationImpl extends ComponentImplementationImpl implements SystemImplementation { + + private Class<?> implementationClass; + + private AssemblyModelContext modelContext; + + protected SystemImplementationImpl() { + } + + public Class getImplementationClass() { + return implementationClass; + } + + public void setImplementationClass(Class value) { + checkNotFrozen(); + implementationClass = value; + } + + public void initialize(AssemblyModelContext context) { + if (isInitialized()) + return; + this.modelContext = context; + // Initialize the component type + ComponentType componentType = getComponentType(); + if (componentType == null) { + componentType = createComponentType(implementationClass); + setComponentType(componentType); + } + super.initialize(modelContext); + } + + /** + * Creates the component type + */ + private ComponentType createComponentType(Class<?> implClass) { + ComponentType componentType; + String baseName = JavaIntrospectionHelper.getBaseName(implClass); + URL componentTypeFile = implClass.getResource(baseName + ".componentType"); + if (componentTypeFile != null) { + componentType = modelContext.getAssemblyLoader().loadComponentType(componentTypeFile.toString()); + // FIXME workaround for TUSCANY-46 where the scope is not read - default system implementations to MODULE scope + for (Service service : componentType.getServices()) { + service.getServiceContract().setScope(Scope.MODULE); + } + } else { + AssemblyFactory factory = new AssemblyFactoryImpl(); + ComponentTypeIntrospector introspector = new Java5ComponentTypeIntrospector(factory); + try { + componentType = introspector.introspect(implClass); + } catch (ConfigurationException e) { + throw new IllegalArgumentException("Unable to introspect implementation class: " + implClass.getName(), e); + } + } + return componentType; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemComponentContextBuilder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemComponentContextBuilder.java new file mode 100644 index 0000000000..ac65a3de49 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemComponentContextBuilder.java @@ -0,0 +1,383 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.builder; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.builder.BuilderException; +import org.apache.tuscany.core.builder.NoAccessorException; +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.builder.UnknownTypeException; +import org.apache.tuscany.core.config.JavaIntrospectionHelper; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.context.ConfigurationContext; +import org.apache.tuscany.core.context.SystemAggregateContext; +import org.apache.tuscany.core.context.impl.AggregateContextImpl; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.FieldInjector; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.MethodInjector; +import org.apache.tuscany.core.injection.ObjectCreationException; +import org.apache.tuscany.core.injection.ReferenceTargetFactory; +import org.apache.tuscany.core.injection.SDOObjectFactory; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.apache.tuscany.core.runtime.RuntimeContext; +import org.apache.tuscany.core.system.annotation.Autowire; +import org.apache.tuscany.core.system.annotation.ParentContext; +import org.apache.tuscany.core.system.assembly.SystemImplementation; +import org.apache.tuscany.core.system.config.SystemComponentRuntimeConfiguration; +import org.apache.tuscany.core.system.context.SystemAggregateContextImpl; +import org.apache.tuscany.model.assembly.AssemblyModelObject; +import org.apache.tuscany.model.assembly.Component; +import org.apache.tuscany.model.assembly.ComponentImplementation; +import org.apache.tuscany.model.assembly.ConfiguredProperty; +import org.apache.tuscany.model.assembly.ConfiguredReference; +import org.apache.tuscany.model.assembly.ConfiguredService; +import org.apache.tuscany.model.assembly.Module; +import org.apache.tuscany.model.assembly.Scope; +import org.osoa.sca.annotations.ComponentName; +import org.osoa.sca.annotations.Context; +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Init; + +import commonj.sdo.DataObject; + +/** + * Decorates components whose implementation type is a + * {@link org.apache.tuscany.core.system.assembly.SystemImplementation} with the appropriate runtime configuration. + * System components are not proxied. + * + * @version $Rev$ $Date$ + */ +public class SystemComponentContextBuilder implements RuntimeConfigurationBuilder<AggregateContext> { + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemComponentContextBuilder() { + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void build(AssemblyModelObject modelObject, AggregateContext parentContext) throws BuilderException { + if (!(modelObject instanceof Component)) { + return; + } + Component component = (Component) modelObject; + + Class implClass = null; + Scope scope = null; + + // Get the component implementation + ComponentImplementation componentImplementation = component.getComponentImplementation(); + if (componentImplementation instanceof SystemImplementation + && componentImplementation.getRuntimeConfiguration() == null) { + + // The component is a system component, implemented by a Java class + SystemImplementation javaImpl = (SystemImplementation) componentImplementation; + scope = componentImplementation.getComponentType().getServices().get(0).getServiceContract().getScope(); + implClass = javaImpl.getImplementationClass(); + + } else if (componentImplementation instanceof Module) { + if (((Module)componentImplementation).getName().startsWith("org.apache.tuscany.core.system")) { + + // The component is a system module component, fix the implementation class to our implementation + // of system module component context + implClass=SystemAggregateContextImpl.class; + scope = Scope.AGGREGATE; + + } else { + + // The component is an app module component, fix the implementation class to our implementation + // of app module component context + implClass=AggregateContextImpl.class; + scope = Scope.AGGREGATE; + + } + + } else { + return; + } + + // FIXME scope + Set<Field> fields; + Set<Method> methods; + try { + fields = JavaIntrospectionHelper.getAllFields(implClass); + methods = JavaIntrospectionHelper.getAllUniqueMethods(implClass); + String name = component.getName(); + Constructor ctr = implClass.getConstructor((Class[]) null); + + List<Injector> injectors = new ArrayList(); + + // handle properties + List<ConfiguredProperty> configuredProperties = component.getConfiguredProperties(); + if (configuredProperties != null) { + for (ConfiguredProperty property : configuredProperties) { + Injector injector = createPropertyInjector(property, fields, methods); + injectors.add(injector); + } + } + + //FIXME do not inject references on an application module yet + if (implClass!=AggregateContextImpl.class) { + // handle references + List<ConfiguredReference> configuredReferences = component.getConfiguredReferences(); + if (configuredReferences != null) { + for (ConfiguredReference reference : configuredReferences) { + Injector injector = createReferenceInjector(parentContext.getName(), component.getName(), parentContext, + reference, fields, methods); + injectors.add(injector); + } + } + } + + // create factory for the component implementation type + EventInvoker initInvoker = null; + boolean eagerInit = false; + EventInvoker destroyInvoker = null; + for (Field field : fields) { + ComponentName compName = field.getAnnotation(ComponentName.class); + if (compName != null) { + Injector injector = new FieldInjector(field, new SingletonObjectFactory(name)); + injectors.add(injector); + } + Context context = field.getAnnotation(Context.class); + if (context != null) { + Injector injector = new FieldInjector(field, new SingletonObjectFactory(parentContext)); + injectors.add(injector); + } + ParentContext parentField = field.getAnnotation(ParentContext.class); + if (parentField != null) { + if (!(parentContext instanceof AggregateContext)) { + BuilderConfigException e = new BuilderConfigException("Component must be a child of"); + e.setIdentifier(AggregateContext.class.getName()); + throw e; + } + Injector injector = new FieldInjector(field, new SingletonObjectFactory((parentContext))); + injectors.add(injector); + } + Autowire autowire = field.getAnnotation(Autowire.class); + if (autowire != null) { + if (!(parentContext instanceof AutowireContext)) { + BuilderConfigException e = new BuilderConfigException("Parent context must implement"); + e.setIdentifier(AutowireContext.class.getName()); + throw e; + } + AutowireContext ctx = (AutowireContext) parentContext; + // for system aggregate context types, only allow autowire of certain types, otherwise we have a + // chicken-and-egg problem + if (SystemAggregateContext.class.isAssignableFrom(implClass) + && !(field.getType().equals(ConfigurationContext.class) + || field.getType().equals(MonitorFactory.class) + || field.getType().equals(RuntimeContext.class) || field.getType().equals( + AutowireContext.class))) { + BuilderConfigException e = new BuilderConfigException("Illegal autowire type for system context"); + e.setIdentifier(field.getType().getName()); + throw e; + } + + Object o = ctx.resolveInstance(field.getType()); + if (autowire.required() && o == null) { + BuilderConfigException e = new BuilderConfigException("No autowire found for field"); + e.setIdentifier(field.getName()); + throw e; + } + Injector injector = new FieldInjector(field, new SingletonObjectFactory(o)); + injectors.add(injector); + } + } + for (Method method : methods) { + Init init = method.getAnnotation(Init.class); + if (init != null && initInvoker == null) { + initInvoker = new MethodEventInvoker(method); + eagerInit = init.eager(); + continue; + } + Destroy destroy = method.getAnnotation(Destroy.class); + if (destroy != null && destroyInvoker == null) { + destroyInvoker = new MethodEventInvoker(method); + continue; + } + ComponentName compName = method.getAnnotation(ComponentName.class); + if (compName != null) { + Injector injector = new MethodInjector(method, new SingletonObjectFactory(name)); + injectors.add(injector); + } + Context context = method.getAnnotation(Context.class); + if (context != null) { + Injector injector = new MethodInjector(method, new SingletonObjectFactory(parentContext)); + injectors.add(injector); + } + ParentContext parentMethod = method.getAnnotation(ParentContext.class); + if (parentMethod != null) { + if (!(parentContext instanceof AggregateContext)) { + BuilderConfigException e = new BuilderConfigException("Component must be a child of "); + e.setIdentifier(AggregateContext.class.getName()); + throw e; + } + Injector injector = new MethodInjector(method, new SingletonObjectFactory((parentContext))); + injectors.add(injector); + } + Autowire autowire = method.getAnnotation(Autowire.class); + if (autowire != null) { + if (!(parentContext instanceof AutowireContext)) { + BuilderConfigException e = new BuilderConfigException("Parent context must implement)"); + e.setIdentifier(AutowireContext.class.getName()); + throw e; + } + if (method.getParameterTypes() == null || method.getParameterTypes().length != 1) { + BuilderConfigException e = new BuilderConfigException( + "Autowire setter methods must take one parameter"); + e.setIdentifier(method.getName()); + throw e; + } + AutowireContext ctx = (AutowireContext) parentContext; + Class paramType = method.getParameterTypes()[0]; + // for system aggregate context types, only allow autowire of certain types, otherwise we have a + // chicken-and-egg problem + if (SystemAggregateContext.class.isAssignableFrom(implClass) + && !(paramType.equals(ConfigurationContext.class) || paramType.equals(MonitorFactory.class) + || paramType.equals(RuntimeContext.class) || paramType.equals(AutowireContext.class))) { + BuilderConfigException e = new BuilderConfigException("Illegal autowire type for system context"); + e.setIdentifier(paramType.getName()); + throw e; + } + Object o = ctx.resolveInstance(paramType); + if (autowire.required() && o == null) { + BuilderConfigException e = new BuilderConfigException("No autowire found for method "); + e.setIdentifier(method.getName()); + throw e; + } + + Injector injector = new MethodInjector(method, new SingletonObjectFactory(o)); + injectors.add(injector); + } + } + // decorate the logical model + SystemComponentRuntimeConfiguration config = new SystemComponentRuntimeConfiguration(name, + JavaIntrospectionHelper.getDefaultConstructor(implClass), injectors, eagerInit, initInvoker, + destroyInvoker, scope); + componentImplementation.setRuntimeConfiguration(config); + } catch (BuilderConfigException e) { + e.addContextName(component.getName()); + e.addContextName(parentContext.getName()); + throw e; + } catch (NoSuchMethodException e) { + BuilderConfigException ce = new BuilderConfigException("Class does not have a no-arg constructor", e); + ce.setIdentifier(implClass.getName()); + throw ce; + } + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + /** + * Creates an <code>Injector</code> for component properties + */ + private Injector createPropertyInjector(ConfiguredProperty property, Set<Field> fields, Set<Method> methods) + throws NoAccessorException { + Object value = property.getValue(); + String propName = property.getProperty().getName(); + // @FIXME is this how to get property type of object + Class type = value.getClass(); + + // There is no efficient way to do this + Method method = null; + Field field = JavaIntrospectionHelper.findClosestMatchingField(propName, type, fields); + if (field == null) { + method = JavaIntrospectionHelper.findClosestMatchingMethod(propName, new Class[] { type }, methods); + if (method == null) { + throw new NoAccessorException(propName); + } + } + Injector injector = null; + // FIXME support types other than String + if (value instanceof DataObject) { + if (field != null) { + injector = new FieldInjector(field, new SDOObjectFactory((DataObject) value)); + } else { + injector = new MethodInjector(method, new SDOObjectFactory((DataObject) value)); + } + } else if (JavaIntrospectionHelper.isImmutable(type)) { + if (field != null) { + injector = new FieldInjector(field, new SingletonObjectFactory(value)); + } else { + injector = new MethodInjector(method, new SingletonObjectFactory(value)); + } + } else { + if (field != null) { + throw new UnknownTypeException(field.getName()); + } else { + throw new UnknownTypeException(method.getName()); + } + } + return injector; + + } + + /** + * Creates an <code>Injector</code> for service references + */ + private Injector createReferenceInjector(String moduleName, String componentName, AggregateContext parentContext, + ConfiguredReference reference, Set<Field> fields, Set<Method> methods) throws NoAccessorException, + BuilderConfigException { + String refName = reference.getReference().getName(); + List<ConfiguredService> services = reference.getTargetConfiguredServices(); + Class type; + if (services.size() == 1) { + // get the interface + type = reference.getReference().getServiceContract().getInterface(); + } else { + // FIXME do we support arrays? + type = List.class; + } + Method method = null; + Field field = JavaIntrospectionHelper.findClosestMatchingField(refName, type, fields); + if (field == null) { + method = JavaIntrospectionHelper.findClosestMatchingMethod(refName, new Class[] { type }, methods); + if (method == null) { + throw new NoAccessorException(refName); + } + } + Injector injector; + try { + if (field != null) { + injector = new FieldInjector(field, new ReferenceTargetFactory(reference, parentContext)); + } else { + injector = new MethodInjector(method, new ReferenceTargetFactory(reference, parentContext)); + } + } catch (ObjectCreationException e) { + BuilderConfigException ce = new BuilderConfigException("Error configuring reference", e); + ce.setIdentifier(refName); + throw ce; + } + return injector; + + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemEntryPointBuilder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemEntryPointBuilder.java new file mode 100644 index 0000000000..6520fc0557 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemEntryPointBuilder.java @@ -0,0 +1,63 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.builder; + +import org.apache.tuscany.core.builder.BuilderException; +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.injection.FactoryInitException; +import org.apache.tuscany.core.injection.ReferenceTargetFactory; +import org.apache.tuscany.core.system.assembly.SystemBinding; +import org.apache.tuscany.core.system.config.SystemEntryPointRuntimeConfiguration; +import org.apache.tuscany.model.assembly.AssemblyModelObject; +import org.apache.tuscany.model.assembly.EntryPoint; + +/** + * Decorates the logical model with entry point context configuration builders + * + * @version $Rev$ $Date$ + */ +public class SystemEntryPointBuilder implements RuntimeConfigurationBuilder<AggregateContext> { + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemEntryPointBuilder() { + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void build(AssemblyModelObject modelObject, AggregateContext context) throws BuilderException { + if (!(modelObject instanceof EntryPoint)) { + return; + } + EntryPoint entryPoint = (EntryPoint) modelObject; + if (!(entryPoint.getBindings().get(0) instanceof SystemBinding) + || entryPoint.getConfiguredReference().getRuntimeConfiguration() != null) { + return; + } + try { + SystemEntryPointRuntimeConfiguration config = new SystemEntryPointRuntimeConfiguration(entryPoint.getName(), + new ReferenceTargetFactory(entryPoint.getConfiguredReference(), context)); + entryPoint.getConfiguredReference().setRuntimeConfiguration(config); + } catch (FactoryInitException e) { + e.addContextName(entryPoint.getName()); + e.addContextName(context.getName()); + throw e; + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemExternalServiceBuilder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemExternalServiceBuilder.java new file mode 100644 index 0000000000..dc00e6505f --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/builder/SystemExternalServiceBuilder.java @@ -0,0 +1,77 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.builder; + +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.builder.BuilderException; +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.injection.ReferenceTargetFactory; +import org.apache.tuscany.core.system.assembly.SystemBinding; +import org.apache.tuscany.core.system.config.SystemExternalServiceRuntimeConfiguration; +import org.apache.tuscany.core.system.injection.AutowireFactory; +import org.apache.tuscany.model.assembly.AssemblyModelObject; +import org.apache.tuscany.model.assembly.ExternalService; + +/** + * Creates runtime configurations for system type external services + * + * @version $Rev$ $Date$ + */ +public class SystemExternalServiceBuilder implements RuntimeConfigurationBuilder<AggregateContext> { + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemExternalServiceBuilder() { + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void build(AssemblyModelObject modelObject, AggregateContext context) throws BuilderException { + if (!(modelObject instanceof ExternalService)) { + return; + } + ExternalService externalService = (ExternalService) modelObject; + if (externalService.getConfiguredService() != null + && externalService.getConfiguredService().getRuntimeConfiguration() != null) { + return; + } else if (externalService.getBindings() == null || externalService.getBindings().size() < 1 + || !(externalService.getBindings().get(0) instanceof SystemBinding)) { + return; + } + SystemBinding binding = (SystemBinding)externalService.getBindings().get(0); + if (binding.getTargetName() != null) { + SystemExternalServiceRuntimeConfiguration config = new SystemExternalServiceRuntimeConfiguration(externalService + .getName(), new ReferenceTargetFactory(binding.getTargetName(), context)); + externalService.getConfiguredService().setRuntimeConfiguration(config); + } else if (externalService.getConfiguredService().getService().getServiceContract().getInterface() != null) { + // autowire + Class<?> claz = externalService.getConfiguredService().getService().getServiceContract().getInterface(); + if (claz == null) { + BuilderException e = new BuilderConfigException("Interface type not specified"); + e.setIdentifier(externalService.getName()); + e.addContextName(externalService.getName()); + e.addContextName(context.getName()); + throw e; + } + SystemExternalServiceRuntimeConfiguration config = new SystemExternalServiceRuntimeConfiguration(externalService + .getName(), new AutowireFactory(claz, (AutowireContext) context)); + externalService.getConfiguredService().setRuntimeConfiguration(config); + } + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemComponentRuntimeConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemComponentRuntimeConfiguration.java new file mode 100644 index 0000000000..cf05059b90 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemComponentRuntimeConfiguration.java @@ -0,0 +1,140 @@ +package org.apache.tuscany.core.system.config; + +import java.lang.reflect.Constructor; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.core.builder.ContextCreationException; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.system.context.SystemComponentContext; +import org.apache.tuscany.model.assembly.Scope; + +/** + * A RuntimeConfiguration that handles system component implementation types + * + * @version $Rev$ $Date$ + */ +public class SystemComponentRuntimeConfiguration implements RuntimeConfiguration<InstanceContext> { + + // the component name as configured in the hosting module + private String name; + + // the implementation type constructor + private Constructor ctr; + + // injectors for properties, references and other metadata values such as @Context + private List<Injector> setters; + + // an invoker for a method decorated with @Init + private EventInvoker init; + + // whether the component should be eagerly initialized when its scope starts + private boolean eagerInit; + + // an invoker for a method decorated with @Destroy + private EventInvoker destroy; + + // the scope of the implementation instance + private Scope scope; + + // if the component implementation scope is stateless + private boolean stateless; + + // if the component implementation is an aggregate context + private boolean isAggregate; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + /** + * Creates the runtime configuration + * + * @param name the SCDL name of the component the context refers to + * @param ctr the implementation type constructor + * @param setters a collection of <code>Injectors</code> used to configure properties, references and other meta + * data values on implementation instances + * @param eagerInit whether the component should be eagerly initialized + * @param init an <code>Invoker</code> pointing to a method on the implementation type decorated with + * <code>@Init</code> + * @param destroy an <code>Invoker</code> pointing to a method on the implementation type decorated with + * <code>@Destroy</code> + * @param scope the scope of the component implementation type + */ + public SystemComponentRuntimeConfiguration(String name, Constructor ctr, List<Injector> setters, boolean eagerInit, + EventInvoker init, EventInvoker destroy, Scope scope) { + assert (name != null) : "Name was null"; + assert (ctr != null) : "Constructor was null"; + assert (setters != null) : "Setters were null"; + this.name = name; + this.ctr = ctr; + this.isAggregate = AggregateContext.class.isAssignableFrom(ctr.getDeclaringClass()); + this.setters = setters; + this.eagerInit = eagerInit; + this.init = init; + this.destroy = destroy; + this.scope = scope; + stateless = (scope == Scope.INSTANCE); + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public String getName() { + return name; + } + + public Scope getScope() { + return scope; + } + + public InstanceContext createInstanceContext() throws ContextCreationException { + if (isAggregate) { + // aggregate context types are themselves an instance context + PojoObjectFactory objectFactory = new PojoObjectFactory(ctr, null, setters); + AggregateContext ctx = (AggregateContext) objectFactory.getInstance(); + ctx.setName(name); + return ctx; + } else { + PojoObjectFactory objectFactory = new PojoObjectFactory(ctr, null, setters); + return new SystemComponentContext(name, objectFactory, eagerInit, init, destroy, stateless); + } + } + + // -- Proxy + + public void prepare() { + } + + public void addTargetProxyFactory(String serviceName, ProxyFactory factory) { + throw new UnsupportedOperationException(); + } + + public ProxyFactory getTargetProxyFactory(String serviceName) { + return null; + } + + public Map<String, ProxyFactory> getTargetProxyFactories() { + return null; + } + + public void addSourceProxyFactory(String referenceName, ProxyFactory factory) { + throw new UnsupportedOperationException(); + } + + public ProxyFactory getSourceProxyFactory(String referenceName) { + return null; + } + + public Map<String, ProxyFactory> getSourceProxyFactories() { + return null; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemEntryPointRuntimeConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemEntryPointRuntimeConfiguration.java new file mode 100644 index 0000000000..f6c25e9b86 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemEntryPointRuntimeConfiguration.java @@ -0,0 +1,92 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.config; + +import java.util.Map; + +import org.apache.tuscany.core.builder.ContextCreationException; +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.EntryPointContext; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.system.context.SystemEntryPointContext; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Creates {@link SystemEntryPointContext} instances based on an entry point configuration in an assembly model + * + * @version $Rev$ $Date$ + */ +public class SystemEntryPointRuntimeConfiguration implements RuntimeConfiguration<EntryPointContext> { + + // the name of the entry point + private String name; + + // the factory for returning a reference to the implementation instance of the component exposed by the entry point + private ObjectFactory factory; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemEntryPointRuntimeConfiguration(String name, ObjectFactory factory) { + this.name = name; + this.factory = factory; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public EntryPointContext createInstanceContext() throws ContextCreationException { + return new SystemEntryPointContext(name, factory); + } + + public Scope getScope() { + return Scope.MODULE; + } + + public String getName() { + return name; + } + + // -- Proxy + public void prepare() { + } + + public void addTargetProxyFactory(String serviceName, ProxyFactory pFactory) { + throw new UnsupportedOperationException(); + } + + public ProxyFactory getTargetProxyFactory(String serviceName) { + return null; + } + + public Map<String, ProxyFactory> getTargetProxyFactories() { + return null; + } + + public void addSourceProxyFactory(String referenceName, ProxyFactory pFactory) { + throw new UnsupportedOperationException(); + } + + public ProxyFactory getSourceProxyFactory(String referenceName) { + return null; + } + + public Map<String, ProxyFactory> getSourceProxyFactories() { + return null; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemExternalServiceRuntimeConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemExternalServiceRuntimeConfiguration.java new file mode 100644 index 0000000000..789982bdcf --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemExternalServiceRuntimeConfiguration.java @@ -0,0 +1,97 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.config; + +import java.util.Map; + +import org.apache.tuscany.core.builder.ContextCreationException; +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.ExternalServiceContext; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.system.context.SystemExternalServiceContext; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Creates system type external service contexts + * + * @see org.apache.tuscany.core.context.ExternalServiceContext + * @see org.apache.tuscany.core.system.context.SystemExternalServiceContext + * + * @version $Rev$ $Date$ + */ +public class SystemExternalServiceRuntimeConfiguration implements RuntimeConfiguration<ExternalServiceContext> { + + // the name of the external service + private String name; + + // the factory for returning a reference to the implementation instance of the component represented by the external service + private ObjectFactory factory; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemExternalServiceRuntimeConfiguration(String name, ObjectFactory factory) { + assert (name != null) : "Name was null"; + assert (factory != null) : "Object factory was null"; + this.name = name; + this.factory = factory; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public Scope getScope() { + return Scope.MODULE; + } + + public String getName() { + return name; + } + + public ExternalServiceContext createInstanceContext() throws ContextCreationException { + return new SystemExternalServiceContext(name, factory); + } + + // -- Proxy + public void prepare() { + } + + public void addTargetProxyFactory(String serviceName, ProxyFactory pFactory) { + throw new UnsupportedOperationException(); + } + + public ProxyFactory getTargetProxyFactory(String serviceName) { + return null; + } + + public Map<String, ProxyFactory> getTargetProxyFactories() { + return null; + } + + public void addSourceProxyFactory(String referenceName, ProxyFactory pFactory) { + throw new UnsupportedOperationException(); + } + + public ProxyFactory getSourceProxyFactory(String referenceName) { + return null; + } + + public Map<String, ProxyFactory> getSourceProxyFactories() { + return null; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemObjectRuntimeConfiguration.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemObjectRuntimeConfiguration.java new file mode 100644 index 0000000000..06acb12deb --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/config/SystemObjectRuntimeConfiguration.java @@ -0,0 +1,92 @@ +/** + * + * Copyright 2005 BEA Systems Inc. + * Copyright 2005 International Business Machines Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.config; + +import java.util.Map; + +import org.apache.tuscany.core.builder.ContextCreationException; +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.system.context.SystemComponentContext; +import org.apache.tuscany.model.assembly.Scope; + +/** + * A RuntimeConfiguration that contains the configuration needed to convert a simple + * Java Object into a component. The object is assumed to be fully initialized and + * will always be added with MODULE scope. + * + * @version $Rev$ $Date$ + */ +public class SystemObjectRuntimeConfiguration implements RuntimeConfiguration { + private final String name; + private final ObjectFactory<?> objectFactory; + + /** + * Construct a RuntimeConfiguration for the supplied Java Object. + * + * @param name the name to be assigned to the resulting component + * @param instance the Java Object that provides the implementation + */ + public SystemObjectRuntimeConfiguration(String name, Object instance) { + this.name = name; + objectFactory = new SingletonObjectFactory(instance); + } + + public Context createInstanceContext() throws ContextCreationException { + return new SystemComponentContext(name, objectFactory, false, null, null, false); + } + + public Scope getScope() { + return Scope.MODULE; + } + + public String getName() { + return name; + } + + public void prepare() { + throw new UnsupportedOperationException(); + } + + public void addTargetProxyFactory(String serviceName, ProxyFactory factory) { + throw new UnsupportedOperationException(); + } + + public ProxyFactory getTargetProxyFactory(String serviceName) { + throw new UnsupportedOperationException(); + } + + public Map getTargetProxyFactories() { + throw new UnsupportedOperationException(); + } + + public void addSourceProxyFactory(String referenceName, ProxyFactory factory) { + throw new UnsupportedOperationException(); + } + + public ProxyFactory getSourceProxyFactory(String referenceName) { + throw new UnsupportedOperationException(); + } + + public Map getSourceProxyFactories() { + throw new UnsupportedOperationException(); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemAggregateContextImpl.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemAggregateContextImpl.java new file mode 100644 index 0000000000..a2efc35ac1 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemAggregateContextImpl.java @@ -0,0 +1,666 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.context; + +import static org.apache.tuscany.core.context.EventContext.HTTP_SESSION; +import static org.apache.tuscany.core.context.EventContext.REQUEST_END; +import static org.apache.tuscany.core.context.EventContext.SESSION_NOTIFY; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.context.AutowireResolutionException; +import org.apache.tuscany.core.context.ConfigurationContext; +import org.apache.tuscany.core.context.ContextInitException; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.DuplicateNameException; +import org.apache.tuscany.core.context.EntryPointContext; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.EventException; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.ScopeRuntimeException; +import org.apache.tuscany.core.context.ScopeStrategy; +import org.apache.tuscany.core.context.SimpleComponentContext; +import org.apache.tuscany.core.context.SystemAggregateContext; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.context.impl.EventContextImpl; +import org.apache.tuscany.core.invocation.jdk.JDKProxyFactoryFactory; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.invocation.spi.ProxyFactoryFactory; +import org.apache.tuscany.core.message.MessageFactory; +import org.apache.tuscany.core.message.impl.MessageFactoryImpl; +import org.apache.tuscany.core.runtime.RuntimeContext; +import org.apache.tuscany.core.system.annotation.Autowire; +import org.apache.tuscany.core.system.annotation.ParentContext; +import org.apache.tuscany.core.system.assembly.SystemBinding; +import org.apache.tuscany.core.system.config.SystemObjectRuntimeConfiguration; +import org.apache.tuscany.model.assembly.Aggregate; +import org.apache.tuscany.model.assembly.Component; +import org.apache.tuscany.model.assembly.EntryPoint; +import org.apache.tuscany.model.assembly.Extensible; +import org.apache.tuscany.model.assembly.ExternalService; +import org.apache.tuscany.model.assembly.Module; +import org.apache.tuscany.model.assembly.AggregatePart; +import org.apache.tuscany.model.assembly.Scope; +import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl; + +/** + * Implements an aggregate context for system components. By default a system context uses the scopes specified by + * {@link org.apache.tuscany.core.system.context.SystemScopeStrategy}. In addition, it implements an autowire policy + * where entry points configured with a {@link org.apache.tuscany.core.system.assembly.SystemBinding} are matched + * according to their exposed interface. A system context may contain child aggregate contexts but an entry point in a + * child context will only be outwardly accessible if there is an entry point that exposes it configured in the + * top-level system context. + * + * @version $Rev$ $Date$ + */ +public class SystemAggregateContextImpl extends AbstractContext implements SystemAggregateContext { + + public static final int DEFAULT_WAIT = 1000 * 60; + + // ---------------------------------- + // Fields + // ---------------------------------- + + // The parent context, if one exists + @ParentContext + protected AggregateContext parentContext; + + // The parent configuration context, if one exists + @Autowire(required = false) + protected ConfigurationContext configurationContext; + + // The system monitor factory + @Autowire(required = false) + protected MonitorFactory monitorFactory; + + // The logical model representing the module assembly + // protected ModuleComponent moduleComponent; + protected Module module; + + protected List<RuntimeConfiguration<InstanceContext>> configurations = new ArrayList(); + + protected ScopeStrategy scopeStrategy; + + // The event context for associating context events to threads + protected EventContext eventContext; + + // The scopes for this context + protected Map<Scope, ScopeContext> scopeContexts; + + protected Map<Scope, ScopeContext> immutableScopeContexts; + + // A component context name to scope context index + protected Map<String, ScopeContext> scopeIndex; + + // Listeners for context events + protected List<RuntimeEventListener> listeners = new CopyOnWriteArrayList(); + + // Blocking latch to ensure the module is initialized exactly once prior to servicing requests + protected CountDownLatch initializeLatch = new CountDownLatch(1); + + // Indicates whether the module context has been initialized + protected boolean initialized; + + // a mapping of service type to component name + private Map<Class, NameToScope> autowireIndex = new ConcurrentHashMap(); + + @Autowire(required = false) + private AutowireContext autowireContext; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemAggregateContextImpl() { + super(); + scopeIndex = new ConcurrentHashMap(); + // FIXME the assembly factory should be injected here + module = new AssemblyFactoryImpl().createModule(); + eventContext = new EventContextImpl(); + scopeStrategy = new SystemScopeStrategy(); + } + + public SystemAggregateContextImpl(String name, AggregateContext parent, AutowireContext autowire, ScopeStrategy strategy, + EventContext ctx, ConfigurationContext configCtx, MonitorFactory factory) { + super(name); + this.parentContext = parent; + this.autowireContext = autowire; + this.scopeStrategy = strategy; + this.eventContext = ctx; + this.configurationContext = configCtx; + this.monitorFactory = factory; + scopeIndex = new ConcurrentHashMap(); + // FIXME the assembly factory should be injected here + module = new AssemblyFactoryImpl().createModule(); + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public void start() { + synchronized (initializeLatch) { + try { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Context not in UNINITIALIZED state"); + } + + lifecycleState = INITIALIZING; + initializeScopes(); + + Map<Scope, List<RuntimeConfiguration<SimpleComponentContext>>> configurationsByScope = new HashMap(); + if (configurations != null) { + for (RuntimeConfiguration config : configurations) { + // FIXME scopes are defined at the interface level + Scope scope = config.getScope(); + // ensure duplicate names were not added before the context was started + if (scopeIndex.get(config.getName()) != null) { + throw new DuplicateNameException(config.getName()); + } + scopeIndex.put(config.getName(), scopeContexts.get(scope)); + List<RuntimeConfiguration<SimpleComponentContext>> list = configurationsByScope.get(scope); + if (list == null) { + list = new ArrayList(); + configurationsByScope.put(scope, list); + } + list.add(config); + } + } + for (EntryPoint ep : module.getEntryPoints()) { + registerAutowire(ep); + } + for (Component component : module.getComponents()) { + registerAutowire(component); + } + for (ExternalService es : module.getExternalServices()) { + registerAutowire(es); + } + for (Map.Entry entries : configurationsByScope.entrySet()) { + // register configurations with scope contexts + ScopeContext scope = scopeContexts.get(entries.getKey()); + scope.registerConfigurations((List<RuntimeConfiguration<InstanceContext>>) entries.getValue()); + } + for (ScopeContext scope : scopeContexts.values()) { + // register scope contexts as a listeners for events in the aggregate context + registerListener(scope); + scope.start(); + } + lifecycleState = RUNNING; + } catch (ConfigurationException e) { + lifecycleState = ERROR; + throw new ContextInitException(e); + } catch (CoreRuntimeException e) { + lifecycleState = ERROR; + e.addContextName(getName()); + throw e; + } finally { + initialized = true; + // release the latch and allow requests to be processed + initializeLatch.countDown(); + } + } + } + + public void stop() { + if (lifecycleState == STOPPED) { + return; + } + // need to block a start until reset is complete + initializeLatch = new CountDownLatch(2); + lifecycleState = STOPPING; + initialized = false; + if (scopeContexts != null) { + for (ScopeContext scope : scopeContexts.values()) { + try { + if (scope.getLifecycleState() == ScopeContext.RUNNING) { + scope.stop(); + } + } catch (ScopeRuntimeException e) { + // log.error("Error stopping scope container [" + scopeContainers[i].getName() + "]", e); + } + } + } + scopeContexts = null; + scopeIndex.clear(); + // allow initialized to be called + initializeLatch.countDown(); + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void setModule(Module module) { + assert (module != null) : "Module cannot be null"; + name = module.getName(); + this.module = module; + } + + public void addContextListener(LifecycleEventListener listener) { + super.addContextListener(listener); + } + + public void setEventContext(EventContext eventContext) { + this.eventContext = eventContext; + } + + public void setMonitorFactory(MonitorFactory factory) { + this.monitorFactory = factory; + } + + public AggregateContext getParent() { + return parentContext; + } + + public void registerModelObjects(List<Extensible> models) throws ConfigurationException { + assert (models != null) : "Model object collection was null"; + for (Extensible model : models) { + registerModelObject(model); + } + } + + public void registerModelObject(Extensible model) throws ConfigurationException { + assert (model != null) : "Model object was null"; + initializeScopes(); + if (configurationContext != null) { + try { + configurationContext.configure(model); + configurationContext.build(this, model); + } catch (ConfigurationException e) { + e.addContextName(getName()); + throw e; + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + RuntimeConfiguration<InstanceContext> configuration = null; + if (model instanceof Module) { + // merge new module definition with the existing one + Module oldModule = module; + Module newModule = (Module) model; + module = newModule; + for (Component component : newModule.getComponents()) { + configuration = (RuntimeConfiguration<InstanceContext>) component.getComponentImplementation() + .getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.addContextName(component.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(component); + } + for (EntryPoint ep : newModule.getEntryPoints()) { + configuration = (RuntimeConfiguration<InstanceContext>) ep.getConfiguredReference().getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.setIdentifier(ep.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(ep); + } + for (ExternalService service : newModule.getExternalServices()) { + configuration = (RuntimeConfiguration<InstanceContext>) service.getConfiguredService().getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.setIdentifier(service.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(service); + } + // merge existing module component assets + module.getComponents().addAll(oldModule.getComponents()); + module.getEntryPoints().addAll(oldModule.getEntryPoints()); + module.getExternalServices().addAll(oldModule.getExternalServices()); + } else { + if (model instanceof Component) { + Component component = (Component) model; + module.getComponents().add(component); + configuration = (RuntimeConfiguration<InstanceContext>) component.getComponentImplementation() + .getRuntimeConfiguration(); + } else if (model instanceof EntryPoint) { + EntryPoint ep = (EntryPoint) model; + module.getEntryPoints().add(ep); + configuration = (RuntimeConfiguration<InstanceContext>) ep.getConfiguredReference().getRuntimeConfiguration(); + } else if (model instanceof ExternalService) { + ExternalService service = (ExternalService) model; + module.getExternalServices().add(service); + configuration = (RuntimeConfiguration<InstanceContext>) service.getConfiguredService().getRuntimeConfiguration(); + } else { + BuilderConfigException e = new BuilderConfigException("Unknown model type"); + e.setIdentifier(model.getClass().getName()); + e.addContextName(getName()); + throw e; + } + if (configuration == null) { + ConfigurationException e = new ConfigurationException( + "Runtime configuration not set. Ensure a runtime configuration builder is registered for the component implementation type"); + if (model instanceof AggregatePart) { + e.setIdentifier(((AggregatePart) model).getName()); + } + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(model); + } + } + + public void registerJavaObject(String componentName, Object instance) throws ConfigurationException { + registerConfiguration(new SystemObjectRuntimeConfiguration(componentName, instance)); + } + + protected void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) throws ConfigurationException { + if (lifecycleState == RUNNING) { + if (scopeIndex.get(configuration.getName()) != null) { + throw new DuplicateNameException(configuration.getName()); + } + ScopeContext scope = scopeContexts.get(configuration.getScope()); + if (scope == null) { + ConfigurationException e = new ConfigurationException("Component has an unknown scope"); + e.addContextName(configuration.getName()); + e.addContextName(getName()); + throw e; + } + scope.registerConfiguration(configuration); + scopeIndex.put(configuration.getName(), scope); + } else { + configurations.add(configuration); + } + + } + + public void registerListener(RuntimeEventListener listener) { + assert (listener != null) : "Listener cannot be null"; + listeners.add(listener); + } + + public void fireEvent(int eventType, Object message) throws EventException { + checkInit(); + if (eventType == SESSION_NOTIFY) { + // update context + eventContext.setIdentifier(HTTP_SESSION, message); + } else if (eventType == REQUEST_END) { + // be very careful with pooled threads, ensuring threadlocals are cleaned up + eventContext.clearIdentifier(HTTP_SESSION); + } + for (RuntimeEventListener listener : listeners) { + listener.onEvent(eventType, message); + } + } + + public InstanceContext getContext(String componentName) { + checkInit(); + assert (componentName != null) : "Name was null"; + ScopeContext scope = scopeIndex.get(componentName); + if (scope == null) { + return null; + } + return scope.getContext(componentName); + + } + + /** + * @see org.apache.tuscany.core.context.AggregateContext#getAggregate() + */ + public Aggregate getAggregate() { + return module; + } + + public Object getInstance(QualifiedName qName) throws TargetException { + return getInstance(qName, true); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + assert (qName != null) : "Name was null "; + // use the port name to get the context since entry points ports + ScopeContext scope = scopeIndex.get(qName.getPortName()); + if (scope == null) { + return null; + } + InstanceContext ctx = scope.getContext(qName.getPortName()); + if (!(ctx instanceof EntryPointContext)) { + TargetException e = new TargetException("Target not an entry point"); + e.setIdentifier(qName.getQualifiedName()); + e.addContextName(name); + throw e; + } + return ctx.getInstance(null, notify); + } + + public Object locateInstance(String qualifiedName) throws TargetException { + checkInit(); + QualifiedName qName = new QualifiedName(qualifiedName); + ScopeContext scope = scopeIndex.get(qName.getPartName()); + if (scope == null) { + TargetException e = new TargetException("Component not found"); + e.setIdentifier(qualifiedName); + e.addContextName(getName()); + throw e; + } + InstanceContext ctx = scope.getContext(qName.getPartName()); + try { + return ctx.getInstance(qName, true); + } catch (TargetException e) { + e.addContextName(getName()); + throw e; + } + } + + // ---------------------------------- + // InstanceContext methods + // ---------------------------------- + + public Object getImplementationInstance() throws TargetException { + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return this; + } + + public Map<Scope, ScopeContext> getScopeContexts() { + initializeScopes(); + return immutableScopeContexts; + } + + // ---------------------------------- + // Protected methods + // ---------------------------------- + + /** + * Blocks until the module context has been initialized + */ + protected void checkInit() { + if (!initialized) { + try { + /* block until the module has initialized */ + boolean success = initializeLatch.await(DEFAULT_WAIT, TimeUnit.MILLISECONDS); + if (!success) { + throw new ContextInitException("Timeout waiting for module context to initialize"); + } + } catch (InterruptedException e) { // should not happen + } + } + + } + + protected void initializeScopes() { + if (scopeContexts == null) { + scopeContexts = scopeStrategy.createScopes(eventContext); + immutableScopeContexts = Collections.unmodifiableMap(scopeContexts); + } + } + + // //////////////////////////// + + // ---------------------------------- + // AutowireContext methods + // ---------------------------------- + + // FIXME These should be removed and configured + private static final MessageFactory messageFactory = new MessageFactoryImpl(); + + private static final ProxyFactoryFactory proxyFactoryFactory = new JDKProxyFactoryFactory(); + + public <T> T resolveInstance(Class<T> instanceInterface) throws AutowireResolutionException { + if (RuntimeContext.class.equals(instanceInterface)) { + return autowireContext.resolveInstance(instanceInterface); + } else if (MonitorFactory.class.equals(instanceInterface)) { + return instanceInterface.cast(monitorFactory); + } else if (ConfigurationContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } else if (AggregateContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } else if (AutowireContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } else if (MessageFactory.class.equals(instanceInterface)) { + return instanceInterface.cast(messageFactory); + } else if (ProxyFactoryFactory.class.equals(instanceInterface)) { + return instanceInterface.cast(proxyFactoryFactory); + } + + NameToScope mapping = autowireIndex.get(instanceInterface); + if (mapping != null) { + try { + return instanceInterface.cast(mapping.getScopeContext().getInstance(mapping.getName())); + } catch (TargetException e) { + AutowireResolutionException ae = new AutowireResolutionException("Autowire instance not found", e); + ae.addContextName(getName()); + throw ae; + } + } + return null; + } + + private void registerAutowire(Extensible model) throws ConfigurationException { + if (lifecycleState == INITIALIZING || lifecycleState == INITIALIZED || lifecycleState == RUNNING) { + // only autowire entry points with system bindings + if (model instanceof EntryPoint) { + EntryPoint ep = (EntryPoint) model; + if (ep.getBindings() != null) { + if (ep.getBindings().get(0) instanceof SystemBinding) { + ScopeContext scope = scopeContexts.get(((RuntimeConfiguration) ep.getConfiguredReference() + .getRuntimeConfiguration()).getScope()); + if (scope == null) { + ConfigurationException ce = new ConfigurationException("Scope not found for entry point"); + ce.setIdentifier(ep.getName()); + ce.addContextName(getName()); + throw ce; + } + NameToScope mapping = new NameToScope(new QualifiedName(ep.getName()), scope); + autowireIndex.put(ep.getConfiguredService().getService().getServiceContract().getInterface(), mapping); + } + } + } + } + } + + // ---------------------------------- + // ConfigurationContext methods + // ---------------------------------- + + public void configure(Extensible model) throws ConfigurationException { + if (configurationContext != null) { + configurationContext.configure(model); + } + } + + public void build(AggregateContext parent, Extensible model) throws BuilderConfigException { + if (configurationContext != null) { + configurationContext.build(parent, model); + } + } + + public void wire(ProxyFactory sourceFactory, ProxyFactory targetFactory, Class targetType, boolean downScope, + ScopeContext targetScopeContext) throws BuilderConfigException { + if (configurationContext != null) { + try { + configurationContext.wire(sourceFactory, targetFactory, targetType, downScope, targetScopeContext); + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + } + + public void wire(ProxyFactory targetFactory, Class targetType, ScopeContext targetScopeContext) throws BuilderConfigException { + if (configurationContext != null) { + try { + configurationContext.wire(targetFactory, targetType, targetScopeContext); + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + } + + // ---------------------------------- + // Inner classes + // ---------------------------------- + + /** + * Maps a context name to a scope + */ + private class NameToScope { + + private QualifiedName epName; + + private ScopeContext scope; + + public NameToScope(QualifiedName epName, ScopeContext scope) { + this.epName = epName; + this.scope = scope; + } + + public QualifiedName getName() { + return epName; + } + + public ScopeContext getScopeContext() { + return scope; + } + + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemComponentContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemComponentContext.java new file mode 100644 index 0000000000..4418f52e19 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemComponentContext.java @@ -0,0 +1,198 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.context; + +import java.util.Iterator; + +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.ContextInitException; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.SimpleComponentContext; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.ObjectCallbackException; +import org.apache.tuscany.core.injection.ObjectCreationException; + +/** + * Manages system component implementation instances + * + * @version $Rev$ $Date$ + */ +public class SystemComponentContext extends AbstractContext implements SimpleComponentContext { + + private boolean eagerInit; + + private EventInvoker initInvoker; + + private EventInvoker destroyInvoker; + + private Injector componentName; + + private Injector moduleContext; + + private boolean stateless; + + // the cached target instance + private Object cachedTargetInstance; + + // responsible for creating a new implementation instance with injected references and properties + private ObjectFactory objectFactory; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemComponentContext(String name, ObjectFactory objectFactory, boolean eagerInit, EventInvoker initInvoker, + EventInvoker destroyInvoker, boolean stateless) { + super(name); + assert (objectFactory != null) : "Object factory was null"; + if (eagerInit == true && initInvoker == null) { + throw new AssertionError("No intialization method found for eager init implementation"); + } + this.objectFactory = objectFactory; + + this.eagerInit = eagerInit; + this.initInvoker = initInvoker; + this.destroyInvoker = destroyInvoker; + this.stateless = stateless; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void setName(String name) { + super.setName(name); + } + + protected int type; + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public synchronized Object getInstance(QualifiedName qName) throws TargetException { + return getInstance(qName, true); + } + + public synchronized Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + if (cachedTargetInstance != null) { + return cachedTargetInstance; // already cached, just return + } + + if (getLifecycleState() == ERROR || getLifecycleState() == CONFIG_ERROR) { + return null; + } + synchronized (this) { + try { + Object instance = objectFactory.getInstance(); + startInstance(instance); + if (notify) { + for (Iterator iter = contextListener.iterator(); iter.hasNext();) { + LifecycleEventListener listener = (LifecycleEventListener) iter.next(); + listener.onInstanceCreate(this); + } + } + setLifecycleState(RUNNING); + if (stateless) { + return instance; + } else { + // cache the actual instance + cachedTargetInstance = instance; + return cachedTargetInstance; + } + } catch (ObjectCreationException e) { + setLifecycleState(Context.ERROR); + TargetException te = new TargetException("Error creating instance for component", e); + te.setIdentifier(getName()); + throw te; + } + } + + } + + public Object getImplementationInstance() throws TargetException { + return getInstance(null); + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return getInstance(null, notify); + } + + public boolean isEagerInit() { + return eagerInit; + } + + public boolean isDestroyable() { + return (destroyInvoker != null); + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public void start() throws ContextInitException { + if (getLifecycleState() != UNINITIALIZED && getLifecycleState() != STOPPED) { + throw new IllegalStateException("Component must be in UNINITIALIZED state [" + getLifecycleState() + "]"); + } + if (objectFactory == null) { + setLifecycleState(ERROR); + ContextInitException e = new ContextInitException("Object factory not found "); + e.setIdentifier(getName()); + throw e; + } + setLifecycleState(INITIALIZED); + } + + public void stop() { + if (cachedTargetInstance != null) { + if (destroyInvoker != null) { + try { + destroyInvoker.invokeEvent(cachedTargetInstance); + } catch (ObjectCallbackException e) { + throw new TargetException(e.getCause()); + } + } + } + setLifecycleState(STOPPED); + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + private void startInstance(Object instance) throws TargetException { + try { + // handle @Init + if (initInvoker != null) { + initInvoker.invokeEvent(instance); + } + } catch (ObjectCallbackException e) { + TargetException te = new TargetException("Error initializing instance", e); + te.setIdentifier(getName()); + throw te; + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemEntryPointContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemEntryPointContext.java new file mode 100644 index 0000000000..5533424334 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemEntryPointContext.java @@ -0,0 +1,82 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.context; + +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EntryPointContext; +import org.apache.tuscany.core.context.TargetException; + +/** + * Manages an entry point into a system module. System entry points cache a direct (i.e. non-proxied) reference to a + * component instance. + * + * @version $Rev$ $Date$ + */ +public class SystemEntryPointContext extends AbstractContext implements EntryPointContext { + + // responsible for resolving the component implementation instance exposed by the entry point + private ObjectFactory factory; + + // a reference to the component's implementation instance exposed by the entry point + private Object cachedInstance; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemEntryPointContext(String name, ObjectFactory factory) { + super(name); + assert (factory != null) : "Object factory was null"; + this.factory = factory; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public Object getInstance(QualifiedName qName) throws TargetException { + return getInstance(qName, true); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + try { + if (cachedInstance == null) { + cachedInstance = factory.getInstance(); + } + return cachedInstance; + } catch (TargetException e) { + e.addContextName(getName()); + throw e; + } + } + + public void start() throws CoreRuntimeException { + lifecycleState = RUNNING; + } + + public void stop() throws CoreRuntimeException { + lifecycleState = STOPPED; + } + + public Object getImplementationInstance() throws TargetException{ + return getInstance(null); + } + + public Object getImplementationInstance(boolean notify) throws TargetException{ + return getInstance(null,notify); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemExternalServiceContext.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemExternalServiceContext.java new file mode 100644 index 0000000000..9b09cea082 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemExternalServiceContext.java @@ -0,0 +1,82 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.context; + +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.ExternalServiceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.TargetException; + +/** + * An implementation of an external service for system wiring. As system components are not proxied and the system + * binding is by-reference, the implementation caches a reference to its configured target. + * + * @version $Rev$ $Date$ + */ +public class SystemExternalServiceContext extends AbstractContext implements ExternalServiceContext { + + // a factory for retrieving the target of the external service wire + private ObjectFactory factory; + + // the cached target + private Object cachedInstance; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public SystemExternalServiceContext(String name, ObjectFactory factory) { + super(name); + assert (factory != null) : "Object factory was null"; + this.factory = factory; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public Object getInstance(QualifiedName qName) throws TargetException { + return getInstance(qName, false); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + try { + if (cachedInstance == null) { + cachedInstance = factory.getInstance(); + } + return cachedInstance; + } catch (TargetException e) { + e.addContextName(getName()); + throw e; + } + + } + + public void start() { + lifecycleState = RUNNING; + } + + public void stop() { + lifecycleState = STOPPED; + } + + public Object getImplementationInstance() throws TargetException { + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return this; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemScopeStrategy.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemScopeStrategy.java new file mode 100644 index 0000000000..0dbd75da19 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/context/SystemScopeStrategy.java @@ -0,0 +1,56 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.system.context; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.scope.AbstractScopeStrategy; +import org.apache.tuscany.core.context.scope.AggregateScopeContext; +import org.apache.tuscany.core.context.scope.ModuleScopeContext; +import org.apache.tuscany.core.context.scope.StatelessScopeContext; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implements a {@link org.apache.tuscany.core.context.ScopeStrategy} for a system aggregate context with the following scopes: + * <ul> + * <li>{@link org.apache.tuscany.model.assembly.Scope#AGGREGATE</li> + * <li>{@link org.apache.tuscany.model.assembly.Scope#MODULE</li> + * <li>{@link org.apache.tuscany.model.assembly.Scope#INSTANCE</li> + * </ul> + * + * @version $Rev$ $Date$ + */ +public class SystemScopeStrategy extends AbstractScopeStrategy { + + public SystemScopeStrategy() { + } + + public Map<Scope, ScopeContext> createScopes(EventContext eventContext) { + ScopeContext aggregrateScope = new AggregateScopeContext(eventContext); + ScopeContext moduleScoper = new ModuleScopeContext(eventContext); + ScopeContext statelessScope = new StatelessScopeContext(eventContext); + Map<Scope, ScopeContext> scopes = new HashMap(); + scopes.put(Scope.AGGREGATE, aggregrateScope); + scopes.put(Scope.MODULE, moduleScoper); + scopes.put(Scope.INSTANCE, statelessScope); + return scopes; + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/injection/AutowireFactory.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/injection/AutowireFactory.java new file mode 100644 index 0000000000..3bde49dbbe --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/injection/AutowireFactory.java @@ -0,0 +1,50 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.system.injection; + +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.injection.FactoryInitException; +import org.apache.tuscany.core.injection.ObjectCreationException; + +/** + * Implementation of ObjectFactory that returns an instance by resolving against an AutowireContext. + * + * @version $Rev$ $Date$ + */ +public class AutowireFactory<T> implements ObjectFactory<T> { + + private AutowireContext autoWireContext; + + private Class<T> implementationType; + + /** + * Constructor specifying the context to wire against and the type of service required. + * + * @param implementationType the type of service required + * @param autoWireContext the context to wire against + */ + public AutowireFactory(Class<T> implementationType, AutowireContext autoWireContext) { + assert (implementationType != null) : "Implementation type was null"; + assert (autoWireContext != null) : "Autowire context was null"; + this.implementationType = implementationType; + this.autoWireContext = autoWireContext; + } + + public T getInstance() throws ObjectCreationException { + // todo what about required? should this just return null? + return autoWireContext.resolveInstance(implementationType); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/loader/SystemSCDLModelLoader.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/loader/SystemSCDLModelLoader.java new file mode 100644 index 0000000000..f49efe3ebc --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/system/loader/SystemSCDLModelLoader.java @@ -0,0 +1,49 @@ +package org.apache.tuscany.core.system.loader; + +import org.apache.tuscany.core.system.assembly.SystemAssemblyFactory; +import org.apache.tuscany.core.system.assembly.impl.SystemAssemblyFactoryImpl; +import org.apache.tuscany.core.system.scdl.ScdlFactory; +import org.apache.tuscany.core.system.scdl.SystemImplementation; +import org.apache.tuscany.model.assembly.AssemblyModelContext; +import org.apache.tuscany.model.assembly.AssemblyModelObject; +import org.apache.tuscany.model.scdl.loader.SCDLModelLoader; +import org.apache.tuscany.sdo.util.SDOUtil; + +/** + * Populates the assembly model from an SCDL model + */ +public class SystemSCDLModelLoader implements SCDLModelLoader { + + private SystemAssemblyFactory systemFactory; + + static { + // Register the system SCDL model + SDOUtil.registerStaticTypes(ScdlFactory.class); + } + + /** + * Constructs a new JavaSCDLModelLoader. + */ + public SystemSCDLModelLoader() { + this.systemFactory=new SystemAssemblyFactoryImpl(); + } + + /** + * @see org.apache.tuscany.model.scdl.loader.SCDLModelLoader#load(org.apache.tuscany.model.assembly.AssemblyModelContext, java.lang.Object) + */ + public AssemblyModelObject load(AssemblyModelContext modelContext, Object object) { + if (object instanceof SystemImplementation) { + SystemImplementation scdlImplementation=(SystemImplementation)object; + org.apache.tuscany.core.system.assembly.SystemImplementation implementation=systemFactory.createSystemImplementation(); + Class implementationClass; + try { + implementationClass=modelContext.getSystemResourceLoader().loadClass(scdlImplementation.getClass_()); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + implementation.setImplementationClass(implementationClass); + return implementation; + } else + return null; + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/ContextBinder.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/ContextBinder.java new file mode 100644 index 0000000000..690d03ac36 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/ContextBinder.java @@ -0,0 +1,39 @@ +/** + * + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.webapp; + +import org.osoa.sca.SCA; +import org.osoa.sca.ModuleContext; + +/** + * @version $Rev$ $Date$ + */ +class ContextBinder extends SCA { + static final ContextBinder BINDER = new ContextBinder(); + + public void setContext(ModuleContext context) { + setModuleContext(context); + } + + public void start() { + throw new AssertionError(); + } + + public void stop() { + throw new AssertionError(); + } +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyRequestFilter.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyRequestFilter.java new file mode 100644 index 0000000000..b72c546bf6 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyRequestFilter.java @@ -0,0 +1,97 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.webapp; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; + +import org.osoa.sca.ModuleContext; +import org.osoa.sca.CurrentModuleContext; + +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.webapp.LazyHTTPSessionId; + +/** + * Notifies the {@link org.apache.tuscany.core.context.AggregateContext} of web request start and end events as well as setting up the + * current session context. The latter is done using lazy Servlet-based session retrieval. The filter fires a session + * start event, passing a <tt>LazyServletSessionId</tt> as the session id. The <tt>LazyServletSessionId</tt> is a + * wrapper for the servlet request which may be called by the <tt>ModuleContext</tt> to retrieve the session id + * lazily. + * + * @version $Rev: 379957 $ $Date: 2006-02-22 14:58:24 -0800 (Wed, 22 Feb 2006) $ + */ +public class TuscanyRequestFilter implements Filter { + private AggregateContext moduleContext; + + public TuscanyRequestFilter() { + } + + public void init(FilterConfig filterConfig) throws ServletException { + ServletContext servletContext = filterConfig.getServletContext(); + moduleContext = (AggregateContext) servletContext.getAttribute(TuscanyServletListener.MODULE_COMPONENT_NAME); + } + + public void destroy() { + } + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { + ModuleContext oldContext = CurrentModuleContext.getContext(); + try { + // Set the current module context + ContextBinder.BINDER.setContext((ModuleContext) moduleContext); + + // Handle a request + if (request instanceof HttpServletRequest) { + if (((HttpServletRequest) request).getSession(false) != null) { + + // A session is already active + moduleContext.fireEvent(EventContext.SESSION_NOTIFY, ((HttpServletRequest) request).getSession(true)); + } else { + // Create a lazy wrapper since a session is not yet active + moduleContext.fireEvent(EventContext.SESSION_NOTIFY, new LazyHTTPSessionId((HttpServletRequest) request)); + } + } else { + moduleContext.fireEvent(EventContext.SESSION_NOTIFY, request); + } + // Start processing the request + moduleContext.fireEvent(EventContext.REQUEST_START, request); + // Dispatch to the next filter + filterChain.doFilter(request, response); + } catch (Exception e) { + throw new ServletException(e); + + } finally { + try { + // End processing the request + moduleContext.fireEvent(EventContext.REQUEST_END, request); + } catch (Exception e) { + throw new ServletException(e); + } + ContextBinder.BINDER.setContext(oldContext); + } + } + +} diff --git a/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java new file mode 100644 index 0000000000..56b4b52495 --- /dev/null +++ b/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/webapp/TuscanyServletListener.java @@ -0,0 +1,168 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.webapp; + +import java.util.ArrayList; +import java.util.List; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.osoa.sca.CurrentModuleContext; +import org.osoa.sca.ModuleContext; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.common.monitor.impl.NullMonitorFactory; +import org.apache.tuscany.common.resource.ResourceLoader; +import org.apache.tuscany.common.resource.impl.ResourceLoaderImpl; +import org.apache.tuscany.core.builder.RuntimeConfigurationBuilder; +import org.apache.tuscany.core.builder.impl.DefaultWireBuilder; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.config.ModuleComponentConfigurationLoader; +import org.apache.tuscany.core.config.impl.ModuleComponentConfigurationLoaderImpl; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.runtime.RuntimeContext; +import org.apache.tuscany.core.runtime.RuntimeContextImpl; +import org.apache.tuscany.core.system.builder.SystemComponentContextBuilder; +import org.apache.tuscany.core.system.builder.SystemEntryPointBuilder; +import org.apache.tuscany.core.system.builder.SystemExternalServiceBuilder; +import org.apache.tuscany.core.system.loader.SystemSCDLModelLoader; +import org.apache.tuscany.model.assembly.AssemblyFactory; +import org.apache.tuscany.model.assembly.AssemblyModelContext; +import org.apache.tuscany.model.assembly.ModuleComponent; +import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl; +import org.apache.tuscany.model.assembly.impl.AssemblyModelContextImpl; +import org.apache.tuscany.model.assembly.loader.AssemblyModelLoader; +import org.apache.tuscany.model.scdl.loader.SCDLModelLoader; +import org.apache.tuscany.model.scdl.loader.impl.SCDLAssemblyModelLoaderImpl; + +/** + * ServletContextListener that can be added to a standard web application to boot + * a Tuscany runtime inside that application. All implementation classes should + * be located in the web application itself. + * + * @version $Rev: 380792 $ $Date: 2006-02-24 11:25:11 -0800 (Fri, 24 Feb 2006) $ + */ +public class TuscanyServletListener implements ServletContextListener, HttpSessionListener { + public static final String SCA_COMPONENT_NAME = "org.apache.tuscany.core.webapp.ModuleComponentName"; + public static final String MODULE_COMPONENT_NAME = "org.apache.tuscany.core.webapp.ModuleComponentContext"; + public static final String TUSCANY_RUNTIME_NAME = RuntimeContext.class.getName(); + + private final Object sessionKey = new Object(); + + private RuntimeContext runtimeContext; + private AggregateContext systemModuleComponentContext; + private AggregateContext moduleContext; + + private static final String SYSTEM_MODULE_COMPONENT = "org.apache.tuscany.core.system"; + + public void contextInitialized(ServletContextEvent servletContextEvent) { + ServletContext servletContext = servletContextEvent.getServletContext(); + String name = servletContext.getInitParameter(SCA_COMPONENT_NAME); + String uri = name; // todo get from context path + MonitorFactory monitorFactory = new NullMonitorFactory(); // todo have one that writes to the servlet log + + try { + bootRuntime(name, uri, monitorFactory); + } catch (ConfigurationException e) { + throw new RuntimeException(e.getMessage(), e); + } + + servletContext.setAttribute(TUSCANY_RUNTIME_NAME, runtimeContext); + servletContext.setAttribute(MODULE_COMPONENT_NAME, moduleContext); + } + + public void contextDestroyed(ServletContextEvent servletContextEvent) { + moduleContext.fireEvent(EventContext.MODULE_STOP, null); + moduleContext.stop(); + systemModuleComponentContext.fireEvent(EventContext.MODULE_STOP, null); + systemModuleComponentContext.stop(); + runtimeContext.stop(); + servletContextEvent.getServletContext().removeAttribute(MODULE_COMPONENT_NAME); + servletContextEvent.getServletContext().removeAttribute(TUSCANY_RUNTIME_NAME); + } + + public void sessionCreated(HttpSessionEvent event) { + // do nothing since sessions are lazily created in {@link TuscanyRequestFilter} + } + + public void sessionDestroyed(HttpSessionEvent event) { + // todo do we actually need to bind the module context to the thread to fire this event? + ModuleContext oldContext = CurrentModuleContext.getContext(); + try { + ContextBinder.BINDER.setContext((ModuleContext) moduleContext); + moduleContext.fireEvent(EventContext.SESSION_END, event.getSession()); + } finally{ + ContextBinder.BINDER.setContext(oldContext); + } + } + + private void bootRuntime(String name, String uri, MonitorFactory monitorFactory) throws ConfigurationException { + // Create a resource loader from the current classloader + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + ResourceLoader resourceLoader = new ResourceLoaderImpl(classLoader); + + // Create an assembly model factory + AssemblyFactory modelFactory=new AssemblyFactoryImpl(); + + // Create an assembly model loader + List<SCDLModelLoader> scdlLoaders=new ArrayList<SCDLModelLoader>(); + scdlLoaders.add(new SystemSCDLModelLoader()); + AssemblyModelLoader modelLoader=new SCDLAssemblyModelLoaderImpl(scdlLoaders); + + // Create an assembly model context + AssemblyModelContext modelContext = new AssemblyModelContextImpl(modelFactory, modelLoader, resourceLoader); + + // Create system configuration builders + List<RuntimeConfigurationBuilder> configBuilders = new ArrayList(); + configBuilders.add((new SystemComponentContextBuilder())); + configBuilders.add(new SystemEntryPointBuilder()); + configBuilders.add(new SystemExternalServiceBuilder()); + + // Create a runtime context and start it + runtimeContext = new RuntimeContextImpl(monitorFactory, scdlLoaders, configBuilders,new DefaultWireBuilder()); + runtimeContext.start(); + + // Get the system context + AggregateContext systemContext = runtimeContext.getSystemContext(); + + // Load the system module component + ModuleComponentConfigurationLoader loader = new ModuleComponentConfigurationLoaderImpl(modelContext); + ModuleComponent systemModuleComponent = loader.loadSystemModuleComponent(SYSTEM_MODULE_COMPONENT, SYSTEM_MODULE_COMPONENT); + + // Register it with the system context + systemContext.registerModelObject(systemModuleComponent); + + // Get the aggregate context representing the system module component + systemModuleComponentContext = (AggregateContext) systemContext.getContext(SYSTEM_MODULE_COMPONENT); + systemModuleComponentContext.registerModelObject(systemModuleComponent.getComponentImplementation()); + systemModuleComponentContext.fireEvent(EventContext.MODULE_START, null); + + // Load the SCDL configuration of the application module + ModuleComponent moduleComponent = loader.loadModuleComponent(name, uri); + + // Register it under the root application context + runtimeContext.getRootContext().registerModelObject(moduleComponent); + moduleContext=(AggregateContext)runtimeContext.getContext(moduleComponent.getName()); + moduleContext.registerModelObject(moduleComponent.getComponentImplementation()); + + moduleContext.fireEvent(EventContext.MODULE_START, null); + } +} |