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