org.qedeq.kernel.bo.service.control.KernelQedeqBoStorage.java Source code

Java tutorial

Introduction

Here is the source code for org.qedeq.kernel.bo.service.control.KernelQedeqBoStorage.java

Source

/* This file is part of the project "Hilbert II" - http://www.qedeq.org
 *
 * Copyright 2000-2013,  Michael Meyling <mime@qedeq.org>.
 *
 * "Hilbert II" is free software; you can redistribute
 * it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */

package org.qedeq.kernel.bo.service.control;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.qedeq.base.trace.Trace;
import org.qedeq.kernel.bo.KernelContext;
import org.qedeq.kernel.bo.common.QedeqBo;
import org.qedeq.kernel.bo.log.QedeqLog;
import org.qedeq.kernel.bo.module.InternalKernelServices;
import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
import org.qedeq.kernel.bo.module.KernelQedeqBo;
import org.qedeq.kernel.se.common.ModuleAddress;
import org.qedeq.kernel.se.state.LoadingState;

/**
 * Holds all known QEDEQ modules.
 */
class KernelQedeqBoStorage {

    /** This class. */
    private static final Class CLASS = KernelQedeqBoStorage.class;

    /** QEDEQ Modules; key: ModuleAddress, value: KernelQedeqBo. */
    private final Map bos = new HashMap();

    /**
     * Get {@link QedeqBo} for an module address. If it is unknown it will be created.
     *
     * @param   services    Internal kernel services.
     * @param   address     Module address.
     * @return  QedeqBo for module.
     */
    synchronized DefaultKernelQedeqBo getKernelQedeqBo(final InternalKernelServices services,
            final ModuleAddress address) {
        if (bos.containsKey(address)) {
            return (DefaultKernelQedeqBo) bos.get(address);
        }
        final DefaultKernelQedeqBo prop = new DefaultKernelQedeqBo(services, address);
        bos.put(address, prop);
        return prop;
    }

    /**
     * Remove all modules from memory.
     */
    synchronized void removeAllModules() {
        final String method = "removeAllModules()";
        Trace.begin(CLASS, this, method);
        try {
            for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext();) {
                Map.Entry entry = (Map.Entry) iterator.next();
                final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBo) entry.getValue();
                prop.delete();
            }
            bos.clear();
        } catch (RuntimeException e) {
            Trace.trace(CLASS, this, method, e);
        } finally {
            Trace.end(CLASS, this, method);
        }
    }

    /**
     * Validate module dependencies and throw Error if they are not correct.
     */
    synchronized void validateDependencies() {
        final String method = "validateDependencies";
        String url = StringUtils.EMPTY;
        String text = StringUtils.EMPTY;
        boolean error = false;
        Trace.begin(CLASS, this, method);
        // for debugging: print dependency tree:
        //        for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext(); ) {
        //            Map.Entry entry = (Map.Entry) iterator.next();
        //            final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBo) entry.getValue();
        //            prop.getStateManager().printDependencyTree();
        //        }
        for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext();) {
            Map.Entry entry = (Map.Entry) iterator.next();
            final DefaultKernelQedeqBo prop = (DefaultKernelQedeqBo) entry.getValue();
            Trace.param(CLASS, this, method, "prop", prop);
            if (!prop.hasLoadedRequiredModules()) {
                continue;
            }

            // prop must be in dependent list for all required modules
            final KernelModuleReferenceList refs = prop.getKernelRequiredModules();
            for (int i = 0; i < refs.size(); i++) {
                final DefaultKernelQedeqBo ref = (DefaultKernelQedeqBo) refs.getKernelQedeqBo(i);
                final KernelModuleReferenceList dependents = ref.getDependentModules();
                if (!dependents.contains(prop)) {
                    Trace.fatal(CLASS, this, method, ref.getUrl() + " missing dependent module: " + prop.getUrl(),
                            null);
                    if (!error) {
                        url = ref.getUrl();
                        text = "missing dependent module " + prop.getUrl();
                    }
                    error = true;
                }
            }

            // for all dependent modules, prop must be in required list
            final KernelModuleReferenceList dependents = prop.getDependentModules();
            for (int i = 0; i < dependents.size(); i++) {
                final DefaultKernelQedeqBo dependent = (DefaultKernelQedeqBo) dependents.getKernelQedeqBo(i);
                final KernelModuleReferenceList refs2 = dependent.getKernelRequiredModules();
                if (!refs2.contains(prop)) {
                    Trace.fatal(CLASS, this, method,
                            dependent.getUrl() + " missing required module: " + prop.getUrl(), null);
                    if (!error) {
                        url = prop.getUrl();
                        text = "missing required module " + prop.getUrl();
                    }
                    error = true;
                }
            }
        }
        Trace.end(CLASS, this, method);

        // if the dependencies are not ok we throw an error!
        if (error) {
            Error e = new Error("QEDEQ dependencies and status are flawed! "
                    + "This is a major error! We do a kernel shutdown!");
            Trace.fatal(CLASS, this, method, "Shutdown because of major validation error", e);
            QedeqLog.getInstance().logFailureReply(e.getMessage(), url, text);
            KernelContext.getInstance().shutdown();
            throw e;
        }
    }

    /**
     * Remove a QEDEQ module from memory.
     *
     * @param   prop    Defines the module.
     */
    synchronized void removeModule(final KernelQedeqBo prop) {
        final String method = "removeModule(KernelQedeqBo)";
        Trace.begin(CLASS, this, method);
        try {
            Trace.trace(CLASS, this, method, "removing " + prop.getUrl());
            bos.remove(prop.getModuleAddress());
        } catch (RuntimeException e) {
            Trace.fatal(CLASS, this, method, "unexpected runtime exception", e);
            throw e;
        } finally {
            Trace.end(CLASS, this, method);
        }
    }

    /**
     * Get list of all successfully loaded modules.
     *
     * @return  list of all successfully loaded modules.
     */
    synchronized ModuleAddress[] getAllLoadedModules() {
        final String method = "getAllModules()";
        Trace.begin(CLASS, this, method);
        try {
            final List list = new ArrayList();
            for (final Iterator iterator = bos.entrySet().iterator(); iterator.hasNext();) {
                Map.Entry entry = (Map.Entry) iterator.next();
                final QedeqBo prop = (QedeqBo) entry.getValue();
                if (prop.getLoadingState().getCode() >= LoadingState.STATE_LOADED.getCode()) {
                    list.add(prop.getModuleAddress());
                }
            }
            return (ModuleAddress[]) list.toArray(new ModuleAddress[list.size()]);
        } finally {
            Trace.end(CLASS, this, method);
        }
    }

}