001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002 *
003 * Copyright 2000-2011, 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.HashMap;
019 import java.util.Map;
020
021 import org.qedeq.base.trace.Trace;
022 import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
023 import org.qedeq.kernel.se.common.DefaultSourceFileExceptionList;
024 import org.qedeq.kernel.se.common.DependencyState;
025 import org.qedeq.kernel.se.common.ModuleDataException;
026 import org.qedeq.kernel.se.common.Plugin;
027 import org.qedeq.kernel.se.common.SourceFileException;
028 import org.qedeq.kernel.se.common.SourceFileExceptionList;
029
030
031 /**
032 * Load all required QEDEQ modules.
033 *
034 * @author Michael Meyling
035 */
036 public final class LoadRequiredModules {
037
038 /** This class. */
039 private static final Class CLASS = LoadRequiredModules.class;
040
041 /** All QedeqBos currently in state "loading required modules". */
042 private final Map loadingRequiredInProgress = new HashMap();
043
044 /**
045 * Don't use this constructor.
046 */
047 private LoadRequiredModules() {
048 // nothing to do
049 }
050
051 /**
052 * Load all required QEDEQ modules for a given QEDEQ module.
053 *
054 * @param plugin We work for this plugin.
055 * @param prop QEDEQ module BO. This module must be loaded.
056 * @return Loading successful.
057 * @throws IllegalArgumentException BO is not loaded
058 */
059 public static boolean loadRequired(final Plugin plugin, final DefaultKernelQedeqBo prop) {
060 // did we check this already?
061 if (prop.getDependencyState().areAllRequiredLoaded()) {
062 return true; // everything is OK
063 }
064 return (new LoadRequiredModules()).loadAllRequired(plugin, prop);
065 }
066
067 /**
068 * Load all required QEDEQ modules for a given QEDEQ module.
069 *
070 * @param plugin We work for this plugin.
071 * @param prop QEDEQ module BO. This module must be loaded.
072 * @return Loading successful.
073 * @throws IllegalArgumentException BO is not loaded
074 */
075 private boolean loadAllRequired(final Plugin plugin, final DefaultKernelQedeqBo prop) {
076 final String method = "loadRequired(DefaultQedeqBo)";
077 Trace.param(CLASS, this, method, "prop.getModuleAddress", prop.getModuleAddress());
078 synchronized (prop) {
079 if (prop.getDependencyState().areAllRequiredLoaded()) {
080 return true; // everything is OK
081 }
082 if (!prop.isLoaded()) {
083 throw new IllegalArgumentException("Programming error BO must be loaded!");
084 }
085 if (loadingRequiredInProgress.containsKey(prop)) { // already checked?
086 throw new IllegalStateException("Programming error: must not be marked!");
087 }
088 prop.setDependencyProgressState(DependencyState.STATE_LOADING_REQUIRED_MODULES);
089 loadingRequiredInProgress.put(prop, prop);
090
091 }
092 SourceFileExceptionList sfl = null;
093 final LoadDirectlyRequiredModules loader = new LoadDirectlyRequiredModules(plugin, prop);
094 KernelModuleReferenceList required = null;
095 try {
096 required = loader.load();
097 sfl = loader.getErrorList();
098 } catch (SourceFileExceptionList e) {
099 sfl = e;
100 }
101 if (sfl == null || sfl.size() == 0) {
102 for (int i = 0; i < required.size(); i++) {
103 Trace.trace(CLASS, this, method, "loading required modules of " + prop.getUrl());
104 DefaultKernelQedeqBo current = null;
105 current = (DefaultKernelQedeqBo) required.getKernelQedeqBo(i);
106 if (loadingRequiredInProgress.containsKey(current)) {
107 ModuleDataException me = new LoadRequiredModuleException(
108 ServiceErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_CODE,
109 ServiceErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_TEXT + "\""
110 + required.getLabel(i) + "\"",
111 required.getModuleContext(i));
112 final SourceFileException sf = prop.createSourceFileException(plugin, me);
113 if (sfl == null) {
114 sfl = new DefaultSourceFileExceptionList(sf);
115 } else {
116 sfl.add(sf);
117 }
118 continue;
119 }
120 if (!loadAllRequired(plugin, current)) {
121 // LATER 20110119 m31: we take only the first error, is that ok?
122 ModuleDataException me = new LoadRequiredModuleException(
123 ServiceErrors.IMPORT_OF_MODULE_FAILED_CODE,
124 ServiceErrors.IMPORT_OF_MODULE_FAILED_TEXT + "\"" + required.getLabel(i)
125 + "\", " + current.getErrors().get(0).getMessage(),
126 required.getModuleContext(i));
127 final SourceFileException sf = prop.createSourceFileException(plugin, me);
128 if (sfl == null) {
129 sfl = new DefaultSourceFileExceptionList(sf);
130 } else {
131 sfl.add(sf);
132 }
133 continue;
134 }
135 }
136 }
137
138 synchronized (prop) {
139 loadingRequiredInProgress.remove(prop);
140 if (prop.getDependencyState().areAllRequiredLoaded()) {
141 return true; // everything is OK, someone elses thread might have corrected errors!
142 }
143 prop.getLabels().setModuleReferences(required);
144 if (sfl == null || sfl.size() == 0) {
145 prop.setLoadedRequiredModules(required);
146 return true;
147 } else {
148 prop.setDependencyFailureState(
149 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
150 return false;
151 }
152 }
153 }
154
155 }
|