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