001: // ========================================================================
002: // $Id: NamingEntry.java 1106 2006-10-17 17:00:06Z janb $
003: // Copyright 2006 Mort Bay Consulting Pty. Ltd.
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: // http://www.apache.org/licenses/LICENSE-2.0
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014: // ========================================================================
015:
016: package org.mortbay.jetty.plus.naming;
017:
018: import java.util.ArrayList;
019: import java.util.List;
020:
021: import javax.naming.Binding;
022: import javax.naming.Context;
023: import javax.naming.InitialContext;
024: import javax.naming.LinkRef;
025: import javax.naming.Name;
026: import javax.naming.NameNotFoundException;
027: import javax.naming.NameParser;
028: import javax.naming.NamingEnumeration;
029: import javax.naming.NamingException;
030: import javax.naming.Reference;
031: import javax.naming.Referenceable;
032:
033: import org.mortbay.log.Log;
034: import org.mortbay.naming.NamingUtil;
035:
036: /**
037: * NamingEntry
038: *
039: * Base class for all jndi related entities. Instances of
040: * subclasses of this class are declared in jetty.xml or in a
041: * webapp's WEB-INF/jetty-env.xml file.
042: *
043: * NOTE: that all NamingEntries will be bound in a single namespace.
044: * The "global" level is just in the top level context. The "local"
045: * level is a context specific to a webapp.
046: */
047: public abstract class NamingEntry {
048: public static final int SCOPE_GLOBAL = 0;
049: public static final int SCOPE_LOCAL = 1;
050: protected String jndiName;
051: protected Object objectToBind;
052: protected String absoluteObjectNameString;
053: protected String namingEntryNameString;
054: protected String objectNameString;
055: protected Context context;
056: protected boolean isGlobal;
057: protected static ThreadLocal scope = new ThreadLocal();
058:
059: public static void setScope(int scopeType) {
060: scope.set(new Integer(scopeType));
061: }
062:
063: public static int getScope() {
064: Integer val = (Integer) scope.get();
065: return (val == null ? SCOPE_GLOBAL : val.intValue());
066: }
067:
068: public static NamingEntry lookupNamingEntry(int scopeType,
069: Class clazz, String jndiName) throws NamingException {
070: NamingEntry namingEntry = null;
071:
072: switch (scopeType) {
073: case SCOPE_GLOBAL: {
074: try {
075: namingEntry = (NamingEntry) lookupNamingEntry(
076: new InitialContext(), clazz, jndiName);
077: } catch (NameNotFoundException e) {
078: namingEntry = null;
079: }
080: break;
081: }
082: case SCOPE_LOCAL: {
083: if (getScope() == SCOPE_LOCAL) {
084: //NOTE: LOCAL scope will only work if you are actually in the webapp scope itself
085: try {
086: InitialContext ic = new InitialContext();
087: namingEntry = (NamingEntry) lookupNamingEntry(
088: (Context) ic.lookup("java:comp/env"),
089: clazz, jndiName);
090: } catch (NameNotFoundException e) {
091: namingEntry = null;
092: }
093: } else {
094: Log
095: .warn("Can't lookup locally scoped naming entries outside of scope");
096: throw new NamingException(
097: "Can't lookup locally scoped naming entries outside of scope");
098: }
099: break;
100: }
101: default: {
102: Log.info("No scope to lookup name: " + jndiName);
103: }
104: }
105: return namingEntry;
106: }
107:
108: /** Get all NameEntries of a certain type in a context.
109: *
110: * @param scopeType local or global
111: * @param clazz the type of the entry
112: * @return
113: * @throws NamingException
114: */
115: public static List lookupNamingEntries(int scopeType, Class clazz)
116: throws NamingException {
117: ArrayList list = new ArrayList();
118: switch (scopeType) {
119: case SCOPE_GLOBAL: {
120: lookupNamingEntries(list, new InitialContext(), clazz);
121: break;
122: }
123: case SCOPE_LOCAL: {
124: //WARNING: you can only look up local scope if you are indeed in the scope
125: if (getScope() == SCOPE_LOCAL) {
126: InitialContext ic = new InitialContext();
127:
128: lookupNamingEntries(list, (Context) ic
129: .lookup("java:comp/env"), clazz);
130: } else {
131: Log
132: .warn("Can't lookup local scope naming entries outside of local scope");
133: throw new NamingException(
134: "Can't lookup locally scoped naming entries outside of scope");
135: }
136: break;
137: }
138: }
139: return list;
140: }
141:
142: private static List lookupNamingEntries(List list, Context context,
143: Class clazz) throws NamingException {
144: try {
145: String name = (clazz == null ? "" : clazz.getName());
146: NamingEnumeration nenum = context.listBindings(name);
147: while (nenum.hasMoreElements()) {
148: Binding binding = (Binding) nenum.next();
149: if (binding.getObject() instanceof Context) {
150: lookupNamingEntries(list, (Context) binding
151: .getObject(), null);
152: } else
153: list.add(binding.getObject());
154: }
155: } catch (NameNotFoundException e) {
156: Log.debug("No entries of type " + clazz.getName()
157: + " in context=" + context);
158: }
159:
160: return list;
161: }
162:
163: /**
164: * Find a NamingEntry.
165: * @param context the context to search
166: * @param clazz the type of the entry (ie subclass of this class)
167: * @param jndiName the name of the class instance
168: * @return
169: * @throws NamingException
170: */
171: private static Object lookupNamingEntry(Context context,
172: Class clazz, String jndiName) throws NamingException {
173: NameParser parser = context.getNameParser("");
174: Name name = parser.parse("");
175: name.add(clazz.getName());
176: name.addAll(parser.parse(jndiName));
177:
178: return context.lookup(name);
179: }
180:
181: /** Constructor
182: * @param jndiName the name of the object which will eventually be in java:comp/env
183: * @param object the object to be bound
184: * @throws NamingException
185: */
186: public NamingEntry(String jndiName, Object object)
187: throws NamingException {
188: this .jndiName = jndiName;
189: this .objectToBind = object;
190: InitialContext icontext = new InitialContext();
191:
192: //if a threadlocal is set indicating we are inside a
193: //webapp, then bind naming entries to the webapp's
194: //context instead of the global context
195: switch (getScope()) {
196: case SCOPE_GLOBAL: {
197: context = icontext;
198: isGlobal = true;
199: break;
200: }
201: case SCOPE_LOCAL: {
202: context = (Context) icontext.lookup("java:comp/env");
203: isGlobal = false;
204: break;
205: }
206: }
207:
208: NameParser parser = context.getNameParser("");
209: Name contextName = parser.parse(context.getNameInNamespace());
210:
211: Name name = parser.parse("");
212: name.add(getClass().getName());
213: name.add(getJndiName());
214: namingEntryNameString = name.toString();
215: //bind this NameEntry in the given context so we can access it later
216: NamingUtil.bind(context, namingEntryNameString, this );
217: String absoluteNamingEntryNameString = (isGlobal() ? ""
218: : "java:")
219: + name.addAll(0, contextName).toString();
220:
221: //bind the object itself in the given context so that we can get it later
222: Name objectName = parser.parse(getJndiName());
223: objectNameString = objectName.toString();
224: NamingUtil.bind(context, objectNameString, getObjectToBind());
225:
226: //remember the full name of the bound object so that it can be used in
227: //link references later
228: Name fullName = objectName.addAll(0, contextName);
229: absoluteObjectNameString = (isGlobal() ? "" : "java:")
230: + fullName.toString();
231:
232: Log.debug("Bound " + absoluteObjectNameString);
233: Log.debug("Bound " + absoluteNamingEntryNameString);
234: }
235:
236: /**
237: * Add a java:comp/env binding for the object represented by
238: * this NamingEntry
239: * @throws NamingException
240: */
241: public void bindToEnv() throws NamingException {
242: //don't bind local scope naming entries as they are already bound to java:comp/env
243: if (isGlobal()) {
244: InitialContext ic = new InitialContext();
245: Context env = (Context) ic.lookup("java:comp/env");
246: Log.info("Binding java:comp/env/" + getJndiName() + " to "
247: + absoluteObjectNameString);
248: NamingUtil.bind(env, getJndiName(), new LinkRef(
249: absoluteObjectNameString));
250: }
251: }
252:
253: /**
254: * Unbind this NamingEntry from a java:comp/env
255: */
256: public void unbindEnv() {
257: try {
258: InitialContext ic = new InitialContext();
259: Context env = (Context) ic.lookup("java:comp/env");
260: Log.info("Unbinding java:comp/env/" + getJndiName());
261: env.unbind(getJndiName());
262: } catch (NamingException e) {
263: Log.warn(e);
264: }
265: }
266:
267: /**
268: * Unbind this NamingEntry entirely
269: */
270: public void unbind() {
271: try {
272: context.unbind(objectNameString);
273: context.unbind(namingEntryNameString);
274: } catch (NamingException e) {
275: Log.warn(e);
276: }
277: }
278:
279: /**
280: * Get the unique name of the object
281: * @return
282: */
283: public String getJndiName() {
284: return this .jndiName;
285: }
286:
287: /**
288: * Get the object that is to be bound
289: * @return
290: */
291: public Object getObjectToBind() throws NamingException {
292: return this .objectToBind;
293: }
294:
295: /**
296: * Check if this naming entry was global or locally scoped to a webapp
297: * @return true if naming entry was bound at global scope, false otherwise
298: */
299: public boolean isGlobal() {
300: return this.isGlobal;
301: }
302:
303: }
|