001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.transport;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.util.logging.Logger;
023:
024: import org.apache.cxf.Bus;
025: import org.apache.cxf.message.Exchange;
026: import org.apache.cxf.message.Message;
027: import org.apache.cxf.service.model.EndpointInfo;
028: import org.apache.cxf.ws.addressing.EndpointReferenceType;
029: import org.apache.cxf.wsdl.EndpointReferenceUtils;
030:
031: /**
032: * Abstract base class factoring out common Destination logic,
033: * allowing non-decoupled transports to be written without any
034: * regard for the decoupled back-channel or partial response logic.
035: */
036: public abstract class AbstractDestination extends AbstractObservable
037: implements Destination {
038:
039: protected final EndpointReferenceType reference;
040: protected final EndpointInfo endpointInfo;
041: protected final Bus bus;
042:
043: public AbstractDestination(EndpointReferenceType ref,
044: EndpointInfo ei) {
045: this (null, ref, ei);
046: }
047:
048: public AbstractDestination(Bus b, EndpointReferenceType ref,
049: EndpointInfo ei) {
050: reference = ref;
051: endpointInfo = ei;
052: bus = b;
053: }
054:
055: /**
056: * @return the reference associated with this Destination
057: */
058: public EndpointReferenceType getAddress() {
059: return reference;
060: }
061:
062: /**
063: * Retreive a back-channel Conduit, which must be policy-compatible
064: * with the current Message and associated Destination. For example
065: * compatible Quality of Protection must be asserted on the back-channel.
066: * This would generally only be an issue if the back-channel is decoupled.
067: *
068: * @param inMessage the current inbound message (null to indicate a
069: * disassociated back-channel)
070: * @param partialResponse in the decoupled case, this is expected to be the
071: * outbound Message to be sent over the in-built back-channel.
072: * @param address the backchannel address (null to indicate anonymous)
073: * @return a suitable Conduit
074: */
075: public Conduit getBackChannel(Message inMessage,
076: Message partialResponse, EndpointReferenceType address)
077: throws IOException {
078: Conduit backChannel = null;
079: Exchange ex = inMessage.getExchange();
080: EndpointReferenceType target = address != null ? address : ex
081: .get(EndpointReferenceType.class);
082: if (target == null) {
083: backChannel = getInbuiltBackChannel(inMessage);
084: } else {
085: if (partialResponse != null) {
086: if (markPartialResponse(partialResponse, target)) {
087: backChannel = getInbuiltBackChannel(inMessage);
088: }
089: } else {
090: ConduitInitiator conduitInitiator = getConduitInitiator();
091: if (conduitInitiator != null) {
092: backChannel = conduitInitiator.getConduit(
093: endpointInfo, target);
094: // ensure decoupled back channel input stream is closed
095: backChannel
096: .setMessageObserver(new MessageObserver() {
097: public void onMessage(Message m) {
098: if (m.getContentFormats().contains(
099: InputStream.class)) {
100: InputStream is = m
101: .getContent(InputStream.class);
102: try {
103: is.close();
104: } catch (Exception e) {
105: // ignore
106: }
107: }
108: }
109: });
110: }
111: }
112: }
113: return backChannel;
114: }
115:
116: /**
117: * Shutdown the Destination, i.e. stop accepting incoming messages.
118: */
119: public void shutdown() {
120: // nothing to do by default
121: }
122:
123: /**
124: * Mark message as a partial message. Only required if decoupled
125: * mode is supported.
126: *
127: * @param partialResponse the partial response message
128: * @param the decoupled target
129: * @return true iff partial responses are supported
130: */
131: protected boolean markPartialResponse(Message partialResponse,
132: EndpointReferenceType decoupledTarget) {
133: return false;
134: }
135:
136: /**
137: * @return the associated conduit initiator, or null if decoupled mode
138: * not supported.
139: */
140: protected ConduitInitiator getConduitInitiator() {
141: return null;
142: }
143:
144: /**
145: * @param inMessage the incoming message
146: * @return the inbuilt backchannel
147: */
148: protected abstract Conduit getInbuiltBackChannel(Message inMessage);
149:
150: /**
151: * Backchannel conduit.
152: */
153: protected abstract class AbstractBackChannelConduit extends
154: AbstractConduit {
155:
156: public AbstractBackChannelConduit() {
157: super (EndpointReferenceUtils
158: .getAnonymousEndpointReference());
159: }
160:
161: /**
162: * Register a message observer for incoming messages.
163: *
164: * @param observer the observer to notify on receipt of incoming
165: */
166: public void setMessageObserver(MessageObserver observer) {
167: // shouldn't be called for a back channel conduit
168: }
169:
170: protected Logger getLogger() {
171: return AbstractDestination.this.getLogger();
172: }
173: }
174: }
|