Source code: recoin/system/RuntimeManager.java
1
2 package recoin.system;
3
4 import recoin.group.Component;
5 import recoin.group.Module;
6 import recoin.group.ModuleGroup;
7 import recoin.group.connector.AdminConnector;
8 import recoin.system.session.SessionManager;
9 import recoin.exception.*;
10 import recoin.exception.ClassLoadingException;
11 import recoin.exception.InitiationException;
12
13 import java.util.Enumeration;
14 import java.util.Hashtable;
15 import java.util.Vector;
16
17 import org.apache.log4j.Logger;
18
19 /**
20 * The RuntimeManager administrates and observes the runtime components of the application.
21 * <br><br>
22 * A RuntimeManager executes orders received from an ApplicationManager object. Because
23 * the RuntimeManager is a central object that holds references to all runtime components,
24 * all exceptions and logging is handled here.
25 * @author Jan H. Scheufen
26 * @version 0.2.9
27 */
28 public class RuntimeManager
29 {
30 /**
31 * The global properties that were set in the configuration file.
32 */
33 private Hashtable properties;
34 /**
35 * The SessionManager.
36 */
37 private SessionManager sessionManager;
38 /**
39 * The ApplicationManager that controls the application.
40 */
41 private ApplicationManager applicationManager;
42 /**
43 * The RepositoryManager to load and unload Module objects to and from the layers.
44 */
45 private RepositoryManager repositoryManager;
46 /**
47 * The remote administration service.
48 */
49 private AdminConnector remoteAdmin;
50 /**
51 * The ModuleGroups.
52 */
53 private Hashtable moduleGroups;
54 /**
55 * The logger for this class.
56 */
57 static Logger logger;
58
59 /**
60 * Creates a new RuntimeManager that is controlled by the specified ApplicationManager.
61 * It is initiated with the specified properties and uses the data in the specified
62 * Repository by loading the RepositoryManager class that is declared in the
63 * Repository.
64 * @param aManager the ApplicationManager that controls this RuntimeManager
65 * @param props the global properties
66 * @param rep the Repository to use
67 * @throws recoin.exception.ClassLoadingException
68 */
69 public RuntimeManager(ApplicationManager aManager, Hashtable props, Repository rep) throws ClassLoadingException
70 {
71 // Initialize the logger for this class.
72 logger = Logger.getLogger( RuntimeManager.class.getName() );
73 logger.info(System.getProperty("line.separator") + " ######################################" + System.getProperty("line.separator") +
74 "-------<|||||||| Starting up RECOIN ||||||||>--------------------------------------<<<<<<" + System.getProperty("line.separator") +
75 " \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\");
76 moduleGroups = new Hashtable();
77 properties = props;
78
79 applicationManager = aManager;
80 sessionManager = new SessionManager(this);
81 try
82 {
83 repositoryManager = (RepositoryManager)Class.forName(rep.getClassname()).newInstance();
84 repositoryManager.setRepository(rep);
85 repositoryManager.setRuntimeManager(this);
86 repositoryManager.initiate();
87 logger.info("RepositoryManager "+repositoryManager.getClass().getName()+" loaded successfully.");
88 }
89 catch( ClassNotFoundException e )
90 {
91 throw new ClassLoadingException( "Couldn't find class for RepositoryManager "+rep.getClassname(), e );
92 }
93 catch( InstantiationException e )
94 {
95 throw new ClassLoadingException( "Couldn't initiate RepositoryManager "+rep.getClassname(), e );
96 }
97 catch( IllegalAccessException e )
98 {
99 throw new ClassLoadingException( "Illegal Access for class "+rep.getClassname(), e );
100 }
101 catch (InitiationException e)
102 {
103 logger.error("RepositoryManager "+rep.getClassname()+" not initiated!");
104 }
105
106 logger.info("Starting remote administration service.");
107 remoteAdmin = new AdminConnector( this );
108
109 logger.debug("Populating module groups.");
110 String groupname = "";
111
112 // ##### Connector Group #####
113 groupname = ModuleGroup.CONNECTOR;
114 moduleGroups.put( groupname, createModuleGroup(groupname) );
115
116 // ##### PreQuery Group #####
117 groupname = ModuleGroup.PREQUERY;
118 moduleGroups.put( groupname, createModuleGroup(groupname) );
119
120 // ##### Adapter Group #####
121 groupname = ModuleGroup.ADAPTER;
122 moduleGroups.put( groupname, createModuleGroup(groupname) );
123
124 // ##### PostResult Group #####
125 groupname = ModuleGroup.POSTRESULT;
126 moduleGroups.put( groupname, createModuleGroup(groupname) );
127
128 }
129
130 /**
131 * Returns the ModuleGroups in a Hashtable where the groupnames are the keys.
132 * @return the ModuleGroups
133 */
134 public Hashtable getModuleGroups()
135 {
136 return moduleGroups;
137 }
138
139 /**
140 * Returns the RepositoryManager that is used to access the repository.
141 * @return the RepositoryManager
142 */
143 public RepositoryManager getRepositoryManager()
144 {
145 return repositoryManager;
146 }
147
148 /**
149 * Returns the SessionManager.
150 * @return the SessionManager
151 */
152 public SessionManager getSessionManager()
153 {
154 return sessionManager;
155 }
156
157 /**
158 * Removes those modules from the specified Vector which have their
159 * <code>activate</code> field set to false and returns the resulting Vector.
160 * @param modules a Vector of Module objects
161 * @return the filtered Vector
162 */
163 private Vector getStartupModules( Vector modules )
164 {
165 // Reset all Components inside of Module objects to uninitiated and remove unwanted modules.
166 for( Enumeration enum = modules.elements(); enum.hasMoreElements(); )
167 {
168 Module m = (Module) enum.nextElement();
169 for( Enumeration compEnum = m.getComponents().elements(); compEnum.hasMoreElements(); )
170 {
171 try
172 {
173 Component component = (Component)compEnum.nextElement();
174 component.setInitiated(false);
175 repositoryManager.updateComponent( component );
176 }
177 catch (RepositoryException e)
178 {
179 logger.error("Unable to update Component in repository.",e);
180 }
181 }
182 if( !m.getActivateOnStartup() )
183 {
184 try
185 {
186 modules.remove( m );
187 m.setActive(false);
188 repositoryManager.updateModule( m );
189 }
190 catch (RepositoryException e)
191 {
192 logger.error("Unable to update Module with id="+m.getID(),e);
193 }
194 }
195 }
196 logger.debug("Found "+modules.size()+" Modules to load on startup.");
197 return modules;
198 }
199
200 /**
201 * Creates and returns a ModuleGroup for the specified groupname that is automatically
202 * populated with the Modules of the same groupname that have declared to be loaded
203 * on startup, i.e. have their <code>activate</code> field set to <code>true</code>.
204 * @param groupname the name of the ModuleGroup
205 * @return the new ModuleGroup
206 */
207 private ModuleGroup createModuleGroup( String groupname )
208 {
209 ModuleGroup group = (ModuleGroup) new ModuleGroup( this, groupname );
210 Vector modules = new Vector();
211 try
212 {
213 modules = repositoryManager.getModulesByGroupname(groupname);
214 }
215 catch (RepositoryException e)
216 {
217 logger.error("Couldn't get Modules for groupname="+groupname+" from repository.", e);
218 }
219 modules = getStartupModules( modules );
220 logger.debug("Found total of "+modules.size()+" startup Modules for ModuleGroup name="+groupname);
221 // Set modules and activate them.
222 if( modules.size() > 0 )
223 {
224 group.setModules( modules );
225 }
226 logger.info("ModuleGroup '"+groupname+"' created successfully.");
227 // Update repository.
228 logger.debug("Updating Module information in repository for newly added Module objects.");
229 for( Enumeration enum = modules.elements(); enum.hasMoreElements(); )
230 {
231 try
232 {
233 Module module = (Module) enum.nextElement();
234 repositoryManager.updateModule( module );
235 }
236 catch (RepositoryException e)
237 {
238 logger.error("Unable to update Module after activating Module objects in group '"+groupname+"'.",e);
239 }
240 }
241 return group;
242 }
243
244 /**
245 * Loads the specified Component into the Module with the specified ID.
246 * After locating the Module, the Component is added to the Module. If the
247 * Component had already been loaded previously, it is first removed
248 * and then added again, thus performing a reload.
249 * @param component the Component to load
250 * @param moduleID the ID of the Module
251 * @return true if Component has been added successfully, false otherwise
252 */
253 public boolean loadComponent(Component component, int moduleID)
254 {
255 // find Module object in moduleGroups
256 for( Enumeration groupKeys = moduleGroups.keys(); groupKeys.hasMoreElements(); )
257 {
258 String name = (String)groupKeys.nextElement();
259 ModuleGroup group = (ModuleGroup)moduleGroups.get( name );
260 for( Enumeration modules = group.getModules().elements(); modules.hasMoreElements(); )
261 {
262 Module module = (Module)modules.nextElement();
263 if( module.getID() == moduleID )
264 {
265 for( Enumeration compEnum = module.getComponents().elements(); compEnum.hasMoreElements(); )
266 {
267 Component comp = (Component)compEnum.nextElement();
268 if( comp.getID() == component.getID() )
269 {
270 module.removeComponent( comp );
271 }
272 }
273 // add the Component to the Module
274 module.addComponent( component );
275 }
276 }
277 }
278
279 try
280 {
281 // to make sure, first unload Component in repository. Otherwise RepositoryException
282 // might be thrown because of duplicate key entry!
283 repositoryManager.unloadComponent( component.getID(), moduleID );
284 // update the relationship between Component and Module
285 repositoryManager.loadComponent( component.getID(), moduleID );
286 // update the state of the Component loaded in the Module
287 repositoryManager.updateComponent( component, moduleID );
288 }
289 catch (RepositoryException e)
290 {
291 logger.error("Unable to update repository while (re)loading Component with id="+component.getID()+" to Module with id="+moduleID,e);
292 return false;
293 }
294 return true;
295 }
296
297 /**
298 * Unloads the specified Component from the Module with the specified ID.
299 * After locating the Module, the Component is removed from the Module and
300 * its <code>initiated</code> field is set to <code>false</code>.
301 * @param component the Component to load
302 * @param moduleID the ID of the Module
303 * @return true if Component has been removed successfully, false otherwise
304 */
305 public boolean unloadComponent(int componentID, int moduleID)
306 {
307 // find Module object in moduleGroups
308 for( Enumeration groupKeys = moduleGroups.keys(); groupKeys.hasMoreElements(); )
309 {
310 String name = (String)groupKeys.nextElement();
311 ModuleGroup group = (ModuleGroup)moduleGroups.get( name );
312 for( Enumeration modules = group.getModules().elements(); modules.hasMoreElements(); )
313 {
314 Module module = (Module)modules.nextElement();
315 if( module.getID() == moduleID )
316 {
317 Component component;
318 // remove Component if it is contained in the Module.
319 for( Enumeration enum = module.getComponents().elements(); enum.hasMoreElements(); )
320 {
321 component = (Component) enum.nextElement();
322 if( component.getID() == componentID )
323 {
324 module.removeComponent( component );
325 // since only one Component with the same id can be in Module, break for-loop
326 break;
327 }
328 }
329 }
330 }
331 }
332
333 try
334 {
335 // update the relationship between Component and Module in the repository.
336 // the state of the Component is automatically lost, so Component doesn't have
337 // to be updated!
338 repositoryManager.unloadComponent( componentID, moduleID );
339 }
340 catch (RepositoryException e)
341 {
342 logger.error("Unable to update repository while unloading Component with id="+componentID+" from Module with id="+moduleID,e);
343 return false;
344 }
345 return true;
346 }
347
348 /**
349 * Deploys the specfified Module to the ModuleGroup that has the same groupname.
350 * After the Module is added to the ModuleGroup, it is activated.
351 * @param module the Module
352 */
353 public void deployModule(Module module)
354 {
355 ModuleGroup group = (ModuleGroup)moduleGroups.get( module.getGroupname() );
356 if( group.getModules().contains( module ))
357 logger.warn("Module id="+module.getID()+" already contained in ModuleGroup '"+group.getGroupname());
358 else
359 logger.debug("Adding Module id="+module.getID()+" to ModuleGroup '"+group.getGroupname());
360 try
361 {
362 // add Module to ModuleGroup and activate
363 group.addModule( module );
364 // update repository
365 repositoryManager.activateModule( module.getID(), module.isActive() );
366 // Also update Component objects.
367 for( Enumeration compEnum = module.getComponents().elements(); compEnum.hasMoreElements(); )
368 {
369 Component component = (Component)compEnum.nextElement();
370 // update initiated state of component in repository
371 repositoryManager.updateComponent( component, module.getID() );
372 }
373 logger.debug("Module with id="+module.getID()+" successfully deployed to group '"+group.getGroupname()+"'.");
374 }
375 catch (IllegalModuleException e)
376 {
377 logger.error("Unable to add Module with id="+module.getID()+" to ModuleGroup "+group.getGroupname(),e);
378 }
379 catch (RepositoryException e)
380 {
381 logger.error("Unable to update Module with id="+module.getID()+" in repository.",e);
382 }
383 }
384
385 /**
386 * Undeploys the Module with the specified ID. Because only the ID is used to
387 * locate the Module, all ModuleGroups are searched and any Modules with the
388 * same ID are removed. In general this shouldn't happen, because there should
389 * only be one ModuleGroup for each groupname.
390 * @param id the ID of the Module
391 */
392 public void undeployModule(int id)
393 {
394 // find Module object in moduleGroups
395 for( Enumeration groupKeys = moduleGroups.keys(); groupKeys.hasMoreElements(); )
396 {
397 String name = (String)groupKeys.nextElement();
398 ModuleGroup group = (ModuleGroup)moduleGroups.get( name );
399 for( Enumeration modules = group.getModules().elements(); modules.hasMoreElements(); )
400 {
401 Module module = (Module)modules.nextElement();
402 if( module.getID() == id )
403 {
404 try
405 {
406 // Remove Module from ModuleGroup and deactivate.
407 group.removeModule( module );
408 // Update state of Module in repository
409 repositoryManager.activateModule( module.getID(), module.isActive() );
410 // Also update Component objects.
411 for( Enumeration compEnum = module.getComponents().elements(); compEnum.hasMoreElements(); )
412 {
413 Component component = (Component)compEnum.nextElement();
414 component.setInitiated(false);
415 // update initiated state of component in repository
416 repositoryManager.updateComponent( component, module.getID() );
417 }
418 }
419 catch (RepositoryException e)
420 {
421 logger.error("Unable to update repository while undeploying Module with id="+id,e);
422 }
423 }
424 }
425 }
426 }
427
428 }