View Javadoc
1   package org.apache.fulcrum.pool;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.lang.reflect.Method;
23  import java.util.ArrayList;
24  
25  import org.apache.fulcrum.factory.FactoryService;
26  
27  /**
28   * An inner class for class specific pools.
29   */
30  public class PoolBuffer 
31  {
32  
33  	/**
34  	 * A buffer for class instances.
35  	 */
36  	private BoundedBuffer pool;
37  
38  	/**
39  	 * A flag to determine if a more efficient recycler is implemented.
40  	 */
41  	private boolean arrayCtorRecyclable;
42  
43  	/**
44  	 * A cache for recycling methods.
45  	 */
46  	private ArrayList<Recycler> recyclers;
47  
48  	/**
49  	 * Constructs a new pool buffer with a specific capacity.
50  	 *
51  	 * @param capacity a capacity.
52  	 */
53  	public PoolBuffer(int capacity) 
54  	{
55  		pool = new BoundedBuffer(capacity);
56  	}
57  
58  	/**
59  	 * Tells pool that it contains objects which can be initialized using an Object
60  	 * array.
61  	 *
62  	 * @param isArrayCtor a <code>boolean</code> value
63  	 */
64  	public void setArrayCtorRecyclable(boolean isArrayCtor) 
65  	{
66  		arrayCtorRecyclable = isArrayCtor;
67  	}
68  
69  	/**
70  	 * Polls for an instance from the pool.
71  	 * 
72  	 * 
73  	 * @param params         object parameters
74  	 * @param signature      signature of the class
75  	 * @param factoryService service to add
76  	 * @throws PoolException if service failed to be found
77  	 * @return an instance or null.
78  	 */
79  	public <T> T poll(Object[] params, String[] signature, FactoryService factoryService) throws PoolException 
80  	{
81  		T instance = pool.poll();
82  		if (instance != null) 
83  		{
84  			if (arrayCtorRecyclable) 
85  			{
86  				((ArrayCtorRecyclable) instance).recycle(params);
87  			} else if (instance instanceof Recyclable) {
88  				try 
89  				{
90  					if (signature != null && signature.length > 0) 
91  					{
92  						/* Get the recycle method from the cache. */
93  						Method recycle = getRecycle(signature);
94  						if (recycle == null) 
95  						{
96  							synchronized (this) {
97  								/* Make a synchronized recheck. */
98  								recycle = getRecycle(signature);
99  								if (recycle == null) 
100 								{
101 									Class<? extends Object> clazz = instance.getClass();
102 									recycle = clazz.getMethod("recycle",
103 											factoryService.getSignature(clazz, params, signature));
104 
105 									@SuppressWarnings("unchecked")
106 									ArrayList<Recycler> cache = recyclers != null
107 											? (ArrayList<Recycler>) recyclers.clone()
108 											: new ArrayList<Recycler>();
109 									cache.add(new Recycler(recycle, signature));
110 									recyclers = cache;
111 								}
112 							}
113 						}
114 						recycle.invoke(instance, params);
115 					} else {
116 						((Recyclable) instance).recycle();
117 					}
118 				} 
119 				catch (Exception x) 
120 				{
121 					throw new PoolException("Recycling failed for " + instance.getClass().getName(), x);
122 				}
123 			}
124 		}
125 		return instance;
126 	}
127 
128 	/**
129 	 * Offers an instance to the pool.
130 	 * 
131 	 * @param instance an instance.
132 	 * @return false if failed to dispose
133 	 */
134 	public boolean offer(Object instance) 
135 	{
136 		if (instance instanceof Recyclable) 
137 		{
138 			try 
139 			{
140 				((Recyclable) instance).dispose();
141 			} 
142 			catch (Exception x) 
143 			{
144 				return false;
145 			}
146 		}
147 		return pool.offer(instance);
148 	}
149 
150 	/**
151 	 * Returns the capacity of the pool.
152 	 *
153 	 * @return the capacity.
154 	 */
155 	public int capacity() 
156 	{
157 		return pool.capacity();
158 	}
159 
160 	/**
161 	 * Returns the size of the pool.
162 	 *
163 	 * @return the size.
164 	 */
165 	public int size() 
166 	{
167 		return pool.size();
168 	}
169 
170 	/**
171 	 * Returns a cached recycle method corresponding to the given signature.
172 	 *
173 	 * @param signature the signature.
174 	 * @return the recycle method or null.
175 	 */
176 	private Method getRecycle(String[] signature) 
177 	{
178 		ArrayList<Recycler> cache = recyclers;
179 		if (cache != null) 
180 		{
181 			Method recycle;
182 			for (Recycler recycler : cache) 
183 			{
184 				recycle = recycler.match(signature);
185 				if (recycle != null)
186 					return recycle;
187 			}
188 		}
189 		return null;
190 	}
191 }