KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > hivemind > impl > RegistryBuilder


1 // Copyright 2004, 2005 The Apache Software Foundation
2
//
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 implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15 package org.apache.hivemind.impl;
16
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Locale JavaDoc;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hivemind.ErrorHandler;
24 import org.apache.hivemind.Registry;
25 import org.apache.hivemind.definition.ConfigurationPointDefinition;
26 import org.apache.hivemind.definition.DefinitionMessages;
27 import org.apache.hivemind.definition.ModuleDefinition;
28 import org.apache.hivemind.definition.Occurances;
29 import org.apache.hivemind.definition.RegistryDefinition;
30 import org.apache.hivemind.definition.RegistryDefinitionPostProcessor;
31 import org.apache.hivemind.definition.impl.RegistryDefinitionImpl;
32 import org.apache.hivemind.events.RegistryInitializationListener;
33 import org.apache.hivemind.internal.RegistryInfrastructure;
34
35 /**
36  * Class used to build a {@link org.apache.hivemind.Registry} from a {@link org.apache.hivemind.definition.RegistryDefinition}.
37  *
38  * A note about threadsafety: The assumption is that a single thread will access the RegistryBuilder
39  * at one time (typically, a startup class within some form of server or application). Code here and
40  * in many of the related classes is divided into construction-time logic and runtime logic. Runtime
41  * logic is synchronized and threadsafe. Construction-time logic is not threadsafe. Once the
42  * registry is fully constructed, it is not allowed to invoke those methods (though, at this time,
43  * no checks occur).
44  * <p>
45  * Runtime methods, such as {@link org.apache.hivemind.impl.ModuleImpl#getService(String, Class)}
46  * are fully threadsafe.
47  *
48  * @author Howard Lewis Ship
49  */

