001// SECTION-START[License Header]
002// <editor-fold defaultstate="collapsed" desc=" Generated License ">
003/*
004 *   Java Object Management and Configuration
005 *   Copyright (C) Christian Schulte, 2005-206
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 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
021 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
022 *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
023 *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
024 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
025 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
026 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
027 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
029 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030 *
031 *   $JOMC: DefaultLocator.java 4795 2013-04-21 09:09:02Z schulte $
032 *
033 */
034// </editor-fold>
035// SECTION-END
036package org.jomc.ri;
037
038import java.io.IOException;
039import java.net.URI;
040import java.util.Locale;
041import javax.naming.Context;
042import javax.naming.InitialContext;
043import javax.naming.NamingException;
044import javax.rmi.PortableRemoteObject;
045import org.jomc.spi.Locator;
046
047// SECTION-START[Documentation]
048// <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
049/**
050 * Default {@code Locator} implementation.
051 *
052 * <dl>
053 *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.DefaultLocator</dd>
054 *   <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ DefaultLocator</dd>
055 *   <dt><b>Abstract:</b></dt><dd>No</dd>
056 *   <dt><b>Final:</b></dt><dd>No</dd>
057 *   <dt><b>Stateless:</b></dt><dd>No</dd>
058 * </dl>
059 *
060 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.0
061 * @version 1.0
062 */
063// </editor-fold>
064// SECTION-END
065// SECTION-START[Annotations]
066// <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
067@javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" )
068// </editor-fold>
069// SECTION-END
070public 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        for ( int i = SUPPORTED_URI_SCHEMES.length - 1; i >= 0; i-- )
106        {
107            if ( SUPPORTED_URI_SCHEMES[i].equals( location.getScheme() ) )
108            {
109                return true;
110            }
111        }
112
113        return false;
114    }
115
116    /**
117     * Gets the JNDI context of the instance.
118     *
119     * @return The JNDI context of the instance.
120     *
121     * @throws NamingException if getting the context fails.
122     */
123    public Context getJndiContext() throws NamingException
124    {
125        if ( this.jndiContext == null )
126        {
127            this.jndiContext = new InitialContext();
128        }
129
130        return this.jndiContext;
131    }
132
133    /**
134     * Gets the JNDI name for a given location.
135     *
136     * @param location The location to get a JNDI name for.
137     *
138     * @return The JNDI name for {@code location}.
139     *
140     * @throws NullPointerException if {@code location} is {@code null}.
141     */
142    public String getJndiName( final URI location )
143    {
144        if ( location == null )
145        {
146            throw new NullPointerException( "location" );
147        }
148
149        String name = location.getSchemeSpecificPart();
150        if ( name == null || name.replace( '/', ' ' ).trim().length() == 0 )
151        {
152            name = "";
153        }
154        if ( location.getFragment() != null )
155        {
156            name += '#' + location.getFragment();
157        }
158
159        return name;
160    }
161
162    public <T> T getObject( final Class<T> specification, final URI location ) throws IOException
163    {
164        if ( specification == null )
165        {
166            throw new NullPointerException( "specification" );
167        }
168        if ( location == null )
169        {
170            throw new NullPointerException( "location" );
171        }
172
173        T object = null;
174
175        try
176        {
177            final String scheme = location.getScheme();
178            if ( !this.isLocationSupported( location ) )
179            {
180                throw new IOException( getUnsupportedUriSchemeMessage( Locale.getDefault(), location.getScheme() ) );
181            }
182
183            final Object jndiObject = this.getJndiContext().lookup( this.getJndiName( location ) );
184
185            if ( JNDI_URI_SCHEME.equals( scheme ) )
186            {
187                object = (T) jndiObject;
188            }
189            else if ( JNDI_RMI_URI_SCHEME.equals( scheme ) )
190            {
191                object = (T) PortableRemoteObject.narrow( jndiObject, specification );
192            }
193
194            return object;
195        }
196        catch ( final NamingException e )
197        {
198            // JDK: As of JDK 6, "new IOException( message, cause )".
199            throw (IOException) new IOException( getMessage( e ) ).initCause( e );
200        }
201        catch ( final ClassCastException e )
202        {
203            // JDK: As of JDK 6, "new IOException( message, cause )".
204            throw (IOException) new IOException( getIllegalObjectMessage(
205                Locale.getDefault(), object != null ? object.toString() : null,
206                specification.getName() ) ).initCause( e );
207
208        }
209    }
210
211    private static String getMessage( final Throwable t )
212    {
213        return t != null
214               ? t.getMessage() != null && t.getMessage().trim().length() > 0
215                 ? t.getMessage()
216                 : getMessage( t.getCause() )
217               : null;
218
219    }
220
221    // SECTION-END
222    // SECTION-START[Constructors]
223    // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
224    /** Creates a new {@code DefaultLocator} instance. */
225    @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" )
226    public DefaultLocator()
227    {
228        // SECTION-START[Default Constructor]
229        super();
230        // SECTION-END
231    }
232    // </editor-fold>
233    // SECTION-END
234    // SECTION-START[Dependencies]
235    // SECTION-END
236    // SECTION-START[Properties]
237    // SECTION-END
238    // SECTION-START[Messages]
239    // <editor-fold defaultstate="collapsed" desc=" Generated Messages ">
240    /**
241     * Gets the text of the {@code <Illegal Object Message>} message.
242     * <p><dl>
243     *   <dt><b>Languages:</b></dt>
244     *     <dd>English (default)</dd>
245     *     <dd>Deutsch</dd>
246     *   <dt><b>Final:</b></dt><dd>No</dd>
247     * </dl></p>
248     * @param locale The locale of the message to return.
249     * @param objectInfo Format argument.
250     * @param classInfo Format argument.
251     * @return The text of the {@code <Illegal Object Message>} message for {@code locale}.
252     * @throws org.jomc.ObjectManagementException if getting the message instance fails.
253     */
254    @SuppressWarnings("unused")
255    @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" )
256    private static String getIllegalObjectMessage( final java.util.Locale locale, final java.lang.String objectInfo, final java.lang.String classInfo )
257    {
258        java.io.BufferedReader reader = null;
259        boolean suppressExceptionOnClose = true;
260
261        try
262        {
263            final String message = java.text.MessageFormat.format( java.util.ResourceBundle.getBundle( "org.jomc.ri.DefaultLocator", locale ).getString( "Illegal Object Message" ), objectInfo, classInfo, (Object) null );
264            final java.lang.StringBuilder builder = new java.lang.StringBuilder( message.length() );
265            reader = new java.io.BufferedReader( new java.io.StringReader( message ) );
266            final String lineSeparator = System.getProperty( "line.separator", "\n" );
267
268            String line;
269            while ( ( line = reader.readLine() ) != null )
270            {
271                builder.append( lineSeparator ).append( line );
272            }
273
274            suppressExceptionOnClose = false;
275            return builder.length() > 0 ? builder.substring( lineSeparator.length() ) : "";
276        }
277        catch( final java.lang.ClassCastException e )
278        {
279            throw new org.jomc.ObjectManagementException( e.getMessage(), e );
280        }
281        catch( final java.lang.IllegalArgumentException e )
282        {
283            throw new org.jomc.ObjectManagementException( e.getMessage(), e );
284        }
285        catch( final java.util.MissingResourceException e )
286        {
287            throw new org.jomc.ObjectManagementException( e.getMessage(), e );
288        }
289        catch( final java.io.IOException e )
290        {
291            throw new org.jomc.ObjectManagementException( e.getMessage(), e );
292        }
293        finally
294        {
295            try
296            {
297                if( reader != null )
298                {
299                    reader.close();
300                }
301            }
302            catch( final java.io.IOException e )
303            {
304                if( !suppressExceptionOnClose )
305                {
306                    throw new org.jomc.ObjectManagementException( e.getMessage(), e );
307                }
308            }
309        }
310    }
311    /**
312     * Gets the text of the {@code <Unsupported URI Scheme Message>} message.
313     * <p><dl>
314     *   <dt><b>Languages:</b></dt>
315     *     <dd>English (default)</dd>
316     *     <dd>Deutsch</dd>
317     *   <dt><b>Final:</b></dt><dd>No</dd>
318     * </dl></p>
319     * @param locale The locale of the message to return.
320     * @param schemeInfo Format argument.
321     * @return The text of the {@code <Unsupported URI Scheme Message>} message for {@code locale}.
322     * @throws org.jomc.ObjectManagementException if getting the message instance fails.
323     */
324    @SuppressWarnings("unused")
325    @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" )
326    private static String getUnsupportedUriSchemeMessage( final java.util.Locale locale, final java.lang.String schemeInfo )
327    {
328        java.io.BufferedReader reader = null;
329        boolean suppressExceptionOnClose = true;
330
331        try
332        {
333            final String message = java.text.MessageFormat.format( java.util.ResourceBundle.getBundle( "org.jomc.ri.DefaultLocator", locale ).getString( "Unsupported URI Scheme Message" ), schemeInfo, (Object) null );
334            final java.lang.StringBuilder builder = new java.lang.StringBuilder( message.length() );
335            reader = new java.io.BufferedReader( new java.io.StringReader( message ) );
336            final String lineSeparator = System.getProperty( "line.separator", "\n" );
337
338            String line;
339            while ( ( line = reader.readLine() ) != null )
340            {
341                builder.append( lineSeparator ).append( line );
342            }
343
344            suppressExceptionOnClose = false;
345            return builder.length() > 0 ? builder.substring( lineSeparator.length() ) : "";
346        }
347        catch( final java.lang.ClassCastException e )
348        {
349            throw new org.jomc.ObjectManagementException( e.getMessage(), e );
350        }
351        catch( final java.lang.IllegalArgumentException e )
352        {
353            throw new org.jomc.ObjectManagementException( e.getMessage(), e );
354        }
355        catch( final java.util.MissingResourceException e )
356        {
357            throw new org.jomc.ObjectManagementException( e.getMessage(), e );
358        }
359        catch( final java.io.IOException e )
360        {
361            throw new org.jomc.ObjectManagementException( e.getMessage(), e );
362        }
363        finally
364        {
365            try
366            {
367                if( reader != null )
368                {
369                    reader.close();
370                }
371            }
372            catch( final java.io.IOException e )
373            {
374                if( !suppressExceptionOnClose )
375                {
376                    throw new org.jomc.ObjectManagementException( e.getMessage(), e );
377                }
378            }
379        }
380    }
381    // </editor-fold>
382    // SECTION-END
383}