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    
010    package org.picocontainer.gems.jndi;
011    
012    import java.io.IOException;
013    import java.io.Serializable;
014    
015    import javax.naming.Context;
016    import javax.naming.InitialContext;
017    import javax.naming.Name;
018    import javax.naming.NameNotFoundException;
019    import javax.naming.NamingException;
020    
021    import org.picocontainer.ObjectReference;
022    import org.picocontainer.PicoCompositionException;
023    
024    /**
025     * object reference to store and retrieve objects from JNDI
026     * 
027     * @author ko5tik
028     * 
029     */
030    @SuppressWarnings("serial")
031    public 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    }