001/*****************************************************************************
002 * Copyright (c) PicoContainer Organization. All rights reserved.            *
003 * ------------------------------------------------------------------------- *
004 * The software in this package is published under the terms of the BSD      *
005 * style license a copy of which has been included with this distribution in *
006 * the LICENSE.txt file.                                                     *
007 *                                                                           *
008 *****************************************************************************/
009
010package org.picocontainer.gems.jndi;
011
012import java.io.IOException;
013import java.io.Serializable;
014
015import javax.naming.Context;
016import javax.naming.InitialContext;
017import javax.naming.Name;
018import javax.naming.NameNotFoundException;
019import javax.naming.NamingException;
020
021import org.picocontainer.ObjectReference;
022import org.picocontainer.PicoCompositionException;
023
024/**
025 * object reference to store and retrieve objects from JNDI
026 * 
027 * @author ko5tik
028 * 
029 */
030@SuppressWarnings("serial")
031public class JNDIObjectReference<T> implements ObjectReference<T> , Serializable{
032
033
034        String name;
035
036        transient Context context;
037
038        public JNDIObjectReference(final String name, final Context ctx) {
039                super();
040                this.name = name;
041                this.context = ctx;
042        }
043
044        public JNDIObjectReference(final String jndiName) throws NamingException {
045                this(jndiName,new InitialContext());
046        }
047
048        /**
049         * retrieve object from JNDI if possible
050         */
051        public T get() {
052                try {
053                        return (T) context.lookup(name);
054                } catch(NameNotFoundException e) {
055                        // this is not error, but normal situation - nothing
056                        // was stored yet
057                        return null;
058                } catch (NamingException e) {
059                        throw new PicoCompositionException("unable to resolve jndi name:"
060                                        + name, e);
061                }
062        }
063
064        /**
065         * store object in JNDI under specified name
066         */
067        public void set(final T item) {
068                try {
069                        if (item == null) {
070                                context.unbind(name);
071                        } else {
072
073                                Context ctx = context;
074                                Name n = ctx.getNameParser("").parse(name);
075                                while (n.size() > 1) {
076                                        String ctxName = n.get(0);
077                                        try {
078                                                ctx = (Context) ctx.lookup(ctxName);
079                                        } catch (NameNotFoundException e) {
080                                                ctx = ctx.createSubcontext(ctxName);
081                                        }
082                                        n = n.getSuffix(1);
083                                }
084                                // unbind name just in case
085                                try {
086                                        if (ctx.lookup(n) != null) {
087                                                ctx.unbind(n);
088                                        }
089                                } catch (NameNotFoundException e) {
090                                        // that's ok
091                                }
092                                ctx.bind(n, item);
093                        }
094                } catch (NamingException e) {
095                        throw new PicoCompositionException("unable to bind to  jndi name:"
096                                        + name, e);
097                }
098        }
099
100        /**
101         * name of this reference
102         * 
103         * @return
104         */
105        public String getName() {
106                return name;
107        }
108
109        /**
110         * here we try to capture (eventual) deserealisation of this reference by
111         * some container (notably JBoss)  and restore context as initial context
112         * I hope this will be sufficient for most puproses
113         * 
114         * @param in
115         * @throws IOException
116         * @throws ClassNotFoundException
117         */
118        private void readObject(final java.io.ObjectInputStream in)throws IOException, ClassNotFoundException {
119                try {
120                        context = new InitialContext();
121                } catch (NamingException e) {
122                        throw new IOException("unable to create initial context");
123                }
124                in.defaultReadObject();
125        }
126        
127        
128        @Override
129        public String toString() {
130                return "(" + getName() + ")";
131        }
132}