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