001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.fukurou.util;
017
018 import java.util.MissingResourceException;
019 import java.util.Map;
020 import java.util.HashMap;
021 // import java.util.Date;
022 import java.util.List;
023 import java.util.ArrayList;
024 import java.util.Iterator;
025 // import java.util.Locale ;
026
027 // import java.text.DateFormat;
028 // import java.text.SimpleDateFormat;
029
030 /**
031 * AbstractObjectPool は、生成された Object をã?ールするキャãƒ?‚·ュクラスですã?
032 * サブクラスで、各クラスごとにオブジェクトを生æ??�å?期化?�終äº?�™るよã�?�«å�?ƒ¡ソãƒ?ƒ‰ã‚?
033 * コーãƒ?‚£ングしなおしてくださいã€?
034 * サブクラスでは、Object createInstance() と、oid objectInitial( Object obj )ã€?
035 * void objectFinal( Object obj ) ã‚?オーバã?ライドしてくださいã€?
036 *
037 * @version 4.0
038 * @author Kazuhiko Hasegawa
039 * @since JDK5.0,
040 */
041 abstract public class AbstractObjectPool<E> {
042 /** å†?ƒ¨でオブジェクトをプã?ルしてã�?‚‹配å?ã€? */
043 private List<E> pool = null; // プã?ルしてã�?‚‹オブジェクãƒ?
044 private Map<Integer,TimeStampObject> poolBack = null; // 作æ?したオブジェクトã?タイãƒ?‚¹タンプ管ç�?
045
046 /** プã?ル自体を拡張可能かどã�?�‹を決める変数。拡張制é™?true)?�無制é™?false) */
047 private boolean limit ;
048
049 /** æœ?¤§オブジェクト数 */
050 private int maxsize ;
051
052 /** 生æ?したオブジェクトã?寿命(ç§?を指定しますã? 0 は、制限なしですã?*/
053 private int limitTime ; // 3.5.4.3 (2004/01/05) キャãƒ?‚·ュの寿命を指定しますã?
054
055 /** 制限なしã?場合でもã?実質こã?値以上ã?キャãƒ?‚·ュは、許可しませんã€?/
056 private static final int MAX_LIMIT_COUNT = 1000 ; // 3.6.0.8 (2004/11/19)
057
058 /**
059 * 初期化メソãƒ?ƒ‰
060 *
061 * 初期オブジェクト数、最大オブジェクト数、拡張制限をæŒ?®šしますã?
062 *
063 * 初期オブジェクト数は、ã?ールを作æ?すると同時に確保するオブジェクトã?個数ですã?
064 * オブジェクトã?生æ?に時間がかかり、かつ、å¿?�šè¤?•°使用するのであれば,
065 * 予めè¤?•°確保しておけば、パフォーマンスが向上しますã?
066 * æœ?¤§オブジェクト数は、拡張制限が、無制é™?limit = false )の場合ã?ã€?
067 * 無視されますã?制限ありã?場合ã?、この値を上限に、オブジェクトを増やしますã?
068 * 拡張制限ã?、生成するオブジェクト数に制限をかけるかどã�?�‹を指定しますã?
069 * ä¸?ˆ¬に、コネクション等ã?リソースを確保するå?合ã?、拡張制限をåŠ?�ˆてã€?
070 * 生æ?するオブジェクト数を制限しますã?
071 *
072 * @param minsize 初期オブジェクト数
073 * @param maxsize æœ?¤§オブジェクト数
074 * @param limit 拡張制é™?true)?�無制é™?false)
075 */
076 protected synchronized void init( final int minsize, final int maxsize, final boolean limit ) {
077 init( minsize, maxsize, limit,0 ) ;
078 }
079
080 /**
081 * 初期化メソãƒ?ƒ‰
082 *
083 * 初期オブジェクト数、å?期é?列数、拡張制限ã?オブジェクトã?寿命を指定しますã?
084 *
085 * 初期オブジェクト数、å?期é?列数、拡張制限ã?までは、{@link #init( int , int , boolean ) init}
086 * を参照してくださいã€?
087 * オブジェクトã?寿命は、生成された時間からの経過時間(ç§?ã�?�‘、キャãƒ?‚·ュしておく
088 * 場合に使用しますã?
089 * 例えば、コネクション等でã€?•·期間のプã?リングがリソースを圧迫する場合やã€?
090 * 接続å?自身がã?タイマã?でåˆ?–する場合など、オブジェクトã?生存期間を
091 * æŒ?®šして管ç�?�™るå¿?¦�がありますã?
092 *
093 * @param minsize 初期オブジェクト数
094 * @param maxsize 初期配å?数
095 * @param limit 拡張制é™?true)?�無制é™?false)
096 * @param limitTime オブジェクトã?寿命の時間制限å?(ç§?
097 * @see #init( int , int , boolean )
098 */
099 protected synchronized void init( final int minsize, final int maxsize,
100 final boolean limit,final int limitTime ) {
101 pool = new ArrayList<E>( maxsize );
102 poolBack = new HashMap<Integer,TimeStampObject>();
103 this.maxsize = maxsize;
104 this.limit = limit;
105 this.limitTime = limitTime;
106 for( int i=0; i<minsize; i++ ) {
107 E obj = createInstance();
108 pool.add( obj );
109
110 Integer key = Integer.valueOf( obj.hashCode() );
111 poolBack.put( key,new TimeStampObject( obj,limitTime ) );
112 }
113 }
114
115 /**
116 * キャãƒ?‚·ュのインスタンスを返しますã?
117 *
118 * なおã?拡張制限をしてã�?‚‹場合に、最初に確保した数以上ã?オブジェクト生成ã?
119 * 要求があったå?合ã??¤ MissingResourceException ã�?throw されますã?
120 * まã�?オブジェクトが寿命をè¶?�ˆてã�?‚‹場合ã?、削除した後ã?新たに次の
121 * オブジェクトã?生æ?を行いますã?
122 *
123 * @og.rev 4.0.0.1 (2007/12/03) 生æ?リミットチェãƒ?‚¯を厳å¯?�«行うã€?
124 * @og.rev 4.0.0.1 (2007/12/03) 生æ?リミットエラー時に、タイãƒ?‚¢ウトをチェãƒ?‚¯するã€?
125 *
126 * @return キャãƒ?‚·ュのインスタンス
127 * @throws MissingResourceException 拡張制限により、新しいインスタンスを生成できなã�??å�?
128 */
129 public synchronized E newInstance() throws MissingResourceException {
130 final E rtnobj ;
131 if( pool.isEmpty() ) {
132 if( limit && poolBack.size() >= maxsize ) {
133 String errMsg = "生æ?リミットいっぱã�?�§新たに生æ?できませんã€?"
134 + poolBack.size() + "]";
135
136 // 4.0.0.1 (2007/12/03) 生æ?リミットエラー時に、タイãƒ?‚¢ウトをチェãƒ?‚¯するã€?
137 Iterator<TimeStampObject> itr = poolBack.values().iterator();
138 while( itr.hasNext() ) {
139 TimeStampObject tso = itr.next();
140 if( tso == null || tso.isTimeOver() ) {
141 itr.remove();
142 }
143 }
144
145 throw new MissingResourceException( errMsg,getClass().getName(),"limit" );
146 }
147 else if( poolBack.size() > MAX_LIMIT_COUNT ) {
148 clear(); // 全件キャãƒ?‚·ュをç?æ£?�—ますã?
149 String errMsg = "ObjectPool で、メモリリークの可能性がありますã?["
150 + poolBack.size() + "]";
151 throw new RuntimeException( errMsg );
152 }
153 // 新規作æ?
154 rtnobj = createInstance();
155 Integer key = Integer.valueOf( rtnobj.hashCode() );
156 poolBack.put( key,new TimeStampObject( rtnobj,limitTime ) );
157 }
158 else {
159 // 既存取りå?ã�?
160 rtnobj = pool.remove(0);
161 if( rtnobj != null ) {
162 Integer key = Integer.valueOf( rtnobj.hashCode() );
163 TimeStampObject tso = poolBack.get( key );
164 if( tso == null || tso.isTimeOver() ) {
165 remove( rtnobj );
166 return newInstance();
167 }
168 }
169 else {
170 // 通常ありえなã�??
171 String errMsg = "オブジェクトã?取得に失敗しましたã€? ;
172 throw new MissingResourceException( errMsg,getClass().getName(),"pool" );
173 }
174 }
175
176 return rtnobj;
177 }
178
179 /**
180 * 具体的に新しいインスタンスを生成するメソãƒ?ƒ‰ã€?
181 *
182 * サブクラスで具体的に記述するå¿?¦�がありますã?
183 *
184 * @return 新しいインスタンス
185 */
186 abstract protected E createInstance();
187
188 /**
189 * オブジェクトを、オブジェクトã?ールに戻しますã?
190 * 戻すべきオブジェクトが null の場合ã?,削除されたと判断しますã?
191 *
192 * @param obj オブジェクトã?ールに戻すオブジェクãƒ?
193 */
194 public synchronized void release( final E obj ) {
195 E obj2 = objectInitial( obj );
196 if( obj2 != null ) {
197 Integer key = Integer.valueOf( obj2.hashCode() );
198 TimeStampObject tso = poolBack.get( key );
199 if( tso != null ) {
200 pool.add( obj2 );
201 }
202 else { // 3.5.6.2 (2004/07/05) 追åŠ?
203 LogWriter.log( "ObjectPool で、メモリリークの可能性があるã?[" + obj2 + "]" );
204 remove( obj2 );
205 }
206 }
207 }
208
209 /**
210 * オブジェクトを、オブジェクトã?ールから削除しますã?
211 * remove されるオブジェクトã?、すでにキャãƒ?‚·ュから取り出された後なのでã€?
212 * そã?まま、何もしなければ自然消æ»?GC)されますã?
213 * 自然消æ»?�™る前に、objectFinal( Object ) が呼ばれますã?
214 * 生æ?されたオブジェクトã?総数もã?ひとつ減らしますã?
215 *
216 * @param obj 削除するオブジェクãƒ?
217 */
218 public synchronized void remove( final E obj ) {
219 if( obj != null ) {
220 Integer key = Integer.valueOf( obj.hashCode() );
221 poolBack.remove( key );
222 }
223
224 objectFinal( obj );
225 }
226
227 /**
228 * オブジェクトã?ールの要ç´?•°を返しますã?
229 *
230 * @return プã?ルの要ç´?•°
231 */
232 public synchronized int size() {
233 return poolBack.size();
234 }
235
236 /**
237 * オブジェクトã?ールが要ç´?‚’持たなã�?�‹どã�?�‹を判定しますã?
238 *
239 * @return オブジェクトã?ールが要ç´?‚’持ってã�?�ªã�??つまりそのサイズã�?0 の場合にã�?�‘ true、そã�?�§なã�??合ã? false
240 */
241 public synchronized boolean isEmpty() {
242 return poolBack.isEmpty() ;
243 }
244
245 /**
246 * すべての要ç´?‚’ オブジェクトã?ールから削除しますã?
247 * 貸しå?し中のオブジェクトã?、クリアしません。よって、返り値はã€?
248 * すべてのオブジェクトをクリアできた場合ã?、true 、貸しå?し中の
249 * オブジェクトが存在した場å�?クリアできなかったå?å�?は、false ですã?
250 *
251 * @return すべてクリア(true)/貸しå?し中のオブジェクトが残ってã�?‚‹(false)
252 */
253 public synchronized boolean clear() {
254 Iterator<E> itr = pool.iterator();
255 while( itr.hasNext() ) {
256 remove( itr.next() );
257 }
258 pool.clear();
259
260 // 貸しå?し中の場合ã?、remove 出来なã�?‚º、poolBack に残ってã�?‚‹ã€?
261 // それでもã?poolBack をクリアすることで、release 返却時にもã?
262 // remove されるよã�?�«なりますã?
263 // ただしã?作æ?オブジェクト数がã?ä¸?—¦ 0 にリセãƒ?ƒˆされる為ã€?
264 // æœ?¤§貸しå?し可能数がã?ä¸?™‚çš?�«増えてしまã�?�¾すã?
265 boolean flag = poolBack.isEmpty();
266 poolBack.clear();
267
268 return flag;
269 }
270
271 /**
272 * オブジェクトã?ールから削除するときに呼ばれますã?
273 * こã?メソãƒ?ƒ‰でå�?‚ªブジェクトごとの終äº??ç�?‚’行いますã?
274 * 例えば?¤ãƒ??タベã?スコネクションであれば?¤close() 処ç�?�ªどですã?
275 *
276 * ãƒ?ƒ•ォルトでは、なにも行いませんã€?
277 *
278 * @param obj 終äº??ç�?‚’行うオブジェクãƒ?
279 */
280 protected synchronized void objectFinal( final E obj ) {
281 // ここでは処ç�?‚’行いませんã€?
282 }
283
284 /**
285 * オブジェクトã?ールに戻すとã�?release するとã�?に呼ばれますã?
286 * こã?メソãƒ?ƒ‰でå�?‚ªブジェクトごとの初期処ç�?‚’行いますã?
287 * オブジェクトã?ールに戻すときには?¤初期化して?¤次の貸しå?しに
288 * 対応できるように、å?期å?ç�?�—ておくå¿?¦�がありますã?
289 *
290 * ãƒ?ƒ•ォルトでは、引数のオブジェクトをそã?まま返しますã?
291 *
292 * @param obj 初期処ç�?‚’行うオブジェクãƒ?
293 *
294 * @return 初期処ç�?‚’行ったオブジェクãƒ?
295 */
296 protected synchronized E objectInitial( final E obj ) {
297 return obj;
298 }
299
300 /**
301 * å†?ƒ¨状況を簡易的に表現したæ–?—å?を返しますã?
302 *
303 * @return こã?オブジェクトã?ールのæ–?—å?表現
304 */
305 @Override
306 public synchronized String toString() {
307 StringBuilder buf = new StringBuilder();
308 buf.append( " freeCount = [" ).append( pool.size() ).append( "]\n" );
309 buf.append( " createCount = [" ).append( poolBack.size() ).append( "]" );
310 buf.append( " ( max=[" ).append( maxsize ).append( "] )\n" );
311 buf.append( " limiter = [" ).append( limit ).append( "]\n" );
312 buf.append( " limitTime = [" ).append( limitTime ).append( "](s)\n" );
313
314 Iterator<E> itr = pool.iterator();
315 buf.append( "Free Objects \n" );
316 while( itr.hasNext() ) {
317 E obj = itr.next();
318 if( obj != null ) {
319 Integer key = Integer.valueOf( obj.hashCode() );
320 buf.append( " " );
321 buf.append( poolBack.get( key ) );
322 buf.append( " " ).append( obj );
323 buf.append( "\n" );
324 }
325 }
326 return buf.toString();
327 }
328 }
329
330 /**
331 * TimeStampObject は、生成された Object をã?生æ?時刻とともに管ç�?�™るクラスですã?
332 * å†?ƒ¨のハッシュキーは、登録するオブジェクトと同ä¸?�§、管ç�?�§きるのは、異なるオブジェクãƒ?
333 * のみですã?
334 *
335 * @version 4.0
336 * @author Kazuhiko Hasegawa
337 * @since JDK5.0,
338 */
339 class TimeStampObject implements Comparable<TimeStampObject> { // 4.3.3.6 (2008/11/15) Generics警告対å¿?
340 private final long timeStamp ;
341 private final long limitTime ;
342 private final int hcode ;
343
344 /**
345 * コンストラクターã€?
346 *
347 * @param obj 管ç�?�™るオブジェクãƒ?
348 * @param limit オブジェクトã?寿命(ç§?
349 * @throws IllegalArgumentException TimeStampObject のインスタンスに、NULL はセãƒ?ƒˆできませんã€?
350 */
351 public TimeStampObject( final Object obj,final int limit ) {
352 if( obj == null ) {
353 String errMsg = "TimeStampObject のインスタンスに、NULL はセãƒ?ƒˆできませんã€? ;
354 throw new IllegalArgumentException( errMsg );
355 }
356
357 timeStamp = System.currentTimeMillis();
358 if( limit > 0 ) {
359 limitTime = timeStamp + limit * 1000L ;
360 }
361 else {
362 limitTime = Long.MAX_VALUE ;
363 }
364
365 hcode = (int)((timeStamp)&(Integer.MAX_VALUE))^(obj.hashCode()) ;
366 }
367
368 /**
369 * å†?ƒ¨管ç�?�—てã�?‚‹オブジェクトã?生æ?時刻を返しますã?
370 *
371 * @return 生æ?時刻(ms)
372 */
373 public long getTimeStamp() {
374 return timeStamp;
375 }
376
377 /**
378 * オブジェクトã?寿命がきたかどã�?�‹を返しますã?
379 *
380 * @return 寿命判å®?true:寿命/false:まã�?½¿える)
381 */
382 public boolean isTimeOver() {
383 return (System.currentTimeMillis() > limitTime );
384 }
385
386 /**
387 * オブジェクトが同じかどã�?�‹を判定しますã?
388 *
389 * å†?ƒ¨オブジェクトã? equals() メソãƒ?ƒ‰と、作æ?時刻の両方を判断しますã?
390 * å†?ƒ¨オブジェクトã? equals() が同じでもã?作æ?時刻が異なるとã€?
391 * false を返しますã?これは、å?く同ä¸?‚ªブジェクトを管ç�?�™るå?合でもã?
392 * タイãƒ?‚¹タンプを差し替える事で、異なるオブジェクトとして
393 * 認識させるとã�?�†ことですã?
394 *
395 * @param obj Object
396 *
397 * @return true:同じ/false:異なるã?
398 */
399 public boolean equals( final Object obj ) {
400 if( obj instanceof TimeStampObject ) {
401 TimeStampObject other = (TimeStampObject)obj ;
402 return ( hcode == other.hcode ) && ( timeStamp == other.timeStamp ) ;
403 }
404 return false ;
405 }
406
407 /**
408 * ハッシュコードを返しますã?
409 *
410 * ここで返すのは、è?åˆ??身のハッシュコードではなくã?
411 * å†?ƒ¨管ç�??オブジェクトã?ハッシュコードですã?
412 *
413 * hashcode = (int)((timeStamp)&(Integer.MAX_VALUE))^(obj.hashCode())
414 *
415 * こã?計算式ã?、変更される可能性がありますã?
416 *
417 * @return å†?ƒ¨管ç�??オブジェクトã?ハッシュコーãƒ?
418 */
419 public int hashCode() { return hcode; }
420
421 /**
422 * こã?オブジェクトとæŒ?®šされたオブジェクトã?é ?º�を比è¼?�—ますã?
423 *
424 * こã?オブジェクトがæŒ?®šされたオブジェクトより小さã�??合ã?è²??整数ã€?
425 * 等しã�??合ã?ゼロ、大きい場合ã?正の整数を返しますã?
426 *
427 * @param other TimeStampObject オブジェクãƒ?
428 *
429 * @return é ?º�比è¼??値
430 * @throws ClassCastException æŒ?®šされたオブジェクトがキャストできなã�??合ã?
431 * @see Comparable#compareTo(Object)
432 */
433 // public int compareTo( final Object obj ) {
434 public int compareTo( final TimeStampObject other ) { // 4.3.3.6 (2008/11/15) Generics警告対å¿?
435 // TimeStampObject other = (TimeStampObject)obj;
436 long diff = (timeStamp - other.timeStamp);
437
438 if( diff > 0 ) { return 1; }
439 else if( diff < 0 ) { return -1; }
440 else {
441 if( equals( other ) ) { return 0; }
442 else { return (hcode - other.hcode); }
443 }
444 }
445
446 /**
447 * こã?オブジェクトã?å†?ƒ¨表現を返しますã?
448 *
449 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正しますã?
450 *
451 * @return オブジェクトã?å†?ƒ¨表現æ–?—å?
452 */
453 public String toString() {
454 // Create Timeは、ä¸?º¦求めれã?変わらなã�??で、キャãƒ?‚·ュしても良ã�??
455 // DateFormat formatter = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss",Locale.JAPAN );
456
457 // return ( "[Create Time = " + formatter.format( new Date( timeStamp ) )
458 // + " , Time Over = " + (int)((limitTime - System.currentTimeMillis())/1000.0) + "(S)]" );
459
460 return ( "[Create Time = " + HybsDateUtil.getDate( timeStamp,"yyyy/MM/dd HH:mm:ss" )
461 + " , Time Over = " + (int)((limitTime - System.currentTimeMillis())/1000.0) + "(S)]" );
462 }
463 }