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