Source Code Cross Referenced for CallingConventionManager.java in  » Web-Services » xins » org » xins » server » 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 » Web Services » xins » org.xins.server 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: CallingConventionManager.java,v 1.85 2007/09/18 08:45:06 agoubard Exp $
003:         *
004:         * Copyright 2003-2007 Orange Nederland Breedband B.V.
005:         * See the COPYRIGHT file for redistribution and use restrictions.
006:         */
007:        package org.xins.server;
008:
009:        import java.lang.reflect.Constructor;
010:        import java.util.ArrayList;
011:        import java.util.Arrays;
012:        import java.util.HashMap;
013:        import java.util.HashSet;
014:        import java.util.Iterator;
015:        import java.util.List;
016:        import java.util.Map;
017:        import java.util.Set;
018:
019:        import javax.servlet.http.HttpServletRequest;
020:
021:        import org.xins.common.Utils;
022:        import org.xins.common.collections.InvalidPropertyValueException;
023:        import org.xins.common.collections.MissingRequiredPropertyException;
024:        import org.xins.common.collections.PropertyReader;
025:        import org.xins.common.manageable.BootstrapException;
026:        import org.xins.common.manageable.InitializationException;
027:        import org.xins.common.manageable.Manageable;
028:        import org.xins.common.text.TextUtils;
029:
030:        /**
031:         * Manages the <code>CallingConvention</code> instances for the API.
032:         *
033:         * @version $Revision: 1.85 $ $Date: 2007/09/18 08:45:06 $
034:         * @author <a href="mailto:mees.witteman@orange-ftgroup.com">Mees Witteman</a>
035:         * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
036:         * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
037:         *
038:         * @see CallingConvention
039:         */
040:        class CallingConventionManager extends Manageable {
041:
042:            /**
043:             * The name of the bootstrap property that specifies the name of the default
044:             * calling convention.
045:             */
046:            private static final String API_CALLING_CONVENTION_PROPERTY = "org.xins.api.calling.convention";
047:
048:            /**
049:             * The name of the bootstrap property that specifies the class of the default
050:             * calling convention.
051:             */
052:            private static final String API_CALLING_CONVENTION_CLASS_PROPERTY = "org.xins.api.calling.convention.class";
053:
054:            /**
055:             * The name of the request parameter that specifies the name of the calling
056:             * convention to use.
057:             */
058:            static final String CALLING_CONVENTION_PARAMETER = "_convention";
059:
060:            /**
061:             * The name of the XINS standard calling convention.
062:             */
063:            private static final String STANDARD_CALLING_CONVENTION = "_xins-std";
064:
065:            /**
066:             * The XINS XML calling convention.
067:             */
068:            private static final String XML_CALLING_CONVENTION = "_xins-xml";
069:
070:            /**
071:             * The XINS XSLT calling convention.
072:             */
073:            private static final String XSLT_CALLING_CONVENTION = "_xins-xslt";
074:
075:            /**
076:             * The name of the SOAP calling convention.
077:             *
078:             * @since XINS 1.3.0
079:             */
080:            private static final String SOAP_CALLING_CONVENTION = "_xins-soap";
081:
082:            /**
083:             * The name of the SOAP calling convention with mapping.
084:             *
085:             * @since XINS 2.1
086:             */
087:            private static final String SOAP_MAP_CALLING_CONVENTION = "_xins-soap-map";
088:
089:            /**
090:             * The name of the XML-RPC calling convention.
091:             *
092:             * @since XINS 1.3.0
093:             */
094:            private static final String XML_RPC_CALLING_CONVENTION = "_xins-xmlrpc";
095:
096:            /**
097:             * The name of the JSON-RPC calling convention.
098:             *
099:             * @since XINS 2.0.
100:             */
101:            public static final String JSON_RPC_CALLING_CONVENTION = "_xins-jsonrpc";
102:
103:            /**
104:             * The name of the JSON calling convention. The call is a Yahoo! style call.
105:             *
106:             * @since XINS 2.0.
107:             */
108:            private static final String JSON_CALLING_CONVENTION = "_xins-json";
109:
110:            /**
111:             * List of the names of the calling conventions currently included in
112:             * XINS.
113:             */
114:            private static final List CONVENTIONS = Arrays.asList(new String[] {
115:                    STANDARD_CALLING_CONVENTION, XML_CALLING_CONVENTION,
116:                    XSLT_CALLING_CONVENTION, SOAP_CALLING_CONVENTION,
117:                    SOAP_MAP_CALLING_CONVENTION, XML_RPC_CALLING_CONVENTION,
118:                    JSON_RPC_CALLING_CONVENTION, JSON_CALLING_CONVENTION });
119:
120:            /**
121:             * Array of type <code>Class</code> that is used when constructing a
122:             * <code>CallingConvention</code> instance via RMI.
123:             */
124:            private static final Class[] CONSTRUCTOR_ARG_CLASSES = { API.class };
125:
126:            /**
127:             * Placeholder object used to indicate that the construction of a calling
128:             * convention object failed. Never <code>null</code>.
129:             */
130:            private static final Object CREATION_FAILED = new Object();
131:
132:            /**
133:             * The API. Never <code>null</code>.
134:             */
135:            private final API _api;
136:
137:            /**
138:             * The name of the default calling convention. There is always a default
139:             * calling convention (at least after bootstrapping).
140:             *
141:             * <p>This field is initialized during bootstrapping.
142:             */
143:            private String _defaultConventionName;
144:
145:            /**
146:             * The names of the possible calling conventions.
147:             */
148:            private List _conventionNames;
149:
150:            /**
151:             * Map containing all calling conventions. The key is the name of the
152:             * calling convention, the value is the calling convention object, or
153:             * {@link #CREATION_FAILED} if the calling convention object could not be
154:             * constructed.
155:             */
156:            private final HashMap _conventions;
157:
158:            /**
159:             * Creates a <code>CallingConventionManager</code> for the specified API.
160:             *
161:             * @param api
162:             *    the API, cannot be <code>null</code>.
163:             */
164:            CallingConventionManager(API api) {
165:
166:                // Store the reference to the API
167:                _api = api;
168:
169:                // Fill the list of the convention names with the pre defined conventions
170:                _conventionNames = new ArrayList();
171:                _conventionNames.addAll(CONVENTIONS);
172:
173:                // Create a map to store the conventions in
174:                _conventions = new HashMap(12);
175:
176:            }
177:
178:            /**
179:             * Performs the bootstrap procedure (actual implementation).
180:             *
181:             * @param properties
182:             *    the bootstrap properties, not <code>null</code>.
183:             *
184:             * @throws MissingRequiredPropertyException
185:             *    if a required property is not given.
186:             *
187:             * @throws InvalidPropertyValueException
188:             *    if the value of a certain property is invalid.
189:             *
190:             * @throws BootstrapException
191:             *    if the bootstrapping failed for any other reason.
192:             */
193:            protected void bootstrapImpl(PropertyReader properties)
194:                    throws MissingRequiredPropertyException,
195:                    InvalidPropertyValueException, BootstrapException {
196:
197:                // Determine the name and class of the custom calling convention
198:                _defaultConventionName = determineDefaultConvention(properties);
199:
200:                // Append the defined calling conventions
201:                Iterator itCustomCC = properties.getNames();
202:                while (itCustomCC.hasNext()) {
203:                    String nextProperty = (String) itCustomCC.next();
204:                    if (nextProperty
205:                            .startsWith(API_CALLING_CONVENTION_PROPERTY + '.')
206:                            && !nextProperty
207:                                    .equals(API_CALLING_CONVENTION_CLASS_PROPERTY)) {
208:                        String conventionName = nextProperty.substring(32,
209:                                nextProperty.length() - 6);
210:                        _conventionNames.add(conventionName);
211:                    }
212:                }
213:
214:                // Construct and bootstrap the default calling convention
215:                CallingConvention cc = create(properties,
216:                        _defaultConventionName);
217:
218:                // If created, store the object and attempt bootstrapping
219:                if (cc != null) {
220:                    _conventions.put(_defaultConventionName, cc);
221:                    bootstrap(_defaultConventionName, cc, properties);
222:
223:                    if (cc.getState() != Manageable.BOOTSTRAPPED) {
224:                        throw new BootstrapException(
225:                                "Failed to bootstrap the default calling convention.");
226:                    }
227:
228:                    // Otherwise, if it's the default calling convention, fails
229:                } else {
230:                    throw new BootstrapException(
231:                            "Failed to create the default calling convention.");
232:                }
233:            }
234:
235:            /**
236:             * Determines the default calling convention.
237:             *
238:             * @param properties
239:             *    the bootstrap properties, cannot be <code>null</code>.
240:             *
241:             * @return
242:             *    the name of the default calling convention, never <code>null</code>.
243:             *
244:             * @throws MissingRequiredPropertyException
245:             *    if a required property is not given.
246:             *
247:             * @throws InvalidPropertyValueException
248:             *    if the value of a certain property is invalid.
249:             */
250:            private String determineDefaultConvention(PropertyReader properties)
251:                    throws MissingRequiredPropertyException,
252:                    InvalidPropertyValueException {
253:
254:                // Name of the default calling convention (if any)
255:                String name = TextUtils.trim(properties
256:                        .get(API_CALLING_CONVENTION_PROPERTY), null);
257:
258:                // No calling convention defined
259:                if (name == null) {
260:
261:                    // Log: No custom calling convention specified
262:                    Log.log_3246();
263:
264:                    // Fallback to the XINS-specified default calling convention
265:                    name = STANDARD_CALLING_CONVENTION;
266:                }
267:
268:                // Log: Determined default calling convention
269:                Log.log_3245(name);
270:
271:                // Return the name of the default calling convention
272:                return name;
273:            }
274:
275:            /**
276:             * Constructs the calling convention with the specified name, using the
277:             * specified bootstrap properties. This method is called for both
278:             * <em>regular</em> and <em>custom</em> calling conventions.
279:             *
280:             * <p>If the name does not identify a recognized calling convention, then
281:             * <code>null</code> is returned.
282:             *
283:             * @param properties
284:             *    the bootstrap properties, cannot be <code>null</code>.
285:             *
286:             * @param name
287:             *    the name of the calling convention to construct, cannot be
288:             *    <code>null</code>.
289:             *
290:             * @return
291:             *    a non-bootstrapped {@link CallingConvention} instance that matches
292:             *    the specified name, or <code>null</code> if no match is found.
293:             */
294:            private CallingConvention create(PropertyReader properties,
295:                    String name) {
296:
297:                // Determine the name of the CallingConvention class
298:                String className;
299:                if (name.charAt(0) == '_') {
300:                    className = classNameForRegular(name);
301:                } else {
302:                    className = properties.get(API_CALLING_CONVENTION_PROPERTY
303:                            + '.' + name + ".class");
304:                }
305:
306:                // If the class could not be determined, then return null
307:                if (className == null) {
308:                    Log.log_3239(null, name, null);
309:                    return null;
310:                }
311:
312:                Log.log_3237(name, className);
313:
314:                // Construct a CallingConvention instance
315:                CallingConvention cc = construct(name, className);
316:
317:                // NOTE: Logging of construction failures is done in construct(...)
318:
319:                // Constructed successfully
320:                if (cc != null) {
321:                    cc.setAPI(_api);
322:                    cc.setConventionName(name);
323:                }
324:
325:                return cc;
326:            }
327:
328:            /**
329:             * Determines the name of the class that represents the regular calling
330:             * convention with the specified name. A <em>regular</em> calling
331:             * convention is one that comes with the XINS framework.
332:             *
333:             * @param name
334:             *    the name of the calling convention, should not be <code>null</code>
335:             *    and should normally starts with an underscore character
336:             *    (<code>'_'</code>).
337:             *
338:             * @return
339:             *    the name of the {@link CallingConvention} class that matches the
340:             *    specified calling convention name, or <code>null</code> if unknown.
341:             */
342:            private String classNameForRegular(String name) {
343:
344:                // XINS standard
345:                if (name.equals(STANDARD_CALLING_CONVENTION)) {
346:                    return "org.xins.server.StandardCallingConvention";
347:
348:                    // XINS XML
349:                } else if (name.equals(XML_CALLING_CONVENTION)) {
350:                    return "org.xins.server.XMLCallingConvention";
351:
352:                    // XSLT
353:                } else if (name.equals(XSLT_CALLING_CONVENTION)) {
354:                    return "org.xins.server.XSLTCallingConvention";
355:
356:                    // SOAP
357:                } else if (name.equals(SOAP_CALLING_CONVENTION)) {
358:                    return "org.xins.server.SOAPCallingConvention";
359:
360:                    // SOAP MAP
361:                } else if (name.equals(SOAP_MAP_CALLING_CONVENTION)) {
362:                    return "org.xins.server.SOAPMapCallingConvention";
363:
364:                    // XML-RPC
365:                } else if (name.equals(XML_RPC_CALLING_CONVENTION)) {
366:                    return "org.xins.server.XMLRPCCallingConvention";
367:
368:                    // JSON-RPC
369:                } else if (name.equals(JSON_RPC_CALLING_CONVENTION)) {
370:                    return "org.xins.server.JSONRPCCallingConvention";
371:
372:                    // JSON
373:                } else if (name.equals(JSON_CALLING_CONVENTION)) {
374:                    return "org.xins.server.JSONCallingConvention";
375:
376:                    // Unrecognized
377:                } else {
378:                    return null;
379:                }
380:            }
381:
382:            /**
383:             * Constructs a new <code>CallingConvention</code> instance by class name.
384:             *
385:             * @param name
386:             *    the name of the calling convention, cannot be <code>null</code>.
387:             *
388:             * @param className
389:             *    the name of the class, cannot be <code>null</code>.
390:             *
391:             * @return
392:             *    the constructed {@link CallingConvention} instance, or
393:             *    <code>null</code> if the construction failed.
394:             */
395:            private CallingConvention construct(String name, String className) {
396:
397:                // Try to load the class
398:                Class clazz;
399:                try {
400:                    clazz = Class.forName(className);
401:                } catch (Throwable exception) {
402:                    Log.log_3239(exception, name, className);
403:                    return null;
404:                }
405:
406:                // Get the constructor that accepts an API argument
407:                Constructor con = null;
408:                try {
409:                    con = clazz.getConstructor(CONSTRUCTOR_ARG_CLASSES);
410:                } catch (NoSuchMethodException exception) {
411:                    // fall through, do not even log
412:                }
413:
414:                // If there is such a constructor, invoke it
415:                if (con != null) {
416:
417:                    // Invoke it
418:                    Object[] args = { _api };
419:                    try {
420:                        CallingConvention cc = (CallingConvention) con
421:                                .newInstance(args);
422:                        return cc;
423:
424:                        // If the constructor exists but failed, then construction failed
425:                    } catch (Throwable exception) {
426:                        Utils.logIgnoredException(exception);
427:                        return null;
428:                    }
429:                }
430:
431:                // Secondly try a constructor with no arguments
432:                try {
433:                    CallingConvention cc = (CallingConvention) clazz
434:                            .newInstance();
435:                    return cc;
436:                } catch (Throwable exception) {
437:                    Log.log_3239(exception, name, className);
438:                    return null;
439:                }
440:            }
441:
442:            /**
443:             * Bootstraps the specified calling convention.
444:             *
445:             * @param name
446:             *    the name of the calling convention, cannot be <code>null</code>.
447:             *
448:             * @param cc
449:             *    the {@link CallingConvention} object to bootstrap, cannot be
450:             *    <code>null</code>.
451:             *
452:             * @param properties
453:             *    the bootstrap properties, cannot be <code>null</code>.
454:             */
455:            private void bootstrap(String name, CallingConvention cc,
456:                    PropertyReader properties) {
457:
458:                // Bootstrapping calling convention
459:                Log.log_3240(name);
460:
461:                try {
462:                    cc.bootstrap(properties);
463:
464:                    // Missing property
465:                } catch (MissingRequiredPropertyException exception) {
466:                    Log.log_3242(name, exception.getPropertyName(), exception
467:                            .getDetail());
468:
469:                    // Invalid property
470:                } catch (InvalidPropertyValueException exception) {
471:                    Log.log_3243(name, exception.getPropertyName(), exception
472:                            .getPropertyValue(), exception.getReason());
473:
474:                    // Catch BootstrapException and any other exceptions not caught
475:                    // by previous catch statements
476:                } catch (Throwable exception) {
477:                    Log.log_3244(exception, name);
478:                }
479:            }
480:
481:            /**
482:             * Performs the initialization procedure (actual implementation).
483:             *
484:             * @param properties
485:             *    the initialization properties, not null.
486:             *
487:             * @throws MissingRequiredPropertyException
488:             *    if a required property is not given.
489:             *
490:             * @throws InvalidPropertyValueException
491:             *    if the value of a certain property is invalid.
492:             *
493:             * @throws InitializationException
494:             *    if the initialization failed, for any other reason.
495:             */
496:            protected void initImpl(PropertyReader properties)
497:                    throws MissingRequiredPropertyException,
498:                    InvalidPropertyValueException, InitializationException {
499:
500:                // Loop through all CallingConvention instances
501:                Iterator iterator = _conventions.entrySet().iterator();
502:                while (iterator.hasNext()) {
503:
504:                    // Determine the name and get the CallingConvention instance
505:                    Map.Entry entry = (Map.Entry) iterator.next();
506:                    String name = (String) entry.getKey();
507:                    Object cc = entry.getValue();
508:
509:                    // Process this CallingConvention only if it was created OK
510:                    if (cc != CREATION_FAILED) {
511:
512:                        // Initialize the CallingConvention
513:                        CallingConvention conv = (CallingConvention) cc;
514:                        init(name, conv, properties);
515:
516:                        // Fail if the *default* calling convention fails to initialize
517:                        if (!conv.isUsable()
518:                                && name.equals(_defaultConventionName)) {
519:                            throw new InitializationException(
520:                                    "Failed to initialize the default calling convention \""
521:                                            + name + "\".");
522:                        }
523:                    }
524:                }
525:            }
526:
527:            /**
528:             * Initializes the specified calling convention.
529:             *
530:             * <p>If the specified calling convention is not even bootstrapped, the
531:             * initialization is not even attempted.
532:             *
533:             * @param name
534:             *    the name of the calling convention, cannot be <code>null</code>.
535:             *
536:             * @param cc
537:             *    the {@link CallingConvention} object to initialize, cannot be
538:             *    <code>null</code>.
539:             *
540:             * @param properties
541:             *    the initialization properties, cannot be <code>null</code>.
542:             */
543:            private void init(String name, CallingConvention cc,
544:                    PropertyReader properties) {
545:
546:                // If the CallingConvention is not even bootstrapped, then do not even
547:                // attempt to initialize it
548:                if (!cc.isBootstrapped()) {
549:                    return;
550:                }
551:
552:                // Initialize calling convention
553:                Log.log_3435(name);
554:
555:                try {
556:                    cc.init(properties);
557:
558:                    // Missing property
559:                } catch (MissingRequiredPropertyException exception) {
560:                    Log.log_3437(name, exception.getPropertyName(), exception
561:                            .getDetail());
562:
563:                    // Invalid property
564:                } catch (InvalidPropertyValueException exception) {
565:                    Log.log_3438(name, exception.getPropertyName(), exception
566:                            .getPropertyValue(), exception.getReason());
567:
568:                    // Catch InitializationException and any other exceptions not caught
569:                    // by previous catch statements
570:                } catch (Throwable exception) {
571:                    Log.log_3439(exception, name);
572:                }
573:            }
574:
575:            /**
576:             * Determines the calling convention to use for the specified request.
577:             *
578:             * @param request
579:             *    the incoming request, cannot be <code>null</code>.
580:             *
581:             * @return
582:             *    the calling convention to use, never <code>null</code>.
583:             *
584:             * @throws InvalidRequestException
585:             *    if the request is considered invalid, for example because the calling
586:             *    convention specified in the request is unknown.
587:             */
588:            CallingConvention getCallingConvention(HttpServletRequest request)
589:                    throws InvalidRequestException {
590:
591:                // Get the value of the input parameter that determines the convention
592:                String ccName = request
593:                        .getParameter(CALLING_CONVENTION_PARAMETER);
594:
595:                // If a calling convention is specified then use that one
596:                if (!TextUtils.isEmpty(ccName)) {
597:                    CallingConvention cc = getCallingConvention(ccName);
598:                    if (!Arrays.asList(cc.getSupportedMethods(request))
599:                            .contains(request.getMethod())
600:                            && !"OPTIONS".equals(request.getMethod())) {
601:                        String detail = "Calling convention \"" + ccName
602:                                + "\" does not support the \""
603:                                + request.getMethod() + "\" for this request.";
604:                        Log.log_3507(ccName, detail);
605:                        throw new InvalidRequestException(detail);
606:                    }
607:                    return cc;
608:
609:                    // Otherwise try to detect which one is appropriate
610:                } else {
611:                    return detectCallingConvention(request);
612:                }
613:            }
614:
615:            /**
616:             * Gets the calling convention for the given name.
617:             *
618:             * <p>The returned calling convention is bootstrapped and initialized.
619:             *
620:             * @param name
621:             *    the name of the calling convention to retrieve, should not be
622:             *    <code>null</code>.
623:             *
624:             * @return
625:             *    the calling convention initialized, never <code>null</code>.
626:             *
627:             * @throws InvalidRequestException
628:             *    if the calling convention name is unknown.
629:             */
630:            private CallingConvention getCallingConvention(String name)
631:                    throws InvalidRequestException {
632:
633:                // Get the CallingConvention object
634:                Object o = _conventions.get(name);
635:
636:                // Not found
637:                if (o == null && !_conventionNames.contains(name)) {
638:                    String detail = "Calling convention \"" + name
639:                            + "\" is unknown.";
640:                    Log.log_3507(name, detail);
641:                    throw new InvalidRequestException(detail);
642:                } else if (o == null) {
643:
644:                    // Create the asked calling convention and initiaze it
645:                    CallingConvention cc = create(
646:                            _api.getBootstrapProperties(), name);
647:
648:                    // If created, store the object and attempt bootstrapping
649:                    if (cc != null) {
650:                        o = cc;
651:                        _conventions.put(name, cc);
652:                        bootstrap(name, cc, _api.getBootstrapProperties());
653:                        init(name, cc, _api.getRuntimeProperties());
654:                    } else {
655:                        o = CREATION_FAILED;
656:                        _conventions.put(name, o);
657:                    }
658:                }
659:
660:                // Creation failed
661:                if (o == CREATION_FAILED) {
662:                    String detail = "Calling convention \"" + name
663:                            + "\" is known, but could not be created.";
664:                    Log.log_3507(name, detail);
665:                    throw new InvalidRequestException(detail);
666:
667:                    // Calling convention is recognized and was created OK
668:                } else {
669:
670:                    // Not usable (so not bootstrapped and initialized)
671:                    CallingConvention cc = (CallingConvention) o;
672:                    if (!cc.isUsable()) {
673:                        String detail = "Calling convention \"" + name
674:                                + "\" is known, but is uninitialized.";
675:                        Log.log_3507(name, detail);
676:                        throw new InvalidRequestException(detail);
677:                    }
678:
679:                    return cc;
680:                }
681:            }
682:
683:            /**
684:             * Gets the calling convention for the given name, or <code>null</code> if
685:             * the calling convention is not found or not usable.
686:             *
687:             * <p>The returned calling convention is bootstrapped and initialized.
688:             *
689:             * @param name
690:             *    the name of the calling convention to retrieve, should not be
691:             *    <code>null</code>.
692:             *
693:             * @return
694:             *    the calling convention, or <code>null</code>.
695:             */
696:            CallingConvention getCallingConvention2(String name) {
697:
698:                try {
699:                    return getCallingConvention(name);
700:                } catch (InvalidRequestException ex) {
701:                    return null;
702:                }
703:            }
704:
705:            /**
706:             * Attempts to detect which calling convention is the most appropriate for
707:             * an incoming request. This method is called when the calling convention
708:             * is not explicitly specified in the request.
709:             *
710:             * <p>The {@link CallingConvention#matchesRequest(HttpServletRequest)}
711:             * method is used to determine which calling conventions match. Then
712:             * the following algorithm is used to chose one:
713:             *
714:             * <ul>
715:             *    <li>if the default calling convention matches, use that;
716:             *    <li>otherwise if the {@link XSLTCallingConvention} matches and at
717:             *        least one of the parameters specific for the this calling
718:             *        convention is set, then use it;
719:             *    <li>otherwise if the {@link StandardCallingConvention} matches, use
720:             *        that;
721:             *    <li>otherwise if there is exactly one other calling convention that
722:             *        matches, use that one;
723:             *    <li>if none of the calling conventions match, throw an
724:             *        {@link InvalidRequestException}, indicating that no match could
725:             *        be found;
726:             *    <li>if multiple calling conventions match, throw an
727:             *        {@link InvalidRequestException}, indicating that several matches
728:             *        were found;
729:             * </ul>
730:             *
731:             * @param request
732:             *    the incoming request, cannot be <code>null</code>.
733:             *
734:             * @return
735:             *    the calling convention to use, never <code>null</code>.
736:             *
737:             * @throws InvalidRequestException
738:             *    if the request is considered invalid, for example because the calling
739:             *    convention specified in the request is unknown.
740:             */
741:            CallingConvention detectCallingConvention(HttpServletRequest request)
742:                    throws InvalidRequestException {
743:
744:                // Log: Request does not specify any calling convention
745:                Log.log_3508();
746:
747:                // See if the default calling convention matches
748:                CallingConvention defCC = getCallingConvention2(_defaultConventionName);
749:                if (defCC != null && defCC.matchesRequest(request)) {
750:                    Log.log_3509(defCC.getClass().getName());
751:                    return defCC;
752:                }
753:
754:                // If not, see if XSLT-specific properties are set /and/ _xins-xslt matches
755:                CallingConvention xslCC = getCallingConvention2("_xins-xslt");
756:                if (xslCC != null && xslCC != defCC
757:                        && xslCC.matchesRequest(request)) {
758:
759:                    // Determine if one of the two XSLT-specific parameters is set
760:                    String p1 = request
761:                            .getParameter(XSLTCallingConvention.TEMPLATE_PARAMETER);
762:                    String p2 = request
763:                            .getParameter(XSLTCallingConvention.CLEAR_TEMPLATE_CACHE_PARAMETER);
764:
765:                    // Use the XSLT calling convention if and only if at least one of the
766:                    // parameters is actually set
767:                    if (!(TextUtils.isEmpty(p1) && TextUtils.isEmpty(p2))) {
768:                        Log.log_3509(XSLTCallingConvention.class.getName());
769:                        return xslCC;
770:                    }
771:                }
772:
773:                // If not, see if _xins-std matches
774:                CallingConvention stdCC = getCallingConvention2("_xins-std");
775:                if (stdCC != null && stdCC != defCC
776:                        && stdCC.matchesRequest(request)) {
777:                    Log.log_3509(StandardCallingConvention.class.getName());
778:                    return stdCC;
779:                }
780:
781:                // Local variable to hold the first matching calling convention
782:                CallingConvention matching = null;
783:
784:                // Determine which calling conventions match
785:                Iterator itConventionNames = _conventionNames.iterator();
786:                while (itConventionNames.hasNext()) {
787:                    String name = (String) itConventionNames.next();
788:                    Object value = getCallingConvention2(name);
789:
790:                    // if the value is null, that's maybe an initialization problem
791:                    if (value == null) {
792:                        value = _conventions.get(name);
793:                    }
794:
795:                    // Skip all values that are not CallingConvention instances
796:                    // Skip also the default and the standard calling conventions, we
797:                    // already established that they cannot handle the request
798:                    if (value == CREATION_FAILED || value == defCC
799:                            || value == stdCC) {
800:                        continue;
801:                    }
802:
803:                    // Convert the value to a CallingConvention
804:                    CallingConvention cc = (CallingConvention) value;
805:
806:                    // Determine whether this one can handle it
807:                    if (cc.matchesRequest(request)) {
808:
809:                        // First match
810:                        if (matching == null) {
811:                            matching = cc;
812:
813:                            // Fail: Multiple matches
814:                        } else {
815:                            Log.log_3511();
816:                            String multipleMatches = "Request does not specify a calling "
817:                                    + "convention, it cannot be handled by the "
818:                                    + "default calling convention and multiple "
819:                                    + "calling conventions are able to handle it: \"";
820:                            String message = multipleMatches
821:                                    + matching.getClass().getName() + "\", \""
822:                                    + cc.getClass().getName() + "\".";
823:                            throw new InvalidRequestException(message);
824:                        }
825:                    }
826:                }
827:
828:                // One match
829:                if (matching != null) {
830:                    return matching;
831:
832:                    // Fail: No matches
833:                } else {
834:                    Log.log_3510();
835:                    String noMatches = "Request does not specify a calling convention, it "
836:                            + "cannot be handled by the default calling convention and it was "
837:                            + "not possible to find any calling convention that can handle it.";
838:                    throw new InvalidRequestException(noMatches);
839:                }
840:            }
841:
842:            /**
843:             * Returns the set of HTTP methods supported for function invocations. This
844:             * is the union of the methods supported by the individual calling
845:             * conventions for invoking functions, so excluding the <em>OPTIONS</em>
846:             * method. The latter cannot be used for function invocations, only to
847:             * determine which HTTP methods are available. See
848:             * {@link CallingConvention#getSupportedMethods()}.
849:             *
850:             * @return
851:             *    the {@link Set} of supported HTTP methods, never <code>null</code>.
852:             *
853:             * @throws IllegalStateException
854:             *    if this calling convention manager is not yet bootstrapped and
855:             *    initialized, see {@link #isUsable()}.
856:             */
857:            final Set getSupportedMethods() throws IllegalStateException {
858:
859:                // Make sure this Manageable object is bootstrapped and initialized
860:                assertUsable();
861:
862:                HashSet supportedMethods = new HashSet();
863:                Iterator itConventionNames = _conventionNames.iterator();
864:                while (itConventionNames.hasNext()) {
865:
866:                    String name = (String) itConventionNames.next();
867:                    Object convention = getCallingConvention2(name);
868:
869:                    // if the value is null, that's maybe an initialization problem
870:                    if (convention == null) {
871:                        convention = _conventions.get(name);
872:                    }
873:
874:                    // Add all methods supported by the calling convention
875:                    if (convention instanceof  CallingConvention) {
876:                        CallingConvention cc = (CallingConvention) convention;
877:                        supportedMethods.addAll(Arrays.asList(cc
878:                                .getSupportedMethods()));
879:                    }
880:                }
881:
882:                return supportedMethods;
883:            }
884:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.