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 basic) throws 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 basic) throws 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 url) throws IOException {
351 return services.getModuleAddress(url);
352 }
353
354 public ModuleAddress getModuleAddress(final String url) throws IOException {
355 return services.getModuleAddress(url);
356 }
357
358 public ModuleAddress getModuleAddress(final File file) throws IOException {
359 return services.getModuleAddress(file);
360 }
361
362 public String getSource(final ModuleAddress address) throws 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 moduleServices) throws 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 url) throws IOException {
526 return currentState.getModuleAddress(url);
527 }
528
529 public ModuleAddress getModuleAddress(final String url) throws IOException {
530 return currentState.getModuleAddress(url);
531 }
532
533 public ModuleAddress getModuleAddress(final File file) throws IOException {
534 return currentState.getModuleAddress(file);
535 }
536
537 public String getSource(final ModuleAddress address) throws 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 < 1 || versions[0] < 1) {
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 < 2 || versions[1] < 4) {
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 < 3 || versions[2] < 2) {
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 }
|