001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002 *
003 * Copyright 2000-2014, 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.Kernel;
033 import org.qedeq.kernel.bo.common.ServiceJob;
034 import org.qedeq.kernel.bo.log.QedeqLog;
035 import org.qedeq.kernel.se.common.ModuleAddress;
036 import org.qedeq.kernel.se.common.ModuleService;
037 import org.qedeq.kernel.se.config.QedeqConfig;
038 import org.qedeq.kernel.se.visitor.InterruptException;
039
040
041 /**
042 * This class provides static access methods for the kernel.
043 *
044 * @author Michael Meyling
045 */
046 public final class KernelContext implements KernelProperties, KernelServices {
047
048 /** Message for non started kernel. */
049 private static final String KERNEL_NOT_STARTED = "Kernel not started";
050
051 /** Message for non initialized kernel. */
052 private static final String KERNEL_NOT_INITIALIZED = "Kernel not initialized";
053
054 /** This class. */
055 private static final Class CLASS = KernelContext.class;
056
057 /** One and only instance of this class. */
058 private static final KernelContext INSTANCE = new KernelContext();
059
060 /** Lock file. */
061 private File lockFile;
062
063 /** Lock file stream. */
064 private FileOutputStream lockStream;
065
066 /** Initial kernel state. */
067 private final KernelState initialState = new KernelState() {
068
069 public void init(final QedeqConfig config, final Kernel moduleServices, final KernelProperties basic)
070 throws IOException {
071 if (config == null) {
072 throw new NullPointerException("QedeqConfig is null");
073 }
074 if (moduleServices == null) {
075 throw new NullPointerException("ServiceModule is null");
076 }
077 if (basic == null) {
078 throw new NullPointerException("KernelProperties is null");
079 }
080 KernelContext.this.config = config;
081 KernelContext.this.basic = basic;
082 Trace.setTraceOn(config.isTraceOn());
083 checkJavaVersion();
084 createAllNecessaryDirectories();
085 checkIfApplicationIsAlreadyRunningAndLockFile();
086 KernelContext.this.services = moduleServices;
087 QedeqLog.getInstance().logMessage("--------------------------------------------------"
088 + "---------------------------------------");
089 QedeqLog.getInstance().logMessage("This is "
090 + KernelContext.getInstance().getDescriptiveKernelVersion());
091 QedeqLog.getInstance().logMessage(" see \"http://www.qedeq.org\" for more "
092 + "information");
093 QedeqLog.getInstance().logMessage(" supports rules till version "
094 + KernelContext.getInstance().getMaximalRuleVersion());
095 QedeqLog.getInstance().logMessage(" Java version: "
096 + StringUtility.alignRight(System.getProperty("java.version", "unknown"), 10));
097 QedeqLog.getInstance().logMessage(" used memory: "
098 + StringUtility.alignRight(Runtime.getRuntime().totalMemory()
099 - 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 }
|