diff -r 88b85470e72c -r f50545b5e2f1 src/share/jaxws_classes/com/sun/xml/internal/ws/api/EndpointAddress.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/api/EndpointAddress.java Tue Mar 06 16:09:35 2012 -0800 @@ -0,0 +1,232 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.ws.api; + + +import com.sun.istack.internal.Nullable; + +import javax.xml.ws.WebServiceException; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.util.Iterator; + +/** + * Represents the endpoint address URI. + * + *

+ * Conceptually this can be really thought of as an {@link URI}, + * but it hides some of the details that improve the performance. + * + *

+ * Being an {@link URI} allows this class to represent custom made-up URIs + * (like "jms" for example.) Whenever possible, this object + * also creates an {@link URL} (this is only possible when the address + * has a registered {@link URLStreamHandler}), so that if the clients + * of this code wants to use it, it can do so. + * + * + *

How it improves the performance

+ *
    + *
  1. + * Endpoint address is often eventually turned into an {@link URLConnection}, + * and given that generally this value is read more often than being set, + * it makes sense to eagerly turn it into an {@link URL}, + * thereby avoiding a repeated conversion. + * + *
  2. + * JDK spends a lot of time choosing a list of {@link Proxy} + * to connect to an {@link URL}. Since the default proxy selector + * implementation always return the same proxy for the same URL, + * we can determine the proxy by ourselves to let JDK skip its + * proxy-discovery step. + * + * (That said, user-defined proxy selector can do a lot of interesting things + * --- like doing a round-robin, or pick one from a proxy farm randomly, + * and so it's dangerous to stick to one proxy. For this case, + * we still let JDK decide the proxy. This shouldn't be that much of an + * disappointment, since most people only mess with system properties, + * and never with {@link ProxySelector}. Also, avoiding optimization + * with non-standard proxy selector allows people to effectively disable + * this optimization, which may come in handy for a trouble-shooting.) + *
+ * + * @author Kohsuke Kawaguchi + */ +public final class EndpointAddress { + @Nullable + private URL url; + private final URI uri; + private final String stringForm; + private volatile boolean dontUseProxyMethod; + /** + * Pre-selected proxy. + * + * If {@link #url} is null, this field is null. + * Otherwise, this field could still be null if the proxy couldn't be chosen + * upfront. + */ + private Proxy proxy; + + public EndpointAddress(URI uri) { + this.uri = uri; + this.stringForm = uri.toString(); + try { + initURL(); + proxy = chooseProxy(); + } catch (MalformedURLException e) { + // ignore + } + } + + /** + * + * @see #create(String) + */ + public EndpointAddress(String url) throws URISyntaxException { + this.uri = new URI(url); + this.stringForm = url; + try { + initURL(); + proxy = chooseProxy(); + } catch (MalformedURLException e) { + // ignore + } + } + + + private void initURL() throws MalformedURLException { + String scheme = uri.getScheme(); + //URI.toURL() only works when scheme is not null. + if (scheme == null) { + this.url = new URL(uri.toString()); + return; + } + scheme =scheme.toLowerCase(); + if ("http".equals(scheme) || "https".equals(scheme)) { + url = new URL(uri.toASCIIString()); + } else { + this.url = uri.toURL(); + } + } + + /** + * Creates a new {@link EndpointAddress} with a reasonably + * generic error handling. + */ + public static EndpointAddress create(String url) { + try { + return new EndpointAddress(url); + } catch(URISyntaxException e) { + throw new WebServiceException("Illegal endpoint address: "+url,e); + } + } + + private Proxy chooseProxy() { + ProxySelector sel = + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public ProxySelector run() { + return ProxySelector.getDefault(); + } + }); + + if(sel==null) + return Proxy.NO_PROXY; + + + if(!sel.getClass().getName().equals("sun.net.spi.DefaultProxySelector")) + // user-defined proxy. may return a different proxy for each invocation + return null; + + Iterator it = sel.select(uri).iterator(); + if(it.hasNext()) + return it.next(); + + return Proxy.NO_PROXY; + } + + /** + * Returns an URL of this endpoint adress. + * + * @return + * null if this endpoint address doesn't have a registered {@link URLStreamHandler}. + */ + public URL getURL() { + return url; + } + + /** + * Returns an URI of the endpoint address. + * + * @return + * always non-null. + */ + public URI getURI() { + return uri; + } + + /** + * Tries to open {@link URLConnection} for this endpoint. + * + *

+ * This is possible only when an endpoint address has + * the corresponding {@link URLStreamHandler}. + * + * @throws IOException + * if {@link URL#openConnection()} reports an error. + * @throws AssertionError + * if this endpoint doesn't have an associated URL. + * if the code is written correctly this shall never happen. + */ + public URLConnection openConnection() throws IOException { + assert url!=null : uri+" doesn't have the corresponding URL"; + if (url == null) { + throw new WebServiceException("URI="+uri+" doesn't have the corresponding URL"); + } + if(proxy!=null && !dontUseProxyMethod) { + try { + return url.openConnection(proxy); + } catch(UnsupportedOperationException e) { + // Some OSGi and app server environments donot + // override URLStreamHandler.openConnection(URL, Proxy) as it + // is introduced in Java SE 5 API. Fallback to the other method. + dontUseProxyMethod = true; + } + } + return url.openConnection(); + } + + public String toString() { + return stringForm; + } +}