1 /* 2 * Copyright (c) 1997, 2010, 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.server; 27 28 import com.sun.xml.internal.ws.api.config.management.Reconfigurable; 29 import com.sun.xml.internal.ws.api.Component; 30 import com.sun.xml.internal.ws.api.pipe.Codec; 31 import com.sun.xml.internal.ws.api.message.Packet; 32 import com.sun.xml.internal.ws.api.server.WSEndpoint.PipeHead; 33 import com.sun.xml.internal.ws.util.Pool; 34 35 /** 36 * Receives incoming messages from a transport (such as HTTP, JMS, etc) 37 * in a transport specific way, and delivers it to {@link WSEndpoint.PipeHead#process}. 38 * 39 * <p> 40 * Since this class mostly concerns itself with converting a 41 * transport-specific message representation to a {@link Packet}, 42 * the name is the "adapter". 43 * 44 * <p> 45 * The purpose of this class is twofolds: 46 * 47 * <ol> 48 * <li> 49 * To hide the logic of converting a transport-specific connection 50 * to a {@link Packet} and do the other way around. 51 * 52 * <li> 53 * To manage thread-unsafe resources, such as {@link WSEndpoint.PipeHead}, 54 * and {@link Codec}. 55 * </ol> 56 * 57 * <p> 58 * {@link Adapter}s are extended to work with each kind of transport, 59 * and therefore {@link Adapter} class itself is not all that 60 * useful by itself --- it merely provides a design template 61 * that can be followed. 62 * 63 * <p> 64 * For managing resources, an adapter uses an object called {@link Toolkit} 65 * (think of it as a tray full of tools that a dentist uses --- 66 * trays are identical, but each patient has to get one. You have 67 * a pool of them and you assign it to a patient.) 68 * 69 * {@link Adapter.Toolkit} can be extended by derived classes. 70 * That actual type is the {@code TK} type parameter this class takes. 71 * 72 * @author Kohsuke Kawaguchi 73 */ 74 public abstract class Adapter<TK extends Adapter.Toolkit> 75 implements Reconfigurable, Component { 76 77 protected final WSEndpoint<?> endpoint; 78 79 /** 80 * Object that groups all thread-unsafe resources. 81 */ 82 public class Toolkit { 83 /** 84 * For encoding/decoding infoset to/from the byte stream. 85 */ 86 public final Codec codec; 87 /** 88 * This object from {@link WSEndpoint} serves the request. 89 */ 90 public final PipeHead head; 91 92 public Toolkit() { 93 this.codec = endpoint.createCodec(); 94 this.head = endpoint.createPipeHead(); 95 } 96 } 97 98 /** 99 * Pool of {@link Toolkit}s. 100 * 101 * Instances of this pool may be replaced at runtime. Therefore, when you take 102 * an object out of the pool, you must make sure that it is recycled by the 103 * same instance of the pool. 104 */ 105 protected volatile Pool<TK> pool = new Pool<TK>() { 106 protected TK create() { 107 return createToolkit(); 108 } 109 }; 110 111 /** 112 * Creates an {@link Adapter} that delivers 113 * messages to the given endpoint. 114 */ 115 protected Adapter(WSEndpoint endpoint) { 116 assert endpoint!=null; 117 this.endpoint = endpoint; 118 // Enables other components to reconfigure this adapter 119 endpoint.getComponents().add(getEndpointComponent()); 120 } 121 122 protected Component getEndpointComponent() { 123 return new Component() { 124 public <S> S getSPI(Class<S> spiType) { 125 if (spiType.isAssignableFrom(Reconfigurable.class)) { 126 return spiType.cast(Adapter.this); 127 } 128 return null; 129 } 130 }; 131 } 132 133 /** 134 * The pool instance needs to be recreated to prevent reuse of old Toolkit instances. 135 */ 136 public void reconfigure() { 137 this.pool = new Pool<TK>() { 138 protected TK create() { 139 return createToolkit(); 140 } 141 }; 142 } 143 144 public <S> S getSPI(Class<S> spiType) { 145 if (spiType.isAssignableFrom(Reconfigurable.class)) { 146 return spiType.cast(this); 147 } 148 if (endpoint != null) { 149 return endpoint.getSPI(spiType); 150 } 151 return null; 152 } 153 154 /** 155 * Gets the endpoint that this {@link Adapter} is serving. 156 * 157 * @return 158 * always non-null. 159 */ 160 public WSEndpoint<?> getEndpoint() { 161 return endpoint; 162 } 163 164 /** 165 * Returns a reference to the pool of Toolkits for this adapter. 166 * 167 * The pool may be recreated during runtime reconfiguration and this method 168 * will then return a reference to a new instance. When you recycle a toolkit, 169 * you must make sure that you return it to the same pool instance that you 170 * took it from. 171 * 172 * @return 173 */ 174 protected Pool<TK> getPool() { 175 return pool; 176 } 177 178 /** 179 * Creates a {@link Toolkit} instance. 180 * 181 * <p> 182 * If the derived class doesn't have to add any per-thread state 183 * to {@link Toolkit}, simply implement this as {@code new Toolkit()}. 184 */ 185 protected abstract TK createToolkit(); 186 }