View Javadoc

1   /**
2    * - Digitalis Internal Framework v2.0 - (C) 2007, Digitalis Informatica. Distribuicao e Gestao de Informatica, Lda.
3    * Estrada de Paco de Arcos num.9 - Piso -1 2780-666 Paco de Arcos Telefone: (351) 21 4408990 Fax: (351) 21 4408999
4    * http://www.digitalis.pt
5    */
6   package pt.digitalis.dif.startup;
7   
8   import java.util.Collections;
9   import java.util.Comparator;
10  import java.util.Iterator;
11  import java.util.List;
12  import java.util.Stack;
13  
14  import pt.digitalis.dif.codegen.DIFCodeGenerator;
15  import pt.digitalis.dif.controller.interfaces.IModelManager;
16  import pt.digitalis.dif.controller.security.managers.IAuthenticationManager;
17  import pt.digitalis.dif.controller.security.managers.IIdentityManager;
18  import pt.digitalis.dif.controller.security.managers.impl.IdentityManagerStaticImpl;
19  import pt.digitalis.dif.dem.interfaces.IApplication;
20  import pt.digitalis.dif.dem.interfaces.IApplicationConfiguration;
21  import pt.digitalis.dif.dem.interfaces.IApplicationPrivate;
22  import pt.digitalis.dif.dem.interfaces.IDIFAPI;
23  import pt.digitalis.dif.dem.interfaces.IProvider;
24  import pt.digitalis.dif.dem.interfaces.IService;
25  import pt.digitalis.dif.dem.interfaces.IStage;
26  import pt.digitalis.dif.dem.managers.IDEMManager;
27  import pt.digitalis.dif.dem.managers.impl.UsageIssuesManagerImpl;
28  import pt.digitalis.dif.dem.objects.issues.UsageIssue;
29  import pt.digitalis.dif.exception.InternalFrameworkException;
30  import pt.digitalis.dif.exception.codegen.DIFCodeGenerationException;
31  import pt.digitalis.dif.ioc.DIFIoCRegistry;
32  import pt.digitalis.dif.utils.logging.DIFLogger;
33  import pt.digitalis.log.LogLevel;
34  import pt.digitalis.utils.bytecode.exceptions.CodeGenerationException;
35  import pt.digitalis.utils.inspection.exception.ResourceNotFoundException;
36  import pt.digitalis.utils.ioc.IIoCRegistry;
37  
38  /**
39   * This class contains the initialization logic to set the framework ready to serve requests. Listeners must check if
40   * the framework is ready to serve the request before submitting a new request for service.
41   * 
42   * @author Pedro Viegas <a href="mailto:pviegas@digitalis.pt">pviegas@digitalis.pt</a>
43   * @author Rodrigo Gonçalves <a href="mailto:rgoncalves@digitalis.pt">rgoncalves@digitalis.pt</a>
44   * @created Oct 8, 2007
45   */
46  final public class DIFInitializer {
47  
48      /** The indentation character. */
49      final static private String INDENTATION = "  ";
50  
51      /** Initialization state. */
52      static private boolean initialized = false;
53  
54      /**
55       * Adds the issues of a given location to the buffer.
56       * 
57       * @param location
58       *            the location
59       * @param buffer
60       *            the buffer
61       * @param indentPrefix
62       *            the indentation prefix string or output
63       */
64      static private void addIssuesToBuffer(String location, StringBuffer buffer, String indentPrefix)
65      {
66          // Reuse var
67          List<UsageIssue> issues = null;
68  
69          issues = UsageIssuesManagerImpl.getInstance().getIssues(location);
70  
71          for (UsageIssue usageIssue: issues)
72              buffer.append(indentPrefix + "  => " + usageIssue.getIssueType() + ": " + usageIssue.getIssueDescription()
73                      + "\n");
74      }
75  
76      /**
77       * Dumps the DEM.
78       */
79      static private void dumpDEM()
80      {
81          // When in debug dump the full DEM structure to the log.
82          StringBuffer buffer = new StringBuffer();
83          Stack<String> indentationsStack = new Stack<String>();
84          String currentIndentation = null;
85  
86          buffer.append("\n\nDumping DEM structure:\n");
87          buffer.append("-----------------------------------------\n");
88  
89          IDEMManager dem = DIFIoCRegistry.getRegistry().getImplementation(IDEMManager.class);
90  
91          Iterator<IProvider> providers = dem.getProviders().values().iterator();
92  
93          while (providers.hasNext())
94          {
95              IProvider provider = providers.next();
96  
97              if (providers.hasNext())
98              {
99                  currentIndentation = INDENTATION + "|   ";
100                 buffer.append(INDENTATION + "|-- Provider: " + provider.getName() + " (" + provider.getID() + ")\n");
101             }
102             else
103             {
104                 currentIndentation = INDENTATION + "    ";
105                 buffer.append(INDENTATION + "`-- Provider: " + provider.getName() + " (" + provider.getID() + ")\n");
106             }
107 
108             if (UsageIssuesManagerImpl.getInstance().hasIssues(provider.getOriginalClassName()))
109                 addIssuesToBuffer(provider.getOriginalClassName(), buffer, currentIndentation);
110 
111             // Applications iteration
112             Iterator<IApplication> applications = provider.getApplications().values().iterator();
113 
114             while (applications.hasNext())
115             {
116                 IApplication application = applications.next();
117                 indentationsStack.add(currentIndentation);
118 
119                 if (applications.hasNext())
120                 {
121                     buffer.append(currentIndentation + INDENTATION + "|-- Application: " + application.getName() + " ("
122                             + application.getID() + ")\n");
123                     currentIndentation += INDENTATION + "|   ";
124                 }
125                 else
126                 {
127                     buffer.append(currentIndentation + INDENTATION + "`-- Application: " + application.getName() + " ("
128                             + application.getID() + ")\n");
129                     currentIndentation += INDENTATION + "    ";
130                 }
131 
132                 if (UsageIssuesManagerImpl.getInstance().hasIssues(application.getOriginalClassName()))
133                     addIssuesToBuffer(application.getOriginalClassName(), buffer, currentIndentation);
134 
135                 // Services iteration
136                 Iterator<IService> services = application.getServices().values().iterator();
137 
138                 while (services.hasNext())
139                 {
140                     IService service = services.next();
141                     indentationsStack.add(currentIndentation);
142 
143                     if (services.hasNext())
144                     {
145                         buffer.append(currentIndentation + INDENTATION + "|-- Service: " + service.getName() + " ("
146                                 + service.getID() + ")\n");
147                         currentIndentation += INDENTATION + "|   ";
148                     }
149                     else
150                     {
151                         buffer.append(currentIndentation + INDENTATION + "`-- Service: " + service.getName() + " ("
152                                 + service.getID() + ")\n");
153                         currentIndentation += INDENTATION + "    ";
154                     }
155 
156                     if (UsageIssuesManagerImpl.getInstance().hasIssues(service.getOriginalClassName()))
157                         addIssuesToBuffer(service.getOriginalClassName(), buffer, currentIndentation);
158 
159                     // Stages iteration
160                     Iterator<IStage> stages = service.getStages().values().iterator();
161 
162                     while (stages.hasNext())
163                     {
164                         IStage stage = stages.next();
165                         indentationsStack.add(currentIndentation);
166 
167                         if (stages.hasNext())
168                         {
169                             buffer.append(currentIndentation + INDENTATION + "|-- " + stage.getName() + " ("
170                                     + stage.getID() + ")\n");
171                             currentIndentation += INDENTATION + "|   ";
172                         }
173                         else
174                         {
175                             buffer.append(currentIndentation + INDENTATION + "`-- " + stage.getName() + " ("
176                                     + stage.getID() + ")\n");
177                             currentIndentation += INDENTATION + "    ";
178                         }
179 
180                         if (UsageIssuesManagerImpl.getInstance().hasIssues(stage.getOriginalClassName()))
181                             addIssuesToBuffer(stage.getOriginalClassName(), buffer, currentIndentation);
182 
183                         currentIndentation = indentationsStack.pop();
184                     }
185 
186                     buffer.append(currentIndentation + "\n");
187                     currentIndentation = indentationsStack.pop();
188                 }
189 
190                 currentIndentation = indentationsStack.pop();
191             }
192         }
193 
194         buffer.append("-----------------------------------------\n\n");
195 
196         if (DIFStartupConfiguration.getLogLevel().equals(LogLevel.DEBUG))
197             DIFLogger.getLogger().debug(buffer.toString());
198         else
199             DIFLogger.getLogger().info(buffer.toString());
200     }
201 
202     /**
203      * DIF initialization method. Defines the order of the initialization steps.
204      * 
205      * @param initDEMInstances
206      *            if T searches for DEM instances and initializes then
207      * @param upgradeModelManagers
208      *            if T upgrades all Model Manager contributions
209      * @return T if initialization has successfully completed (or if has been previously done), F otherwise
210      */
211     synchronized static public boolean initialize(boolean initDEMInstances, boolean upgradeModelManagers)
212     {
213         if (!isInitialized())
214         {
215             try
216             {
217                 // IoC initialization (includes module discovery)
218                 IIoCRegistry iocRegistry = DIFIoCRegistry.getRegistry();
219 
220                 // Startup the Identity and Authorization since they will be called form the CG process of the DEM
221                 iocRegistry.getImplementation(IIdentityManager.class);
222                 iocRegistry.getImplementation(IAuthenticationManager.class);
223 
224                 /*
225                  * ATTENTION !!! ......................................................................................
226                  * The model upgrade must be before all things, mainly because:........................................
227                  * - code generation may need to invoke identity manager ..............................................
228                  * - application init usually initializes all models ..................................................
229                  */
230                 if (upgradeModelManagers)
231                 {
232                     // Upgrades all database model, declared to the current application
233                     DIFLogger.getLogger().info("Initializing Model Manager upgrades...");
234                     DIFLogger.getLogger().increaseIndentation();
235                     for (IModelManager modelManager: DIFIoCRegistry.getRegistry().getImplementations(
236                             IModelManager.class))
237                     {
238                         if (modelManager.isEnabled())
239                         {
240                             if (!modelManager.isUpToDate())
241                             {
242                                 String currentVersion = modelManager.getCurrentVersion();
243                                 DIFLogger.getLogger().info(
244                                         "Model '" + modelManager.getSchema() + "': Upgrading from " + currentVersion);
245 
246                                 modelManager.updateVersion();
247                                 DIFLogger.getLogger().info(
248                                         "Model '" + modelManager.getSchema() + "': Upgraded to "
249                                                 + modelManager.getCurrentVersion());
250                             }
251                             else
252                             {
253                                 DIFLogger.getLogger().info("Model '" + modelManager.getSchema() + "': Up to date");
254                             }
255                         }
256                     }
257                     DIFLogger.getLogger().decreaseIndentation();
258                 }
259 
260                 // Create the DIF code generator and inject it's dependencies into it
261                 DIFCodeGenerator codeGen = new DIFCodeGenerator();
262                 iocRegistry.injectDependencies(codeGen);
263 
264                 if (initDEMInstances)
265                 {
266                     // Discover all registered DEM entities packages
267                     codeGen.collectRegisteredPackages();
268 
269                     // Search registered entities
270                     codeGen.searchRegisteredPackages();
271 
272                     // Enhance the registered entities
273                     codeGen.enhanceDEMClasses();
274                 }
275 
276                 // Log all issues if in debug
277                 if (DIFStartupConfiguration.getLogLevel().equals(LogLevel.DEBUG))
278                     UsageIssuesManagerImpl.getInstance().logAllIssuesByType();
279 
280                 // Clean up all temporary data
281                 codeGen.cleanUp();
282 
283                 // Initialize the declared APIs
284                 initializeAPIs();
285 
286                 // Run the applications initialization procedures
287                 initializeApplications();
288 
289                 // If the identityManager is the static implementation, call the static users initialization
290                 IIdentityManager identityManager = DIFIoCRegistry.getRegistry().getImplementation(
291                         IIdentityManager.class);
292                 if (identityManager instanceof IdentityManagerStaticImpl)
293                     ((IdentityManagerStaticImpl) identityManager).initializeStaticCustomUsers();
294 
295                 initialized = true;
296 
297                 // Dump DEM structure with associated issues (if any), if DiF is running in DEBUG mode or if there are
298                 // issues
299                 if (DIFStartupConfiguration.getLogLevel().equals(LogLevel.DEBUG)
300                         || UsageIssuesManagerImpl.getInstance().hasIssues()
301                         || DIFStartupConfiguration.getDeveloperMode() || DIFStartupConfiguration.getTestingMode())
302                 {
303                     dumpDEM();
304                 }
305 
306             }
307             catch (ResourceNotFoundException resourceNotFoundException)
308             {
309                 resourceNotFoundException.printStackTrace();
310 
311             }
312             catch (CodeGenerationException codeGenerationException)
313             {
314                 codeGenerationException.printStackTrace();
315             }
316             catch (DIFCodeGenerationException e)
317             {
318                 e.printStackTrace();
319             }
320             catch (InternalFrameworkException e)
321             {
322                 throw new RuntimeException(e);
323             }
324 
325         }
326         return initialized;
327     }
328 
329     /**
330      * Initialize APIs.
331      * 
332      * @throws InternalFrameworkException
333      */
334     private static void initializeAPIs() throws InternalFrameworkException
335     {
336         List<IDIFAPI> list = DIFIoCRegistry.getRegistry().getImplementations(IDIFAPI.class);
337 
338         Collections.sort(list, new Comparator<IDIFAPI>() {
339 
340             public int compare(IDIFAPI a, IDIFAPI b)
341             {
342                 return a.order().compareTo(b.order());
343             }
344         });
345 
346         for (IDIFAPI difApi: list)
347         {
348             difApi.initialize();
349         }
350 
351     }
352 
353     /**
354      * Initialize all registered DIF Applications.
355      */
356     synchronized static public void initializeApplications()
357     {
358         List<IApplicationConfiguration> appConfImpls = DIFIoCRegistry.getRegistry().getImplementations(
359                 IApplicationConfiguration.class);
360         if (appConfImpls.size() > 0)
361         {
362             appConfImpls.get(0).processConfigurations();
363             DIFLogger.getLogger()
364                     .info("Initializing Applications Configurations using: "
365                             + appConfImpls.get(0).getClass().getSimpleName());
366         }
367 
368         IDEMManager demManager = DIFIoCRegistry.getRegistry().getImplementation(IDEMManager.class);
369         DIFLogger.getLogger().info("Initializing Applications...");
370 
371         for (IProvider provider: demManager.getProviders().values())
372             for (IApplication application: provider.getApplications().values())
373                 ((IApplicationPrivate) application).__CG__initialize();
374     }
375 
376     /**
377      * Initialization state inspector.
378      * 
379      * @return T if the framework has been initialized
380      */
381     synchronized static public boolean isInitialized()
382     {
383         return initialized;
384     }
385 }