View Javadoc

1   /* This file is part of the project "Hilbert II" - http://www.qedeq.org" target="alexandria_uri">http://www.qedeq.org
2    *
3    * Copyright 2000-2014,  Michael Meyling <mime@qedeq.org>.
4    *
5    * "Hilbert II" is free software; you can redistribute
6    * it and/or modify it under the terms of the GNU General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU General Public License for more details.
14   */
15  
16  package org.qedeq.kernel.bo;
17  
18  import java.io.File;
19  import java.io.FileOutputStream;
20  import java.io.IOException;
21  import java.net.URL;
22  import java.nio.channels.FileLock;
23  
24  import org.qedeq.base.io.IoUtility;
25  import org.qedeq.base.trace.Trace;
26  import org.qedeq.base.utility.StringUtility;
27  import org.qedeq.kernel.bo.common.BasicKernel;
28  import org.qedeq.kernel.bo.common.KernelProperties;
29  import org.qedeq.kernel.bo.common.KernelServices;
30  import org.qedeq.kernel.bo.common.KernelState;
31  import org.qedeq.kernel.bo.common.QedeqBo;
32  import org.qedeq.kernel.bo.common.Kernel;
33  import org.qedeq.kernel.bo.common.ServiceJob;
34  import org.qedeq.kernel.bo.log.QedeqLog;
35  import org.qedeq.kernel.se.common.ModuleAddress;
36  import org.qedeq.kernel.se.common.ModuleService;
37  import org.qedeq.kernel.se.config.QedeqConfig;
38  import org.qedeq.kernel.se.visitor.InterruptException;
39  
40  
41  /**
42   * This class provides static access methods for the kernel.
43   *
44   * @author  Michael Meyling
45   */
46  public final class KernelContext implements KernelProperties, KernelServices {
47  
48      /** Message for non started kernel. */
49      private static final String KERNEL_NOT_STARTED = "Kernel not started";
50  
51      /** Message for non initialized kernel. */
52      private static final String KERNEL_NOT_INITIALIZED = "Kernel not initialized";
53  
54      /** This class. */
55      private static final Class CLASS = KernelContext.class;
56  
57      /** One and only instance of this class. */
58      private static final KernelContext INSTANCE = new KernelContext();
59  
60      /** Lock file. */
61      private File lockFile;
62  
63      /** Lock file stream. */
64      private FileOutputStream lockStream;
65  
66      /** Initial kernel state. */
67      private final KernelState initialState = new KernelState() {
68  
69          public void init(final QedeqConfig config, final Kernel moduleServices, final KernelProperties basic)
70                  throws IOException {
71              if (config == null) {
72                  throw new NullPointerException("QedeqConfig is null");
73              }
74              if (moduleServices == null) {
75                  throw new NullPointerException("ServiceModule is null");
76              }
77              if (basic == null) {
78                  throw new NullPointerException("KernelProperties is null");
79              }
80              KernelContext.this.config = config;
81              KernelContext.this.basic = basic;
82              Trace.setTraceOn(config.isTraceOn());
83              checkJavaVersion();
84              createAllNecessaryDirectories();
85              checkIfApplicationIsAlreadyRunningAndLockFile();
86              KernelContext.this.services = moduleServices;
87              QedeqLog.getInstance().logMessage("--------------------------------------------------"
88                   + "---------------------------------------");
89              QedeqLog.getInstance().logMessage("This is "
90                  + KernelContext.getInstance().getDescriptiveKernelVersion());
91              QedeqLog.getInstance().logMessage("  see \"http://www.qedeq.org\" for more "
92                  + "information");
93              QedeqLog.getInstance().logMessage("  supports rules till version "
94                  + KernelContext.getInstance().getMaximalRuleVersion());
95              QedeqLog.getInstance().logMessage("  Java version: "
96                  + StringUtility.alignRight(System.getProperty("java.version", "unknown"), 10));
97              QedeqLog.getInstance().logMessage("  used memory:  "
98                  + StringUtility.alignRight(Runtime.getRuntime().totalMemory()
99                  - Runtime.getRuntime().freeMemory(), 10));
100             QedeqLog.getInstance().logMessage("  free memory:  "
101                 + StringUtility.alignRight(Runtime.getRuntime().freeMemory(), 10));
102             QedeqLog.getInstance().logMessage("  total memory: "
103                 + StringUtility.alignRight(Runtime.getRuntime().totalMemory(), 10));
104             QedeqLog.getInstance().logMessage("  max. memory:  "
105                 + StringUtility.alignRight(Runtime.getRuntime().maxMemory(), 10));
106             QedeqLog.getInstance().logMessage("  processors/cores: "
107                 + StringUtility.alignRight(Runtime.getRuntime().availableProcessors(), 6));
108             currentState = initializedState;
109         }
110 
111         public void startup() {
112             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
113         }
114 
115         public void shutdown() {
116             currentState = initialState;
117             // close stream and associated channel
118             IoUtility.close(lockStream);
119             lockStream = null;
120             config = null;
121             services = null;
122         }
123 
124         public boolean removeAllModules() {
125             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
126         }
127 
128         public void removeModule(final ModuleAddress address) {
129             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
130         }
131 
132         public boolean clearLocalBuffer() {
133             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
134         }
135 
136         public QedeqBo loadModule(final ModuleAddress address) {
137             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
138         }
139 
140         public boolean loadAllModulesFromQedeq() {
141             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
142         }
143 
144         public boolean loadRequiredModules(final ModuleAddress address) {
145             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
146         }
147 
148         public ModuleAddress[] getAllLoadedModules() {
149             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
150         }
151 
152         public QedeqBo getQedeqBo(final ModuleAddress address) {
153             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
154         }
155 
156         public ModuleAddress getModuleAddress(final URL url) {
157             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
158         }
159 
160         public ModuleAddress getModuleAddress(final String url) {
161             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
162         }
163 
164         public ModuleAddress getModuleAddress(final File file) {
165             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
166         }
167 
168         public String getSource(final ModuleAddress address) {
169             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
170         }
171 
172         public boolean checkWellFormedness(final ModuleAddress address) {
173             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
174         }
175 
176         public boolean checkFormallyProved(final ModuleAddress address) {
177             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
178         }
179 
180         public ModuleService[] getPlugins() {
181             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
182         }
183 
184         public Object executePlugin(final String pluginName, final ModuleAddress address,
185                 final Object data) {
186             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
187         }
188 
189         public void clearAllPluginResults(final ModuleAddress address) {
190             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
191         }
192 
193         public ServiceJob[] getServiceProcesses() {
194             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
195         }
196 
197         public ServiceJob[] getRunningServiceProcesses() {
198             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
199         }
200 
201         public void terminateAllServiceProcesses() {
202             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
203         }
204 
205     };
206 
207     /** Initial kernel state. */
208     private final KernelState initializedState = new KernelState() {
209 
210         public void init(final QedeqConfig config, final Kernel moduleServices,
211                 final KernelProperties basic) throws IOException {
212             throw new IllegalStateException("Kernel is already initialized");
213         }
214 
215         public void startup() {
216             services.startupServices();
217             currentState = readyState;
218             QedeqLog.getInstance().logMessage("QEDEQ kernel opened.");
219         }
220 
221         public void shutdown() {
222             services.shutdownServices();
223             KernelContext.this.services = null;
224             initialState.shutdown();
225             QedeqLog.getInstance().logMessage("QEDEQ Kernel closed.");
226         }
227 
228         public boolean removeAllModules() {
229             throw new IllegalStateException(KERNEL_NOT_STARTED);
230         }
231 
232         public void removeModule(final ModuleAddress address) {
233             throw new IllegalStateException(KERNEL_NOT_STARTED);
234         }
235 
236         public boolean clearLocalBuffer() {
237             throw new IllegalStateException(KERNEL_NOT_STARTED);
238         }
239 
240         public QedeqBo loadModule(final ModuleAddress address) {
241             throw new IllegalStateException(KERNEL_NOT_STARTED);
242         }
243 
244         public boolean loadAllModulesFromQedeq() {
245             throw new IllegalStateException(KERNEL_NOT_STARTED);
246         }
247 
248         public boolean loadRequiredModules(final ModuleAddress address) {
249             throw new IllegalStateException(KERNEL_NOT_STARTED);
250         }
251 
252         public ModuleAddress[] getAllLoadedModules() {
253             throw new IllegalStateException(KERNEL_NOT_STARTED);
254         }
255 
256         public QedeqBo getQedeqBo(final ModuleAddress address) {
257             throw new IllegalStateException(KERNEL_NOT_STARTED);
258         }
259 
260         public ModuleAddress getModuleAddress(final URL url) {
261             throw new IllegalStateException(KERNEL_NOT_STARTED);
262         }
263 
264         public ModuleAddress getModuleAddress(final String url) {
265             throw new IllegalStateException(KERNEL_NOT_STARTED);
266         }
267 
268         public ModuleAddress getModuleAddress(final File file) {
269             throw new IllegalStateException(KERNEL_NOT_STARTED);
270         }
271 
272         public String getSource(final ModuleAddress address) {
273             throw new IllegalStateException(KERNEL_NOT_STARTED);
274         }
275 
276         public boolean checkWellFormedness(final ModuleAddress address) {
277             throw new IllegalStateException(KERNEL_NOT_STARTED);
278         }
279 
280         public boolean checkFormallyProved(final ModuleAddress address) {
281             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
282         }
283 
284         public ModuleService[] getPlugins() {
285             return services.getPlugins();
286         }
287 
288         public Object executePlugin(final String pluginName, final ModuleAddress address,
289                 final Object data) {
290             throw new IllegalStateException(KERNEL_NOT_STARTED);
291         }
292 
293         public void clearAllPluginResults(final ModuleAddress address) {
294             throw new IllegalStateException(KERNEL_NOT_STARTED);
295         }
296 
297         public ServiceJob[] getServiceProcesses() {
298             throw new IllegalStateException(KERNEL_NOT_STARTED);
299         }
300 
301         public ServiceJob[] getRunningServiceProcesses() {
302             throw new IllegalStateException(KERNEL_NOT_STARTED);
303         }
304 
305         public void terminateAllServiceProcesses() {
306             throw new IllegalStateException(KERNEL_NOT_STARTED);
307         }
308 
309     };
310 
311     /** State for ready kernel. */
312     private final KernelState readyState = new KernelState() {
313 
314         public void init(final QedeqConfig config, final Kernel moduleServices,
315                 final KernelProperties basic) throws IOException {
316             // we are already ready
317         }
318 
319         public void startup() {
320             // we are already ready
321         }
322 
323         public void shutdown() {
324             try {
325                 final ModuleAddress[] addresses = services.getAllLoadedModules();
326                 if (addresses != null) {
327                     final String[] buffer = new String[addresses.length];
328                     for (int i = 0; i < addresses.length; i++) {
329                         buffer[i] = addresses[i].toString();
330                     }
331                     getConfig().setPreviouslyLoadedModules(buffer);
332                     getConfig().store();
333                     QedeqLog.getInstance().logMessage("Current config file successfully saved.");
334                 }
335             } catch (IOException e) {
336                 Trace.trace(CLASS, this, "shutdown()", e);
337                 QedeqLog.getInstance().logMessage("Saving current config file failed.");
338             }
339             initializedState.shutdown();
340         }
341 
342         public boolean removeAllModules() {
343             return services.removeAllModules();
344         }
345 
346         public void removeModule(final ModuleAddress address) {
347             services.removeModule(address);
348         }
349 
350         public boolean clearLocalBuffer() {
351             return services.clearLocalBuffer();
352         }
353 
354         public QedeqBo loadModule(final ModuleAddress address) {
355             return services.loadModule(address);
356         }
357 
358         public boolean loadAllModulesFromQedeq() {
359             return services.loadAllModulesFromQedeq();
360         }
361 
362         public boolean loadRequiredModules(final ModuleAddress address) {
363             return services.loadRequiredModules(address);
364         }
365 
366         public ModuleAddress[] getAllLoadedModules() {
367             return services.getAllLoadedModules();
368         }
369 
370         public QedeqBo getQedeqBo(final ModuleAddress address) {
371             return services.getQedeqBo(address);
372         }
373 
374         public ModuleAddress getModuleAddress(final URL url) throws IOException {
375             return services.getModuleAddress(url);
376         }
377 
378         public ModuleAddress getModuleAddress(final String url) throws IOException {
379             return services.getModuleAddress(url);
380         }
381 
382         public ModuleAddress getModuleAddress(final File file) throws IOException {
383             return services.getModuleAddress(file);
384         }
385 
386         public String getSource(final ModuleAddress address) throws IOException {
387             return services.getSource(address);
388         }
389 
390         public boolean checkWellFormedness(final ModuleAddress address) {
391             return services.checkWellFormedness(address);
392         }
393 
394         public boolean checkFormallyProved(final ModuleAddress address) {
395             return services.checkFormallyProved(address);
396         }
397 
398         public ModuleService[] getPlugins() {
399             return services.getPlugins();
400         }
401 
402         public Object executePlugin(final String pluginName, final ModuleAddress address,
403                 final Object data) throws InterruptException {
404             return services.executePlugin(pluginName, address, data);
405         }
406 
407         public void clearAllPluginResults(final ModuleAddress address) {
408             services.clearAllPluginResults(address);
409         }
410 
411         public ServiceJob[] getServiceProcesses() {
412             return services.getServiceProcesses();
413         }
414 
415         public ServiceJob[] getRunningServiceProcesses() {
416             return services.getRunningServiceProcesses();
417         }
418 
419         public void terminateAllServiceProcesses() {
420             services.terminateAllServiceProcesses();
421         }
422 
423     };
424 
425     /** Kernel configuration. */
426     private QedeqConfig config;
427 
428     /** Initial kernel state. */
429     private KernelState currentState = initialState;
430 
431     /** For basic kernel informations. */
432     private KernelProperties basic;
433 
434     /** This object can service QEDEQ modules. */
435     private Kernel services;
436 
437     /**
438      * Constructor.
439      */
440     private KernelContext() {
441         basic = new BasicKernel();
442     }
443 
444     /**
445      * Get instance of kernel context.
446      *
447      * @return  Singleton, which is responsible for the kernel access.
448      */
449     public static final KernelContext getInstance() {
450         return INSTANCE;
451     }
452 
453     public String getBuildId() {
454         return basic.getBuildId();
455     }
456 
457     public final String getKernelVersion() {
458         return basic.getKernelVersion();
459     }
460 
461     public final String getKernelCodeName() {
462         return basic.getKernelCodeName();
463     }
464 
465     public final String getKernelVersionDirectory() {
466         return basic.getKernelVersionDirectory();
467     }
468 
469     public final String getDescriptiveKernelVersion() {
470         return basic.getDescriptiveKernelVersion();
471     }
472 
473     public final String getDedication() {
474         return basic.getDedication();
475     }
476 
477     public final String getMaximalRuleVersion() {
478         return basic.getMaximalRuleVersion();
479     }
480 
481     public final boolean isRuleVersionSupported(final String ruleVersion) {
482         return basic.isRuleVersionSupported(ruleVersion);
483     }
484 
485     public boolean isSetConnectionTimeOutSupported() {
486         return basic.isSetConnectionTimeOutSupported();
487     }
488 
489     public boolean isSetReadTimeoutSupported() {
490         return basic.isSetReadTimeoutSupported();
491     }
492 
493     public QedeqConfig getConfig() {
494         return config;
495     }
496 
497     /**
498      * Init the kernel.
499      *
500      * @param   config                  Configuration access. Must not be <code>null</code>.
501      * @param   moduleServices          Services for the kernel. Must not be <code>null</code>.
502      * @throws  IllegalStateException   Kernel is already initialized.
503      * @throws  IOException             Initialization failure.
504      */
505     public void init(final QedeqConfig config, final Kernel moduleServices) throws IOException {
506         currentState.init(config, moduleServices, basic);
507     }
508 
509     /**
510      * Startup the kernel.
511      */
512     public void startup() {
513         currentState.startup();
514     }
515 
516     /**
517      * Shutdown the kernel.
518      */
519     public void shutdown() {
520         currentState.shutdown();
521     }
522 
523     public boolean removeAllModules() {
524         return currentState.removeAllModules();
525     }
526 
527     public void removeModule(final ModuleAddress address) {
528         currentState.removeModule(address);
529     }
530 
531     public boolean clearLocalBuffer() {
532         return currentState.clearLocalBuffer();
533     }
534 
535     public QedeqBo loadModule(final ModuleAddress address) {
536         return currentState.loadModule(address);
537     }
538 
539     public boolean loadAllModulesFromQedeq() {
540         return currentState.loadAllModulesFromQedeq();
541     }
542 
543     public boolean loadRequiredModules(final ModuleAddress address) {
544         return currentState.loadRequiredModules(address);
545     }
546 
547     public ModuleAddress[] getAllLoadedModules() {
548         return currentState.getAllLoadedModules();
549     }
550 
551     public QedeqBo getQedeqBo(final ModuleAddress address) {
552         return currentState.getQedeqBo(address);
553     }
554 
555     public ModuleAddress getModuleAddress(final URL url) throws IOException {
556         return currentState.getModuleAddress(url);
557     }
558 
559     public ModuleAddress getModuleAddress(final String url) throws IOException {
560         return currentState.getModuleAddress(url);
561     }
562 
563     public ModuleAddress getModuleAddress(final File file) throws IOException {
564         return currentState.getModuleAddress(file);
565     }
566 
567     public String getSource(final ModuleAddress address) throws IOException {
568         return currentState.getSource(address);
569     }
570 
571     public boolean checkWellFormedness(final ModuleAddress address) {
572         return currentState.checkWellFormedness(address);
573     }
574 
575     public boolean checkFormallyProved(final ModuleAddress address) {
576         return currentState.checkFormallyProved(address);
577     }
578 
579     public ModuleService[] getPlugins() {
580         return currentState.getPlugins();
581     }
582 
583     public Object executePlugin(final String pluginName, final ModuleAddress address,
584             final Object data) throws InterruptException {
585         return currentState.executePlugin(pluginName, address, data);
586     }
587 
588     public void clearAllPluginResults(final ModuleAddress address) {
589         currentState.clearAllPluginResults(address);
590     }
591 
592     public ServiceJob[] getServiceProcesses() {
593         return currentState.getServiceProcesses();
594     }
595 
596     public ServiceJob[] getRunningServiceProcesses() {
597         return currentState.getRunningServiceProcesses();
598     }
599 
600     public void terminateAllServiceProcesses() {
601         currentState.terminateAllServiceProcesses();
602     }
603 
604     /**
605      * Check java version. We want to be sure that the kernel is run at least with java 1.4.2
606      *
607      * @throws  IOException     Application is running below java 1.4.2.
608      */
609     private void checkJavaVersion() throws IOException {
610         final String method = "checkJavaVersion";
611         Trace.info(CLASS, this, method, "running on java version "
612             + System.getProperty("java.version"));
613         final int[] versions = IoUtility.getJavaVersion();
614         if (versions == null) {
615             Trace.fatal(CLASS, this, method, "running java version unknown", null);
616             // we try to continue
617             return;
618         }
619         final StringBuffer version = new StringBuffer();
620         for (int i = 0; i < versions.length; i++) {
621             if (i > 0) {
622                 version.append(".");
623             }
624             version.append(versions[i]);
625         }
626         Trace.paramInfo(CLASS, this, method, "version", version);
627         // >= 1
628         if (versions.length < 1 || versions[0] < 1) {
629             throw new IOException("This application requires at least Java 1.4.2 but we got "
630                 + version);
631         }
632         if (versions[0] == 1) {         // further checking
633             // >= 1.4
634             if (versions.length < 2 || versions[1] < 4) {
635                 throw new IOException("This application requires at least Java 1.4.2 but we got "
636                     + version);
637             }
638             if (versions[1] == 4) {     // further checking
639                 // >=1.4.2
640                 if (versions.length < 3 || versions[2] < 2) {
641                     throw new IOException(
642                         "This application requires at least Java 1.4.2 but we got "
643                         + version);
644                 }
645             }
646         }
647     }
648 
649     /**
650      * Create all necessary directories for the kernel.
651      *
652      * @throws  IOException     Creation was not possible.
653      */
654     void createAllNecessaryDirectories() throws IOException {
655         // log directory
656         final File logFile = getConfig().getLogFile();
657         final File logDir = logFile.getParentFile();
658         if (!logDir.exists() &&  !logDir.mkdirs()) {
659             throw new IOException("can't create directory: " + logDir.getAbsolutePath());
660         }
661         // buffer directory
662         final File bufferDir = getConfig().getBufferDirectory();
663         if (!bufferDir.exists() &&  !bufferDir.mkdirs()) {
664             throw new IOException("can't create directory: " + bufferDir.getAbsolutePath());
665         }
666         // generation directory
667         final File generationDir = getConfig().getGenerationDirectory();
668         if (!generationDir.exists() &&  !generationDir.mkdirs()) {
669             throw new IOException("can't create directory: " + generationDir.getAbsolutePath());
670         }
671     }
672 
673     /**
674      * Checks if the application is already running. To check that we create a file in the
675      * buffer directory, open a stream and write something into it. The stream is not closed
676      * until kernel shutdown.
677      *
678      * @throws  IOException     Application is already running.
679      */
680     private void checkIfApplicationIsAlreadyRunningAndLockFile()
681             throws IOException {
682         lockFile = new File(getConfig().getBufferDirectory(), "qedeq_lock.lck");
683         FileLock fl = null;
684         try {
685             lockStream = new FileOutputStream(lockFile);
686             lockStream.write("LOCKED".getBytes("UTF8"));
687             lockStream.flush();
688             fl = lockStream.getChannel().tryLock();
689         } catch (IOException e) {
690             throw new IOException("It seems the application is already running.\n"
691                 + "At least accessing the file \"" + lockFile.getAbsolutePath() + "\" failed.");
692         }
693         if (fl == null) {
694             throw new IOException("It seems the application is already running.\n"
695                 + "At least locking the file \"" + lockFile.getAbsolutePath() + "\" failed.");
696         }
697     }
698 
699 }