1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.qedeq.kernel.bo.service.dependency;
17
18 import java.util.Stack;
19
20 import org.qedeq.base.io.Parameters;
21 import org.qedeq.base.trace.Trace;
22 import org.qedeq.base.utility.StringUtility;
23 import org.qedeq.kernel.bo.common.ModuleReferenceList;
24 import org.qedeq.kernel.bo.log.QedeqLog;
25 import org.qedeq.kernel.bo.module.InternalModuleServiceCall;
26 import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
27 import org.qedeq.kernel.bo.module.KernelQedeqBo;
28 import org.qedeq.kernel.bo.service.basis.ControlVisitor;
29 import org.qedeq.kernel.bo.service.basis.ModuleServicePluginExecutor;
30 import org.qedeq.kernel.se.common.ModuleDataException;
31 import org.qedeq.kernel.se.common.ModuleService;
32 import org.qedeq.kernel.se.common.SourceFileException;
33 import org.qedeq.kernel.se.common.SourceFileExceptionList;
34 import org.qedeq.kernel.se.state.DependencyState;
35 import org.qedeq.kernel.se.visitor.InterruptException;
36
37
38
39
40
41
42
43 public final class LoadRequiredModulesExecutor extends ControlVisitor implements ModuleServicePluginExecutor {
44
45
46 private static final Class CLASS = LoadRequiredModulesExecutor.class;
47
48
49 private double percentage;
50
51
52
53
54
55
56
57
58 LoadRequiredModulesExecutor(final ModuleService plugin, final KernelQedeqBo prop,
59 final Parameters parameters) {
60 super(plugin, prop);
61 }
62
63 public Object executePlugin(final InternalModuleServiceCall call, final Object data) throws InterruptException {
64 percentage = 0;
65 final String method = "executePlugin";
66 if (getKernelQedeqBo().hasLoadedRequiredModules()) {
67 percentage = 100;
68 return Boolean.TRUE;
69 }
70 QedeqLog.getInstance().logRequest(
71 "Loading required modules", getKernelQedeqBo().getUrl());
72
73
74 if (!loadAllRequiredModules(call, getKernelQedeqBo(), true)) {
75 final String msg = "Loading required modules failed";
76 QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
77 "Not all required modules could not even be loaded.");
78 return Boolean.FALSE;
79 }
80 percentage = 100;
81 Trace.trace(CLASS, this, method, "loading required modules of " + getKernelQedeqBo().getUrl());
82 getKernelQedeqBo().setDependencyProgressState(DependencyState.STATE_LOADING_REQUIRED_MODULES);
83
84
85 final SourceFileExceptionList sfl = new SourceFileExceptionList();
86 if (circlesInRequiredModules(call, getKernelQedeqBo(), sfl)) {
87 final String msg = "Loading required modules failed";
88 QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
89 "There were circular dependencies.");
90 return Boolean.FALSE;
91 }
92
93 if (getKernelQedeqBo().getDependencyState().areAllRequiredLoaded()) {
94 return Boolean.TRUE;
95 }
96
97 getKernelQedeqBo().getLabels().setModuleReferences(getKernelQedeqBo().getRequiredModules());
98 if (!getKernelQedeqBo().hasBasicFailures() && sfl.size() == 0) {
99 getKernelQedeqBo().setLoadedRequiredModules();
100 QedeqLog.getInstance().logSuccessfulReply(
101 "Loading required modules successful", getKernelQedeqBo().getUrl());
102 return Boolean.TRUE;
103 }
104 if (sfl.size() != 0) {
105 getKernelQedeqBo().setDependencyFailureState(
106 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
107 } else {
108 getKernelQedeqBo().setDependencyFailureState(
109 DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, getKernelQedeqBo().getErrors());
110 }
111 final String msg = "Loading required modules failed";
112 QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
113 StringUtility.replace(getKernelQedeqBo().getErrors().getMessage(), "\n", "\n\t"));
114 return Boolean.FALSE;
115 }
116
117 private boolean circlesInRequiredModules(final InternalModuleServiceCall call, final KernelQedeqBo bo,
118 final SourceFileExceptionList sfl) {
119 if (bo.hasLoadedRequiredModules()) {
120 return false;
121 }
122 Stack loadingRequiredInProgress = new Stack();
123 Stack labels = new Stack();
124
125 loadingRequiredInProgress.push(bo);
126 final KernelModuleReferenceList required = bo.getKernelRequiredModules();
127 final StringBuffer error = new StringBuffer();
128 for (int i = 0; i < required.size(); i++) {
129 final KernelQedeqBo current = required.getKernelQedeqBo(i);
130
131 labels.push(required.getLabel(i));
132 if (loadingRequiredInProgress.contains(current)) {
133
134
135
136 ModuleDataException me = new LoadRequiredModuleException(
137 DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_CODE,
138 DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_TEXT + "\""
139 + required.getLabel(i) + "\"",
140 required.getModuleContext(i));
141 sfl.add(createError(me));
142
143 labels.pop();
144 continue;
145 }
146
147
148
149 error.setLength(0);
150 if (!noCirclesInRequiredModules(call, required.getKernelQedeqBo(i), loadingRequiredInProgress, labels,
151 error)) {
152
153 String text = DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_TEXT + error.toString();
154 ModuleDataException me = new LoadRequiredModuleException(
155 DependencyErrors.RECURSIVE_IMPORT_OF_MODULES_IS_FORBIDDEN_CODE,
156 text, required.getModuleContext(i));
157 sfl.add(createError(me));
158 }
159 labels.pop();
160 }
161
162 loadingRequiredInProgress.pop();
163 if (sfl.size() > 0) {
164 bo.setDependencyFailureState(DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
165 return true;
166 }
167 return false;
168 }
169
170 private boolean noCirclesInRequiredModules(final InternalModuleServiceCall call, final KernelQedeqBo bo,
171 final Stack loadingRequiredInProgress, final Stack labels, final StringBuffer error) {
172 if (!bo.hasLoadedImports()) {
173 return false;
174 }
175
176 loadingRequiredInProgress.push(bo);
177 final KernelModuleReferenceList required = bo.getKernelRequiredModules();
178 boolean result = true;
179 for (int i = 0; i < required.size(); i++) {
180 final KernelQedeqBo current = required.getKernelQedeqBo(i);
181
182 labels.push(required.getLabel(i));
183 if (loadingRequiredInProgress.contains(current)) {
184 for (int j = 0; j < loadingRequiredInProgress.size(); j++) {
185 if (j > 0) {
186 error.append(" -> ");
187 }
188 error.append("\"" + labels.get(j).toString() + "\"");
189 }
190 result = false;
191
192 labels.pop();
193 break;
194 }
195
196 if (!noCirclesInRequiredModules(call, required.getKernelQedeqBo(i), loadingRequiredInProgress, labels,
197 error)) {
198 result = false;
199
200 labels.pop();
201 break;
202 }
203 labels.pop();
204 }
205
206 loadingRequiredInProgress.pop();
207 return result;
208 }
209
210 private boolean loadAllRequiredModules(final InternalModuleServiceCall call, final KernelQedeqBo bo,
211 final boolean first) throws InterruptException {
212 if (bo.hasLoadedImports()) {
213 return true;
214 }
215 getServices().executePlugin(call.getInternalServiceProcess(),
216 LoadDirectlyRequiredModulesPlugin.class.getName(), bo, null);
217 if (!bo.hasLoadedImports()) {
218 return false;
219 }
220 final ModuleReferenceList imports = bo.getRequiredModules();
221 final SourceFileExceptionList sfl = new SourceFileExceptionList();
222 boolean result = true;
223 for (int i = 0; i < imports.size(); i++) {
224 if (!imports.getQedeqBo(i).hasLoadedImports()) {
225 if (!loadAllRequiredModules(call, (KernelQedeqBo) imports.getQedeqBo(i), false)) {
226 result = false;
227 if (first) {
228
229 String text = DependencyErrors.IMPORT_OF_MODULE_FAILED_TEXT + "\""
230 + imports.getLabel(i) + "\"";
231 if (imports.getQedeqBo(i).getErrors().size() > 0) {
232 text += ", " + imports.getQedeqBo(i).getErrors().get(0).getMessage();
233 }
234 ModuleDataException me = new LoadRequiredModuleException(
235 DependencyErrors.IMPORT_OF_MODULE_FAILED_CODE,
236 text, imports.getModuleContext(i));
237 sfl.add(createError(me));
238 }
239 }
240 }
241 }
242 if (sfl.size() > 0) {
243 bo.setDependencyFailureState(DependencyState.STATE_LOADING_REQUIRED_MODULES_FAILED, sfl);
244 }
245 return result;
246 }
247
248 public double getVisitPercentage() {
249 return percentage;
250 }
251
252 public boolean getInterrupted() {
253 return false;
254 }
255
256 public String getLocationDescription() {
257 return super.getLocationDescription();
258 }
259
260
261
262
263
264
265
266
267 private SourceFileException createError(final ModuleDataException me) {
268 return getKernelQedeqBo().createSourceFileException(getService(), me);
269 }
270
271 }