/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.cxf.ws.rm; import java.io.Closeable; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Timer; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; import javax.management.JMException; import javax.xml.namespace.QName; import org.apache.cxf.Bus; import org.apache.cxf.binding.Binding; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.endpoint.Client; import org.apache.cxf.endpoint.ClientLifeCycleListener; import org.apache.cxf.endpoint.ClientLifeCycleManager; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.endpoint.Server; import org.apache.cxf.endpoint.ServerLifeCycleListener; import org.apache.cxf.endpoint.ServerLifeCycleManager; import org.apache.cxf.management.InstrumentationManager; import org.apache.cxf.message.Exchange; import org.apache.cxf.message.ExchangeImpl; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageImpl; import org.apache.cxf.phase.PhaseInterceptorChain; import org.apache.cxf.service.Service; import org.apache.cxf.service.model.BindingInfo; import org.apache.cxf.service.model.InterfaceInfo; import org.apache.cxf.service.model.ServiceInfo; import org.apache.cxf.transport.Conduit; import org.apache.cxf.ws.addressing.AddressingProperties; import org.apache.cxf.ws.addressing.ContextUtils; import org.apache.cxf.ws.addressing.EndpointReferenceType; import org.apache.cxf.ws.addressing.MAPAggregator; import org.apache.cxf.ws.addressing.RelatesToType; import org.apache.cxf.ws.rm.RMConfiguration.DeliveryAssurance; import org.apache.cxf.ws.rm.manager.AcksPolicyType; import org.apache.cxf.ws.rm.manager.DeliveryAssuranceType; import org.apache.cxf.ws.rm.manager.DestinationPolicyType; import org.apache.cxf.ws.rm.manager.RM10AddressingNamespaceType; import org.apache.cxf.ws.rm.manager.SequenceTerminationPolicyType; import org.apache.cxf.ws.rm.manager.SourcePolicyType; import org.apache.cxf.ws.rm.persistence.PersistenceUtils; import org.apache.cxf.ws.rm.persistence.RMMessage; import org.apache.cxf.ws.rm.persistence.RMStore; import org.apache.cxf.ws.rm.policy.RMPolicyUtilities; import org.apache.cxf.ws.rm.soap.RedeliveryQueueImpl; import org.apache.cxf.ws.rm.soap.RetransmissionQueueImpl; import org.apache.cxf.ws.rm.soap.SoapFaultFactory; import org.apache.cxf.ws.rm.v200702.CloseSequenceType; import org.apache.cxf.ws.rm.v200702.CreateSequenceResponseType; import org.apache.cxf.ws.rm.v200702.Identifier; import org.apache.cxf.ws.rm.v200702.SequenceType; import org.apache.cxf.ws.security.SecurityConstants; /** * */ public class RMManager { /** Message contextual property giving WS-ReliableMessaging namespace. */ public static final String WSRM_VERSION_PROPERTY = "org.apache.cxf.ws.rm.namespace"; /** Message contextual property giving addressing namespace to be used by WS-RM implementation. */ public static final String WSRM_WSA_VERSION_PROPERTY = "org.apache.cxf.ws.rm.wsa-namespace"; /** Message contextual property giving the last message flag (Boolean). */ public static final String WSRM_LAST_MESSAGE_PROPERTY = "org.apache.cxf.ws.rm.last-message"; /** Message contextual property giving WS-ReliableMessaging inactivity timeout (Long). */ public static final String WSRM_INACTIVITY_TIMEOUT_PROPERTY = "org.apache.cxf.ws.rm.inactivity-timeout"; /** Message contextual property giving WS-ReliableMessaging base retransmission interval (Long). */ public static final String WSRM_RETRANSMISSION_INTERVAL_PROPERTY = "org.apache.cxf.ws.rm.retransmission-interval"; /** Message contextual property giving WS-ReliableMessaging exponential backoff flag (Boolean). */ public static final String WSRM_EXPONENTIAL_BACKOFF_PROPERTY = "org.apache.cxf.ws.rm.exponential-backoff"; /** Message contextual property giving WS-ReliableMessaging acknowledgement interval (Long). */ public static final String WSRM_ACKNOWLEDGEMENT_INTERVAL_PROPERTY = "org.apache.cxf.ws.rm.acknowledgement-interval"; private static final Logger LOG = LogUtils.getL7dLogger(RMManager.class); private static final String WSRM_RETRANSMIT_CHAIN = RMManager.class.getName() + ".retransmitChain"; private Bus bus; private RMStore store; private SequenceIdentifierGenerator idGenerator; private RetransmissionQueue retransmissionQueue; private RedeliveryQueue redeliveryQueue; private Map<Endpoint, RMEndpoint> reliableEndpoints = new ConcurrentHashMap<Endpoint, RMEndpoint>(); private AtomicReference<Timer> timer = new AtomicReference<Timer>(); private RMConfiguration configuration; private SourcePolicyType sourcePolicy; private DestinationPolicyType destinationPolicy; private InstrumentationManager instrumentationManager; private ManagedRMManager managedManager; // ServerLifeCycleListener public void startServer(Server server) { recoverReliableEndpoint(server.getEndpoint(), (Conduit)null); } public void stopServer(Server server) { } // ClientLifeCycleListener public void clientCreated(final Client client) { if (null == store || null == retransmissionQueue) { return; } String id = RMUtils.getEndpointIdentifier(client.getEndpoint(), getBus()); Collection<SourceSequence> sss = store.getSourceSequences(id/*, protocol*/); if (null == sss || 0 == sss.size()) { return; } LOG.log(Level.FINE, "Number of source sequences: {0}", sss.size()); recoverReliableEndpoint(client.getEndpoint(), client.getConduit()/*, protocol*/); } public void clientDestroyed(Client client) { } // Configuration public void setRMNamespace(String uri) { getConfiguration().setRMNamespace(uri); } public void setRM10AddressingNamespace(RM10AddressingNamespaceType addrns) { getConfiguration().setRM10AddressingNamespace(addrns.getUri()); } public Bus getBus() { return bus; } @Resource public void setBus(Bus b) { bus = b; if (null != bus) { bus.setExtension(this, RMManager.class); } } public RMStore getStore() { return store; } public void setStore(RMStore s) { store = s; } public RetransmissionQueue getRetransmissionQueue() { return retransmissionQueue; } public void setRetransmissionQueue(RetransmissionQueue rq) { retransmissionQueue = rq; } public RedeliveryQueue getRedeliveryQueue() { return redeliveryQueue; } public void setRedeliveryQueue(RedeliveryQueue redeliveryQueue) { this.redeliveryQueue = redeliveryQueue; } public SequenceIdentifierGenerator getIdGenerator() { return idGenerator; } public void setIdGenerator(SequenceIdentifierGenerator generator) { idGenerator = generator; } private Timer getTimer(boolean create) { Timer ret = timer.get(); if (ret == null && create) { Timer newt = new Timer("RMManager-Timer-" + System.identityHashCode(this), true); if (!timer.compareAndSet(null, newt)) { newt.cancel(); } } return timer.get(); } public Timer getTimer() { return getTimer(true); } public BindingFaultFactory getBindingFaultFactory(Binding binding) { return new SoapFaultFactory(binding); } /** * @param dat The deliveryAssurance to set. */ public void setDeliveryAssurance(DeliveryAssuranceType dat) { RMConfiguration cfg = getConfiguration(); cfg.setInOrder(dat.isSetInOrder()); DeliveryAssurance da = null; if (dat.isSetExactlyOnce() || (dat.isSetAtLeastOnce() && dat.isSetAtMostOnce())) { da = DeliveryAssurance.EXACTLY_ONCE; } else if (dat.isSetAtLeastOnce()) { da = DeliveryAssurance.AT_LEAST_ONCE; } else if (dat.isSetAtMostOnce()) { da = DeliveryAssurance.AT_MOST_ONCE; } cfg.setDeliveryAssurance(da); } /** * @return Returns the destinationPolicy. */ public DestinationPolicyType getDestinationPolicy() { return destinationPolicy; } /** * @param destinationPolicy The destinationPolicy to set. */ public void setDestinationPolicy(DestinationPolicyType destinationPolicy) { this.destinationPolicy = destinationPolicy; } /** * Get base configuration for manager. This needs to be modified by endpoint policies to get the effective * configuration. * @return configuration (non-<code>null</code>) */ public RMConfiguration getConfiguration() { if (configuration == null) { setConfiguration(new RMConfiguration()); } return configuration; } /** * @param configuration (non-<code>null</code>) */ public void setConfiguration(RMConfiguration configuration) { if (configuration.getBaseRetransmissionInterval() == null) { Long value = Long.valueOf(RetransmissionQueue.DEFAULT_BASE_RETRANSMISSION_INTERVAL); configuration.setBaseRetransmissionInterval(value); } if (configuration.getRMNamespace() == null) { configuration.setRMNamespace(RM10Constants.NAMESPACE_URI); } this.configuration = configuration; } /** * Get configuration after applying policies. * * @param msg * @return configuration (non-<code>null</code>) */ public RMConfiguration getEffectiveConfiguration(Message msg) { return RMPolicyUtilities.getRMConfiguration(getConfiguration(), msg); } /** * @param rma The rmAssertion to set. */ public void setRMAssertion(org.apache.cxf.ws.rmp.v200502.RMAssertion rma) { setConfiguration(RMPolicyUtilities.intersect(rma, getConfiguration())); } /** * @return Returns the sourcePolicy. */ public SourcePolicyType getSourcePolicy() { return sourcePolicy; } /** * @param sp The sourcePolicy to set. */ public void setSourcePolicy(SourcePolicyType sp) { if (null == sp) { sp = new SourcePolicyType(); } if (sp.getSequenceTerminationPolicy() == null) { SequenceTerminationPolicyType term = new SequenceTerminationPolicyType(); term.setTerminateOnShutdown(true); sp.setSequenceTerminationPolicy(term); } sourcePolicy = sp; } // The real stuff ... public RMEndpoint getReliableEndpoint(Message message) throws RMException { Endpoint endpoint = message.getExchange().getEndpoint(); QName name = endpoint.getEndpointInfo().getName(); if (LOG.isLoggable(Level.FINE)) { LOG.fine("Getting RMEndpoint for endpoint with info: " + name); } if (name.equals(RM10Constants.PORT_NAME) || name.equals(RM11Constants.PORT_NAME)) { WrappedEndpoint wrappedEndpoint = (WrappedEndpoint)endpoint; endpoint = wrappedEndpoint.getWrappedEndpoint(); } String rmUri = (String)message.getContextualProperty(WSRM_VERSION_PROPERTY); if (rmUri == null) { RMProperties rmps = RMContextUtils.retrieveRMProperties(message, false); if (rmps != null) { rmUri = rmps.getNamespaceURI(); } } String addrUri = (String)message.getContextualProperty(WSRM_WSA_VERSION_PROPERTY); if (addrUri == null) { AddressingProperties maps = ContextUtils.retrieveMAPs(message, false, false, false); if (maps != null) { addrUri = maps.getNamespaceURI(); } } RMConfiguration config = getConfiguration(); if (rmUri != null) { config.setRMNamespace(rmUri); ProtocolVariation protocol = ProtocolVariation.findVariant(rmUri, addrUri); if (protocol == null) { org.apache.cxf.common.i18n.Message msg = new org.apache.cxf.common.i18n.Message( "UNSUPPORTED_NAMESPACE", LOG, addrUri, rmUri); LOG.log(Level.INFO, msg.toString()); throw new RMException(msg); } } if (addrUri != null) { config.setRM10AddressingNamespace(addrUri); } Long timeout = (Long)message.getContextualProperty(WSRM_INACTIVITY_TIMEOUT_PROPERTY); if (timeout != null) { config.setInactivityTimeout(timeout); } Long interval = (Long)message.getContextualProperty(WSRM_RETRANSMISSION_INTERVAL_PROPERTY); if (interval != null) { config.setBaseRetransmissionInterval(interval); } Boolean exponential = (Boolean)message.getContextualProperty(WSRM_EXPONENTIAL_BACKOFF_PROPERTY); if (exponential != null) { config.setExponentialBackoff(exponential); } interval = (Long)message.getContextualProperty(WSRM_ACKNOWLEDGEMENT_INTERVAL_PROPERTY); if (interval != null) { config.setAcknowledgementInterval(interval); } RMEndpoint rme = reliableEndpoints.get(endpoint); if (null == rme) { synchronized (endpoint) { rme = reliableEndpoints.get(endpoint); if (rme != null) { return rme; } rme = createReliableEndpoint(endpoint); org.apache.cxf.transport.Destination destination = message.getExchange().getDestination(); EndpointReferenceType replyTo = null; if (null != destination) { AddressingProperties maps = RMContextUtils.retrieveMAPs(message, false, false); replyTo = maps.getReplyTo(); } Endpoint ei = message.getExchange().getEndpoint(); org.apache.cxf.transport.Destination dest = ei == null ? null : ei.getEndpointInfo() .getProperty(MAPAggregator.DECOUPLED_DESTINATION, org.apache.cxf.transport.Destination.class); config = RMPolicyUtilities.getRMConfiguration(config, message); rme.initialise(config, message.getExchange().getConduit(message), replyTo, dest, message); reliableEndpoints.put(endpoint, rme); LOG.fine("Created new RMEndpoint."); } } return rme; } public RMEndpoint findReliableEndpoint(QName qn) { for (RMEndpoint rpe : reliableEndpoints.values()) { if (qn.equals(rpe.getApplicationEndpoint().getService().getName())) { return rpe; } } return null; } public Destination getDestination(Message message) throws RMException { RMEndpoint rme = getReliableEndpoint(message); if (null != rme) { return rme.getDestination(); } return null; } public Source getSource(Message message) throws RMException { RMEndpoint rme = getReliableEndpoint(message); if (null != rme) { return rme.getSource(); } return null; } public SourceSequence getSequence(Identifier inSeqId, Message message, AddressingProperties maps) throws RMException { Source source = getSource(message); SourceSequence seq = source.getCurrent(inSeqId); RMConfiguration config = getEffectiveConfiguration(message); if (null == seq || seq.isExpired()) { // TODO: better error handling EndpointReferenceType to = null; boolean isServer = RMContextUtils.isServerSide(message); EndpointReferenceType acksTo = null; RelatesToType relatesTo = null; if (isServer) { AddressingProperties inMaps = RMContextUtils.retrieveMAPs(message, false, false); inMaps.exposeAs(config.getAddressingNamespace()); acksTo = RMUtils.createReference(inMaps.getTo().getValue()); to = inMaps.getReplyTo(); source.getReliableEndpoint().getServant().setUnattachedIdentifier(inSeqId); relatesTo = (new org.apache.cxf.ws.addressing.ObjectFactory()).createRelatesToType(); Destination destination = getDestination(message); DestinationSequence inSeq = inSeqId == null ? null : destination.getSequence(inSeqId); relatesTo.setValue(inSeq != null ? inSeq.getCorrelationID() : null); } else { to = RMUtils.createReference(maps.getTo().getValue()); acksTo = maps.getReplyTo(); if (RMUtils.getAddressingConstants().getNoneURI().equals(acksTo.getAddress().getValue())) { Endpoint ei = message.getExchange().getEndpoint(); org.apache.cxf.transport.Destination dest = ei == null ? null : ei.getEndpointInfo() .getProperty(MAPAggregator.DECOUPLED_DESTINATION, org.apache.cxf.transport.Destination.class); if (null == dest) { acksTo = RMUtils.createAnonymousReference(); } else { acksTo = dest.getAddress(); } } } if (ContextUtils.isGenericAddress(to)) { org.apache.cxf.common.i18n.Message msg = new org.apache.cxf.common.i18n.Message( "CREATE_SEQ_ANON_TARGET", LOG, to != null && to.getAddress() != null ? to.getAddress().getValue() : null); LOG.log(Level.INFO, msg.toString()); throw new RMException(msg); } Proxy proxy = source.getReliableEndpoint().getProxy(); ProtocolVariation protocol = config.getProtocolVariation(); Exchange exchange = new ExchangeImpl(); Map<String, Object> context = new HashMap<>(16); for (String key : message.getContextualPropertyKeys()) { //copy other properties? if (key.startsWith("ws-security") || key.startsWith("security.")) { context.put(key, message.getContextualProperty(key)); } } CreateSequenceResponseType createResponse = proxy.createSequence(acksTo, relatesTo, isServer, protocol, exchange, context); if (!isServer) { Servant servant = source.getReliableEndpoint().getServant(); servant.createSequenceResponse(createResponse, protocol); // propagate security properties to application endpoint, in case we're using WS-SecureConversation Exchange appex = message.getExchange(); if (appex.get(SecurityConstants.TOKEN) == null) { appex.put(SecurityConstants.TOKEN, exchange.get(SecurityConstants.TOKEN)); appex.put(SecurityConstants.TOKEN_ID, exchange.get(SecurityConstants.TOKEN_ID)); } } seq = source.awaitCurrent(inSeqId); seq.setTarget(to); } return seq; } @PreDestroy public void shutdown() { // shutdown remaining endpoints if (!reliableEndpoints.isEmpty()) { LOG.log(Level.FINE, "Shutting down RMManager with {0} remaining endpoints.", new Object[] {Integer.valueOf(reliableEndpoints.size())}); for (RMEndpoint rme : reliableEndpoints.values()) { rme.shutdown(); } } // remove references to timer tasks cancelled above to make them // eligible for garbage collection Timer t = getTimer(false); if (t != null) { t.purge(); t.cancel(); } // unregistring of this managed bean from the server is done by the bus itself } void shutdownReliableEndpoint(Endpoint e) { RMEndpoint rme = reliableEndpoints.get(e); if (rme == null) { // not found return; } rme.shutdown(); // remove references to timer tasks cancelled above to make them // eligible for garbage collection Timer t = getTimer(false); if (t != null) { t.purge(); } reliableEndpoints.remove(e); } void recoverReliableEndpoint(Endpoint endpoint, Conduit conduit) { if (null == store || null == retransmissionQueue) { return; } String id = RMUtils.getEndpointIdentifier(endpoint, getBus()); Collection<SourceSequence> sss = store.getSourceSequences(id); Collection<DestinationSequence> dss = store.getDestinationSequences(id); if ((null == sss || 0 == sss.size()) && (null == dss || 0 == dss.size())) { return; } LOG.log(Level.FINE, "Number of source sequences: {0}", sss.size()); LOG.log(Level.FINE, "Number of destination sequences: {0}", dss.size()); LOG.log(Level.FINE, "Recovering {0} endpoint with id: {1}", new Object[] {null == conduit ? "client" : "server", id}); RMEndpoint rme = createReliableEndpoint(endpoint); rme.initialise(getConfiguration(), conduit, null, null, null); synchronized (reliableEndpoints) { reliableEndpoints.put(endpoint, rme); } for (SourceSequence ss : sss) { recoverSourceSequence(endpoint, conduit, rme.getSource(), ss); } for (DestinationSequence ds : dss) { recoverDestinationSequence(endpoint, conduit, rme.getDestination(), ds); } retransmissionQueue.start(); redeliveryQueue.start(); } private void recoverSourceSequence(Endpoint endpoint, Conduit conduit, Source s, SourceSequence ss) { Collection<RMMessage> ms = store.getMessages(ss.getIdentifier(), true); if (null == ms || 0 == ms.size()) { store.removeSourceSequence(ss.getIdentifier()); return; } LOG.log(Level.FINE, "Number of messages in sequence: {0}", ms.size()); // only recover the sequence if there are pending messages s.addSequence(ss, false); // choosing an arbitrary valid source sequence as the current source sequence if (s.getAssociatedSequence(null) == null && !ss.isExpired() && !ss.isLastMessage()) { s.setCurrent(ss); } for (RMMessage m : ms) { Message message = new MessageImpl(); Exchange exchange = new ExchangeImpl(); message.setExchange(exchange); exchange.setOutMessage(message); if (null != conduit) { exchange.setConduit(conduit); message.put(Message.REQUESTOR_ROLE, Boolean.TRUE); } exchange.put(Endpoint.class, endpoint); exchange.put(Service.class, endpoint.getService()); exchange.put(Binding.class, endpoint.getBinding()); exchange.put(Bus.class, bus); SequenceType st = new SequenceType(); st.setIdentifier(ss.getIdentifier()); st.setMessageNumber(m.getMessageNumber()); RMProperties rmps = new RMProperties(); rmps.setSequence(st); rmps.setCreatedTime(m.getCreatedTime()); rmps.exposeAs(ss.getProtocol().getWSRMNamespace()); if (ss.isLastMessage() && ss.getCurrentMessageNr() == m.getMessageNumber()) { CloseSequenceType close = new CloseSequenceType(); close.setIdentifier(ss.getIdentifier()); rmps.setCloseSequence(close); } RMContextUtils.storeRMProperties(message, rmps, true); if (null == conduit) { String to = m.getTo(); AddressingProperties maps = new AddressingProperties(); maps.setTo(RMUtils.createReference(to)); RMContextUtils.storeMAPs(maps, message, true, false); } try { // RMMessage is stored in a serialized way, therefore // RMMessage content must be splitted into soap root message // and attachments PersistenceUtils.decodeRMContent(m, message); RMContextUtils.setProtocolVariation(message, ss.getProtocol()); retransmissionQueue.addUnacknowledged(message); } catch (IOException e) { LOG.log(Level.SEVERE, "Error reading persisted message data", e); } } } private void recoverDestinationSequence(Endpoint endpoint, Conduit conduit, Destination d, DestinationSequence ds) { // always recover the sequence d.addSequence(ds, false); Collection<RMMessage> ms = store.getMessages(ds.getIdentifier(), false); if (null == ms || 0 == ms.size()) { return; } LOG.log(Level.FINE, "Number of messages in sequence: {0}", ms.size()); for (RMMessage m : ms) { Message message = new MessageImpl(); Exchange exchange = new ExchangeImpl(); message.setExchange(exchange); if (null != conduit) { exchange.setConduit(conduit); } exchange.put(Endpoint.class, endpoint); exchange.put(Service.class, endpoint.getService()); if (endpoint.getEndpointInfo().getService() != null) { exchange.put(ServiceInfo.class, endpoint.getEndpointInfo().getService()); exchange.put(InterfaceInfo.class, endpoint.getEndpointInfo().getService().getInterface()); } exchange.put(Binding.class, endpoint.getBinding()); exchange.put(BindingInfo.class, endpoint.getEndpointInfo().getBinding()); exchange.put(Bus.class, bus); SequenceType st = new SequenceType(); st.setIdentifier(ds.getIdentifier()); st.setMessageNumber(m.getMessageNumber()); RMProperties rmps = new RMProperties(); rmps.setSequence(st); rmps.setCreatedTime(m.getCreatedTime()); RMContextUtils.storeRMProperties(message, rmps, false); try { // RMMessage is stored in a serialized way, therefore // RMMessage content must be splitted into soap root message // and attachments PersistenceUtils.decodeRMContent(m, message); redeliveryQueue.addUndelivered(message); // add acknowledged undelivered message ds.addDeliveringMessageNumber(m.getMessageNumber()); } catch (IOException e) { LOG.log(Level.SEVERE, "Error reading persisted message data", e); } } // if no messages are recovered and the sequence has been already terminated, remove the sequence if (ds.isTerminated() && ds.allAcknowledgedMessagesDelivered()) { d.removeSequence(ds); store.removeDestinationSequence(ds.getIdentifier()); } } RMEndpoint createReliableEndpoint(final Endpoint endpoint) { endpoint.addCleanupHook(new Closeable() { public void close() throws IOException { shutdownReliableEndpoint(endpoint); } }); return new RMEndpoint(this, endpoint); } public void init(Bus b) { setBus(b); initialise(); registerListeners(); } @PostConstruct void initialise() { if (configuration == null) { getConfiguration().setExponentialBackoff(true); } DeliveryAssurance da = configuration.getDeliveryAssurance(); if (da == null) { configuration.setDeliveryAssurance(DeliveryAssurance.AT_LEAST_ONCE); } if (null == sourcePolicy) { setSourcePolicy(null); } if (null == destinationPolicy) { DestinationPolicyType dp = new DestinationPolicyType(); dp.setAcksPolicy(new AcksPolicyType()); setDestinationPolicy(dp); } if (null == retransmissionQueue) { retransmissionQueue = new RetransmissionQueueImpl(this); } if (null == redeliveryQueue) { redeliveryQueue = new RedeliveryQueueImpl(this); } if (null == idGenerator) { idGenerator = new DefaultSequenceIdentifierGenerator(); } if (null != bus) { managedManager = new ManagedRMManager(this); instrumentationManager = bus.getExtension(InstrumentationManager.class); if (instrumentationManager != null) { try { instrumentationManager.register(managedManager); } catch (JMException jmex) { LOG.log(Level.WARNING, "Registering ManagedRMManager failed.", jmex); } } } } @PostConstruct void registerListeners() { if (null == bus) { return; } ServerLifeCycleManager slm = bus.getExtension(ServerLifeCycleManager.class); if (null != slm) { slm.registerListener(new ServerLifeCycleListener() { public void startServer(Server server) { RMManager.this.startServer(server); } public void stopServer(Server server) { RMManager.this.stopServer(server); } }); } ClientLifeCycleManager clm = bus.getExtension(ClientLifeCycleManager.class); if (null != clm) { clm.registerListener(new ClientLifeCycleListener() { public void clientCreated(Client client) { RMManager.this.clientCreated(client); } public void clientDestroyed(Client client) { RMManager.this.clientDestroyed(client); } }); } } Map<Endpoint, RMEndpoint> getReliableEndpointsMap() { return reliableEndpoints; } void setReliableEndpointsMap(Map<Endpoint, RMEndpoint> map) { reliableEndpoints = map; } class DefaultSequenceIdentifierGenerator implements SequenceIdentifierGenerator { public Identifier generateSequenceIdentifier() { String sequenceID = RMContextUtils.generateUUID(); Identifier sid = new Identifier(); sid.setValue(sequenceID); return sid; } } /** * Clones and saves the interceptor chain the first time this is called, so that it can be used for retransmission. * Calls after the first are ignored. * * @param msg */ public void initializeInterceptorChain(Message msg) { Endpoint ep = msg.getExchange().getEndpoint(); synchronized (ep) { if (ep.get(WSRM_RETRANSMIT_CHAIN) == null) { LOG.info("Setting retransmit chain from message"); PhaseInterceptorChain chain = (PhaseInterceptorChain)msg.getInterceptorChain(); chain = chain.cloneChain(); ep.put(WSRM_RETRANSMIT_CHAIN, chain); } } } /** * Get interceptor chain for retransmitting a message. * * @return chain (<code>null</code> if none set) */ public PhaseInterceptorChain getRetransmitChain(Message msg) { Endpoint ep = msg.getExchange().getEndpoint(); PhaseInterceptorChain pic = (PhaseInterceptorChain)ep.get(WSRM_RETRANSMIT_CHAIN); if (pic == null) { return null; } return pic.cloneChain(); } }