1/*
2 * Copyright (c) 1997, 2017, 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
26package com.sun.xml.internal.ws.util;
27
28import com.sun.xml.internal.ws.api.pipe.Tube;
29import com.sun.xml.internal.ws.api.pipe.TubeCloner;
30
31import javax.xml.bind.JAXBContext;
32import javax.xml.bind.JAXBException;
33
34import java.util.concurrent.ConcurrentLinkedQueue;
35import java.lang.ref.SoftReference;
36
37
38/**
39 * General-purpose object pool.
40 *
41 * <p>
42 * In many parts of the runtime, we need to pool instances of objects that
43 * are expensive to create (such as JAXB objects, StAX parsers, {@link Tube} instances.)
44 *
45 * <p>
46 * This class provides a default implementation of such a pool.
47 *
48 * TODO: improve the implementation
49 *
50 * @author Kohsuke Kawaguchi
51 */
52public abstract class Pool<T> {
53
54    // volatile since multiple threads may access queue reference
55    private volatile SoftReference<ConcurrentLinkedQueue<T>> queue;
56
57    /**
58     * Gets a new object from the pool.
59     *
60     * <p>
61     * If no object is available in the pool, this method creates a new one.
62     *
63     * @return
64     *      always non-null.
65     */
66    public final T take() {
67        T t = getQueue().poll();
68        if(t==null)
69            return create();
70        return t;
71    }
72
73    private ConcurrentLinkedQueue<T> getQueue() {
74        SoftReference<ConcurrentLinkedQueue<T>> q = queue;
75        if (q != null) {
76            ConcurrentLinkedQueue<T> d = q.get();
77            if (d != null)
78                return d;
79        }
80
81        // overwrite the queue
82        ConcurrentLinkedQueue<T> d = new ConcurrentLinkedQueue<T>();
83        queue = new SoftReference<ConcurrentLinkedQueue<T>>(d);
84
85        return d;
86    }
87
88    /**
89     * Returns an object back to the pool.
90     */
91    public final void recycle(T t) {
92        getQueue().offer(t);
93    }
94
95    /**
96     * Creates a new instance of object.
97     *
98     * <p>
99     * This method is used when someone wants to
100     * {@link #take() take} an object from an empty pool.
101     *
102     * <p>
103     * Also note that multiple threads may call this method
104     * concurrently.
105     */
106    protected abstract T create();
107
108
109    /**
110     * JAXB {@link javax.xml.bind.Marshaller} pool.
111     */
112    public static final class Marshaller extends Pool<javax.xml.bind.Marshaller> {
113        private final JAXBContext context;
114
115        public Marshaller(JAXBContext context) {
116            this.context = context;
117        }
118
119        @Override
120        protected javax.xml.bind.Marshaller create() {
121            try {
122                return context.createMarshaller();
123            } catch (JAXBException e) {
124                // impossible
125                throw new AssertionError(e);
126            }
127        }
128    }
129
130    /**
131     * JAXB {@link javax.xml.bind.Marshaller} pool.
132     */
133    public static final class Unmarshaller extends Pool<javax.xml.bind.Unmarshaller> {
134        private final JAXBContext context;
135
136        public Unmarshaller(JAXBContext context) {
137            this.context = context;
138        }
139
140        @Override
141        protected javax.xml.bind.Unmarshaller create() {
142            try {
143                return context.createUnmarshaller();
144            } catch (JAXBException e) {
145                // impossible
146                throw new AssertionError(e);
147            }
148        }
149    }
150
151    /**
152     * {@link Tube} pool.
153     */
154    public static final class TubePool extends Pool<Tube> {
155        private final Tube master;
156
157        public TubePool(Tube master) {
158            this.master = master;
159            recycle(master);    // we'll use master as a part of the pool, too.
160        }
161
162        @Override
163        protected Tube create() {
164            return TubeCloner.clone(master);
165        }
166
167        /**
168         *
169         * @return master tubeline from pool
170         * @deprecated Expected to be used in rare cases where access to master
171         * tubeline is required and safe, such as Stub.close()."
172         */
173        @Deprecated()
174        public final Tube takeMaster() {
175            return master;
176        }
177
178    }
179}
180