001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.jndi;
018:
019: import java.util.Hashtable;
020: import java.util.Iterator;
021: import java.util.Map;
022: import java.util.concurrent.ConcurrentHashMap;
023: import javax.naming.Context;
024: import javax.naming.InvalidNameException;
025: import javax.naming.Name;
026: import javax.naming.NamingException;
027: import javax.naming.Reference;
028: import javax.naming.event.EventContext;
029: import javax.naming.event.NamespaceChangeListener;
030: import javax.naming.event.NamingEvent;
031: import javax.naming.event.NamingExceptionEvent;
032: import javax.naming.event.NamingListener;
033: import javax.naming.spi.ObjectFactory;
034:
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.compass.core.Compass;
038: import org.compass.core.config.CompassSettings;
039:
040: /**
041: * Resolves <code>Compass</code> JNDI lookups and deserialization
042: */
043: public class CompassObjectFactory implements ObjectFactory {
044:
045: // to stop the class from being unloaded
046: private static final CompassObjectFactory INSTANCE;
047:
048: private static final Log log;
049:
050: static {
051: log = LogFactory.getLog(CompassObjectFactory.class);
052: INSTANCE = new CompassObjectFactory();
053: log
054: .debug("Initializing class CompassObjectFactory. Using static instance ["
055: + INSTANCE + "]");
056: }
057:
058: private static final Map INSTANCES = new ConcurrentHashMap();
059:
060: private static final Map NAMED_INSTANCES = new ConcurrentHashMap();
061:
062: private static final NamingListener LISTENER = new NamespaceChangeListener() {
063: public void objectAdded(NamingEvent evt) {
064: log.debug("Compass was successfully bound to name ["
065: + evt.getNewBinding().getName() + "]");
066: }
067:
068: public void objectRemoved(NamingEvent evt) {
069: String name = evt.getOldBinding().getName();
070: if (log.isInfoEnabled()) {
071: log
072: .info("Compass was unbound from name [" + name
073: + "]");
074: }
075: Object instance = NAMED_INSTANCES.remove(name);
076: Iterator iter = INSTANCES.values().iterator();
077: while (iter.hasNext()) {
078: if (iter.next() == instance)
079: iter.remove();
080: }
081: }
082:
083: public void objectRenamed(NamingEvent evt) {
084: String name = evt.getOldBinding().getName();
085: if (log.isInfoEnabled()) {
086: log
087: .info("Compass was renamed from name [" + name
088: + "]");
089: }
090: NAMED_INSTANCES.put(evt.getNewBinding().getName(),
091: NAMED_INSTANCES.remove(name));
092: }
093:
094: public void namingExceptionThrown(NamingExceptionEvent evt) {
095: log.warn("Naming exception occurred accessing compass: "
096: + evt.getException());
097: }
098: };
099:
100: public Object getObjectInstance(Object reference, Name name,
101: Context ctx, Hashtable env) throws Exception {
102: if (log.isDebugEnabled()) {
103: log.debug("JNDI lookup for [" + name + "]");
104: }
105: String uid = (String) ((Reference) reference).get(0)
106: .getContent();
107: return getInstance(uid);
108: }
109:
110: public static void addInstance(String uid, String name,
111: Compass instance, CompassSettings settings) {
112:
113: if (log.isDebugEnabled()) {
114: log.debug("Registering compass [" + uid + "] with ["
115: + ((name == null) ? "unnamed" : name) + ']');
116: }
117: INSTANCES.put(uid, instance);
118: if (name != null)
119: NAMED_INSTANCES.put(name, instance);
120:
121: // must add to JNDI _after_ adding to HashMaps, because some JNDI
122: // servers use serialization
123: if (name == null) {
124: log
125: .info("Not binding compass to JNDI, no JNDI name configured");
126: } else {
127:
128: if (log.isInfoEnabled()) {
129: log
130: .info("Binding compass to JNDI under [" + name
131: + "]");
132: }
133:
134: try {
135: Context ctx = NamingHelper.getInitialContext(settings);
136: NamingHelper.bind(ctx, name, instance);
137: ((EventContext) ctx).addNamingListener(name,
138: EventContext.OBJECT_SCOPE, LISTENER);
139: } catch (InvalidNameException ine) {
140: log.error("Invalid JNDI name [" + name + "]", ine);
141: } catch (NamingException ne) {
142: log.warn("Could not bind compass to JNDI", ne);
143: } catch (ClassCastException cce) {
144: log
145: .warn("InitialContext did not implement EventContext");
146: }
147:
148: }
149:
150: }
151:
152: public static void removeInstance(String uid, String name,
153: CompassSettings settings) {
154: // TODO: theoretically non-threadsafe...
155:
156: if (name != null) {
157: if (log.isInfoEnabled()) {
158: log.info("Unbinding compass from JNDI name [" + name
159: + "]");
160: }
161:
162: try {
163: Context ctx = NamingHelper.getInitialContext(settings);
164: ctx.unbind(name);
165: } catch (InvalidNameException ine) {
166: log.error("Invalid JNDI name [" + name + "]", ine);
167: } catch (NamingException ne) {
168: log.warn("Could not unbind compass from JNDI", ne);
169: }
170:
171: NAMED_INSTANCES.remove(name);
172:
173: }
174:
175: INSTANCES.remove(uid);
176:
177: }
178:
179: public static Object getNamedInstance(String name) {
180: if (log.isDebugEnabled()) {
181: log.debug("lookup with name [" + name + "]");
182: }
183: Object result = NAMED_INSTANCES.get(name);
184: if (result == null) {
185: log.warn("Not found [" + name + "]");
186: log.debug(NAMED_INSTANCES);
187: }
188: return result;
189: }
190:
191: public static Object getInstance(String uid) {
192: if (log.isDebugEnabled()) {
193: log.debug("JNDI lookup for uid [" + uid + "]");
194: }
195: Object result = INSTANCES.get(uid);
196: if (result == null) {
197: log.warn("Not found [" + uid + "]");
198: log.debug(INSTANCES);
199: }
200: return result;
201: }
202:
203: }
|