001    /* ====================================================================
002     * The Apache Software License, Version 1.1
003     *
004     * Copyright (c) 2003 The Apache Software Foundation.  All rights
005     * 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     * 1. Redistributions of source code must retain the above copyright
012     *    notice, this list of conditions and the following disclaimer.
013     *
014     * 2. 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     * 3. The end-user documentation included with the redistribution,
020     *    if any, must include the following acknowledgment:
021     *       "This product includes software developed by the
022     *        Apache Software Foundation (http://www.apache.org/)."
023     *    Alternately, this acknowledgment may appear in the software itself,
024     *    if and wherever such third-party acknowledgments normally appear.
025     *
026     * 4. The names "The Jakarta Project", "Commons", and "Apache Software
027     *    Foundation" must not be used to endorse or promote products derived
028     *    from this software without prior written permission. For written
029     *    permission, please contact apache@apache.org.
030     *
031     * 5. Products derived from this software may not be called "Apache",
032     *    nor may "Apache" appear in their name, without prior written
033     *    permission of the Apache Software Foundation.
034     *
035     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038     * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046     * SUCH DAMAGE.
047     * ====================================================================
048     *
049     * This software consists of voluntary contributions made by many
050     * individuals on behalf of the Apache Software Foundation.  For more
051     * information on the Apache Software Foundation, please see
052     * <http://www.apache.org/>.
053     *
054     */
055    package org.jpu.patterns.serviceLocator;
056    
057    import java.lang.reflect.Method;
058    
059    import org.apache.commons.logging.Log;
060    import org.apache.commons.logging.LogFactory;
061    
062    /**
063     * Subclass of {@link Locator} specialized for stateless session beans.
064     * This class overrides the <code>lookup()</code> method to call
065     * <code>create()</code> on the home object.  Any exceptions thrown
066     * from <code>create()</code> are rethrown wrapped in {@link ServiceLocatorException}.
067     * Of course the home interface must define a public no-arg <code>create()</code>
068     * method (as all SLSB's must); else a <code>ServiceLocatorException</code> will
069     * result.
070     */
071    public class SLSBLocator extends Locator implements ISLSBLocator {
072    
073        /**
074         * Alias for "<code>getSLSB(homeNamingIdentifier, (ServiceLocatorOptions)null)</code>".
075         */
076        public Object getSLSB(String homeNamingIdentifier) throws ServiceLocatorException {
077            return getSLSB(homeNamingIdentifier, (ServiceLocatorOptions)null);
078        }
079    
080        /**
081         * Alias for "<code>getObject(homeNamingIdentifier, c)</code>".
082         */
083        public Object getSLSB(String homeNamingIdentifier, Class c) throws ServiceLocatorException {
084            return getObject(homeNamingIdentifier, c);
085        }
086    
087        /**
088         * Alias for "<code>getObject(homeNamingIdentifier, options)</code>".
089         */
090        public Object getSLSB(String homeNamingIdentifier, ServiceLocatorOptions options) throws ServiceLocatorException {
091            return getObject(homeNamingIdentifier, options);
092        }
093    
094        /**
095         * Overrides the superclass version to create the SLSB from its remote interface.
096         * To change the way the SLSB is created, override {@link #createSLSB(Object,ServiceLocatorOptions)}.
097         */
098        public Object lookup(String namingIdentifier, ServiceLocatorOptions options) throws ServiceLocatorException {
099            Object homeobj = super.lookup(namingIdentifier, options);
100            try {
101                if ( _log.isDebugEnabled() ) {
102                    _log.debug( "homeobj for [jndi=" + namingIdentifier + "] is '" + homeobj + "'." );
103                }
104                Object slsb = createSLSB(homeobj, options);
105                return slsb;
106            }
107            catch( Exception e ) {
108                throw new ServiceLocatorException(e);
109            }
110        } 
111    
112        /**
113         * Narrows the reference to the given home to the appropriate type.  The default implementation examines <code>options</code>
114         * and, if it is of type {@link SLSBLocatorOptions} with <code>castHomeTo</code> non-<code>null</code>, calls
115         * {@link Locator#narrow(Object, Class)} to narrow to this type; 
116         * else it returns the original <code>homeobj</code>.
117         * <p>
118         * This method will be called by {@link #createSLSB(Object, ServiceLocatorOptions)} just before it calls the
119         * home object's accessible no-arg <code>create()</code> method.
120         */
121        public Object narrowSLSBHome(Object homeobj, ServiceLocatorOptions options) throws ServiceLocatorException {
122            if ( options instanceof SLSBLocatorOptions ) {
123                SLSBLocatorOptions myOptions = (SLSBLocatorOptions)options;
124                if ( myOptions.castHomeTo != null ) {
125                    homeobj = narrow(homeobj, myOptions.castHomeTo);
126                }
127            }
128            return homeobj;
129        }
130    
131        /**
132         * Creates a SLSB given its home.  Uses reflection to call the accessible no-arg
133         * <code>create()</code> method on the given home object.  <i>Does not</i>
134         * narrow the resulting <code>EJBObject</code>.  Calls {@link #narrowSLSBHome(Object, ServiceLocatorOptions)}
135         * to narrow the <code>EJBHome</code> before calling <code>create()</code> on it.
136         * Subclasses are free to override this behavior as needed.
137         */
138        public Object createSLSB(Object homeobj, ServiceLocatorOptions options) throws ServiceLocatorException {
139            try {
140                homeobj = narrowSLSBHome(homeobj, options);
141                Method createMethod = homeobj.getClass().getMethod( "create", new Class[0] );
142                if ( _log.isDebugEnabled() ) {
143                    _log.debug( "Calling method '" + createMethod + "'" );
144                }
145                Object svc = createMethod.invoke( homeobj, new Object[0] );
146                if ( _log.isDebugEnabled() ) {
147                    _log.debug( "Back from create().  svc='" + svc + "'" );
148                }
149                return svc;
150            }
151            catch( Exception e ) {
152                throw new ServiceLocatorException(e);
153            }
154        }
155    
156        private static Log _log = LogFactory.getLog(SLSBLocator.class); 
157    }
158