KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > gjndi > binding > GBeanBinding


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

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 JavaDoc;
32 import javax.naming.NamingException JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.LinkedHashMap JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.util.Set JavaDoc;
38
39 /**
40  * @version $Rev$ $Date$
41  */

42 public class GBeanBinding implements GBeanLifecycle {
43     private static final Log log = LogFactory.getLog(GBeanBinding.class);
44
45     private final Context JavaDoc context;
46     private final String JavaDoc name;
47     private final AbstractNameQuery abstractNameQuery;
48     private final Kernel kernel;
49
50     private final LifecycleListener listener = new GBeanLifecycleListener();
51     private final LinkedHashMap JavaDoc bindings = new LinkedHashMap JavaDoc();
52
53     public GBeanBinding(Context JavaDoc context, String JavaDoc 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 JavaDoc set = kernel.listGBeans(abstractNameQuery);
63         for (Iterator JavaDoc 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 JavaDoc 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 JavaDoc abstractNames = new HashSet JavaDoc(bindings.keySet());
87         for (Iterator JavaDoc 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 JavaDoc 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     /**
121      * Binds the specified gbean. This method uses createBindingName and preprocessValue before binding the object.
122      *
123      * @param abstractName the abstract name of the gbean to bind
124      * @throws NamingException if an error occurs during binding
125      */

126     protected synchronized void addBinding(AbstractName abstractName) throws NamingException JavaDoc {
127         if (bindings.containsKey(abstractName)) {
128             // previously bound
129
return;
130         }
131
132         // get the gbean
133
Object JavaDoc instance = null;
134         try {
135             instance = kernel.getGBean(abstractName);
136         } catch (GBeanNotFoundException e) {
137             throw new NamingException JavaDoc("GBean not found: " + abstractName);
138         }
139
140         // preprocess the instance
141
instance = preprocessVaue(abstractName, instance);
142
143         addBinding(abstractName, instance);
144     }
145
146     private synchronized void addBinding(AbstractName abstractName, Object JavaDoc value) throws NamingException JavaDoc {
147         if (bindings.isEmpty()) {
148             context.bind(name, value);
149         }
150         bindings.put(abstractName, value);
151     }
152
153     /**
154      * Unbinds the specified gbean.
155      *
156      * @param abstractName the abstract name of the gbean to unbind
157      */

158     protected synchronized void removeBinding(AbstractName abstractName) {
159         if (first(bindings).getKey().equals(abstractName)) {
160             Object JavaDoc oldValue = bindings.remove(abstractName);
161             Map.Entry JavaDoc newEntry = first(bindings);
162             if (newEntry != null) {
163                 Object JavaDoc newAbstractName = newEntry.getValue();
164                 Object JavaDoc newValue = newEntry.getValue();
165                 try {
166                     context.rebind(name, newValue);
167                 } catch (NamingException JavaDoc e) {
168                     boolean unbound = unbind(abstractName, oldValue);
169                     // avoid double logging
170
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 JavaDoc value) {
181         // first check if we are still bound
182
try {
183             if (context.lookup(name) != value) {
184                 return true;
185             }
186         } catch (NamingException JavaDoc ignored) {
187             // binding doesn't exist
188
return true;
189         }
190
191         try {
192             context.unbind(name);
193             return true;
194         } catch (NamingException JavaDoc e1) {
195             log.error("Unable to remove binding " + name + " to " + abstractName, e1);
196         }
197         return false;
198     }
199
200     private static Map.Entry JavaDoc first(LinkedHashMap JavaDoc map) {
201         if (map.isEmpty()) return null;
202         return (Map.Entry JavaDoc) map.entrySet().iterator().next();
203     }
204
205     /**
206      * Preprocess the value before it is bound. This is usefult for wrapping values with reference objects.
207      * By default, this method simply return the value.
208      *
209      * @param abstractName the abstract name of the gbean to bind
210      * @param value the gbean instance
211      * @return the value to bind
212      */

213     protected Object JavaDoc preprocessVaue(AbstractName abstractName, Object JavaDoc value) throws NamingException JavaDoc {
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 JavaDoc.class);
226         builder.addAttribute("name", String JavaDoc.class, true);
227         builder.addAttribute("abstractNameQuery", AbstractNameQuery.class, true);
228         builder.setConstructor(new String JavaDoc[]{"Context", "name", "abstractNameQuery", "kernel"});
229         GBEAN_INFO = builder.getBeanInfo();
230     }
231 }
232
Popular Tags