001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ha.jndi;
023:
024: import org.jboss.ha.framework.interfaces.HAPartition;
025: import org.jboss.logging.Logger;
026: import org.jnp.interfaces.Naming;
027: import org.jnp.interfaces.NamingContext;
028:
029: import javax.naming.CommunicationException;
030: import javax.naming.InitialContext;
031: import javax.naming.Name;
032: import javax.naming.NameNotFoundException;
033: import javax.naming.NamingException;
034: import java.io.Serializable;
035: import java.util.ArrayList;
036: import java.util.Collection;
037:
038: /**
039: * This class extends the JNP JNDI implementation.
040: * binds and unbinds will be distributed to all members of the cluster
041: * that are running HAJNDI.
042: * lookups will look for Names in HAJNDI then delegate to the local InitialContext
043: * This class is fully serializable for GET_STATE
044: *
045: * @author <a href="mailto:sacha.labourey@jboss.org">Sacha Labourey</a>
046: * @author Scott.Stark@jboss.org
047: * @version $Revision: 57188 $
048: */
049: public class TreeHead extends org.jnp.server.NamingServer implements
050: Serializable, org.jnp.interfaces.Naming {
051: /** @since 1.1.2.2, jboss-3.2.4 */
052: private static final long serialVersionUID = 6342802270002172451L;
053:
054: // Attributes --------------------------------------------------------
055: private static Logger log = Logger.getLogger(TreeHead.class);
056:
057: private transient HAPartition partition;
058: private transient HAJNDI father;
059:
060: // Constructor --------------------------------------------------------
061:
062: public TreeHead() throws NamingException {
063: super ();
064: }
065:
066: // Public --------------------------------------------------------
067:
068: public void init() throws Exception {
069: log.debug("registerRPCHandler");
070: partition.registerRPCHandler("HAJNDI", this );
071: }
072:
073: public void stop() throws Exception {
074:
075: }
076:
077: public void destroy() throws Exception {
078: log.debug("unregisterRPCHandler");
079: partition.unregisterRPCHandler("HAJNDI", this );
080: }
081:
082: public void setPartition(HAPartition partition) {
083: this .partition = partition;
084: }
085:
086: public void setHARMIHead(HAJNDI father) {
087: this .father = father;
088: }
089:
090: // Naming implementation -----------------------------------------
091:
092: public void _bind(Name name, Object obj, String className)
093: throws NamingException {
094: if (log.isTraceEnabled())
095: log.trace("_bind, name=" + name);
096: super .bind(name, obj, className);
097: }
098:
099: public void bind(Name name, Object obj, String className)
100: throws NamingException {
101: if (log.isTraceEnabled())
102: log.trace("bind, name=" + name);
103: super .bind(name, obj, className);
104: // if we get here, this means we can do it on every node.
105: Object[] args = new Object[3];
106: args[0] = name;
107: args[1] = obj;
108: args[2] = className;
109: try {
110: partition.callMethodOnCluster("HAJNDI", "_bind", args,
111: new Class[] { Name.class, Object.class,
112: String.class }, true);
113: } catch (Exception e) {
114: CommunicationException ce = new CommunicationException(
115: "Failed to _bind on cluster");
116: ce.setRootCause(e);
117: throw ce;
118: }
119: }
120:
121: public void _rebind(Name name, Object obj, String className)
122: throws NamingException {
123: if (log.isTraceEnabled())
124: log.trace("_rebind, name=" + name);
125: super .rebind(name, obj, className);
126: }
127:
128: public void rebind(Name name, Object obj, String className)
129: throws NamingException {
130: if (log.isTraceEnabled())
131: log.trace("rebind, name=" + name);
132: super .rebind(name, obj, className);
133:
134: // if we get here, this means we can do it on every node.
135: Object[] args = new Object[3];
136: args[0] = name;
137: args[1] = obj;
138: args[2] = className;
139: try {
140: partition.callMethodOnCluster("HAJNDI", "_rebind", args,
141: new Class[] { Name.class, Object.class,
142: String.class }, true);
143: } catch (Exception e) {
144: CommunicationException ce = new CommunicationException(
145: "Failed to _rebind on cluster");
146: ce.setRootCause(e);
147: throw ce;
148: }
149: }
150:
151: public void _unbind(Name name) throws NamingException {
152: if (log.isTraceEnabled())
153: log.debug("_unbind, name=" + name);
154: super .unbind(name);
155: }
156:
157: public void unbind(Name name) throws NamingException {
158: if (log.isTraceEnabled())
159: log.trace("unbind, name=" + name);
160: super .unbind(name);
161:
162: // if we get here, this means we can do it on every node.
163: Object[] args = new Object[1];
164: args[0] = name;
165: try {
166: partition.callMethodOnCluster("HAJNDI", "_unbind", args,
167: new Class[] { Name.class }, true);
168: } catch (Exception e) {
169: CommunicationException ce = new CommunicationException(
170: "Failed to _unbind on cluster");
171: ce.setRootCause(e);
172: throw ce;
173: }
174: }
175:
176: public Object lookup(Name name) throws NamingException {
177: boolean trace = log.isTraceEnabled();
178: if (trace)
179: log.trace("lookup, name=" + name);
180: Object result = null;
181: try {
182: result = super .lookup(name);
183: } catch (NameNotFoundException ex) {
184: try {
185: // not found in global jndi, look in local.
186: result = lookupLocally(name);
187: } catch (NameNotFoundException nnfe) {
188: // if we get here, this means we can do it on every node.
189: Object[] args = new Object[1];
190: args[0] = name;
191: ArrayList rsp = null;
192: Exception cause = null;
193: try {
194: if (trace)
195: log.trace("calling lookupLocally(" + name
196: + ") on cluster");
197: rsp = partition.callMethodOnCluster("HAJNDI",
198: "lookupLocally", args,
199: new Class[] { Name.class }, true);
200: } catch (Exception ignored) {
201: if (trace)
202: log.trace("Clusterd lookupLocally(" + name
203: + ") failed", ignored);
204: cause = ignored;
205: }
206:
207: if (trace)
208: log.trace("Returned results size: "
209: + (rsp != null ? rsp.size() : 0));
210: if (rsp == null || rsp.size() == 0) {
211: NameNotFoundException nnfe2 = new NameNotFoundException(
212: name.toString());
213: nnfe2.setRootCause(cause);
214: throw nnfe2;
215: }
216:
217: for (int i = 0; i < rsp.size(); i++) {
218: result = rsp.get(i);
219: if (trace) {
220: String type = (result != null ? result
221: .getClass().getName() : "null");
222: log.trace("_lookupLocally, i=" + i + ", value="
223: + result + ", type=" + type);
224: }
225: // Ignore null and Exception return values
226: if (result != null
227: && !(result instanceof Exception))
228: return result;
229: }
230: throw nnfe;
231: }
232: }
233: return result;
234: }
235:
236: public Object _lookupLocally(Name name) {
237: boolean trace = log.isTraceEnabled();
238: if (trace)
239: log.trace("_lookupLocally, name=" + name);
240: try {
241: return lookupLocally(name);
242: } catch (Exception e) {
243: if (trace)
244: log.trace("_lookupLocally failed", e);
245: return e;
246: }
247: }
248:
249: public Object lookupLocally(Name name) throws NamingException {
250: boolean trace = log.isTraceEnabled();
251: if (trace)
252: log.trace("lookupLocally, name=" + name);
253:
254: // TODO: This is a really big hack here
255: // We cannot do InitialContext().lookup(name) because
256: // we get ClassNotFound errors and ClassLinkage errors.
257: // So, what we do is cheat and get the static localServer variable
258: try {
259: if (NamingContext.localServer != null) {
260: return NamingContext.localServer.lookup(name);
261: } else {
262: InitialContext ctx = new InitialContext();
263: return ctx.lookup(name);
264: }
265: } catch (NamingException e) {
266: if (trace)
267: log.trace("lookupLocally failed, name=" + name, e);
268: throw e;
269: } catch (java.rmi.RemoteException e) {
270: NamingException ne = new NamingException(
271: "unknown remote exception");
272: ne.setRootCause(e);
273: if (trace)
274: log.trace("lookupLocally failed, name=" + name, e);
275: throw ne;
276: } catch (RuntimeException e) {
277: if (trace)
278: log.trace("lookupLocally failed, name=" + name, e);
279: throw e;
280: }
281: }
282:
283: protected ArrayList enum2list(javax.naming.NamingEnumeration en) {
284: ArrayList rtn = new ArrayList();
285: try {
286: while (en.hasMore()) {
287: rtn.add(en.next());
288: }
289: en.close();
290: } catch (NamingException ignored) {
291: }
292: return rtn;
293: }
294:
295: public Collection list(Name name) throws NamingException {
296: if (log.isTraceEnabled())
297: log.trace("list, name=" + name);
298: Collection result = null;
299: try {
300: result = super .list(name);
301: } catch (NameNotFoundException ex) {
302: // not found in global jndi, look in local.
303: result = enum2list(new InitialContext().list(name));
304: }
305: return result;
306: }
307:
308: public Collection listBindings(Name name) throws NamingException {
309: if (log.isTraceEnabled())
310: log.trace("listBindings, name=" + name);
311: Collection result = null;
312: try {
313: result = super .listBindings(name);
314: } catch (NameNotFoundException ex) {
315: // not found in global jndi, look in local.
316: result = enum2list(new InitialContext().listBindings(name));
317: }
318: return result;
319: }
320:
321: public javax.naming.Context _createSubcontext(Name name)
322: throws NamingException {
323: if (log.isTraceEnabled())
324: log.trace("_createSubcontext, name=" + name);
325: return super .createSubcontext(name);
326: }
327:
328: public javax.naming.Context createSubcontext(Name name)
329: throws NamingException {
330: if (log.isTraceEnabled())
331: log.trace("createSubcontext, name=" + name);
332: javax.naming.Context result = super .createSubcontext(name);
333:
334: // if we get here, this means we can do it on every node.
335: Object[] args = new Object[1];
336: args[0] = name;
337: try {
338: partition.callMethodOnCluster("HAJNDI",
339: "_createSubcontext", args,
340: new Class[] { Name.class }, true);
341: } catch (Exception e) {
342: CommunicationException ce = new CommunicationException(
343: "Failed to _createSubcontext on cluster");
344: ce.setRootCause(e);
345: throw ce;
346: }
347:
348: return result;
349: }
350:
351: public Naming getRoot() {
352: return father.getHAStub();
353: }
354:
355: }
|