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.util.Properties; 058 059 /** 060 * Base class for all the locators in this package. These classes are 061 * extensible service locators that obtain--and optionally cache--references to 062 * various J2EE objects such as session beans, home objects, and data sources. 063 * They can also handle narrowing as appropriate 064 * and repackage the J2EE exceptions into a 065 * {@link ServiceLocatorException}. 066 * <p> 067 * In general these locators will just hand you the object you want 068 * and from there it's up to you; however, {@link SLSBLocator} will 069 * also use reflection to call the <code>create()</code> method, which 070 * (because the EJB is stateless) takes no arguments, and give you a 071 * reference to the SLSB itself, rather than its home. The EJB's 072 * remote reference, rather than its home, will then be returned (and optionally cached 073 * for subsequent requests). 074 * <p> 075 * The locators in this package <i>are not</i> implemented as singletons, in order 076 * to minimize assumptions about the application in which they are 077 * used and allow the developer to maintain locator instances any way he 078 * chooses. However, in the subpackage {@link org.jpu.patterns.serviceLocator.onePerContext} 079 * are versions that use the {@link org.jpu.patterns.singleton.onePerContext.OnePerContextManager} 080 * facility and define appropriate public <code>getInstance()</code> methods as 081 * described in {@link org.jpu.patterns.singleton.onePerContext.OnePerContextManager}. You can 082 * use these just like you would a traditional singleton, or you can supply an optional 083 * "context" parameter to the <code>getInstance()</code> calls. 084 * <p> 085 * The {@link ServiceLocatorOptions} class can be used by the client to 086 * govern the behavior of the public methods with respect to a single 087 * lookup. Among other options, the client can indicate that the 088 * lookup should bypass the cache. 089 * <p> 090 * <b>Strategies</b><br> 091 * By default the actual JNDI lookup is based on 092 * "<code>InitialContext.lookup()</code>", but you can change this by supplying your own {@link ILookupStrategy} 093 * via {@link #setLookupStrategy}. 094 * <p> 095 * The default caching implementation is a "null" cache, which does no caching, but 096 * you can change this by supplying your own {@link Cache} via {@link #setCache}. 097 * <p> 098 * The default approach to narrowing is based on <code>PortableRemoteObject.narrow()</code>, but 099 * you can change this by supplying your own {@link ILocator.INarrowStrategy} via 100 * {@link #setNarrowStrategy}. 101 * <p> 102 * <b>InitialContext Properties</b><br> 103 * For JNDI-based lookups, the caller must always specify the JNDI name to 104 * be passed to <code>InitialContext.lookup()</code>. In addition, these service locators give 105 * you the option of explicitly specifying a naming provider URL, initial 106 * context factory, or any other properies interpreted by <code>InitialContext</code>. You can do this 107 * either by explicitly adjusting the <code>Properties</code> 108 * instance associated with the {@link ILookupStrategy} (which would affect all lookups performed by 109 * that strategy), or by using the following special syntax for the naming identifiers (which only affects a single lookup operation): 110 * <pre> 111 * <i>jndiName</i>{;<i>name</i>=<i>value</i>}* 112 * </pre> 113 * where <i>name</i> is a property name and <i>value</i> is its value. Here is an example illustrating 114 * an LDAP lookup: 115 * <pre> 116 * <code> 117 * MyQueue;java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory;java.naming.provider.url=ldap://ldap.foo.com:389/ou=myqueues,o=foo.com,c=us 118 * </code> 119 * </pre> 120 * <p> 121 * Thus these service locators allow your application to reference objects defined in any 122 * number of different naming directories and refer to all these objects via simple strings. 123 * Of course these strings would normally reside in an external configuration source. 124 * <p> 125 * Properties passed using the above syntax override any settings in the {@link ILookupStrategy}'s 126 * <code>Properties</code> instance, which in turn override any "java.naming" system properties. 127 */ 128 public interface ILocator { 129 public interface IIdentifierParser { 130 public String getName(); 131 public Properties getProperties(); 132 public String getIdentifier(); 133 } 134 135 /** 136 * Defines the interface that the cache must fulfill. 137 */ 138 public static interface ICache { 139 public Object get(String namingIdentifier); 140 public void clear(); 141 public void remove(String namingIdentifier); 142 public void put(String namingIdentifier, Object obj); 143 } 144 145 /** 146 * Defines the interface for strategies that perform the actual lookup of objects (usually but not 147 * necessarily using JNDI). The default implementation {@link Locator.DefaultLookupStrategy} uses 148 * JNDI. 149 */ 150 public static interface ILookupStrategy { 151 152 public Properties getProperties(); 153 154 /** 155 * Looks up the object with the given name and returns it, or throws an exception if it can't 156 * be found. The {@link ServiceLocatorOptions} object passed to {@link #getObject(String)} 157 * is passed to this method. 158 * <p> 159 * This method <i>should not</i> narrow the object as that will be done by the caller. 160 */ 161 public Object lookup(String namingIdentifier, ServiceLocatorOptions options) throws ServiceLocatorException; 162 } 163 164 /** 165 * Defines the interface for strategies that narrow objects. Narrowing is necessary for 166 * remote objects and is usually done through "<code>PortableRemoteObject.narrow()</code>". 167 * The default implementation {@link Locator.DefaultNarrowStrategy} uses this form of narrowing. 168 * To set your own narrow strategy, either override {@link #newNarrowStrategy()} or call 169 * {@link #setNarrowStrategy}. 170 */ 171 public static interface INarrowStrategy { 172 /** 173 * Narrows the given object to the given type. If either <code>o</code> or 174 * <code>c</code> are <code>null</code>, this method returns <code>o</code>. 175 * Otherwise it attempts to narrow using <code>PortableRemoteObject.narrow()</code> 176 * and rethrows any exceptions as <code>ServiceLocatorException</code>, wrapping 177 * the original exception. 178 * <p> 179 * Subclasses are free to override this method; in particular, local homes 180 * should not be narrowed using <code>PortableRemoteObject.narrow()</code>. 181 */ 182 public Object narrow(Object o, Class c) throws ServiceLocatorException; 183 } 184 185 /** 186 * Removes the object with the specified JNDI name from the cache. 187 */ 188 public void removeFromCache(String namingIdentifier); 189 190 /** 191 * Removes all items from the cache. 192 */ 193 public void clearCache(); 194 195 /** 196 * Convenience alias for "<code>getObject( namingIdentifier, new ServiceLocatorOptions().setCastTo(c) )</code>". 197 * See {@link #getObject(String, ServiceLocatorOptions)}. 198 */ 199 public Object getObject(String namingIdentifier, Class c) throws ServiceLocatorException; 200 201 /** 202 * Convenience alias for "<code>getObject(namingIdentifier, (ServiceLocatorOptions)null)</code>". 203 * See {@link #getObject(String, ServiceLocatorOptions)}. 204 */ 205 public Object getObject(String namingIdentifier) throws ServiceLocatorException; 206 207 /** 208 * Attempts to find the object with the given JNDI name using the given options. 209 * <p> 210 * The method first checks the cache for an object with the given JNDI name, unless 211 * <code>options.noCache</code> is <code>true</code> in which case the cache is 212 * bypassed. If the object is not in the cache or the cache is being bypassed, 213 * the method will attempt to find the object using the protected <code>lookup()</code> 214 * method (which subclasses can override). Any exception thrown from that method 215 * will be allowed to propagate from this method. Any object found through 216 * JNDI is automatically entered into the cache via its public <code>put()</code> 217 * method. 218 * <p> 219 * If the object is found, either in the cache or via JNDI lookup, then if a narrow 220 * type is defined, either via <code>options.castTo</code> or 221 * {@link #getDefaultCast()}, the method will 222 * attempt to narrow the object to that type using the protected <code>narrow()</code> 223 * method (which subclasses are free to override). Narrow's default 224 * implementation uses <code>PortableRemoteObject.narrow()</code>. 225 * <p> 226 * If the named object cannot be found, or if the narrow fails, 227 * {@link ServiceLocatorException} is 228 * thrown wrapping the underlying JNDI exception. 229 * <p> 230 */ 231 public Object getObject(String namingIdentifier, ServiceLocatorOptions options) throws ServiceLocatorException; 232 233 /** 234 * Sets the cache, replacing the previous cache (and hence causing loss of previously 235 * cached objects). 236 */ 237 public void setCache(ICache cache); 238 239 /** 240 * Returns the cache. The returned object is unsynchronized, so the caller should synchronize on 241 * "<code>this</code>" while querying or modifying it. 242 */ 243 public ICache getCache(); 244 245 /** 246 * Sets the {@link ILocator.INarrowStrategy}, replacing the previous one. 247 */ 248 public void setNarrowStrategy(INarrowStrategy ls); 249 250 /** 251 * Returns the current {@link ILocator.INarrowStrategy}. 252 */ 253 public INarrowStrategy getNarrowStrategy(); 254 255 /** 256 * Sets the {@link ILocator.ILookupStrategy}, replacing the previous one. 257 */ 258 public void setLookupStrategy(ILookupStrategy ls); 259 260 /** 261 * Returns the current {@link ILocator.ILookupStrategy}. 262 */ 263 public ILookupStrategy getLookupStrategy(); 264 265 /** 266 * By default instantiates a {@link Locator.NullCache}, but subclasses can 267 * override to supply their own cache implementation. 268 */ 269 public ICache newCache(); 270 271 /** 272 * By default instantiates a {@link Locator.DefaultLookupStrategy}, but subclasses can 273 * override to supply their own {@link ILocator.ILookupStrategy} implementation. 274 */ 275 public ILookupStrategy newLookupStrategy(); 276 277 /** 278 * By default instantiates a {@link Locator.DefaultNarrowStrategy}, but subclasses can 279 * override to supply their own {@link ILocator.INarrowStrategy} implementation. 280 */ 281 public INarrowStrategy newNarrowStrategy(); 282 283 /** 284 * If <code>options.castTo</code> is not <code>null</code>, call {@link org.jpu.patterns.serviceLocator.Locator#narrow(Object,Class)} 285 * variant to narrow the given object to this type and return the result; else if 286 * {@link #getDefaultCast()} is not <code>null</code>, call {@link org.jpu.patterns.serviceLocator.Locator#narrow(Object,Class)} 287 * variant to narrow to this type and return the result; 288 * else return the original object passed via "<code>o</code>". 289 */ 290 public Object narrow(Object o, ServiceLocatorOptions options) throws ServiceLocatorException; 291 292 /** 293 * Simply calls "<code>getNarrowStrategy().narrow(o, c)</code>". If you wish to 294 * change the way narrowing is performed, write your own {@link ILocator.INarrowStrategy} and either override 295 * {@link #newNarrowStrategy()} to instantiate it, or call the public {@link #setNarrowStrategy(ILocator.INarrowStrategy)} 296 * method to replace the existing strategy. 297 */ 298 public Object narrow(Object o, Class c) throws ServiceLocatorException; 299 300 /** 301 * By default returns <code>null</code>, but subclasses can override to 302 * return the <code>Class</code> that should be passed as the second parameter 303 * to {@link #narrow(Object,Class)} if no class is passed via 304 * the <code>castTo</code> attribute of the {@link ServiceLocatorOptions} 305 * instance. If both <code>castTo</code> and the return value of this method 306 * are <code>null</code>, no cast is performed. 307 */ 308 public Class getDefaultCast(); 309 } 310 311