001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.controls.runtime.bean;
020:
021: import java.lang.reflect.InvocationTargetException;
022: import java.util.Stack;
023:
024: import org.apache.beehive.controls.api.context.ControlHandle;
025: import org.apache.beehive.controls.api.context.ControlThreadContext;
026: import org.apache.beehive.controls.api.context.ResourceContext;
027: import org.apache.beehive.controls.api.events.EventDispatcher;
028: import org.apache.beehive.controls.api.events.EventRef;
029:
030: /**
031: * The ControlContainerContext class provides a base class implementation for external containers
032: * of ControlBeans. It provides additional services, such as:
033: *
034: * - defines a contextual service provider for the ResourceManager interface
035: * - defines a simplified contract for the external container to interact with resource
036: * management (beginContext/endContext)
037: */
038: public class ControlContainerContext extends ControlBeanContext
039: implements EventDispatcher,
040: org.apache.beehive.controls.api.context.ControlContainerContext {
041: public ControlContainerContext() {
042: super (null);
043: }
044:
045: protected ControlContainerContext(
046: BeanContextServicesFactory beanContextServicesFactory) {
047: super (null, beanContextServicesFactory);
048: }
049:
050: /**
051: * Defines the beginning of a new control container execution context.
052: */
053: public void beginContext() {
054: ControlThreadContext.beginContext(this );
055: }
056:
057: /**
058: * Ends the current control container execution context
059: */
060: public void endContext() {
061: try {
062: //
063: // Release all resources associated with the current execution context.
064: //
065: releaseResources();
066: } finally {
067: ControlThreadContext.endContext(this );
068: }
069: }
070:
071: /**
072: * Called by BeanContextSupport superclass during construction and deserialization to
073: * initialize subclass transient state
074: */
075: public void initialize() {
076: super .initialize();
077:
078: //
079: // Register the ResourceContext provider on all new ControlContainerContext instances.
080: //
081: addService(
082: org.apache.beehive.controls.api.context.ResourceContext.class,
083: ResourceContextImpl.getProvider());
084: }
085:
086: /**
087: * Adds a new managed ResourceContext to the ControlContainerContext. This method
088: * is used to register a resource context that has just acquired resources
089: * @param resourceContext the ResourceContext service that has acquired resources
090: * @param bean the acquiring ControlBean. Unused by the base implementation, but
091: * available so subclassed containers can have access to the bean.
092: */
093: protected synchronized void addResourceContext(
094: ResourceContext resourceContext, ControlBean bean) {
095: if (!resourceContext.hasResources())
096: _resourceContexts.push(resourceContext);
097: }
098:
099: /**
100: * Removes a managed ResourceContext from the ControlContainerContext. This method
101: * is used to unregister a resource context that has already acquired resources
102: * @param resourceContext the ResourceContext service to be removed
103: * @param bean the acquiring ControlBean. Unused by the base implementation, but
104: * available so subclassed containers can have access to the bean.
105: */
106: protected synchronized void removeResourceContext(
107: ResourceContext resourceContext, ControlBean bean) {
108: //
109: // Ignore removal requests received within the context of global cleanup. The
110: // stack is already being popped, so these are just requests for resources that
111: // already have in-flight removal taking place.
112: //
113: if (!_releasingAll && resourceContext.hasResources())
114: _resourceContexts.remove(resourceContext);
115: }
116:
117: /**
118: * Releases all ResourceContexts associated with the current ControlContainerContext.
119: * This method is called by the associated container whenever all managed ResourceContexts
120: * that have acquired resources should release them.
121: */
122: protected synchronized void releaseResources() {
123: // Set the local flag indicating global resource release is occuring
124: _releasingAll = true;
125:
126: //
127: // Iterate through the list of acquired ResourceContexts and release them
128: //
129: while (!_resourceContexts.empty()) {
130: ResourceContext resourceContext = _resourceContexts.pop();
131: resourceContext.release();
132: }
133:
134: // Clear the local flag indicating global resource release is occuring
135: _releasingAll = false;
136: }
137:
138: /**
139: * Dispatch an operation or an event to a bean within this container bean context.
140: * @param handle the control handle identifying the target bean
141: * @param event the event to be invoked on the target bean
142: * @param args the arguments to be passed to the target method invocation
143: */
144: public Object dispatchEvent(ControlHandle handle, EventRef event,
145: Object[] args) throws IllegalArgumentException,
146: IllegalAccessException, InvocationTargetException {
147: ControlBean bean = getBean(handle.getControlID());
148: if (bean == null)
149: throw new IllegalArgumentException("Invalid bean ID: "
150: + handle.getControlID());
151:
152: return bean.dispatchEvent(event, args);
153: }
154:
155: /**
156: * Returns a ControlHandle to the component containing the control. This handle can be
157: * used to dispatch events and operations to a control instance. This method will return
158: * null if the containing component does not support direct dispatch.
159: *
160: * @param bean the target control bean
161: */
162: public ControlHandle getControlHandle(
163: org.apache.beehive.controls.api.bean.ControlBean bean) {
164: //
165: // The base implementation doesn't support dispatch. Containers should override
166: // and return a valid service handle that does component-specific dispatch.
167: //
168: return null;
169: }
170:
171: /**
172: * Returns true if this container guarantees single-threaded behaviour. By default, top-level
173: * containers are assumed to NOT guarantee this; specific container implementations (for example,
174: * for EJB containers) should override this appropriately.
175: */
176: public boolean isSingleThreadedContainer() {
177: return false;
178: }
179:
180: boolean _releasingAll;
181: Stack<ResourceContext> _resourceContexts = new Stack<ResourceContext>();
182: }
|