001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.transport.tcp.util;
038:
039: import com.sun.istack.NotNull;
040: import com.sun.istack.Nullable;
041: import com.sun.xml.ws.api.SOAPVersion;
042: import com.sun.xml.ws.api.pipe.Codec;
043: import com.sun.xml.ws.api.pipe.SOAPBindingCodec;
044: import com.sun.xml.ws.api.pipe.StreamSOAPCodec;
045: import com.sun.xml.ws.transport.tcp.encoding.WSTCPFastInfosetStreamCodec;
046: import com.sun.xml.ws.transport.tcp.encoding.WSTCPFastInfosetStreamReaderRecyclable;
047: import com.sun.xml.ws.transport.tcp.io.Connection;
048: import com.sun.xml.ws.transport.tcp.resources.MessagesMessages;
049: import java.util.List;
050: import java.util.Map;
051: import java.util.logging.Level;
052: import java.util.logging.Logger;
053: import javax.xml.namespace.QName;
054:
055: public class ChannelContext implements
056: WSTCPFastInfosetStreamReaderRecyclable.RecycleAwareListener {
057: private static final Logger logger = Logger
058: .getLogger(com.sun.xml.ws.transport.tcp.util.TCPConstants.LoggingDomain);
059:
060: // tcp connection session this channel belongs to
061: private final ConnectionSession connectionSession;
062:
063: /**
064: * Channel settings aggreed during client-service handshaking
065: */
066: private final ChannelSettings channelSettings;
067:
068: /**
069: * Codec used to encode/decode messages on this channel
070: */
071: private Codec codec;
072:
073: // Temp storage for decode content type from String representation
074: private final ContentType contentType = new ContentType();
075:
076: public ChannelContext(@NotNull
077: final ConnectionSession connectionSession, @NotNull
078: final ChannelSettings channelSettings) {
079: this .connectionSession = connectionSession;
080: this .channelSettings = channelSettings;
081: }
082:
083: /**
084: * Return TCP session object where which this virual channel is open on
085: */
086: public @NotNull
087: ConnectionSession getConnectionSession() {
088: return connectionSession;
089: }
090:
091: /**
092: * Return channel settings, which were aggreed during handshake phase
093: */
094: public @NotNull
095: ChannelSettings getChannelSettings() {
096: return channelSettings;
097: }
098:
099: /**
100: * Return message Codec, which is used for encoding/decoding messages
101: * on this virtual channel
102: */
103: public @Nullable
104: Codec getCodec() {
105: return codec;
106: }
107:
108: private void setCodec(@NotNull
109: final Codec codec) {
110: this .codec = codec;
111: }
112:
113: /**
114: * Return TCP connection object, where this virtual channel is acting on
115: */
116: public @NotNull
117: Connection getConnection() {
118: return connectionSession.getConnection();
119: }
120:
121: /**
122: * Return channel id
123: */
124: public int getChannelId() {
125: return channelSettings.getChannelId();
126: }
127:
128: /**
129: * Return virtual channel's correspondent service name
130: */
131: public @NotNull
132: QName getWSServiceName() {
133: return channelSettings.getWSServiceName();
134: }
135:
136: public void setWSServiceName(@NotNull
137: final QName wsServiceName) {
138: channelSettings.setWSServiceName(wsServiceName);
139: }
140:
141: /**
142: * Return correspondent WS's URI
143: */
144: public @Nullable
145: WSTCPURI getTargetWSURI() {
146: return channelSettings.getTargetWSURI();
147: }
148:
149: /**
150: * Sets message's content type to TCP protocol specific representation
151: */
152: public void setContentType(@NotNull
153: final String contentTypeS) throws WSTCPException {
154: Connection connection = connectionSession.getConnection();
155: if (logger.isLoggable(Level.FINEST)) {
156: logger
157: .log(
158: Level.FINEST,
159: MessagesMessages
160: .WSTCP_1120_CHANNEL_CONTEXT_ENCODE_CT(contentTypeS));
161: }
162: contentType.parse(contentTypeS);
163:
164: int mt = encodeMimeType(contentType.getMimeType());
165:
166: connection.setContentId(mt);
167: final Map<String, String> parameters = contentType
168: .getParameters();
169: for (Map.Entry<String, String> parameter : parameters
170: .entrySet()) {
171: final int paramId = encodeParam(parameter.getKey());
172: connection
173: .setContentProperty(paramId, parameter.getValue());
174: }
175:
176: if (logger.isLoggable(Level.FINEST)) {
177: logger.log(Level.FINEST, MessagesMessages
178: .WSTCP_1121_CHANNEL_CONTEXT_ENCODED_CT(mt,
179: parameters));
180: }
181: }
182:
183: /**
184: * Gets message's content type from TCP protocol specific representation
185: */
186: public @NotNull
187: String getContentType() throws WSTCPException {
188: Connection connection = connectionSession.getConnection();
189: final int mimeId = connection.getContentId();
190: Map<Integer, String> params = connection.getContentProperties();
191:
192: if (logger.isLoggable(Level.FINEST)) {
193: logger.log(Level.FINEST, MessagesMessages
194: .WSTCP_1122_CHANNEL_CONTEXT_DECODE_CT(mimeId,
195: params));
196: }
197:
198: String mimeType = decodeMimeType(mimeId);
199:
200: String contentTypeStr = mimeType;
201: if (params.size() > 0) {
202: final StringBuffer ctBuf = new StringBuffer(contentTypeStr);
203: for (Map.Entry<Integer, String> parameter : params
204: .entrySet()) {
205: ctBuf.append(';');
206: final String paramKey = decodeParam(parameter.getKey());
207: final String paramValue = parameter.getValue();
208: ctBuf.append(paramKey);
209: ctBuf.append('=');
210: ctBuf.append(paramValue);
211: }
212: contentTypeStr = ctBuf.toString();
213: }
214:
215: if (logger.isLoggable(Level.FINEST)) {
216: logger
217: .log(
218: Level.FINEST,
219: MessagesMessages
220: .WSTCP_1123_CHANNEL_CONTEXT_DECODED_CT(contentTypeStr));
221: }
222: return contentTypeStr;
223: }
224:
225: public int encodeMimeType(@NotNull
226: final String mimeType) throws WSTCPException {
227: int contentId = channelSettings.getNegotiatedMimeTypes()
228: .indexOf(mimeType);
229: if (contentId != -1) {
230: return contentId;
231: }
232:
233: throw new WSTCPException(WSTCPError.createNonCriticalError(
234: TCPConstants.UNKNOWN_CONTENT_ID, MessagesMessages
235: .WSTCP_0011_UNKNOWN_CONTENT_TYPE(mimeType)));
236: }
237:
238: public @NotNull
239: String decodeMimeType(final int contentId) throws WSTCPException {
240: String mimeType = channelSettings.getNegotiatedMimeTypes().get(
241: contentId);
242:
243: if (mimeType != null) {
244: return mimeType;
245: }
246: throw new WSTCPException(WSTCPError.createNonCriticalError(
247: TCPConstants.UNKNOWN_CONTENT_ID, MessagesMessages
248: .WSTCP_0011_UNKNOWN_CONTENT_TYPE(contentId)));
249: }
250:
251: public int encodeParam(@NotNull
252: final String paramStr) throws WSTCPException {
253: int paramId = channelSettings.getNegotiatedParams().indexOf(
254: paramStr);
255: if (paramId != -1) {
256: return paramId;
257: }
258:
259: throw new WSTCPException(WSTCPError.createNonCriticalError(
260: TCPConstants.UNKNOWN_PARAMETER_ID, MessagesMessages
261: .WSTCP_0010_UNKNOWN_PARAMETER(paramStr)));
262: }
263:
264: public @NotNull
265: String decodeParam(final int paramId) throws WSTCPException {
266: String paramStr = channelSettings.getNegotiatedParams().get(
267: paramId);
268:
269: if (paramStr != null) {
270: return paramStr;
271: }
272: throw new WSTCPException(WSTCPError.createNonCriticalError(
273: TCPConstants.UNKNOWN_PARAMETER_ID, MessagesMessages
274: .WSTCP_0010_UNKNOWN_PARAMETER(paramId)));
275: }
276:
277: /**
278: * Configure Codec according to channel settings
279: */
280: public static void configureCodec(@NotNull
281: final ChannelContext channelContext, @NotNull
282: final SOAPVersion soapVersion, @NotNull
283: final Codec defaultCodec) {
284: final List<String> supportedMimeTypes = channelContext
285: .getChannelSettings().getNegotiatedMimeTypes();
286: if (supportedMimeTypes != null) {
287: if (supportedMimeTypes
288: .contains(MimeTypeConstants.FAST_INFOSET_STATEFUL_SOAP11)
289: || supportedMimeTypes
290: .contains(MimeTypeConstants.FAST_INFOSET_STATEFUL_SOAP12)) {
291: logger.log(Level.FINEST,
292: "ChannelContext.configureCodec: FI Stateful");
293: StreamSOAPCodec streamSoapCodec = defaultCodec instanceof SOAPBindingCodec ? ((SOAPBindingCodec) defaultCodec)
294: .getXMLCodec()
295: : null;
296: channelContext.setCodec(WSTCPFastInfosetStreamCodec
297: .create(streamSoapCodec, soapVersion,
298: channelContext, true));
299: return;
300: } else if (supportedMimeTypes
301: .contains(MimeTypeConstants.FAST_INFOSET_SOAP11)
302: || supportedMimeTypes
303: .contains(MimeTypeConstants.FAST_INFOSET_SOAP12)) {
304: logger.log(Level.FINEST,
305: "ChannelContext.configureCodec: FI Stateless");
306: StreamSOAPCodec streamSoapCodec = defaultCodec instanceof SOAPBindingCodec ? ((SOAPBindingCodec) defaultCodec)
307: .getXMLCodec()
308: : null;
309: channelContext.setCodec(WSTCPFastInfosetStreamCodec
310: .create(streamSoapCodec, soapVersion,
311: channelContext, false));
312: return;
313: }
314: }
315:
316: logger.log(Level.FINEST,
317: "ChannelContext.configureCodec: default");
318: channelContext.setCodec(defaultCodec);
319: }
320:
321: @Override
322: public String toString() {
323: return String.format("ID: %d\nURI: %s\nCodec:%s", new Object[] {
324: getChannelId(), getTargetWSURI(), getCodec() });
325: }
326:
327: public void onRecycled() {
328: connectionSession.onReadCompleted();
329: }
330: }
|