1 | /* This file is part of the project "Hilbert II" - http://www.qedeq.org |
2 | * |
3 | * Copyright 2000-2014, Michael Meyling <mime@qedeq.org>. |
4 | * |
5 | * "Hilbert II" is free software; you can redistribute |
6 | * it and/or modify it under the terms of the GNU General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | */ |
15 | |
16 | package org.qedeq.kernel.bo.service.internal; |
17 | |
18 | import java.util.ArrayList; |
19 | import java.util.HashMap; |
20 | import java.util.Iterator; |
21 | import java.util.List; |
22 | import java.util.Map; |
23 | |
24 | import org.apache.commons.lang.StringUtils; |
25 | import org.qedeq.base.trace.Trace; |
26 | import org.qedeq.kernel.bo.KernelContext; |
27 | import org.qedeq.kernel.bo.common.QedeqBo; |
28 | import org.qedeq.kernel.bo.log.QedeqLog; |
29 | import org.qedeq.kernel.bo.module.InternalKernelServices; |
30 | import org.qedeq.kernel.bo.module.KernelModuleReferenceList; |
31 | import org.qedeq.kernel.bo.module.KernelQedeqBo; |
32 | import org.qedeq.kernel.se.common.ModuleAddress; |
33 | import org.qedeq.kernel.se.state.LoadingState; |
34 | |
35 | /** |
36 | * Holds all known QEDEQ modules. Doesn't now anything about locking. |
37 | */ |
38 | class KernelQedeqBoStorage { |
39 | |
40 | /** This class. */ |
41 | private static final Class CLASS = KernelQedeqBoStorage.class; |
42 | |
43 | /** QEDEQ Modules; key: ModuleAddress, value: KernelQedeqBo. */ |
44 | private final Map bos = new HashMap(); |
45 | |
46 | |
47 | /** |
48 | * Get {@link DefaultKernelQedeqBo} for an module address. If it is unknown it will be created. |
49 | * |
50 | * @param services Internal kernel services. |
51 | * @param address Module address. |
52 | * @return QedeqBo for module. |
53 | */ |
54 | synchronized DefaultKernelQedeqBo getKernelQedeqBo(final InternalKernelServices services, |
55 | final ModuleAddress address) { |
56 | if (bos.containsKey(address)) { |
57 | return (DefaultKernelQedeqBo) bos.get(address); |
58 | } |
59 | final DefaultKernelQedeqBo prop = new DefaultKernelQedeqBo(services, address); |
60 | bos.put(address, prop); |
61 | return prop; |
62 | } |
63 | |
64 | /** |
65 | * Remove all modules from memory. |
66 | */ |
67 | synchronized void removeAllModules() { |
68 | final String method = "removeAllModules()"; |
69 | Trace.begin(CLASS, this, method); |
70 | try { |
71 | for (final Iterator iterator |
72 | = bos.entrySet().iterator(); |
73 | iterator.hasNext(); ) { |
74 | Map.Entry entry = (Map.Entry) iterator.next(); |
75 | final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBo) entry.getValue(); |
76 | prop.delete(); |
77 | } |
78 | bos.clear(); |
79 | } catch (RuntimeException e) { |
80 | Trace.trace(CLASS, this, method, e); |
81 | } finally { |
82 | Trace.end(CLASS, this, method); |
83 | } |
84 | } |
85 | |
86 | /** |
87 | * Validate module dependencies and throw Error if they are not correct. |
88 | */ |
89 | synchronized void validateDependencies() { |
90 | final String method = "validateDependencies"; |
91 | String url = StringUtils.EMPTY; |
92 | String text = StringUtils.EMPTY; |
93 | boolean error = false; |
94 | Trace.begin(CLASS, this, method); |
95 | // for debugging: print dependency tree: |
96 | // for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext(); ) { |
97 | // Map.Entry entry = (Map.Entry) iterator.next(); |
98 | // final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBo) entry.getValue(); |
99 | // 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 | } |