Source Code Cross Referenced for I18NStandardMBean.java in  » JMX » mx4j » mx4j » tools » i18n » 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 » JMX » mx4j » mx4j.tools.i18n 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (C) The MX4J Contributors.
003:         * All rights reserved.
004:         *
005:         * This software is distributed under the terms of the MX4J License version 1.0.
006:         * See the terms of the MX4J License in the documentation provided with this software.
007:         */
008:
009:        package mx4j.tools.i18n;
010:
011:        import java.util.Collection;
012:        import java.util.Collections;
013:        import java.util.Enumeration;
014:        import java.util.HashMap;
015:        import java.util.HashSet;
016:        import java.util.Locale;
017:        import java.util.Map;
018:        import java.util.MissingResourceException;
019:        import java.util.ResourceBundle;
020:        import java.util.Set;
021:        import java.util.StringTokenizer;
022:        import javax.management.MBeanAttributeInfo;
023:        import javax.management.MBeanConstructorInfo;
024:        import javax.management.MBeanInfo;
025:        import javax.management.MBeanOperationInfo;
026:        import javax.management.MBeanParameterInfo;
027:        import javax.management.NotCompliantMBeanException;
028:        import javax.management.StandardMBean;
029:
030:        /**
031:         * An extension of StandardMBean to support internationalization. <p>
032:         * <p/>
033:         * The I18N information is taken from a property bundle named MyImplMBeanResources
034:         * where "MyImpl" is the fully qualified class implementing the MBean. <p>
035:         * These bundles are nested following the class hierachy of the <b>implementation</b>
036:         * class. This means that a superclass of the real implementing class can
037:         * define the resource bundle for the common attributes and operations.
038:         * <p/>
039:         * The resource bundle naming rules defined by {@link java.util.ResourceBundle}
040:         * are used; in particular : <UL>
041:         * <LI>If a <b>class</b> called MyPackage.MyImplMBeanResources_localInfo exists it is used (programmatic methd)
042:         * <LI>Otherwise the <b>file</b> called MyPackage.MyImplMBeanResources_localInfo.properties is used.
043:         * </UL>
044:         * <p/>
045:         * localInfo consists of one or more sections of "language_country_variant" (eg en_GB or fr_FR).
046:         * <p/>
047:         * The locale to be used is determined by one of the following mechanisms (in this order) <UL>
048:         * <LI>The locale object explicitly passed to the constructor (if not null)
049:         * <LI>The static method {@link #setDefaultLocale}
050:         * <LI>The system property "mx4j.descriptionLocale"
051:         * <LI>The current system default locale
052:         * </UL>
053:         * <p/>
054:         * The bundle should contain keys as described below :
055:         * <H2>Global bean description</H2>
056:         * The global bean description is given by the single key "descr": <pre>
057:         * descr=The MBean Description
058:         * </pre>
059:         * <p/>
060:         * <H2>Attributes</H2>
061:         * Attribute desciptions are given by keys of form "attr.Name" where Name
062:         * is the attribute name (the method name minus the get/set prefix) : <pre>
063:         * attr.Counter=The counter
064:         * </pre>
065:         * <p/>
066:         * <H2>Constructors</H2>
067:         * <H3>Non ambiguous case</H3>
068:         * All constructors having a different <b>number</b> of arguments may be described in this way: <pre>
069:         * cons.N=desciption of constructor N
070:         * cons.N.param.1=Description of first parameter of constructor N
071:         * cons.N.paramName.1=paramName1
072:         * cons.N.param.2=Description of first parameter of constructor N
073:         * cons.N.paramName.2=paramName2
074:         * </pre>
075:         * Where N is a sequential number starting at one.
076:         * <p/>
077:         * <H3>Ambiguous case</H3>
078:         * Where several constructors exist with the same number of arguments an explicit
079:         * signature must be given. The signature is a comma separated list of class descriptions
080:         * (as returned by {@link java.lang.Class#getName} and has the key cons.N.sig : <pre>
081:         * cons.N.sig=int,java.lang.Object
082:         * cons.N.param.1=The int parameter
083:         * cons.N.param.2=The Object parameter
084:         * </pre>
085:         * <p/>
086:         * <H2>Operations</H2>
087:         * <H3>No overloading</H3>
088:         * When no overloaded versions of an operation exist (same method name but different parameters)
089:         * the simplest case shown below can be used : <pre>
090:         * op.<I>operationName</I>=The description
091:         * op.<I>operationName</I>.param.1=The first parameter
092:         * op.<I>operationName</I>.paramName.1=param1
093:         * </pre>
094:         * <p/>
095:         * <H3>Non ambiguous overloading case</H3>
096:         * When operation overloading is used but the overloaded versions differ in the number
097:         * of parameters the format below can be used : <pre>
098:         * op.<I>operationName</I>.1=The first version of operationName
099:         * op.<I>operationName</I>.1.param.1=parameter for first version
100:         * op.<I>operationName</I>.1.paramName.1=param1
101:         * op.<I>operationName</I>.2=The second version of operationName
102:         * op.<I>operationName</I>.2.paramName.1=param1
103:         * op.<I>operationName</I>.2.param.1=first parameter for second version
104:         * op.<I>operationName</I>.2.param.2=second parameter for second version
105:         * op.<I>operationName</I>.2.paramName.2=param2
106:         * </pre>
107:         * <p/>
108:         * <H3>Ambiguous overloading case</H3>
109:         * When operations with the same name have the same number of arguments an explicit
110:         * signature must be used : <pre>
111:         * op.<I>operationName</I>.1.sig=int
112:         * op.<I>operationName</I>.1=The first version of operationName (takes int)
113:         * op.<I>operationName</I>.1.param.1=parameter for first version
114:         * op.<I>operationName</I>.1.paramName.1=param1
115:         * op.<I>operationName</I>.2.sig=java.lang.Object
116:         * op.<I>operationName</I>.2=The second version of operationName (take Object)
117:         * op.<I>operationName</I>.2.paramName.1=param1
118:         * op.<I>operationName</I>.2.param.1=first parameter for second version
119:         * </pre>
120:         * <p/>
121:         * <H2>Restrictions</H2>
122:         * Parameter names must only contain characters allowed in a Java identifier
123:         * (in particular spaces are <b>not</b> allowed). This is required by the JMX specifications.
124:         * No such restrictions exist for the other descriptions.
125:         * <p/>
126:         * <H2>Behaviour with missing data</H2>
127:         * If no resource bunde exists for the MBean a java.util.MissingResourceException
128:         * will be thrown by the constructor. <p>
129:         * <p/>
130:         * If the resouce bundle is found but the bean description, constructor description or
131:         * parameter name is missing the String "??(key)" will be returned instead (eg
132:         * "??(op.myOperation)". <p>
133:         * <p/>
134:         * If a paramName key is missing (for constructor or operation) the version normally
135:         * given by StandardMBean is used (generally "pN").<p>
136:         * <p/>
137:         * If a non ambiguous description cannot be determined the fixed (non translatable)
138:         * descriptions "ambiguous constructor", "parameter for ambiguous constructor",
139:         * "ambiguous operation", "parameter for ambiguous operation" are returned.
140:         */
141:        public class I18NStandardMBean extends StandardMBean {
142:            private static final String IDPROP_DEFAULT_LOCALE = "mx4j.descriptionLocale";
143:            private static final String RESOURCE_SUFFIX = "MBeanResources";
144:            private static final String KEY_DESCR = "descr";
145:            private static final String KEY_CONS = "cons";
146:            private static final String KEY_ATTR = "attr";
147:            private static final String KEY_OP = "op";
148:            private static final String KEY_PARAM = "param";
149:            private static final String KEY_PARAM_NAME = "paramName";
150:            private static final String KEY_SIG = "sig";
151:
152:            private static Locale g_defaultLocale = null;
153:
154:            private NestedResourceBundle m_bundle;
155:            private Map m_mapConstructorSignatureToResourceIndex;
156:            private Map m_mapConstructorParamCountToResourceIndex;
157:            private Map m_mapConstructorToResourceIndex = new HashMap();
158:            private Map m_mapOperationNameToSignatures = new HashMap();
159:            private Map m_mapOperationNameToParamCounts = new HashMap();
160:            private Set m_setAmbiguousConstructors = new HashSet();
161:            private Set m_setAmbiguousOperations = new HashSet();
162:
163:            /**
164:             * Makes an I18NStandardMBean for the default locale with a separate implementation class.
165:             *
166:             * @see javax.management.StandardMBean#StandardMBean(java.lang.Object, java.lang.Class)
167:             */
168:            public I18NStandardMBean(Object implementation, Class mbeanInterface)
169:                    throws NotCompliantMBeanException {
170:                this (implementation, mbeanInterface, null);
171:            }
172:
173:            /**
174:             * Makes an I18NStandardMBean for the given locale with a separate implementation class.
175:             *
176:             * @see javax.management.StandardMBean#StandardMBean(java.lang.Object, java.lang.Class)
177:             */
178:            public I18NStandardMBean(Object implementation,
179:                    Class mbeanInterface, Locale locale)
180:                    throws NotCompliantMBeanException {
181:                super (implementation, mbeanInterface);
182:                setupBundle(implementation, locale);
183:            }
184:
185:            /**
186:             * Makes a I18NStandardMBean for the default locale implemented by a subclass.
187:             *
188:             * @see javax.management.StandardMBean#StandardMBean(java.lang.Class)
189:             */
190:            protected I18NStandardMBean(Class mbeanInterface)
191:                    throws NotCompliantMBeanException {
192:                super (mbeanInterface);
193:                setupBundle(this , null);
194:            }
195:
196:            /**
197:             * Makes a I18NStandardMBean for the given locale implemented by a subclass.
198:             *
199:             * @see javax.management.StandardMBean#StandardMBean(java.lang.Class)
200:             */
201:            protected I18NStandardMBean(Class mbeanInterface, Locale locale)
202:                    throws NotCompliantMBeanException {
203:                super (mbeanInterface);
204:                setupBundle(this , locale);
205:            }
206:
207:            private void setupBundle(Object implementation, Locale locale) {
208:                // calculate the effective locale:
209:                if (locale == null) {
210:                    locale = g_defaultLocale;
211:                }
212:                if (locale == null) {
213:                    locale = getLocaleFromSystemProperties();
214:                }
215:
216:                // create bundle
217:                NestedResourceBundle cur = null;
218:                MissingResourceException ex = null;
219:                for (Class c = implementation.getClass(); c != null; c = c
220:                        .getSuperclass()) {
221:                    String bundleName = c.getName() + RESOURCE_SUFFIX;
222:                    try {
223:                        ResourceBundle b = ResourceBundle.getBundle(bundleName,
224:                                locale);
225:                        NestedResourceBundle nb = new NestedResourceBundle(b);
226:                        if (cur == null) {
227:                            m_bundle = nb;
228:                        } else {
229:                            cur.setParent(nb);
230:                        }
231:                        cur = nb;
232:                    } catch (MissingResourceException e) {
233:                        if (m_bundle == null)
234:                            ex = e; // save first exception
235:                    }
236:                }
237:                if (m_bundle == null) {
238:                    ex.fillInStackTrace();
239:                    throw ex;
240:                }
241:            }
242:
243:            // Obtain the default locale from system properties
244:            private Locale getLocaleFromSystemProperties() {
245:                Locale locale = Locale.getDefault();
246:                String stdLocale = System.getProperty(IDPROP_DEFAULT_LOCALE);
247:                if (stdLocale != null && stdLocale.length() > 0) {
248:                    StringTokenizer st = new StringTokenizer(stdLocale, "_");
249:                    switch (st.countTokens()) {
250:                    case 2:
251:                        locale = new Locale(st.nextToken(), st.nextToken());
252:                        break;
253:                    case 3:
254:                        locale = new Locale(st.nextToken(), st.nextToken(), st
255:                                .nextToken());
256:                        break;
257:                    default:
258:                        throw new IllegalArgumentException("Invalid locale in "
259:                                + IDPROP_DEFAULT_LOCALE + ":" + stdLocale);
260:                    }
261:                }
262:                return locale;
263:            }
264:
265:            /**
266:             * Set the locale which will be used for future I18NStandardMBeans. <p>
267:             * The locale specified can be overridden on a per class basis via the
268:             * constructors but overrides other means of setting the Locale (system properties). <p>
269:             * <p/>
270:             * Changing the locale has no effect on already constructed MBeans.
271:             *
272:             * @param locale the Locale for future MBeans
273:             */
274:            public static void setDefaultLocale(Locale locale) {
275:                g_defaultLocale = locale;
276:            }
277:
278:            /**
279:             * Initialise internal data structures. <p>
280:             * This method is always called first during getMBeanInfo processing.
281:             * We use this to avoid keeping all our internal Maps in memory too long.
282:             *
283:             * @see javax.management.StandardMBean#getCachedMBeanInfo
284:             */
285:            protected MBeanInfo getCachedMBeanInfo() {
286:                MBeanInfo info = super .getCachedMBeanInfo();
287:                if (info == null) {
288:                    // only setup if we are going to be called!
289:                    m_mapConstructorToResourceIndex = new HashMap();
290:                    m_mapOperationNameToSignatures = new HashMap();
291:                    m_mapOperationNameToParamCounts = new HashMap();
292:                    m_setAmbiguousConstructors = new HashSet();
293:                    m_setAmbiguousOperations = new HashSet();
294:                    m_mapConstructorSignatureToResourceIndex = getSignatureMap(KEY_CONS);
295:                    m_mapConstructorParamCountToResourceIndex = getParamCountMap(KEY_CONS);
296:                }
297:                return info;
298:            }
299:
300:            /**
301:             * Once the MBeanInfo has been obtained discard our caches.
302:             *
303:             * @see javax.management.StandardMBean#cacheMBeanInfo(javax.management.MBeanInfo)
304:             */
305:            protected void cacheMBeanInfo(MBeanInfo info) {
306:                super .cacheMBeanInfo(info);
307:                m_mapConstructorToResourceIndex = null;
308:                m_mapOperationNameToSignatures = null;
309:                m_mapOperationNameToParamCounts = null;
310:                m_setAmbiguousConstructors = null;
311:                m_setAmbiguousOperations = null;
312:                m_mapConstructorSignatureToResourceIndex = null;
313:                m_mapConstructorParamCountToResourceIndex = null;
314:            }
315:
316:            /*
317:             * Initialises internal structures based on available constructors. <p>
318:             * Return value is supplied by superclass.<p>
319:             *
320:             * For all the constructors :<ul>
321:             * <li>Create a map of MBeanConstructorInfo=>resource bundle index for explicit signatures
322:             * <li>Create list of "ambiguous" constructors based on number of arguments.
323:             * </ul>
324:             * Note we assume that this metthod will be called BEFORE the constructor related
325:             * getDesciption methods. The spec does not say anything about this.
326:             */
327:            protected MBeanConstructorInfo[] getConstructors(
328:                    MBeanConstructorInfo[] cstrs, Object impl) {
329:                Map argCountToCstr = new HashMap();
330:                for (int i = 0; i < cstrs.length; i++) {
331:                    MBeanConstructorInfo ci = cstrs[i];
332:                    MBeanParameterInfo[] params = ci.getSignature();
333:
334:                    // update potentially ambiguous constructors (same number of arguments)
335:                    Integer count = new Integer(params.length);
336:                    Object first = argCountToCstr.get(count);
337:                    if (first != null) {
338:                        // already have a constructor with this number of args
339:                        m_setAmbiguousConstructors.add(first); // Set so no duplication
340:                        m_setAmbiguousConstructors.add(ci);
341:                        // this one is ambiguous too
342:                    } else {
343:                        argCountToCstr.put(count, ci);
344:                    }
345:
346:                    // update signature=>resource index mapping (if explicit signature provided)
347:                    String sig = makeSignatureString(params);
348:                    Integer idx = (Integer) m_mapConstructorSignatureToResourceIndex
349:                            .get(sig);
350:                    if (idx != null) {
351:                        m_mapConstructorToResourceIndex.put(ci, idx);
352:                    }
353:                }
354:                return super .getConstructors(cstrs, impl);
355:            }
356:
357:            /**
358:             * Obtain global description for MBean. <p>
359:             * Taken from "descr" key in resource bundle. <p>
360:             * <p/>
361:             * Also performs internal initialisations requiring the MBeanInfo obtained
362:             * by introspection. Therefore the superclass must call this method BEFORE
363:             * the other hooks.
364:             *
365:             * @see javax.management.StandardMBean#getDescription(javax.management.MBeanInfo)
366:             */
367:            protected String getDescription(MBeanInfo info) {
368:                findAmbiguousOperations(info); // assume called first
369:                return getValueFromBundle(KEY_DESCR);
370:            }
371:
372:            /**
373:             * Obtain the constructor description. <p>
374:             * Taken from "cons.N" key in resource bundle. <p>
375:             * <p/>
376:             * Maybe "ambiguous constructor" if correct index cannot be determined by
377:             * an explicit signature or parameter counts.
378:             *
379:             * @see javax.management.StandardMBean#getDescription(javax.management.MBeanConstructorInfo)
380:             */
381:            protected String getDescription(MBeanConstructorInfo cstr) {
382:                int idx = getConstructorIndex(cstr);
383:                if (idx < 1) {
384:                    return "ambiguous constructor";
385:                }
386:                return getValueFromBundle(KEY_CONS + "." + idx);
387:            }
388:
389:            /**
390:             * Obtain the constructor parameter description. <p>
391:             * Taken from "cons.N.param.<I>seq</I>" key in resource bundle. <p>
392:             * <p/>
393:             * Maybe "parameter for ambiguous constructor" if correct index cannot be determined by
394:             * an explicit signature or parameter counts.
395:             *
396:             * @see javax.management.StandardMBean#getDescription(javax.management.MBeanConstructorInfo, javax.management.MBeanParameterInfo, int)
397:             */
398:            protected String getDescription(MBeanConstructorInfo cstr,
399:                    MBeanParameterInfo param, int seq) {
400:                int idx = getConstructorIndex(cstr);
401:                if (idx < 1) {
402:                    return "parameter for ambiguous constructor";
403:                }
404:                return getValueFromBundle(KEY_CONS + "." + idx + ".param."
405:                        + (seq + 1));
406:            }
407:
408:            /**
409:             * Obtain constructor parameter name. <p>
410:             * Taken from "cons.N.paramName.<I>seq</I>" key in resource bundle. <p>
411:             * <p/>
412:             * If this key does not exist or if the correct index N cannot be determined by
413:             * an explicit signature or parameter counts the superclass method is called.
414:             *
415:             * @see javax.management.StandardMBean#getParameterName(javax.management.MBeanConstructorInfo, javax.management.MBeanParameterInfo, int)
416:             */
417:            protected String getParameterName(MBeanConstructorInfo cstr,
418:                    MBeanParameterInfo param, int seq) {
419:                int idx = getConstructorIndex(cstr);
420:                String name = null;
421:                if (idx >= 1) {
422:                    name = getValueOrNullFromBundle(KEY_CONS + "." + idx
423:                            + ".paramName." + (seq + 1));
424:                }
425:                if (name == null) {
426:                    name = super .getParameterName(cstr, param, seq);
427:                }
428:                return name;
429:            }
430:
431:            /**
432:             * Obtain the attribute description. <p>
433:             * Taken from the "attr.<I>attributeName</I>" key in resource bundle.
434:             *
435:             * @see javax.management.StandardMBean#getDescription(javax.management.MBeanAttributeInfo)
436:             */
437:            protected String getDescription(MBeanAttributeInfo attr) {
438:                return getValueFromBundle(KEY_ATTR + "." + attr.getName());
439:            }
440:
441:            /**
442:             * Obtain the operation description. <p>
443:             * Taken from the "op.<I>operationName</I>.N" or the "op.<I>operationName</I>"
444:             * key in the resource bundle. <p>
445:             * May be "ambiguous operation" if the correct key cannot be determined by
446:             * signature or parameter counts.
447:             *
448:             * @see javax.management.StandardMBean#getDescription(javax.management.MBeanOperationInfo)
449:             */
450:            protected String getDescription(MBeanOperationInfo op) {
451:                try {
452:                    return getValueFromBundle(getOperationKey(op));
453:                } catch (IllegalStateException e) {
454:                    return e.getMessage();
455:                }
456:            }
457:
458:            /**
459:             * Obtain the operation parameter description. <p>
460:             * Taken from the "op.<I>operationName</I>.N.param.M" or the "op.<I>operationName</I>.param"
461:             * key in the resource bundle. <p>
462:             * May be "parameter for ambiguous operation" if the correct key cannot be determined by
463:             * signature or parameter counts.
464:             *
465:             * @see javax.management.StandardMBean#getDescription(javax.management.MBeanOperationInfo, javax.management.MBeanParameterInfo, int)
466:             */
467:            protected String getDescription(MBeanOperationInfo op,
468:                    MBeanParameterInfo param, int seq) {
469:                try {
470:                    return getValueFromBundle(getOperationKey(op) + "."
471:                            + KEY_PARAM + "." + (seq + 1));
472:                } catch (IllegalStateException e) {
473:                    return "parameter for " + e.getMessage();
474:                }
475:            }
476:
477:            /**
478:             * Obtain operation parameter name. <p>
479:             * Taken from the "op.<I>operationName</I>.N.paramName.M" or the "op.<I>operationName.paramName</I>.M"
480:             * key in the resource bundle. <p>
481:             * <p/>
482:             * If this key does not exist or if the correct index N cannot be determined by
483:             * an explicit signature or parameter counts the superclass method is called.
484:             *
485:             * @see javax.management.StandardMBean#getParameterName(javax.management.MBeanOperationInfo, javax.management.MBeanParameterInfo, int)
486:             */
487:            protected String getParameterName(MBeanOperationInfo op,
488:                    MBeanParameterInfo param, int seq) {
489:                String name = null;
490:                try {
491:                    name = getValueOrNullFromBundle(getOperationKey(op) + "."
492:                            + KEY_PARAM_NAME + "." + (seq + 1));
493:                } catch (IllegalStateException e) {
494:                }
495:
496:                if (name == null) {
497:                    name = super .getParameterName(op, param, seq);
498:                }
499:                return name;
500:            }
501:
502:            /*
503:             * Obtain 1 based index of constructor in resource bundle.
504:             * First look for a signature match (.sig in bundle)
505:             * If not found and constuctor is potentially ambiguous (another constructor with the same number of params exists) return -1
506:             * If not found try a parameter number match.
507:             * If parameter number match is ambiguous return -1
508:             * If no match found return 0
509:             */
510:            private int getConstructorIndex(MBeanConstructorInfo cons) {
511:                Integer idx = (Integer) m_mapConstructorToResourceIndex
512:                        .get(cons);
513:                if (idx != null) {
514:                    return idx.intValue();
515:                }
516:
517:                // do multiple constuctors with the same arg count exist?
518:                if (m_setAmbiguousConstructors.contains(cons))
519:                    return -1;
520:
521:                // no signature match - try using parameter count
522:                int nbParams = cons.getSignature().length;
523:                idx = (Integer) m_mapConstructorParamCountToResourceIndex
524:                        .get(new Integer(nbParams));
525:                if (idx != null) {
526:                    return idx.intValue();
527:                }
528:                return 0;
529:            }
530:
531:            /*
532:             * Obtain the root bundle key for the given operation.
533:             * If a matching signature entry exists for this operation
534:             * is of form : "op.operationName.N"
535:             * otherwise it is of form "op.operationName"
536:             * where N is the index of the matching signature.
537:             * If the operation is ambiguous throw an IllegalStateException.
538:             */
539:            private String getOperationKey(MBeanOperationInfo op) {
540:                String operationName = op.getName();
541:
542:                // lookup by signature
543:                Map sigMap = getOperationSignatureMap(operationName);
544:                MBeanParameterInfo[] params = op.getSignature();
545:                String sig = makeSignatureString(params);
546:                Integer idx = (Integer) sigMap.get(sig);
547:
548:                StringBuffer sbRet = new StringBuffer(KEY_OP + ".");
549:                sbRet.append(operationName);
550:
551:                if (idx == null) {
552:                    if (m_setAmbiguousOperations.contains(op)) {
553:                        throw new IllegalStateException("ambiguous operation");
554:                    }
555:
556:                    // no direct signature mapping, try matching by parameter counts
557:                    Map countMap = getOperationParamCountMap(operationName);
558:                    idx = (Integer) countMap.get(new Integer(params.length));
559:                    if (idx != null && idx.intValue() < 1) {
560:                        throw new IllegalStateException("ambiguous operation");
561:                    }
562:                }
563:
564:                if (idx != null) {
565:                    sbRet.append(".");
566:                    sbRet.append(idx);
567:                }
568:                return sbRet.toString();
569:            }
570:
571:            /*
572:             * Initialise the set m_setAmbiguousOperations with those operations
573:             * that have the same name and same number of parameters.
574:             */
575:            private void findAmbiguousOperations(MBeanInfo info) {
576:                // obtain potentially ambiguous operations (same name, same number parameters)
577:                MBeanOperationInfo[] ops = info.getOperations();
578:                Map mapNameToArgCountMap = new HashMap();
579:                for (int i = 0; i < ops.length; i++) {
580:                    MBeanOperationInfo op = ops[i];
581:                    String name = op.getName();
582:                    Map argCountToOp = (Map) mapNameToArgCountMap.get(name);
583:                    if (argCountToOp == null) {
584:                        argCountToOp = new HashMap();
585:                        mapNameToArgCountMap.put(name, argCountToOp);
586:                    }
587:
588:                    Integer count = new Integer(op.getSignature().length);
589:                    Object first = argCountToOp.get(count);
590:                    if (first != null) {
591:                        // already have an operation with this number of args
592:                        m_setAmbiguousOperations.add(first); // Set so no duplication
593:                        m_setAmbiguousOperations.add(op); // this one is ambiguous too
594:                    } else {
595:                        argCountToOp.put(count, op);
596:                    }
597:                }
598:            }
599:
600:            /*
601:             * Obtain Map of operation signature=>resource bundle index.
602:             * Use lazy instantiation and caching.
603:             * The entries in resource bundle have form :
604:             * op.operationName.1.sig=xxx
605:             * op.operationName.2.sig=yyy
606:             *
607:             * The above example would give xxx=>1, yyy=>2
608:             */
609:            private Map getOperationSignatureMap(String operationName) {
610:                // look up in cache
611:                Map m = (Map) m_mapOperationNameToSignatures.get(operationName);
612:                if (m != null) {
613:                    return m;
614:                }
615:
616:                // construct map
617:                m = getSignatureMap(KEY_OP + "." + operationName);
618:                m_mapOperationNameToSignatures.put(operationName, m); // cache
619:                return m;
620:            }
621:
622:            /*
623:             * Obtain Map of parameter count =>resource bundle index for the given operation
624:             * Use lazy instantiation and caching.
625:             */
626:            private Map getOperationParamCountMap(String operationName) {
627:                // look up in cache
628:                Map m = (Map) m_mapOperationNameToParamCounts
629:                        .get(operationName);
630:                if (m != null) {
631:                    return m;
632:                }
633:
634:                // construct map
635:                m = getParamCountMap(KEY_OP + "." + operationName);
636:                m_mapOperationNameToParamCounts.put(operationName, m); // cache
637:                return m;
638:            }
639:
640:            /*
641:             * Obtain a Map of parameter count => Integer index from resource bundle
642:             * The entries in resource bundle have form :
643:             * prefix.1.param.1=xxx
644:             * prefix.1.param.2=yyy
645:             * prefix.2.param.1=zzz
646:             *
647:             * The above example would give 2=>1, 1=>2 (index1 has 2 parameter, index 2 has 1 parameter)
648:             * If there are duplicate parameter counts map to -1
649:             */
650:            private Map getParamCountMap(String prefix) {
651:                int nb;
652:                Map m = new HashMap();
653:
654:                for (int i = 1;; i++) {
655:                    String key = prefix + "." + i;
656:                    String sig = getValueOrNullFromBundle(key);
657:                    if (sig == null) {
658:                        break;
659:                    }
660:                    nb = 0;
661:                    for (int j = 1;; j++) {
662:                        key = prefix + "." + i + "." + KEY_PARAM + "." + j;
663:                        if (getValueOrNullFromBundle(key) != null) {
664:                            nb = j;
665:                        } else {
666:                            break;
667:                        }
668:                    }
669:                    Integer nbObj = new Integer(nb);
670:                    int idx = m.containsKey(nbObj) ? -1 : i;
671:                    m.put(nbObj, new Integer(idx));
672:                }
673:                return m;
674:            }
675:
676:            /*
677:             * Create a map of signature string=>Integer index from resource bundle.
678:             * The entries in resource bundle have form :
679:             * prefix.1.sig=signature1
680:             *  prefix.2.sig=signature2
681:             * ..
682:             * The list stops at the first non existant index.
683:             * The signatures are comma separated types of the form returned by
684:             * Class.getName(), eg: java.lang.Object,Z,[Z;
685:             */
686:            private Map getSignatureMap(String prefix) {
687:                Map m = new HashMap();
688:                for (int i = 1;; i++) {
689:                    String key = prefix + "." + i + "." + KEY_SIG;
690:                    String sig = getValueOrNullFromBundle(key);
691:                    if (sig == null) {
692:                        break;
693:                    }
694:                    m.put(sig, new Integer(i));
695:                }
696:                return m;
697:            }
698:
699:            // create a comma separated list of signatures.
700:            private String makeSignatureString(MBeanParameterInfo[] params) {
701:                StringBuffer sb = new StringBuffer();
702:                for (int i = 0; i < params.length; i++) {
703:                    if (i > 0) {
704:                        sb.append(",");
705:                    }
706:                    sb.append(params[i].getType());
707:                }
708:                return sb.toString();
709:            }
710:
711:            private String getValueFromBundle(String key) {
712:                String value;
713:                try {
714:                    value = m_bundle.getString(key);
715:                } catch (MissingResourceException e) {
716:                    value = "??(" + key + ")";
717:                }
718:                return value;
719:            }
720:
721:            private String getValueOrNullFromBundle(String key) {
722:                String value = null;
723:                try {
724:                    value = m_bundle.getString(key);
725:                } catch (MissingResourceException e) {
726:                }
727:                return value;
728:            }
729:
730:            private static class NestedResourceBundle extends ResourceBundle {
731:                private ResourceBundle _impl;
732:
733:                NestedResourceBundle(ResourceBundle impl) {
734:                    _impl = impl;
735:                }
736:
737:                void setParent(NestedResourceBundle parent) {
738:                    super .setParent(parent);
739:                }
740:
741:                /* (non-Javadoc)
742:                 * @see java.util.ResourceBundle#handleGetObject(java.lang.String)
743:                 */
744:                protected Object handleGetObject(String key) {
745:                    try {
746:                        return _impl.getString(key);
747:                    } catch (MissingResourceException e) {
748:                        return null; // Resource bundle will ask parent
749:                    }
750:                }
751:
752:                /* (non-Javadoc)
753:                 * @see java.util.ResourceBundle#getKeys()
754:                 */
755:                public Enumeration getKeys() {
756:                    // obtain union of all keys in bundle hierachy (no doublons)
757:                    HashSet hs = new HashSet();
758:                    addEnumeration(hs, _impl.getKeys());
759:                    if (parent != null) {
760:                        addEnumeration(hs, parent.getKeys());
761:                    }
762:                    return Collections.enumeration(hs);
763:                }
764:
765:                private void addEnumeration(Collection col, Enumeration e) {
766:                    while (e.hasMoreElements()) {
767:                        col.add(e.nextElement());
768:                    }
769:                }
770:
771:            }
772:
773:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.