001    // SECTION-START[License Header]
002    /*
003     *   Copyright (c) 2009 The JOMC Project
004     *   Copyright (c) 2005 Christian Schulte <cs@jomc.org>
005     *   All rights reserved.
006     *
007     *   Redistribution and use in source and binary forms, with or without
008     *   modification, are permitted provided that the following conditions
009     *   are met:
010     *
011     *     o Redistributions of source code must retain the above copyright
012     *       notice, this list of conditions and the following disclaimer.
013     *
014     *     o Redistributions in binary form must reproduce the above copyright
015     *       notice, this list of conditions and the following disclaimer in
016     *       the documentation and/or other materials provided with the
017     *       distribution.
018     *
019     *   THIS SOFTWARE IS PROVIDED BY THE JOMC PROJECT AND CONTRIBUTORS "AS IS"
020     *   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021     *   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
022     *   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JOMC PROJECT OR
023     *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
024     *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
025     *   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
026     *   OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
027     *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
028     *   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
029     *   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030     *
031     *   $Id$
032     *
033     */
034    // SECTION-END
035    package org.jomc.ri;
036    
037    import java.io.IOException;
038    import java.net.URI;
039    import java.text.MessageFormat;
040    import java.util.ResourceBundle;
041    import javax.naming.Context;
042    import javax.naming.InitialContext;
043    import javax.naming.NamingException;
044    import javax.rmi.PortableRemoteObject;
045    import org.jomc.spi.Locator;
046    
047    // SECTION-START[Documentation]
048    /**
049     *
050     * Default {@code Locator} implementation.
051     *
052     * The default {@code Locator} implementation looks up objects using JNDI.
053     * It supports location URI schemes {@code jndi} and {@code jndi+rmi}.
054     *
055     *
056     * @author <a href="mailto:cs@jomc.org">Christian Schulte</a> 1.0
057     * @version $Id$
058     */
059    // SECTION-END
060    // SECTION-START[Annotations]
061    @javax.annotation.Generated( value = "org.jomc.tools.JavaSources",
062                                 comments = "See http://jomc.sourceforge.net/jomc/1.0-alpha-4/jomc-tools" )
063    // SECTION-END
064    public class DefaultLocator implements Locator
065    {
066        // SECTION-START[DefaultLocator]
067    
068        /** Constant for the {@code 'jndi'} URI scheme. */
069        private static final String JNDI_URI_SCHEME = "jndi";
070    
071        /** Constant for the {@code 'jndi+rmi'} URI scheme. */
072        private static final String JNDI_RMI_URI_SCHEME = "jndi+rmi";
073    
074        /** URI schemes supported by this {@code Locator} implementation. */
075        private static final String[] SUPPORTED_URI_SCHEMES =
076        {
077            JNDI_URI_SCHEME, JNDI_RMI_URI_SCHEME
078        };
079    
080        /** The JNDI context of the instance. */
081        private Context jndiContext;
082    
083        /**
084         * Gets a flag indicating support for a given location URI.
085         *
086         * @param location The location URI to test support for.
087         *
088         * @return {@code true} if {@code location} is supported by this implementation; {@code false} else.
089         *
090         * @throws NullPointerException if {@code location} is {@code null}.
091         */
092        public boolean isLocationSupported( final URI location )
093        {
094            if ( location == null )
095            {
096                throw new NullPointerException( "location" );
097            }
098    
099            final String scheme = location.getScheme();
100            for ( String s : SUPPORTED_URI_SCHEMES )
101            {
102                if ( s.equals( scheme ) )
103                {
104                    return true;
105                }
106            }
107    
108            return false;
109        }
110    
111        /**
112         * Gets the JNDI context of the instance.
113         *
114         * @return The JNDI context of the instance.
115         *
116         * @throws NamingException if getting the context fails.
117         */
118        public Context getJndiContext() throws NamingException
119        {
120            if ( this.jndiContext == null )
121            {
122                this.jndiContext = new InitialContext();
123            }
124    
125            return this.jndiContext;
126        }
127    
128        /**
129         * Gets the JNDI name for a given location.
130         *
131         * @param location The location to get a JNDI name for.
132         *
133         * @return The JNDI name for {@code location}.
134         *
135         * @throws NullPointerException if {@code location} is {@code null}.
136         */
137        public String getJndiName( final URI location )
138        {
139            if ( location == null )
140            {
141                throw new NullPointerException( "location" );
142            }
143    
144            String name = location.getSchemeSpecificPart();
145            if ( name == null || name.replace( '/', ' ' ).trim().length() == 0 )
146            {
147                name = "";
148            }
149            if ( location.getFragment() != null )
150            {
151                name += '#' + location.getFragment();
152            }
153    
154            return name;
155        }
156    
157        public <T> T getObject( final Class<T> specification, final URI location ) throws IOException
158        {
159            if ( specification == null )
160            {
161                throw new NullPointerException( "specification" );
162            }
163            if ( location == null )
164            {
165                throw new NullPointerException( "location" );
166            }
167    
168            try
169            {
170                T object = null;
171    
172                final String scheme = location.getScheme();
173                if ( !this.isLocationSupported( location ) )
174                {
175                    throw new IOException( this.getMessage( "unsupportedUriScheme", new Object[]
176                        {
177                            location.getScheme()
178                        } ) );
179    
180                }
181    
182                final Object jndiObject = this.getJndiContext().lookup( this.getJndiName( location ) );
183    
184                if ( JNDI_URI_SCHEME.equals( scheme ) )
185                {
186                    object = (T) jndiObject;
187                }
188                else if ( JNDI_RMI_URI_SCHEME.equals( scheme ) )
189                {
190                    object = (T) PortableRemoteObject.narrow( jndiObject, specification );
191                }
192    
193                return object;
194            }
195            catch ( final NamingException e )
196            {
197                throw (IOException) new IOException( e.getMessage() ).initCause( e );
198            }
199        }
200    
201        private String getMessage( final String key, final Object args )
202        {
203            return new MessageFormat( ResourceBundle.getBundle( DefaultLocator.class.getName().replace( '.', '/' ) ).
204                getString( key ) ).format( args );
205    
206        }
207    
208        // SECTION-END
209        // SECTION-START[Constructors]
210    
211        /** Creates a new {@code DefaultLocator} instance. */
212        @javax.annotation.Generated( value = "org.jomc.tools.JavaSources",
213                                     comments = "See http://jomc.sourceforge.net/jomc/1.0-alpha-4/jomc-tools" )
214        public DefaultLocator()
215        {
216            // SECTION-START[Default Constructor]
217            super();
218            // SECTION-END
219        }
220        // SECTION-END
221        // SECTION-START[Dependencies]
222        // SECTION-END
223        // SECTION-START[Properties]
224        // SECTION-END
225        // SECTION-START[Messages]
226        // SECTION-END
227    }