KernelQedeqBoStorage.java
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 (DefaultKernelQedeqBobos.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.Entryiterator.next();
074                 final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBoentry.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.Entryiterator.next();
094             final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBoentry.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                     (KernelModuleReferenceListYodaUtility.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 = (KernelModuleReferenceListYodaUtility.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.Entryiterator.next();
179                 final QedeqBo prop = (QedeqBoentry.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 }