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.server;
038:
039: import com.sun.istack.NotNull;
040: import com.sun.istack.Nullable;
041: import com.sun.xml.ws.api.server.WSEndpoint;
042: import com.sun.xml.ws.transport.tcp.io.Connection;
043: import com.sun.xml.ws.transport.tcp.resources.MessagesMessages;
044: import com.sun.xml.ws.transport.tcp.servicechannel.ServiceChannelCreator;
045: import com.sun.xml.ws.transport.tcp.util.ChannelContext;
046: import com.sun.xml.ws.transport.tcp.util.TCPConstants;
047: import com.sun.xml.ws.transport.tcp.util.WSTCPError;
048: import com.sun.xml.ws.transport.tcp.util.WSTCPException;
049: import com.sun.xml.ws.transport.tcp.util.WSTCPURI;
050: import com.sun.xml.ws.transport.tcp.servicechannel.ServiceChannelWSImpl;
051: import com.sun.xml.ws.util.exception.JAXWSExceptionBase;
052: import java.io.IOException;
053: import java.util.ArrayList;
054: import java.util.HashMap;
055: import java.util.List;
056: import java.util.Map;
057: import java.util.logging.Level;
058: import java.util.logging.Logger;
059:
060: /**
061: * @author Alexey Stashok
062: */
063: public final class WSTCPDelegate implements WSTCPAdapterRegistry,
064: TCPMessageListener {
065: private static final Logger logger = Logger
066: .getLogger(com.sun.xml.ws.transport.tcp.util.TCPConstants.LoggingDomain
067: + ".server");
068:
069: private final Map<String, TCPAdapter> fixedUrlPatternEndpoints = new HashMap<String, TCPAdapter>();
070: private final List<TCPAdapter> pathUrlPatternEndpoints = new ArrayList<TCPAdapter>();
071:
072: private volatile TCPAdapter serviceChannelWSAdapter;
073:
074: /**
075: * Custom registry, where its possible to delegate Adapter search
076: */
077: private WSTCPAdapterRegistry customWSRegistry;
078:
079: public WSTCPDelegate() {
080: }
081:
082: public void setCustomWSRegistry(@NotNull
083: final WSTCPAdapterRegistry customWSRegistry) {
084: this .customWSRegistry = customWSRegistry;
085: }
086:
087: public void registerAdapters(@NotNull
088: final String contextPath, @NotNull
089: final List<TCPAdapter> adapters) {
090:
091: for (TCPAdapter adapter : adapters)
092: registerEndpointUrlPattern(contextPath, adapter);
093: }
094:
095: public void freeAdapters(@NotNull
096: final String contextPath, @NotNull
097: final List<TCPAdapter> adapters) {
098:
099: for (TCPAdapter adapter : adapters) {
100: final String urlPattern = contextPath + adapter.urlPattern;
101: logger
102: .log(
103: Level.FINE,
104: MessagesMessages
105: .WSTCP_1100_WSTCP_DELEGATE_DEREGISTER_ADAPTER(urlPattern));
106:
107: if (fixedUrlPatternEndpoints.remove(urlPattern) == null) {
108: pathUrlPatternEndpoints.remove(adapter);
109: }
110: }
111: }
112:
113: private void registerEndpointUrlPattern(@NotNull
114: final String contextPath, @NotNull
115: final TCPAdapter adapter) {
116:
117: final String urlPattern = contextPath + adapter.urlPattern;
118: logger
119: .log(
120: Level.FINE,
121: MessagesMessages
122: .WSTCP_1101_WSTCP_DELEGATE_REGISTER_ADAPTER(urlPattern));
123:
124: if (urlPattern.endsWith("/*")) {
125: pathUrlPatternEndpoints.add(adapter);
126: } else {
127: if (fixedUrlPatternEndpoints.containsKey(urlPattern)) {
128: // Warning because of duplication
129: } else {
130: fixedUrlPatternEndpoints.put(urlPattern, adapter);
131: }
132: }
133: }
134:
135: /**
136: * Determines which {@link TCPAdapter} serves the given request.
137: */
138: public @Nullable
139: TCPAdapter getTarget(@NotNull
140: final WSTCPURI tcpURI) {
141: TCPAdapter result = null;
142: final String path = tcpURI.path;
143: if (path != null) {
144: result = fixedUrlPatternEndpoints.get(path);
145: if (result == null) {
146: for (TCPAdapter candidate : pathUrlPatternEndpoints) {
147: if (path.startsWith(candidate.getValidPath())) {
148: result = candidate;
149: break;
150: }
151: }
152: }
153: }
154:
155: if (result == null && customWSRegistry != null) {
156: logger
157: .log(
158: Level.FINE,
159: MessagesMessages
160: .WSTCP_1102_WSTCP_DELEGATE_GOING_TO_CUSTOM_REG(tcpURI));
161: return customWSRegistry.getTarget(tcpURI);
162: }
163:
164: return result;
165: }
166:
167: /**
168: * Implementation of TCPMessageListener.onError
169: * method is called if error occured during frame processing
170: * on upper level
171: */
172: public void onError(ChannelContext channelContext, WSTCPError error)
173: throws IOException {
174: sendErrorResponse(channelContext, error);
175: }
176:
177: /**
178: * Implementation of TCPMessageListener.onMessage
179: * method is called once request message come
180: */
181: public void onMessage(@NotNull
182: final ChannelContext channelContext) throws IOException {
183: if (logger.isLoggable(Level.FINE)) {
184: final Connection connection = channelContext
185: .getConnection();
186: logger.log(Level.FINE, MessagesMessages
187: .WSTCP_1103_WSTCP_DELEGATE_ON_MESSAGE(connection
188: .getHost(), connection.getPort(),
189: connection.getLocalHost(), connection
190: .getLocalPort()));
191: }
192: try {
193: TCPAdapter target = null;
194: if (channelContext.getChannelId() > 0) {
195: final WSTCPURI tcpURI = channelContext.getTargetWSURI();
196: target = getTarget(tcpURI);
197: } else {
198: target = getServiceChannelWSAdapter();
199: }
200:
201: if (target != null) {
202: target.handle(channelContext);
203: } else {
204: TCPAdapter
205: .sendErrorResponse(
206: channelContext,
207: WSTCPError
208: .createNonCriticalError(
209: TCPConstants.UNKNOWN_CHANNEL_ID,
210: MessagesMessages
211: .WSTCP_0026_UNKNOWN_CHANNEL_ID(channelContext
212: .getChannelId())));
213: }
214:
215: } catch (WSTCPException e) {
216: final Connection connection = channelContext
217: .getConnection();
218: logger.log(Level.SEVERE, MessagesMessages
219: .WSTCP_0023_TARGET_EXEC_ERROR(connection.getHost(),
220: connection.getPort()), e);
221:
222: sendErrorResponse(channelContext, e.getError());
223:
224: if (e.getError().isCritical()) {
225: channelContext.getConnectionSession().close();
226: }
227: } catch (JAXWSExceptionBase e) {
228: final Connection connection = channelContext
229: .getConnection();
230: logger.log(Level.SEVERE, MessagesMessages
231: .WSTCP_0023_TARGET_EXEC_ERROR(connection.getHost(),
232: connection.getPort()), e);
233:
234: sendErrorResponse(
235: channelContext,
236: WSTCPError
237: .createNonCriticalError(
238: TCPConstants.GENERAL_CHANNEL_ERROR,
239: MessagesMessages
240: .WSTCP_0025_GENERAL_CHANNEL_ERROR(MessagesMessages
241: .WSTCP_0004_CHECK_SERVER_LOG())));
242: } catch (IOException e) {
243: final Connection connection = channelContext
244: .getConnection();
245: logger.log(Level.SEVERE, MessagesMessages
246: .WSTCP_0023_TARGET_EXEC_ERROR(connection.getHost(),
247: connection.getPort()), e);
248: throw e;
249: } catch (Exception e) {
250: final Connection connection = channelContext
251: .getConnection();
252: logger.log(Level.SEVERE, MessagesMessages
253: .WSTCP_0023_TARGET_EXEC_ERROR(connection.getHost(),
254: connection.getPort()), e);
255: sendErrorResponse(
256: channelContext,
257: WSTCPError
258: .createNonCriticalError(
259: TCPConstants.GENERAL_CHANNEL_ERROR,
260: MessagesMessages
261: .WSTCP_0025_GENERAL_CHANNEL_ERROR(MessagesMessages
262: .WSTCP_0004_CHECK_SERVER_LOG())));
263: } finally {
264: if (logger.isLoggable(Level.FINE)) {
265: logger
266: .log(
267: Level.FINE,
268: MessagesMessages
269: .WSTCP_1104_WSTCP_DELEGATE_ON_MESSAGE_COMPLETED());
270: }
271: }
272: }
273:
274: public void destroy() {
275: logger.log(Level.FINE, MessagesMessages
276: .WSTCP_1105_WSTCP_DELEGATE_DESTROY());
277: }
278:
279: /**
280: * Returns TCPAdapter for service channel
281: * cannot do that once in constructor because of GF startup performance
282: * initialize it lazy
283: */
284: private @NotNull
285: TCPAdapter getServiceChannelWSAdapter() throws Exception {
286: if (serviceChannelWSAdapter == null) {
287: registerServiceChannelWSAdapter();
288: }
289:
290: return serviceChannelWSAdapter;
291: }
292:
293: private void sendErrorResponse(ChannelContext channelContext,
294: WSTCPError error) throws IOException {
295: try {
296: TCPAdapter.sendErrorResponse(channelContext, error);
297: } catch (Throwable e) {
298: logger.log(Level.SEVERE, MessagesMessages
299: .WSTCP_0002_SERVER_ERROR_MESSAGE_SENDING_FAILED(),
300: e);
301: throw new IOException(e.getClass().getName() + ": "
302: + e.getMessage());
303: }
304: }
305:
306: private synchronized void registerServiceChannelWSAdapter()
307: throws Exception {
308: if (serviceChannelWSAdapter == null) {
309: WSEndpoint<ServiceChannelWSImpl> endpoint = ServiceChannelCreator
310: .getServiceChannelEndpointInstance();
311: final String serviceNameLocal = endpoint.getServiceName()
312: .getLocalPart();
313:
314: serviceChannelWSAdapter = new TCPServiceChannelWSAdapter(
315: serviceNameLocal,
316: TCPConstants.SERVICE_CHANNEL_URL_PATTERN, endpoint,
317: this);
318: registerEndpointUrlPattern(
319: TCPConstants.SERVICE_CHANNEL_CONTEXT_PATH,
320: serviceChannelWSAdapter);
321: }
322: }
323: }
|