View Javadoc
1   package org.codehaus.plexus.component.manager;
2   
3   /*
4   * Copyright 2001-2006 Codehaus Foundation.
5   *
6   * Licensed under the Apache License, Version 2.0 (the "License");
7   * you may not use this file except in compliance with the License.
8   * You may obtain a copy of the License at
9   *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18  
19  import org.codehaus.plexus.MutablePlexusContainer;
20  import org.codehaus.plexus.classworlds.realm.ClassRealm;
21  import org.codehaus.plexus.component.builder.AbstractComponentBuildListener;
22  import org.codehaus.plexus.component.builder.ComponentBuilder;
23  import org.codehaus.plexus.component.builder.XBeanComponentBuilder;
24  import org.codehaus.plexus.component.factory.ComponentInstantiationException;
25  import org.codehaus.plexus.component.repository.ComponentDescriptor;
26  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
27  import org.codehaus.plexus.lifecycle.LifecycleHandler;
28  import org.codehaus.plexus.logging.Logger;
29  import org.codehaus.plexus.personality.plexus.lifecycle.phase.PhaseExecutionException;
30  
31  import java.util.Collections;
32  import java.util.HashMap;
33  import java.util.Iterator;
34  import java.util.Map;
35  import java.util.Map.Entry;
36  
37  public abstract class AbstractComponentManager<T>
38      implements ComponentManager<T>
39  {
40      protected final MutablePlexusContainer container;
41  
42      private final ClassRealm realm;
43  
44      protected final ComponentDescriptor<T> componentDescriptor;
45  
46      private final Class<? extends T> type;
47  
48      private final String role;
49      
50      private final String roleHint;
51  
52      protected final ComponentBuilder<T> builder = new XBeanComponentBuilder<T>(this);
53  
54  
55      private final LifecycleHandler lifecycleHandler;
56  
57      /**
58       * Contains a mapping from singleton instances to the realms
59       * they were used to configure with. This realm will be used to
60       * call all lifecycle methods.
61       * @return a synchronized map, make sure to synchronize the map when iterating.
62       */
63      protected final Map<Object, ClassRealm> componentContextRealms = Collections.synchronizedMap(new HashMap<Object, ClassRealm>());
64  
65      private int connections;
66  
67      private long startId;
68  
69      public AbstractComponentManager( MutablePlexusContainer container,
70                         LifecycleHandler lifecycleHandler,
71                         ComponentDescriptor<T> componentDescriptor,
72                         String role,
73                         String roleHint)
74      {
75          if ( container == null )
76          {
77              throw new NullPointerException( "container is null" );
78          }
79          this.container = container;
80  
81          if ( lifecycleHandler == null )
82          {
83              throw new NullPointerException( "lifecycleHandler is null" );
84          }
85          this.lifecycleHandler = lifecycleHandler;
86  
87          if ( componentDescriptor == null )
88          {
89              throw new NullPointerException( "componentDescriptor is null" );
90          }
91          this.componentDescriptor = componentDescriptor;
92  
93          if ( role == null )
94          {
95              throw new NullPointerException( "role is null" );
96          }
97          this.role = role;
98  
99          if ( roleHint == null )
100         {
101             throw new NullPointerException( "roleHint is null" );
102         }
103         this.roleHint = roleHint;
104 
105         this.realm = componentDescriptor.getRealm();
106 
107         this.type = componentDescriptor.getImplementationClass();
108     }
109 
110     public ComponentDescriptor<T> getComponentDescriptor()
111     {
112         return componentDescriptor;
113     }
114 
115     public Class<? extends T> getType()
116     {
117         return type;
118     }
119 
120     public ClassRealm getRealm()
121     {
122         return realm;
123     }
124 
125     public String getRole()
126     {
127         return role;
128     }
129 
130     public String getRoleHint()
131     {
132         return roleHint;
133     }
134 
135     public LifecycleHandler getLifecycleHandler()
136     {
137         return lifecycleHandler;
138     }
139 
140     protected void incrementConnectionCount()
141     {
142         connections++;
143     }
144 
145     protected void decrementConnectionCount()
146     {
147         connections--;
148     }
149 
150     protected boolean connected()
151     {
152         return connections > 0;
153     }
154 
155     public int getConnections()
156     {
157         return connections;
158     }
159 
160     // ----------------------------------------------------------------------
161     // Lifecylce Management
162     // ----------------------------------------------------------------------
163 
164     public void start( Object component ) throws PhaseExecutionException
165     {
166         startId = NEXT_START_ID.getAndIncrement();
167         getLifecycleHandler().start( component,  this, componentDescriptor.getRealm() );
168     }
169 
170     /**
171      * @deprecated for internal use only.. will be removed
172      */
173     public long getStartId()
174     {
175         return startId;
176     }
177 
178     protected T createComponentInstance()
179         throws ComponentInstantiationException, ComponentLifecycleException
180     {
181         return builder.build(componentDescriptor, realm, new AbstractComponentBuildListener() {
182             public void componentCreated( ComponentDescriptor<?> componentDescriptor, Object component, ClassRealm realm) {
183                 componentContextRealms.put( component, realm );
184             }
185         });
186     }
187 
188     protected void endComponentLifecycle( Object component )
189         throws ComponentLifecycleException
190     {
191         ClassRealm contextRealm = componentContextRealms.remove( component );
192         if ( contextRealm == null )
193         {
194             contextRealm = container.getLookupRealm( component );
195         }
196 
197         try
198         {
199             getLifecycleHandler().end( component, this, contextRealm );
200         }
201         catch ( PhaseExecutionException e )
202         {
203             throw new ComponentLifecycleException( "Error ending component lifecycle", e );
204         }
205     }
206 
207     public MutablePlexusContainer getContainer()
208     {
209         return container;
210     }
211 
212     public Logger getLogger()
213     {
214         return container.getLogger();
215     }
216 
217     public void dissociateComponentRealm( ClassRealm realm )
218         throws ComponentLifecycleException
219     {
220         synchronized ( componentContextRealms )
221         {
222             for ( Iterator<Entry<Object, ClassRealm>> iterator = componentContextRealms.entrySet().iterator(); iterator.hasNext(); )
223             {
224                 Entry<Object, ClassRealm> entry = iterator.next();
225                 ClassRealm componentRealm = entry.getValue();
226 
227                 if ( componentRealm.getId().equals( realm.getId() ) )
228                 {
229                     iterator.remove();
230                 }
231             }
232         }
233     }
234 }