Source Code Cross Referenced for Pooled.java in  » Inversion-of-Control » PicoContainer » org » picocontainer » gems » behaviors » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Inversion of Control » PicoContainer » org.picocontainer.gems.behaviors 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*****************************************************************************
002:         * Copyright (C) NanoContainer Organization. All rights reserved.            *
003:         * ------------------------------------------------------------------------- *
004:         * The software in this package is published under the terms of the BSD      *
005:         * style license a copy of which has been included with this distribution in *
006:         * the LICENSE.txt file.                                                     *
007:         *                                                                           *
008:         * Original code by Aslak Hellesoy & Joerg Schaible                                       *
009:         *****************************************************************************/package org.picocontainer.gems.behaviors;
010:
011:        import java.io.ByteArrayOutputStream;
012:        import java.io.IOException;
013:        import java.io.NotSerializableException;
014:        import java.io.ObjectInputStream;
015:        import java.io.ObjectOutputStream;
016:        import java.io.Serializable;
017:        import java.util.ArrayList;
018:        import java.util.List;
019:
020:        import org.picocontainer.ComponentAdapter;
021:        import org.picocontainer.Behavior;
022:        import org.picocontainer.PicoContainer;
023:        import org.picocontainer.behaviors.AbstractBehavior;
024:        import org.picocontainer.LifecycleStrategy;
025:        import org.picocontainer.PicoCompositionException;
026:
027:        import com.thoughtworks.proxy.ProxyFactory;
028:        import com.thoughtworks.proxy.factory.StandardProxyFactory;
029:        import com.thoughtworks.proxy.kit.NoOperationResetter;
030:        import com.thoughtworks.proxy.kit.Resetter;
031:        import com.thoughtworks.proxy.toys.nullobject.Null;
032:        import com.thoughtworks.proxy.toys.pool.Pool;
033:
034:        /**
035:         * {@link ComponentAdapter} implementation that pools components.
036:         * <p>
037:         * The implementation utilizes a delegated ComponentAdapter to create the instances of the pool. The
038:         * pool can be configured to grow unlimited or to a maximum size. If a component is requested from
039:         * this adapter, the implementation returns an availailabe instance from the pool or will create a
040:         * new one, if the maximum pool size is not reached yet. If none is available, the implementation
041:         * can wait a defined time for a returned object before it throws a {@link PoolException}.
042:         * </p>
043:         * <p>
044:         * This implementation uses the {@link Pool} toy from the <a
045:         * href="http://proxytoys.codehaus.org">ProxyToys</a> project. This ensures, that any component,
046:         * that is out of scope will be automatically returned to the pool by the garbage collector.
047:         * Additionally will every component instance also implement
048:         * {@link com.thoughtworks.proxy.toys.pool.Poolable}, that can be used to return the instance
049:         * manually. After returning an instance it should not be used in client code anymore.
050:         * </p>
051:         * <p>
052:         * Before a returning object is added to the available instances of the pool again, it should be
053:         * reinitialized to a normalized state. By providing a proper Resetter implementation this can be
054:         * done automatically. If the object cannot be reused anymore it can also be dropped and the pool
055:         * may request a new instance.
056:         * </p>
057:         * <p>
058:         * The pool supports components with a lifecycle. If the delegated {@link ComponentAdapter}
059:         * implements a {@link LifecycleStrategy}, any component retrieved form the pool will be started
060:         * before and stopped again, when it returns back into the pool. Also if a component cannot be
061:         * resetted it will automatically be disposed. If the container of the pool is disposed, that any
062:         * returning object is also disposed and will not return to the pool anymore. Note, that current
063:         * implementation cannot dispose pooled objects.
064:         * </p>
065:         * 
066:         * @author J&ouml;rg Schaible
067:         * @author Aslak Helles&oslash;y
068:         */
069:        public final class Pooled extends AbstractBehavior implements  Behavior {
070:
071:            private static final long serialVersionUID = 1L;
072:
073:            /**
074:             * Context of the Pooled used to initialize it.
075:             * 
076:             * @author J&ouml;rg Schaible
077:             */
078:            public static interface Context {
079:                /**
080:                 * Retrieve the maximum size of the pool. An implementation may return the maximum value or
081:                 * {@link Pooled#UNLIMITED_SIZE} for <em>unlimited</em> growth.
082:                 * 
083:                 * @return the maximum pool size
084:                 */
085:                int getMaxSize();
086:
087:                /**
088:                 * Retrieve the maximum number of milliseconds to wait for a returned element. An
089:                 * implementation may return alternatively {@link Pooled#BLOCK_ON_WAIT} or
090:                 * {@link Pooled#FAIL_ON_WAIT}.
091:                 * 
092:                 * @return the maximum number of milliseconds to wait
093:                 */
094:                int getMaxWaitInMilliseconds();
095:
096:                /**
097:                 * Allow the implementation to invoke the garbace collector manually if the pool is
098:                 * exhausted.
099:                 * 
100:                 * @return <code>true</code> for an internal call to {@link System#gc()}
101:                 */
102:                boolean autostartGC();
103:
104:                /**
105:                 * Retrieve the ProxyFactory to use to create the pooling proxies.
106:                 * 
107:                 * @return the {@link ProxyFactory}
108:                 */
109:                ProxyFactory getProxyFactory();
110:
111:                /**
112:                 * Retrieve the {@link Resetter} of the objects returning to the pool.
113:                 * 
114:                 * @return the Resetter instance
115:                 */
116:                Resetter getResetter();
117:
118:                /**
119:                 * Retrieve the serialization mode of the pool. Following values are possible:
120:                 * <ul>
121:                 * <li>{@link Pool#SERIALIZATION_STANDARD}</li>
122:                 * <li>{@link Pool#SERIALIZATION_NONE}</li>
123:                 * <li>{@link Pool#SERIALIZATION_FORCE}</li>
124:                 * </ul>
125:                 * 
126:                 * @return the serialization mode
127:                 */
128:                int getSerializationMode();
129:            }
130:
131:            /**
132:             * The default context for a Pooled.
133:             * 
134:             * @author J&ouml;rg Schaible
135:             */
136:            public static class DefaultContext implements  Context {
137:
138:                /**
139:                 * {@inheritDoc} Returns {@link Pooled#DEFAULT_MAX_SIZE}.
140:                 */
141:                public int getMaxSize() {
142:                    return DEFAULT_MAX_SIZE;
143:                }
144:
145:                /**
146:                 * {@inheritDoc} Returns {@link Pooled#FAIL_ON_WAIT}.
147:                 */
148:                public int getMaxWaitInMilliseconds() {
149:                    return FAIL_ON_WAIT;
150:                }
151:
152:                /**
153:                 * {@inheritDoc} Returns <code>false</code>.
154:                 */
155:                public boolean autostartGC() {
156:                    return false;
157:                }
158:
159:                /**
160:                 * {@inheritDoc} Returns a {@link StandardProxyFactory}.
161:                 */
162:                public ProxyFactory getProxyFactory() {
163:                    return new StandardProxyFactory();
164:                }
165:
166:                /**
167:                 * {@inheritDoc} Returns the {@link Pooled#DEFAULT_RESETTER}.
168:                 */
169:                public Resetter getResetter() {
170:                    return DEFAULT_RESETTER;
171:                }
172:
173:                /**
174:                 * {@inheritDoc} Returns {@link Pool#SERIALIZATION_STANDARD}.
175:                 */
176:                public int getSerializationMode() {
177:                    return Pool.SERIALIZATION_STANDARD;
178:                }
179:
180:            }
181:
182:            /**
183:             * <code>UNLIMITED_SIZE</code> is the value to set the maximum size of the pool to unlimited ({@link Integer#MAX_VALUE}
184:             * in fact).
185:             */
186:            public static final int UNLIMITED_SIZE = Integer.MAX_VALUE;
187:            /**
188:             * <code>DEFAULT_MAX_SIZE</code> is the default size of the pool.
189:             */
190:            public static final int DEFAULT_MAX_SIZE = 8;
191:            /**
192:             * <code>BLOCK_ON_WAIT</code> forces the pool to wait until an object of the pool is returning
193:             * in case none is immediately available.
194:             */
195:            public static final int BLOCK_ON_WAIT = 0;
196:            /**
197:             * <code>FAIL_ON_WAIT</code> forces the pool to fail none is immediately available.
198:             */
199:            public static final int FAIL_ON_WAIT = -1;
200:            /**
201:             * <code>DEFAULT_RESETTER</code> is a {@link NoOperationResetter} that is used by default.
202:             */
203:            public static final Resetter DEFAULT_RESETTER = new NoOperationResetter();
204:
205:            private int maxPoolSize;
206:            private int waitMilliSeconds;
207:            private Pool pool;
208:            private int serializationMode;
209:            private boolean autostartGC;
210:            private boolean started;
211:            private boolean disposed;
212:            private boolean delegateHasLifecylce;
213:            private transient List<Object> components;
214:
215:            /**
216:             * Construct a Pooled. Remember, that the implementation will request new
217:             * components from the delegate as long as no component instance is available in the pool and
218:             * the maximum pool size is not reached. Therefore the delegate may not return the same
219:             * component instance twice. Ensure, that the used {@link ComponentAdapter} does not cache.
220:             * 
221:             * @param delegate the delegated ComponentAdapter
222:             * @param context the {@link Context} of the pool
223:             * @throws IllegalArgumentException if the maximum pool size or the serialization mode is
224:             *             invalid
225:             */
226:            public Pooled(ComponentAdapter delegate, Context context) {
227:                super (delegate);
228:                this .maxPoolSize = context.getMaxSize();
229:                this .waitMilliSeconds = context.getMaxWaitInMilliseconds();
230:                this .autostartGC = context.autostartGC();
231:                this .serializationMode = context.getSerializationMode();
232:                if (maxPoolSize <= 0) {
233:                    throw new IllegalArgumentException(
234:                            "Invalid maximum pool size");
235:                }
236:                started = false;
237:                disposed = false;
238:                delegateHasLifecylce = delegate instanceof  LifecycleStrategy
239:                        && ((LifecycleStrategy) delegate).hasLifecycle(delegate
240:                                .getComponentImplementation());
241:                components = new ArrayList<Object>();
242:
243:                final Class type = delegate.getComponentKey() instanceof  Class ? (Class) delegate
244:                        .getComponentKey()
245:                        : delegate.getComponentImplementation();
246:                final Resetter resetter = context.getResetter();
247:                this .pool = new Pool(type,
248:                        delegateHasLifecylce ? new LifecycleResetter(this ,
249:                                resetter) : resetter,
250:                        context.getProxyFactory(), serializationMode);
251:            }
252:
253:            /**
254:             * Construct an empty ComponentAdapter, used for serialization with reflection only.
255:             * 
256:             */
257:            protected Pooled() {
258:                // @todo super class should support standard ctor
259:                super ((ComponentAdapter) Null.object(ComponentAdapter.class));
260:            }
261:
262:            /**
263:             * {@inheritDoc}
264:             * <p>
265:             * As long as the maximum size of the pool is not reached and the pool is exhausted, the
266:             * implementation will request its delegate for a new instance, that will be managed by the
267:             * pool. Only if the maximum size of the pool is reached, the implementation may wait (depends
268:             * on the initializing {@link Context}) for a returning object.
269:             * </p>
270:             * 
271:             * @throws PoolException if the pool is exhausted or waiting for a returning object timed out or
272:             *             was interrupted
273:             */
274:            public Object getComponentInstance(PicoContainer container) {
275:                if (delegateHasLifecylce) {
276:                    if (disposed)
277:                        throw new IllegalStateException("Already disposed");
278:                }
279:                Object componentInstance;
280:                long now = System.currentTimeMillis();
281:                boolean gc = autostartGC;
282:                while (true) {
283:                    synchronized (pool) {
284:                        componentInstance = pool.get();
285:                        if (componentInstance != null) {
286:                            break;
287:                        }
288:                        if (maxPoolSize > pool.size()) {
289:                            final Object component = super 
290:                                    .getComponentInstance(container);
291:                            if (delegateHasLifecylce) {
292:                                components.add(component);
293:                                if (started) {
294:                                    start(component);
295:                                }
296:                            }
297:                            pool.add(component);
298:                        } else if (!gc) {
299:                            long after = System.currentTimeMillis();
300:                            if (waitMilliSeconds < 0) {
301:                                throw new PoolException("Pool exhausted");
302:                            }
303:                            if (waitMilliSeconds > 0
304:                                    && after - now > waitMilliSeconds) {
305:                                throw new PoolException(
306:                                        "Time out wating for returning object into pool");
307:                            }
308:                            try {
309:                                pool.wait(waitMilliSeconds); // Note, the pool notifies after an object
310:                                // was returned
311:                            } catch (InterruptedException e) {
312:                                // give the client code of the current thread a chance to abort also
313:                                Thread.currentThread().interrupt();
314:                                throw new PoolException(
315:                                        "Interrupted waiting for returning object into the pool",
316:                                        e);
317:                            }
318:                        } else {
319:                            System.gc();
320:                            gc = false;
321:                        }
322:                    }
323:                }
324:                return componentInstance;
325:            }
326:
327:            public String getDescriptor() {
328:                return "Pooled";
329:            }
330:
331:            /**
332:             * Retrieve the current size of the pool. The returned value reflects the number of all managed
333:             * components.
334:             * 
335:             * @return the number of components.
336:             */
337:            public int size() {
338:                return pool.size();
339:            }
340:
341:            static final class LifecycleResetter implements  Resetter,
342:                    Serializable {
343:                private static final long serialVersionUID = 1L;
344:                private final Resetter delegate;
345:                private final Pooled adapter;
346:
347:                LifecycleResetter(final Pooled adapter, final Resetter delegate) {
348:                    this .adapter = adapter;
349:                    this .delegate = delegate;
350:                }
351:
352:                public boolean reset(Object object) {
353:                    final boolean result = delegate.reset(object);
354:                    if (!result || adapter.disposed) {
355:                        if (adapter.started) {
356:                            adapter.stop(object);
357:                        }
358:                        adapter.components.remove(object);
359:                        if (!adapter.disposed) {
360:                            adapter.dispose(object);
361:                        }
362:                    }
363:                    return result && !adapter.disposed;
364:                }
365:
366:            }
367:
368:            /**
369:             * Start of the container ensures that at least one pooled component has been started. Applies
370:             * only if the delegated {@link ComponentAdapter} supports a lifecylce by implementing
371:             * {@link LifecycleStrategy}.
372:             * 
373:             * @throws IllegalStateException if pool was already disposed
374:             */
375:            public void start(final PicoContainer container) {
376:                if (delegateHasLifecylce) {
377:                    if (started)
378:                        throw new IllegalStateException("Already started");
379:                    if (disposed)
380:                        throw new IllegalStateException("Already disposed");
381:                    for (Object component : components) {
382:                        start(component);
383:                    }
384:                    started = true;
385:                    if (pool.size() == 0) {
386:                        getComponentInstance(container);
387:                    }
388:                }
389:            }
390:
391:            /**
392:             * Stop of the container has no effect for the pool. Applies only if the delegated
393:             * {@link ComponentAdapter} supports a lifecylce by implementing {@link org.picocontainer.LifecycleStrategy}.
394:             * 
395:             * @throws IllegalStateException if pool was already disposed
396:             */
397:            public void stop(final PicoContainer container) {
398:                if (delegateHasLifecylce) {
399:                    if (!started)
400:                        throw new IllegalStateException("Not started yet");
401:                    if (disposed)
402:                        throw new IllegalStateException("Already disposed");
403:                    for (Object component : components) {
404:                        stop(component);
405:                    }
406:                    started = false;
407:                }
408:            }
409:
410:            /**
411:             * Dispose of the container will dispose all returning objects. They will not be added to the
412:             * pool anymore. Applies only if the delegated {@link ComponentAdapter} supports a lifecylce by
413:             * implementing {@link LifecycleStrategy}.
414:             * 
415:             * @throws IllegalStateException if pool was already disposed
416:             */
417:            public void dispose(final PicoContainer container) {
418:                if (delegateHasLifecylce) {
419:                    if (started)
420:                        throw new IllegalStateException("Not stopped yet");
421:                    if (disposed)
422:                        throw new IllegalStateException("Already disposed");
423:                    disposed = true;
424:                    for (Object component : components) {
425:                        dispose(component);
426:                    }
427:                    // @todo: Release pooled components and clear collection
428:                }
429:            }
430:
431:            private synchronized void writeObject(final ObjectOutputStream out)
432:                    throws IOException {
433:                out.defaultWriteObject();
434:                int mode = serializationMode;
435:                if (mode == Pool.SERIALIZATION_FORCE && components.size() > 0) {
436:                    try {
437:                        final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
438:                        final ObjectOutputStream testStream = new ObjectOutputStream(
439:                                buffer);
440:                        testStream.writeObject(components); // force NotSerializableException
441:                        testStream.close();
442:                    } catch (final NotSerializableException e) {
443:                        mode = Pool.SERIALIZATION_NONE;
444:                    }
445:                }
446:                if (mode == Pool.SERIALIZATION_STANDARD) {
447:                    out.writeObject(components);
448:                } else {
449:                    out.writeObject(new ArrayList());
450:                }
451:            }
452:
453:            private void readObject(final ObjectInputStream in)
454:                    throws IOException, ClassNotFoundException {
455:                in.defaultReadObject();
456:                components = (List<Object>) in.readObject();
457:            }
458:
459:            /**
460:             * Exception thrown from the Pooled. Only thrown if the interaction with the internal pool fails.
461:             *
462:             * @author J&ouml;rg Schaible
463:             */
464:            public static class PoolException extends PicoCompositionException {
465:
466:                private static final long serialVersionUID = 1L;
467:
468:                /**
469:                 * Construct a PoolException with an explaining message and a originalting cause.
470:                 *
471:                 * @param message the explaining message
472:                 * @param cause the originating cause
473:                 */
474:                public PoolException(String message, Throwable cause) {
475:                    super (message, cause);
476:                }
477:
478:                /**
479:                 * Construct a PoolException with an explaining message.
480:                 *
481:                 * @param message the explaining message
482:                 */
483:                public PoolException(String message) {
484:                    super(message);
485:                }
486:
487:            }
488:
489:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.