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


001:        /*
002:         * $Id: XINSServiceCaller.java,v 1.180 2007/09/11 10:14:20 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.client;
008:
009:        import java.util.HashMap;
010:        import java.util.Iterator;
011:        import org.xins.common.FormattedParameters;
012:
013:        import org.xins.logdoc.ExceptionUtils;
014:
015:        import org.xins.common.MandatoryArgumentChecker;
016:        import org.xins.common.Utils;
017:        import org.xins.common.collections.PropertyReader;
018:        import org.xins.common.http.HTTPCallConfig;
019:        import org.xins.common.http.HTTPCallException;
020:        import org.xins.common.http.HTTPCallRequest;
021:        import org.xins.common.http.HTTPCallResult;
022:        import org.xins.common.http.HTTPServiceCaller;
023:        import org.xins.common.http.StatusCodeHTTPCallException;
024:        import org.xins.common.service.CallConfig;
025:        import org.xins.common.service.CallException;
026:        import org.xins.common.service.CallExceptionList;
027:        import org.xins.common.service.CallRequest;
028:        import org.xins.common.service.CallResult;
029:        import org.xins.common.service.ConnectionTimeOutCallException;
030:        import org.xins.common.service.ConnectionRefusedCallException;
031:        import org.xins.common.service.Descriptor;
032:        import org.xins.common.service.GenericCallException;
033:        import org.xins.common.service.IOCallException;
034:        import org.xins.common.service.ServiceCaller;
035:        import org.xins.common.service.SocketTimeOutCallException;
036:        import org.xins.common.service.TargetDescriptor;
037:        import org.xins.common.service.TotalTimeOutCallException;
038:        import org.xins.common.service.UnexpectedExceptionCallException;
039:        import org.xins.common.service.UnknownHostCallException;
040:        import org.xins.common.service.UnsupportedProtocolException;
041:        import org.xins.common.spec.ErrorCodeSpec;
042:        import org.xins.common.text.ParseException;
043:        import org.xins.common.text.TextUtils;
044:        import org.xins.common.xml.Element;
045:
046:        /**
047:         * XINS service caller. This class can be used to perform a call to a XINS
048:         * service, over HTTP, and fail-over to other XINS services if the first one
049:         * fails.
050:         *
051:         * <h2>Supported protocols</h2>
052:         *
053:         * <p>This service caller currently only supports the HTTP protocol. If a
054:         * {@link TargetDescriptor} is passed to the constructor with a different
055:         * protocol, then an {@link UnsupportedProtocolException} is thrown. In the
056:         * future, HTTPS and other protocols are expected to be supported as well.
057:         *
058:         * <h2>Load-balancing and fail-over</h2>
059:         *
060:         * <p>To perform a XINS call, use {@link #call(XINSCallRequest)}. Fail-over
061:         * and load-balancing can be performed automatically.
062:         *
063:         * <p>How load-balancing is done depends on the {@link Descriptor} passed to
064:         * the {@link #XINSServiceCaller(Descriptor)} constructor. If it is a
065:         * {@link TargetDescriptor}, then only this single target service is called
066:         * and no load-balancing is performed. If it is a
067:         * {@link org.xins.common.service.GroupDescriptor}, then the configuration of
068:         * the <code>GroupDescriptor</code> determines how the load-balancing is done.
069:         * A <code>GroupDescriptor</code> is a recursive data structure, which allows
070:         * for fairly advanced load-balancing algorithms.
071:         *
072:         * <p>If a call attempt fails and there are more available target services,
073:         * then the <code>XINSServiceCaller</code> may or may not fail-over to a next
074:         * target. If the request was not accepted by the target service, then
075:         * fail-over is considered acceptable and will be performed. This includes
076:         * the following situations:
077:         *
078:         * <ul>
079:         *    <li>if the <em>failOverAllowed</em> property is set to <code>true</code>
080:         *        for the {@link XINSCallRequest};
081:         *    <li>on connection refusal;
082:         *    <li>if a connection attempt times out;
083:         *    <li>if an HTTP status code other than 200-299 is returned;
084:         *    <li>if the XINS error code <em>_InvalidRequest</em> is returned;
085:         *    <li>if the XINS error code <em>_DisabledFunction</em> is returned.
086:         * </ul>
087:         *
088:         * <p>If none of these conditions holds, then fail-over is not considered
089:         * acceptable and will not be performed.
090:         *
091:         * <h2>Example code</h2>
092:         *
093:         * <p>The following example code snippet constructs a
094:         * <code>XINSServiceCaller</code> instance:
095:         *
096:         * <blockquote><pre>// Initialize properties for the services. Normally these
097:         // properties would come from a configuration source, like a file.
098:         {@link org.xins.common.collections.BasicPropertyReader} properties = new {@link org.xins.common.collections.BasicPropertyReader#BasicPropertyReader() org.xins.common.collections.BasicPropertyReader}();
099:         properties.{@link org.xins.common.collections.BasicPropertyReader#set(String,String) set}("myapi",         "group, random, server1, server2");
100:         properties.{@link org.xins.common.collections.BasicPropertyReader#set(String,String) set}("myapi.server1", "service, http://server1/myapi, 10000");
101:         properties.{@link org.xins.common.collections.BasicPropertyReader#set(String,String) set}("myapi.server2", "service, http://server2/myapi, 12000");
102:
103:         // Construct a descriptor and a XINSServiceCaller instance
104:         {@link Descriptor Descriptor} descriptor = {@link org.xins.common.service.DescriptorBuilder DescriptorBuilder}.{@link org.xins.common.service.DescriptorBuilder#build(PropertyReader,String) build}(properties, "myapi");
105:         XINSServiceCaller caller = new {@link #XINSServiceCaller(Descriptor) XINSServiceCaller}(descriptor);</pre></blockquote>
106:         *
107:         * <p>Then the following code snippet uses this <code>XINSServiceCaller</code>
108:         * to perform a call to a XINS function named <em>_GetStatistics</em>, using
109:         * HTTP POST:
110:         *
111:         * <blockquote><pre>// Prepare for the call
112:         {@link String}          function = "_GetStatistics";
113:         {@link org.xins.common.collections.PropertyReader}  params   = null;
114:         boolean         failOver = true;
115:         {@link org.xins.common.http.HTTPMethod}      method   = {@link org.xins.common.http.HTTPMethod}.{@link org.xins.common.http.HTTPMethod#POST POST};
116:         {@link XINSCallRequest} request  = new {@link XINSCallRequest#XINSCallRequest(String,PropertyReader,boolean,HTTPMethod) XINSCallRequest}(function, params, failOver, method);
117:
118:         // Perform the call
119:         {@link XINSCallResult} result = caller.{@link #call(XINSCallRequest) call}(request);</pre></blockquote>
120:         *
121:         * @version $Revision: 1.180 $ $Date: 2007/09/11 10:14:20 $
122:         * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
123:         *
124:         * @since XINS 1.0.0
125:         */
126:        public final class XINSServiceCaller extends ServiceCaller {
127:
128:            /**
129:             * The result parser. This field cannot be <code>null</code>.
130:             */
131:            private final XINSCallResultParser _parser;
132:
133:            /**
134:             * The <code>CAPI</code> object that uses this caller. This field is
135:             * <code>null</code> if this caller is not used by a <code>CAPI</code>
136:             * class.
137:             */
138:            private AbstractCAPI _capi;
139:
140:            /**
141:             * The map containing the service caller to call for the descriptor.
142:             * The key of the {@link HashMap} is a {@link TargetDescriptor} and the value
143:             * is a {@link ServiceCaller}.
144:             */
145:            private HashMap _serviceCallers;
146:
147:            /**
148:             * Constructs a new <code>XINSServiceCaller</code> with the specified
149:             * descriptor and call configuration.
150:             *
151:             * @param descriptor
152:             *    the descriptor of the service, cannot be <code>null</code>.
153:             *
154:             * @param callConfig
155:             *    the call configuration object for this service caller, or
156:             *    <code>null</code> if a default one should be associated with this
157:             *    service caller.
158:             *
159:             * @throws IllegalArgumentException
160:             *    if <code>descriptor == null</code>.
161:             *
162:             * @throws UnsupportedProtocolException
163:             *    if <code>descriptor</code> is or contains a {@link TargetDescriptor}
164:             *    with an unsupported protocol.
165:             *
166:             * @since XINS 1.1.0
167:             */
168:            public XINSServiceCaller(Descriptor descriptor,
169:                    XINSCallConfig callConfig) throws IllegalArgumentException,
170:                    UnsupportedProtocolException {
171:
172:                // Call constructor of superclass
173:                super (descriptor, callConfig);
174:
175:                // Initialize the fields
176:                _parser = new XINSCallResultParser();
177:            }
178:
179:            /**
180:             * Constructs a new <code>XINSServiceCaller</code> with the specified
181:             * descriptor and the default HTTP method.
182:             *
183:             * @param descriptor
184:             *    the descriptor of the service, cannot be <code>null</code>.
185:             *
186:             * @throws IllegalArgumentException
187:             *    if <code>descriptor == null</code>.
188:             *
189:             * @throws UnsupportedProtocolException
190:             *    if <code>descriptor</code> is or contains a {@link TargetDescriptor}
191:             *    with an unsupported protocol (<em>since XINS 1.1.0</em>).
192:             */
193:            public XINSServiceCaller(Descriptor descriptor)
194:                    throws IllegalArgumentException,
195:                    UnsupportedProtocolException {
196:                this (descriptor, null);
197:            }
198:
199:            /**
200:             * Constructs a new <code>XINSServiceCaller</code> with the specified
201:             * descriptor and the default HTTP method.
202:             *
203:             * @since XINS 1.2.0
204:             */
205:            public XINSServiceCaller() {
206:                this ((Descriptor) null, (XINSCallConfig) null);
207:            }
208:
209:            /**
210:             * Checks if the specified protocol is supported (implementation method).
211:             * The protocol is the part in a URL before the string <code>"://"</code>).
212:             *
213:             * <p>This method should only ever be called from the
214:             * {@link #isProtocolSupported(String)} method.
215:             *
216:             * <p>The implementation of this method in class <code>ServiceCaller</code>
217:             * throws an {@link UnsupportedOperationException}.
218:             *
219:             * @param protocol
220:             *    the protocol, guaranteed not to be <code>null</code>.
221:             *
222:             * @return
223:             *    <code>true</code> if the specified protocol is supported, or
224:             *    <code>false</code> if it is not.
225:             *
226:             * @since XINS 1.2.0
227:             */
228:            protected boolean isProtocolSupportedImpl(String protocol) {
229:                return "http".equalsIgnoreCase(protocol)
230:                        || "https".equalsIgnoreCase(protocol)
231:                        || "file".equalsIgnoreCase(protocol);
232:            }
233:
234:            public void setDescriptor(Descriptor descriptor) {
235:                super .setDescriptor(descriptor);
236:
237:                // Create the ServiceCaller for each descriptor
238:                if (_serviceCallers == null) {
239:                    _serviceCallers = new HashMap();
240:                }
241:                if (descriptor != null) {
242:                    Iterator targets = descriptor.iterateTargets();
243:                    while (targets.hasNext()) {
244:                        TargetDescriptor nextTarget = (TargetDescriptor) targets
245:                                .next();
246:                        String protocol = nextTarget.getProtocol();
247:                        if ("http".equalsIgnoreCase(protocol)
248:                                || "https".equalsIgnoreCase(protocol)) {
249:                            HTTPServiceCaller serviceCaller = new HTTPServiceCaller(
250:                                    nextTarget);
251:                            _serviceCallers.put(nextTarget, serviceCaller);
252:                        } else if ("file".equalsIgnoreCase(protocol)) {
253:                            FileServiceCaller serviceCaller = new FileServiceCaller(
254:                                    nextTarget);
255:                            _serviceCallers.put(nextTarget, serviceCaller);
256:                        }
257:                    }
258:                } else {
259:                    _serviceCallers.clear();
260:                }
261:            }
262:
263:            /**
264:             * Sets the associated <code>CAPI</code> instance.
265:             *
266:             * <p>This method is expected to be called only once, before any calls are
267:             * made with this caller.
268:             *
269:             * @param capi
270:             *    the associated <code>CAPI</code> instance, or
271:             *    <code>null</code>.
272:             */
273:            void setCAPI(AbstractCAPI capi) {
274:                _capi = capi;
275:            }
276:
277:            /**
278:             * Returns a default <code>CallConfig</code> object. This method is called
279:             * by the <code>ServiceCaller</code> constructor if no
280:             * <code>CallConfig</code> object was given.
281:             *
282:             * <p>The implementation of this method in class {@link XINSServiceCaller}
283:             * returns a standard {@link XINSCallConfig} object which has unconditional
284:             * fail-over disabled and the HTTP method set to
285:             * {@link org.xins.common.http.HTTPMethod#POST POST}.
286:             *
287:             * @return
288:             *    a new {@link XINSCallConfig} instance with default settings, never
289:             *    <code>null</code>.
290:             */
291:            protected CallConfig getDefaultCallConfig() {
292:                return new XINSCallConfig();
293:            }
294:
295:            /**
296:             * Sets the <code>XINSCallConfig</code> associated with this XINS service
297:             * caller.
298:             *
299:             * @param config
300:             *    the fall-back {@link XINSCallConfig} object for this service caller,
301:             *    cannot be <code>null</code>.
302:             *
303:             * @throws IllegalArgumentException
304:             *    if <code>config == null</code>.
305:             *
306:             * @since XINS 1.2.0
307:             */
308:            protected final void setXINSCallConfig(XINSCallConfig config)
309:                    throws IllegalArgumentException {
310:                super .setCallConfig(config);
311:            }
312:
313:            /**
314:             * Returns the <code>XINSCallConfig</code> associated with this service
315:             * caller.
316:             *
317:             * <p>This method is the type-safe equivalent of {@link #getCallConfig()}.
318:             *
319:             * @return
320:             *    the fall-back {@link XINSCallConfig} object for this XINS service
321:             *    caller, never <code>null</code>.
322:             *
323:             * @since XINS 1.2.0
324:             */
325:            public final XINSCallConfig getXINSCallConfig() {
326:                return (XINSCallConfig) getCallConfig();
327:            }
328:
329:            /**
330:             * Executes the specified XINS call request towards one of the associated
331:             * targets. If the call succeeds with one of these targets, then a
332:             * {@link XINSCallResult} object is returned. Otherwise, if none of the
333:             * targets could successfully be called, a
334:             * {@link org.xins.common.service.CallException} is thrown.
335:             *
336:             * <p>If the call succeeds, but the result is unsuccessful, then an
337:             * {@link UnsuccessfulXINSCallException} is thrown, which contains the
338:             * result.
339:             *
340:             * @param request
341:             *    the call request, not <code>null</code>.
342:             *
343:             * @param callConfig
344:             *    the call configuration, or <code>null</code> if the one specified in
345:             *    the request should be used, or -if the request does not specify any
346:             *    either- the one specified for this service caller.
347:             *
348:             * @return
349:             *    the result of the call, cannot be <code>null</code>.
350:             *
351:             * @throws IllegalArgumentException
352:             *    if <code>request == null</code>.
353:             *
354:             * @throws GenericCallException
355:             *    if the first call attempt failed due to a generic reason and all the
356:             *    other call attempts failed as well.
357:             *
358:             * @throws HTTPCallException
359:             *    if the first call attempt failed due to an HTTP-related reason and
360:             *    all the other call attempts failed as well.
361:             *
362:             * @throws XINSCallException
363:             *    if the first call attempt failed due to a XINS-related reason and
364:             *    all the other call attempts failed as well.
365:             *
366:             * @since XINS 1.1.0
367:             */
368:            public XINSCallResult call(XINSCallRequest request,
369:                    XINSCallConfig callConfig) throws IllegalArgumentException,
370:                    GenericCallException, HTTPCallException, XINSCallException {
371:
372:                // Determine when we started the call
373:                long start = System.currentTimeMillis();
374:
375:                // Perform the call
376:                XINSCallResult result;
377:                try {
378:                    result = (XINSCallResult) doCall(request, callConfig);
379:
380:                    // Handle failures
381:                } catch (Throwable exception) {
382:
383:                    // Log that the call completely failed, unless the back-end returned
384:                    // a functional error code. We assume that a functional error code
385:                    // can never fail-over, so this issue will have been logged at the
386:                    // correct (non-error) level already.
387:                    if (!(exception instanceof  UnsuccessfulXINSCallException)
388:                            || ((UnsuccessfulXINSCallException) exception)
389:                                    .getType() != ErrorCodeSpec.FUNCTIONAL) {
390:
391:                        // Determine how long the call took
392:                        long duration = System.currentTimeMillis() - start;
393:
394:                        // Serialize all parameters, including the data section, for logging
395:                        PropertyReader parameters = request.getParameters();
396:                        Element dataSection = request.getDataSection();
397:                        FormattedParameters params = new FormattedParameters(
398:                                parameters, dataSection, "(null)", "&", 160);
399:
400:                        // Serialize the exception chain
401:                        String chain = exception.getMessage();
402:
403:                        Log.log_2113(request.getFunctionName(), params,
404:                                duration, chain);
405:                    }
406:
407:                    // Allow only GenericCallException, HTTPCallException and
408:                    // XINSCallException to proceed
409:                    if (exception instanceof  GenericCallException) {
410:                        throw (GenericCallException) exception;
411:                    }
412:                    if (exception instanceof  HTTPCallException) {
413:                        throw (HTTPCallException) exception;
414:                    }
415:                    if (exception instanceof  XINSCallException) {
416:                        throw (XINSCallException) exception;
417:
418:                        // Unknown kind of exception. This should never happen. Log and
419:                        // re-throw the exception, wrapped within a ProgrammingException
420:                    } else {
421:                        throw Utils.logProgrammingError(exception);
422:                    }
423:                }
424:
425:                return result;
426:            }
427:
428:            /**
429:             * Executes the specified XINS call request towards one of the associated
430:             * targets. If the call succeeds with one of these targets, then a
431:             * {@link XINSCallResult} object is returned. Otherwise, if none of the
432:             * targets could successfully be called, a
433:             * {@link org.xins.common.service.CallException} is thrown.
434:             *
435:             * <p>If the call succeeds, but the result is unsuccessful, then an
436:             * {@link UnsuccessfulXINSCallException} is thrown, which contains the
437:             * result.
438:             *
439:             * @param request
440:             *    the call request, not <code>null</code>.
441:             *
442:             * @return
443:             *    the result of the call, cannot be <code>null</code>.
444:             *
445:             * @throws IllegalArgumentException
446:             *    if <code>request == null</code>.
447:             *
448:             * @throws GenericCallException
449:             *    if the first call attempt failed due to a generic reason and all the
450:             *    other call attempts failed as well.
451:             *
452:             * @throws HTTPCallException
453:             *    if the first call attempt failed due to an HTTP-related reason and
454:             *    all the other call attempts failed as well.
455:             *
456:             * @throws XINSCallException
457:             *    if the first call attempt failed due to a XINS-related reason and
458:             *    all the other call attempts failed as well.
459:             */
460:            public XINSCallResult call(XINSCallRequest request)
461:                    throws IllegalArgumentException, GenericCallException,
462:                    HTTPCallException, XINSCallException {
463:                return call(request, null);
464:            }
465:
466:            /**
467:             * Executes the specified request on the given target. If the call
468:             * succeeds, then a {@link XINSCallResult} object is returned, otherwise a
469:             * {@link org.xins.common.service.CallException} is thrown.
470:             *
471:             * @param target
472:             *    the target to call, cannot be <code>null</code>.
473:             *
474:             * @param callConfig
475:             *    the call configuration, never <code>null</code>.
476:             *
477:             * @param request
478:             *    the call request to be executed, must be an instance of class
479:             *    {@link XINSCallRequest}, cannot be <code>null</code>.
480:             *
481:             * @return
482:             *    the result, if and only if the call succeeded, always an instance of
483:             *    class {@link XINSCallResult}, never <code>null</code>.
484:             *
485:             * @throws IllegalArgumentException
486:             *    if <code>request    == null
487:             *          || callConfig == null
488:             *          || target     == null</code>.
489:             *
490:             * @throws ClassCastException
491:             *    if the specified <code>request</code> object is not <code>null</code>
492:             *    and not an instance of class {@link XINSCallRequest}.
493:             *
494:             * @throws GenericCallException
495:             *    if the call attempt failed due to a generic reason.
496:             *    other call attempts failed as well.
497:             *
498:             * @throws HTTPCallException
499:             *    if the call attempt failed due to an HTTP-related reason.
500:             *
501:             * @throws XINSCallException
502:             *    if the call attempt failed due to a XINS-related reason.
503:             */
504:            public Object doCallImpl(CallRequest request,
505:                    CallConfig callConfig, TargetDescriptor target)
506:                    throws IllegalArgumentException, ClassCastException,
507:                    GenericCallException, HTTPCallException, XINSCallException {
508:
509:                // Check preconditions
510:                MandatoryArgumentChecker.check("request", request,
511:                        "callConfig", callConfig, "target", target);
512:
513:                // Convert arguments to the appropriate classes
514:                XINSCallRequest xinsRequest = (XINSCallRequest) request;
515:                XINSCallConfig xinsConfig = (XINSCallConfig) callConfig;
516:
517:                // Get URL, function and parameters (for logging)
518:                String url = target.getURL();
519:                String function = xinsRequest.getFunctionName();
520:                PropertyReader p = xinsRequest.getParameters();
521:                Element dataSection = xinsRequest.getDataSection();
522:
523:                FormattedParameters params = new FormattedParameters(p,
524:                        dataSection, "", "&", 160);
525:
526:                // Get the time-out values (for logging)
527:                int totalTimeOut = target.getTotalTimeOut();
528:                int connectionTimeOut = target.getConnectionTimeOut();
529:                int socketTimeOut = target.getSocketTimeOut();
530:
531:                // Log: Right before the call is performed
532:                Log.log_2100(url, function, params);
533:
534:                // Get the contained HTTP request from the XINS request
535:                HTTPCallRequest httpRequest = xinsRequest.getHTTPCallRequest();
536:
537:                // Convert XINSCallConfig to HTTPCallConfig
538:                HTTPCallConfig httpConfig = xinsConfig.getHTTPCallConfig();
539:
540:                // Determine the start time. Only required when an unexpected kind of
541:                // exception is caught.
542:                long start = System.currentTimeMillis();
543:
544:                // Perform the HTTP call
545:                HTTPCallResult httpResult;
546:                long duration;
547:                try {
548:                    ServiceCaller serviceCaller = (ServiceCaller) _serviceCallers
549:                            .get(target);
550:                    httpResult = (HTTPCallResult) serviceCaller.doCallImpl(
551:                            httpRequest, httpConfig, target);
552:
553:                    // Call failed due to a generic service calling error
554:                } catch (GenericCallException exception) {
555:                    duration = exception.getDuration();
556:                    if (exception instanceof  UnknownHostCallException) {
557:                        Log.log_2102(url, function, params, duration);
558:                    } else if (exception instanceof  ConnectionRefusedCallException) {
559:                        Log.log_2103(url, function, params, duration);
560:                    } else if (exception instanceof  ConnectionTimeOutCallException) {
561:                        Log.log_2104(url, function, params, duration,
562:                                connectionTimeOut);
563:                    } else if (exception instanceof  SocketTimeOutCallException) {
564:                        Log.log_2105(url, function, params, duration,
565:                                socketTimeOut);
566:                    } else if (exception instanceof  TotalTimeOutCallException) {
567:                        Log.log_2106(url, function, params, duration,
568:                                totalTimeOut);
569:                    } else if (exception instanceof  IOCallException) {
570:                        Log
571:                                .log_2109(exception, url, function, params,
572:                                        duration);
573:                    } else if (exception instanceof  UnexpectedExceptionCallException) {
574:                        Log.log_2111(ExceptionUtils.getCause(exception), url,
575:                                function, params, duration);
576:                    } else {
577:                        String detail = "Unrecognized GenericCallException subclass "
578:                                + exception.getClass().getName() + '.';
579:                        Utils.logProgrammingError(detail);
580:                    }
581:                    throw exception;
582:
583:                    // Call failed due to an HTTP-related error
584:                } catch (HTTPCallException exception) {
585:                    duration = exception.getDuration();
586:                    if (exception instanceof  StatusCodeHTTPCallException) {
587:                        int code = ((StatusCodeHTTPCallException) exception)
588:                                .getStatusCode();
589:                        Log.log_2108(url, function, params, duration, code);
590:                    } else {
591:                        String detail = "Unrecognized HTTPCallException subclass "
592:                                + exception.getClass().getName() + '.';
593:                        Utils.logProgrammingError(detail);
594:                    }
595:                    throw exception;
596:
597:                    // Unknown kind of exception. This should never happen. Log and re-throw
598:                    // the exception, packed up as a CallException.
599:                } catch (Throwable exception) {
600:                    duration = System.currentTimeMillis() - start;
601:                    Utils.logProgrammingError(exception);
602:
603:                    String message = "Unexpected exception: "
604:                            + exception.getClass().getName() + ". Message: "
605:                            + TextUtils.quote(exception.getMessage()) + '.';
606:
607:                    Log.log_2111(exception, url, function, params, duration);
608:                    throw new UnexpectedExceptionCallException(request, target,
609:                            duration, message, exception);
610:                }
611:
612:                // Determine duration
613:                duration = httpResult.getDuration();
614:
615:                // Make sure data was received
616:                byte[] httpData = httpResult.getData();
617:                if (httpData == null || httpData.length == 0) {
618:
619:                    // Log: No data was received
620:                    Log.log_2110(url, function, params, duration,
621:                            "No data received.");
622:
623:                    // Throw an appropriate exception
624:                    throw InvalidResultXINSCallException.noDataReceived(
625:                            xinsRequest, target, duration);
626:                }
627:
628:                // Parse the result
629:                XINSCallResultData resultData;
630:                try {
631:                    resultData = _parser.parse(httpData);
632:
633:                    // If parsing failed, then abort
634:                } catch (ParseException e) {
635:
636:                    // Create a message for the new exception
637:                    String detail = e.getDetail();
638:                    String message = detail != null
639:                            && detail.trim().length() > 0 ? "Failed to parse result: "
640:                            + detail.trim()
641:                            : "Failed to parse result.";
642:
643:                    // Log: Parsing failed
644:                    Log.log_2110(url, function, params, duration, message);
645:
646:                    // Throw an appropriate exception
647:                    throw InvalidResultXINSCallException.parseError(httpData,
648:                            xinsRequest, target, duration, e);
649:                }
650:
651:                // If the result is unsuccessful, then throw an exception
652:                String errorCode = resultData.getErrorCode();
653:                if (errorCode != null) {
654:
655:                    boolean functionalError = false;
656:                    ErrorCodeSpec.Type type = null;
657:                    if (_capi != null) {
658:                        functionalError = _capi.isFunctionalError(errorCode);
659:                    }
660:
661:                    // Log this
662:                    if (functionalError) {
663:                        Log
664:                                .log_2115(url, function, params, duration,
665:                                        errorCode);
666:                    } else {
667:                        Log
668:                                .log_2112(url, function, params, duration,
669:                                        errorCode);
670:                    }
671:
672:                    // Standard error codes (start with an underscore)
673:                    if (errorCode.charAt(0) == '_') {
674:                        if (errorCode.equals("_DisabledFunction")) {
675:                            throw new DisabledFunctionException(xinsRequest,
676:                                    target, duration, resultData);
677:                        } else if (errorCode.equals("_InternalError")
678:                                || errorCode.equals("_InvalidResponse")) {
679:                            throw new InternalErrorException(xinsRequest,
680:                                    target, duration, resultData);
681:                        } else if (errorCode.equals("_InvalidRequest")) {
682:                            throw new InvalidRequestException(xinsRequest,
683:                                    target, duration, resultData);
684:                        } else {
685:                            throw new UnacceptableErrorCodeXINSCallException(
686:                                    xinsRequest, target, duration, resultData);
687:                        }
688:
689:                        // Non-standard error codes, CAPI not used
690:                    } else if (_capi == null) {
691:                        throw new UnsuccessfulXINSCallException(xinsRequest,
692:                                target, duration, resultData, null);
693:
694:                        // Non-standard error codes, CAPI used
695:                    } else {
696:                        AbstractCAPIErrorCodeException ex = _capi
697:                                .createErrorCodeException(xinsRequest, target,
698:                                        duration, resultData);
699:
700:                        if (ex != null) {
701:                            ex.setType(type);
702:                            throw ex;
703:                        } else {
704:
705:                            // If the CAPI class was generated using a XINS release older
706:                            // than 1.2.0, then it will not override the
707:                            // 'createErrorCodeException' method and consequently the
708:                            // method will return null. It cannot be determined here
709:                            // whether the error code is acceptable or not
710:                            String ver = _capi.getXINSVersion();
711:                            if (ver.startsWith("0.") || ver.startsWith("1.0.")
712:                                    || ver.startsWith("1.1.")) {
713:                                throw new UnsuccessfulXINSCallException(
714:                                        xinsRequest, target, duration,
715:                                        resultData, null);
716:
717:                            } else {
718:                                throw new UnacceptableErrorCodeXINSCallException(
719:                                        xinsRequest, target, duration,
720:                                        resultData);
721:                            }
722:                        }
723:                    }
724:                }
725:
726:                // Call completely succeeded
727:                Log.log_2101(url, function, params, duration);
728:
729:                return resultData;
730:            }
731:
732:            /**
733:             * Constructs an appropriate <code>CallResult</code> object for a
734:             * successful call attempt. This method is called from
735:             * {@link #doCall(CallRequest,CallConfig)}.
736:             *
737:             * <p>The implementation of this method in class
738:             * {@link XINSServiceCaller} expects an {@link XINSCallRequest} and
739:             * returns an {@link XINSCallResult}.
740:             *
741:             * @param request
742:             *    the {@link CallRequest} that was to be executed, never
743:             *    <code>null</code> when called from {@link #doCall(CallRequest,CallConfig)};
744:             *    should be an instance of class {@link XINSCallRequest}.
745:             *
746:             * @param succeededTarget
747:             *    the {@link TargetDescriptor} for the service that was successfully
748:             *    called, never <code>null</code> when called from
749:             *    {@link #doCall(CallRequest,CallConfig)}.
750:             *
751:             * @param duration
752:             *    the call duration in milliseconds, must be a non-negative number.
753:             *
754:             * @param exceptions
755:             *    the list of {@link org.xins.common.service.CallException} instances,
756:             *    or <code>null</code> if there were no call failures.
757:             *
758:             * @param result
759:             *    the result from the call, which is the object returned by
760:             *    {@link #doCallImpl(CallRequest,CallConfig,TargetDescriptor)}, always an instance
761:             *    of class {@link XINSCallResult}, never <code>null</code>; .
762:             *
763:             * @return
764:             *    a {@link XINSCallResult} instance, never <code>null</code>.
765:             *
766:             * @throws ClassCastException
767:             *    if either <code>request</code> or <code>result</code> is not of the
768:             *    correct class.
769:             */
770:            protected CallResult createCallResult(CallRequest request,
771:                    TargetDescriptor succeededTarget, long duration,
772:                    CallExceptionList exceptions, Object result)
773:                    throws ClassCastException {
774:
775:                XINSCallResult r = new XINSCallResult(
776:                        (XINSCallRequest) request, succeededTarget, duration,
777:                        exceptions, (XINSCallResultData) result);
778:
779:                return r;
780:            }
781:
782:            /**
783:             * Determines whether a call should fail-over to the next selected target
784:             * based on a request, call configuration and exception list.
785:             *
786:             * @param request
787:             *    the request for the call, as passed to {@link #doCall(CallRequest,CallConfig)},
788:             *    should not be <code>null</code>.
789:             *
790:             * @param callConfig
791:             *    the call config that is currently in use, never <code>null</code>.
792:             *
793:             * @param exceptions
794:             *    the current list of {@link CallException}s; never <code>null</code>.
795:             *
796:             * @return
797:             *    <code>true</code> if the call should fail-over to the next target, or
798:             *    <code>false</code> if it should not.
799:             */
800:            protected boolean shouldFailOver(CallRequest request,
801:                    CallConfig callConfig, CallExceptionList exceptions) {
802:
803:                // Get the most recent exception
804:                CallException exception = exceptions.last();
805:
806:                boolean should;
807:
808:                // Let the superclass look at this first.
809:                if (super .shouldFailOver(request, callConfig, exceptions)) {
810:                    should = true;
811:
812:                    // Otherwise check if the request may fail-over from HTTP point-of-view
813:                    //
814:                    // XXX: Note that this duplicates code that is already in the
815:                    //      HTTPServiceCaller. This may need to be refactored at some point.
816:                    //      It has been decided to take this approach since the
817:                    //      shouldFailOver method in class HTTPServiceCaller has protected
818:                    //      access.
819:                    //      An alternative solution that should be investigated is to
820:                    //      subclass HTTPServiceCaller.
821:
822:                    // A non-2xx HTTP status code indicates the request was not handled
823:                } else if (exception instanceof  StatusCodeHTTPCallException) {
824:                    int code = ((StatusCodeHTTPCallException) exception)
825:                            .getStatusCode();
826:                    should = (code < 200 || code > 299);
827:
828:                    // Some XINS error codes indicate the request was not accepted
829:                } else if (exception instanceof  UnsuccessfulXINSCallException) {
830:                    String s = ((UnsuccessfulXINSCallException) exception)
831:                            .getErrorCode();
832:                    should = ("_InvalidRequest".equals(s) || "_DisabledFunction"
833:                            .equals(s));
834:
835:                    // Otherwise do not fail over
836:                } else {
837:                    should = false;
838:                }
839:
840:                return should;
841:            }
842:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.