1 17 package org.apache.geronimo.gjndi.binding; 18 19 import org.apache.commons.logging.Log; 20 import org.apache.commons.logging.LogFactory; 21 import org.apache.geronimo.gbean.AbstractName; 22 import org.apache.geronimo.gbean.AbstractNameQuery; 23 import org.apache.geronimo.gbean.GBeanInfo; 24 import org.apache.geronimo.gbean.GBeanInfoBuilder; 25 import org.apache.geronimo.gbean.GBeanLifecycle; 26 import org.apache.geronimo.kernel.GBeanNotFoundException; 27 import org.apache.geronimo.kernel.Kernel; 28 import org.apache.geronimo.kernel.lifecycle.LifecycleAdapter; 29 import org.apache.geronimo.kernel.lifecycle.LifecycleListener; 30 31 import javax.naming.Context ; 32 import javax.naming.NamingException ; 33 import java.util.HashSet ; 34 import java.util.Iterator ; 35 import java.util.LinkedHashMap ; 36 import java.util.Map ; 37 import java.util.Set ; 38 39 42 public class GBeanBinding implements GBeanLifecycle { 43 private static final Log log = LogFactory.getLog(GBeanBinding.class); 44 45 private final Context context; 46 private final String name; 47 private final AbstractNameQuery abstractNameQuery; 48 private final Kernel kernel; 49 50 private final LifecycleListener listener = new GBeanLifecycleListener(); 51 private final LinkedHashMap bindings = new LinkedHashMap (); 52 53 public GBeanBinding(Context context, String name, AbstractNameQuery abstractNameQuery, Kernel kernel) { 54 this.context = context; 55 this.name = name; 56 this.abstractNameQuery = abstractNameQuery; 57 this.kernel = kernel; 58 } 59 60 public synchronized void doStart() { 61 kernel.getLifecycleMonitor().addLifecycleListener(listener, abstractNameQuery); 62 Set set = kernel.listGBeans(abstractNameQuery); 63 for (Iterator iterator = set.iterator(); iterator.hasNext();) { 64 AbstractName abstractName = (AbstractName) iterator.next(); 65 try { 66 if (kernel.isRunning(abstractName)) { 67 addBinding(abstractName); 68 } 69 } catch (NamingException e) { 70 log.error("Error adding binding for " + abstractName, e); 71 } 72 } 73 74 } 75 76 public void doStop() { 77 destroy(); 78 } 79 80 public void doFail() { 81 destroy(); 82 } 83 84 private synchronized void destroy() { 85 kernel.getLifecycleMonitor().removeLifecycleListener(listener); 86 Set abstractNames = new HashSet (bindings.keySet()); 87 for (Iterator iterator = abstractNames.iterator(); iterator.hasNext();) { 88 AbstractName abstractName = (AbstractName) iterator.next(); 89 removeBinding(abstractName); 90 } 91 bindings.clear(); 92 } 93 94 private class GBeanLifecycleListener extends LifecycleAdapter { 95 public void running(AbstractName abstractName) { 96 try { 97 addBinding(abstractName); 98 } catch (NamingException e) { 99 log.error("Error adding binding for " + abstractName); 100 } 101 } 102 103 public void stopping(AbstractName abstractName) { 104 removeBinding(abstractName); 105 } 106 107 public void stopped(AbstractName abstractName) { 108 removeBinding(abstractName); 109 } 110 111 public void failed(AbstractName abstractName) { 112 removeBinding(abstractName); 113 } 114 115 public void unloaded(AbstractName abstractName) { 116 removeBinding(abstractName); 117 } 118 } 119 120 126 protected synchronized void addBinding(AbstractName abstractName) throws NamingException { 127 if (bindings.containsKey(abstractName)) { 128 return; 130 } 131 132 Object instance = null; 134 try { 135 instance = kernel.getGBean(abstractName); 136 } catch (GBeanNotFoundException e) { 137 throw new NamingException ("GBean not found: " + abstractName); 138 } 139 140 instance = preprocessVaue(abstractName, instance); 142 143 addBinding(abstractName, instance); 144 } 145 146 private synchronized void addBinding(AbstractName abstractName, Object value) throws NamingException { 147 if (bindings.isEmpty()) { 148 context.bind(name, value); 149 } 150 bindings.put(abstractName, value); 151 } 152 153 158 protected synchronized void removeBinding(AbstractName abstractName) { 159 if (first(bindings).getKey().equals(abstractName)) { 160 Object oldValue = bindings.remove(abstractName); 161 Map.Entry newEntry = first(bindings); 162 if (newEntry != null) { 163 Object newAbstractName = newEntry.getValue(); 164 Object newValue = newEntry.getValue(); 165 try { 166 context.rebind(name, newValue); 167 } catch (NamingException e) { 168 boolean unbound = unbind(abstractName, oldValue); 169 if (unbound) log.error("Unable to rebind binding " + name + " to " + newAbstractName); 171 } 172 } else { 173 unbind(abstractName, oldValue); 174 } 175 } else { 176 bindings.remove(abstractName); 177 } 178 } 179 180 private boolean unbind(AbstractName abstractName, Object value) { 181 try { 183 if (context.lookup(name) != value) { 184 return true; 185 } 186 } catch (NamingException ignored) { 187 return true; 189 } 190 191 try { 192 context.unbind(name); 193 return true; 194 } catch (NamingException e1) { 195 log.error("Unable to remove binding " + name + " to " + abstractName, e1); 196 } 197 return false; 198 } 199 200 private static Map.Entry first(LinkedHashMap map) { 201 if (map.isEmpty()) return null; 202 return (Map.Entry ) map.entrySet().iterator().next(); 203 } 204 205 213 protected Object preprocessVaue(AbstractName abstractName, Object value) throws NamingException { 214 return value; 215 } 216 217 public static final GBeanInfo GBEAN_INFO; 218 219 public static GBeanInfo getGBeanInfo() { 220 return GBEAN_INFO; 221 } 222 223 static { 224 GBeanInfoBuilder builder = GBeanInfoBuilder.createStatic(GBeanBinding.class, "GBeanBinding"); 225 builder.addReference("Context", Context .class); 226 builder.addAttribute("name", String .class, true); 227 builder.addAttribute("abstractNameQuery", AbstractNameQuery.class, true); 228 builder.setConstructor(new String []{"Context", "name", "abstractNameQuery", "kernel"}); 229 GBEAN_INFO = builder.getBeanInfo(); 230 } 231 } 232 | Popular Tags |