KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > component > servlet > AbstractReferenceProxyLatch


1 /*
2  * Copyright 2002-2004 The Apache Software Foundation
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  *
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.avalon.excalibur.component.servlet;
18
19 import org.apache.avalon.excalibur.logger.LoggerManager;
20 import org.apache.avalon.framework.component.ComponentManager;
21 import org.apache.avalon.framework.logger.AbstractLogEnabled;
22 import org.apache.avalon.framework.service.ServiceManager;
23 import org.apache.excalibur.instrument.InstrumentManager;
24
25 /**
26  * Servlet containers do not have a guaranteed order in which servlets will
27  * be destroyed like there is with initialization. This means that the
28  * servlet which created and controls an object may be destroyed while other
29  * servlets are still using it. This presents a problem in environments where
30  * common objects are placed into the ServletContext and used by more than
31  * one servlet.
32  *
33  * To solve this problem an object is placed into the ServletContext wrapped
34  * in a ReferenceProxy. Whe nthe servlet is ready to be shutdown. This
35  * proxy latch is used to wait until all other servlets are done with the
36  * components before disposing them.
37  *
38  * @deprecated ECM is no longer supported
39  *
40  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
41  * @version CVS $Revision: 1.4 $ $Date: 2004/02/28 11:47:16 $
42  * @since 4.2
43  */

44 abstract class AbstractReferenceProxyLatch
45     extends AbstractLogEnabled
46 {
47     /** Name of the latch */
48     private String JavaDoc m_name;
49
50     /** Number of registered proxies which have not yet been finalized. */
51     private int m_waitingProxies;
52
53     /** Flag that keeps track of when the trigger is requested. */
54     private boolean m_triggerRequested;
55
56     /*---------------------------------------------------------------
57      * Constructors
58      *-------------------------------------------------------------*/

59     /**
60      * Create a new ReferenceProxyLatch.
61      */

62     public AbstractReferenceProxyLatch()
63     {
64     }
65
66     /*---------------------------------------------------------------
67      * Methods
68      *-------------------------------------------------------------*/

69     /**
70      * @param object Object to be protected.
71      * @param name Name of the object.
72      * @return A new ReferenceProxy instance protecting the object.
73      */

74     public ReferenceProxy createProxy( Object JavaDoc object, String JavaDoc name )
75     {
76         m_name = name;
77
78         if( getLogger().isDebugEnabled() )
79         {
80             getLogger().debug( "Creating a proxy named '" + m_name + "' for a "
81                                + object.getClass().getName() );
82         }
83
84         AbstractReferenceProxy proxy;
85         if( object instanceof LoggerManager )
86         {
87             proxy = new LoggerManagerReferenceProxy( (LoggerManager)object, this, name );
88         }
89         else if( object instanceof ServiceManager )
90         {
91             proxy = new ServiceManagerReferenceProxy( (ServiceManager)object, this, name );
92         }
93         else if( object instanceof ComponentManager )
94         {
95             proxy = new ComponentManagerReferenceProxy( (ComponentManager)object, this, name );
96         }
97         else if( object instanceof InstrumentManager )
98         {
99             proxy = new InstrumentManagerReferenceProxy( (InstrumentManager)object, this, name );
100         }
101         else
102         {
103             throw new IllegalArgumentException JavaDoc( "Don't know how to create a proxy for a "
104                                                 + object.getClass().getName() );
105         }
106
107         m_waitingProxies++;
108
109         return proxy;
110     }
111
112     /**
113      * Request that the triggered() method be called by asking all of the proxies
114      * managed by the latch to notify that they are no longer accepting requests
115      * to reference their internal objects.
116      */

117     public void requestTrigger()
118     {
119         int waitingProxies;
120         synchronized( this )
121         {
122             waitingProxies = m_waitingProxies;
123         }
124
125         if( waitingProxies > 0 )
126         {
127             // Invoke garbage collection so that any proxies will be GCed if possible.
128
System.gc();
129
130             // Give the JVM a little time for the proxies to be GCed
131
try
132             {
133                 Thread.sleep( 1500 );
134             }
135             catch( InterruptedException JavaDoc e )
136             {
137             }
138         }
139
140         synchronized( this )
141         {
142             m_triggerRequested = true;
143             waitingProxies = m_waitingProxies;
144         }
145
146         if( waitingProxies > 0 )
147         {
148             if( getLogger().isDebugEnabled() )
149             {
150                 getLogger().debug( "Trigger requested. " + waitingProxies
151                                    + " proxies have not yet been finalized." );
152             }
153         }
154         else
155         {
156             if( getLogger().isDebugEnabled() )
157             {
158                 getLogger().debug( "Trigger requested. All proxies have been finalized." );
159             }
160
161             try
162             {
163                 triggered();
164             }
165             catch( Exception JavaDoc e )
166             {
167                 getLogger().error( "Encountered an unexpected error in the trigger callback:", e );
168             }
169         }
170     }
171
172     /**
173      * Called by a proxy when it is finalized.
174      *
175      * @param proxy The AbstractRefernceProxy that is ready.
176      */

177     void notifyFinalized( AbstractReferenceProxy proxy )
178     {
179         synchronized( this )
180         {
181             m_waitingProxies--;
182
183             // Was that the last proxy?
184
if( m_waitingProxies > 0 )
185             {
186                 if( getLogger().isDebugEnabled() )
187                 {
188                     getLogger().debug( "The proxy named '" + proxy.getName() + "' was finalized. "
189                                        + m_waitingProxies + " proxies remaining." );
190                 }
191                 return;
192             }
193         }
194
195         // Do this outside the synchronization block.
196
if ( getLogger().isDebugEnabled() )
197         {
198             getLogger().debug( "The proxy named '" + proxy.getName() + "' was finalized. "
199                 + "All proxies have been finalized." );
200         }
201
202         if ( m_triggerRequested )
203         {
204             try
205             {
206                 triggered();
207             }
208             catch ( Exception JavaDoc e )
209             {
210                 getLogger().error( "Encountered an unexpected error in the trigger callback:", e );
211             }
212         }
213     }
214
215     /**
216      * Called when all of the proxies have notified that they are done.
217      */

218     public abstract void triggered() throws Exception JavaDoc;
219 }
220
Popular Tags