KernelContext.java
001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002  *
003  * Copyright 2000-2011,  Michael Meyling <mime@qedeq.org>.
004  *
005  * "Hilbert II" is free software; you can redistribute
006  * it and/or modify it under the terms of the GNU General Public
007  * License as published by the Free Software Foundation; either
008  * version 2 of the License, or (at your option) any later version.
009  *
010  * This program is distributed in the hope that it will be useful,
011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013  * GNU General Public License for more details.
014  */
015 
016 package org.qedeq.kernel.bo;
017 
018 import java.io.File;
019 import java.io.FileOutputStream;
020 import java.io.IOException;
021 import java.net.URL;
022 import java.nio.channels.FileLock;
023 
024 import org.qedeq.base.io.IoUtility;
025 import org.qedeq.base.trace.Trace;
026 import org.qedeq.base.utility.StringUtility;
027 import org.qedeq.kernel.bo.common.KernelProperties;
028 import org.qedeq.kernel.bo.common.KernelServices;
029 import org.qedeq.kernel.bo.common.KernelState;
030 import org.qedeq.kernel.bo.common.QedeqBo;
031 import org.qedeq.kernel.bo.common.ServiceModule;
032 import org.qedeq.kernel.bo.common.ServiceProcess;
033 import org.qedeq.kernel.bo.log.QedeqLog;
034 import org.qedeq.kernel.se.common.ModuleAddress;
035 import org.qedeq.kernel.se.common.Plugin;
036 import org.qedeq.kernel.se.config.QedeqConfig;
037 
038 
039 /**
040  * This class provides static access methods for the kernel.
041  *
042  @author  Michael Meyling
043  */
044 public final class KernelContext implements KernelProperties, KernelServices {
045 
046     /** Message for non started kernel. */
047     private static final String KERNEL_NOT_STARTED = "Kernel not started";
048 
049     /** Message for non initialized kernel. */
050     private static final String KERNEL_NOT_INITIALIZED = "Kernel not initialized";
051 
052     /** This class. */
053     private static final Class CLASS = KernelContext.class;
054 
055     /** One and only instance of this class. */
056     private static final KernelContext INSTANCE = new KernelContext();
057 
058     /** Lock file. */
059     private File lockFile;
060 
061     /** Lock file stream. */
062     private FileOutputStream lockStream;
063 
064     /** Initial kernel state. */
065     private final KernelState initialState = new KernelState() {
066 
067         public void init(final QedeqConfig config, final ServiceModule moduleServices, final KernelProperties basic)
068                 throws IOException {
069             KernelContext.this.config = config;
070             KernelContext.this.basic = basic;
071             Trace.setTraceOn(config.isTraceOn());
072             checkJavaVersion();
073             createAllNecessaryDirectories();
074             checkIfApplicationIsAlreadyRunningAndLockFile();
075             KernelContext.this.services = moduleServices;
076             QedeqLog.getInstance().logMessage("--------------------------------------------------"
077                  "---------------------------------------");
078             QedeqLog.getInstance().logMessage("This is "
079                 + KernelContext.getInstance().getDescriptiveKernelVersion());
080             QedeqLog.getInstance().logMessage("  see \"http://www.qedeq.org\" for more "
081                 "information");
082             QedeqLog.getInstance().logMessage("  supports rules till version "
083                 + KernelContext.getInstance().getMaximalRuleVersion());
084             QedeqLog.getInstance().logMessage("  Java version: "
085                 + StringUtility.alignRight(System.getProperty("java.version""unknown")10));
086             QedeqLog.getInstance().logMessage("  used memory:  "
087                 + StringUtility.alignRight(Runtime.getRuntime().totalMemory()
088                 - Runtime.getRuntime().freeMemory()10));
089             QedeqLog.getInstance().logMessage("  free memory:  "
090                 + StringUtility.alignRight(Runtime.getRuntime().freeMemory()10));
091             QedeqLog.getInstance().logMessage("  total memory: "
092                 + StringUtility.alignRight(Runtime.getRuntime().totalMemory()10));
093             QedeqLog.getInstance().logMessage("  max. memory:  "
094                 + StringUtility.alignRight(Runtime.getRuntime().maxMemory()10));
095             QedeqLog.getInstance().logMessage("  processors/cores: "
096                 + StringUtility.alignRight(Runtime.getRuntime().availableProcessors()6));
097             currentState = initializedState;
098         }
099 
100         public void startup() {
101             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
102         }
103 
104         public void shutdown() {
105             currentState = initialState;
106             // close stream and associated channel
107             IoUtility.close(lockStream);
108             lockStream = null;
109         }
110 
111         public void removeAllModules() {
112             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
113         }
114 
115         public void removeModule(final ModuleAddress address) {
116             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
117         }
118 
119         public boolean clearLocalBuffer() {
120             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
121         }
122 
123         public QedeqBo loadModule(final ModuleAddress address) {
124             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
125         }
126 
127         public boolean loadAllModulesFromQedeq() {
128             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
129         }
130 
131         public boolean loadRequiredModules(final ModuleAddress address) {
132             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
133         }
134 
135         public ModuleAddress[] getAllLoadedModules() {
136             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
137         }
138 
139         public QedeqBo getQedeqBo(final ModuleAddress address) {
140             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
141         }
142 
143         public ModuleAddress getModuleAddress(final URL url) {
144             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
145         }
146 
147         public ModuleAddress getModuleAddress(final String url) {
148             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
149         }
150 
151         public ModuleAddress getModuleAddress(final File file) {
152             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
153         }
154 
155         public String getSource(final ModuleAddress address) {
156             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
157         }
158 
159         public boolean checkModule(final ModuleAddress address) {
160             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
161         }
162 
163         public Plugin[] getPlugins() {
164             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
165         }
166 
167         public Object executePlugin(final String pluginName, final ModuleAddress address) {
168             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
169         }
170 
171         public void clearAllPluginResults(final ModuleAddress address) {
172             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
173         }
174 
175         public ServiceProcess[] getServiceProcesses() {
176             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
177         }
178 
179         public void stopAllPluginExecutions() {
180             throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
181         }
182 
183         public QedeqConfig getConfig() {
184             return config;
185         }
186 
187     };
188 
189     /** Initial kernel state. */
190     private final KernelState initializedState = new KernelState() {
191 
192         public void init(final QedeqConfig config, final ServiceModule moduleServices,
193                 final KernelProperties basicthrows IOException {
194             throw new IllegalStateException("Kernel is already initialized");
195         }
196 
197         public void startup() {
198             services.startupServices();
199             currentState = readyState;
200             QedeqLog.getInstance().logMessage("QEDEQ kernel opened.");
201         }
202 
203         public void shutdown() {
204             services.shutdownServices();
205             KernelContext.this.services = null;
206             initialState.shutdown();
207             QedeqLog.getInstance().logMessage("QEDEQ Kernel closed.");
208         }
209 
210         public void removeAllModules() {
211             throw new IllegalStateException(KERNEL_NOT_STARTED);
212         }
213 
214         public void removeModule(final ModuleAddress address) {
215             throw new IllegalStateException(KERNEL_NOT_STARTED);
216         }
217 
218         public boolean clearLocalBuffer() {
219             throw new IllegalStateException(KERNEL_NOT_STARTED);
220         }
221 
222         public QedeqBo loadModule(final ModuleAddress address) {
223             throw new IllegalStateException(KERNEL_NOT_STARTED);
224         }
225 
226         public boolean loadAllModulesFromQedeq() {
227             throw new IllegalStateException(KERNEL_NOT_STARTED);
228         }
229 
230         public boolean loadRequiredModules(final ModuleAddress address) {
231             throw new IllegalStateException(KERNEL_NOT_STARTED);
232         }
233 
234         public ModuleAddress[] getAllLoadedModules() {
235             throw new IllegalStateException(KERNEL_NOT_STARTED);
236         }
237 
238         public QedeqBo getQedeqBo(final ModuleAddress address) {
239             throw new IllegalStateException(KERNEL_NOT_STARTED);
240         }
241 
242         public ModuleAddress getModuleAddress(final URL url) {
243             throw new IllegalStateException(KERNEL_NOT_STARTED);
244         }
245 
246         public ModuleAddress getModuleAddress(final String url) {
247             throw new IllegalStateException(KERNEL_NOT_STARTED);
248         }
249 
250         public ModuleAddress getModuleAddress(final File file) {
251             throw new IllegalStateException(KERNEL_NOT_STARTED);
252         }
253 
254         public String getSource(final ModuleAddress address) {
255             throw new IllegalStateException(KERNEL_NOT_STARTED);
256         }
257 
258         public boolean checkModule(final ModuleAddress address) {
259             throw new IllegalStateException(KERNEL_NOT_STARTED);
260         }
261 
262         public Plugin[] getPlugins() {
263             return services.getPlugins();
264         }
265 
266         public Object executePlugin(final String pluginName, final ModuleAddress address) {
267             throw new IllegalStateException(KERNEL_NOT_STARTED);
268         }
269 
270         public void clearAllPluginResults(final ModuleAddress address) {
271             throw new IllegalStateException(KERNEL_NOT_STARTED);
272         }
273 
274         public ServiceProcess[] getServiceProcesses() {
275             throw new IllegalStateException(KERNEL_NOT_STARTED);
276         }
277 
278         public void stopAllPluginExecutions() {
279             throw new IllegalStateException(KERNEL_NOT_STARTED);
280         }
281 
282         public QedeqConfig getConfig() {
283             return config;
284         }
285 
286     };
287 
288     /** State for ready kernel. */
289     private final KernelState readyState = new KernelState() {
290 
291         public void init(final QedeqConfig config, final ServiceModule moduleServices,
292                 final KernelProperties basicthrows IOException {
293             // we are already ready
294         }
295 
296         public void startup() {
297             // we are already ready
298         }
299 
300         public void shutdown() {
301             try {
302                 final ModuleAddress[] addresses = services.getAllLoadedModules();
303                 final String[] buffer = new String[addresses.length];
304                 for (int i = 0; i < addresses.length; i++) {
305                     buffer[i= addresses[i].toString();
306                 }
307                 getConfig().setLoadedModules(buffer);
308                 getConfig().store();
309                 QedeqLog.getInstance().logMessage("Current config file successfully saved.");
310             catch (IOException e) {
311                 Trace.trace(CLASS, this, "shutdown()", e);
312                 QedeqLog.getInstance().logMessage("Saving current config file failed.");
313             }
314             initializedState.shutdown();
315         }
316 
317         public void removeAllModules() {
318             services.removeAllModules();
319         }
320 
321         public void removeModule(final ModuleAddress address) {
322             services.removeModule(address);
323         }
324 
325         public boolean clearLocalBuffer() {
326             return services.clearLocalBuffer();
327         }
328 
329         public QedeqBo loadModule(final ModuleAddress address) {
330             return services.loadModule(address);
331         }
332 
333         public boolean loadAllModulesFromQedeq() {
334             return services.loadAllModulesFromQedeq();
335         }
336 
337         public boolean loadRequiredModules(final ModuleAddress address) {
338             return services.loadRequiredModules(address);
339         }
340 
341         public ModuleAddress[] getAllLoadedModules() {
342             return services.getAllLoadedModules();
343         }
344 
345         public QedeqBo getQedeqBo(final ModuleAddress address) {
346             return services.getQedeqBo(address);
347         }
348 
349         public ModuleAddress getModuleAddress(final URL urlthrows IOException {
350             return services.getModuleAddress(url);
351         }
352 
353         public ModuleAddress getModuleAddress(final String urlthrows IOException {
354             return services.getModuleAddress(url);
355         }
356 
357         public ModuleAddress getModuleAddress(final File filethrows IOException {
358             return services.getModuleAddress(file);
359         }
360 
361         public String getSource(final ModuleAddress addressthrows IOException {
362             return services.getSource(address);
363         }
364 
365         public boolean checkModule(final ModuleAddress address) {
366             return services.checkModule(address);
367         }
368 
369         public Plugin[] getPlugins() {
370             return services.getPlugins();
371         }
372 
373         public Object executePlugin(final String pluginName, final ModuleAddress address) {
374             return services.executePlugin(pluginName, address);
375         }
376 
377         public void clearAllPluginResults(final ModuleAddress address) {
378             services.clearAllPluginResults(address);
379         }
380 
381         public ServiceProcess[] getServiceProcesses() {
382             return services.getServiceProcesses();
383         }
384 
385         public void stopAllPluginExecutions() {
386             services.stopAllPluginExecutions();
387         }
388 
389         public QedeqConfig getConfig() {
390             return config;
391         }
392 
393     };
394 
395     /** Kernel configuration. */
396     private QedeqConfig config;
397 
398     /** Initial kernel state. */
399     private KernelState currentState = initialState;
400 
401     /** For basic kernel informations. */
402     private KernelProperties basic;
403 
404     /** This object can service QEDEQ modules. */
405     private ServiceModule services;
406 
407     /**
408      * Constructor.
409      */
410     private KernelContext() {
411         basic = new BasicKernel();
412     }
413 
414     /**
415      * Get instance of kernel context.
416      *
417      @return  Singleton, which is responsible for the kernel access.
418      */
419     public static final KernelContext getInstance() {
420         return INSTANCE;
421     }
422 
423     public String getBuildId() {
424         return basic.getBuildId();
425     }
426 
427     public final String getKernelVersion() {
428         return basic.getKernelVersion();
429     }
430 
431     public final String getKernelCodeName() {
432         return basic.getKernelCodeName();
433     }
434 
435     public final String getKernelVersionDirectory() {
436         return basic.getKernelVersionDirectory();
437     }
438 
439     public final String getDescriptiveKernelVersion() {
440         return basic.getDescriptiveKernelVersion();
441     }
442 
443     public final String getDedication() {
444         return basic.getDedication();
445     }
446 
447     public final String getMaximalRuleVersion() {
448         return basic.getMaximalRuleVersion();
449     }
450 
451     public final boolean isRuleVersionSupported(final String ruleVersion) {
452         return basic.isRuleVersionSupported(ruleVersion);
453     }
454 
455     public boolean isSetConnectionTimeOutSupported() {
456         return basic.isSetConnectionTimeOutSupported();
457     }
458 
459     public boolean isSetReadTimeoutSupported() {
460         return basic.isSetReadTimeoutSupported();
461     }
462 
463     public QedeqConfig getConfig() {
464         return config;
465     }
466 
467     /**
468      * Init the kernel.
469      *
470      @param   config          Configuration access.
471      @param   moduleServices  Services for the kernel.
472      @throws  IOException     Initialization failure.
473      */
474     public void init(final QedeqConfig config, final ServiceModule moduleServicesthrows IOException {
475         currentState.init(config, moduleServices, basic);
476     }
477 
478     /**
479      * Startup the kernel.
480      */
481     public void startup() {
482         currentState.startup();
483     }
484 
485     /**
486      * Shutdown the kernel.
487      */
488     public void shutdown() {
489         currentState.shutdown();
490     }
491 
492     public void removeAllModules() {
493         currentState.removeAllModules();
494     }
495 
496     public void removeModule(final ModuleAddress address) {
497         currentState.removeModule(address);
498     }
499 
500     public boolean clearLocalBuffer() {
501         return currentState.clearLocalBuffer();
502     }
503 
504     public QedeqBo loadModule(final ModuleAddress address) {
505         return currentState.loadModule(address);
506     }
507 
508     public boolean loadAllModulesFromQedeq() {
509         return currentState.loadAllModulesFromQedeq();
510     }
511 
512     public boolean loadRequiredModules(final ModuleAddress address) {
513         return currentState.loadRequiredModules(address);
514     }
515 
516     public ModuleAddress[] getAllLoadedModules() {
517         return currentState.getAllLoadedModules();
518     }
519 
520     public QedeqBo getQedeqBo(final ModuleAddress address) {
521         return currentState.getQedeqBo(address);
522     }
523 
524     public ModuleAddress getModuleAddress(final URL urlthrows IOException {
525         return currentState.getModuleAddress(url);
526     }
527 
528     public ModuleAddress getModuleAddress(final String urlthrows IOException {
529         return currentState.getModuleAddress(url);
530     }
531 
532     public ModuleAddress getModuleAddress(final File filethrows IOException {
533         return currentState.getModuleAddress(file);
534     }
535 
536     public String getSource(final ModuleAddress addressthrows IOException {
537         return currentState.getSource(address);
538     }
539 
540     public boolean checkModule(final ModuleAddress address) {
541         return currentState.checkModule(address);
542     }
543 
544     public Plugin[] getPlugins() {
545         return currentState.getPlugins();
546     }
547 
548     public Object executePlugin(final String pluginName, final ModuleAddress address) {
549         return currentState.executePlugin(pluginName, address);
550     }
551 
552     public void clearAllPluginResults(final ModuleAddress address) {
553         currentState.clearAllPluginResults(address);
554     }
555 
556     public ServiceProcess[] getServiceProcesses() {
557         return currentState.getServiceProcesses();
558     }
559 
560     public void stopAllPluginExecutions() {
561         currentState.stopAllPluginExecutions();
562     }
563 
564     /**
565      * Check java version. We want to be shure that the kernel is run at least with java 1.4.2
566      *
567      @throws  IOException     Application is running below java 1.4.2.
568      */
569     private void checkJavaVersion() throws IOException {
570         final String method = "checkJavaVersion";
571         Trace.info(CLASS, this, method, "running on java version "
572             + System.getProperty("java.version"));
573         final int[] versions = IoUtility.getJavaVersion();
574         if (versions == null) {
575             Trace.fatal(CLASS, this, method, "running java version unknown"null);
576             // we try to continue
577             return;
578         }
579         final StringBuffer version = new StringBuffer();
580         for (int i = 0; i < versions.length; i++) {
581             if (i > 0) {
582                 version.append(".");
583             }
584             version.append(versions[i]);
585         }
586         Trace.paramInfo(CLASS, this, method, "version", version);
587         // >= 1
588         if (versions.length < || versions[01) {
589             throw new IOException("This application requires at least Java 1.4.2 but we got "
590                 + version);
591         }
592         if (versions[0== 1) {         // further checking
593             // >= 1.4
594             if (versions.length < || versions[14) {
595                 throw new IOException("This application requires at least Java 1.4.2 but we got "
596                     + version);
597             }
598             if (versions[1== 4) {     // further checking
599                 // >=1.4.2
600                 if (versions.length < || versions[22) {
601                     throw new IOException(
602                         "This application requires at least Java 1.4.2 but we got "
603                         + version);
604                 }
605             }
606         }
607     }
608 
609     /**
610      * Create all necessary directories for the kernel.
611      *
612      @throws  IOException     Creation was not possible.
613      */
614     void createAllNecessaryDirectories() throws IOException {
615         // log directory
616         final File logFile = new File(getConfig().getBasisDirectory(), getConfig().getLogFile());
617         final File logDir = logFile.getParentFile();
618         if (!logDir.exists() &&  !logDir.mkdirs()) {
619             throw new IOException("can't create directory: " + logDir.getAbsolutePath());
620         }
621         // buffer directory
622         final File bufferDir = getConfig().getBufferDirectory();
623         if (!bufferDir.exists() &&  !bufferDir.mkdirs()) {
624             throw new IOException("can't create directory: " + bufferDir.getAbsolutePath());
625         }
626         // generation directory
627         final File generationDir = getConfig().getGenerationDirectory();
628         if (!generationDir.exists() &&  !generationDir.mkdirs()) {
629             throw new IOException("can't create directory: " + generationDir.getAbsolutePath());
630         }
631     }
632 
633     /**
634      * Checks if the application is already running. To check that we create a file in the
635      * buffer directory, open a stream and write something into it. The stream is not closed
636      * until kernel shutdown.
637      *
638      @throws  IOException     Application is already running.
639      */
640     private void checkIfApplicationIsAlreadyRunningAndLockFile()
641             throws IOException {
642         lockFile = new File(getConfig().getBufferDirectory()"qedeq_lock.lck");
643         FileLock fl = null;
644         try {
645             lockStream = new FileOutputStream(lockFile);
646             lockStream.write("LOCKED".getBytes("UTF8"));
647             lockStream.flush();
648             fl = lockStream.getChannel().tryLock();
649         catch (IOException e) {
650             throw new IOException("It seems the application is already running.\n"
651                 "At least accessing the file \"" + lockFile.getAbsolutePath() "\" failed.");
652         }
653         if (fl == null) {
654             throw new IOException("It seems the application is already running.\n"
655                 "At least locking the file \"" + lockFile.getAbsolutePath() "\" failed.");
656         }
657     }
658 
659 }