50 public final class RegistryBuilder
51 {
52     private static final Log LOG = LogFactory.getLog(RegistryBuilder.class);
53
54     static
55     {
56         if (!LOG.isErrorEnabled())
57         {
58             System.err
59                     .println("********************************************************************************");
60             System.err
61                     .println("* L O G G I N G C O N F I G U R A T I O N E R R O R *");
62             System.err
63                     .println("* ---------------------------------------------------------------------------- *");
64             System.err
65                     .println("* Logging is not enabled for org.apache.hivemind.impl.RegistryBuilder. *");
66             System.err
67                     .println("* Errors during HiveMind module descriptor parsing and validation may not be *");
68             System.err
69                     .println("* logged. This may result in difficult-to-trace runtime exceptions, if there *");
70             System.err
71                     .println("* are errors in any of your module descriptors. You should enable error *");
72             System.err
73                     .println("* logging for the org.apache.hivemind and hivemind loggers. *");
74             System.err
75                     .println("********************************************************************************");
76         }
77     }
78
79     /**
80      * Delegate used for handling errors.
81      */

82
83     private ErrorHandler _errorHandler;
84
85     private RegistryDefinition _registryDefinition;
86
87     /**
88      * Constructs a new instance that starts with a empty {@link RegistryDefinition} which can be
89      * requested by {@link #getRegistryDefinition()}.
90      */

91     public RegistryBuilder()
92     {
93         this(new RegistryDefinitionImpl(), new DefaultErrorHandler());
94     }
95     
96     /**
97      * Constructs a new instance that starts with the provided {@link RegistryDefinition}.
98      * The definition can still be altered afterwards.
99      */

100    public RegistryBuilder(RegistryDefinition registryDefinition)
101     {
102         this(registryDefinition, new DefaultErrorHandler());
103     }
104
105     public RegistryBuilder(ErrorHandler errorHandler)
106     {
107         this(new RegistryDefinitionImpl(), errorHandler);
108     }
109     
110     public RegistryBuilder(RegistryDefinition registryDefinition, ErrorHandler errorHandler)
111     {
112         _registryDefinition = registryDefinition;
113         _errorHandler = errorHandler;
114     }
115
116     /**
117      * @return the contained registry definition
118      */

119     public RegistryDefinition getRegistryDefinition()
120     {
121         return _registryDefinition;
122     }
123  
124     /**
125      * Constructs the registry from its {@link RegistryDefinition}. Default locale is used.
126      * @see #constructRegistry(Locale)
127      */

128     public Registry constructRegistry()
129     {
130         return constructRegistry();
131     }
132     
133     /**
134      * Constructs the registry from its {@link RegistryDefinition}.
135      * @param locale the locale used for translating resources
136      */

137     public Registry constructRegistry(Locale JavaDoc locale)
138     {
139         // Add Core HiveMind services like ClassFactory
140
CoreServicesProvider coreServicesProvider = new CoreServicesProvider();
141         coreServicesProvider.process(_registryDefinition, _errorHandler);
142         
143         // Try to resolve all so far unresolved extensions
144
ExtensionResolver extensionResolver = new ExtensionResolver(_registryDefinition, _errorHandler);
145         extensionResolver.resolveExtensions();
146         
147         checkDependencies(_registryDefinition);
148         checkContributionCounts(_registryDefinition);
149         
150         // Notify post processors
151
for (Iterator JavaDoc i = _registryDefinition.getPostProcessors().iterator(); i.hasNext();)
152         {
153             RegistryDefinitionPostProcessor processor = (RegistryDefinitionPostProcessor) i.next();
154
155             processor.postprocess(_registryDefinition, _errorHandler);
156         }
157
158         RegistryInfrastructureConstructor constructor = new RegistryInfrastructureConstructor(_errorHandler, LOG, locale);
159         RegistryInfrastructure infrastructure = constructor
160                 .constructRegistryInfrastructure(_registryDefinition);
161
162         // Notify initialization listeners
163
for (Iterator JavaDoc i = _registryDefinition.getRegistryInitializationListeners().iterator(); i.hasNext();)
164         {
165             RegistryInitializationListener listener = (RegistryInitializationListener) i.next();
166
167             listener.registryInitialized(infrastructure);
168         }
169         
170         infrastructure.startup();
171
172         return new RegistryImpl(infrastructure);
173     }
174     
175     /**
176      * Constructs the registry from a specified {@link RegistryDefinition}.
177      * @param definition the registry definition
178      * @param errorHandler errorHandler used for handling recoverable errors
179      * @param locale the locale used for translating resources
180      * @return the registry
181      */

182     public static Registry constructRegistry(RegistryDefinition definition, ErrorHandler errorHandler,
183             Locale JavaDoc locale)
184     {
185         RegistryBuilder builder = new RegistryBuilder(definition, errorHandler);
186         return builder.constructRegistry(locale);
187     }
188
189     /**
190      * Checks if all dependencies of modules are present.
191      */

192     private void checkDependencies(RegistryDefinition definition)
193     {
194         for (Iterator JavaDoc iterModules = definition.getModules().iterator(); iterModules.hasNext();)
195         {
196             ModuleDefinition module = (ModuleDefinition) iterModules.next();
197             
198             for (Iterator JavaDoc iterDependencies = module.getDependencies().iterator(); iterDependencies.hasNext();)
199             {
200                 String JavaDoc requiredModuleId = (String JavaDoc) iterDependencies.next();
201                 checkModuleDependency(definition, module, requiredModuleId);
202             }
203         }
204         
205     }
206
207     private void checkModuleDependency(RegistryDefinition definition, ModuleDefinition sourceModule, String JavaDoc requiredModuleId)
208     {
209         ModuleDefinition requiredModule = (ModuleDefinition) definition.getModule(requiredModuleId);
210         if (requiredModule == null)
211         {
212             // TODO: Include Location in Dependencies
213
_errorHandler.error(
214                     LOG,
215                     DefinitionMessages.dependencyOnUnknownModule(requiredModuleId),
216                     null,
217                     null);
218             return;
219         }
220     }
221     
222     /**
223      * Checks that each configuration extension point has the right number of contributions.
224      */

225     public void checkContributionCounts(RegistryDefinition definition)
226     {
227         for (Iterator JavaDoc iterModules = definition.getModules().iterator(); iterModules.hasNext();)
228         {
229             ModuleDefinition module = (ModuleDefinition) iterModules.next();
230             
231             for (Iterator JavaDoc iterConfigurations = module.getConfigurationPoints().iterator(); iterConfigurations.hasNext();)
232             {
233                 ConfigurationPointDefinition cpd = (ConfigurationPointDefinition) iterConfigurations.next();
234                 checkContributionCounts(module, cpd);
235             }
236         }
237     }
238     
239     private void checkContributionCounts(ModuleDefinition definingModule, ConfigurationPointDefinition configurationPoint)
240     {
241         Occurances expected = configurationPoint.getExpectedContributions();
242
243         int actual = configurationPoint.getContributions().size();
244
245         if (expected.inRange(actual))
246             return;
247
248         _errorHandler.error(LOG, DefinitionMessages.wrongNumberOfContributions(
249                 definingModule, configurationPoint,
250                 actual,
251                 expected), configurationPoint.getLocation(), null);
252     }
253
254     /**
255      * Automatically loads hivemind modules on the classpath which are
256      * provided by {@link RegistryProvider}s which are defined in Manifest-Files.
257      */

258     public void autoDetectModules()
259     {
260         RegistryProviderAutoDetector detector = new RegistryProviderAutoDetector(new DefaultClassResolver());
261         List JavaDoc providers = detector.getProviders();
262         for (Iterator JavaDoc iterProviders = providers.iterator(); iterProviders.hasNext();)
263         {
264             RegistryProvider provider = (RegistryProvider) iterProviders.next();
265             provider.process(getRegistryDefinition(), _errorHandler);
266         }
267     }
268
269     /**
270      * Constructs a default registry based on just the modules visible to the thread context class
271      * loader (this is sufficient is the majority of cases), and using the default locale. If you
272      * have different error handling needs, or wish to pick up HiveMind modules
273      * for non-standard locations, you must create a RegistryBuilder instance yourself.
274      */

275     public static Registry constructDefaultRegistry()
276     {
277         RegistryBuilder builder = new RegistryBuilder();
278         builder.autoDetectModules();
279         return builder.constructRegistry(Locale.getDefault());
280     }
281
282     public ErrorHandler getErrorHandler()
283     {
284         return _errorHandler;
285     }
286
287 }
Popular Tags