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.service;
017
018 import java.util.ArrayList;
019 import java.util.HashMap;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.Map;
023
024 import org.qedeq.base.trace.Trace;
025 import org.qedeq.base.utility.YodaUtility;
026 import org.qedeq.kernel.bo.common.QedeqBo;
027 import org.qedeq.kernel.bo.module.InternalKernelServices;
028 import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
029 import org.qedeq.kernel.bo.module.KernelQedeqBo;
030 import org.qedeq.kernel.se.common.LoadingState;
031 import org.qedeq.kernel.se.common.ModuleAddress;
032
033 /**
034 * Holds all known QEDEQ modules.
035 */
036 class KernelQedeqBoStorage {
037
038 /** This class. */
039 private static final Class CLASS = KernelQedeqBoStorage.class;
040
041 /** QEDEQ Modules; key: ModuleAddress, value: KernelQedeqBo. */
042 private final Map bos = new HashMap();
043
044
045 /**
046 * Get {@link QedeqBo} for an module address. If it is unknown it will be created.
047 *
048 * @param services Internal kernel services.
049 * @param address Module address.
050 * @return QedeqBo for module.
051 */
052 synchronized DefaultKernelQedeqBo getKernelQedeqBo(final InternalKernelServices services,
053 final ModuleAddress address) {
054 if (bos.containsKey(address)) {
055 return (DefaultKernelQedeqBo) bos.get(address);
056 } else {
057 final DefaultKernelQedeqBo prop = new DefaultKernelQedeqBo(services, address);
058 bos.put(address, prop);
059 return prop;
060 }
061 }
062
063 /**
064 * Remove all modules from memory.
065 */
066 synchronized void removeAllModules() {
067 final String method = "removeAllModules()";
068 Trace.begin(CLASS, this, method);
069 try {
070 for (final Iterator iterator
071 = bos.entrySet().iterator();
072 iterator.hasNext(); ) {
073 Map.Entry entry = (Map.Entry) iterator.next();
074 final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBo) entry.getValue();
075 prop.delete();
076 }
077 bos.clear();
078 } catch (RuntimeException e) {
079 Trace.trace(CLASS, this, method, e);
080 } finally {
081 Trace.end(CLASS, this, method);
082 }
083 }
084
085 /**
086 * Validate module dependencies and throw Error if they are not correct.
087 */
088 synchronized void validateDependencies() {
089 final String method = "validateDependencies";
090 boolean error = false;
091 Trace.begin(CLASS, this, method);
092 for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext(); ) {
093 Map.Entry entry = (Map.Entry) iterator.next();
094 final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBo) entry.getValue();
095 Trace.param(CLASS, this, method, "prop", prop);
096 if (!prop.hasLoadedRequiredModules()) {
097 continue;
098 }
099
100 // prop must be in dependent list for all required modules
101 final KernelModuleReferenceList refs = prop.getKernelRequiredModules();
102 for (int i = 0; i < refs.size(); i++) {
103 final KernelQedeqBo ref = refs.getKernelQedeqBo(i);
104 KernelModuleReferenceList dependents;
105 // FIXME 20110811 m31: this is too dirty!
106 try {
107 dependents
108 = (KernelModuleReferenceList) YodaUtility.getFieldValue(ref, "dependent");
109 } catch (NoSuchFieldException e) {
110 throw new RuntimeException(e);
111 }
112 if (!dependents.contains(prop)) { // TODO mime 20080325: Q & D
113 Trace.fatal(CLASS, this, method, ref.getUrl() + " missing dependent module: "
114 + prop.getUrl(), null);
115 error = true;
116 }
117 }
118
119 // for all dependent modules, prop must be in required list
120 final KernelModuleReferenceList dependents = prop.getDependentModules();
121 for (int i = 0; i < dependents.size(); i++) {
122 final KernelQedeqBo dependent = dependents.getKernelQedeqBo(i);
123 KernelModuleReferenceList refs2;
124 try {
125 // FIXME 20110811 m31: this is too dirty!
126 refs2 = (KernelModuleReferenceList) YodaUtility.getFieldValue(
127 dependent, "required");
128 } catch (NoSuchFieldException e) {
129 throw new RuntimeException(e);
130 }
131 if (!refs2.contains(prop)) { // TODO mime 20080325: Q & D
132 Trace.fatal(CLASS, this, method, dependent.getUrl()
133 + " missing required module: " + prop.getUrl(), null);
134 error = true;
135 }
136 }
137 }
138 Trace.end(CLASS, this, method);
139
140 // if the dependencies are not ok we throw an error!
141 if (error) {
142 Error e = new Error("QEDEQ dependencies and status are flawed! This is a major error!");
143 Trace.fatal(CLASS, this, method, "Shutdown because of major validation error", e);
144 throw e;
145 }
146 }
147
148 /**
149 * Remove a QEDEQ module from memory.
150 *
151 * @param prop Defines the module.
152 */
153 synchronized void removeModule(final KernelQedeqBo prop) {
154 final String method = "removeModule(KernelQedeqBo)";
155 Trace.begin(CLASS, this, method);
156 try {
157 Trace.trace(CLASS, this, method, "removing " + prop.getUrl());
158 bos.remove(prop.getModuleAddress());
159 } catch (RuntimeException e) {
160 Trace.fatal(CLASS, this, method, "unexpected runtime exception", e);
161 throw e;
162 } finally {
163 Trace.end(CLASS, this, method);
164 }
165 }
166
167 /**
168 * Get list of all successfully loaded modules.
169 *
170 * @return list of all successfully loaded modules.
171 */
172 synchronized ModuleAddress[] getAllLoadedModules() {
173 final String method = "getAllModules()";
174 Trace.begin(CLASS, this, method);
175 try {
176 final List list = new ArrayList();
177 for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext(); ) {
178 Map.Entry entry = (Map.Entry) iterator.next();
179 final QedeqBo prop = (QedeqBo) entry.getValue();
180 if (prop.getLoadingState().getCode() >= LoadingState.STATE_LOADED.getCode()) {
181 list.add(prop.getModuleAddress());
182 }
183 }
184 return (ModuleAddress[]) list.toArray(new ModuleAddress[list.size()]);
185 } finally {
186 Trace.end(CLASS, this, method);
187 }
188 }
189
190 /**
191 * Get number of QEDEQ modules in STATE_LOADED.
192 *
193 * @return Number of loaded modules.
194 */
195 synchronized int getNumberOfLoadedModules() {
196 return getAllLoadedModules().length;
197 }
198
199 }
|