001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.services.impl;
016    
017    import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
018    import org.apache.tapestry.event.ReportStatusEvent;
019    import org.apache.tapestry.event.ReportStatusListener;
020    import org.apache.tapestry.event.ResetEventListener;
021    import org.apache.tapestry.services.ObjectPool;
022    
023    import java.util.*;
024    
025    /**
026     * Implementation of the {@link org.apache.tapestry.services.ObjectPool} interface.
027     * <p>
028     * This ia a minimal implementation, one that has no concept of automatically removing unused pooled
029     * objects. Eventually, it will also register for notifications about general cache cleaning.
030     * 
031     * @author Howard Lewis Ship
032     * @since 4.0
033     */
034    public class ObjectPoolImpl implements ObjectPool, ResetEventListener, ReportStatusListener
035    {
036        private String _serviceId;
037    
038        private int _count = 0;
039    
040        private final ReentrantLock _lock = new ReentrantLock();
041    
042        /**
043         * Pool of Lists (of pooled objects), keyed on arbitrary key.
044         */
045        private Map _pool = new HashMap();
046            
047        public Object get(Object key)
048        {
049            List pooled = (List) _pool.get(key);
050            
051            try
052            {
053                _lock.lock();
054                
055                if (pooled == null || pooled.isEmpty())
056                    return null;
057    
058                _count--;
059    
060                return pooled.remove(0);
061    
062            } finally
063            {
064                _lock.unlock();
065            }
066        }
067    
068        public void store(Object key, Object value)
069        {
070            List pooled = (List) _pool.get(key);
071    
072            try
073            {
074                _lock.lock();
075                
076                if (pooled == null)
077                {
078                    pooled = new LinkedList();
079                    _pool.put(key, pooled);
080                }
081    
082                pooled.add(value);
083    
084                _count++;
085            } finally
086            {
087                _lock.unlock();
088            }
089        }
090    
091        public void resetEventDidOccur()
092        {
093            _pool.clear();
094    
095            _count = 0;
096        }
097    
098        public void reportStatus(ReportStatusEvent event)
099        {
100            event.title(_serviceId);
101    
102            event.property("total count", _count);
103    
104            event.section("Count by Key");
105    
106            Iterator i = _pool.entrySet().iterator();
107    
108            while (i.hasNext())
109            {
110                Map.Entry entry = (Map.Entry) i.next();
111    
112                String key = entry.getKey().toString();
113    
114                List pooled = (List) entry.getValue();
115    
116                event.property(key, pooled.size());
117            }
118        }
119    
120        public void setServiceId(String serviceId)
121        {
122            _serviceId = serviceId;
123        }
124    }