001: package org.objectweb.celtix.bus.ws.rm;
002:
003: import java.io.IOException;
004: import java.util.Collection;
005: import java.util.Iterator;
006: import java.util.logging.Level;
007: import java.util.logging.Logger;
008:
009: import javax.xml.ws.handler.MessageContext;
010:
011: import org.objectweb.celtix.bindings.AbstractClientBinding;
012: import org.objectweb.celtix.bindings.BindingContextUtils;
013: import org.objectweb.celtix.bindings.DataBindingCallback;
014: import org.objectweb.celtix.bindings.Request;
015: import org.objectweb.celtix.bindings.Response;
016: import org.objectweb.celtix.bus.ws.addressing.ContextUtils;
017: import org.objectweb.celtix.bus.ws.addressing.VersionTransformer;
018: import org.objectweb.celtix.common.i18n.Message;
019: import org.objectweb.celtix.common.logging.LogUtils;
020: import org.objectweb.celtix.transports.Transport;
021: import org.objectweb.celtix.ws.addressing.AddressingProperties;
022: import org.objectweb.celtix.ws.addressing.RelatesToType;
023: import org.objectweb.celtix.ws.addressing.v200408.EndpointReferenceType;
024: import org.objectweb.celtix.ws.rm.CreateSequenceResponseType;
025: import org.objectweb.celtix.ws.rm.Identifier;
026: import org.objectweb.celtix.ws.rm.OfferType;
027: import org.objectweb.celtix.ws.rm.persistence.RMDestinationSequence;
028: import org.objectweb.celtix.ws.rm.wsdl.SequenceFault;
029:
030: public class RMProxy {
031:
032: private static final Logger LOG = LogUtils
033: .getL7dLogger(RMProxy.class);
034: private RMHandler handler;
035: // REVISIT assumption there is only a single outstanding offer
036: private Identifier offeredIdentifier;
037:
038: public RMProxy(RMHandler h) {
039: handler = h;
040: }
041:
042: public void createSequence(
043: RMSource source,
044: org.objectweb.celtix.ws.addressing.EndpointReferenceType to,
045: EndpointReferenceType acksTo, RelatesToType relatesTo)
046: throws IOException, SequenceFault {
047: CreateSequenceRequest request = new CreateSequenceRequest(
048: handler.getBinding(), getTransport(), source, to,
049: acksTo, relatesTo);
050: setOfferedIdentifier(request.getIncludedOffer());
051:
052: send(request, CreateSequenceRequest.createDataBindingCallback());
053: }
054:
055: public void createSequenceResponse(AddressingProperties inMAPs,
056: CreateSequenceResponseType csr) throws IOException,
057: SequenceFault {
058: CreateSequenceResponse request = new CreateSequenceResponse(
059: handler.getBinding(), getTransport(), inMAPs, csr);
060:
061: send(request, CreateSequenceResponse
062: .createDataBindingCallback());
063: }
064:
065: public void terminateSequence(SourceSequence seq)
066: throws IOException {
067: if (canSend(seq.getTarget())) {
068: TerminateSequenceRequest request = new TerminateSequenceRequest(
069: handler.getBinding(), getTransport(), seq);
070: // required?
071: handler.getSource().removeSequence(seq);
072:
073: send(request, TerminateSequenceRequest
074: .createDataBindingCallback());
075: }
076: }
077:
078: /**
079: * Send a standalone message requesting acknowledgments for the
080: * given sequences.
081: *
082: * @param seqs the sequences for which acknowledgments are requested.
083: * @throws IOException
084: */
085: public void requestAcknowledgment(Collection<SourceSequence> seqs)
086: throws IOException {
087: // it only makes sense to relate a group of sequnces in the same
088: // AckRequest if they all have the same AcksTo, hence we can safely
089: // take the AckTo from the first sequence in the collection
090: SourceSequence first = getFirstSequence(seqs);
091: if (canSend(first.getTarget())) {
092: SequenceInfoRequest request = new SequenceInfoRequest(
093: handler.getBinding(), getTransport(), first
094: .getTarget());
095: request.requestAcknowledgement(seqs);
096: send(request, null);
097: }
098: }
099:
100: /**
101: * Send a standalone LastMessage message for the given sequence.
102: *
103: * @param seq the sequence for which the last message is to be sent.
104: * @throws IOException
105: */
106:
107: public void lastMessage(SourceSequence seq) throws IOException {
108: LOG.fine("sending standalone last message");
109: if (canSend(seq.getTarget())) {
110: SequenceInfoRequest request = new SequenceInfoRequest(
111: handler.getBinding(), getTransport(), seq
112: .getTarget());
113: request.lastMessage(seq);
114: send(request, null);
115: }
116: }
117:
118: /**
119: * Send a standalone SequenceAcknowledgement message for the given sequence.
120: *
121: * @param seq the sequence for which an acknowledgment is to be sent.
122: * @throws IOException
123: */
124: public void acknowledge(RMDestinationSequence seq)
125: throws IOException {
126: // required?
127: if (Names.WSA_ANONYMOUS_ADDRESS.equals(seq.getAcksTo()
128: .getAddress().getValue())) {
129: LOG
130: .log(Level.WARNING,
131: "STANDALONE_ANON_ACKS_NOT_SUPPORTED");
132: return;
133: }
134: LOG.fine("sending standalone sequence acknowledgment");
135: if (canSend(seq.getAcksTo())) {
136: SequenceInfoRequest request = new SequenceInfoRequest(
137: handler.getBinding(), handler.getTransport(), seq
138: .getAcksTo());
139: request.acknowledge(seq);
140: send(request, null);
141: }
142: }
143:
144: protected Identifier getOfferedIdentifier() {
145: return offeredIdentifier;
146: }
147:
148: protected void setOfferedIdentifier(OfferType offer) {
149: if (offer != null) {
150: offeredIdentifier = offer.getIdentifier();
151: }
152: }
153:
154: private void send(Request request, DataBindingCallback callback)
155: throws IOException {
156:
157: boolean isOneway = request.isOneway();
158: if (handler.getBinding() != null) {
159: handler.getBinding().send(request, callback);
160: if (!(handler.getClientBinding() == null || isOneway)) {
161: Response response = ((AbstractClientBinding) handler
162: .getClientBinding()).getResponseCorrelator()
163: .getResponse(request);
164: response.setHandlerInvoker(request.getHandlerInvoker());
165: MessageContext responseContext = response
166: .getBindingMessageContext();
167: DataBindingCallback responseCallback = BindingContextUtils
168: .retrieveDataBindingCallback(responseContext);
169: response.processLogical(responseCallback);
170: }
171: } else {
172: AddressingProperties maps = ContextUtils.retrieveMAPs(
173: request.getObjectMessageContext(), true, true);
174: String action = maps.getAction() != null ? maps.getAction()
175: .getValue() : "empty";
176: Message msg = new Message("NO_BINDING_FOR_OUT_OF_BAND_MSG",
177: LOG, action);
178: LOG.severe(msg.toString());
179: }
180: }
181:
182: /**
183: * A outgoing out-of-band protocol message cannot be sent if from the server
184: * side if the target (e.g. the AcksTo address) is anonymous.
185: *
186: * @param to the target EPR
187: * @return true if the message may be sent
188: */
189: protected boolean canSend(EndpointReferenceType to) {
190: return !(handler.getClientBinding() == null && ContextUtils
191: .isGenericAddress(VersionTransformer.convert(to)));
192: }
193:
194: /**
195: * A outgoing out-of-band protocol message cannot be sent if from the server
196: * side if the target (e.g. the AcksTo address) is anonymous.
197: *
198: * @param to the target EPR
199: * @return true if the message may be sent
200: */
201: protected boolean canSend(
202: org.objectweb.celtix.ws.addressing.EndpointReferenceType to) {
203: boolean ret = false;
204: if (handler.getClientBinding() == null) {
205: ret = !ContextUtils.isGenericAddress(to);
206: } else {
207: try {
208: ret = ((AbstractClientBinding) handler
209: .getClientBinding()).getTransport() != null;
210: } catch (IOException ioe) {
211: // ignore
212: }
213: }
214: return ret;
215: }
216:
217: /**
218: * This is required as the resource injected transport may be shutdown already
219: * (e.g. for LastMessage or TerminateSequence messages originating from
220: * BusLifeCycleListener.preShutdown()).
221: *
222: * @return
223: */
224: protected Transport getTransport() {
225: Transport ret = null;
226: if (handler.getClientBinding() == null) {
227: ret = handler.getTransport();
228: } else {
229: try {
230: ret = ((AbstractClientBinding) handler
231: .getClientBinding()).getTransport();
232: } catch (IOException ioe) {
233: // ignore
234: }
235: }
236: return ret;
237: }
238:
239: private SourceSequence getFirstSequence(
240: Collection<SourceSequence> seqs) {
241: Iterator<SourceSequence> i = seqs.iterator();
242: return i.hasNext() ? i.next() : null;
243: }
244: }
|