Fields Summary |
---|
private static final Logger | logger |
protected int | receiveBufferSizeCurrent value of receive buffer read from incoming SequenceAcknowledgement
messages if RM Destination implements properietary Indigo Flow Control feature. |
protected ProtocolMessageSender | protocolMessageSenderThe helper class used to send protocol messages
CreateSequenceElement
CreateSequenceResponseElement
LastMessage
AckRequestedElement |
private com.sun.xml.ws.api.SOAPVersion | version |
private boolean | secureReliableMessagingFlag to indicate if secureReliableMessaging is on |
private JAXBElement | strThe SecurityTokenReference to pass to CreateSequence |
private boolean | isAnonymousIndicates whether the sequence uses anonymous acksTo |
private boolean | isActive |
private long | resendDeadlineTime after which resend of messages in sequences is attempted at
next opportunity. |
private long | ackRequestDeadlineTime after which Ack is requested at next opportunity. |
private com.sun.xml.ws.api.rm.AcknowledgementListener | ackListenerCan be registered to listen for sequence acknowledgements. |
private Service | serviceService using this sequence (if known) |
private static boolean | sendHeartbeatsThis field is used only as a hack to test Server-side
timeout functionality. It is not intended to be used
for any other purpose. |
Methods Summary |
---|
public synchronized void | acknowledge(int i)Implementation of acknowledge defers discarding stored messages when
the AcksTo endpoint is anonymous and the message is a two-way request.
In this case, the actual work usually done by acknowledge() needs to
wait until the response is received. The RMClientPipe invokes
acknowledgeResponse at that time.
Message mess = get(i);
if (isAnonymous() && mess.isTwoWayRequest) {
return;
} else {
super.acknowledge(i);
if (ackListener != null) {
ackListener.notify(this, i);
}
//if this acknowledgement is not on the protocol
//response for the one-way message (endpoint behaved
//unkindly, or possibly dropped the request), the sending
//thread is waiting in the resend loop in RMClientPipe.
mess.resume();
}
|
public synchronized void | acknowledgeResponse(int i)Acknowledges that a response to a two-way operation has been
received. See Javadoc for acknowledge
super.acknowledge(i);
if (ackListener != null) {
ackListener.notify(this, i);
}
|
public void | connect(java.net.URI destination, java.net.URI acksTo, boolean twoWay)Connects to remote RM Destination by sending request through the proxy
stored in the port field.
try {
this.destination = destination;
this.acksTo = acksTo;
String anonymous = rmConstants.getAnonymousURI().toString();
String acksToString;
if (acksTo == null) {
acksToString = anonymous;
} else {
acksToString = acksTo.toString();
}
this.isAnonymous = acksToString.equals(anonymous);
CreateSequenceElement cs = new CreateSequenceElement();
/**
* ADDRESSING_FIXME
* This needs to be fixed commenting temporarily to get the compilation
* problems fixed
*/
/*if (RMConstants.getAddressingVersion() == AddressingVersion.W3C){
cs.setAcksTo(new W3CAcksToImpl(new URI(acksToString)));
} else {
cs.setAcksTo(new MemberSubmissionAcksToImpl(new URI(acksToString)));
}*/
W3CEndpointReference endpointReference = null;
AddressingVersion addressingVersion = rmConstants.getAddressingVersion();
if ( addressingVersion == AddressingVersion.W3C){
//WSEndpointReference wsepr = new WSEndpointReference(getClass().getResourceAsStream("w3c-anonymous-acksTo.xml"), addressingVersion);
WSEndpointReference epr = AddressingVersion.W3C.anonymousEpr;
Source s = epr.asSource("AcksTo");
endpointReference = new W3CEndpointReference(s);
}/*else {
WSEndpointReference wsepr = new WSEndpointReference(getClass().getResourceAsStream("member-anonymous-acksTo.xml"), addressingVersion);
Source s = wsepr.asSource("AcksTo");
endpointReference = new MemberSubmissionEndpointReference(s);
}*/
cs.setAcksTo(endpointReference);
String incomingID = "uuid:" + UUID.randomUUID();
if (twoWay) {
Identifier id = new Identifier();
id.setValue(incomingID);
OfferType offer = new OfferType();
offer.setIdentifier(id);
cs.setOffer(offer);
}
if (secureReliableMessaging) {
JAXBElement<SecurityTokenReferenceType> str = getSecurityTokenReference();
if (str != null) {
cs.setSecurityTokenReference(str.getValue());
} else {
throw new RMException("SecurityTokenReference is null");
}
}
CreateSequenceResponseElement csr = protocolMessageSender.sendCreateSequence(cs,destination,
acksTo,version);
if (csr != null ) {
Identifier idOutbound = csr.getIdentifier();
this.id = idOutbound.getValue();
AcceptType accept = csr.getAccept();
if (accept != null) {
/**
* ADDRESSING_FIXME Needs to be fixes once
* AcksTO issue is resolved
*/
/* URI uriAccept = accept.getAcksTo();*/
URI uriAccept = null;
inboundSequence = new ClientInboundSequence(this,
incomingID,
uriAccept);
} else {
inboundSequence = new ClientInboundSequence(this,
incomingID, null);
}
//start the inactivity clock
resetLastActivityTime();
} else {
//maybe a non-anonymous AcksTo
//Handle CreateSequenceRefused fault
}
} catch (Exception e) {
throw new RMException(e);
}
|
public void | disconnect()Disconnect from the RMDestination by invoking TerminateSequence on
the proxy stored in the port field. State of
sequence is set to inactive.
disconnect(false);
|
public void | disconnect(boolean keepAlive)Disconnect from the RMDestination by invoking TerminateSequence on
the proxy stored in the port field.
//FIXME - find another check for connectiveness.. want to get rid of
//unnecessary InboundSequences.
if (inboundSequence == null) {
throw new IllegalStateException("Not connected.");
}
isActive = keepAlive;
//TODO
//Move this after waitForAcks to obviate problems caused by
//the LastMessage Protocol message being processed concurrently with
//application messages. At the moment, this may cause problems in
//Glassfish container with ordered delivery configured. This will
//probably no longer be the case when the Tube/Fibre architecture
//is used.
sendLast();
//this will block until all messages are complete
waitForAcks();
TerminateSequenceElement ts = new TerminateSequenceElement();
Identifier idTerminate = new Identifier();
idTerminate.setValue(id);
ts.setIdentifier(idTerminate);
protocolMessageSender.sendTerminateSequence(ts,this,version);
|
public synchronized void | doMaintenanceTasks()Handler periodically invoked by RMSource.MaintenanceThread.
Has two duties:
- Resend incomplete messages.
- Send AckRequested message down the pipeline if Inactivity
timeout is approaching.
if (storedMessages > 0 && isResendDue()) {
int top = getNextIndex();
for (int i = 1; i < top; i++) {
Message mess = get(i);
if (mess != null && !mess.isComplete()) {
logger.fine("resending " + getId() + ":" + i);
resend(i);
}
}
} else {
//check whether we need to prime the pump
if (isGettingClose(System.currentTimeMillis() - getLastActivityTime(),
config.getInactivityTimeout())) {
//send an AckRequested down the pipe. Need to use a background
//Thread. This is being called by the RMSource maintenance thread
//whose health we have to be very careful with. If the heartbeat
//message takes inordinately long to process, the maintenance thread
//could miss many assignments.
new AckRequestedSender(this).start();
}
}
|
private long | getAckRequestInterval()
//send an ackRequest at every opportunity under these conditions
//1. Sequence has been terminated
//2. Number of stored messages exceeds 1/2 available space.
//3. Number of stored messages at endpoint exceeds 1/2
// available space.
if (!isActive ||
storedMessages > (getTransferWindowSize() / 2) ||
getReceiveBufferSize() > (config.getBufferSize() / 2)) {
return 0;
}
return config.getAckRequestInterval();
|
public com.sun.xml.ws.api.rm.AcknowledgementListener | getAcknowledgementListener()Accessor for the AcknowledgementListener field.
return ackListener;
|
public int | getReceiveBufferSize()Accessor for the receiveBufferSize field.
return receiveBufferSize;
|
private long | getResendInterval()
//do a resend at every opportunity under these conditions
//1. Sequence has been terminated
//2. Number of stored messages exceeds 1/2 available space.
if (!isActive ||
storedMessages > (getTransferWindowSize() / 2) ) {
return 0;
}
return config.getResendInterval();
|
public javax.xml.bind.JAXBElement | getSecurityTokenReference()
return str;
|
public com.sun.xml.ws.rm.jaxws.runtime.SequenceConfig | getSequenceConfig()Accessor for the sequenceConfig field
return config;
|
public com.sun.xml.ws.api.rm.SequenceSettings | getSequenceSettings()Implementation of the getSequenceSettings method in
com.sun.xml.ws.rm.api.client.ClientSequence. Need
to populate the sequence ids in the returned SequenceSettings
object, since in general, they will not be set in the underlying
SequenceConfig object.
SequenceSettings settings = getSequenceConfig();
settings.sequenceId = getId();
InboundSequence iseq = getInboundSequence();
settings.companionSequenceId = (iseq != null) ?
iseq.getId() :
null;
return settings;
|
public javax.xml.ws.Service | getService()Accessor for the service field.
return service;
|
public int | getTransferWindowSize()Return the hoped-for limit to number of stored messages. Currently
the limit is not enforced, but as the number of stored messages approaches
the limit, resends and ackRequests occur more frequently.
//Use server size receive buffer size for now. Might
//want to make this configurable.
return config.getBufferSize();
|
protected synchronized boolean | isAckRequested()Checks whether an ack should be requested. Currently checks whether the
The algorithm checks whether the ackRequest deadline has elapsed.
The ackRequestDeadline is determined by the ackRequestInterval in the
SequenceConfig member for this sequence.
long time = System.currentTimeMillis();
if (time > ackRequestDeadline) {
//reset the clock
ackRequestDeadline = time + getAckRequestInterval();
return true;
} else {
return false;
}
|
public boolean | isAnonymous()Return value is determined by whether the destination endpoint is the
anonymous URI.
return isAnonymous;
|
public synchronized boolean | isResendDue()Checks whether a resend should happen. The algorithm checks whether
the resendDeadline has elapsed.
The resendDeadline is determined by the resendInterval in the
SequenceConfig member for this sequence.
long time = System.currentTimeMillis();
if (time > resendDeadline) {
//reset the clock
resendDeadline = time + getResendInterval();
return true;
} else {
return false;
}
|
public boolean | isSecureReliableMessaging()
return secureReliableMessaging;
|
public boolean | isTransferWindowFull()Returns true if TransferWindow is full. In this case, we
hold off on sending messages.
return getTransferWindowSize() == storedMessages;
|
public void | registerProtocolMessageSender(ProtocolMessageSender pms)
this.protocolMessageSender = pms;
|
public synchronized void | requestAck()Forces an ack request on next message
ackRequestDeadline = System.currentTimeMillis();
|
public void | resend(int messageNumber)Causes the specified message number to be resent.
Message mess = get(messageNumber);
mess.resume();
|
private void | sendLast()
protocolMessageSender.sendLast(this,version);
|
public void | setAcknowledgementListener(com.sun.xml.ws.api.rm.AcknowledgementListener listener)Registers a AcknowledgementListener for this
sequence
this.ackListener = listener;
|
public void | setReceiveBufferSize(int receiveBufferSize)Mutator for the receiveBufferSize field.
this.receiveBufferSize = receiveBufferSize;
|
public void | setSecureReliableMessaging(boolean secureReliableMessaging)
this.secureReliableMessaging = secureReliableMessaging;
|
public void | setSecurityTokenReference(javax.xml.bind.JAXBElement str)
this.str = str;
|
public void | setService(javax.xml.ws.Service service)Sets the value of the service field.
this.service = service;
|