001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/framework/util/ObjectPool.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005     Department of Geography, University of Bonn
006     and
007     lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035     ----------------------------------------------------------------------------*/
036    package org.deegree.framework.util;
037    
038    import java.io.IOException;
039    import java.io.InputStream;
040    import java.util.ArrayList;
041    import java.util.Collections;
042    import java.util.HashMap;
043    import java.util.List;
044    import java.util.Map;
045    import java.util.Properties;
046    import java.util.Timer;
047    import java.util.TimerTask;
048    
049    import org.deegree.framework.log.ILogger;
050    import org.deegree.framework.log.LoggerFactory;
051    
052    /**
053     * class to manage the object pool. this is part of the combination of the object pool pattern an the singelton pattern.
054     * 
055     * @version $Revision: 20107 $
056     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
057     * @author last edited by: $Author: aschmitz $
058     * 
059     * @version $Revision: 20107 $, $Date: 2009-10-13 13:15:16 +0200 (Di, 13. Okt 2009) $
060     */
061    public abstract class ObjectPool extends TimerTask {
062    
063        private static final ILogger LOG = LoggerFactory.getLogger( ObjectPool.class );
064    
065        /**
066         * all available objects
067         */
068        protected List<Object> available = null;
069    
070        /**
071         * all objects in use
072         */
073        protected List<Object> in_use = null;
074    
075        /**
076         * the start life time for each object
077         */
078        protected Map<Object, Long> startLifeTime = null;
079    
080        /**
081         * the start usage time for each object
082         */
083        protected Map<Object, Long> startUsageTime = null;
084    
085        /**
086         * number of existing instances
087         */
088        protected int existingInstances = 0;
089    
090        private int maxInstances = 50;
091    
092        // min * sec * millisec. example: 15*60*1000 = 15 minutes
093        private int maxLifeTime = 15 * 60 * 1000;
094    
095        // min * sec * millisec. example: 5*60*1000 = 5 minutes
096        private int maxUsageTime = 5 * 60 * 1000;
097    
098        // milliseconds
099        private int updateInterval = 15000;
100    
101        /**
102         * Creates a new ObjectPool object.
103         */
104        protected ObjectPool() {
105            available = Collections.synchronizedList( new ArrayList<Object>( maxInstances ) );
106            in_use = Collections.synchronizedList( new ArrayList<Object>( maxInstances ) );
107            startLifeTime = Collections.synchronizedMap( new HashMap<Object, Long>( maxInstances ) );
108            startUsageTime = Collections.synchronizedMap( new HashMap<Object, Long>( maxInstances ) );
109            Timer timer = new Timer();
110            timer.scheduleAtFixedRate( this, 10000, updateInterval );
111            InputStream is = ObjectPool.class.getResourceAsStream( "pool.properties" );
112            if ( is != null ) {
113                Properties props = new Properties();
114                try {
115                    props.load( is );
116                    is.close();
117                } catch ( IOException e ) {
118                    LOG.logInfo( "could not load pool properties" );
119                    return;
120                }
121                maxInstances = Integer.parseInt( props.getProperty( "maxInstances" ) );
122                maxLifeTime = Integer.parseInt( props.getProperty( "maxLifeTime" ) );
123                maxUsageTime = Integer.parseInt( props.getProperty( "maxUsageTime" ) );
124                updateInterval = Integer.parseInt( props.getProperty( "updateInterval" ) );
125                LOG.logInfo( "pool configuration read from pool.properties" );
126                LOG.logDebug( "pool properties", this.toString() );
127            }
128        }
129    
130        /**
131         * dummy
132         * 
133         * @return null
134         */
135        public static ObjectPool getInstance() {
136            return null;
137        }
138    
139        /**
140         * clears the complete pool. objects in used while the clear() method has been called won't be put back to the pool
141         * if released back through the <tt>releaseObject</tt> method.
142         */
143        public synchronized void clear() {
144            in_use.clear();
145            available.clear();
146            startUsageTime.clear();
147            startLifeTime.clear();
148        }
149    
150        /**
151         * release an object back to the pool so it is available for other requests.
152         * 
153         * @param object
154         * @throws Exception
155         */
156        public void releaseObject( Object object )
157                                throws Exception {
158    
159            if ( in_use.contains( object ) ) {
160                // remove the object from the 'in use' container
161                in_use.remove( object );
162                // remove the objects entry from the 'usage star time' container
163                startUsageTime.remove( object );
164                // push the object to the list of available objects
165                available.add( object );
166            }
167        }
168    
169        /**
170         * this method will be called when the submitted object will be removed from the pool
171         * 
172         * @param o
173         */
174        public abstract void onObjectKill( Object o );
175    
176        /**
177         * @return the max life time
178         */
179        public int getMaxLifeTime() {
180            return ( this.maxLifeTime );
181        }
182    
183        /**
184         * @param maxLifeTime
185         */
186        public void setMaxLifeTime( int maxLifeTime ) {
187            this.maxLifeTime = maxLifeTime;
188        }
189    
190        /**
191         * @return the max usage time
192         */
193        public int getMaxUsageTime() {
194            return ( this.maxUsageTime );
195        }
196    
197        /**
198         * @param maxUsageTime
199         */
200        public void setMaxUsageTime( int maxUsageTime ) {
201            this.maxUsageTime = maxUsageTime;
202        }
203    
204        /**
205         * @return the update interval
206         */
207        public int getUpdateInterval() {
208            return ( this.updateInterval );
209        }
210    
211        /**
212         * @param updateInterval
213         */
214        public void setUpdateInterval( int updateInterval ) {
215            this.updateInterval = updateInterval;
216        }
217    
218        /**
219         * @return max instances
220         */
221        public int getMaxInstances() {
222            return ( this.maxInstances );
223        }
224    
225        /**
226         * @param maxInstances
227         */
228        public void setMaxInstances( int maxInstances ) {
229            this.maxInstances = maxInstances;
230        }
231    
232        @Override
233        public String toString() {
234            String ret = getClass().getName() + "\n";
235            ret = "startLifeTime = " + startLifeTime + "\n";
236            ret += ( "startUsageTime = " + startUsageTime + "\n" );
237            ret += ( "maxLifeTime = " + maxLifeTime + "\n" );
238            ret += ( "maxUsageTime = " + maxUsageTime + "\n" );
239            ret += ( "updateInterval = " + updateInterval + "\n" );
240            ret += ( "maxInstances = " + maxInstances + "\n" );
241            return ret;
242        }
243    
244        @Override
245        public void run() {
246            cleaner();
247            usage();
248        }
249    
250        private synchronized void cleaner() {
251    
252            try {
253                Object[] os = available.toArray();
254                for ( int i = 0; i < os.length; i++ ) {
255                    Object o = os[i];
256                    Long lng = startLifeTime.get( o );
257                    long l = System.currentTimeMillis();
258                    if ( lng == null || ( l - lng.longValue() ) > maxLifeTime ) {
259                        if ( o != null ) {
260                            available.remove( o );
261                            startLifeTime.remove( o );
262                            onObjectKill( o );
263                        }
264                        existingInstances--;
265                    }
266                }
267    
268            } catch ( Exception e ) {
269                LOG.logError( "ObjectPool Cleaner ", e );
270            }
271    
272        }
273    
274        private synchronized void usage() {
275            try {
276                Object[] os = in_use.toArray();
277                for ( int i = 0; i < os.length; i++ ) {
278                    Object o = os[i];
279                    Long lng = startUsageTime.get( o );
280                    long l = System.currentTimeMillis();
281                    if ( lng == null || ( l - lng.longValue() ) > maxUsageTime ) {
282                        if ( o != null ) {
283                            in_use.remove( o );
284                            startUsageTime.remove( o );
285                            startLifeTime.remove( o );
286                            onObjectKill( o );
287                        }
288                    }
289                }
290            } catch ( Exception e ) {
291                LOG.logError( "UsageChecker ", e );
292            }
293    
294        }
295    
296    }