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 }