001: /* JFox, the OpenSource J2EE Application Server
002: *
003: * Copyright (C) 2002 huihoo.com
004: * Distributable under GNU LGPL license
005: * See the GNU Lesser General Public License for more details.
006: */
007:
008: package org.huihoo.jfox.jndi;
009:
010: import java.rmi.RemoteException;
011: import java.rmi.MarshalledObject;
012: import java.io.IOException;
013: import java.util.Map;
014: import java.util.Collections;
015: import java.util.HashMap;
016: import java.util.List;
017: import java.util.ArrayList;
018: import java.util.Iterator;
019: import java.util.Hashtable;
020:
021: import javax.naming.Context;
022: import javax.naming.Name;
023: import javax.naming.NamingException;
024: import javax.naming.InvalidNameException;
025: import javax.naming.NameAlreadyBoundException;
026: import javax.naming.NameNotFoundException;
027: import javax.naming.NotContextException;
028: import javax.naming.Binding;
029: import javax.naming.NameClassPair;
030: import javax.naming.ContextNotEmptyException;
031:
032: import org.huihoo.jfox.jndi.NamingService;
033:
034: /**
035: *
036: * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
037: */
038:
039: // NOTE: all name was absolute name
040: //public class NamingServiceSupport extends PortableRemoteObject implements NamingService,Serializable {
041: //public class NamingServiceSupport extends UnicastRemoteObject implements NamingService,Serializable {
042: public class NamingServiceSupport implements NamingService {
043: /**
044: * the bindings hold all the naming
045: */
046: private static Map bindings = Collections
047: .synchronizedMap(new HashMap());
048:
049: // public NamingServiceSupport() throws RemoteException {
050: // }
051:
052: public void bind(Context ctx, Name name, Object obj,
053: String className) throws NamingException, RemoteException {
054: if (name.isEmpty()) {
055: throw new InvalidNameException();
056: }
057: // doCreate needed subcontext
058: if (name.size() > 1) {
059: Name prefix = name.getPrefix(name.size() - 1);
060: if (!prefix.toString().equals("/")) {
061: this .createSubcontext(ctx, name
062: .getPrefix(name.size() - 1));
063: }
064: }
065:
066: if (this .isBound(name)) {
067: throw new NameAlreadyBoundException(name.toString());
068: }
069: // so bind it
070: setBinding(name, obj, className);
071: }
072:
073: public void rebind(Context ctx, Name name, Object obj,
074: String className) throws NamingException, RemoteException {
075: if (name.isEmpty()) {
076: throw new InvalidNameException();
077: }
078: // doCreate needed subcontext
079: this .createSubcontext(ctx, name.getPrefix(name.size() - 1));
080:
081: // can't rebind a context
082: if (this .isBound(name)
083: && (this .getBinding(name).getObject() instanceof Context)) {
084: throw new NamingException("Cannot rebind a context!");
085: }
086:
087: // so bind it
088: setBinding(name, obj, className);
089: }
090:
091: public void unbind(Context ctx, Name name) throws NamingException,
092: RemoteException {
093: if (!this .isBound(name)) { // not bound,throw Exception
094: throw new NameNotFoundException("name: " + name.toString());
095: }
096:
097: if (this .getBinding(name).getObject() instanceof Context) { // is a context
098: this .destroySubcontext(ctx, name);
099: } else { // is a normal object
100: removeBinding(name);
101: }
102: }
103:
104: public Object lookup(Name name) throws NamingException,
105: RemoteException {
106: if (this .isBound(name)) {
107: Object obj = this .getBinding(name).getObject();
108: return obj;
109: } else {
110: throw new NameNotFoundException(name.toString());
111: }
112: }
113:
114: public Object lookupLink(Name name) throws NamingException,
115: RemoteException {
116: return null;
117: }
118:
119: public List list(Context ctx, Name name) throws NamingException,
120: RemoteException {
121: if (!this .isBound(name)) { // not bound
122: throw new NameNotFoundException(name.toString());
123: }
124: // if(!(this.getBinding(name).getObject() instanceof Context)){ // not context
125: // throw new NotContextException("name: " + name.toString());
126: // }
127: isContext(name);
128:
129: List list = new ArrayList();
130: Iterator it = bindings.keySet().iterator();
131: while (it.hasNext()) {
132: String key = (String) it.next();
133: Name namekey = ctx.getNameParser(key).parse(key);
134: if (namekey.startsWith(name)
135: && (namekey.size() == name.size() + 1)) {
136: Binding bind = this .getBinding(namekey);
137: list.add(new NameClassPair(bind.getName(), bind
138: .getClassName(), false));
139: }
140: }
141: return list;
142: }
143:
144: public List listBindings(Context ctx, Name name)
145: throws NamingException, RemoteException {
146: if (!this .isBound(name)) { // not bound
147: throw new NameNotFoundException(name.toString());
148: }
149: // if(!(this.getBinding(name).getObject() instanceof Context)){ // not context
150: // throw new NotContextException("name: " + name.toString());
151: // }
152: isContext(name);
153:
154: List list = new ArrayList();
155: Iterator it = bindings.keySet().iterator();
156: while (it.hasNext()) {
157: String key = (String) it.next();
158: Name namekey = ctx.getNameParser(key).parse(key);
159: if (namekey.startsWith(name)
160: && (namekey.size() == name.size() + 1)) {
161: Binding bind = this .getBinding(namekey);
162: list.add(bind);
163: }
164: }
165: return list;
166: }
167:
168: public synchronized Context createSubcontext(Context ctx, Name name)
169: throws NamingException, RemoteException {
170: if (name.isEmpty() || name.toString().trim().equals("/")) {
171: throw new InvalidNameException(name.toString());
172: }
173: Context lastContext = null;
174: for (int i = 2; i <= name.size(); i++) { // while i = Configure.ROOT_NAME_LENGTH ,will doCreate the root context
175: Name subName = name.getPrefix(i);
176: if (!this .isBound(subName)) {
177: lastContext = createNextSubcontext(subName, ctx
178: .getEnvironment()); // name not binding,doCreate a sub context
179: }
180: }
181: return lastContext;
182: }
183:
184: /**
185: * destory a empty sub context
186: */
187: public void destroySubcontext(Context ctx, Name name)
188: throws NamingException, RemoteException {
189: if (!bindings.containsKey(name.toString())) {
190: throw new NameNotFoundException("name: " + name.toString());
191: }
192:
193: isContext(name);
194:
195: List list = this .list(ctx, name);
196: if (list.isEmpty()) { // context is empty
197: removeBinding(name);
198: } else { // context not empty
199: throw new ContextNotEmptyException("name: "
200: + name.toString());
201: }
202: }
203:
204: public void closeSubcontext(Context ctx, Name name)
205: throws NamingException, RemoteException {
206: if (!bindings.containsKey(name.toString())) {
207: throw new NameNotFoundException("name: " + name.toString());
208: }
209:
210: isContext(name);
211:
212: // Object binding = this.getBinding(name).getObject();
213: // if(!(binding instanceof MarshalledObject)){
214: // throw new NotContextException("name: " + name.toString() + ", " + binding);
215: // }
216: // Object obj = binding;
217: // try {
218: // obj = ((MarshalledObject)binding).get();
219: // }
220: // catch(Exception e){
221: // throw new NamingException(e.toString());
222: // }
223: //
224: // if(!(obj instanceof Context)) {
225: // throw new NotContextException("name: " + name.toString() + ", " + binding);
226: // }
227:
228: List list = this .list(ctx, name);
229: if (!list.isEmpty()) { // context is not empty
230: for (int i = 0; i < list.size(); i++) {
231: String sub_name = ((NameClassPair) list.get(i))
232: .getName();
233: if (sub_name.trim().equals("/"))
234: continue;
235: removeBinding(ctx.getNameParser(sub_name).parse(
236: sub_name));
237: }
238: }
239:
240: removeBinding(name);
241: }
242:
243: public boolean isBound(Name name) throws RemoteException {
244: return bindings.containsKey(name.toString()) ? true : false;
245: }
246:
247: /**
248: * get the Binding object that bind with the key
249: */
250: private Binding getBinding(Name key) {
251: String s_key = key.toString();
252: Object obj = bindings.get(s_key);
253: if (obj == null)
254: return null;
255: Binding b = (Binding) bindings.get(s_key);
256: return b;
257: }
258:
259: private void setBinding(Name name, Object obj, String className) {
260: String n = name.toString();
261: bindings.put(n, new Binding(n, className, obj, false));
262: }
263:
264: /**
265: * doCreate a sub context with the name
266: * return the context
267: */
268: private Context createNextSubcontext(Name name, Hashtable env)
269: throws NamingException {
270: ContextSupport ctx = new ContextSupport(name, env);
271: Object obj = ctx;
272: try {
273: obj = new MarshalledObject(ctx);
274: } catch (IOException e) {
275: throw new NamingException(e.toString());
276: }
277: setBinding(name, obj, ctx.getClass().getName());
278: return ctx;
279: }
280:
281: private void isContext(Name name) throws NamingException {
282: Object binding = this .getBinding(name).getObject();
283: if (!(binding instanceof MarshalledObject)) {
284: throw new NotContextException("name: " + name.toString()
285: + ", " + binding);
286: }
287: Object obj = binding;
288: try {
289: obj = ((MarshalledObject) binding).get();
290: } catch (Exception e) {
291: throw new NamingException(e.toString());
292: }
293:
294: if (!(obj instanceof Context)) {
295: throw new NotContextException("name: " + name.toString()
296: + ", " + binding);
297: }
298:
299: }
300:
301: /**
302: * remove from bindings
303: */
304: private void removeBinding(Name name) {
305: bindings.remove(name.toString());
306: }
307:
308: }
|