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: package com.sun.xml.ws.tx.webservice.member;
037:
038: import com.sun.istack.NotNull;
039: import com.sun.xml.ws.api.addressing.AddressingVersion;
040: import com.sun.xml.ws.developer.StatefulWebServiceManager;
041: import com.sun.xml.ws.tx.common.AddressManager;
042: import static com.sun.xml.ws.tx.common.Constants.UNKNOWN_ID;
043: import com.sun.xml.ws.tx.common.StatefulWebserviceFactory;
044: import com.sun.xml.ws.tx.common.TxLogger;
045: import com.sun.xml.ws.tx.webservice.member.at.CoordinatorPortType;
046: import com.sun.xml.ws.tx.webservice.member.at.CoordinatorPortTypeImpl;
047: import com.sun.xml.ws.tx.webservice.member.at.ParticipantPortType;
048: import com.sun.xml.ws.tx.webservice.member.at.ParticipantPortTypeImpl;
049: import com.sun.xml.ws.tx.webservice.member.coord.RegistrationCoordinatorPortType;
050: import com.sun.xml.ws.tx.webservice.member.coord.RegistrationCoordinatorPortTypeImpl;
051: import com.sun.xml.ws.tx.webservice.member.coord.RegistrationRequesterPortType;
052: import com.sun.xml.ws.tx.webservice.member.coord.RegistrationRequesterPortTypeImpl;
053:
054: import javax.net.ssl.HostnameVerifier;
055: import javax.net.ssl.HttpsURLConnection;
056: import javax.net.ssl.SSLSession;
057: import javax.xml.ws.EndpointReference;
058: import java.io.BufferedReader;
059: import java.io.InputStream;
060: import java.io.InputStreamReader;
061: import java.net.HttpURLConnection;
062: import java.net.URI;
063: import java.net.URL;
064: import java.util.logging.Level;
065:
066: /**
067: * This class ...
068: *
069: * @author Ryan.Shoemaker@Sun.COM
070: * @version $Revision: 1.11 $
071: * @since 1.0
072: */
073: // suppress known deprecation warnings about using short term workaround StatefulWebService.export(Class, String webServiceEndpoint, PortType)
074: @SuppressWarnings("deprecation")
075: final public class TXStatefulWebserviceFactoryImpl implements
076: StatefulWebserviceFactory {
077:
078: private static final TxLogger logger = TxLogger
079: .getLogger(TXStatefulWebserviceFactoryImpl.class);
080:
081: @NotNull
082: public StatefulWebServiceManager getManager(@NotNull
083: String serviceName, @NotNull
084: String portName) {
085: registerFallback();
086: if (serviceName.equals(ParticipantPortTypeImpl.serviceName)) {
087: // ParticipantPortTypeImpl && CoordinatorPortTypeImpl have the same serviceName
088: if (portName.equals(ParticipantPortTypeImpl.portName)) {
089: return ParticipantPortTypeImpl.getManager();
090: } else if (portName
091: .equals(CoordinatorPortTypeImpl.portName)) {
092: return CoordinatorPortTypeImpl.getManager();
093: } else {
094: throw new IllegalStateException(LocalizationMessages
095: .WSTX_SERVICE_PORT_NOT_FOUND_5001(portName,
096: serviceName));
097: }
098: } else if (serviceName
099: .equals(RegistrationRequesterPortTypeImpl.serviceName)) {
100: if (portName
101: .equals(RegistrationRequesterPortTypeImpl.portName)) {
102: return RegistrationRequesterPortTypeImpl.getManager();
103: } else if (portName
104: .equals(RegistrationCoordinatorPortTypeImpl.portName)) {
105: return RegistrationCoordinatorPortTypeImpl.getManager();
106: } else {
107: throw new IllegalStateException(LocalizationMessages
108: .WSTX_SERVICE_PORT_NOT_FOUND_5001(portName,
109: serviceName));
110: }
111: } else {
112: throw new IllegalStateException(LocalizationMessages
113: .WSTX_SERVICE_PORT_NOT_FOUND_5001(portName,
114: serviceName));
115: }
116: }
117:
118: @NotNull
119: public EndpointReference createService(@NotNull
120: String serviceName, @NotNull
121: String portName, @NotNull
122: URI address, @NotNull
123: AddressingVersion addressingVersion, @NotNull
124: String activityId, @NotNull
125: String registrantId) {
126: registerFallback();
127: if (serviceName.equals(ParticipantPortTypeImpl.serviceName)) {
128: // ParticipantPortTypeImpl && CoordinatorPortTypeImpl have the same serviceName
129: if (portName.equals(ParticipantPortTypeImpl.portName)) {
130: ParticipantPortTypeImpl participant = new ParticipantPortTypeImpl(
131: activityId, registrantId);
132: return ParticipantPortTypeImpl.getManager().export(
133: addressingVersion.eprType.eprClass,
134: address.toString(), participant);
135: } else if (portName
136: .equals(CoordinatorPortTypeImpl.portName)) {
137: CoordinatorPortTypeImpl coordinator = new CoordinatorPortTypeImpl(
138: activityId, registrantId);
139: return CoordinatorPortTypeImpl.getManager().export(
140: addressingVersion.eprType.eprClass,
141: address.toString(), coordinator);
142: } else {
143: throw new IllegalStateException(LocalizationMessages
144: .WSTX_SERVICE_PORT_NOT_FOUND_5001(portName,
145: serviceName));
146: }
147: } else if (serviceName
148: .equals(RegistrationRequesterPortTypeImpl.serviceName)) {
149: if (portName
150: .equals(RegistrationRequesterPortTypeImpl.portName)) {
151: RegistrationRequesterPortTypeImpl registrationRequester = new RegistrationRequesterPortTypeImpl(
152: activityId, registrantId);
153: return RegistrationRequesterPortTypeImpl.getManager()
154: .export(addressingVersion.eprType.eprClass,
155: address.toString(),
156: registrationRequester);
157: } else if (portName
158: .equals(RegistrationCoordinatorPortTypeImpl.portName)) {
159: RegistrationCoordinatorPortTypeImpl registrationCoordinator = new RegistrationCoordinatorPortTypeImpl(
160: activityId);
161: return RegistrationCoordinatorPortTypeImpl.getManager()
162: .export(addressingVersion.eprType.eprClass,
163: address.toString(),
164: registrationCoordinator);
165: } else {
166: throw new IllegalStateException(LocalizationMessages
167: .WSTX_SERVICE_PORT_NOT_FOUND_5001(portName,
168: serviceName));
169: }
170: } else {
171: throw new IllegalStateException(LocalizationMessages
172: .WSTX_SERVICE_PORT_NOT_FOUND_5001(portName,
173: serviceName));
174: }
175: }
176:
177: static private boolean registeredFallback = false;
178:
179: static private boolean wstxServiceAvailable = false;
180:
181: /**
182: * Returns true iff all endpoints for wstx_service are available.
183: *
184: * Identifies when no coordinator specified for application client.
185: * Also, identifies when there is a configuration issue for wstx_service.
186: */
187: public boolean isWSTXServiceAvailable() {
188: registerFallback();
189: return wstxServiceAvailable;
190: }
191:
192: /**
193: * Instances that handle request for unknown StatefulWebService instance.
194: * This can happen when a request for a StatefulWebService is received after the instance has
195: * timed out or was explicitly unexported.
196: */
197: private void registerFallback() {
198: if (!registeredFallback) {
199: registeredFallback = true;
200:
201: // force the lazy deployment of our ws so we can access the stateful manager field
202: pingStatefulServices();
203:
204: if (isWSTXServiceAvailable()) {
205: ParticipantPortTypeImpl participant = new ParticipantPortTypeImpl(
206: UNKNOWN_ID, UNKNOWN_ID);
207: if (ParticipantPortTypeImpl.getManager() != null) {
208: ParticipantPortTypeImpl.getManager()
209: .setFallbackInstance(participant);
210: } else {
211: wstxServiceAvailable = false;
212: }
213:
214: CoordinatorPortTypeImpl coordinator = new CoordinatorPortTypeImpl(
215: UNKNOWN_ID, UNKNOWN_ID);
216: if (CoordinatorPortTypeImpl.getManager() != null) {
217: CoordinatorPortTypeImpl.getManager()
218: .setFallbackInstance(coordinator);
219: } else {
220: wstxServiceAvailable = false;
221: }
222:
223: RegistrationRequesterPortTypeImpl registrationRequester = new RegistrationRequesterPortTypeImpl(
224: UNKNOWN_ID, UNKNOWN_ID);
225: if (RegistrationRequesterPortTypeImpl.getManager() != null) {
226: RegistrationRequesterPortTypeImpl.getManager()
227: .setFallbackInstance(registrationRequester);
228: } else {
229: wstxServiceAvailable = false;
230: }
231:
232: RegistrationCoordinatorPortTypeImpl registrationCoordinator = new RegistrationCoordinatorPortTypeImpl(
233: UNKNOWN_ID);
234: if (RegistrationCoordinatorPortTypeImpl.getManager() != null) {
235: RegistrationCoordinatorPortTypeImpl.getManager()
236: .setFallbackInstance(
237: registrationCoordinator);
238: } else {
239: wstxServiceAvailable = false;
240: }
241: } else {
242: registeredFallback = false;
243: }
244: }
245: }
246:
247: private boolean pingServices = true;
248:
249: /**
250: * A workaround for WSIT issue 309
251: * <p/>
252: * The GF performance team does not want our wstx services to load during app server
253: * startup, so they are marked to lazy deploy upon the first invocation. Unfortunately
254: * we need to access the stateful webservice manager field in some of these services
255: * before the first invocation, so we will ping each of them to force the load to happen.
256: * <p/>
257: * This will only happen once and it will only happen after we are certain that an app
258: * needs these services running.
259: */
260: private void pingStatefulServices() {
261: if (pingServices) {
262: pingServices = false;
263: wstxServiceAvailable = true; // if any pingService fails, this reverts to false.
264:
265: if (logger.isLogging(Level.FINEST)) {
266: logger.finest("pingStatefulServices",
267: "pinging register service...");
268: }
269: pingService((AddressManager.getAddress(
270: RegistrationCoordinatorPortType.class, false)
271: .toString() + "?wsdl"),
272: RegistrationCoordinatorPortTypeImpl.class);
273: if (!wstxServiceAvailable) {
274: return; // short-circuit if the first ping fails
275: }
276: if (logger.isLogging(Level.FINEST)) {
277: logger.finest("pingStatefulServices",
278: "pinging registerResponse service...");
279: }
280: pingService((AddressManager.getAddress(
281: RegistrationRequesterPortType.class, false)
282: .toString() + "?wsdl"),
283: RegistrationRequesterPortTypeImpl.class);
284: if (logger.isLogging(Level.FINEST)) {
285: logger.finest("pingStatefulServices",
286: "pinging ATCoordinator service...");
287: }
288: pingService(
289: (AddressManager.getAddress(
290: CoordinatorPortType.class, false)
291: .toString() + "?wsdl"),
292: CoordinatorPortTypeImpl.class);
293: if (logger.isLogging(Level.FINEST)) {
294: logger.finest("pingStatefulServices",
295: "pinging ATParticipant service...");
296: }
297: pingService(
298: (AddressManager.getAddress(
299: ParticipantPortType.class, false)
300: .toString() + "?wsdl"),
301: ParticipantPortTypeImpl.class);
302: }
303: }
304:
305: /*
306: * This method accesses a url specifically to force the app server to completely
307: * load our stateful webservices. We're pinging the services by accessing their
308: * wsdl files.
309: *
310: * PostCondition: if pingService fails, sets wstxServiceAvailable to false.
311: */
312: private void pingService(String urlAddr, Class sws) {
313: final String METHOD = "pingService";
314: HttpURLConnection conn = null;
315: InputStream response = null;
316: BufferedReader reader = null;
317: try {
318: URL url = new URL(urlAddr);
319: conn = (HttpURLConnection) url.openConnection();
320: if (conn instanceof HttpsURLConnection) {
321: ((HttpsURLConnection) conn)
322: .setHostnameVerifier(new HostnameVerifier() {
323: public boolean verify(String string,
324: SSLSession sSLSession) {
325: return true;
326: }
327: });
328: }
329: conn.setRequestMethod("GET");
330: conn.setRequestProperty("Content-Type",
331: "application/x-www-form-urlencoded"); // taken from wsimport
332: conn.connect();
333: response = conn.getInputStream();
334: reader = new BufferedReader(new InputStreamReader(response));
335: String line = reader.readLine();
336: while (line != null) {
337: // logger.finest(METHOD, line);
338: line = reader.readLine();
339: }
340: if (logger.isLogging(Level.FINEST)) {
341: logger.finest(METHOD, "RESPONSE CODE: "
342: + conn.getResponseCode());
343: }
344: if (sws.getDeclaredField("manager").equals(null)) {
345: logger.severe(METHOD, LocalizationMessages
346: .ENDPOINT_NOT_AVAILABLE_5002(urlAddr, sws
347: .getName()));
348: } else {
349: logger.finest(METHOD, "Injection succeeded");
350: }
351: } catch (Exception e) {
352: if (wstxServiceAvailable) {
353: wstxServiceAvailable = false;
354:
355: // only print stacktrace for first endpoint ping failure.
356: logger.warning(METHOD, LocalizationMessages
357: .ENDPOINT_NOT_AVAILABLE_5002(urlAddr, sws
358: .getName()));
359: logger.fine(METHOD, LocalizationMessages
360: .ENDPOINT_NOT_AVAILABLE_5002(urlAddr, sws
361: .getName()), e);
362: } else {
363: logger.severe(METHOD, LocalizationMessages
364: .ENDPOINT_NOT_AVAILABLE_5002(urlAddr, sws
365: .getName()));
366: }
367: } finally {
368: try {
369: if (conn != null)
370: conn.disconnect();
371: if (reader != null)
372: reader.close();
373: } catch (Exception e) {
374: // ignore
375: }
376: }
377: }
378: }
|