Source Code Cross Referenced for CallingConvention.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: CallingConvention.java,v 1.105.2.1 2007/09/27 14:43:33 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.io.IOException;
010:        import java.util.ArrayList;
011:        import java.util.Arrays;
012:        import java.util.Enumeration;
013:        import java.util.Iterator;
014:
015:        import javax.servlet.http.HttpServletRequest;
016:        import javax.servlet.http.HttpServletResponse;
017:
018:        import org.xins.common.MandatoryArgumentChecker;
019:        import org.xins.common.Utils;
020:        import org.xins.common.collections.BasicPropertyReader;
021:        import org.xins.common.manageable.Manageable;
022:        import org.xins.common.text.ParseException;
023:        import org.xins.common.text.TextUtils;
024:        import org.xins.common.xml.Element;
025:        import org.xins.common.xml.ElementParser;
026:
027:        /**
028:         * Abstraction of a calling convention. A calling convention determines how an
029:         * HTTP request is converted to a XINS function invocation request and how a
030:         * XINS function result is converted back to an HTTP response.
031:         *
032:         * <h2>Thread safety</h2>
033:         *
034:         * <p>Calling convention implementations must be thread-safe.
035:         *
036:         * @version $Revision: 1.105.2.1 $ $Date: 2007/09/27 14:43:33 $
037:         * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
038:         * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
039:         *
040:         * @see CallingConventionManager
041:         */
042:        abstract class CallingConvention extends Manageable {
043:
044:            /**
045:             * The default value of the <code>"Server"</code> header sent with an HTTP
046:             * response. The actual value is
047:             * <code>"XINS/Java Server Framework "</code>, followed by the version of
048:             * the framework.
049:             *
050:             * <p>TODO: Move this constant and the associated functionality elsewhere,
051:             * since it does not seem to belong in this class.
052:             */
053:            private static final String SERVER_HEADER = "XINS/Java Server Framework "
054:                    + Library.getVersion();
055:
056:            /**
057:             * The default set of supported HTTP methods.
058:             */
059:            private static final String[] DEFAULT_SUPPORTED_METHODS = new String[] {
060:                    "HEAD", "GET", "POST" };
061:
062:            /**
063:             * The key used in the HttpRequest attribute used to cache the parsed
064:             * XML Element when the request is an XML request.
065:             */
066:            private static final String CACHED_XML_ELEMENT_KEY = "CACHED_XML_ELEMENT_KEY";
067:
068:            /**
069:             * The current API. The value is set after the construction of the calling
070:             * convention.
071:             */
072:            private API _api;
073:
074:            /**
075:             * The convention name associated with this calling convention (e.g. _xins-std).
076:             */
077:            private String _conventionName;
078:
079:            /**
080:             * Constructs a new <code>CallingConvention</code>. A
081:             * <code>CallingConvention</code> instance can only be generated by the
082:             * XINS/Java Server Framework.
083:             */
084:            protected CallingConvention() {
085:            }
086:
087:            /**
088:             * Determines the current API.
089:             *
090:             * @return
091:             *    the current {@link API}, never <code>null</code>.
092:             *
093:             * @since XINS 1.5.0
094:             */
095:            protected final API getAPI() {
096:                return _api;
097:            }
098:
099:            /**
100:             * Sets the current API.
101:             *
102:             * @param api
103:             *    the current {@link API}, never <code>null</code>.
104:             */
105:            final void setAPI(API api) {
106:                _api = api;
107:            }
108:
109:            /**
110:             * Gets the name of the convention associated with this CC.
111:             *
112:             * @return
113:             *    the name of this calling convention, never <code>null</code>.
114:             *
115:             * @since XINS 2.1
116:             */
117:            final String getConventionName() {
118:                return _conventionName;
119:            }
120:
121:            /**
122:             * Sets the name of the convention associated with this CC.
123:             *
124:             * @param conventionName
125:             *    the calling convention name, never <code>null</code>.
126:             *
127:             * @since XINS 2.1
128:             */
129:            final void setConventionName(String conventionName) {
130:                _conventionName = conventionName;
131:            }
132:
133:            /**
134:             * Determines which HTTP methods are supported for function invocations.
135:             *
136:             * <p>Each <code>String</code> in the returned array must be one
137:             * supported method.
138:             *
139:             * <p>The returned array must not be <code>null</code>, it must only
140:             * contain valid HTTP method names, so they may not contain whitespace, for
141:             * example. Duplicates will be ignored. HTTP method names must be in uppercase.
142:             *
143:             * <p>There must be at least one HTTP method supported for function
144:             * invocations.
145:             *
146:             * <p>Note that <em>OPTIONS</em> must not be returned by this method, as it
147:             * is not an HTTP method that can ever be used to invoke a XINS function.
148:             * <p>HTTP <em>OPTIONS</em> requests are treated differently. For the path
149:             * <code>*</code> the capabilities of the whole server are returned. For other
150:             * paths, the appropriate calling convention is determined, after which the
151:             * set of supported HTTP methods is returned to the called.
152:             *
153:             * @return
154:             *    the HTTP methods supported, in a <code>String</code> array, must
155:             *    not be <code>null</code>.
156:             *
157:             * @since XINS 1.5.0
158:             */
159:            protected String[] getSupportedMethods() {
160:                return DEFAULT_SUPPORTED_METHODS;
161:            }
162:
163:            /**
164:             * Determines which HTTP methods are supported for function invocations,
165:             * for the specified request.
166:             *
167:             * <p>Each <code>String</code> in the returned array must be one
168:             * supported method.
169:             *
170:             * <p>The returned array may be <code>null</code>. If it is not, then the
171:             * returned array must only contain valid HTTP method names, so they may
172:             * not contain whitespace, for example. HTTP method names must be in uppercase.
173:             *
174:             * <p>There must be at least one HTTP method supported for function
175:             * invocations.
176:             *
177:             * <p>Note that <em>OPTIONS</em> must not be returned by this method, as it
178:             * is not an HTTP method that can ever be used to invoke a XINS function.
179:             *
180:             * <p>The set of supported methods must be a subset of the set returned by
181:             * {@link #getSupportedMethods()}.
182:             *
183:             * <p>The default implementation of this method returns the set returned by
184:             * {@link #getSupportedMethods()}.
185:             *
186:             * @param request
187:             *    the request to determine the supported methods for.
188:             *
189:             * @return
190:             *    the HTTP methods supported for the specified request, in a
191:             *    <code>String</code> array, can be <code>null</code>.
192:             *
193:             * @since XINS 1.5.0
194:             */
195:            protected String[] getSupportedMethods(HttpServletRequest request) {
196:                return getSupportedMethods();
197:            }
198:
199:            /**
200:             * Checks if the specified request can be handled by this calling
201:             * convention. Assuming this <code>CallingConvention</code> instance is
202:             * usable and the HTTP method is supported, this method delegates to
203:             * {@link #matches(HttpServletRequest)}.
204:             *
205:             * <p>If this calling convention is not usable (see {@link #isUsable()}),
206:             * then <code>false</code> is returned, even <em>before</em> calling
207:             * {@link #matches(HttpServletRequest)}.
208:             *
209:             * <p>If this method does not support the HTTP method for function
210:             * invocations, then <code>false</code> is returned.
211:             *
212:             * <p>If {@link #matches(HttpServletRequest)} throws an exception, then
213:             * this exception is ignored and <code>false</code> is returned.
214:             *
215:             * <p>This method is guaranteed not to throw any exception.
216:             *
217:             * @param httpRequest
218:             *    the HTTP request to investigate, cannot be <code>null</code>.
219:             *
220:             * @return
221:             *    <code>true</code> if this calling convention is <em>possibly</em>
222:             *    able to handle this request, or <code>false</code> if it is
223:             *    <em>definitely</em> not able to handle this request.
224:             */
225:            final boolean matchesRequest(HttpServletRequest httpRequest) {
226:
227:                // First check if this CallingConvention instance is bootstrapped and
228:                // initialized
229:                if (!isUsable()) {
230:                    return false;
231:                }
232:
233:                // Make sure the HTTP method is supported
234:                String method = httpRequest.getMethod();
235:                if (!Arrays.asList(getSupportedMethods(httpRequest)).contains(
236:                        method)
237:                        && !"OPTIONS".equals(method)) {
238:                    return false;
239:                }
240:
241:                // Delegate to the 'matches' method
242:                try {
243:                    return matches(httpRequest);
244:
245:                    // Assume that an exception indicates the request cannot be handled
246:                    //
247:                    // NOTE: We do not log this exception, because it would possibly show up
248:                    //       in the logs on a regular basis, drawing attention to a
249:                    //       non-issue.
250:                } catch (Throwable exception) {
251:                    return false;
252:                }
253:            }
254:
255:            /**
256:             * Checks if the specified request can possibly be handled by this calling
257:             * convention as a function invocation.
258:             *
259:             * <p>Implementations of this method should be optimized for performance,
260:             * as this method may be called for each incoming request. Also, this
261:             * method should not have any side-effects except possibly some caching in
262:             * case there is a match.
263:             *
264:             * <p>If this method throws any exception, the exception is logged as an
265:             * ignorable exception and <code>false</code> is assumed.
266:             *
267:             * <p>This method should only be called by the XINS/Java Server Framework.
268:             *
269:             * @param httpRequest
270:             *    the HTTP request to investigate, never <code>null</code>.
271:             *
272:             * @return
273:             *    <code>true</code> if this calling convention is <em>possibly</em>
274:             *    able to handle this request, or <code>false</code> if it is
275:             *    <em>definitely</em> not able to handle this request.
276:             *
277:             * @throws Exception
278:             *    if analysis of the request causes an exception; in this case
279:             *    <code>false</code> will be assumed by the framework.
280:             *
281:             * @since XINS 1.4.0
282:             */
283:            protected abstract boolean matches(HttpServletRequest httpRequest)
284:                    throws Exception;
285:
286:            /**
287:             * Converts an HTTP request to a XINS request (wrapper method). This method
288:             * checks the arguments, checks that the HTTP method is actually supported,
289:             * calls the implementation method and then checks the return value from
290:             * that method.
291:             *
292:             * @param httpRequest
293:             *    the HTTP request, cannot be <code>null</code>.
294:             *
295:             * @return
296:             *    the XINS request object, never <code>null</code>.
297:             *
298:             * @throws IllegalStateException
299:             *    if this calling convention is currently not usable, see
300:             *    {@link Manageable#assertUsable()}.
301:             *
302:             * @throws IllegalArgumentException
303:             *    if <code>httpRequest == null</code>.
304:             *
305:             * @throws InvalidRequestException
306:             *    if the request is considerd to be invalid, at least for this calling
307:             *    convention; either because the HTTP method is not supported, or
308:             *    because {@link #convertRequestImpl(HttpServletRequest)} indicates so.
309:             *
310:             * @throws FunctionNotSpecifiedException
311:             *    if the request does not indicate the name of the function to execute.
312:             */
313:            final FunctionRequest convertRequest(HttpServletRequest httpRequest)
314:                    throws IllegalStateException, IllegalArgumentException,
315:                    InvalidRequestException, FunctionNotSpecifiedException {
316:
317:                // Make sure the current state is okay
318:                assertUsable();
319:
320:                // Check preconditions
321:                MandatoryArgumentChecker.check("httpRequest", httpRequest);
322:
323:                // Delegate to the implementation method
324:                FunctionRequest xinsRequest;
325:                try {
326:                    xinsRequest = convertRequestImpl(httpRequest);
327:
328:                    // Filter any thrown exceptions
329:                } catch (Throwable exception) {
330:                    if (exception instanceof  InvalidRequestException) {
331:                        throw (InvalidRequestException) exception;
332:                    } else if (exception instanceof  FunctionNotSpecifiedException) {
333:                        throw (FunctionNotSpecifiedException) exception;
334:                    } else {
335:                        throw Utils.logProgrammingError(exception);
336:                    }
337:                }
338:
339:                // Make sure the returned value is not null
340:                if (xinsRequest == null) {
341:                    throw Utils.logProgrammingError("Method returned null.");
342:                }
343:
344:                return xinsRequest;
345:            }
346:
347:            /**
348:             * Converts an HTTP request to a XINS request (implementation method). This
349:             * method should only be called from the XINS/Java Server Framework self.
350:             * Then it is guaranteed that:
351:             * <ul>
352:             *    <li>the state is usable;
353:             *    <li>the <code>httpRequest</code> argument is not <code>null</code>;
354:             *    <li>the HTTP method is in the set of supported methods, as indicated
355:             *        by {@link #getSupportedMethods()}.
356:             * </ul>
357:             *
358:             * <p>Note that {@link #getSupportedMethods(HttpServletRequest)} will not
359:             * have been called prior to this method call.
360:             *
361:             * @param httpRequest
362:             *    the HTTP request.
363:             *
364:             * @return
365:             *    the XINS request object, should not be <code>null</code>.
366:             *
367:             * @throws InvalidRequestException
368:             *    if the request is considerd to be invalid.
369:             *
370:             * @throws FunctionNotSpecifiedException
371:             *    if the request does not indicate the name of the function to execute.
372:             */
373:            protected abstract FunctionRequest convertRequestImpl(
374:                    HttpServletRequest httpRequest)
375:                    throws InvalidRequestException,
376:                    FunctionNotSpecifiedException;
377:
378:            /**
379:             * Converts a XINS result to an HTTP response (wrapper method). This method
380:             * checks the arguments, then calls the implementation method and then
381:             * checks the return value from that method.
382:             *
383:             * <p>Note that this method is not called if there is an error while
384:             * converting the request.
385:             *
386:             * @param xinsResult
387:             *    the XINS result object that should be converted to an HTTP response,
388:             *    cannot be <code>null</code>.
389:             *
390:             * @param httpResponse
391:             *    the HTTP response object to configure, cannot be <code>null</code>.
392:             *
393:             * @param httpRequest
394:             *    the HTTP request, cannot be <code>null</code>.
395:             *
396:             * @throws IllegalStateException
397:             *    if this calling convention is currently not usable, see
398:             *    {@link Manageable#assertUsable()}.
399:             *
400:             * @throws IllegalArgumentException
401:             *    if <code>xinsResult   == null
402:             *          || httpResponse == null
403:             *          || httpRequest  == null</code>.
404:             *
405:             * @throws IOException
406:             *    if the invocation of any of the methods in either
407:             *    <code>httpResponse</code> or <code>httpRequest</code> caused an I/O
408:             *    error.
409:             */
410:            final void convertResult(FunctionResult xinsResult,
411:                    HttpServletResponse httpResponse,
412:                    HttpServletRequest httpRequest)
413:                    throws IllegalStateException, IllegalArgumentException,
414:                    IOException {
415:
416:                // Make sure the current state is okay
417:                assertUsable();
418:
419:                // Check preconditions
420:                MandatoryArgumentChecker.check("xinsResult", xinsResult,
421:                        "httpResponse", httpResponse, "httpRequest",
422:                        httpRequest);
423:
424:                // By default, all calling conventions return the same "Server" header.
425:                // This can be overridden in the convertResultImpl() method.
426:                httpResponse.addHeader("Server", SERVER_HEADER);
427:
428:                // Delegate to the implementation method
429:                try {
430:                    convertResultImpl(xinsResult, httpResponse, httpRequest);
431:
432:                    // Filter any thrown exceptions
433:                } catch (Throwable exception) {
434:                    if (exception instanceof  IOException) {
435:                        Log.log_3506(exception, getClass().getName());
436:                        throw (IOException) exception;
437:                    } else {
438:                        throw Utils.logProgrammingError(exception);
439:                    }
440:                }
441:            }
442:
443:            /**
444:             * Converts a XINS result to an HTTP response (implementation method). This
445:             * method should only be called from the XINS/Java Server Framework self.
446:             * Then it is guaranteed that none of the arguments is <code>null</code>.
447:             *
448:             * @param xinsResult
449:             *    the XINS result object that should be converted to an HTTP response,
450:             *    will not be <code>null</code>.
451:             *
452:             * @param httpResponse
453:             *    the HTTP response object to configure.
454:             *
455:             * @param httpRequest
456:             *    the HTTP request.
457:             *
458:             * @throws IOException
459:             *    if the invocation of any of the methods in either
460:             *    <code>httpResponse</code> or <code>httpRequest</code> caused an I/O
461:             *    error.
462:             */
463:            protected abstract void convertResultImpl(
464:                    FunctionResult xinsResult,
465:                    HttpServletResponse httpResponse,
466:                    HttpServletRequest httpRequest) throws IOException;
467:
468:            // XXX: Replace IOException with more appropriate exception?
469:
470:            /**
471:             * Parses XML from the specified HTTP request and checks that the content
472:             * type is correct.
473:             *
474:             * <p>This method uses a cache to optimize performance if either of the
475:             * <code>parseXMLRequest</code> methods is called multiple times for the
476:             * same request.
477:             *
478:             * <p>Calling this method is equivalent with calling
479:             * {@link #parseXMLRequest(HttpServletRequest,boolean)} with the
480:             * <code>checkType</code> argument set to <code>true</code>.
481:             *
482:             * @param httpRequest
483:             *    the HTTP request, cannot be <code>null</code>.
484:             *
485:             * @return
486:             *    the parsed element, never <code>null</code>.
487:             *
488:             * @throws IllegalArgumentException
489:             *    if <code>httpRequest == null</code>.
490:             *
491:             * @throws InvalidRequestException
492:             *    if the HTTP request cannot be read or cannot be parsed correctly.
493:             *
494:             * @since XINS 1.4.0
495:             */
496:            protected Element parseXMLRequest(HttpServletRequest httpRequest)
497:                    throws IllegalArgumentException, InvalidRequestException {
498:                return parseXMLRequest(httpRequest, true);
499:            }
500:
501:            /**
502:             * Parses XML from the specified HTTP request and optionally checks that
503:             * the content type is correct.
504:             *
505:             * <p>Since XINS 1.4.0, this method uses a cache to optimize performance if
506:             * either of the <code>parseXMLRequest</code> methods is called multiple
507:             * times for the same request.
508:             *
509:             * @param httpRequest
510:             *    the HTTP request, cannot be <code>null</code>.
511:             *
512:             * @param checkType
513:             *    flag indicating whether this method should check that the content
514:             *    type of the request is <em>text/xml</em>.
515:             *
516:             * @return
517:             *    the parsed element, never <code>null</code>.
518:             *
519:             * @throws IllegalArgumentException
520:             *    if <code>httpRequest == null</code>.
521:             *
522:             * @throws InvalidRequestException
523:             *    if the HTTP request cannot be read or cannot be parsed correctly.
524:             *
525:             * @since XINS 1.3.0
526:             */
527:            protected Element parseXMLRequest(HttpServletRequest httpRequest,
528:                    boolean checkType) throws IllegalArgumentException,
529:                    InvalidRequestException {
530:
531:                // Check arguments
532:                MandatoryArgumentChecker.check("httpRequest", httpRequest);
533:
534:                // Determine if the request matches the cached request and the parsed
535:                // XML is already cached
536:                Object cached = httpRequest
537:                        .getAttribute(CACHED_XML_ELEMENT_KEY);
538:
539:                // Cache miss
540:                if (cached == null) {
541:                    Log.log_3512();
542:
543:                    // Cache hit
544:                } else {
545:                    Log.log_3513();
546:                    return (Element) cached;
547:                }
548:
549:                // Always first check the content type, even if checking is enabled. We
550:                // do this because the parsed request will only be stored if the content
551:                // type was OK.
552:                String contentType = httpRequest.getContentType();
553:                String errorMessage = null;
554:                if (contentType == null || contentType.trim().length() < 1) {
555:                    errorMessage = "No content type set.";
556:                } else {
557:                    String contentTypeLC = contentType.toLowerCase();
558:                    if (!("text/xml".equals(contentTypeLC) || contentTypeLC
559:                            .startsWith("text/xml;"))) {
560:                        errorMessage = "Invalid content type \""
561:                                + contentType
562:                                + "\". Expected \"text/xml\" (case-insensitive) or a variant of it.";
563:                    }
564:                }
565:
566:                // The content-type check was unsuccessful
567:                if (errorMessage != null) {
568:
569:                    // Log: Not caching XML since the content type is not "text/xml"
570:                    Log.log_3515();
571:
572:                    // If checking is enabled
573:                    if (checkType) {
574:                        throw new InvalidRequestException(errorMessage);
575:                    }
576:                }
577:
578:                // Parse the content in the HTTP request
579:                ElementParser parser = new ElementParser();
580:                Element element;
581:                try {
582:                    element = parser.parse(httpRequest.getReader());
583:
584:                    // I/O error
585:                } catch (IOException ex) {
586:                    String message = "Failed to read XML request.";
587:                    throw new InvalidRequestException(message, ex);
588:
589:                    // Parsing error
590:                } catch (ParseException ex) {
591:                    String message = "Failed to parse XML request.";
592:                    throw new InvalidRequestException(message, ex);
593:                }
594:
595:                // Only store in the cache if the content type was OK
596:                if (errorMessage == null) {
597:                    httpRequest.setAttribute(CACHED_XML_ELEMENT_KEY, element);
598:                    Log.log_3514();
599:                }
600:
601:                return element;
602:            }
603:
604:            /**
605:             * Gathers all parameters from the specified request. The parameters are
606:             * returned as a {@link BasicPropertyReader}.
607:             * If no parameters are found, then <code>null</code> is returned.
608:             *
609:             * <p>If a parameter is found to have multiple values, then an
610:             * {@link InvalidRequestException} is thrown.
611:             *
612:             * @param httpRequest
613:             *    the HTTP request to get the parameters from, cannot be
614:             *    <code>null</code>.
615:             *
616:             * @return
617:             *    the properties found, or <code>null</code> if none were found.
618:             *
619:             * @throws InvalidRequestException
620:             *    if a parameter is found that has multiple values.
621:             */
622:            BasicPropertyReader gatherParams(HttpServletRequest httpRequest)
623:                    throws InvalidRequestException {
624:
625:                // Get the parameters from the HTTP request
626:                Enumeration params = httpRequest.getParameterNames();
627:
628:                // The property set to return from this method
629:                BasicPropertyReader pr;
630:
631:                // If there are no parameters, then return null
632:                if (!params.hasMoreElements()) {
633:                    pr = null;
634:
635:                    // There seem to be some parameters
636:                } else {
637:                    pr = new BasicPropertyReader();
638:
639:                    do {
640:                        // Get the parameter name
641:                        String name = (String) params.nextElement();
642:
643:                        // Get all parameter values (can be multiple)
644:                        String[] values = httpRequest.getParameterValues(name);
645:
646:                        // Be gentle, allow nulls and zero-sized arrays
647:                        if (values != null && values.length != 0) {
648:
649:                            // Get the parameter value, allowing duplicate values, but not
650:                            // different ones; this may throw an InvalidRequestException
651:                            String value = getParamValue(name, values);
652:
653:                            // Associate the name with the one and only value
654:                            pr.set(name, value);
655:                        }
656:                    } while (params.hasMoreElements());
657:                }
658:                return pr;
659:            }
660:
661:            /**
662:             * Changes a parameter set to remove all parameters that should not be
663:             * passed to functions.
664:             *
665:             * <p>A parameter will be removed if it matches any of the following
666:             * conditions:
667:             *
668:             * <ul>
669:             *    <li>parameter name is <code>null</code>;
670:             *    <li>parameter name is empty;
671:             *    <li>parameter value is <code>null</code>;
672:             *    <li>parameter value is empty;
673:             *    <li>parameter name equals <code>"function"</code>.
674:             * </ul>
675:             *
676:             * @param parameters
677:             *    the {@link BasicPropertyReader} containing the set of parameters
678:             *    to investigate, cannot be <code>null</code>.
679:             *
680:             * @throws IllegalArgumentException
681:             *    if <code>parameters == null</code>.
682:             */
683:            static void cleanUpParameters(BasicPropertyReader parameters)
684:                    throws IllegalArgumentException {
685:
686:                // Check arguments
687:                MandatoryArgumentChecker.check("parameters", parameters);
688:
689:                // Get the parameter names
690:                Iterator names = parameters.getNames();
691:
692:                // Loop through all parameters
693:                ArrayList toRemove = new ArrayList();
694:                while (names.hasNext()) {
695:
696:                    // Determine parameter name and value
697:                    String name = (String) names.next();
698:                    String value = parameters.get(name);
699:
700:                    // If the parameter name or value is empty, or if the name is
701:                    // "function", then mark the parameter as 'to be removed'.
702:                    // Parameters starting with an underscore are reserved for XINS, so
703:                    // mark these as 'to be removed' as well.
704:                    if (TextUtils.isEmpty(name) || TextUtils.isEmpty(value)
705:                            || "function".equals(name) || name.charAt(0) == '_') {
706:                        toRemove.add(name);
707:                    }
708:                }
709:
710:                // If there is anything to remove, then do so
711:                Iterator itRemove = toRemove.iterator();
712:                while (itRemove.hasNext()) {
713:                    String name = (String) itRemove.next();
714:                    parameters.set(name, null);
715:                }
716:            }
717:
718:            /**
719:             * Determines a single value for a parameter based on an array of values.
720:             * If there is only one value, then that value is returned. If there are
721:             * multiple equal values, then the value is returned as well. However, if
722:             * there are multiple values and at least one of them is different, then an
723:             * {@link InvalidRequestException} is thrown.
724:             *
725:             * @param name
726:             *    the name of the parameter, only used when throwing an
727:             *    {@link InvalidRequestException}, should not be <code>null</code>.
728:             *
729:             * @param values
730:             *    the values, should not be <code>null</code> and should not have a
731:             *    size of zero.
732:             *
733:             * @return
734:             *    the single value of the parameter, if any.
735:             *
736:             * @throws NullPointerException
737:             *    if <code>values == null || values[<em>n</em>] == null</code>, where
738:             *    <code>0 &lt;= <em>n</em> &lt; values.length</code>.
739:             *
740:             * @throws IndexOutOfBoundsException
741:             *    if <code>values.length &lt; 1</code>.
742:             *
743:             * @throws InvalidRequestException
744:             *    if the parameter is found to have multiple different values.
745:             */
746:            private final String getParamValue(String name, String[] values)
747:                    throws NullPointerException, IndexOutOfBoundsException,
748:                    InvalidRequestException {
749:
750:                String value = values[0];
751:
752:                // We only need to do crunching if there is more than one value
753:                if (values.length > 1) {
754:                    for (int i = 1; i < values.length; i++) {
755:                        String other = values[i];
756:                        if (!value.equals(other)) {
757:                            throw new InvalidRequestException(
758:                                    "Found multiple values for the parameter named \""
759:                                            + name + "\".");
760:                        }
761:                    }
762:                }
763:
764:                return value;
765:            }
766:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.