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.common;
037:
038: import com.sun.xml.ws.tx.webservice.member.at.CoordinatorPortType;
039: import com.sun.xml.ws.tx.webservice.member.at.ParticipantPortType;
040: import com.sun.xml.ws.tx.webservice.member.coord.RegistrationCoordinatorPortType;
041: import com.sun.xml.ws.tx.webservice.member.coord.RegistrationPortTypeRPC;
042: import com.sun.xml.ws.tx.webservice.member.coord.RegistrationRequesterPortType;
043:
044: import java.lang.reflect.Method;
045: import java.net.InetAddress;
046: import java.net.URI;
047: import java.net.URISyntaxException;
048: import java.net.UnknownHostException;
049: import java.util.logging.Level;
050:
051: /**
052: * This class handles all address calculations for the wstx-service enpoints
053: *
054: * @author Ryan.Shoemaker@Sun.COM
055: * @version $Revision: 1.3 $
056: * @since 1.0
057: */
058: public class AddressManager {
059:
060: static final private TxLogger logger = TxLogger
061: .getLogger(AddressManager.class);
062:
063: private static String hostAndPort;
064: private static String secureHostAndPort;
065:
066: private static final String context = "/__wstx-services";
067:
068: // override props - default to https
069: private static String preferredScheme = System.getProperty(
070: "com.sun.xml.ws.tx.preferredScheme", "https");
071: private static String httpPortOverride = System.getProperty(
072: "com.sun.xml.ws.tx.httpPortOverride", null);
073: private static String httpsPortOverride = System.getProperty(
074: "com.sun.xml.ws.tx.httpsPortOverride", null);
075: private static String hostNameOverride = System.getProperty(
076: "com.sun.xml.ws.tx.hostNameOverride", null);
077:
078: static {
079: // get the host and port info from GF
080: callGetDefaultVirtualServerHostAndPort();
081:
082: // log a message if the preferred scheme has been overridden to http
083: if ((preferredScheme.equals("http") && (logger
084: .isLogging(Level.FINEST)))) {
085: logger.fine("static initializer",
086: "preferred scheme has been set to: "
087: + preferredScheme);
088: }
089:
090: // logic to override the dynamic settings
091: // users can select a preferred scheme and override the http and https port numbers if necessary
092: calculateHostAndPortOverrides();
093: }
094:
095: private AddressManager() {
096: }
097:
098: /**
099: * Return an address for the specified port type using the preferred scheme.
100: * <p/>
101: * This method should be used most of the time unless you explicitly know which
102: * scheme you want back.
103: *
104: * @param portType the endpoint port type
105: * @return a URI representing the preferred endpoint address
106: */
107: public static URI getPreferredAddress(Class portType) {
108: return "http".equals(preferredScheme) ? getAddress(portType,
109: false) : getAddress(portType, true);
110: }
111:
112: /**
113: * Return an address for the specified port type based on the 'secure' flag. If
114: * the 'secure' flag is true, the address will begin with "https", otherwise it
115: * will begin with "http".
116: *
117: * @param portType the endpoint port type
118: * @param secure flag to control whether the address is secure or non-secure
119: * @return a URI representing the endpoint address with the specified secure or non-secure scheme
120: */
121: public static URI getAddress(Class portType, boolean secure) {
122: StringBuilder addr = new StringBuilder();
123:
124: if (secure) {
125: addr.append("https://").append(secureHostAndPort).append(
126: context);
127: } else { // non-secure
128: addr.append("http://").append(hostAndPort).append(context);
129: }
130:
131: // assign the proper context path onto the end of the scheme, host, port, and context root
132: // TODO: are there other addresses we need to generate?
133: if (portType == RegistrationCoordinatorPortType.class) {
134: addr.append("/wscoor/coordinator/register");
135: } else if (portType == RegistrationRequesterPortType.class) {
136: addr.append("/wscoor/coordinator/registerResponse");
137: } else if (portType == RegistrationPortTypeRPC.class) {
138: addr.append("/wscoor/coordinator/synchRegister");
139: } else if (portType == CoordinatorPortType.class) {
140: addr.append("/wsat/coordinator");
141: } else if (portType == ParticipantPortType.class) {
142: addr.append("/wsat/2pc");
143: } else {
144: return null;
145: }
146:
147: URI uri = null;
148: try {
149: uri = new URI(addr.toString());
150: } catch (URISyntaxException e) {
151: }
152:
153: return uri;
154: }
155:
156: /**
157: * Call appserv-core/com.sun.enterprise.webservice.WsTxUtils in GF to get the host and port information.
158: */
159: private static void callGetDefaultVirtualServerHostAndPort() {
160: try {
161: if (logger.isLogging(Level.FINEST)) {
162: logger.finest("static initializer",
163: "getting host and port from AS...");
164: }
165: Class c = Class
166: .forName("com.sun.enterprise.webservice.WsTxUtils");
167: Object instance = c.newInstance();
168: Method m = c
169: .getMethod("getDefaultVirtualServerHostAndPort",
170: boolean.class);
171: hostAndPort = (String) m.invoke(instance, false);
172: secureHostAndPort = (String) m.invoke(instance, true);
173:
174: if (secureHostAndPort == null || hostAndPort == null) {
175: // there must have been an error on the GF-side, so fallback to a default
176: fallback();
177: logger
178: .warning(
179: "getAddress",
180: LocalizationMessages
181: .HOST_AND_PORT_LOOKUP_FAILURE_2015(preferredScheme
182: + "://"
183: + secureHostAndPort));
184: }
185:
186: // this is an undocumented override
187: if (hostNameOverride != null) {
188: hostAndPort = hostNameOverride
189: + hostAndPort.substring(hostAndPort
190: .indexOf(':'), hostAndPort.length());
191: secureHostAndPort = hostNameOverride
192: + secureHostAndPort.substring(secureHostAndPort
193: .indexOf(':'), secureHostAndPort
194: .length());
195: logger.finest("static initializer",
196: "manual hostname overridden to: "
197: + hostNameOverride);
198: }
199:
200: if (logger.isLogging(Level.FINEST)) {
201: logger.finest("static initializer", "hostAndPort: "
202: + hostAndPort);
203: logger.finest("static initializer",
204: "secureHostAndPort: " + secureHostAndPort);
205: }
206: } catch (Throwable t) { // trap every possible failure calling the gf code
207: fallback();
208: logger.info("static initializer", LocalizationMessages
209: .HOST_AND_PORT_LOOKUP_FAILURE_2015(preferredScheme
210: + "://" + secureHostAndPort));
211: logger.finest("static initializer", LocalizationMessages
212: .HOST_AND_PORT_LOOKUP_FAILURE_2015(preferredScheme
213: + "://" + secureHostAndPort), t);
214: }
215: }
216:
217: /**
218: * Lookup any system props that override the preferred scheme, and http/s ports
219: */
220: private static void calculateHostAndPortOverrides() {
221: final String hostName = hostAndPort.substring(0, hostAndPort
222: .indexOf(':'));
223: if ("http".equals(preferredScheme)) {
224: if (httpPortOverride != null) {
225: if (logger.isLogging(Level.FINEST)) {
226: logger.finest("static initializer",
227: "http port overriden to: "
228: + httpPortOverride);
229: }
230: hostAndPort = hostName + ':' + httpPortOverride;
231: }
232: } else if ("https".equals(preferredScheme)) {
233: if (httpsPortOverride != null) {
234: if (logger.isLogging(Level.FINEST)) {
235: logger.finest("static initializer",
236: "https port overriden to: "
237: + httpsPortOverride);
238: }
239: secureHostAndPort = hostName + ':' + httpsPortOverride;
240: }
241: } else {
242: logger.warning("static initializer", LocalizationMessages
243: .PREFERRED_SCHEME_ERROR_2016(preferredScheme));
244: preferredScheme = "https";
245: if (httpsPortOverride != null) {
246: if (logger.isLogging(Level.FINEST)) {
247: logger.finest("static initializer",
248: "https port overriden to: "
249: + httpsPortOverride);
250: }
251: secureHostAndPort = hostName + ':' + httpsPortOverride;
252: }
253: }
254: }
255:
256: /**
257: * Set the static fields to sane value that might work as a last-ditch effort.
258: */
259: private static void fallback() {
260: // worst-case scenario: fall back to https://canonicalhostname:8181, but also set
261: // hostAndPort since it is used to ping the services.
262: preferredScheme = "https";
263: final String hostName = getServiceHostName();
264: hostAndPort = hostName + ":8080";
265: secureHostAndPort = hostName + ":8181";
266: }
267:
268: /**
269: * This method returns the fully qualified name of the host. If
270: * the name can't be resolved (on windows if there isn't a domain specified), just
271: * host name is returned
272: *
273: * @return the host name
274: */
275: private static String getServiceHostName() {
276: String hostname = null;
277: try {
278: // look for full name
279: hostname = InetAddress.getLocalHost()
280: .getCanonicalHostName();
281: } catch (UnknownHostException ex) {
282: logger.warning("getServiceHostName", LocalizationMessages
283: .FQDN_LOOKUP_FAILURE_2012(), ex);
284: try {
285: // fallback to ip address
286: hostname = InetAddress.getLocalHost().getHostAddress();
287: } catch (UnknownHostException e) {
288: logger
289: .warning("getServiceHostName",
290: LocalizationMessages
291: .FQDN_LOOKUP_FAILURE_2012(), e);
292: }
293: }
294:
295: return hostname;
296: }
297:
298: }
|