1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.ws.api.pipe; 27 28 import com.sun.istack.internal.NotNull; 29 import com.sun.istack.internal.Nullable; 30 import com.sun.xml.internal.ws.api.EndpointAddress; 31 import com.sun.xml.internal.ws.api.pipe.helper.PipeAdapter; 32 import com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe; 33 import com.sun.xml.internal.ws.util.ServiceFinder; 34 import com.sun.xml.internal.ws.util.pipe.StandaloneTubeAssembler; 35 import java.util.logging.Level; 36 37 import javax.xml.ws.WebServiceException; 38 import java.util.logging.Logger; 39 40 /** 41 * Factory for transport tubes that enables transport pluggability. 42 * 43 * <p> 44 * At runtime, on the client side, JAX-WS (more specifically the default {@link TubelineAssembler} 45 * of JAX-WS client runtime) relies on this factory to create a suitable transport {@link Tube} 46 * that can handle the given {@link EndpointAddress endpoint address}. 47 * 48 * <p> 49 * JAX-WS extensions that provide additional transport support can 50 * extend this class and implement the {@link #doCreate} method. 51 * They are expected to check the scheme of the endpoint address 52 * (and possibly some other settings from bindings), and create 53 * their transport tube implementations accordingly. 54 * For example, 55 * 56 * <pre> 57 * class MyTransportTubeFactoryImpl { 58 * Tube doCreate(...) { 59 * String scheme = address.getURI().getScheme(); 60 * if(scheme.equals("foo")) 61 * return new MyTransport(...); 62 * else 63 * return null; 64 * } 65 * } 66 * </pre> 67 * 68 * <p> 69 * {@link TransportTubeFactory} look-up follows the standard service 70 * discovery mechanism, so you need 71 * {@code META-INF/services/com.sun.xml.internal.ws.api.pipe.BasicTransportTubeFactory}. 72 * 73 * @author Jitendra Kotamraju 74 * @see StandaloneTubeAssembler 75 */ 76 public abstract class TransportTubeFactory { 77 /** 78 * Creates a transport {@link Tube} for the given port, if this factory can do so, 79 * or return null. 80 * 81 * @param context 82 * Object that captures various contextual information 83 * that can be used to determine the tubeline to be assembled. 84 * 85 * @return 86 * null to indicate that this factory isn't capable of creating a transport 87 * for this port (which causes the caller to search for other {@link TransportTubeFactory}s 88 * that can. Or non-null. 89 * 90 * @throws WebServiceException 91 * if this factory is capable of creating a transport tube but some fatal 92 * error prevented it from doing so. This exception will be propagated 93 * back to the user application, and no further {@link TransportTubeFactory}s 94 * are consulted. 95 */ 96 public abstract Tube doCreate(@NotNull ClientTubeAssemblerContext context); 97 98 private static final TransportTubeFactory DEFAULT = new DefaultTransportTubeFactory(); 99 private static class DefaultTransportTubeFactory extends TransportTubeFactory { 100 101 @Override 102 public Tube doCreate(ClientTubeAssemblerContext context) { 103 return createDefault(context); 104 } 105 106 } 107 108 /** 109 * Locates {@link TransportTubeFactory}s and create a suitable transport {@link Tube}. 110 * 111 * @param classLoader 112 * used to locate {@code META-INF/servces} files. 113 * @return 114 * Always non-null, since we fall back to our default {@link Tube}. 115 */ 116 public static Tube create(@Nullable ClassLoader classLoader, @NotNull ClientTubeAssemblerContext context) { 117 for (TransportTubeFactory factory : ServiceFinder.find(TransportTubeFactory.class,classLoader, context.getContainer())) { 118 Tube tube = factory.doCreate(context); 119 if (tube !=null) { 120 if (logger.isLoggable(Level.FINE)) { 121 TransportTubeFactory.logger.log(Level.FINE, "{0} successfully created {1}", new Object[]{factory.getClass(), tube}); 122 } 123 return tube; 124 } 125 } 126 127 // See if there is a {@link TransportPipeFactory} out there and use it for compatibility. 128 ClientPipeAssemblerContext ctxt = new ClientPipeAssemblerContext( 129 context.getAddress(), context.getWsdlModel(), context.getService(), 130 context.getBinding(), context.getContainer()); 131 ctxt.setCodec(context.getCodec()); 132 for (TransportPipeFactory factory : ServiceFinder.find(TransportPipeFactory.class,classLoader)) { 133 Pipe pipe = factory.doCreate(ctxt); 134 if (pipe!=null) { 135 if (logger.isLoggable(Level.FINE)) { 136 logger.log(Level.FINE, "{0} successfully created {1}", new Object[]{factory.getClass(), pipe}); 137 } 138 return PipeAdapter.adapt(pipe); 139 } 140 } 141 142 return DEFAULT.createDefault(ctxt); 143 } 144 145 protected Tube createDefault(ClientTubeAssemblerContext context) { 146 // default built-in transports 147 String scheme = context.getAddress().getURI().getScheme(); 148 if (scheme != null) { 149 if(scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) 150 return createHttpTransport(context); 151 } 152 throw new WebServiceException("Unsupported endpoint address: "+context.getAddress()); // TODO: i18n 153 } 154 155 protected Tube createHttpTransport(ClientTubeAssemblerContext context) { 156 return new HttpTransportPipe(context.getCodec(), context.getBinding()); 157 } 158 159 private static final Logger logger = Logger.getLogger(TransportTubeFactory.class.getName()); 160 }