Source Code Cross Referenced for RMClientTube.java in  » 6.0-JDK-Modules-com.sun » wsit » com » sun » xml » ws » rm » jaxws » runtime » 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 » 6.0 JDK Modules com.sun » wsit » com.sun.xml.ws.rm.jaxws.runtime.client 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         * 
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         * 
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common Development
008:         * and Distribution License("CDDL") (collectively, the "License").  You
009:         * may not use this file except in compliance with the License. You can obtain
010:         * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011:         * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
012:         * language governing permissions and limitations under the License.
013:         * 
014:         * When distributing the software, include this License Header Notice in each
015:         * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016:         * Sun designates this particular file as subject to the "Classpath" exception
017:         * as provided by Sun in the GPL Version 2 section of the License file that
018:         * accompanied this code.  If applicable, add the following below the License
019:         * Header, with the fields enclosed by brackets [] replaced by your own
020:         * identifying information: "Portions Copyrighted [year]
021:         * [name of copyright owner]"
022:         * 
023:         * Contributor(s):
024:         * 
025:         * If you wish your version of this file to be governed by only the CDDL or
026:         * only the GPL Version 2, indicate your decision by adding "[Contributor]
027:         * elects to include this software in this distribution under the [CDDL or GPL
028:         * Version 2] license."  If you don't indicate a single choice of license, a
029:         * recipient has the option to distribute your version of this file under
030:         * either the CDDL, the GPL Version 2 or to extend the choice of license to
031:         * its licensees as provided above.  However, if you add GPL Version 2 code
032:         * and therefore, elected the GPL Version 2 license, then the option applies
033:         * only if the new code is made subject to such option by the copyright
034:         * holder.
035:         */
036:
037:        /*
038:         * RMClientTube.java
039:         *
040:         * @author Mike Grogan
041:         * @author Bhakti Mehta
042:         * Created on February 4, 2006, 2:58 PM
043:         *
044:         */
045:
046:        package com.sun.xml.ws.rm.jaxws.runtime.client;
047:
048:        import com.sun.istack.NotNull;
049:        import com.sun.xml.ws.api.WSBinding;
050:        import com.sun.xml.ws.api.WSService;
051:        import com.sun.xml.ws.api.addressing.AddressingVersion;
052:        import com.sun.xml.ws.api.message.Message;
053:        import com.sun.xml.ws.api.message.Packet;
054:        import com.sun.xml.ws.api.model.wsdl.WSDLBoundOperation;
055:        import com.sun.xml.ws.api.model.wsdl.WSDLBoundPortType;
056:        import com.sun.xml.ws.api.model.wsdl.WSDLOperation;
057:        import com.sun.xml.ws.api.model.wsdl.WSDLPort;
058:        import com.sun.xml.ws.api.pipe.*;
059:        import com.sun.xml.ws.client.ClientTransportException;
060:        import com.sun.xml.ws.rm.Constants;
061:        import com.sun.xml.ws.rm.MessageSender;
062:        import com.sun.xml.ws.rm.RMException;
063:        import com.sun.xml.ws.rm.jaxws.runtime.InboundMessageProcessor;
064:        import com.sun.xml.ws.rm.jaxws.runtime.SequenceConfig;
065:        import com.sun.xml.ws.rm.jaxws.runtime.TubeBase;
066:        import com.sun.xml.ws.rm.jaxws.util.LoggingHelper;
067:        import com.sun.xml.ws.security.secconv.SecureConversationInitiator;
068:        import com.sun.xml.ws.security.secext10.SecurityTokenReferenceType;
069:
070:        import javax.xml.bind.JAXBElement;
071:        import javax.xml.soap.SOAPException;
072:        import javax.xml.ws.BindingProvider;
073:        import javax.xml.ws.WebServiceException;
074:        import java.io.IOException;
075:        import java.net.SocketTimeoutException;
076:        import java.net.URI;
077:        import java.net.URISyntaxException;
078:        import java.util.logging.Level;
079:        import java.util.logging.Logger;
080:
081:        /**
082:         * Client-side Pipe implementation.
083:         */
084:        public class RMClientTube
085:                extends
086:                TubeBase<RMSource, ClientOutboundSequence, ClientInboundSequence> {
087:
088:            public static final Logger logger = Logger.getLogger(LoggingHelper
089:                    .getLoggerName(RMClientTube.class));
090:            public static final LoggingHelper logHelper = new LoggingHelper(
091:                    logger);
092:
093:            /*
094:             * Metadata from ctor.
095:             */
096:            private WSDLPort port;
097:            private WSService service;
098:            private WSBinding binding;
099:            private SecureConversationInitiator securityPipe;
100:
101:            /*
102:             * SequenceConfig from policy
103:             */
104:            private SequenceConfig config;
105:
106:            /**
107:             * RM OutboundSequence handled by this Pipe.
108:             */
109:            private ClientOutboundSequence outboundSequence;
110:
111:            /**
112:             * RM InboundSequence handled by this Pipe.
113:             */
114:            private ClientInboundSequence inboundSequence;
115:
116:            /**
117:             * Message processor to handle inbound messages
118:             */
119:            private InboundMessageProcessor messageProcessor;
120:
121:            /**
122:             * Flag to indicate if security pipe is our next pipe
123:             * then we need to create CreateSequenceRequest with
124:             * STR
125:             */
126:            private boolean secureReliableMessaging;
127:
128:            /**
129:             * The BindingProvider instance using the OutboundSequence
130:             * serviced by this pipe.
131:             */
132:            private BindingProvider proxy;
133:
134:            /**
135:             * State of a specific request/response.  The Tubeline handle one such
136:             * exchange at a time, so it is safe to store these if they are not copied
137:             * by the clone operation.
138:             */
139:
140:            /*Store the MEP of the current exchange*/
141:            private Boolean isOneWayMessage = false;
142:
143:            /* TubelineHelper to assist in resending of messages */
144:            private TubelineHelper tubelineHelper;
145:
146:            /**
147:             * Constructor accepts all possible arguments available in
148:             * <code>PipelineAssembler.createClient</code>.  It may not need all of them.
149:             * TODO It also needs a way to access the Security Pipe.
150:             */
151:            public RMClientTube(WSDLPort port, WSService service,
152:                    WSBinding binding,
153:                    SecureConversationInitiator securityPipe, Tube nextTube) {
154:
155:                super (RMSource.getRMSource(), nextTube);
156:
157:                this .port = port;
158:                this .service = service;
159:                this .binding = binding;
160:                this .securityPipe = securityPipe;
161:
162:                this .config = new SequenceConfig(port, binding);
163:                config.setSoapVersion(binding.getSOAPVersion());
164:
165:                this .messageProcessor = this .provider
166:                        .getInboundMessageProcessor();
167:
168:                if (securityPipe != null) {
169:                    this .secureReliableMessaging = true;
170:                } else {
171:                    this .secureReliableMessaging = false;
172:                }
173:
174:                this .version = config.getRMVersion();
175:                this .unmarshaller = version.createUnmarshaller();
176:                this .marshaller = version.createMarshaller();
177:
178:            }
179:
180:            /**
181:             * Copy constructor used by <code>copy</code> method.
182:             *
183:             * @param toCopy to be copied.
184:             * @param cloner passed as an argument to copy.
185:             */
186:            private RMClientTube(RMClientTube toCopy, TubeCloner cloner) {
187:
188:                super (RMSource.getRMSource(), toCopy, cloner);
189:
190:                if (securityPipe != null) {
191:
192:                    securityPipe = toCopy.securityPipe;
193:                    this .secureReliableMessaging = true;
194:                } else {
195:                    securityPipe = null;
196:                    this .secureReliableMessaging = false;
197:                }
198:
199:                this .port = toCopy.port;
200:                this .service = toCopy.service;
201:                this .binding = toCopy.binding;
202:
203:                this .config = toCopy.config;
204:                this .version = toCopy.version;
205:                this .messageProcessor = this .provider
206:                        .getInboundMessageProcessor();
207:
208:                this .outboundSequence = toCopy.outboundSequence;
209:                this .inboundSequence = toCopy.inboundSequence;
210:                this .unmarshaller = config.getRMVersion().createUnmarshaller();
211:                this .marshaller = config.getRMVersion().createMarshaller();
212:
213:            }
214:
215:            /**
216:             * Perform lazy initialization when the first message is processed. Need to:
217:             * <ul>
218:             * <li>Initialize a SequenceConfig using the metadata parameters passed in the ctor</li>
219:             * <li>Initialize outboundSequence and inboundSequence using the SequenceConfig</li>
220:             * </ul>
221:             *
222:             * @param packet
223:             *      Destination EndpointAddress URI from the request context.  Default to EndpointAddress
224:             *          from WSDLPort if it is missing
225:             */
226:            @SuppressWarnings("unchecked")
227:            private synchronized void initialize(Packet packet)
228:                    throws RMException {
229:
230:                String dest = packet.endpointAddress.toString();
231:
232:                if (outboundSequence != null) {
233:
234:                    //sequence has already been initialized.  We need to
235:                    //make sure that application programmer has not changed
236:                    //the destination for requests by changing the value of
237:                    //the BindingProvider ENDPOINT_ADDRESS_PROPERTY.  This is
238:                    //allowable from the JAX-WS POV, but breaks the RM assumption
239:                    //that sequences exactly correspond to connections between
240:                    //single client instances and endpoints.
241:
242:                    if (dest != null
243:                            && !dest.equals("")
244:                            && outboundSequence.getDestination().toString() != dest) {
245:                        //WSRM2017: The Endpoint Address cannot be changed by a client of an RM-enabled endpoint//
246:                        throw new RMException(
247:                                Messages.UNCHANGEABLE_ENDPOINT_ADDRESS.format());
248:                    }
249:
250:                } else {
251:
252:                    if (binding.getAddressingVersion() == AddressingVersion.MEMBER) {
253:
254:                        //WSRM2008: The Reliable Messaging Client does not support the Member submission addressing version, which is used by the endpoint.//
255:                        throw new RMException(
256:                                Messages.UNSUPPORTED_ADDRESSING_VERSION
257:                                        .format());
258:                    }
259:                    //store this in field
260:                    this .proxy = packet.proxy;
261:
262:                    //make sure we have a destination
263:                    if (dest == null) {
264:                        dest = port.getAddress().toString();
265:                    }
266:
267:                    String acksTo = ProtocolMessageReceiver.getAcksTo();
268:
269:                    //use helper function to speilunk the metadata and find out if the port
270:                    //has a two-way operation.
271:                    boolean twoWay = checkForTwoWayOperation();
272:
273:                    URI destURI;
274:                    URI acksToURI;
275:
276:                    try {
277:                        destURI = new URI(dest);
278:                    } catch (URISyntaxException e) {
279:                        //Invalid destination URI   {0}//
280:                        throw new RMException(Messages.INVALID_DEST_URI
281:                                .format(dest));
282:                    }
283:
284:                    try {
285:                        acksToURI = new URI(acksTo);
286:                    } catch (URISyntaxException e) {
287:                        //Invalid acksTo URI   {0}//
288:                        throw new RMException(Messages.INVALID_ACKS_TO_URI
289:                                .format(acksTo));
290:                    }
291:
292:                    ClientOutboundSequence specifiedOutboundSequence = (ClientOutboundSequence) packet.proxy
293:                            .getRequestContext()
294:                            .get(Constants.sequenceProperty);
295:                    if (specifiedOutboundSequence != null) {
296:                        outboundSequence = specifiedOutboundSequence;
297:                    } else {
298:                        //we need to connect to the back end.
299:                        outboundSequence = new ClientOutboundSequence(config);
300:
301:                        if (secureReliableMessaging) {
302:                            try {
303:                                JAXBElement<SecurityTokenReferenceType> str = securityPipe
304:                                        .startSecureConversation(packet);
305:
306:                                outboundSequence.setSecurityTokenReference(str);
307:                                if (str == null) {
308:                                    //Without this, no security configuration
309:                                    //that does not include SC is allowed.
310:                                    secureReliableMessaging = false;
311:                                }
312:                            } catch (Exception e) {
313:                                secureReliableMessaging = false;
314:                                outboundSequence
315:                                        .setSecurityTokenReference(null);
316:                            }
317:                        }
318:
319:                        outboundSequence
320:                                .setSecureReliableMessaging(secureReliableMessaging);
321:
322:                        outboundSequence
323:                                .registerProtocolMessageSender(new ProtocolMessageSender(
324:                                        messageProcessor, config, marshaller,
325:                                        unmarshaller, port, binding, next,
326:                                        packet));
327:
328:                        outboundSequence.connect(destURI, acksToURI, twoWay);
329:
330:                        inboundSequence = (ClientInboundSequence) outboundSequence
331:                                .getInboundSequence();
332:
333:                        //set a Session object in BindingProvider property allowing user to close
334:                        //the sequence
335:                        ClientSession.setSession(this .proxy, new ClientSession(
336:                                outboundSequence.getId(), this ));
337:
338:                        provider.addOutboundSequence(outboundSequence);
339:
340:                        //if the message in the packet was sent by RMSource.createSequence,
341:                        //put the sequence in a packet property.  The process method, that
342:                        //called us will find it there and return it to the caller.
343:                        String reqUri = packet.getMessage()
344:                                .getPayloadNamespaceURI();
345:                        if (reqUri.equals(Constants.createSequenceNamespace)) {
346:                            packet.invocationProperties.put(
347:                                    Constants.createSequenceProperty,
348:                                    outboundSequence);
349:                        }
350:
351:                        //make this available to the client
352:                        //FIXME - Can this work?
353:                        packet.proxy.getRequestContext().put(
354:                                Constants.sequenceProperty, outboundSequence);
355:
356:                    }
357:                }
358:            }
359:
360:            /**
361:             * Look in the WSDLPort and determine whether it contains any two-way operations.
362:             */
363:            private boolean checkForTwoWayOperation() {
364:
365:                WSDLBoundPortType portType;
366:                if (port == null || null == (portType = port.getBinding())) {
367:
368:                    //no WSDL perhaps? Returning false here means that will be no
369:                    //reverse sequence.  That is the correct behavior.
370:                    return false;
371:                }
372:
373:                for (WSDLBoundOperation op : portType.getBindingOperations()) {
374:                    WSDLOperation operation = op.getOperation();
375:                    if (!operation.isOneWay()) {
376:                        return true;
377:                    }
378:                }
379:
380:                //all operations are one-way
381:                return false;
382:            }
383:
384:            private com.sun.xml.ws.rm.Message prepareRequestMessage(
385:                    Packet request) throws RMException {
386:
387:                com.sun.xml.ws.rm.Message message = null;
388:
389:                //FIXME - Need a better way for client to pass a message number.
390:                Object mn = request.proxy.getRequestContext().get(
391:                        Constants.messageNumberProperty);
392:                if (mn != null) {
393:                    request.invocationProperties.put(
394:                            Constants.messageNumberProperty, mn);
395:                }
396:
397:                //Add to OutboundSequence and include RM headers according to the
398:                //state of the RMSource
399:                message = handleOutboundMessage(outboundSequence, request);
400:
401:                if (!request.getMessage().isOneWay(port)) {
402:                    //ClientOutboundSequence needs to know this.  If this flag is true,
403:                    //messages stored in the sequence cannot be discarded when they are acked.
404:                    //They may need to be resent to provide a vehicle or resends of lost responses.
405:                    //Instead, they are discarded when ClientOutboundSequence.acknowledgeResponse
406:                    //is called by the in RMClientPipe.process when a response is received.
407:
408:                    //The behavior of the retry loop also varies according to whether the message
409:                    //is one-way.  If it is, the retry loop needs wait for acks.  If not, the loop
410:                    //can exit if an application response has been received.
411:                    message.isTwoWayRequest = true;
412:                    this .isOneWayMessage = false;
413:                } else {
414:                    //TODO eliminate one of these flags
415:                    message.isTwoWayRequest = false;
416:                    this .isOneWayMessage = true;
417:                }
418:
419:                //RM would always want expectReply to the true.  We need to look at
420:                //protocol responses for all messages, since they might contain RM
421:                //headers
422:                request.expectReply = true;
423:
424:                //initialize TubelineHelper
425:                tubelineHelper = new TubelineHelper(request, message);
426:
427:                //Make the helper available in the message, so it can be used to resend the message, if necessary
428:                message.setMessageSender(tubelineHelper);
429:
430:                return message;
431:
432:            }
433:
434:            /*
435:             * Set state of message to "complete" when its processing results in an
436:             * unrecoverable failure.
437:             */
438:            private void completeFaultedMessage(
439:                    com.sun.xml.ws.rm.Message message) {
440:
441:                try {
442:                    outboundSequence.acknowledge(message.getMessageNumber());
443:                } catch (RMException e) {
444:                    //TODO log entry
445:                }
446:            }
447:
448:            /* Tube methods */
449:
450:            /**
451:             * Send a Last message and a TerminateSequence message down the pipeline.
452:             */
453:            public synchronized void preDestroy() {
454:                try {
455:                    provider.terminateSequence(outboundSequence);
456:                    next.preDestroy();
457:                } catch (Exception e) {
458:                    //Faulted TerminateSequence message of bug downstream.  We are
459:                    //done with the sequence anyway.  Log and go about our business
460:                    logger.log(Level.FINE,
461:                            //WSRM2007: RMClientPipe threw Exception in preDestroy//
462:                            Messages.UNEXPECTED_PREDESTROY_EXCEPTION.format(),
463:                            e);
464:                }
465:            }
466:
467:            public RMClientTube copy(TubeCloner cloner) {
468:                //Need to prevent copying during the time-consuming process
469:                //of connecting to the endpoint and creating a sequence.  Conveniently, this
470:                //takes place in the <code>initialize</code> method, which needs to be
471:                //synchronized anyway.  Therefore it works to use the synchronized block here.
472:
473:                //TODO - This race condition probably cannot ocurr any more.  If not, remove
474:                //the synchronization
475:                synchronized (this ) {
476:                    return new RMClientTube(this , cloner);
477:                }
478:            }
479:
480:            public @NotNull
481:            NextAction processRequest(Packet request) {
482:
483:                com.sun.xml.ws.rm.Message message = null;
484:
485:                try {
486:
487:                    if (tubelineHelper == null) {
488:                        //First time through here
489:
490:                        //prepare the state of the tube with initialize, etc
491:                        initialize(request);
492:
493:                        //If the request is being sent by RMSource.createSequence, we are done.
494:                        Object seq = request.invocationProperties
495:                                .get(Constants.createSequenceProperty);
496:
497:                        if (seq != null) {
498:                            request.invocationProperties.put(
499:                                    Constants.createSequenceProperty, null);
500:                            request.proxy.getRequestContext().put(
501:                                    Constants.sequenceProperty, seq);
502:                            //TODO..return something reasonable that will not cause disp.invoke
503:                            //to throw an exception here.  Other than that, we don't care about the
504:                            //response message.  We are only interested in the sequence that has been
505:                            //stored in the requestcontext.
506:                            com.sun.xml.ws.api.message.Message mess = com.sun.xml.ws.api.message.Messages
507:                                    .createEmpty(binding.getSOAPVersion());
508:                            request.setMessage(mess);
509:                            doReturnWith(request);
510:                        }
511:
512:                    }
513:
514:                    message = prepareRequestMessage(request);
515:
516:                    //BUGBUG - It is possible for filter to be uninitialized here or have the wrong
517:                    //value.  The initialization should be done here rather than in the RMClientPipe
518:                    //ctor, and there is no reason for it to be a field (at least in the client pipe)
519:                    filter = this .provider.getProcessingFilter();
520:
521:                    if (filter == null
522:                            || filter.handleClientRequestMessage(message)) {
523:
524:                        //reset last activity timer in sequence.
525:                        outboundSequence.resetLastActivityTime();
526:
527:                        tubelineHelper.send();
528:
529:                    }
530:
531:                    return doSuspend();
532:
533:                } catch (RMException e) {
534:
535:                    Message faultMessage = e.getFaultMessage();
536:                    if (faultMessage != null) {
537:                        try {
538:                            Packet ret = new Packet(
539:                                    com.sun.xml.ws.api.message.Messages
540:                                            .create(faultMessage
541:                                                    .readAsSOAPMessage()));
542:                            ret.invocationProperties
543:                                    .putAll(request.invocationProperties);
544:
545:                            return doReturnWith(ret);
546:
547:                        } catch (SOAPException e1) {
548:
549:                            return doThrow(new WebServiceException(e));
550:                        }
551:                    } else {
552:
553:                        return processException(e);
554:                    }
555:
556:                } catch (Throwable ee) {
557:
558:                    logger.log(Level.SEVERE,
559:                    //WSRM2006: Unexpected  Exception in RMClientPipe.process.
560:                            Messages.UNEXPECTED_PROCESS_EXCEPTION.format(), ee);
561:                    return processException(new WebServiceException(ee));
562:                }
563:
564:            }
565:
566:            /**
567:             * Use the default implementation of processReponse.  This will be invoked
568:             * by CompletionCallback in TubelineHelper.
569:             */
570:            public @NotNull
571:            NextAction processResponse(Packet response) {
572:                if (response != null) {
573:                    return doReturnWith(response);
574:                } else if (tubelineHelper != null) {
575:                    return doThrow(tubelineHelper.throwable);
576:                } else {
577:                    throw new IllegalStateException("null Packet in response.");
578:                }
579:            }
580:
581:            /**
582:             * Use default implementation of processException.  It will be:
583:             *
584:             * 1. invoked by CompletionCallback.onCompletion(Throwable) in TubelineHelper 
585:             * in the event that the Exception is on that needs to be returned to application
586:             * 2. Exceptions caught in initialize() and prepareRequest()
587:             */
588:            public @NotNull
589:            NextAction processException(Throwable t) {
590:
591:                if (!(t instanceof  WebServiceException)) {
592:
593:                    t = new WebServiceException(t);
594:                }
595:
596:                return doThrow(t);
597:            }
598:
599:            /* Inner classes */
600:
601:            /**
602:             * ApplicationMessageHelper is used to execute a single request in the tail of the
603:             * Tubeline.  
604:             */
605:            public class TubelineHelper implements  MessageSender {
606:
607:                private final Fiber fiber;
608:                private final Fiber parentFiber;
609:                private final TubelineHelperCallback callback;
610:
611:                //Store the request packet and message for this helper.
612:                private Packet packet;
613:                private com.sun.xml.ws.rm.Message message;
614:
615:                public Throwable throwable;
616:                private boolean sent;
617:
618:                public TubelineHelper(Packet packet,
619:                        com.sun.xml.ws.rm.Message message) {
620:
621:                    this .message = message;
622:                    this .packet = packet;
623:                    this .sent = false;
624:
625:                    parentFiber = Fiber.current();
626:                    if (parentFiber == null) {
627:                        throw new IllegalStateException("No current fiber.");
628:                    }
629:
630:                    Engine engine = parentFiber.owner;
631:
632:                    fiber = engine.createFiber();
633:                    callback = new TubelineHelperCallback();
634:                    throwable = null;
635:                };
636:
637:                public void send() {
638:
639:                    message.setIsBusy(true);
640:
641:                    if (packet == null) {
642:                        throw new IllegalStateException(
643:                                "Request not set in TubelineHelper");
644:                    }
645:
646:                    //use a copy of the original message
647:                    com.sun.xml.ws.api.message.Message copy = message.getCopy();
648:                    packet.setMessage(copy);
649:                    fiber.start(TubeCloner.clone(next), packet, callback);
650:
651:                }
652:
653:                private class TubelineHelperCallback implements 
654:                        Fiber.CompletionCallback {
655:
656:                    TubelineHelperCallback() {
657:                    }
658:
659:                    public void onCompletion(@NotNull
660:                    Packet response) {
661:
662:                        try {
663:                            if (response != null) {
664:
665:                                //Perform operations in the RMSource according to the contents of
666:                                //the RM Headers on the incoming message.
667:                                Message mess = response.getMessage();
668:                                com.sun.xml.ws.rm.Message rmMessage = null;
669:
670:                                if (mess != null) {
671:                                    rmMessage = handleInboundMessage(response);
672:                                }
673:
674:                                //if a diagnostic / debugging filter has been set, allow it to inspect
675:                                //the response message.
676:                                if (filter != null) {
677:                                    filter
678:                                            .handleClientResponseMessage(rmMessage);
679:                                }
680:
681:                                if (mess != null && mess.isFault()) {
682:                                    //don't want to resend
683:                                    logger
684:                                            .log(
685:                                                    Level.FINE,
686:                                                    //WSRM2004: Marking faulted message {0} as acked.
687:                                                    Messages.ACKING_FAULTED_MESSAGE
688:                                                            .format(message
689:                                                                    .getMessageNumber()));
690:                                    outboundSequence.acknowledge(message
691:                                            .getMessageNumber());
692:                                }
693:
694:                                //check for empty body response to two-way message.  WCF will return
695:                                //one when it drops the request message.  In this case we also need to retry.
696:
697:                                if (mess != null
698:                                        && !isOneWayMessage
699:                                        && mess.getPayloadNamespaceURI() == null) {
700:                                    //resend
701:                                    logger.log(Level.FINE,
702:                                    //WSRM2005: Queuing dropped message for resend.
703:                                            Messages.RESENDING_DROPPED_MESSAGE
704:                                                    .format());
705:                                    return;
706:                                }
707:
708:                                //If a response to a two-way operation has been received, it is
709:                                //time to release the request being retained on the OutboundSequence.
710:                                //This will also result in the state of the message being set to
711:                                //"complete" so the retry loop will exit.
712:                                if (message.isTwoWayRequest) {
713:                                    outboundSequence
714:                                            .acknowledgeResponse(message
715:                                                    .getMessageNumber());
716:                                }
717:
718:                            }
719:
720:                            //invoke the rest of the pipeline
721:                            parentFiber.resume(response);
722:
723:                        } catch (Exception e) {
724:                            onCompletion(e);
725:                        } finally {
726:                            message.setIsBusy(false);
727:                        }
728:
729:                    }
730:
731:                    public void onCompletion(@NotNull
732:                    Throwable t) {
733:
734:                        throwable = t;
735:
736:                        try {
737:                            if (t instanceof  ClientTransportException) {
738:                                //resend in this case
739:                                if (logger.isLoggable(Level.FINE)) {
740:                                    logger.log(Level.FINE,
741:                                    //WSRM2000: Sending message caused {0}. Queuing for resend.
742:                                            Messages.QUEUE_FOR_RESEND.format(t
743:                                                    .toString()));
744:                                }
745:                                return;
746:
747:                            } else if (t instanceof  WebServiceException) {
748:
749:                                //Unwrap exception and see if it makes sense to retry this
750:                                //request.
751:                                Throwable cause = t.getCause();
752:
753:                                if (cause != null
754:                                        && (cause instanceof  IOException || cause instanceof  SocketTimeoutException)) {
755:                                    if (logger.isLoggable(Level.FINE)) {
756:                                        //Sending message caused {0}. Queuing for resend.//
757:                                        logger.log(Level.FINE,
758:                                                //WSRM2000: Sending message caused {0}. Queuing for resend.//
759:                                                Messages.QUEUE_FOR_RESEND
760:                                                        .format(t.toString()),
761:                                                t);
762:                                    }
763:
764:                                    //Simply return. Maintenance thread will invoke send() until
765:                                    //we get a normal
766:                                    return;
767:
768:                                } else {
769:                                    //non-transport-related Exception;
770:                                    logger
771:                                            .log(
772:                                                    Level.SEVERE,
773:                                                    //WSRM2003: Unexpected exception  wrapped in WSException.//
774:                                                    Messages.UNEXPECTED_WRAPPED_EXCEPTION
775:                                                            .format(), t);
776:                                    completeFaultedMessage(message);
777:                                    //TODO - need to propogate exception back to client here 
778:                                    parentFiber.resume(null);
779:                                }
780:                            } else {
781:                                //Bug in software somewhere..  Any RuntimeException here must be a 
782:                                //WebServiceException
783:                                logger.log(Level.SEVERE,
784:                                //  WSRM2001: Unexpected exception in trySend.//
785:                                        Messages.UNEXPECTED_TRY_SEND_EXCEPTION
786:                                                .format(), t);
787:
788:                                //TODO - need to propogate exception back to client 
789:                                parentFiber.resume(null);
790:                            }
791:                        } finally {
792:                            message.setIsBusy(false);
793:                        }
794:                    }
795:                };
796:            }
797:
798:        }
w___w___w_._j_a___va2s_._com__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.