/** * @param message * @param endpoint * @param to * @return */ protected Conduit buildConduit( SoapMessage message, final Endpoint endpoint, AttributedURIType to) { Conduit c; final String address = to.getValue(); ConduitSelector cs = new DeferredConduitSelector() { @Override public synchronized Conduit selectConduit(Message message) { Conduit conduit = null; EndpointInfo endpointInfo = endpoint.getEndpointInfo(); EndpointReferenceType original = endpointInfo.getTarget(); try { if (null != address) { endpointInfo.setAddress(address); } conduit = super.selectConduit(message); } finally { endpointInfo.setAddress(original); } return conduit; } }; cs.setEndpoint(endpoint); c = cs.selectConduit(message); // REVISIT // use application endpoint message observer instead? c.setMessageObserver( new MessageObserver() { public void onMessage(Message message) { LOG.fine("Ignoring response to resent message."); } }); message.getExchange().setConduit(c); return c; }
/** * Add MAPs which are specific to the requestor or responder role. * * @param maps the MAPs being assembled * @param message the current message * @param isRequestor true iff the current messaging role is that of requestor * @param isFault true if a fault is being mediated */ private void addRoleSpecific( AddressingProperties maps, Message message, boolean isRequestor, boolean isFault) { if (isRequestor) { Exchange exchange = message.getExchange(); // add request-specific MAPs boolean isOneway = exchange.isOneWay(); boolean isOutbound = ContextUtils.isOutbound(message); // To if (maps.getTo() == null) { Conduit conduit = null; if (isOutbound) { conduit = ContextUtils.getConduit(null, message); } String s = (String) message.get(Message.ENDPOINT_ADDRESS); EndpointReferenceType reference = conduit != null ? conduit.getTarget() : ContextUtils.getNoneEndpointReference(); if (conduit != null && !StringUtils.isEmpty(s) && !reference.getAddress().getValue().equals(s)) { EndpointReferenceType ref = new EndpointReferenceType(); AttributedURIType tp = new AttributedURIType(); tp.setValue(s); ref.setAddress(tp); ref.setMetadata(reference.getMetadata()); ref.setReferenceParameters(reference.getReferenceParameters()); ref.getOtherAttributes().putAll(reference.getOtherAttributes()); reference = ref; } maps.setTo(reference); } // ReplyTo, set if null in MAPs or if set to a generic address // (anonymous or none) that may not be appropriate for the // current invocation EndpointReferenceType replyTo = maps.getReplyTo(); if (ContextUtils.isGenericAddress(replyTo)) { replyTo = getReplyTo(message, replyTo); if (replyTo == null || (isOneway && (replyTo == null || replyTo.getAddress() == null || !Names.WSA_NONE_ADDRESS.equals(replyTo.getAddress().getValue())))) { AttributedURIType address = ContextUtils.getAttributedURI( isOneway ? Names.WSA_NONE_ADDRESS : Names.WSA_ANONYMOUS_ADDRESS); replyTo = ContextUtils.WSA_OBJECT_FACTORY.createEndpointReferenceType(); replyTo.setAddress(address); } maps.setReplyTo(replyTo); } // FaultTo if (maps.getFaultTo() == null) { maps.setFaultTo(maps.getReplyTo()); } else if (maps.getFaultTo().getAddress() == null) { maps.setFaultTo(null); } } else { // add response-specific MAPs AddressingProperties inMAPs = getMAPs(message, false, false); maps.exposeAs(inMAPs.getNamespaceURI()); // To taken from ReplyTo or FaultTo in incoming MAPs (depending // on the fault status of the response) if (isFault && inMAPs.getFaultTo() != null) { maps.setTo(inMAPs.getFaultTo()); } else if (maps.getTo() == null && inMAPs.getReplyTo() != null) { maps.setTo(inMAPs.getReplyTo()); } // RelatesTo taken from MessageID in incoming MAPs if (inMAPs.getMessageID() != null && !Boolean.TRUE.equals(message.get(Message.PARTIAL_RESPONSE_MESSAGE))) { String inMessageID = inMAPs.getMessageID().getValue(); maps.setRelatesTo(ContextUtils.getRelatesTo(inMessageID)); } else { maps.setRelatesTo(ContextUtils.getRelatesTo(Names.WSA_UNSPECIFIED_RELATIONSHIP)); } // fallback fault action if (isFault && maps.getAction() == null) { maps.setAction(ContextUtils.getAttributedURI(Names.WSA_DEFAULT_FAULT_ACTION)); } if (isFault && !ContextUtils.isGenericAddress(inMAPs.getFaultTo())) { Message m = message.getExchange().getInFaultMessage(); if (m == null) { m = message; } InternalContextUtils.rebaseResponse(inMAPs.getFaultTo(), inMAPs, m); Destination destination = InternalContextUtils.createDecoupledDestination(m.getExchange(), inMAPs.getFaultTo()); m.getExchange().setDestination(destination); } } }
private void doResend(SoapMessage message) { try { // initialize copied interceptor chain for message PhaseInterceptorChain retransmitChain = manager.getRetransmitChain(message); ProtocolVariation protocol = RMContextUtils.getProtocolVariation(message); Endpoint endpoint = manager.getReliableEndpoint(message).getEndpoint(protocol); PhaseChainCache cache = new PhaseChainCache(); boolean after = true; if (retransmitChain == null) { // no saved retransmit chain, so construct one from scratch (won't work for WS-Security on // server, so // need to fix) retransmitChain = buildRetransmitChain(endpoint, cache); after = false; } message.setInterceptorChain(retransmitChain); // clear flag for SOAP out interceptor so envelope will be written message.remove(SoapOutInterceptor.WROTE_ENVELOPE_START); // discard all saved content Set<Class<?>> formats = message.getContentFormats(); List<CachedOutputStreamCallback> callbacks = null; for (Class<?> clas : formats) { Object content = message.getContent(clas); if (content != null) { LOG.info( "Removing " + clas.getName() + " content of actual type " + content.getClass().getName()); message.removeContent(clas); if (clas == OutputStream.class && content instanceof WriteOnCloseOutputStream) { callbacks = ((WriteOnCloseOutputStream) content).getCallbacks(); } } } // read SOAP headers from saved input stream RewindableInputStream is = (RewindableInputStream) message.get(RMMessageConstants.SAVED_CONTENT); is.rewind(); XMLStreamReader reader = StaxUtils.createXMLStreamReader(is, "UTF-8"); message.getHeaders().clear(); if (reader.getEventType() != XMLStreamConstants.START_ELEMENT && reader.nextTag() != XMLStreamConstants.START_ELEMENT) { throw new IllegalStateException("No document found"); } readHeaders(reader, message); int event; while ((event = reader.nextTag()) != XMLStreamConstants.START_ELEMENT) { if (event == XMLStreamConstants.END_ELEMENT) { throw new IllegalStateException("No body content present"); } } // set message addressing properties AddressingProperties maps = new MAPCodec().unmarshalMAPs(message); RMContextUtils.storeMAPs(maps, message, true, MessageUtils.isRequestor(message)); AttributedURIType to = null; if (null != maps) { to = maps.getTo(); } if (null == to) { LOG.log(Level.SEVERE, "NO_ADDRESS_FOR_RESEND_MSG"); return; } if (RMUtils.getAddressingConstants().getAnonymousURI().equals(to.getValue())) { LOG.log(Level.FINE, "Cannot resend to anonymous target"); return; } // initialize conduit for new message Conduit c = message.getExchange().getConduit(message); if (c == null) { c = buildConduit(message, endpoint, to); } c.prepare(message); // replace standard message marshaling with copy from saved stream ListIterator<Interceptor<? extends Message>> iterator = retransmitChain.getIterator(); while (iterator.hasNext()) { Interceptor<? extends Message> incept = iterator.next(); // remove JAX-WS interceptors which handle message modes and such if (incept.getClass().getName().startsWith("org.apache.cxf.jaxws.interceptors")) { retransmitChain.remove(incept); } else if (incept instanceof PhaseInterceptor && (((PhaseInterceptor<?>) incept).getPhase() == Phase.MARSHAL)) { // remove any interceptors from the marshal phase retransmitChain.remove(incept); } } retransmitChain.add(new CopyOutInterceptor(reader)); // restore callbacks on output stream if (callbacks != null) { OutputStream os = message.getContent(OutputStream.class); if (os != null) { WriteOnCloseOutputStream woc; if (os instanceof WriteOnCloseOutputStream) { woc = (WriteOnCloseOutputStream) os; } else { woc = new WriteOnCloseOutputStream(os); message.setContent(OutputStream.class, woc); } for (CachedOutputStreamCallback cb : callbacks) { woc.registerCallback(cb); } } } // send the message message.put(RMMessageConstants.RM_RETRANSMISSION, Boolean.TRUE); if (after) { retransmitChain.doInterceptStartingAfter(message, RMCaptureOutInterceptor.class.getName()); } else { retransmitChain.doIntercept(message); } if (LOG.isLoggable(Level.INFO)) { RMProperties rmps = RMContextUtils.retrieveRMProperties(message, true); SequenceType seq = rmps.getSequence(); LOG.log( Level.INFO, "Retransmitted message " + seq.getMessageNumber() + " in sequence " + seq.getIdentifier().getValue()); rmps = new RMProperties(); } } catch (Exception ex) { LOG.log(Level.SEVERE, "RESEND_FAILED_MSG", ex); } }