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.dependency;
017
018 import java.util.HashMap;
019 import java.util.Map;
020
021 import org.qedeq.base.io.Parameters;
022 import org.qedeq.base.trace.Trace;
023 import org.qedeq.base.utility.StringUtility;
024 import org.qedeq.kernel.bo.log.QedeqLog;
025 import org.qedeq.kernel.bo.module.ControlVisitor;
026 import org.qedeq.kernel.bo.module.InternalServiceProcess;
027 import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
028 import org.qedeq.kernel.bo.module.KernelQedeqBo;
029 import org.qedeq.kernel.bo.module.PluginExecutor;
030 import org.qedeq.kernel.se.common.ModuleDataException;
031 import org.qedeq.kernel.se.common.Plugin;
032 import org.qedeq.kernel.se.common.SourceFileException;
033 import org.qedeq.kernel.se.common.SourceFileExceptionList;
034 import org.qedeq.kernel.se.state.DependencyState;
035
036
037 /**
038 * Load all required QEDEQ modules.
039 *
040 * @author Michael Meyling
041 */
042 public final class LoadRequiredModulesExecutor extends ControlVisitor implements PluginExecutor {
043
044 /** This class. */
045 private static final Class CLASS = LoadRequiredModulesExecutor.class;
046
047 /**
048 * Constructor.
049 *
050 * @param plugin Plugin we work for.
051 * @param prop Internal QedeqBo.
052 * @param parameters Currently ignored.
053 */
054 LoadRequiredModulesExecutor(final Plugin plugin, final KernelQedeqBo prop,
055 final Parameters parameters) {
056 super(plugin, prop);
057 }
058
059 public Object executePlugin(final InternalServiceProcess process, final Object data) {
060 final String method = "executePlugin";
061 if (getQedeqBo().hasLoadedRequiredModules()) {
062 return Boolean.TRUE; // everything is OK
063 }
064 QedeqLog.getInstance().logRequest(
065 "Loading required modules", getQedeqBo().getUrl());
066 // all QedeqBos currently in state "loading required modules"
067 Map loadingRequiredInProgress = (Map) data;
068 if (loadingRequiredInProgress == null) {
069 loadingRequiredInProgress = new HashMap();
070 }
071 Boolean all = (Boolean) getServices().executePlugin(LoadAllRequiredModulesPlugin.class.getName(),
072 getQedeqBo(), null, process);
073 if (!all.booleanValue()) {
074 final String msg = "Loading required modules failed";
075 QedeqLog.getInstance().logFailureReply(msg, getQedeqBo().getUrl(),
076 "Not all required modules could not even be loaded.");
077 getQedeqBo().setDependencyFailureState(
078 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, getQedeqBo().getErrors());
079 return Boolean.FALSE;
080 }
081 if (loadingRequiredInProgress.containsKey(getQedeqBo())) { // already checked?
082 throw new IllegalStateException("Programming error: must not be marked!");
083 }
084 getQedeqBo().setDependencyProgressState(getPlugin(), DependencyState.STATE_LOADING_REQUIRED_MODULES);
085
086 loadingRequiredInProgress.put(getQedeqBo(), getQedeqBo());
087
088 final KernelModuleReferenceList required = (KernelModuleReferenceList) getQedeqBo().getRequiredModules();
089
090 final SourceFileExceptionList sfl = new SourceFileExceptionList();
091 Trace.trace(CLASS, this, method, "loading required modules of " + getQedeqBo().getUrl());
092 for (int i = 0; i < required.size(); i++) {
093 final KernelQedeqBo current = required.getKernelQedeqBo(i);
094 if (loadingRequiredInProgress.containsKey(current)) {
095 ModuleDataException me = new LoadRequiredModuleException(
096 DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_CODE,
097 DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_TEXT + "\""
098 + required.getLabel(i) + "\"",
099 required.getModuleContext(i));
100 sfl.add(createError(me));
101 continue;
102 }
103 getQedeqBo().getKernelServices().executePlugin(LoadRequiredModulesPlugin.class.getName(),
104 current, loadingRequiredInProgress, process);
105 if (!current.hasLoadedRequiredModules()) {
106 // LATER 20110119 m31: we take only the first error, is that ok?
107 String text = DependencyErrors.IMPORT_OF_MODULE_FAILED_TEXT + "\""
108 + required.getLabel(i) + "\"";
109 if (current.getErrors().size() > 0) {
110 // FIXME 20130324 m31: what if this changed directly after .size() call?
111 text += ", " + current.getErrors().get(0).getMessage();
112 }
113 ModuleDataException me = new LoadRequiredModuleException(
114 DependencyErrors.IMPORT_OF_MODULE_FAILED_CODE,
115 text, required.getModuleContext(i));
116 sfl.add(createError(me));
117 continue;
118 }
119 }
120
121 loadingRequiredInProgress.remove(getQedeqBo());
122
123 if (getQedeqBo().getDependencyState().areAllRequiredLoaded()) {
124 return Boolean.TRUE; // everything is OK, someone elses thread might have corrected errors!
125 }
126 getQedeqBo().getLabels().setModuleReferences(required); // FIXME why here?
127 if (!getQedeqBo().hasBasicFailures() && sfl.size() == 0) {
128 getQedeqBo().setLoadedRequiredModules();
129 QedeqLog.getInstance().logSuccessfulReply(
130 "Loading required modules successful", getQedeqBo().getUrl());
131 return Boolean.TRUE;
132 }
133 if (sfl.size() != 0) {
134 getQedeqBo().setDependencyFailureState(
135 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
136 } else {
137 getQedeqBo().setDependencyFailureState(
138 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, getQedeqBo().getErrors());
139 }
140 final String msg = "Loading required modules failed";
141 QedeqLog.getInstance().logFailureReply(msg, getQedeqBo().getUrl(),
142 StringUtility.replace(getQedeqBo().getErrors().getMessage(), "\n", "\n\t"));
143 return Boolean.FALSE;
144 }
145
146 // FIXME
147 public double getExecutionPercentage() {
148 return 1;
149 }
150
151 public boolean getInterrupted() {
152 return false;
153 }
154
155 public String getLocationDescription() {
156 return "running";
157 }
158
159
160 /**
161 * Prepare exception for error collection.
162 *
163 * @param me Basis exception.
164 * @return Error.
165 */
166 private SourceFileException createError(final ModuleDataException me) {
167 return getQedeqBo().createSourceFileException(getPlugin(), me);
168 }
169
170 }
|