001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
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    package org.apache.hivemind.lib.impl;
016    
017    import java.util.Hashtable;
018    
019    import javax.naming.Context;
020    import javax.naming.InitialContext;
021    import javax.naming.NamingException;
022    
023    import org.apache.hivemind.ApplicationRuntimeException;
024    import org.apache.hivemind.HiveMind;
025    import org.apache.hivemind.lib.NameLookup;
026    import org.apache.hivemind.lib.RemoteExceptionCoordinator;
027    import org.apache.hivemind.lib.RemoteExceptionEvent;
028    import org.apache.hivemind.lib.RemoteExceptionListener;
029    
030    /**
031     * Standard implementation of the {@link org.apache.hivemind.lib.NameLookup}
032     * service interface.
033     *
034     * @author Howard Lewis Ship
035     */
036    public class NameLookupImpl implements NameLookup, RemoteExceptionListener
037    {
038        private RemoteExceptionCoordinator _coordinator;
039        private Context _initialContext;
040        private String _initialFactory;
041        private String _URLPackages;
042        private String _providerURL;
043    
044        public Object lookup(String name, Class expected)
045        {
046            int i = 0;
047    
048            while (true)
049            {
050                Context context = null;
051                Object raw = null;
052    
053                try
054                {
055                    context = getInitialContext();
056    
057                    raw = context.lookup(name);
058                }
059                catch (NamingException ex)
060                {
061                    if (i++ == 0)
062                        _coordinator.fireRemoteExceptionDidOccur(this, ex);
063                    else
064                        throw new ApplicationRuntimeException(
065                            ImplMessages.unableToLookup(name, context),
066                            ex);
067                    continue;
068                }
069    
070                if (raw == null)
071                    throw new ApplicationRuntimeException(ImplMessages.noObject(name, expected));
072    
073                if (!expected.isAssignableFrom(raw.getClass()))
074                    throw new ApplicationRuntimeException(ImplMessages.wrongType(name, raw, expected));
075    
076                return raw;
077            }
078        }
079    
080        private Context getInitialContext() throws NamingException
081        {
082            if (_initialContext == null)
083            {
084    
085                Hashtable properties = new Hashtable();
086    
087                if (!HiveMind.isBlank(_initialFactory))
088                    properties.put(Context.INITIAL_CONTEXT_FACTORY, _initialFactory);
089    
090                if (!HiveMind.isBlank(_providerURL))
091                    properties.put(Context.PROVIDER_URL, _providerURL);
092    
093                if (!HiveMind.isBlank(_URLPackages))
094                    properties.put(Context.URL_PKG_PREFIXES, _URLPackages);
095    
096                _initialContext = constructContext(properties);
097            }
098    
099            return _initialContext;
100        }
101    
102        /**
103         * Constructs the InitialContext (this is separated out in a standalone
104         * method so that it may be overridden in a testing subclass).
105         */
106        protected Context constructContext(Hashtable properties) throws NamingException
107        {
108            return new InitialContext(properties);
109        }
110    
111        /**
112         * Sets the InitialContext to null.
113         */
114        public void remoteExceptionDidOccur(RemoteExceptionEvent event)
115        {
116            _initialContext = null;
117        }
118    
119        /**
120         * Sets the initial factory used to create the initial JNDI context.
121         * Equivalent to the system property <code>java.naming.factory.initial</code>.
122         */
123        public void setInitialFactory(String string)
124        {
125            _initialFactory = string;
126        }
127    
128        /**
129         * Sets the JNDI provider URL, used to create the initial JNDI context.
130         * Equivalent to the system property <code>java.naming.provider.url</code>.
131         */
132        public void setProviderURL(String string)
133        {
134            _providerURL = string;
135        }
136    
137        /**
138         * Sets the URL packages, used to create the initial JNDI context.
139         * Equivalent to the system property
140         * <code>java.naming.factory.url.pkgs</code>
141         */
142    
143        public void setURLPackages(String string)
144        {
145            _URLPackages = string;
146        }
147    
148        public void setCoordinator(RemoteExceptionCoordinator coordinator)
149        {
150            _coordinator = coordinator;
151        }
152    
153    }