001 /** 002 * 003 * Copyright 2004 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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: 430508 $ $Date: 2006-08-10 12:56:47 -0700 (Thu, 10 Aug 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 }