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: */package org.apache.geronimo.gbean.runtime;
017:
018: import org.apache.commons.logging.Log;
019: import org.apache.commons.logging.LogFactory;
020: import org.apache.geronimo.gbean.AbstractName;
021: import org.apache.geronimo.gbean.AbstractNameQuery;
022: import org.apache.geronimo.gbean.InvalidConfigurationException;
023: import org.apache.geronimo.kernel.GBeanNotFoundException;
024: import org.apache.geronimo.kernel.Kernel;
025: import org.apache.geronimo.kernel.lifecycle.LifecycleAdapter;
026: import org.apache.geronimo.kernel.lifecycle.LifecycleListener;
027: import org.apache.geronimo.kernel.management.State;
028:
029: /**
030: * @version $Rev: 476049 $ $Date: 2006-11-16 20:35:17 -0800 (Thu, 16 Nov 2006) $
031: */
032: public final class GBeanDependency {
033:
034: private static final Log log = LogFactory
035: .getLog(GBeanDependency.class);
036:
037: /**
038: * The GBeanInstance to which this reference belongs.
039: */
040: private final GBeanInstance gbeanInstance;
041:
042: /**
043: * The target objectName targetName to watch for a connection.
044: */
045: private final AbstractName targetName;
046:
047: /**
048: * Our listener for lifecycle events
049: */
050: private final LifecycleListener listener;
051:
052: /**
053: * The kernel to which the reference is bound.
054: */
055: private final Kernel kernel;
056:
057: private boolean targetRunning = false;
058: private boolean dependencyRegistered = false;
059:
060: public GBeanDependency(GBeanInstance gbeanInstance,
061: AbstractName targetName, Kernel kernel)
062: throws InvalidConfigurationException {
063: this .gbeanInstance = gbeanInstance;
064: this .kernel = kernel;
065: this .targetName = targetName;
066: listener = createLifecycleListener();
067: }
068:
069: public AbstractName getTargetName() {
070: return targetName;
071: }
072:
073: public final synchronized void online() {
074: //TODO consider including interfaces in query
075: AbstractNameQuery query = new AbstractNameQuery(targetName,
076: null);
077: kernel.getLifecycleMonitor().addLifecycleListener(listener,
078: query);
079: targetRunning = isRunning(kernel, targetName);
080: }
081:
082: public synchronized boolean start() {
083: if (targetRunning && !dependencyRegistered) {
084: AbstractName abstractName = gbeanInstance.getAbstractName();
085: kernel.getDependencyManager().addDependency(abstractName,
086: targetName);
087: dependencyRegistered = true;
088: }
089: return targetRunning;
090: }
091:
092: public synchronized void stop() {
093: if (dependencyRegistered) {
094: AbstractName abstractName = gbeanInstance.getAbstractName();
095: kernel.getDependencyManager().removeDependency(
096: abstractName, targetName);
097: dependencyRegistered = false;
098: }
099: }
100:
101: public final synchronized void offline() {
102: // make sure we are stopped
103: stop();
104:
105: kernel.getLifecycleMonitor().removeLifecycleListener(listener);
106: targetRunning = false;
107: }
108:
109: private synchronized void attemptFullStart() {
110: try {
111: // there could be an issue with really badly written components holding up a stop when the
112: // component never reached the starting phase... then a target registers and we automatically
113: // attempt to restart
114: // waitingForMe = false;
115: gbeanInstance.start();
116: } catch (Exception e) {
117: log.warn(
118: "Exception occured while attempting to fully start: objectName="
119: + gbeanInstance.getObjectName(), e);
120: }
121: }
122:
123: protected LifecycleListener createLifecycleListener() {
124: return new LifecycleAdapter() {
125: public void running(AbstractName abstractName) {
126: addTarget(abstractName);
127: }
128:
129: public void stopped(AbstractName abstractName) {
130: removeTarget(abstractName);
131: }
132:
133: public void failed(AbstractName abstractName) {
134: removeTarget(abstractName);
135: }
136:
137: public void unloaded(AbstractName abstractName) {
138: removeTarget(abstractName);
139: }
140: };
141: }
142:
143: protected final void addTarget(AbstractName abstractName) {
144: // if we are running, and we now have two valid targets, which is an illegal state so we need to fail
145: synchronized (this ) {
146: targetRunning = true;
147: GBeanInstance gbeanInstance1 = gbeanInstance;
148: if (gbeanInstance1.getStateInstance() == State.RUNNING) {
149: log
150: .error("Illegal state: two or more targets are running for a dependency: "
151: + getDescription()
152: + ",\n newTarget=" + abstractName);
153: }
154: attemptFullStart();
155: }
156: }
157:
158: protected final void removeTarget(AbstractName abstractName) {
159: synchronized (this ) {
160: targetRunning = false;
161: GBeanInstance gbeanInstance1 = gbeanInstance;
162: if (gbeanInstance1.getStateInstance() == State.RUNNING) {
163: // we no longer have a valid target, which is an illegal state so we need to fail
164: log
165: .error("Illegal state: current target for a single valued reference stopped: "
166: + getDescription()
167: + ",\n stopped Target="
168: + abstractName);
169: gbeanInstance1.referenceFailed();
170: }
171: }
172: }
173:
174: /**
175: * Is the component in the Running state
176: *
177: * @param objectName name of the component to check
178: * @return true if the component is running; false otherwise
179: */
180: private boolean isRunning(Kernel kernel, AbstractName objectName) {
181: try {
182: final int state = kernel.getGBeanState(objectName);
183: return state == State.RUNNING_INDEX;
184: } catch (GBeanNotFoundException e) {
185: // gbean is no longer registerd
186: return false;
187: } catch (Exception e) {
188: // problem getting the attribute, gbean has most likely failed
189: return false;
190: }
191: }
192:
193: protected final String getDescription() {
194: return "\n GBeanInstance: " + gbeanInstance.getName()
195: + "\n Target Name: " + targetName;
196: }
197:
198: public boolean equals(Object o) {
199: if (this == o)
200: return true;
201: if (o == null || getClass() != o.getClass())
202: return false;
203:
204: final GBeanDependency that = (GBeanDependency) o;
205:
206: if (gbeanInstance != null ? !gbeanInstance
207: .equals(that.gbeanInstance)
208: : that.gbeanInstance != null) {
209: return false;
210: }
211: return !(targetName != null ? !targetName
212: .equals(that.targetName) : that.targetName != null);
213:
214: }
215:
216: public int hashCode() {
217: int result;
218: result = (gbeanInstance != null ? gbeanInstance.hashCode() : 0);
219: result = 29 * result
220: + (targetName != null ? targetName.hashCode() : 0);
221: return result;
222: }
223: }
|