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 checkWellFormedness(final ModuleAddress address) {
161 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
162 }
163
164 public boolean checkFormallyProved(final ModuleAddress address) {
165 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
166 }
167
168 public Plugin[] getPlugins() {
169 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
170 }
171
172 public Object executePlugin(final String pluginName, final ModuleAddress address,
173 final Object data) {
174 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
175 }
176
177 public void clearAllPluginResults(final ModuleAddress address) {
178 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
179 }
180
181 public ServiceProcess[] getServiceProcesses() {
182 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
183 }
184
185 public ServiceProcess[] getRunningServiceProcesses() {
186 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
187 }
188
189 public void stopAllPluginExecutions() {
190 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
191 }
192
193 };
194
195 /** Initial kernel state. */
196 private final KernelState initializedState = new KernelState() {
197
198 public void init(final QedeqConfig config, final ServiceModule moduleServices,
199 final KernelProperties basic) throws IOException {
200 throw new IllegalStateException("Kernel is already initialized");
201 }
202
203 public void startup() {
204 services.startupServices();
205 currentState = readyState;
206 QedeqLog.getInstance().logMessage("QEDEQ kernel opened.");
207 }
208
209 public void shutdown() {
210 services.shutdownServices();
211 KernelContext.this.services = null;
212 initialState.shutdown();
213 QedeqLog.getInstance().logMessage("QEDEQ Kernel closed.");
214 }
215
216 public void removeAllModules() {
217 throw new IllegalStateException(KERNEL_NOT_STARTED);
218 }
219
220 public void removeModule(final ModuleAddress address) {
221 throw new IllegalStateException(KERNEL_NOT_STARTED);
222 }
223
224 public boolean clearLocalBuffer() {
225 throw new IllegalStateException(KERNEL_NOT_STARTED);
226 }
227
228 public QedeqBo loadModule(final ModuleAddress address) {
229 throw new IllegalStateException(KERNEL_NOT_STARTED);
230 }
231
232 public boolean loadAllModulesFromQedeq() {
233 throw new IllegalStateException(KERNEL_NOT_STARTED);
234 }
235
236 public boolean loadRequiredModules(final ModuleAddress address) {
237 throw new IllegalStateException(KERNEL_NOT_STARTED);
238 }
239
240 public ModuleAddress[] getAllLoadedModules() {
241 throw new IllegalStateException(KERNEL_NOT_STARTED);
242 }
243
244 public QedeqBo getQedeqBo(final ModuleAddress address) {
245 throw new IllegalStateException(KERNEL_NOT_STARTED);
246 }
247
248 public ModuleAddress getModuleAddress(final URL url) {
249 throw new IllegalStateException(KERNEL_NOT_STARTED);
250 }
251
252 public ModuleAddress getModuleAddress(final String url) {
253 throw new IllegalStateException(KERNEL_NOT_STARTED);
254 }
255
256 public ModuleAddress getModuleAddress(final File file) {
257 throw new IllegalStateException(KERNEL_NOT_STARTED);
258 }
259
260 public String getSource(final ModuleAddress address) {
261 throw new IllegalStateException(KERNEL_NOT_STARTED);
262 }
263
264 public boolean checkWellFormedness(final ModuleAddress address) {
265 throw new IllegalStateException(KERNEL_NOT_STARTED);
266 }
267
268 public boolean checkFormallyProved(final ModuleAddress address) {
269 throw new IllegalStateException(KERNEL_NOT_INITIALIZED);
270 }
271
272 public Plugin[] getPlugins() {
273 return services.getPlugins();
274 }
275
276 public Object executePlugin(final String pluginName, final ModuleAddress address,
277 final Object data) {
278 throw new IllegalStateException(KERNEL_NOT_STARTED);
279 }
280
281 public void clearAllPluginResults(final ModuleAddress address) {
282 throw new IllegalStateException(KERNEL_NOT_STARTED);
283 }
284
285 public ServiceProcess[] getServiceProcesses() {
286 throw new IllegalStateException(KERNEL_NOT_STARTED);
287 }
288
289 public ServiceProcess[] getRunningServiceProcesses() {
290 throw new IllegalStateException(KERNEL_NOT_STARTED);
291 }
292
293 public void stopAllPluginExecutions() {
294 throw new IllegalStateException(KERNEL_NOT_STARTED);
295 }
296
297 };
298
299 /** State for ready kernel. */
300 private final KernelState readyState = new KernelState() {
301
302 public void init(final QedeqConfig config, final ServiceModule moduleServices,
303 final KernelProperties basic) throws IOException {
304 // we are already ready
305 }
306
307 public void startup() {
308 // we are already ready
309 }
310
311 public void shutdown() {
312 try {
313 final ModuleAddress[] addresses = services.getAllLoadedModules();
314 final String[] buffer = new String[addresses.length];
315 for (int i = 0; i < addresses.length; i++) {
316 buffer[i] = addresses[i].toString();
317 }
318 getConfig().setPreviouslyLoadedModules(buffer);
319 getConfig().store();
320 QedeqLog.getInstance().logMessage("Current config file successfully saved.");
321 } catch (IOException e) {
322 Trace.trace(CLASS, this, "shutdown()", e);
323 QedeqLog.getInstance().logMessage("Saving current config file failed.");
324 }
325 initializedState.shutdown();
326 }
327
328 public void removeAllModules() {
329 services.removeAllModules();
330 }
331
332 public void removeModule(final ModuleAddress address) {
333 services.removeModule(address);
334 }
335
336 public boolean clearLocalBuffer() {
337 return services.clearLocalBuffer();
338 }
339
340 public QedeqBo loadModule(final ModuleAddress address) {
341 return services.loadModule(address);
342 }
343
344 public boolean loadAllModulesFromQedeq() {
345 return services.loadAllModulesFromQedeq();
346 }
347
348 public boolean loadRequiredModules(final ModuleAddress address) {
349 return services.loadRequiredModules(address);
350 }
351
352 public ModuleAddress[] getAllLoadedModules() {
353 return services.getAllLoadedModules();
354 }
355
356 public QedeqBo getQedeqBo(final ModuleAddress address) {
357 return services.getQedeqBo(address);
358 }
359
360 public ModuleAddress getModuleAddress(final URL url) throws IOException {
361 return services.getModuleAddress(url);
362 }
363
364 public ModuleAddress getModuleAddress(final String url) throws IOException {
365 return services.getModuleAddress(url);
366 }
367
368 public ModuleAddress getModuleAddress(final File file) throws IOException {
369 return services.getModuleAddress(file);
370 }
371
372 public String getSource(final ModuleAddress address) throws IOException {
373 return services.getSource(address);
374 }
375
376 public boolean checkWellFormedness(final ModuleAddress address) {
377 return services.checkWellFormedness(address);
378 }
379
380 public boolean checkFormallyProved(final ModuleAddress address) {
381 return services.checkFormallyProved(address);
382 }
383
384 public Plugin[] getPlugins() {
385 return services.getPlugins();
386 }
387
388 public Object executePlugin(final String pluginName, final ModuleAddress address,
389 final Object data) {
390 return services.executePlugin(pluginName, address, data);
391 }
392
393 public void clearAllPluginResults(final ModuleAddress address) {
394 services.clearAllPluginResults(address);
395 }
396
397 public ServiceProcess[] getServiceProcesses() {
398 return services.getServiceProcesses();
399 }
400
401 public ServiceProcess[] getRunningServiceProcesses() {
402 return services.getRunningServiceProcesses();
403 }
404
405 public void stopAllPluginExecutions() {
406 services.stopAllPluginExecutions();
407 }
408
409 };
410
411 /** Kernel configuration. */
412 private QedeqConfig config;
413
414 /** Initial kernel state. */
415 private KernelState currentState = initialState;
416
417 /** For basic kernel informations. */
418 private KernelProperties basic;
419
420 /** This object can service QEDEQ modules. */
421 private ServiceModule services;
422
423 /**
424 * Constructor.
425 */
426 private KernelContext() {
427 basic = new BasicKernel();
428 }
429
430 /**
431 * Get instance of kernel context.
432 *
433 * @return Singleton, which is responsible for the kernel access.
434 */
435 public static final KernelContext getInstance() {
436 return INSTANCE;
437 }
438
439 public String getBuildId() {
440 return basic.getBuildId();
441 }
442
443 public final String getKernelVersion() {
444 return basic.getKernelVersion();
445 }
446
447 public final String getKernelCodeName() {
448 return basic.getKernelCodeName();
449 }
450
451 public final String getKernelVersionDirectory() {
452 return basic.getKernelVersionDirectory();
453 }
454
455 public final String getDescriptiveKernelVersion() {
456 return basic.getDescriptiveKernelVersion();
457 }
458
459 public final String getDedication() {
460 return basic.getDedication();
461 }
462
463 public final String getMaximalRuleVersion() {
464 return basic.getMaximalRuleVersion();
465 }
466
467 public final boolean isRuleVersionSupported(final String ruleVersion) {
468 return basic.isRuleVersionSupported(ruleVersion);
469 }
470
471 public boolean isSetConnectionTimeOutSupported() {
472 return basic.isSetConnectionTimeOutSupported();
473 }
474
475 public boolean isSetReadTimeoutSupported() {
476 return basic.isSetReadTimeoutSupported();
477 }
478
479 public QedeqConfig getConfig() {
480 return config;
481 }
482
483 /**
484 * Init the kernel.
485 *
486 * @param config Configuration access.
487 * @param moduleServices Services for the kernel.
488 * @throws IOException Initialization failure.
489 */
490 public void init(final QedeqConfig config, final ServiceModule moduleServices) throws IOException {
491 currentState.init(config, moduleServices, basic);
492 }
493
494 /**
495 * Startup the kernel.
496 */
497 public void startup() {
498 currentState.startup();
499 }
500
501 /**
502 * Shutdown the kernel.
503 */
504 public void shutdown() {
505 currentState.shutdown();
506 }
507
508 public void removeAllModules() {
509 currentState.removeAllModules();
510 }
511
512 public void removeModule(final ModuleAddress address) {
513 currentState.removeModule(address);
514 }
515
516 public boolean clearLocalBuffer() {
517 return currentState.clearLocalBuffer();
518 }
519
520 public QedeqBo loadModule(final ModuleAddress address) {
521 return currentState.loadModule(address);
522 }
523
524 public boolean loadAllModulesFromQedeq() {
525 return currentState.loadAllModulesFromQedeq();
526 }
527
528 public boolean loadRequiredModules(final ModuleAddress address) {
529 return currentState.loadRequiredModules(address);
530 }
531
532 public ModuleAddress[] getAllLoadedModules() {
533 return currentState.getAllLoadedModules();
534 }
535
536 public QedeqBo getQedeqBo(final ModuleAddress address) {
537 return currentState.getQedeqBo(address);
538 }
539
540 public ModuleAddress getModuleAddress(final URL url) throws IOException {
541 return currentState.getModuleAddress(url);
542 }
543
544 public ModuleAddress getModuleAddress(final String url) throws IOException {
545 return currentState.getModuleAddress(url);
546 }
547
548 public ModuleAddress getModuleAddress(final File file) throws IOException {
549 return currentState.getModuleAddress(file);
550 }
551
552 public String getSource(final ModuleAddress address) throws IOException {
553 return currentState.getSource(address);
554 }
555
556 public boolean checkWellFormedness(final ModuleAddress address) {
557 return currentState.checkWellFormedness(address);
558 }
559
560 public boolean checkFormallyProved(final ModuleAddress address) {
561 return currentState.checkFormallyProved(address);
562 }
563
564 public Plugin[] getPlugins() {
565 return currentState.getPlugins();
566 }
567
568 public Object executePlugin(final String pluginName, final ModuleAddress address,
569 final Object data) {
570 return currentState.executePlugin(pluginName, address, data);
571 }
572
573 public void clearAllPluginResults(final ModuleAddress address) {
574 currentState.clearAllPluginResults(address);
575 }
576
577 public ServiceProcess[] getServiceProcesses() {
578 return currentState.getServiceProcesses();
579 }
580
581 public ServiceProcess[] getRunningServiceProcesses() {
582 return currentState.getRunningServiceProcesses();
583 }
584
585 public void stopAllPluginExecutions() {
586 currentState.stopAllPluginExecutions();
587 }
588
589 /**
590 * Check java version. We want to be sure that the kernel is run at least with java 1.4.2
591 *
592 * @throws IOException Application is running below java 1.4.2.
593 */
594 private void checkJavaVersion() throws IOException {
595 final String method = "checkJavaVersion";
596 Trace.info(CLASS, this, method, "running on java version "
597 + System.getProperty("java.version"));
598 final int[] versions = IoUtility.getJavaVersion();
599 if (versions == null) {
600 Trace.fatal(CLASS, this, method, "running java version unknown", null);
601 // we try to continue
602 return;
603 }
604 final StringBuffer version = new StringBuffer();
605 for (int i = 0; i < versions.length; i++) {
606 if (i > 0) {
607 version.append(".");
608 }
609 version.append(versions[i]);
610 }
611 Trace.paramInfo(CLASS, this, method, "version", version);
612 // >= 1
613 if (versions.length < 1 || versions[0] < 1) {
614 throw new IOException("This application requires at least Java 1.4.2 but we got "
615 + version);
616 }
617 if (versions[0] == 1) { // further checking
618 // >= 1.4
619 if (versions.length < 2 || versions[1] < 4) {
620 throw new IOException("This application requires at least Java 1.4.2 but we got "
621 + version);
622 }
623 if (versions[1] == 4) { // further checking
624 // >=1.4.2
625 if (versions.length < 3 || versions[2] < 2) {
626 throw new IOException(
627 "This application requires at least Java 1.4.2 but we got "
628 + version);
629 }
630 }
631 }
632 }
633
634 /**
635 * Create all necessary directories for the kernel.
636 *
637 * @throws IOException Creation was not possible.
638 */
639 void createAllNecessaryDirectories() throws IOException {
640 // log directory
641 final File logFile = getConfig().getLogFile();
642 final File logDir = logFile.getParentFile();
643 if (!logDir.exists() && !logDir.mkdirs()) {
644 throw new IOException("can't create directory: " + logDir.getAbsolutePath());
645 }
646 // buffer directory
647 final File bufferDir = getConfig().getBufferDirectory();
648 if (!bufferDir.exists() && !bufferDir.mkdirs()) {
649 throw new IOException("can't create directory: " + bufferDir.getAbsolutePath());
650 }
651 // generation directory
652 final File generationDir = getConfig().getGenerationDirectory();
653 if (!generationDir.exists() && !generationDir.mkdirs()) {
654 throw new IOException("can't create directory: " + generationDir.getAbsolutePath());
655 }
656 }
657
658 /**
659 * Checks if the application is already running. To check that we create a file in the
660 * buffer directory, open a stream and write something into it. The stream is not closed
661 * until kernel shutdown.
662 *
663 * @throws IOException Application is already running.
664 */
665 private void checkIfApplicationIsAlreadyRunningAndLockFile()
666 throws IOException {
667 lockFile = new File(getConfig().getBufferDirectory(), "qedeq_lock.lck");
668 FileLock fl = null;
669 try {
670 lockStream = new FileOutputStream(lockFile);
671 lockStream.write("LOCKED".getBytes("UTF8"));
672 lockStream.flush();
673 fl = lockStream.getChannel().tryLock();
674 } catch (IOException e) {
675 throw new IOException("It seems the application is already running.\n"
676 + "At least accessing the file \"" + lockFile.getAbsolutePath() + "\" failed.");
677 }
678 if (fl == null) {
679 throw new IOException("It seems the application is already running.\n"
680 + "At least locking the file \"" + lockFile.getAbsolutePath() + "\" failed.");
681 }
682 }
683
684 }
|