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