Source Code Cross Referenced for componentContext.java in  » UML » MetaBoss » com » metaboss » naming » component » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » UML » MetaBoss » com.metaboss.naming.component 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002:        // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003:        // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004:        // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005:        // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006:        // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007:        // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008:        // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009:        // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010:        // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011:        // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012:        // POSSIBILITY OF SUCH DAMAGE.
013:        //
014:        // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015:        package com.metaboss.naming.component;
016:
017:        import java.lang.reflect.InvocationHandler;
018:        import java.lang.reflect.Proxy;
019:        import java.util.Collections;
020:        import java.util.Comparator;
021:        import java.util.HashMap;
022:        import java.util.Hashtable;
023:        import java.util.Iterator;
024:        import java.util.Map;
025:        import java.util.SortedMap;
026:        import java.util.TreeMap;
027:        import java.util.regex.Pattern;
028:
029:        import javax.naming.CompositeName;
030:        import javax.naming.ConfigurationException;
031:        import javax.naming.Context;
032:        import javax.naming.InvalidNameException;
033:        import javax.naming.Name;
034:        import javax.naming.NameNotFoundException;
035:        import javax.naming.NameParser;
036:        import javax.naming.NamingEnumeration;
037:        import javax.naming.NamingException;
038:        import javax.naming.OperationNotSupportedException;
039:        import javax.naming.spi.ObjectFactory;
040:
041:        import org.apache.commons.logging.Log;
042:        import org.apache.commons.logging.LogFactory;
043:
044:        /** A sample service provider that implements interface factories lookup */
045:        class componentContext implements  Context {
046:            private static final Log sLogger = LogFactory
047:                    .getLog(componentContext.class);
048:            // This map keps mapping keys to match
049:            private SortedMap mMappingInstructions = new TreeMap(
050:                    new Comparator() {
051:                        // Compares two keys and places more detailed key on top. The more detailed
052:                        // key is the key which has as more non-wild card characters at the front and
053:                        // (if the same number at the front) at the back.  
054:                        public int compare(Object pObject1, Object pObject2) {
055:                            String lKey1 = (String) pObject1;
056:                            String lKey2 = (String) pObject2;
057:                            int lExplicitPrefixLength1 = lKey1.indexOf("*");
058:                            int lExplicitPrefixLength2 = lKey2.indexOf("*");
059:                            if (lExplicitPrefixLength1 < 0
060:                                    && lExplicitPrefixLength2 < 0)
061:                                return lKey1.compareTo(lKey2); // Both keys do not have a wild card it does not really matter which one is used first. Use natural string comparison
062:                            if (lExplicitPrefixLength1 < 0)
063:                                return -1; // Object1 should be on top of Object2 because Object1 is explicit and Object2 is not  				 
064:                            if (lExplicitPrefixLength2 < 0)
065:                                return 1; // Object2 should be on top of Object1 because Object2 is explicit and Object1 is not
066:                            // Both of the objects are not explicit
067:                            if (lExplicitPrefixLength1 > lExplicitPrefixLength2)
068:                                return -1; // Object1 should be on top of Object2 because Object1 has longer explicit prefix than Object2  				 
069:                            if (lExplicitPrefixLength1 < lExplicitPrefixLength2)
070:                                return 1; // Object2 should be on top of Object1 because Object2 has longer explicit prefix than Object1
071:                            // Both of the objects have same length of the explicit prefix
072:                            int lExplicitSuffixLength1 = lKey1.length()
073:                                    - lKey1.lastIndexOf("*") - 1;
074:                            int lExplicitSuffixLength2 = lKey2.length()
075:                                    - lKey2.lastIndexOf("*") - 1;
076:                            if (lExplicitSuffixLength1 == lExplicitSuffixLength2)
077:                                return lKey1.compareTo(lKey2); // Same length of explicit suffixes and prefixes - for now just return natural string comparison
078:                            return lExplicitSuffixLength1 > lExplicitSuffixLength2 ? -1
079:                                    : 1; // The key with the longer suffix is on top
080:                        }
081:                    });
082:            private Hashtable mEnvironmentProperties;
083:            private static Map sCustomEnvironmentFactoryCache = Collections
084:                    .synchronizedMap(new HashMap());
085:            private static Map sComponentFactoryCache = Collections
086:                    .synchronizedMap(new HashMap());
087:            protected static final NameParser myParser = new componentNameParser();
088:
089:            // If this key is present in the context environment this mechanism will try to instantiate
090:            // the object factory with the value taken as the class name. It will then call getObjectInstance() method
091:            // of this factory to obtain the java.util.Map object which contains the additional environment properties map
092:            // during this call to the getObjectInstance() method, the name parameter will be set to the 'component'
093:            // and the environment parameter will be set to the Context Environment Properties passed in the constructor.
094:            // This allows to do a number of things:
095:            // 1. In the future when we are providing some other contexts, the single custom factory
096:            // will be able to provide additional environment properties for different classes of URLs.
097:            // All the generic factory will need to do is to base the logic of which environment settings to return on the 
098:            // value of the name parameter.
099:            // 2. The factory may check the context environment and fix it by returning the Map with the same keys (which will
100:            // override it) and different values. If property needs to be removed - the returned property value may be set to null
101:            // The main need for this feature is to allow customisation of the place where jndi properties are stored.
102:            // The mappings obtained from the CustomEnvironmentFactory take precedence over the ones found in the context environment  
103:            private static final String sCustomEnvironmentPropertiesFactoryEnvKey = "com.metaboss.naming.componentCustomEnvironmentPropertiesFactory";
104:
105:            // Name of the system property which controlls if we should cache the factories once they are found for the particular caller 
106:            private static final String sEnableComponentFactoryCachingSystemPropertyKey = "com.metaboss.naming.component.EnableComponentFactoryCaching";
107:            private static boolean sEnableComponentFactoryCaching = true;
108:
109:            static {
110:                // Find out if context caching is disabled
111:                sEnableComponentFactoryCaching = Boolean
112:                        .valueOf(
113:                                System
114:                                        .getProperty(
115:                                                sEnableComponentFactoryCachingSystemPropertyKey,
116:                                                "true")).booleanValue();
117:                if (sLogger.isDebugEnabled())
118:                    sLogger.debug("Component factory caching is "
119:                            + (sEnableComponentFactoryCaching ? "enabled"
120:                                    : "disabled"));
121:            }
122:
123:            public componentContext(Hashtable pEnvironmentProperties)
124:                    throws NamingException {
125:                mEnvironmentProperties = (pEnvironmentProperties != null) ? (Hashtable) (pEnvironmentProperties
126:                        .clone())
127:                        : null;
128:                // Check if we need to load custom mappings
129:                if (mEnvironmentProperties != null) {
130:                    String lCustomEnvironmentPropertiesFactoryClassName = (String) mEnvironmentProperties
131:                            .get(sCustomEnvironmentPropertiesFactoryEnvKey);
132:                    if (lCustomEnvironmentPropertiesFactoryClassName != null) {
133:                        // Obtain custom environment object factory
134:                        ObjectFactory lCustomEnvironmentPropertiesFactory = (ObjectFactory) sCustomEnvironmentFactoryCache
135:                                .get(lCustomEnvironmentPropertiesFactoryClassName);
136:                        if (lCustomEnvironmentPropertiesFactory == null)
137:                            sCustomEnvironmentFactoryCache
138:                                    .put(
139:                                            lCustomEnvironmentPropertiesFactoryClassName,
140:                                            lCustomEnvironmentPropertiesFactory = loadCustomMappingsFactory(lCustomEnvironmentPropertiesFactoryClassName));
141:
142:                        // Obtain custom environment map from this object factory and combine if necessary
143:                        try {
144:                            Map lCustomEnvironmentMap = (Map) lCustomEnvironmentPropertiesFactory
145:                                    .getObjectInstance(null, new CompositeName(
146:                                            "component"), null,
147:                                            mEnvironmentProperties);
148:                            if (lCustomEnvironmentMap != null) {
149:                                // Iterate through the map. putAll() is not good enough as we want to delete the properties where value is set to null
150:                                for (Iterator lIter = lCustomEnvironmentMap
151:                                        .entrySet().iterator(); lIter.hasNext();) {
152:                                    Map.Entry lEntry = (Map.Entry) lIter.next();
153:                                    String lPropertyName = (String) lEntry
154:                                            .getKey();
155:                                    String lPropertyValue = (String) lEntry
156:                                            .getValue();
157:                                    if (lPropertyValue != null)
158:                                        mEnvironmentProperties.put(
159:                                                lPropertyName, lPropertyValue);
160:                                    else
161:                                        mEnvironmentProperties
162:                                                .remove(lPropertyName);
163:                                }
164:
165:                            }
166:                        } catch (Exception e) {
167:                            sLogger
168:                                    .error(
169:                                            "Unable to use "
170:                                                    + lCustomEnvironmentPropertiesFactoryClassName
171:                                                    + " factory class.", e);
172:                            throw new ConfigurationException(
173:                                    "Unable to use "
174:                                            + lCustomEnvironmentPropertiesFactoryClassName
175:                                            + " factory class. Original exception class: "
176:                                            + e.getClass().getName());
177:                        }
178:                    }
179:                }
180:                rebuildMappingInstructionsTree();
181:            }
182:
183:            private static final String sMappingEnvKeyPrefix = "com.metaboss.naming.component.";
184:            private static final int sMappingEnvKeyPrefixLength = sMappingEnvKeyPrefix
185:                    .length();
186:
187:            // Helper. Reads the environment hashtable, gets all setting with 'com.metaboss.naming.component.' prefix,
188:            // prepare them to be used for mapping and store in the mappling instructions tree
189:            private void rebuildMappingInstructionsTree() {
190:                mMappingInstructions.clear();
191:                if (mEnvironmentProperties != null
192:                        && mEnvironmentProperties.size() > 0) {
193:                    for (Iterator lEnvKeysIterator = mEnvironmentProperties
194:                            .keySet().iterator(); lEnvKeysIterator.hasNext();) {
195:                        String lEnvKey = (String) lEnvKeysIterator.next();
196:                        addEnvToMappingInstructionsTreeIfNecessary(lEnvKey);
197:                    }
198:                }
199:            }
200:
201:            // Helper. Adds a single environment variable to the mapping instructions set if necessary
202:            private void addEnvToMappingInstructionsTreeIfNecessary(
203:                    String pEnvKey) {
204:                if (pEnvKey.startsWith(sMappingEnvKeyPrefix)) {
205:                    // This is our mapping key.
206:                    pEnvKey = pEnvKey.substring(sMappingEnvKeyPrefixLength);
207:                    // Find out if it has wild cards and create the regular expression if it has
208:                    if (pEnvKey.indexOf("*") >= 0) {
209:                        // This is the wildcard mapping for which we should have a reqular expression
210:                        // below is a bit hard to understand, but very simple piece of code which 
211:                        // makes regular expression out of string with wildcards. It replaces
212:                        // replaces '.' with '\.' ; '**' with ([\w\.]*) and '*' with '([\w]*)
213:                        // The complexity here is because the '*' regex itself, so it is not easy to replace
214:                        // '**' and '*' in one go - we need to tokenise and loop through
215:
216:                        // Here is an example of the old code it is simpler, but it did not work because while replacing '*' we were
217:                        // damaging our own prior work
218:                        // String lRegExp = pEnvKey.replaceAll("\\.","\\\\."); // Dots have a special meaning in regexps
219:                        //lRegExp = lRegExp.replaceAll("\\*\\*","([\\\\w\\\\.]*)"); // Two starts consume all characters including dots
220:                        //lRegExp = lRegExp.replaceAll("\\*","([\\\\w]*)"); // One star consumes all characters excluding dots
221:
222:                        String lTemp = pEnvKey.replaceAll("\\.", "\\\\."); // Dots have a special meaning in regexps
223:                        // Tokenise at '**' boundary - replace '*' in every token seprately and than add the replacement for '**' 
224:                        StringBuffer lRegExpBuffer = new StringBuffer();
225:                        String[] lDoubleDotTokens = lTemp.split("\\*\\*");
226:                        for (int i = 0; i < lDoubleDotTokens.length; i++) {
227:                            if (i > 0)
228:                                lRegExpBuffer.append("([\\w\\.]*)"); // Two stars consume all characters including dots
229:                            lRegExpBuffer.append(lDoubleDotTokens[i]
230:                                    .replaceAll("\\*", "([\\\\w]*)")); // One star consumes all characters excluding dots
231:                        }
232:                        if (sLogger.isDebugEnabled())
233:                            sLogger
234:                                    .debug("JNDI Mapping instruction '"
235:                                            + pEnvKey
236:                                            + "' will be matched using regular expression '"
237:                                            + lRegExpBuffer.toString() + "'.");
238:                        mMappingInstructions.put(pEnvKey, Pattern
239:                                .compile(lRegExpBuffer.toString()));
240:                    } else {
241:                        // This is straight mapping which should just use .equals()
242:                        if (sLogger.isDebugEnabled())
243:                            sLogger
244:                                    .debug("JNDI Mapping instruction '"
245:                                            + pEnvKey
246:                                            + "' will be matched as using simple string comparison.");
247:                        mMappingInstructions.put(pEnvKey, null);
248:                    }
249:                }
250:            }
251:
252:            // Helper. This method returns matching env key or null if this location does not match any instructions     
253:            private String getMatchingMappingInstructionKey(
254:                    String pLocationToMatch) {
255:                for (Iterator lMappingInstructionsIterator = mMappingInstructions
256:                        .entrySet().iterator(); lMappingInstructionsIterator
257:                        .hasNext();) {
258:                    Map.Entry lMappingInstruction = (Map.Entry) lMappingInstructionsIterator
259:                            .next();
260:                    Pattern lPattern = (Pattern) lMappingInstruction.getValue();
261:                    if (lPattern != null) {
262:                        // There is a pattern - we wiil need to use reg ex 
263:                        if (lPattern.matcher(pLocationToMatch).matches())
264:                            return sMappingEnvKeyPrefix
265:                                    + (String) lMappingInstruction.getKey();
266:                    } else {
267:                        // No pattern specified - will use simple compare
268:                        String lKey = (String) lMappingInstruction.getKey();
269:                        if (lKey.equals(pLocationToMatch))
270:                            return sMappingEnvKeyPrefix
271:                                    + (String) lMappingInstruction.getKey();
272:                    }
273:                }
274:                return null;
275:            }
276:
277:            // This helper interprets the mapping instructions text like factory(factory(factory(factory())) and
278:            // returns the list of fuly resolved names. The zero element contains the leftmost maping instruction 
279:            // (the one to be used last) and the last element contains the rightmost instruction (the one which should be used first 
280:            private String[] interpretTheMappingInstructionText(
281:                    String pMappingInstructionKey,
282:                    String pMappingInstructionText,
283:                    NameDetails pInterfaceNameDetails,
284:                    StackTraceElement pClientStackElement)
285:                    throws NamingException {
286:                // TODO: Finish implementation of the subset definitions
287:                //  ${component} - full name of the component interface
288:                //  ${componentName} - name of the component interface
289:                //  ${componentPackage[,x[,x]]} - name of the component interface package with optional sections select
290:                //  ${client} - full name of the client class
291:                //  ${clientName} - name of the client class
292:                //  ${clientPackage[,x[,x]]} - name of the client class package with optional sections select
293:                if (pMappingInstructionText.indexOf("${component") >= 0) {
294:                    // Replace ${component... expressions with parts of the component name
295:                    pMappingInstructionText = pMappingInstructionText
296:                            .replaceAll("\\$\\{component\\}",
297:                                    pInterfaceNameDetails.FullName);
298:                    pMappingInstructionText = pMappingInstructionText
299:                            .replaceAll("\\$\\{componentName\\}",
300:                                    pInterfaceNameDetails.InterfaceName);
301:                    pMappingInstructionText = pMappingInstructionText
302:                            .replaceAll("\\$\\{componentPackage\\}",
303:                                    pInterfaceNameDetails.PackageName);
304:                }
305:                if (pMappingInstructionText.indexOf("${client") >= 0
306:                        && pClientStackElement != null) {
307:                    // Replace ${client... expressions with parts of the client name
308:                    String lClientFullName = pClientStackElement.getClassName();
309:                    String lClientPackageName;
310:                    String lClientClassName;
311:                    int lClassNameDotPos = lClientFullName.lastIndexOf(".");
312:                    if (lClassNameDotPos >= 1) {
313:                        // We have got a package name
314:                        lClientPackageName = lClientFullName.substring(0,
315:                                lClassNameDotPos);
316:                        lClientClassName = lClientFullName
317:                                .substring(lClassNameDotPos + 1);
318:                    } else {
319:                        // Very unlikely, but it is still valid to have an interface at the top level
320:                        lClientPackageName = "";
321:                        lClientClassName = lClientFullName;
322:                    }
323:                    pMappingInstructionText = pMappingInstructionText
324:                            .replaceAll("\\$\\{client\\}", lClientFullName);
325:                    pMappingInstructionText = pMappingInstructionText
326:                            .replaceAll("\\$\\{clientName\\}", lClientClassName);
327:                    pMappingInstructionText = pMappingInstructionText
328:                            .replaceAll("\\$\\{clientPackage\\}",
329:                                    lClientPackageName);
330:                }
331:                int lMappingInstructionTextLength = pMappingInstructionText
332:                        .length();
333:                if (lMappingInstructionTextLength == 0)
334:                    throw new ConfigurationException(
335:                            "Component mapping instruction can not be empty. Mapping key : '"
336:                                    + pMappingInstructionKey + "'");
337:                // Look a the closing brackets and calculate how many of them are there
338:                int lNumberOfClosingBrackets = 0;
339:                for (; lNumberOfClosingBrackets < lMappingInstructionTextLength
340:                        && pMappingInstructionText
341:                                .charAt(lMappingInstructionTextLength - 1
342:                                        - lNumberOfClosingBrackets) == ')'; lNumberOfClosingBrackets++)
343:                    ;
344:                if (lNumberOfClosingBrackets == 0)
345:                    return new String[] { pMappingInstructionText }; // Simplest case - no brackets
346:                // We have some brackets, so lets split the text
347:                String[] lMappingInstructionsParts = pMappingInstructionText
348:                        .substring(
349:                                0,
350:                                lMappingInstructionTextLength
351:                                        - lNumberOfClosingBrackets)
352:                        .split("\\(");
353:                if (lMappingInstructionsParts.length != (lNumberOfClosingBrackets + 1))
354:                    throw new ConfigurationException(
355:                            " Illegal component mapping instruction (number of open and closed brackets mismatch) : '"
356:                                    + pMappingInstructionText
357:                                    + "' Mapping key : '"
358:                                    + pMappingInstructionKey + "'");
359:                return lMappingInstructionsParts;
360:            }
361:
362:            // This helper creates factories as per supplied factory names in the given order
363:            private ObjectFactory[] loadObjectFactories(
364:                    String pMappingInstructionKey, String[] pFactoryNames,
365:                    NameDetails pInterfaceNameDetails) throws NamingException {
366:                ObjectFactory[] lObjectFactories = new ObjectFactory[pFactoryNames.length];
367:                for (int i = 0; i < pFactoryNames.length; i++) {
368:                    // This caters for the fact when factory class has been specified explicitly			
369:                    String lPossibleFactoryName = pFactoryNames[i];
370:                    // This caters for the fact when the specified name is the package and we have to build factory name by using an interface name and suffix - 'Factory'			
371:                    String lAnotherPossibleFactoryName = lPossibleFactoryName
372:                            + "." + pInterfaceNameDetails.InterfaceName
373:                            + "Factory";
374:                    // WARNING. THIS IS THE OLD WAY FOR BACKWARDS COMPATIBILITY ONLY
375:                    // This caters for the fact when the specified name is the package and we have to build factory name by using an interface name and suffix - 'FactoryImpl'			
376:                    String lYetAnotherPossibleFactoryName = lPossibleFactoryName
377:                            + "."
378:                            + pInterfaceNameDetails.InterfaceName
379:                            + "FactoryImpl";
380:                    // First try the name as is
381:                    ObjectFactory lFactory = tryLoadingComponentImplementationFactory(lPossibleFactoryName);
382:                    if (lFactory == null) {
383:                        if ((lFactory = tryLoadingComponentImplementationFactory(lAnotherPossibleFactoryName)) == null) {
384:                            if ((lFactory = tryLoadingComponentImplementationFactory(lYetAnotherPossibleFactoryName)) == null)
385:                                throw new NamingException(
386:                                        "Unable to load the factory class. Neither '"
387:                                                + lPossibleFactoryName
388:                                                + "' nor '"
389:                                                + lAnotherPossibleFactoryName
390:                                                + "' nor '"
391:                                                + lYetAnotherPossibleFactoryName
392:                                                + "' class was found. Mapping key : '"
393:                                                + pMappingInstructionKey + "'");
394:                            else
395:                                sLogger
396:                                        .debug("Will use "
397:                                                + lYetAnotherPossibleFactoryName
398:                                                + " as per "
399:                                                + pMappingInstructionKey
400:                                                + " jndi property to create instance of "
401:                                                + pInterfaceNameDetails.FullName
402:                                                + " component.");
403:                        } else
404:                            sLogger.debug("Will use "
405:                                    + lAnotherPossibleFactoryName + " as per "
406:                                    + pMappingInstructionKey
407:                                    + " jndi property to create instance of "
408:                                    + pInterfaceNameDetails.FullName
409:                                    + " component.");
410:                    } else
411:                        sLogger.debug("Will use " + lPossibleFactoryName
412:                                + " as per " + pMappingInstructionKey
413:                                + " jndi property to create instance of "
414:                                + pInterfaceNameDetails.FullName
415:                                + " component.");
416:                    lObjectFactories[i] = lFactory;
417:                }
418:                return lObjectFactories;
419:            }
420:
421:            // Helper. Atempts to load single component mlementation factory class 
422:            private ObjectFactory tryLoadingComponentImplementationFactory(
423:                    String pFactoryClassName) throws NamingException {
424:                // Instantiate the factory
425:                try {
426:                    // Obtain the factory class. Use following strategy to load the class
427:                    // 1. Try jvm's classes via Class.forName(....)
428:                    // 2. Try special componentImplementation loader
429:
430:                    // 2. See if we have loaded the jar for this implementation package already and load class from there if necessary 
431:                    // 3. See if jar with the package name.jar exists, load it in the dynamic jar loader and try step 2 once more
432:                    Class lObjectFactoryClass = null;
433:                    try {
434:                        // Try context classloader to load the factory
435:                        ClassLoader lContextClassLoader = Thread
436:                                .currentThread().getContextClassLoader();
437:                        if (lContextClassLoader != null) {
438:                            try {
439:                                lObjectFactoryClass = lContextClassLoader
440:                                        .loadClass(pFactoryClassName);
441:                            } catch (ClassNotFoundException e1) {
442:                                // Ignore for  now - whole thing will fall through to the next try 
443:                            }
444:                        }
445:                        if (lObjectFactoryClass == null)
446:                            lObjectFactoryClass = Class
447:                                    .forName(pFactoryClassName);
448:                    } catch (ClassNotFoundException e) {
449:                        ClassLoader lClassLoader = componentImplementationLoader
450:                                .getComponentImplementationClassLoader(pFactoryClassName);
451:                        if (lClassLoader != null) {
452:                            try {
453:                                lObjectFactoryClass = lClassLoader
454:                                        .loadClass(pFactoryClassName);
455:                            } catch (ClassNotFoundException e1) {
456:                                // Ignore for  now - whole thing will fall through if no factory was found 
457:                            }
458:                        }
459:                    }
460:                    if (lObjectFactoryClass == null)
461:                        return null;
462:                    return (ObjectFactory) lObjectFactoryClass.newInstance();
463:                } catch (IllegalAccessException e) {
464:                    throw new ConfigurationException(
465:                            "Unable to access constructor for instance of "
466:                                    + pFactoryClassName
467:                                    + " class. Original exception : " + e);
468:                } catch (InstantiationException e) {
469:                    throw new ConfigurationException("Unable to instantiate "
470:                            + pFactoryClassName
471:                            + " class. Original exception : " + e);
472:                }
473:            }
474:
475:            // Helper. Atempts to load single component mlementation factory class 
476:            private ObjectFactory loadCustomMappingsFactory(
477:                    String pFactoryClassName) throws NamingException {
478:                // Instantiate the factory
479:                try {
480:                    // Obtain the factory class. Use following strategy to load the class
481:                    // 1. Try context class loader 
482:                    // 2. System class loader 
483:                    Class lObjectFactoryClass = null;
484:                    try {
485:                        // Try context classloader to load the factory
486:                        ClassLoader lContextClassLoader = Thread
487:                                .currentThread().getContextClassLoader();
488:                        if (lContextClassLoader != null) {
489:                            try {
490:                                lObjectFactoryClass = lContextClassLoader
491:                                        .loadClass(pFactoryClassName);
492:                            } catch (ClassNotFoundException e1) {
493:                                // Ignore for  now - whole thing will fall through to the next try 
494:                            }
495:                        }
496:                        if (lObjectFactoryClass == null)
497:                            lObjectFactoryClass = Class
498:                                    .forName(pFactoryClassName);
499:
500:                        if (lObjectFactoryClass == null)
501:                            throw new ConfigurationException(
502:                                    "Unable to find the " + pFactoryClassName
503:                                            + " factory class.");
504:
505:                        return (ObjectFactory) lObjectFactoryClass
506:                                .newInstance();
507:                    } catch (ClassNotFoundException e) {
508:                        throw new ConfigurationException("Unable to find the "
509:                                + pFactoryClassName
510:                                + " factory class. Original exception : " + e);
511:                    }
512:                } catch (IllegalAccessException e) {
513:                    throw new ConfigurationException(
514:                            "Unable to access constructor for instance of "
515:                                    + pFactoryClassName
516:                                    + " class. Original exception : " + e);
517:                } catch (InstantiationException e) {
518:                    throw new ConfigurationException("Unable to instantiate "
519:                            + pFactoryClassName
520:                            + " class. Original exception : " + e);
521:                }
522:            }
523:
524:            // Helper. Atempts to load an interface class being looked up 
525:            private Class loadInterfaceClassBeingLookedup(
526:                    NameDetails pInterfaceNameDetails) throws NamingException {
527:                // Obtain the class. Use thread's classloader first
528:                Class lInterfaceClass = null;
529:                try {
530:                    // Try context classloader to load the factory
531:                    ClassLoader lContextClassLoader = Thread.currentThread()
532:                            .getContextClassLoader();
533:                    if (lContextClassLoader != null) {
534:                        try {
535:                            lInterfaceClass = lContextClassLoader
536:                                    .loadClass(pInterfaceNameDetails.FullName);
537:                        } catch (ClassNotFoundException e1) {
538:                            // Ignore for  now - whole thing will fall through to the next try 
539:                        }
540:                    }
541:                    if (lInterfaceClass == null)
542:                        lInterfaceClass = Class
543:                                .forName(pInterfaceNameDetails.FullName);
544:                } catch (ClassNotFoundException e) {
545:                    throw new ConfigurationException(
546:                            "Unable to load class for the '"
547:                                    + pInterfaceNameDetails.FullName
548:                                    + "' interface which is being looked up. Original exception : "
549:                                    + e);
550:                }
551:                if (lInterfaceClass == null)
552:                    throw new ConfigurationException(
553:                            "Unable to load class for the '"
554:                                    + pInterfaceNameDetails.FullName
555:                                    + "' interface which is being looked up.");
556:                if (!lInterfaceClass.isInterface())
557:                    throw new OperationNotSupportedException(
558:                            "The component:/ namespace is reserved for the component interfaces. Unable to lookup the '"
559:                                    + pInterfaceNameDetails.FullName
560:                                    + "' class because it is not an interface.");
561:                return lInterfaceClass;
562:            }
563:
564:            private componentContext cloneCtx() throws NamingException {
565:                return new componentContext(mEnvironmentProperties);
566:            }
567:
568:            private class NameDetails {
569:                public String FullName;
570:                public String PackageName;
571:                public String InterfaceName;
572:            }
573:
574:            /**
575:             * Utility method for disassempbling the name onto its components
576:             * @param name The non-null composite or compound name to process.
577:             * @return The structure which contains the various parts of the name 
578:             */
579:            protected NameDetails getMyComponents(Name name)
580:                    throws NamingException {
581:                if (name.size() < 2
582:                        || name.get(0).equals("component:") == false)
583:                    throw new InvalidNameException(
584:                            name.toString()
585:                                    + " is not valid component naming URL. Expected \"component:/<interface full name>[/<reserved for future use>]\"");
586:                NameDetails lNameDetails = new NameDetails();
587:                lNameDetails.FullName = name.get(1);
588:                int lClassNameDotPos = name.get(1).lastIndexOf(".");
589:                if (lClassNameDotPos >= 1) {
590:                    // We have got a package name
591:                    lNameDetails.PackageName = lNameDetails.FullName.substring(
592:                            0, lClassNameDotPos);
593:                    lNameDetails.InterfaceName = lNameDetails.FullName
594:                            .substring(lClassNameDotPos + 1);
595:                } else {
596:                    // Very unlikely, but it is still valid to have an interface at the top level
597:                    lNameDetails.PackageName = "";
598:                    lNameDetails.InterfaceName = lNameDetails.FullName;
599:                }
600:                return lNameDetails;
601:            }
602:
603:            public Object lookup(String name) throws NamingException {
604:                return lookup(new CompositeName(name));
605:            }
606:
607:            public Object lookup(Name name) throws NamingException {
608:                if (name.isEmpty()) {
609:                    // Asking to look up this context itself.  Create and return
610:                    // a new instance with its own independent environment.
611:                    return (cloneCtx());
612:                }
613:
614:                // Extract components that belong to this namespace
615:                NameDetails lNameDetails = getMyComponents(name);
616:                Class lInterfaceClass = loadInterfaceClassBeingLookedup(lNameDetails);
617:
618:                // Try to find object for this originator in internal hashtable
619:                StackTraceElement lStackElement = findCallOriginatorFrame();
620:                String lLookupOriginatorPackage = null;
621:                String lBindingsKey = lNameDetails.FullName;
622:                if (lStackElement != null) {
623:                    String lOriginatorLocation = lStackElement.getClassName()
624:                            + "." + lStackElement.getMethodName();
625:                    sLogger.debug("Received jndi lookup request for "
626:                            + lNameDetails.FullName + " component from within "
627:                            + lOriginatorLocation + "() method body.");
628:                    String lClassName = lStackElement.getClassName();
629:                    int lPackageNameEnd = lClassName.lastIndexOf(".");
630:                    if (lPackageNameEnd > 0) {
631:                        lLookupOriginatorPackage = lClassName.substring(0,
632:                                lPackageNameEnd);
633:                    }
634:                    lBindingsKey += "/" + lOriginatorLocation;
635:                } else
636:                    sLogger.debug("Received jndi lookup request for "
637:                            + lNameDetails.FullName
638:                            + " component from within unrecognised location.");
639:                ObjectFactory[] lObjectFactories;
640:                if ((sEnableComponentFactoryCaching == false)
641:                        || ((lObjectFactories = (ObjectFactory[]) sComponentFactoryCache
642:                                .get(lBindingsKey)) == null)) {
643:                    // Go through the plan - more explicit elements are checked first
644:                    String lMappingInstructionKey = null;
645:                    if (lMappingInstructionKey == null && lStackElement != null)
646:                        lMappingInstructionKey = getMatchingMappingInstructionKey(lNameDetails.FullName
647:                                + "/"
648:                                + lStackElement.getClassName()
649:                                + "."
650:                                + lStackElement.getMethodName());
651:                    if (lMappingInstructionKey == null && lStackElement != null)
652:                        lMappingInstructionKey = getMatchingMappingInstructionKey(lNameDetails.FullName
653:                                + "/" + lStackElement.getClassName());
654:                    if (lMappingInstructionKey == null
655:                            && lLookupOriginatorPackage != null)
656:                        lMappingInstructionKey = getMatchingMappingInstructionKey(lNameDetails.FullName
657:                                + "/" + lLookupOriginatorPackage);
658:                    if (lMappingInstructionKey == null)
659:                        lMappingInstructionKey = getMatchingMappingInstructionKey(lNameDetails.FullName);
660:                    if (lMappingInstructionKey == null && lStackElement != null)
661:                        lMappingInstructionKey = getMatchingMappingInstructionKey(lNameDetails.PackageName
662:                                + "/"
663:                                + lStackElement.getClassName()
664:                                + "."
665:                                + lStackElement.getMethodName());
666:                    if (lMappingInstructionKey == null && lStackElement != null)
667:                        lMappingInstructionKey = getMatchingMappingInstructionKey(lNameDetails.PackageName
668:                                + "/" + lStackElement.getClassName());
669:                    if (lMappingInstructionKey == null
670:                            && lLookupOriginatorPackage != null)
671:                        lMappingInstructionKey = getMatchingMappingInstructionKey(lNameDetails.PackageName
672:                                + "/" + lLookupOriginatorPackage);
673:                    if (lMappingInstructionKey == null)
674:                        lMappingInstructionKey = getMatchingMappingInstructionKey(lNameDetails.PackageName);
675:                    if (lMappingInstructionKey == null) {
676:                        if (sLogger.isDebugEnabled()) {
677:                            // Dump the whole mapping instructions table so it will be easier to debug what is going on
678:                            if (mEnvironmentProperties != null
679:                                    && mEnvironmentProperties.size() > 0) {
680:                                sLogger
681:                                        .debug("-----------------------------------------------------------------");
682:                                sLogger
683:                                        .debug("Following JNDI mapping instructions are taken into consideration when interfaces are mapped to implementations:");
684:                                for (Iterator lEnvEntriesIterator = mEnvironmentProperties
685:                                        .entrySet().iterator(); lEnvEntriesIterator
686:                                        .hasNext();) {
687:                                    Map.Entry lEnvEntry = (Map.Entry) lEnvEntriesIterator
688:                                            .next();
689:                                    String lMappingKey = (String) lEnvEntry
690:                                            .getKey();
691:                                    String lMappingValue = (String) lEnvEntry
692:                                            .getValue();
693:                                    if (lMappingKey
694:                                            .startsWith(sMappingEnvKeyPrefix))
695:                                        sLogger.debug(lMappingKey + "="
696:                                                + lMappingValue);
697:                                }
698:                                sLogger
699:                                        .debug("-----------------------------------------------------------------");
700:                            } else
701:                                sLogger
702:                                        .debug("There are no JNDI mapping instructions found, hence the mapping of interfaces to implementations will fail.");
703:                        }
704:                        throw new NameNotFoundException(
705:                                "Unable to find component implementation mapping for "
706:                                        + name
707:                                        + ".  Use com.metaboss.naming.component.<iface name>|<iface package or full class name name>[/<user package or full class or full method name>] environment setting to define mapping.");
708:                    }
709:                    // Build the factory name
710:                    String lMappingInstructionText = (String) mEnvironmentProperties
711:                            .get(lMappingInstructionKey);
712:                    // The mapping instructions text may consist from one or more factory location expressions nested
713:                    // to any depth as follows
714:                    //    factory expression(factory expression(factory expression())) 
715:                    // each factory expression is essentaally a fully qualified name of the factory class with the few enchancements
716:                    //    - the ${componentPackage} keyword gets replaced with the package name of the interface being looked up
717:                    //    - the name is tried as is to do Class.forName()
718:                    //    - if this is not successful the name is appended with ".<InterfaceName>Factory" and Class.forName() is attempted again
719:                    // Once all factories are obtained, the getObjectInstance() on all of the factories is invoked. With the 
720:                    // deepest factory is invoked first and the first listed factory involved last. The object
721:                    // obtained from the previous factory is passed in to the  getObjectInstance() of the next factory, this allows to
722:                    // build chains of objects.
723:                    // The object returned from  the factory must implement the interface we are looking up or the 
724:                    // generic java.lang.reflect.InvocationHandler interface
725:                    String[] lMappingInstructionParts = interpretTheMappingInstructionText(
726:                            lMappingInstructionKey, lMappingInstructionText,
727:                            lNameDetails, lStackElement);
728:                    lObjectFactories = loadObjectFactories(
729:                            lMappingInstructionKey, lMappingInstructionParts,
730:                            lNameDetails);
731:                    // Store the factory in the cache if necessary
732:                    if (sEnableComponentFactoryCaching)
733:                        sComponentFactoryCache.put(lBindingsKey,
734:                                lObjectFactories);
735:                } else {
736:                    if (lObjectFactories.length > 1)
737:                        sLogger
738:                                .debug("Will use previously cached list of object factories to create instance of "
739:                                        + lNameDetails.FullName + " component.");
740:                    else
741:                        sLogger
742:                                .debug("Will use previously cached object factory to create instance of "
743:                                        + lNameDetails.FullName + " component.");
744:                }
745:
746:                // Now attempt to create the object
747:                Object lImplementation = null;
748:                for (int i = (lObjectFactories.length - 1); i >= 0; i--) {
749:                    ObjectFactory lObjectFactory = lObjectFactories[i];
750:                    try {
751:                        lImplementation = lObjectFactory.getObjectInstance(
752:                                lImplementation, null, null,
753:                                mEnvironmentProperties);
754:                    } catch (Exception e) {
755:                        sLogger.debug("Unable to instantiate "
756:                                + lNameDetails.FullName + " component.", e);
757:                        throw new NamingException(
758:                                "Unable to instantiate "
759:                                        + lNameDetails.FullName
760:                                        + " component. Object factory has had an exception : "
761:                                        + e);
762:                    }
763:                    if (lImplementation == null)
764:                        throw new NamingException(
765:                                "Unable to instantiate "
766:                                        + lNameDetails.FullName
767:                                        + " component. Object factory has returned null.");
768:                    Class lImplementationClass = lImplementation.getClass();
769:                    // Check if this is an instance of the interface	
770:                    if (!lInterfaceClass.isAssignableFrom(lImplementationClass)) {
771:                        // It is not an instance of the interface, it can still be the instance of the InvocationHandler
772:                        if (InvocationHandler.class
773:                                .isAssignableFrom(lImplementationClass)) {
774:                            // This is the generic invocation handler, we need to create the
775:                            // instance of the interface on the fly and return it
776:                            lImplementation = Proxy.newProxyInstance(
777:                                    lInterfaceClass.getClassLoader(),
778:                                    new Class[] { lInterfaceClass },
779:                                    (InvocationHandler) lImplementation);
780:                        }
781:                    }
782:                }
783:                return lImplementation;
784:            }
785:
786:            public void bind(String name, Object obj) throws NamingException {
787:                bind(new CompositeName(name), obj);
788:            }
789:
790:            public void bind(Name name, Object obj) throws NamingException {
791:                throw new OperationNotSupportedException(
792:                        "componentContext does not support binding");
793:            }
794:
795:            public void rebind(String name, Object obj) throws NamingException {
796:                rebind(new CompositeName(name), obj);
797:            }
798:
799:            public void rebind(Name name, Object obj) throws NamingException {
800:                throw new OperationNotSupportedException(
801:                        "componentContext does not support rebinding");
802:            }
803:
804:            public void unbind(String name) throws NamingException {
805:                unbind(new CompositeName(name));
806:            }
807:
808:            public void unbind(Name name) throws NamingException {
809:                throw new OperationNotSupportedException(
810:                        "componentContext does not support unbinding");
811:            }
812:
813:            public void rename(String oldname, String newname)
814:                    throws NamingException {
815:                rename(new CompositeName(oldname), new CompositeName(newname));
816:            }
817:
818:            public void rename(Name oldname, Name newname)
819:                    throws NamingException {
820:                throw new OperationNotSupportedException(
821:                        "componentContext does not support renaming");
822:            }
823:
824:            public NamingEnumeration list(String name) throws NamingException {
825:                return list(new CompositeName(name));
826:            }
827:
828:            public NamingEnumeration list(Name name) throws NamingException {
829:                throw new OperationNotSupportedException(
830:                        "componentContext does not support list");
831:            }
832:
833:            public NamingEnumeration listBindings(String name)
834:                    throws NamingException {
835:                return listBindings(name);
836:            }
837:
838:            public NamingEnumeration listBindings(Name name)
839:                    throws NamingException {
840:                throw new OperationNotSupportedException(
841:                        "componentContext does not support listbindings");
842:            }
843:
844:            public void destroySubcontext(String name) throws NamingException {
845:                destroySubcontext(new CompositeName(name));
846:            }
847:
848:            public void destroySubcontext(Name name) throws NamingException {
849:                throw new OperationNotSupportedException(
850:                        "componentContext does not support subcontexts");
851:            }
852:
853:            public Context createSubcontext(String name) throws NamingException {
854:                return createSubcontext(new CompositeName(name));
855:            }
856:
857:            public Context createSubcontext(Name name) throws NamingException {
858:                throw new OperationNotSupportedException(
859:                        "componentContext does not support subcontexts");
860:            }
861:
862:            public Object lookupLink(String name) throws NamingException {
863:                return lookupLink(new CompositeName(name));
864:            }
865:
866:            public Object lookupLink(Name name) throws NamingException {
867:                // This flat context does not treat links specially
868:                return lookup(name);
869:            }
870:
871:            public NameParser getNameParser(String name) throws NamingException {
872:                return getNameParser(new CompositeName(name));
873:            }
874:
875:            public NameParser getNameParser(Name name) throws NamingException {
876:                // Do lookup to verify name exists
877:                Object obj = lookup(name);
878:                if (obj instanceof  Context) {
879:                    ((Context) obj).close();
880:                }
881:                return myParser;
882:            }
883:
884:            public String composeName(String name, String prefix)
885:                    throws NamingException {
886:                Name result = composeName(new CompositeName(name),
887:                        new CompositeName(prefix));
888:                return result.toString();
889:            }
890:
891:            public Name composeName(Name name, Name prefix)
892:                    throws NamingException {
893:                Name result = (Name) (prefix.clone());
894:                result.addAll(name);
895:                return result;
896:            }
897:
898:            public Object addToEnvironment(String propName, Object propVal)
899:                    throws NamingException {
900:                if (mEnvironmentProperties == null) {
901:                    mEnvironmentProperties = new Hashtable(5, 0.75f);
902:                }
903:                // This property is posibly a mapping instruction - add it to the instructions set
904:                addEnvToMappingInstructionsTreeIfNecessary(propName);
905:                return mEnvironmentProperties.put(propName, propVal);
906:            }
907:
908:            public Object removeFromEnvironment(String propName)
909:                    throws NamingException {
910:                if (mEnvironmentProperties == null)
911:                    return null;
912:                // This property is posibly a mapping instruction - remove it from the instructions set
913:                mMappingInstructions.remove(propName);
914:                return mEnvironmentProperties.remove(propName);
915:            }
916:
917:            public Hashtable getEnvironment() throws NamingException {
918:                if (mEnvironmentProperties == null) {
919:                    // Must return non-null
920:                    return new Hashtable(3, 0.75f);
921:                } else {
922:                    return (Hashtable) mEnvironmentProperties.clone();
923:                }
924:            }
925:
926:            public String getNameInNamespace() throws NamingException {
927:                return "";
928:            }
929:
930:            public void close() throws NamingException {
931:            }
932:
933:            // Full names of the classes which should be ignored
934:            private static String[] sTransparentClassNames = new String[] { "com.metaboss.naming.component.componentContext", };
935:
936:            // Prefixes of the packages which should be ignored
937:            private static String[] sTransparentPackagePrefixes = new String[] { "javax.naming." };
938:
939:            // Helper. Returns the stack trace element describing the 
940:            // piece of code which has made a call. Returns null if owner can not be determined
941:            private StackTraceElement findCallOriginatorFrame() {
942:                // Find out the package, which owns this call
943:                Throwable lThrowable = new Throwable();
944:                StackTraceElement[] lStackFrameDetails = lThrowable
945:                        .getStackTrace();
946:                for (int lStackFrameIndex = 0; lStackFrameIndex < lStackFrameDetails.length; lStackFrameIndex++) {
947:                    StackTraceElement lElement = lStackFrameDetails[lStackFrameIndex];
948:                    // Check if this stack trace element is transparent - which meant that it is not participating in the mappings
949:                    String lClassName = lElement.getClassName();
950:                    boolean lIsTransparent = false;
951:                    for (int i = 0; i < sTransparentClassNames.length; i++) {
952:                        if ((lIsTransparent = lClassName
953:                                .equals(sTransparentClassNames[i])) == true)
954:                            break; // Found match with the transparent class
955:                    }
956:                    if (lIsTransparent)
957:                        continue; // Found transparent element
958:                    for (int i = 0; i < sTransparentPackagePrefixes.length; i++) {
959:                        if ((lIsTransparent = lClassName
960:                                .startsWith(sTransparentPackagePrefixes[i])) == true)
961:                            break; // Found match with the transparent package
962:                    }
963:                    if (lIsTransparent)
964:                        continue; // Found transparent element
965:                    // If the control has fallen to here it means that we have hit first not transaparent element 
966:                    return lElement; // Found first non transparent element
967:                }
968:                return null;
969:            }
970:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.