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