+ * @version $Revision: #1 $ $Date: 2015/05/18 $
+ */
+public abstract class AbstractContentTypeUnloader extends PackageLoader {
+ /**
+ * Internal logger instance to faciliate debugging. Enable logging output
+ * by editing /WEB-INF/conf/log4j.properties int hte runtime environment
+ * and set com.arsdigita.cms.contenttypes.AbstractContentTypeLoader=DEBUG
+ * by uncommenting or adding the line.
+ */
+ private static final Logger s_log = Logger.getLogger(
+ AbstractContentTypeLoader.class);
+
+ /**
+ * The run method is invoked to execute the unloader step. Before calling
+ * this method any required parameters registered by the noargs
+ * constructer should be set.
+ *
+ * Overwrites the parent's class abstract method adding the task specific
+ * sweep() method.
+ *
+ * @param ctx The context to the unload-script
+ */
+ @Override
+ public void run(final ScriptContext ctx) {
+ new KernelExcursion() {
+
+ @Override
+ protected void excurse() {
+ setEffectiveParty(Kernel.getSystemParty());
+
+ sweepTypes(ctx);
+
+ }
+ }.run();
+ }
+
+ /**
+ * Parses the content-types specified in the "contentType".xml-file and
+ * stores them into a list. Then retrieves all content-sections into
+ * a dataCollection and removes all the content-types stored in the list
+ * from the sections in that dataCollection.
+ *
+ * @param ctx The context to the unload-script
+ */
+ private void sweepTypes(ScriptContext ctx) {
+ XMLContentTypeHandler handler = new XMLContentTypeHandler();
+ // Retrieve the content type definition file(s)
+ String[] contentTypes = getTypes();
+ for (String contentType : contentTypes) {
+ XML.parseResource(contentType, handler);
+ }
+
+ List types = handler.getContentTypes();
+ Session ssn = ctx.getSession();
+ DataCollection sections = ssn.retrieve(
+ ContentSection.BASE_DATA_OBJECT_TYPE);
+
+ while (sections.next()) {
+ ContentSection section = (ContentSection)
+ DomainObjectFactory.newInstance(sections.getDataObject());
+ if (!isLoadableInto(section)) {
+ continue;
+ }
+
+ for (Iterator it = types.iterator(); it.hasNext();) {
+ final ContentType type = (ContentType) it.next();
+
+ //Is the order important?? (here: same as in load step)
+ section.removeContentType(type);
+ }
+ }
+ //TODO: still to be implemented
+ }
+
+ /**
+ * Provides a list of contenttype property definitions.
+ *
+ * In the file there are definitions of the type's name as displayed in
+ * content center select box and the authoring steps. These are loaded into
+ * database.
+ *
+ * It is a XML file and by convention named after the content type or the
+ * module's base name which implements one or more content types. It is
+ * usually something like
+ *
+ * "/WEB-INF/content-types/com/arsdigita/cms/contenttypes/Event.xml"
+ *
+ * The path is fixed by convention and the name is the same as the
+ * content types's.
+ * Must be implemented by each content type loader to provide its
+ * specific definition files.
+ *
+ * @return This content type's property definitions through the ".xml"-file
+ */
+ protected abstract String[] getTypes();
+
+ /**
+ * Checks, if its possible to load into the given section.
+ *
+ * @param The section to be checked
+ * @return true, if its possible to load into the section, otherwise false
+ */
+ private boolean isLoadableInto(ContentSection section) {
+ if (section == null) {
+ throw new NullPointerException("section");
+ }
+
+ if (getContentSections().size() > 0) {
+ return getContentSections().contains(section.getName());
+ } else {
+ return ContentSection.getConfig().getDefaultContentSection().
+ equals(section.getName());
+ }
+ }
+
+ /**
+ * Returns a list of content sections into which the content type should be
+ * installed.
+ *
+ * If this returns an empty list, then the content type will be loaded
+ * into the section specified by {@link
+ * com.arsdigita.cms.ContentSectionConfig#get
+ * @return DefaultContentSection()}.
+ *
+ * The default implementation returns an empty list.
+ *
+ * @post return != null
+ */
+ protected List getContentSections() {
+ return java.util.Collections.EMPTY_LIST;
+ }
+}
diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ContentTypeInitializer.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ContentTypeInitializer.java
index 18f8bef87..4804f8cf0 100755
--- a/ccm-cms/src/com/arsdigita/cms/contenttypes/ContentTypeInitializer.java
+++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ContentTypeInitializer.java
@@ -116,8 +116,7 @@ public abstract class ContentTypeInitializer extends CompoundInitializer {
new ContentPageMetadataProvider());
final String[] stylesheets = getStylesheets();
- for (int i = 0; i < stylesheets.length; i++) {
- String stylesheet = stylesheets[i];
+ for (String stylesheet : stylesheets) {
ContentType.registerXSLFile(type, stylesheet);
}
} catch (com.arsdigita.domain.DataObjectNotFoundException e) {
@@ -135,7 +134,7 @@ public abstract class ContentTypeInitializer extends CompoundInitializer {
* Has to be overwritten by each specific content type to provide its
* TraversalXML if it uses one.
*
- * @return Fully qualified file name (relative to docuemnt / context root)
+ * @return Fully qualified file name (relative to document / context root)
* to traversal adapter.
*/
public String getTraversalXML() {
diff --git a/ccm-core/src/com/arsdigita/kernel/KernelExcursion.java b/ccm-core/src/com/arsdigita/kernel/KernelExcursion.java
index 3b47bded1..51c99e072 100755
--- a/ccm-core/src/com/arsdigita/kernel/KernelExcursion.java
+++ b/ccm-core/src/com/arsdigita/kernel/KernelExcursion.java
@@ -46,6 +46,7 @@ public abstract class KernelExcursion implements Runnable {
private static final Logger s_log = Logger.getLogger
(KernelExcursion.class);
+ @Override
public final void run() {
s_log.debug("Running excursion");
diff --git a/ccm-core/src/com/arsdigita/loader/PackageLoader.java b/ccm-core/src/com/arsdigita/loader/PackageLoader.java
index ad1d16cd3..16916de37 100755
--- a/ccm-core/src/com/arsdigita/loader/PackageLoader.java
+++ b/ccm-core/src/com/arsdigita/loader/PackageLoader.java
@@ -54,6 +54,14 @@ public abstract class PackageLoader extends AbstractScript {
private final static Logger s_log = Logger.getLogger(PackageLoader.class);
+ /**
+ * Checks if the given table exists in the database specified
+ * by the given connection.
+ *
+ * @param conn The specified connection to the database
+ * @param table The table name
+ * @return true if the table exists, otherwise false
+ */
public static boolean exists(Connection conn, String table) {
try {
DatabaseMetaData md = conn.getMetaData();
@@ -100,6 +108,7 @@ public abstract class PackageLoader extends AbstractScript {
public static void load(Connection conn, String script) {
SQLLoader loader = new SQLLoader(conn) {
+ @Override
protected Reader open(String name) {
String resourceName = name.replace('\\', '/');
ClassLoader cload = getClass().getClassLoader();
@@ -128,8 +137,8 @@ public abstract class PackageLoader extends AbstractScript {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer w = new OutputStreamWriter(baos);
- for (int i = 0; i < args.length; i++) {
- w.write(args[i]);
+ for (String arg : args) {
+ w.write(arg);
w.write("\n");
}
diff --git a/ccm-core/src/com/arsdigita/packaging/Load.java b/ccm-core/src/com/arsdigita/packaging/Load.java
index cc54641bf..6f7e3807e 100755
--- a/ccm-core/src/com/arsdigita/packaging/Load.java
+++ b/ccm-core/src/com/arsdigita/packaging/Load.java
@@ -19,19 +19,12 @@
package com.arsdigita.packaging;
import com.arsdigita.loader.PackageLoader;
-import com.arsdigita.persistence.ConnectionSource;
-import com.arsdigita.persistence.DedicatedConnectionSource;
-import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.Session;
import com.arsdigita.persistence.SessionManager;
-import com.arsdigita.persistence.metadata.MetadataRoot;
-import com.arsdigita.persistence.pdl.PDLCompiler;
import com.arsdigita.runtime.InteractiveParameterReader;
import com.arsdigita.runtime.ConfigRegistry;
-import com.arsdigita.runtime.RegistryConfig;
import com.arsdigita.runtime.RuntimeConfig;
import com.arsdigita.runtime.Runtime;
-import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.util.JavaPropertyReader;
import com.arsdigita.util.jdbc.Connections;
import com.arsdigita.util.parameter.CompoundParameterReader;
@@ -39,26 +32,15 @@ import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.ParameterContext;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Properties;
-import java.util.Scanner;
-import java.util.Set;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
@@ -114,14 +96,17 @@ import org.apache.log4j.Logger;
* May be necessary for an update which contains new modules already configured
* in the registry but missing in the (old) database.
*
- * @author Rafael H. Schloming <rhs@mit.edu>
+ * @author Tobias Osmers
+ * @version $Revision: #3 $ $Date: 2015/04/27 $
*/
+class Load extends Command implements LoadCenter {
-class Load extends Command {
-
+ private static final LoadCenterDelegate delegate = new LoadCenterDelegate();
+
private static final Logger logger = Logger.getLogger(Load.class);
private static final Options OPTIONS = getOptions();
+ //Initializes all available option-flags in an option-set
static {
logger.debug("Static initalizer starting...");
OPTIONS.addOption
@@ -204,11 +189,14 @@ class Load extends Command {
/**
* Invoked from the central tool "MasterTool" to execute the load process.
*
- * @param args
- * @return
+ * @param args The parameters and option-flags
+ * @return true if successful, false otherwise
*/
+ @Override
public boolean run(String[] args) {
+ //Takes the option-set and the arguments and parses
+ //them into a command-line
CommandLine line;
try {
line = new PosixParser().parse(OPTIONS, args);
@@ -217,153 +205,84 @@ class Load extends Command {
return false;
}
- // fill with command line arguments which is a list of packages by their
- // package-keys to load.
- List packages = line.getArgList();
-
- if (line.hasOption("packagekeys-file")) {
- String file = line.getOptionValue("packagekeys-file");
- logger.debug("File with package keys: " + file );
- try {
- Scanner sc = new Scanner(new File(file));
- while (sc.hasNext()) {
- packages.add(sc.next());
- }
- } catch (IOException e) {
- System.err.println(e.getMessage());
- return false;
- }
- }
-
- if (packages.isEmpty()) {
- usage(OPTIONS, System.err, "PACKAGE-KEYS");
- return false;
- }
-
-
-
+ //[--usage || --help]
+ //If set, prints an info-output and returns the function
+ //with true
if (line.hasOption("usage") || line.hasOption("help")) {
usage(OPTIONS, System.out, "PACKAGE-KEYS");
return true;
}
-
- final boolean all = !(line.hasOption("config")
- || line.hasOption("schema")
- || line.hasOption("data")
- || line.hasOption("init"));
-
- // RegistryConfig contains a list of package-keys of loaded packages
- RegistryConfig rc = new RegistryConfig(); // Create a new (empty) config object.
- rc.load(); // Load config values from file
- List loaded = Arrays.asList(rc.getPackages()); // retrieve list of installed packages
-
- Map loaders = new HashMap();
- List keys = new ArrayList();
- keys.addAll(packages); // from command line parameters packages to be installed
- boolean err = false;
- while (!keys.isEmpty()) {
- String key = (String) keys.remove(0);
- if (loaders.containsKey(key)) { continue; }
- Loader l = Loader.get(key);
- if (l == null) {
- System.err.println("unable to locate package: " + key);
- err = true;
- } else {
- loaders.put(key, l);
- if (line.hasOption("recursive")) {
- keys.addAll(l.getInfo().getRequiredPackages());
- }
- }
- }
- if (err) { return false; }
-
- Loader[] sorted = (Loader[]) loaders.values().toArray
- (new Loader[loaders.size()]);
- sort(sorted);
-
- if (all) {
- List missing = new ArrayList();
- addTo(missing, getRequiredPackages(sorted));
- missing.removeAll(getProvidedPackages(sorted));
- missing.removeAll(loaded);
- List conflicts = new ArrayList(loaded);
- conflicts.retainAll(getProvidedPackages(sorted));
- if (!missing.isEmpty()) {
- System.err.println("required packages: " + missing);
- }
- if (!conflicts.isEmpty()) {
- System.err.println("conflicting packages: " + conflicts);
- }
- if (missing.size() + conflicts.size() > 0) {
+
+ //Gets all packages which will be unloaded and assures
+ //that this list is not empty.
+ List packages;
+ try {
+ packages = getAllPackages(line);
+ if (packages.isEmpty()) {
+ usage(OPTIONS, System.err, "PACKAGE-KEYS");
return false;
}
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ return false;
+ }
+
+ //Gets all unloaders corresponding to the packages which
+ //will be unloaded.
+ Loader[] loaders;
+ try {
+ loaders = getAllLoaders(line, packages, LoadType.LOAD);
+ } catch (Error e) {
+ System.err.println(e.getMessage());
+ return false;
}
- ParameterMap contexts = new ParameterMap();
+ //Determines if all steps have to be performed.
+ final boolean all = hasAllOptions(line);
+
+ //Checks that there are no missing or conflicting packages.
+ if (!noMissingAndConflictingPackages(loaders, all)) {
+ return false;
+ }
- Properties parameters = new Properties();
+ //Gets all parameters set in a file or given to by the
+ //agrument line and adds the parameters to the cpr.
CompoundParameterReader cpr = new CompoundParameterReader();
- if (line.hasOption("parameter-file")) {
- String file = line.getOptionValue("parameter-file");
- try {
- InputStream fis = new FileInputStream(file);
- parameters.load(fis);
- fis.close();
- } catch (IOException e) {
- System.err.println(e.getMessage());
- return false;
- }
- // deprecated, use JavaPropertyReader instead
- // cpr.add(new JavaPropertyLoader(parameters));
+ Properties parameters = new Properties();
+ try {
+ getAllParameters(line, parameters);
cpr.add(new JavaPropertyReader(parameters));
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ return false;
}
- if (line.hasOption("parameters")) {
- Properties props = props(line.getOptionValues("parameters"));
- // deprecated, use JavaPropertyReader instead
- // cpr.add(new JavaPropertyLoader(props));
- cpr.add(new JavaPropertyReader(props));
- parameters.putAll(props);
- }
+
+ //Adds an appropriate entry to the cpr for interactive
+ //parameter reading.
if (line.hasOption("interactive")) {
cpr.add(new InteractiveParameterReader(System.in, System.out));
}
Config config = null;
+
try {
- if (all || line.hasOption("config")) {
- ConfigRegistry reg = new ConfigRegistry();
- for (int i = 0; i < sorted.length; i++) {
- if (!reg.getPackages().contains(sorted[i].getKey())) {
- reg.initialize(sorted[i].getKey());
- }
- }
- config = new Config(reg);
- config.load(System.err);
+ //Initializes all packages in the registry and creates
+ //a configuration.
+ config = getConfig(line, loaders, config, all);
+ //Collects the configuration-parameters and data-scripts
+ //in the contexts
+ ParameterMap contexts = getContexts(line, loaders, config, all);
- Parameter param = config.getParameter("waf.config.packages");
- ParameterContext ctx = config.getContainer(param);
- String[] pkgs = (String[]) ctx.get(param);
- for (int i = 0; i < sorted.length; i++) {
- if (!contains(pkgs, sorted[i].getKey())) {
- pkgs = concat(pkgs, new String[] { sorted[i].getKey() });
- }
- }
- ctx.set(param, pkgs);
-
- contexts.addContexts(config.getContexts());
- }
-
- if (all || line.hasOption("data")) {
- for (int i = 0; i < sorted.length; i++) {
- contexts.addContexts(sorted[i].getScripts());
- }
- }
-
- if (!contexts.load(new JavaPropertyReader(parameters), System.err)) {
+ //Loads the collected configuration-parameters and data-
+ //scripts. Saves the configuration.
+ if (!contexts.load(new JavaPropertyReader(parameters), System.err) ||
+ !saveConfig(config)) {
return false;
}
+ //Creates a parameter-editor which guides through the steps
+ //of setting config key values.
if (line.hasOption("interactive")) {
ParameterEditor editor =
new ParameterEditor(contexts, System.in, System.out);
@@ -372,240 +291,282 @@ class Load extends Command {
return false;
}
- if (!saveConfig(config)) {
- return false;
- }
-
Session ssn = null;
+
+ //All --schema and --data specific tasks.
if (all || line.hasOption("schema") || line.hasOption("data")) {
- Check checkdb = new CheckDB();
- checkdb.run(null);
- if (checkdb.getStatus() == null
- || checkdb.getStatus().equals(Check.FAIL)) {
+ //Checks for existence and accessibility of a database.
+ if (!checkDatabase()) {
+ rollbackConfig(config, packages);
+ return false;
+ }
+
+ //Opens/aquires a connection to the database.
+ Connection conn =
+ Connections.acquire(RuntimeConfig.getConfig().getJDBCURL());
+
+ //Checks the schema, looks for missing or conflicting
+ //tables and checks the initializers
+ if (!checkSchema(line, loaders, all)
+ || !noMissingAndConflictingTables(line, loaders, conn, all)
+ || !checkInits(line, loaders, conn, all)) {
+ rollbackConfig(config, packages);
+ return false;
+ }
+
+ //Loads the schema.
+ try {
+ loadSchema(line, loaders, conn, all);
+ } catch (SQLException e) {
+ System.err.println(e.getMessage());
rollbackConfig(config,packages);
return false;
}
- if (all || line.hasOption("schema")) {
- boolean passed = true;
- for (int i = 0; i < sorted.length; i++) {
- passed &= sorted[i].checkSchema();
- }
- if (!passed) {
- rollbackConfig(config,packages);
- return false;
- }
- }
-
- Connection conn =
- Connections.acquire(RuntimeConfig.getConfig().getJDBCURL());
-
- List required = new ArrayList();
- addTo(required, getRequiredTables(sorted));
- List provided = new ArrayList();
-
- if (all || line.hasOption("schema")) {
- required.removeAll(getProvidedTables(sorted));
- addTo(provided, getProvidedTables(sorted));
- } else if (line.hasOption("data")) {
- addTo(required, getProvidedTables(sorted));
- }
-
- List missing = getMissing(conn, required);
- List conflicts = getConflicts(conn, provided);
-
- if (!missing.isEmpty()) {
- System.err.println("required tables: " + missing);
- }
-
- if (!conflicts.isEmpty()) {
- System.err.println("conflicting tables (already exist): " +
- conflicts);
- }
-
- if (conflicts.size() > 0 || missing.size() > 0) {
+ //Checks and loads the data.
+ if (!checkAndLoadData(line, loaders, ssn, all, cpr)) {
rollbackConfig(config,packages);
return false;
}
-
- if (PackageLoader.exists(conn, "inits")
- && (line.hasOption("init") || all)) {
- final boolean success = checkInitializerDependencies
- (sorted);
-
- if (!success) {
- rollbackConfig(config,packages);
- return false;
- }
- }
-
- if (all || line.hasOption("schema")) {
- for (int i = 0; i < sorted.length; i++) {
- sorted[i].loadSchema(conn);
- }
- try {
- conn.commit();
- } catch (SQLException e) {
- System.err.println(e.getMessage());
- rollbackConfig(config,packages);
- return false;
- }
- }
-
-
- if (all || line.hasOption("data")) {
- if (ssn == null) {
- new Runtime().startup();
- ssn = SessionManager.getSession();
- }
-
- boolean passed = true;
- for (int i = 0; i < sorted.length; i++) {
- passed &= sorted[i].checkData(ssn);
- }
- if (!passed) {
- rollbackConfig(config,packages);
- return false;
- }
-
- for (int i = 0; i < sorted.length; i++) {
- sorted[i].loadData(ssn, cpr);
- }
- }
}
+
+ //All --init specific tasks.
if (all || line.hasOption("init")) {
- if (ssn == null) {
- new Runtime().startup();
- ssn = SessionManager.getSession();
- }
- for (int i = 0; i < sorted.length; i++) {
- sorted[i].loadInits(ssn);
- }
+ loadInits(loaders, ssn);
}
} catch (Throwable t) {
t.printStackTrace(System.err);
rollbackConfig(config,packages);
return false;
}
+
return true;
}
- private boolean checkInitializerDependencies(final Loader[] sorted) {
- final List required = new ArrayList();
- final List provided = new ArrayList();
- addTo(required, getRequiredInitializers(sorted));
- required.removeAll(getProvidedInitializers(sorted));
- addTo(provided, getProvidedInitializers(sorted));
-
- final Session boot = session();
- final List missing = getMissing(boot, required);
- final List conflicts = getConflicts(boot, provided);
-
- if (!missing.isEmpty()) {
- System.err.println("required initializers: " + missing);
- return false;
- }
-
- if (!conflicts.isEmpty()) {
- System.err.println("conflicting initializers: " + conflicts);
- return false;
- }
-
- return true;
+ /**
+ * Gets all packages to be unloaded either from the command-line or a file,
+ * if the option flag [--packagekeys-file FILE] has been set and puts them
+ * in a list of packages (by their package-keys).
+ *
+ * @param line The command-line with all options and arguments
+ * @return The list of packages to be unloaded
+ * @throws IOException
+ */
+ @Override
+ public List getAllPackages(CommandLine line) throws IOException {
+ return delegate.getAllPackages(line);
}
-
- private boolean saveConfig(Config config) {
- if (config != null) {
- try {
- config.save();
- } catch (IOException e) {
- System.err.println(e.getMessage());
- return false;
- }
- }
- return true;
+
+ /**
+ * Gets all loaders to the given package-list and sorts them before re-
+ * turning. Creates a map that assigns to every package-key an equivalent
+ * loader. This loader contains a bunch of informations (required,
+ * provided, scripts) provided by an ".load"-file. Then all loaders from
+ * the map (pkg-key -> loader) are composed into an array of loaders and
+ * sorted.
+ *
+ * @param line The command-line with all options and arguments
+ * @param packages The list of packages to be loaded
+ * @param loadType Weather packages are been loaded or unloaded
+ * @return A sorted list of loaders
+ * @throws Error
+ */
+ @Override
+ public Loader[] getAllLoaders(CommandLine line, List packages,
+ LoadType loadType) throws Error {
+ return delegate.getAllLoaders(line, packages, loadType);
}
-
- private void rollbackConfig(Config config, List packages) {
- if (config != null) {
- Parameter param = config.getParameter("waf.config.packages");
- ParameterContext ctx = config.getContainer(param);
- String[] pkgs = (String[]) ctx.get(param);
- LinkedList original = new LinkedList();
- for (int i = 0; i < pkgs.length; i++) {
- boolean isnew = false;
- for (int j = 0; j < packages.size(); j++) {
- // Operator == compares object identity.
- // comparison here refers to package names, so an
- // object comparison will never be true.
- // instead: equals()
- // if (pkgs[i].toString() == packages.get(j).toString()) {
- if (pkgs[i].toString().equals(packages.get(j).toString())) {
- isnew = true;
- }
- }
- if (!isnew) {
- original.add(pkgs[i]);
+
+ /**
+ * Determines if all steps (config, schema, data, inits) have to be
+ * performed.
+ *
+ * @param line The command-line with all options and arguments
+ * @return True if all options need to be performed
+ */
+ @Override
+ public boolean hasAllOptions(CommandLine line) {
+ return delegate.hasAllOptions(line);
+ }
+
+ /**
+ * Creates a new (empty) config object and loads config values from a file.
+ * Then retrieves a list of installed packages. RegistryConfig contains a
+ * list of package-keys of loaded packages.
+ *
+ * If all steps need to be performed, it checks if there are no more missing
+ * or conflicting packages. Missing means, that a package required by a
+ * soon-to-be-loaded-package, has not been loaded yet. Conflicting means,
+ * that a package which will soon be provided by a soon-to-be-loaded-package
+ * has already been loaded. Either way leads to a problem, therefore
+ * returning false.
+ * @param loaders The loaders to the packages being loaded
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return True if there are no missing or conflicting packages, otherwise
+ * false
+ */
+ private boolean noMissingAndConflictingPackages(Loader[] loaders,
+ boolean all) {
+ return delegate.noMissingAndConflictingPackages(loaders, all);
+ }
+
+ /**
+ * Collects all parameters either set in a file or given per line-argument
+ * and stores them in a parameter-variable.
+ *
+ * @param line The command-line with all options and arguments
+ * @param parameters The properties to store the collected parameters
+ * @throws IOException
+ */
+ private static void getAllParameters(CommandLine line, Properties parameters)
+ throws IOException {
+ if (line.hasOption("parameter-file")) {
+ String file = line.getOptionValue("parameter-file");
+ InputStream fis = new FileInputStream(file);
+ parameters.load(fis);
+ fis.close();
+ }
+ if (line.hasOption("parameters")) {
+ Properties params = argsToProperties(line.getOptionValues("parameters"));
+ parameters.putAll(params);
+ }
+ }
+
+ /**
+ * [SUPPORT]
+ * Converts a list of parameter-arguments into properties.
+ *
+ * used in: getAllParameters,
+ * Set.java -> run
+ *
+ * @param args List of parameter arguments
+ * @return A Properties-Object
+ * @throws IOException
+ */
+ public static Properties argsToProperties(String[] args) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Writer w = new OutputStreamWriter(baos);
+ for (String arg : args) {
+ w.write(arg);
+ w.write("\n");
+ }
+ w.flush();
+ Properties params = new Properties();
+ params.load(new ByteArrayInputStream(baos.toByteArray()));
+ return params;
+ }
+
+ /**
+ * Initializes all package-keys in the registry and creates a specified
+ * configuration.
+ *
+ * @param line The command-line with all options and arguments
+ * @param loaders The loaders to the packages being loaded
+ * @param config The configuration-file
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return A configuration for all packages
+ */
+ private static Config getConfig(CommandLine line, Loader[] loaders, Config
+ config, boolean all) {
+ if (all || line.hasOption("config")) {
+ ConfigRegistry reg = new ConfigRegistry();
+ for (Loader loader : loaders) {
+ if (!reg.getPackages().contains(loader.getKey())) {
+ reg.initialize(loader.getKey());
}
}
- String[] orig = new String[original.size()];
- for (int i = 0; i < original.size(); i++) {
- orig[i] = (String)original.get(i);
- }
- ctx.set(param, orig);
- saveConfig(config);
+ config = new Config(reg);
}
+ return config;
}
-
- private static List getMissing(Connection conn, List tables) {
- List missing = new ArrayList();
- for (Iterator it = tables.iterator(); it.hasNext(); ) {
- String table = (String) it.next();
- if (!PackageLoader.exists(conn, table)) {
- missing.add(table);
+
+
+
+ /**
+ * Collects the contexts in a parameter-map. First setting packages in
+ * a parameter-context and adding this parameter-context to the parameter-
+ * map. Second adding all data-scripts to the context in the parameter-
+ * map.
+ *
+ * @param line The command-line with all options and arguments
+ * @param loaders The loaders to the packages being loaded
+ * @param config The configuration-file
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return The context in a parameter-map
+ */
+ private static ParameterMap getContexts(CommandLine line, Loader[]
+ loaders, Config config, boolean all) {
+ ParameterMap contexts = new ParameterMap();
+ if (all || line.hasOption("config")) {
+ setParameterContext(loaders, config);
+ //Adds the configuration to the context
+ contexts.addContexts(config.getContexts());
+ }
+ if (all || line.hasOption("data")) {
+ for (Loader loader : loaders) {
+ //Adds the data-scripts to the context
+ contexts.addContexts(loader.getScripts());
}
}
- return missing;
+ return contexts;
}
-
- private static List getConflicts(Connection conn, List tables) {
- List conflicts = new ArrayList();
- for (Iterator it = tables.iterator(); it.hasNext(); ) {
- String table = (String) it.next();
- if (PackageLoader.exists(conn, table)) {
- conflicts.add(table);
+
+ /**
+ * [SUPPORT]
+ * Sets all packages from the loaders-list in a configuration-file to the
+ * key "waf.config.packages".
+ *
+ * used in: getContexts
+ *
+ * @param loaders The loaders to the packages being loaded
+ * @param config The configuration-file
+ */
+ private static void setParameterContext(Loader[] loaders, Config config) {
+ config.load(System.err);
+ Parameter param = config.getParameter("waf.config.packages");
+ ParameterContext ctx = config.getContainer(param);
+ String[] pkgs = (String[]) ctx.get(param);
+ for (Loader loader : loaders) {
+ if (!contains(pkgs, loader.getKey())) {
+ pkgs = concat(pkgs, new String[]{loader.getKey()});
}
}
- return conflicts;
+ ctx.set(param, pkgs);
}
-
- private static final String INIT = "com.arsdigita.runtime.Initializer";
-
- private static List getMissing(Session ssn, List inits) {
- List missing = new ArrayList();
- for (Iterator it = inits.iterator(); it.hasNext(); ) {
- String init = (String) it.next();
- OID oid = new OID(ssn.getMetadataRoot().getObjectType(INIT), init);
- if (ssn.retrieve(oid) == null) {
- missing.add(init);
+
+ /**
+ * [SUPPORT]
+ * Checks if a String-array contains a certain String.
+ *
+ * used in: setParameterContext
+ *
+ * @param array The String-array
+ * @param str The String to be checked of being contained by the array
+ * @return True on success, otherwise false
+ */
+ private static boolean contains(String[] array, String str) {
+ for (String s : array) {
+ if (s.equals(str)) {
+ return true;
}
}
- return missing;
+ return false;
}
-
- private static List getConflicts(Session ssn, List inits) {
- List conflicts = new ArrayList();
- for (Iterator it = inits.iterator(); it.hasNext(); ) {
- String init = (String) it.next();
- OID oid = new OID(ssn.getMetadataRoot().getObjectType(INIT), init);
- if (ssn.retrieve(oid) != null) {
- conflicts.add(init);
- }
- }
- return conflicts;
- }
-
+
+ /**
+ * [SUPPORT]
+ * Concatenates two String-array to one.
+ *
+ * used in: setParameterContext
+ *
+ * @param a first String-array
+ * @param b second String-array
+ * @return The concatenated String-array
+ */
private static String[] concat(String[] a, String[] b) {
if (a == null) { return b; }
if (b == null) { return a; }
@@ -614,166 +575,188 @@ class Load extends Command {
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
-
- private static boolean contains(String[] array, String str) {
- for (int i = 0; i < array.length; i++) {
- if (array[i].equals(str)) {
- return true;
+
+ /**
+ * Saves the configurations made during the load process.
+ *
+ * @param config The configurations
+ * @return true on success, otherwise false.
+ */
+ private boolean saveConfig(Config config) {
+ return delegate.saveConfig(config);
+ }
+
+ /**
+ * Checks existence and accessibility of the database and does a rollback
+ * if necessary.
+ *
+ * @return True on success, otherwise false
+ */
+ @Override
+ public boolean checkDatabase() {
+ return delegate.checkDatabase();
+ }
+
+ /**
+ * Sets back the configuration to the original packages. Goes through
+ * all packages from the configuration-context and removes the ones
+ * contained in the list of packages which will be loaded.
+ *
+ * @param config The configuration
+ * @param packages The packages to be loaded
+ * @return True on success, otherwise false
+ */
+ @Override
+ public boolean rollbackConfig(Config config, List packages) {
+ return delegate.rollbackConfig(config, packages);
+ }
+
+ /**
+ * Lists the required and provided tables and checks if there are no more
+ * missing or conflicting tables.
+ * Missing means, that a table required by a soon-to-be-created-table, has
+ * not been created yet. Conflicting means, that a table which will soon be
+ * provided by a soon-to-be-created-table has already been created. Either
+ * way leads to a problem, therefore returning false.
+ *
+ * @param line The command-line with all options and arguments
+ * @param loaders The loaders to the packages being loaded
+ * @param conn The connection to the database
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return True if there are no missing or conflicting tables, otherwise
+ * false
+ */
+ private boolean noMissingAndConflictingTables(CommandLine line, Loader[]
+ loaders, Connection conn, boolean all) {
+ return delegate.noMissingAndConflictingTables(line, loaders, conn, all);
+ }
+
+ /**
+ * Checks if the table "inits" exists in the given database connection and
+ * then checks the initializer dependencies in the list of loaders from the
+ * soon-to-be-loaded packages.
+ *
+ * @param line The command-line with all options and arguments
+ * @param loaders The loaders to the packages being loaded
+ * @param conn The connection to the database
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return True on success, otherwise false
+ */
+ private boolean checkInits(CommandLine line, Loader[] loaders, Connection
+ conn, boolean all) {
+ boolean success = true;
+ if (PackageLoader.exists(conn, "inits")
+ && (line.hasOption("init") || all)) {
+ success = checkInitializerDependencies(loaders, "loader");
+ }
+ return success;
+ }
+
+ /**
+ * [SUPPORT]
+ * Checks the initializer dependencies set in the ".load"-file.
+ *
+ * used in: checkInits
+ *
+ * @param loaders A list of loaders to the corresponding packages
+ * to-be-loaded
+ * @param sessionName Name of the session
+ * @return true on success, otherwise false
+ */
+ @Override
+ public boolean checkInitializerDependencies(final Loader[] loaders,
+ String sessionName) {
+ return delegate.checkInitializerDependencies(loaders, sessionName);
+ }
+
+ /**
+ * Checks the schema of the packages.
+ *
+ * @param line The command-line with all options and arguments
+ * @param loaders The loaders to the packages being loaded
+ * @param Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return True on success, otherwise false
+ */
+ private boolean checkSchema(CommandLine line, Loader[] loaders, boolean all) {
+ boolean passed = true;
+ if (all || line.hasOption("schema")) {
+ for (Loader loader : loaders) {
+ passed &= loader.checkSchema();
}
}
-
- return false;
+ return passed;
}
-
- private static Session session() {
- Session ssn = SessionManager.getSession("loader");
- if (ssn == null) {
- String pdl = "/com/arsdigita/runtime/Initializer.pdl";
- MetadataRoot root = new MetadataRoot();
- PDLCompiler compiler = new PDLCompiler();
- compiler.parse
- (new InputStreamReader
- (Load.class.getResourceAsStream(pdl)),
- pdl);
- compiler.emit(root);
- ConnectionSource source = new DedicatedConnectionSource
- (RuntimeConfig.getConfig().getJDBCURL());
- ssn = SessionManager.open("loader", root, source);
- }
-
- return ssn;
- }
-
- static Properties props(String[] args) {
- try {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- Writer w = new OutputStreamWriter(baos);
- for (int i = 0; i < args.length; i++) {
- w.write(args[i]);
- w.write("\n");
+
+ /**
+ * Loads all schemas of the packages into the database through the opened
+ * connection.
+ *
+ * @param line The command-line with all options and arguments
+ * @param loaders The loaders to the packages being loaded
+ * @param conn The connection to the database
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @throws SQLException
+ */
+ private void loadSchema(CommandLine line, Loader[] loaders, Connection conn,
+ boolean all) throws SQLException {
+ if (all || line.hasOption("schema")) {
+ for (Loader loader : loaders) {
+ loader.loadSchema(conn);
}
-
- w.flush();
-
- Properties props = new Properties();
- props.load(new ByteArrayInputStream(baos.toByteArray()));
- return props;
- } catch (IOException e) {
- throw new UncheckedWrapperException(e);
+ conn.commit();
}
}
-
- private static void sort(Loader[] loaders) {
- Set all = new HashSet();
- for (int i = 0; i < loaders.length; i++) {
- all.addAll(loaders[i].getProvided());
- }
-
- Set provided = new HashSet();
- List sorted = new ArrayList();
- List in = new ArrayList(Arrays.asList(loaders));
- int before;
- do {
- before = in.size();
- for (Iterator it = in.iterator(); it.hasNext(); ) {
- Loader loader = (Loader) it.next();
- Set required = loader.getRequired();
- required.retainAll(all);
- if (provided.containsAll(required)) {
- sorted.add(loader);
- provided.addAll(loader.getProvided());
- it.remove();
+
+ /**
+ * Checks and Loads the data of the packages into the database.
+ *
+ * @param line The command-line with all options and arguments
+ * @param loaders The loaders to the packages being loaded
+ * @param ssn The session for the database-connection
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return True on success, otherwise false
+ */
+ private boolean checkAndLoadData(CommandLine line, Loader[] loaders, Session
+ ssn, boolean all, CompoundParameterReader cpr) {
+ boolean passed = true;
+ if (all || line.hasOption("data")) {
+ //Starts new session for the db-connection
+ if (ssn == null) {
+ new Runtime().startup();
+ ssn = SessionManager.getSession();
+ }
+ for (Loader loader : loaders) {
+ passed &= loader.checkData(ssn);
+ }
+ if (passed) {
+ for (Loader loader : loaders) {
+ loader.loadData(ssn, cpr);
}
}
- } while (in.size() < before);
-
- if (in.size() > 0) {
- throw new IllegalStateException
- ("circular dependencies: " + in);
}
-
- int index = 0;
- for (Iterator it = sorted.iterator(); it.hasNext(); ) {
- loaders[index++] = (Loader) it.next();
+ return passed;
+ }
+
+ /**
+ * Records/Loads the initializers and classes into the database through the
+ * started session.
+ *
+ * @param loaders The loaders to the packages being loaded
+ * @param ssn The session for the database-connection
+ */
+ private void loadInits(Loader[] loaders, Session ssn) {
+ //Starts new session for the db-connection
+ if (ssn == null) {
+ new Runtime().startup();
+ ssn = SessionManager.getSession();
}
+ for (Loader loader : loaders) {
+ loader.loadInits(ssn);
+ }
}
-
- private static final int REQ_TABLE = 0;
- private static final int REQ_INITIALIZER = 1;
- private static final int REQ_PACKAGE = 2;
- private static final int PROV_TABLE = 3;
- private static final int PROV_INITIALIZER = 4;
- private static final int PROV_PACKAGE = 5;
-
- private static List get(Loader[] loaders, int type) {
- ArrayList result = new ArrayList();
-
- for (int i = 0; i < loaders.length; i++) {
- LoaderInfo info = loaders[i].getInfo();
-
- List c;
-
- switch (type) {
- case REQ_TABLE:
- c = info.getRequiredTables();
- break;
- case REQ_INITIALIZER:
- c = info.getRequiredInitializers();
- break;
- case REQ_PACKAGE:
- c = info.getRequiredPackages();
- break;
- case PROV_TABLE:
- c = info.getProvidedTables();
- break;
- case PROV_INITIALIZER:
- c = info.getProvidedInitializers();
- break;
- case PROV_PACKAGE:
- c = new ArrayList();
- c.add(loaders[i].getKey());
- break;
- default:
- throw new IllegalArgumentException("unknown type: " + type);
- }
-
- addTo(result, c);
- }
-
- return result;
- }
-
- private static List getRequiredTables(Loader[] loaders) {
- return get(loaders, REQ_TABLE);
- }
-
- private static List getProvidedTables(Loader[] loaders) {
- return get(loaders, PROV_TABLE);
- }
-
- private static List getRequiredInitializers(Loader[] loaders) {
- return get(loaders, REQ_INITIALIZER);
- }
-
- private static List getProvidedInitializers(Loader[] loaders) {
- return get(loaders, PROV_INITIALIZER);
- }
-
- private static List getRequiredPackages(Loader[] loaders) {
- return get(loaders, REQ_PACKAGE);
- }
-
- private static List getProvidedPackages(Loader[] loaders) {
- return get(loaders, PROV_PACKAGE);
- }
-
- private static void addTo(List a, List b) {
- for (Iterator it = b.iterator(); it.hasNext(); ) {
- Object o = it.next();
- if (!a.contains(o)) {
- a.add(o);
- }
- }
- }
-
-}
+}
\ No newline at end of file
diff --git a/ccm-core/src/com/arsdigita/packaging/LoadCenter.java b/ccm-core/src/com/arsdigita/packaging/LoadCenter.java
new file mode 100644
index 000000000..463bc755a
--- /dev/null
+++ b/ccm-core/src/com/arsdigita/packaging/LoadCenter.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.packaging;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.commons.cli.CommandLine;
+
+/**
+ * Interface used for the "delegate-design-pattern" and therefore sets all
+ * method-declarations which have to be implemented by the helper class
+ * "LoadCenterDeligate" known as the delegate to support the "load"-
+ * and "unload"-commands.
+ *
+ * The "delegate-design-pattern" is a possibility to imitate multiple
+ * inheritance and thus reduce the redundancy.
+ *
+ * @author Tobias Osmers
+ * @version $Revision: #1 $ $Date: 2015/04/22 $
+ */
+public interface LoadCenter {
+ enum LoadType {LOAD, UNLOAD};
+
+ /**
+ * Gets all packages to be unloaded either from the command-line or a file,
+ * if the option flag [--packagekeys-file FILE] has been set and puts them
+ * in a list of packages (by their package-keys).
+ *
+ * @param line The command-line with all options and arguments
+ * @return The list of packages to be unloaded
+ * @throws IOException
+ */
+ List getAllPackages(CommandLine line) throws IOException;
+
+ /**
+ * Gets all loaders to the given package-list and sorts them before re-
+ * turning. Creates a map that assigns to every package-key an equivalent
+ * loader. This loader contains a bunch of informations (required,
+ * provided, scripts) provided by an ".load"-file. Then all loaders from
+ * the map (pkg-key -> loader) are composed into an array of loaders and
+ * sorted.
+ *
+ * @param line The command-line with all options and arguments
+ * @param packages The list of packages to be loaded
+ * @param loadType Weather packages are been loaded or unloaded
+ * @return A sorted list of loaders
+ * @throws Error
+ */
+ Loader[] getAllLoaders(CommandLine line, List packages,
+ LoadType loadType) throws Error;
+
+ /**
+ * Determines if all steps (config, schema, data, inits) have to be
+ * performed.
+ *
+ * @param line The command-line with all options and arguments
+ * @return True if all options need to be performed
+ */
+ boolean hasAllOptions(CommandLine line);
+
+ /**
+ * Checks existence and accessibility of the database and does a rollback
+ * if necessary.
+ *
+ * @return True on success, otherwise false
+ */
+ boolean checkDatabase();
+
+ /**
+ * Sets back the configuration to the original packages. Goes through
+ * all packages from the configuration-context and removes the ones
+ * contained in the list of packages which will be loaded.
+ *
+ * @param config The configuration
+ * @param packages The packages to be loaded
+ * @return True on success, otherwise false
+ */
+ boolean rollbackConfig(Config config, List packages);
+
+ /**
+ * Checks the initializer dependencies set in the ".load"-file.
+ *
+ * @param loaders A list of loaders to the corresponding packages
+ * to-be-loaded
+ * @param sessionName Name of the session
+ * @return true on success, otherwise false
+ */
+ boolean checkInitializerDependencies(final Loader[] loaders,
+ String sessionName);
+
+}
diff --git a/ccm-core/src/com/arsdigita/packaging/LoadCenterDelegate.java b/ccm-core/src/com/arsdigita/packaging/LoadCenterDelegate.java
new file mode 100644
index 000000000..27f53d3de
--- /dev/null
+++ b/ccm-core/src/com/arsdigita/packaging/LoadCenterDelegate.java
@@ -0,0 +1,695 @@
+/*
+ * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.packaging;
+
+import com.arsdigita.loader.PackageLoader;
+import com.arsdigita.persistence.ConnectionSource;
+import com.arsdigita.persistence.DedicatedConnectionSource;
+import com.arsdigita.persistence.OID;
+import com.arsdigita.persistence.Session;
+import com.arsdigita.persistence.SessionManager;
+import com.arsdigita.persistence.metadata.MetadataRoot;
+import com.arsdigita.persistence.pdl.PDLCompiler;
+import com.arsdigita.runtime.ConfigRegistry;
+import com.arsdigita.runtime.RegistryConfig;
+import com.arsdigita.runtime.RuntimeConfig;
+import com.arsdigita.util.parameter.Parameter;
+import com.arsdigita.util.parameter.ParameterContext;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+import org.apache.commons.cli.CommandLine;
+import org.apache.log4j.Logger;
+
+/**
+ * The helper class for the "delegate-design-pattern" known as the "delegate"
+ * whom is given the responsibility to execute tasks for the "load"- and
+ * "unload"-command.
+ *
+ * Contains all implementations defined in the interface as well as their needed
+ * support methods. Furthermore this class implements some methods with support
+ * methods only used by the load.java-class.
+ *
+ *
+ * @author Tobias Osmers
+ * @version $Revision: #2 $ $Date: 2015/04/27 $
+ */
+public class LoadCenterDelegate implements LoadCenter {
+
+ private static final Logger logger = Logger.getLogger(Unload.class);
+ private static final String INIT = "com.arsdigita.runtime.Initializer";
+
+ private final InfoGetter infoGetter = new InfoGetter();
+
+ /**
+ * Gets all packages to be unloaded either from the command-line or a file,
+ * if the option flag [--packagekeys-file FILE] has been set and puts them
+ * in a list of packages (by their package-keys).
+ *
+ * @param line The command-line with all options and arguments
+ * @return The list of packages to be unloaded
+ * @throws IOException
+ */
+ @Override
+ public List getAllPackages(CommandLine line) throws IOException {
+ List packages = line.getArgList();
+ //[--packagekeys-file FILE]
+ if (line.hasOption("packagekeys-file")) {
+ String file = line.getOptionValue("packagekeys-file");
+ logger.debug("File with package keys: " + file );
+ Scanner sc = new Scanner(new File(file));
+ while (sc.hasNext()) {
+ packages.add(sc.next());
+ }
+ }
+ return packages;
+ }
+
+ /**
+ * Gets all loaders to the given package-list and sorts them before re-
+ * turning. Creates a map that assigns to every package-key an equivalent
+ * loader. This loader contains a bunch of informations (required,
+ * provided, scripts) provided by an ".load"-file. Then all loaders from
+ * the map (pkg-key -> loader) are composed into an array of loaders and
+ * sorted.
+ *
+ * @param line The command-line with all options and arguments
+ * @param packages The list of packages to be loaded
+ * @param loadType Weather packages are been loaded or unloaded
+ * @return A sorted list of loaders
+ * @throws Error
+ */
+ @Override
+ public Loader[] getAllLoaders(CommandLine line, List packages,
+ LoadType loadType) throws Error {
+ Map pkgLoaderMap = new HashMap();
+ List packageKeys = new ArrayList();
+ packageKeys.addAll(packages);
+ while (!packageKeys.isEmpty()) {
+ String packageKey = (String) packageKeys.remove(0);
+ if (pkgLoaderMap.containsKey(packageKey)) {
+ continue;
+ }
+ Loader loader = Loader.get(packageKey, loadType);
+ if (loader == null) {
+ throw new Error("unable to locate package: " + packageKey);
+ } else {
+ pkgLoaderMap.put(packageKey, loader);
+ //[--recursive]
+ //If set, all packages required for this package will
+ //be added to the list of packages being unloaded.
+ if (line.hasOption("recursive")) {
+ packageKeys.addAll(loader.getInfo().getRequiredPackages());
+ }
+ }
+ }
+ Loader[] loaders = (Loader[]) pkgLoaderMap.values().toArray
+ (new Loader[pkgLoaderMap.size()]);
+
+ sort(loaders, loadType);
+
+ return loaders;
+ }
+
+ /**
+ * [SUPPORT]
+ * Sorts a given list of loaders, so that the internal order of which
+ * package when to load/unload is consistent with the packages available.
+ * Load: If a package A requires package B, package B has to be loaded
+ * already.
+ * Unload: If a package A provides package B, package B has to be unloaded
+ * first.
+ * Set all: Set of packages to be loaded and its provided packages
+ * List in: List of packages to be loaded (input)
+ * Set required: Set of packages required by the packages from in
+ * List sorted: List of loaders to be loaded
+ * Set provided: Set of provided packages and to be loaded packages
+ * Loaders[] loaders: List of packages to be loaded in the right order
+ *
+ * used in: getAllLoaders
+ *
+ * @param loaders A list of loaders (to be loaded packages)
+ * @param loadType Weather packages are been loaded or unloaded
+ */
+ private static void sort(Loader[] loaders, LoadType loadType) {
+ Set all = new HashSet();
+ for (Loader loader : loaders) {
+ all.addAll(loader.getProvided());
+ }
+ Set provided = new HashSet();
+ List sorted = new ArrayList();
+ List in = new ArrayList(Arrays.asList(loaders));
+ int before;
+ do {
+ before = in.size();
+ for (Iterator it = in.iterator(); it.hasNext(); ) {
+ Loader loader = (Loader) it.next();
+ Set required = loader.getRequired();
+ //Only possible to load
+ required.retainAll(all);
+ //If the already provided packages contain all
+ //required ones its save to add this one too.
+ //Ensures that the order of loading packages is
+ //right.
+ if (provided.containsAll(required)) {
+ sorted.add(loader);
+ provided.addAll(loader.getProvided());
+ it.remove();
+ }
+ }
+ } while (in.size() < before);
+ if (in.size() > 0) {
+ throw new IllegalStateException
+ ("circular dependencies: " + in);
+ }
+ int index = 0;
+ for (Iterator it = sorted.iterator(); it.hasNext(); ) {
+ loaders[index++] = (Loader) it.next();
+ }
+
+ //In case packages are being unloaded
+ if (loadType == LoadType.UNLOAD) {
+ reverseArray(loaders);
+ }
+ }
+
+ /**
+ * [SUPPORT]
+ * Reverses the list of loaders to ensure the right order for unloading.
+ *
+ * used in: sort
+ *
+ * @param loaders The loaders for the packages being unloaded
+ */
+ private static void reverseArray(Loader[] loaders) {
+ for (int i = 0; i < loaders.length / 2; i++) {
+ Loader temp = loaders[i];
+ loaders[i] = loaders[loaders.length - 1 - i];
+ loaders[loaders.length - 1 - i] = temp;
+ }
+ }
+
+ /**
+ * Determines if all steps (config, schema, data, inits) have to be
+ * performed.
+ *
+ * @param line The command-line with all options and arguments
+ * @return True if all options need to be performed
+ */
+ @Override
+ public boolean hasAllOptions(CommandLine line) {
+ return !(line.hasOption("config")
+ || line.hasOption("schema")
+ || line.hasOption("data")
+ || line.hasOption("init"));
+ }
+
+ /**
+ * Creates a new (empty) config object and loads config values from a file.
+ * Then retrieves a list of installed packages. RegistryConfig contains a
+ * list of package-keys of loaded packages.
+ *
+ * If all steps need to be performed, it checks if there are no more missing
+ * or conflicting packages. Missing means, that a package required by a
+ * soon-to-be-loaded-package, has not been loaded yet. Conflicting means,
+ * that a package which will soon be provided by a soon-to-be-loaded-package
+ * has already been loaded. Either way leads to a problem, therefore
+ * returning false.
+ * @param loaders The loaders to the packages being loaded
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return True if there are no missing or conflicting packages, otherwise
+ * false
+ */
+ public boolean noMissingAndConflictingPackages(Loader[] loaders,
+ boolean all) {
+ RegistryConfig rc = new RegistryConfig();
+ rc.load();
+ List loaded = Arrays.asList(rc.getPackages());
+ if (all) {
+ List missing = new ArrayList();
+ addTo(missing, InfoGetter.getRequiredPackages(loaders));
+ missing.removeAll(InfoGetter.getProvidedPackages(loaders));
+ missing.removeAll(loaded);
+ List conflicts = new ArrayList(loaded);
+ conflicts.retainAll(InfoGetter.getProvidedPackages(loaders));
+ if (!missing.isEmpty()) {
+ System.err.println("required packages: " + missing);
+ }
+ if (!conflicts.isEmpty()) {
+ System.err.println("conflicting packages: " + conflicts);
+ }
+ if (missing.size() + conflicts.size() > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * [SUPPORT]
+ * Adds the elements of the second list to the first list.
+ *
+ * used in: noMissingOrConflictingPackages,
+ * checkInitializerDependencies
+ *
+ *
+ * @param a The first list
+ * @param b The second list
+ */
+ private static void addTo(List a, List b) {
+ for (Iterator it = b.iterator(); it.hasNext(); ) {
+ Object o = it.next();
+ if (!a.contains(o)) {
+ a.add(o);
+ }
+ }
+ }
+
+ /**
+ * Saves the configurations made during the load process.
+ *
+ * used in: rollbackConfig, Load.java
+ *
+ * @param config The configurations
+ * @return true on success, otherwise false.
+ */
+ public boolean saveConfig(Config config) {
+ if (config != null) {
+ try {
+ config.save();
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks existence and accessibility of the database and does a rollback
+ * if necessary.
+ *
+ * @return True on success, otherwise false
+ */
+ @Override
+ public boolean checkDatabase() {
+ Check checkdb = new CheckDB();
+ checkdb.run(null);
+ if (checkdb.getStatus() == null ||
+ checkdb.getStatus().equals(Check.FAIL)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sets back the configuration to the original packages. Goes through
+ * all packages from the configuration-context and removes the ones
+ * contained in the list of packages which will be loaded.
+ *
+ * @param config The configuration
+ * @param packages The packages to be loaded
+ * @return True on success, otherwise false
+ */
+ @Override
+ public boolean rollbackConfig(Config config, List packages) {
+ if (config == null) {
+ config = new Config(new ConfigRegistry());
+ config.load(System.err);
+ }
+ Parameter param = config.getParameter("waf.config.packages");
+ ParameterContext ctx = config.getContainer(param);
+ String[] pkgs = (String[]) ctx.get(param);
+ LinkedList original = new LinkedList();
+ for (String pkg : pkgs) {
+ boolean isnew = false;
+ for (Object package1 : packages) {
+ // Operator == compares object identity.
+ // comparison here refers to package names, so an
+ // object comparison will never be true.
+ // instead: equals()
+ // if (pkgs[i].toString() == packages.get(j).toString()) {
+ if (pkg.equals(package1.toString())) {
+ isnew = true;
+ }
+ }
+ if (!isnew) {
+ original.add(pkg);
+ }
+ }
+ String[] orig = new String[original.size()];
+ for (int i = 0; i < original.size(); i++) {
+ orig[i] = (String)original.get(i);
+ }
+ ctx.set(param, orig);
+ return saveConfig(config);
+ }
+
+ /**
+ * Lists the required and provided tables and checks if there are no more
+ * missing or conflicting tables.
+ * Missing means, that a table required by a soon-to-be-created-table, has
+ * not been created yet. Conflicting means, that a table which will soon be
+ * provided by a soon-to-be-created-table has already been created. Either
+ * way leads to a problem, therefore returning false.
+ *
+ * @param line The command-line with all options and arguments
+ * @param loaders The loaders to the packages being loaded
+ * @param conn The connection to the database
+ * @param all Weather all steps (config, schema, data, inits) must be
+ * performed
+ * @return True if there are no missing or conflicting tables, otherwise
+ * false
+ */
+ public boolean noMissingAndConflictingTables(CommandLine line, Loader[]
+ loaders, Connection conn, boolean all) {
+ List required = new ArrayList();
+ addTo(required, InfoGetter.getRequiredTables(loaders));
+ List provided = new ArrayList();
+
+ if (all || line.hasOption("schema")) {
+ required.removeAll(InfoGetter.getProvidedTables(loaders));
+ addTo(provided, InfoGetter.getProvidedTables(loaders));
+ } else if (line.hasOption("data")) {
+ addTo(required, InfoGetter.getProvidedTables(loaders));
+ }
+
+ List missing = getMissing(conn, required);
+ List conflicts = getConflicts(conn, provided);
+ if (!missing.isEmpty()) {
+ System.err.println("required tables: " + missing);
+ }
+ if (!conflicts.isEmpty()) {
+ System.err.println(
+ "conflicting tables (already exist): " + conflicts);
+ }
+ if (conflicts.size() > 0 || missing.size() > 0) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * [SUPPORT]
+ * Returns all tables, required by the tables in the given list, which
+ * haven't been created yet in the database for the given connection, thus
+ * all missing tables.
+ *
+ * used in: noMissingAndConflictingTables
+ *
+ * @param conn The connection to the database
+ * @param tables The list of tables to be installed
+ * @return A list of missing tables
+ */
+ private static List getMissing(Connection conn, List tables) {
+ List missing = new ArrayList();
+ for (Iterator it = tables.iterator(); it.hasNext(); ) {
+ String table = (String) it.next();
+ if (!PackageLoader.exists(conn, table)) {
+ missing.add(table);
+ }
+ }
+ return missing;
+ }
+
+ /**
+ * [SUPPORT]
+ * Returns all tables, provided by the tables in the given list, which have
+ * already been created in the database for the given connection, thus
+ * all conflicting tables.
+ *
+ * used in: noMissingAndConflictingTables
+ *
+ * @param conn The connection to the database
+ * @param tables The list of tables to be installed
+ * @return A list of conflicting tables
+ */
+ private static List getConflicts(Connection conn, List tables) {
+ List conflicts = new ArrayList();
+ for (Iterator it = tables.iterator(); it.hasNext(); ) {
+ String table = (String) it.next();
+ if (PackageLoader.exists(conn, table)) {
+ conflicts.add(table);
+ }
+ }
+ return conflicts;
+ }
+
+ /**
+ * Checks the initializer dependencies set in the ".load"-file.
+ *
+ * @param loaders A list of loaders to the corresponding packages
+ * to-be-loaded
+ * @param sessionName Name of the session
+ * @return true on success, otherwise false
+ */
+ @Override
+ public boolean checkInitializerDependencies(final Loader[] loaders,
+ String sessionName) {
+ final List required = new ArrayList();
+ final List provided = new ArrayList();
+ addTo(required, InfoGetter.getRequiredInitializers(loaders));
+ required.removeAll(InfoGetter.getProvidedInitializers(loaders));
+ addTo(provided, InfoGetter.getProvidedInitializers(loaders));
+
+ final Session boot = session(sessionName);
+ final List missing = getMissing(boot, required);
+ final List conflicts = getConflicts(boot, provided);
+
+ if (!missing.isEmpty()) {
+ System.err.println("required initializers: " + missing);
+ return false;
+ }
+ if (!conflicts.isEmpty()) {
+ System.err.println("conflicting initializers: " + conflicts);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * [SUPPORT]
+ * Returns the session to the given name, if existing. If not, opens a new
+ * Session for the database-connection with the given name.
+ *
+ * used in: checkInitializerDependencies
+ *
+ * @return A session for the database-connection
+ */
+ private static Session session(String name) {
+ Session ssn = SessionManager.getSession(name);
+ if (ssn == null) {
+ String pdl = "/com/arsdigita/runtime/Initializer.pdl";
+ MetadataRoot root = new MetadataRoot();
+ PDLCompiler compiler = new PDLCompiler();
+ compiler.parse
+ (new InputStreamReader
+ (Load.class.getResourceAsStream(pdl)),
+ pdl);
+ compiler.emit(root);
+ ConnectionSource source = new DedicatedConnectionSource
+ (RuntimeConfig.getConfig().getJDBCURL());
+ ssn = SessionManager.open(name, root, source);
+ }
+ return ssn;
+ }
+
+ /**
+ * [SUPPORT]
+ * Returns a list of initializers, required by the initializers in the
+ * given list, which haven't been initialized yet, thus are missing.
+ *
+ * used in: checkInitializerDependencies
+ *
+ * @param ssn The session for the db-connection
+ * @param inits List of initializers
+ * @return List of missing initializers
+ */
+ private static List getMissing(Session ssn, List inits) {
+ List missing = new ArrayList();
+ for (Iterator it = inits.iterator(); it.hasNext(); ) {
+ String init = (String) it.next();
+ OID oid = new OID(ssn.getMetadataRoot().getObjectType(INIT), init);
+ if (ssn.retrieve(oid) == null) {
+ missing.add(init);
+ }
+ }
+ return missing;
+ }
+
+ /**
+ * [SUPPORT]
+ * Returns all initializers, provided by initializers in the given list,
+ * which have already been initialized, thus all conflicting initializers.
+ *
+ * used in: checkInitializerDependencies
+ *
+ * @param ssn The session for the db-connection
+ * @param inits List of initializers
+ * @return List of conflicting initializers
+ */
+ private static List getConflicts(Session ssn, List inits) {
+ List conflicts = new ArrayList();
+ for (Iterator it = inits.iterator(); it.hasNext(); ) {
+ String init = (String) it.next();
+ OID oid = new OID(ssn.getMetadataRoot().getObjectType(INIT), init);
+ if (ssn.retrieve(oid) != null) {
+ conflicts.add(init);
+ }
+ }
+ return conflicts;
+ }
+
+
+ /**
+ * Hidden class to get information from the loaders
+ */
+ private static class InfoGetter {
+ //Enum for the information type wished to retrieve.
+ private static enum InfoType {
+ REQ_TABLE, REQ_INITIALIZER, REQ_PACKAGE,
+ PROV_TABLE, PROV_INITIALIZER, PROV_PACKAGE;
+ }
+
+ /**
+ * Returns the required packages to the given loaders and is used,
+ * when checking for missing or conflicting packages.
+ *
+ * @param loaders List of loaders
+ * @return List of required packages
+ */
+ private static List getRequiredPackages(Loader[] loaders) {
+ return get(loaders, InfoType.REQ_PACKAGE);
+ }
+
+ /**
+ * Returns the provided packages to the given loaders and is used,
+ * when checking for missing or conflicting packages.
+ *
+ * @param loaders List of loaders
+ * @return List of provided packages
+ */
+ private static List getProvidedPackages(Loader[] loaders) {
+ return get(loaders, InfoType.PROV_PACKAGE);
+ }
+
+ /**
+ * Returns the required tables to the given loaders and is used when
+ * checking for missing or conflicting tables.
+ *
+ * @param loaders List of loaders
+ * @return List of required tables
+ */
+ private static List getRequiredTables(Loader[] loaders) {
+ return get(loaders, InfoType.REQ_TABLE);
+ }
+
+ /**
+ * Returns the provided tables to the given loaders and is used when
+ * checking for missing or conflicting tables.
+ *
+ * @param loaders List of loaders
+ * @return List of provided tables
+ */
+ private static List getProvidedTables(Loader[] loaders) {
+ return get(loaders, InfoType.PROV_TABLE);
+ }
+
+ /**
+ * Returns the required initializers to the given loaders and is used,
+ * when checking for missing or conflicting initializers.
+ *
+ * supports: checkInitializerDependencies
+ *
+ * @param loaders List of loaders
+ * @return List of required initializers
+ */
+ private static List getRequiredInitializers(Loader[] loaders) {
+ return get(loaders, InfoType.REQ_INITIALIZER);
+ }
+
+ /**
+ * Returns the provided initializers to the given loaders and is used,
+ * when checking for missing or conflicting initializers.
+ *
+ * supports: checkInitializerDependencies
+ *
+ * @param loaders List of loaders
+ * @return List of provided initializers
+ */
+ private static List getProvidedInitializers(Loader[] loaders) {
+ return get(loaders, InfoType.PROV_INITIALIZER);
+ }
+
+ /**
+ * Main-Getter, to retrieve the informations provided by the ".load"-file
+ * and stored in a loader.
+ *
+ * @param loaders List of loaders of the packages to be loaded
+ * @param informationType type of the information
+ * @return
+ */
+ private static List get(Loader[] loaders, InfoType infoType) {
+ ArrayList result = new ArrayList();
+
+ for (Loader loader : loaders) {
+ LoaderInfo info = loader.getInfo();
+ List c;
+ switch (infoType) {
+ case REQ_TABLE:
+ c = info.getRequiredTables();
+ break;
+ case REQ_INITIALIZER:
+ c = info.getRequiredInitializers();
+ break;
+ case REQ_PACKAGE:
+ c = info.getRequiredPackages();
+ break;
+ case PROV_TABLE:
+ c = info.getProvidedTables();
+ break;
+ case PROV_INITIALIZER:
+ c = info.getProvidedInitializers();
+ break;
+ case PROV_PACKAGE:
+ c = new ArrayList();
+ c.add(loader.getKey());
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "unknown type: " + infoType.toString());
+ }
+ addTo(result, c);
+ }
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ccm-core/src/com/arsdigita/packaging/Loader.java b/ccm-core/src/com/arsdigita/packaging/Loader.java
index 127aeb09e..5fb9b496a 100755
--- a/ccm-core/src/com/arsdigita/packaging/Loader.java
+++ b/ccm-core/src/com/arsdigita/packaging/Loader.java
@@ -22,6 +22,7 @@ import com.arsdigita.db.DbHelper;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.KernelExcursion;
import com.arsdigita.loader.PackageLoader;
+import com.arsdigita.packaging.LoadCenter.LoadType;
import com.arsdigita.persistence.DataAssociation;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.OID;
@@ -50,62 +51,101 @@ import org.apache.log4j.Logger;
/**
* Loader
*
- * Helper class for load which actually performs the loading of
- * the database schema and of the initial content.
+ * Helper class for load and unload which actually performs the loading and
+ * unloading of the database schema, the data and of the initial content.
*
- * @author Rafael H. Schloming <rhs@mit.edu>
+ * @author Rafael H. Schloming <rhs@mit.edu> tosmers;
* @version $Revision: #13 $ $Date: 2004/08/16 $
- * @version $Id: Loader.java 2115 2011-01-13 17:11:50Z pboy $
+ * @version $Id: Loader.java 2116 2015-04-15 14:18:40Z tosmers $
*/
class Loader {
private static final Logger s_log = Logger.getLogger(Loader.class);
private static final String INIT = "com.arsdigita.runtime.Initializer";
- public static Loader get(String pkg) {
+ private String m_key;
+ private LoaderInfo m_info;
+ private Checklist m_checks;
+ private List m_scripts;
+
+
+ /**
+ * Constructor. Creates a loader to the given parameters.
+ *
+ * @param key The corresponding package-key to the loader
+ * @param info The informations from the ".load"-file
+ * @param checks A Checklist
+ */
+ public Loader(String key, LoaderInfo info, Checklist checks,
+ LoadType scriptType) {
+ m_key = key;
+ m_info = info; //all the stuff form .load-file
+ m_checks = checks;
+ m_scripts = new ArrayList();
+ for (Iterator it = m_info.getDataScripts(scriptType).iterator();
+ it.hasNext();) {
+ String script = (String) it.next();
+ m_scripts.add(Classes.newInstance(script));
+ }
+ }
+
+ /**
+ * Gets a loader to the given package-key via an input-stream if
+ * a corresponding ".load"-file to the package-key exists. The
+ * loader contains the informations stored in the ".load"-file.
+ *
+ * @param pkg The package-key
+ * @return A Loader to the given package-key
+ */
+ public static Loader get(String pkg, LoadType scriptType) {
ClassLoader ldr = Loader.class.getClassLoader();
InputStream is = ldr.getResourceAsStream(pkg + ".load");
if (is == null) {
s_log.error(String.format("Failed to find '%s.load'.", pkg));
return null;
}
+ //Contains all relevante data from the .load-file.
LoaderInfo info = new LoaderInfo(is);
try {
is.close();
} catch (IOException e) {
throw new UncheckedWrapperException(e);
}
- return new Loader(pkg, info, Checklist.get(pkg));
- }
- private String m_key;
- private LoaderInfo m_info;
- private Checklist m_checks;
- private List m_scripts;
-
- public Loader(String key, LoaderInfo info, Checklist checks) {
- m_key = key;
- m_info = info;
- m_checks = checks;
- m_scripts = new ArrayList();
- for (Iterator it = m_info.getDataScripts().iterator();
- it.hasNext();) {
- String script = (String) it.next();
- m_scripts.add(Classes.newInstance(script));
- }
+ return new Loader(pkg, info, Checklist.get(pkg), scriptType);
}
+ /**
+ * Getter for the package-key.
+ *
+ * @return The package-key
+ */
public String getKey() {
return m_key;
}
+ /**
+ * Getter for the loader-informations.
+ *
+ * @return The loader-informations
+ */
public LoaderInfo getInfo() {
return m_info;
}
+ /**
+ * List of scripts for the loader, provided by the ".load"-file.
+ *
+ * @return A list of scripts
+ */
public List getScripts() {
return m_scripts;
}
+ /**
+ * Checks the schema, set in the ".load"-file.
+ *
+ * @return true on success, otherwise false
+ */
public boolean checkSchema() {
if (m_checks == null) {
return true;
@@ -114,6 +154,11 @@ class Loader {
}
}
+ /**
+ * Loads the schema, set in the ".load"-file.
+ *
+ * @param conn The connection to the database
+ */
public void loadSchema(Connection conn) {
int db = DbHelper.getDatabase(conn);
String dir = DbHelper.getDatabaseDirectory(db);
@@ -124,7 +169,29 @@ class Loader {
PackageLoader.load(conn, script + "/" + dir + "-create.sql");
}
}
+
+ /**
+ * Unloads the schema, set in the ".load"-file.
+ *
+ * @param conn The connection to the database
+ */
+ public void unloadSchema(Connection conn) {
+ int db = DbHelper.getDatabase(conn);
+ String dir = DbHelper.getDatabaseDirectory(db);
+ List scripts = m_info.getSchemaScripts();
+ for (Iterator it = scripts.iterator(); it.hasNext();) {
+ String script = (String) it.next();
+ s_log.info("Unloading schema for " + script);
+ PackageLoader.load(conn, script + "/" + dir + "-drop.sql");
+ }
+ }
+ /**
+ * Checks the data, set in the ".load"-file.
+ *
+ * @param ssn The session
+ * @return true on success, otherwise false
+ */
public boolean checkData(Session ssn) {
if (m_checks == null) {
return true;
@@ -133,6 +200,12 @@ class Loader {
}
}
+ /**
+ * Loads the data, set in the ".load"-file.
+ *
+ * @param ssn The session
+ * @param prd The ParameterReader
+ */
public void loadData(Session ssn, ParameterReader prd) {
final List inits = m_info.getProvidedInitializers();
CompoundInitializer ini = new CompoundInitializer();
@@ -149,10 +222,10 @@ class Loader {
// final ScriptContext ctx = new ScriptContext(ssn, loader);
final ScriptContext ctx = new ScriptContext(ssn, prd);
new KernelExcursion() {
-
+ @Override
protected void excurse() {
setEffectiveParty(Kernel.getSystemParty());
- for (Iterator it = m_scripts.iterator(); it.hasNext();) {
+ for (Iterator it = m_scripts.iterator(); it.hasNext(); ) {
Script script = (Script) it.next();
s_log.info("Running data loader " + script.getClass().
getName());
@@ -165,14 +238,54 @@ class Loader {
txn.commitTxn();
}
}
+
+ /**
+ * Unloads the data. Takes the data-unload script from the ".load"-file and
+ * implements a new KernelExcursion's excurse-method, in which the
+ * Script.java's run-method is called. This run-method is implemented by
+ * the AbstractContentTypeUnloader.java, which implements himself an other
+ * new KernelExcursion's excurse-method, calling the sweepTypes-method, the
+ * heart of the unloadData functionality.
+ *
+ * @param ssn The session to the database
+ */
+ public void unloadData(Session ssn) {
+ TransactionContext txn = ssn.getTransactionContext();
+ txn.beginTxn();
+
+ final ScriptContext ctx = new ScriptContext(ssn, null);
+ new KernelExcursion() {
+ @Override
+ protected void excurse() {
+ setEffectiveParty(Kernel.getSystemParty());
+ for (Iterator it = m_scripts.iterator(); it.hasNext(); ) {
+ Script script = (Script) it.next();
+ s_log.info("Running data unloader " + script.getClass().
+ getName());
+ script.run(ctx);
+ }
+ }
+ }.run();
+ if (txn.inTxn()) {
+ txn.commitTxn();
+ }
+ }
+
+ /**
+ * Loads the initializers, set in the ".load"-file. Creates a new data-
+ * object with an "oid" for every provided initializer and and add the
+ * required initializers to its requirements for data-associations.
+ *
+ * @param ssn The session
+ */
public void loadInits(final Session ssn) {
final TransactionContext txn = ssn.getTransactionContext();
txn.beginTxn();
final List inits = m_info.getProvidedInitializers();
final List required = m_info.getRequiredInitializers();
- for (Iterator it = inits.iterator(); it.hasNext();) {
+ for (Iterator it = inits.iterator(); it.hasNext(); ) {
String init = (String) it.next();
DataObject dataobject = ssn.create(new OID(INIT, init));
DataAssociation da =
@@ -187,8 +300,46 @@ class Loader {
txn.commitTxn();
}
}
+
+ /**
+ * Unloads the initializers, set in the ".load"-file". Removes for every
+ * provided initializer the required initializers form the requirements in
+ * the data-association and deletes the data object to that provided
+ * initializer.
+ *
+ * @param ssn The session
+ */
+ public void unloadInits(final Session ssn) {
+ final TransactionContext txn = ssn.getTransactionContext();
+ txn.beginTxn();
+
+ final List inits = m_info.getProvidedInitializers();
+ final List required = m_info.getRequiredInitializers();
+ for (Iterator it = inits.iterator(); it.hasNext(); ) {
+ String init = (String) it.next();
+ OID oid = new OID(INIT, init);
+ DataObject dataObject = ssn.retrieve(oid);
+ DataAssociation da =
+ (DataAssociation) dataObject.get("requirements");
+ for (Iterator reqIt = required.iterator(); reqIt.hasNext(); ) {
+ String reqInit = (String) reqIt.next();
+ da.remove(ssn.retrieve(new OID(INIT, reqInit)));
+ }
+ ssn.delete(oid);
+ }
+
+ if (txn.inTxn()) {
+ txn.commitTxn();
+ }
+ }
- Set getRequired() {
+ /**
+ * Returns all tables, initializers and packages required by this loader.
+ * Used in Load.sort
+ *
+ * @return A set of required things like tables, initializers and packages
+ */
+ public Set getRequired() {
Set result = new HashSet();
result.addAll(m_info.getRequiredTables());
result.addAll(m_info.getRequiredInitializers());
@@ -196,7 +347,13 @@ class Loader {
return result;
}
- Set getProvided() {
+ /**
+ * Returns all tables and initializers provided by this loader.
+ * Used in Load.sort
+ *
+ * @return A set of provided things like tables and initializers.
+ */
+ public Set getProvided() {
Set result = new HashSet();
result.addAll(m_info.getProvidedTables());
result.addAll(m_info.getProvidedInitializers());
diff --git a/ccm-core/src/com/arsdigita/packaging/LoaderInfo.java b/ccm-core/src/com/arsdigita/packaging/LoaderInfo.java
index fd1d0cd7c..94c3092eb 100755
--- a/ccm-core/src/com/arsdigita/packaging/LoaderInfo.java
+++ b/ccm-core/src/com/arsdigita/packaging/LoaderInfo.java
@@ -18,6 +18,7 @@
*/
package com.arsdigita.packaging;
+import com.arsdigita.packaging.LoadCenter.LoadType;
import com.arsdigita.xml.XML;
import java.io.InputStream;
import java.util.ArrayList;
@@ -42,6 +43,8 @@ class LoaderInfo {
private List m_providedInitializers = new ArrayList();
private List m_schemaScripts = new ArrayList();
private List m_dataScripts = new ArrayList();
+ private List m_dataLoadScripts = new ArrayList();
+ private List m_dataUnloadScripts = new ArrayList();
private List m_requiredPackages = new ArrayList();
/**
@@ -76,10 +79,19 @@ class LoaderInfo {
return m_schemaScripts;
}
- public List getDataScripts() {
+ public List getDataScripts(LoadType scriptType) {
+ switch (scriptType) {
+ case LOAD:
+ m_dataScripts = m_dataLoadScripts;
+ break;
+ case UNLOAD:
+ m_dataScripts = m_dataUnloadScripts;
+ break;
+ }
return m_dataScripts;
}
+ //Strings correspond to the tag names in the ".load"-files
private static final String PROVIDES = "provides";
private static final String REQUIRES = "requires";
private static final String TABLE = "table";
@@ -87,7 +99,8 @@ class LoaderInfo {
private static final String PACKAGE = "package";
private static final String SCRIPTS = "scripts";
private static final String SCHEMA = "schema";
- private static final String DATA = "data";
+ private static final String DATA_LOAD = "data";
+ private static final String DATA_UNLOAD = "data-unload";
// attributes
private static final String NAME = "name";
@@ -98,6 +111,7 @@ class LoaderInfo {
private List m_context = new ArrayList();
+ @Override
public void startElement(String uri, String name, String qn,
Attributes attrs) {
if (name.equals(TABLE)) {
@@ -165,7 +179,7 @@ class LoaderInfo {
m_schemaScripts.add(dir);
}
- if (name.equals(DATA)) {
+ if (name.equals(DATA_LOAD)) {
if (!m_context.contains(SCRIPTS)) {
throw new IllegalStateException
("data element must appear inside scripts");
@@ -177,12 +191,28 @@ class LoaderInfo {
("data element requires class attribute");
}
- m_dataScripts.add(klass);
+ m_dataLoadScripts.add(klass);
}
+
+ if (name.equals(DATA_UNLOAD)) {
+ if (!m_context.contains(SCRIPTS)) {
+ throw new IllegalStateException
+ ("data element must appear inside scripts");
+ }
+ String klass = attrs.getValue(uri, CLASS);
+ if (klass == null) {
+ throw new IllegalStateException
+ ("data element requires class attribute");
+ }
+
+ m_dataUnloadScripts.add(klass);
+ }
+
m_context.add(name);
}
+ @Override
public void endElement(String uri, String name, String qn) {
m_context.remove(m_context.lastIndexOf(name));
}
diff --git a/ccm-core/src/com/arsdigita/packaging/MasterTool.java b/ccm-core/src/com/arsdigita/packaging/MasterTool.java
index a68202a89..101f1b332 100755
--- a/ccm-core/src/com/arsdigita/packaging/MasterTool.java
+++ b/ccm-core/src/com/arsdigita/packaging/MasterTool.java
@@ -39,7 +39,7 @@ import java.util.Map;
* provided script implementation is ccm, a shell script (sh and bat) backed
* by some PERL scripts, located in the tools directory of CCM trunk.
*
- * @author Justin Ross <jross@redhat.com>
+ * @author Justin Ross <jross@redhat.com> tosmers;
* @version $Id: MasterTool.java 2031 2009-12-10 03:34:04Z terry $
*/
public class MasterTool {
diff --git a/ccm-core/src/com/arsdigita/packaging/Set.java b/ccm-core/src/com/arsdigita/packaging/Set.java
index b9e7d32c4..d7a2dd648 100755
--- a/ccm-core/src/com/arsdigita/packaging/Set.java
+++ b/ccm-core/src/com/arsdigita/packaging/Set.java
@@ -93,8 +93,14 @@ class Set extends Command {
ConfigRegistry reg = new ConfigRegistry();
Config config = new Config(reg);
config.load(System.err);
-
- Properties props = Load.props(line.getArgs());
+
+ Properties props;
+ try {
+ props = Load.argsToProperties(line.getArgs());
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ return false;
+ }
boolean valid = true;
for (Iterator it = props.keySet().iterator(); it.hasNext(); ) {
diff --git a/ccm-core/src/com/arsdigita/packaging/Unload.java b/ccm-core/src/com/arsdigita/packaging/Unload.java
index 9a2b2279e..3dfc080cc 100755
--- a/ccm-core/src/com/arsdigita/packaging/Unload.java
+++ b/ccm-core/src/com/arsdigita/packaging/Unload.java
@@ -18,12 +18,17 @@
*/
package com.arsdigita.packaging;
-import com.arsdigita.runtime.CCMResourceManager;
-import com.arsdigita.util.Files;
-
-import java.io.File;
-import java.io.FileFilter;
+import com.arsdigita.loader.PackageLoader;
+import com.arsdigita.persistence.Session;
+import com.arsdigita.persistence.SessionManager;
+import com.arsdigita.runtime.RuntimeConfig;
+import com.arsdigita.runtime.Runtime;
+import com.arsdigita.util.jdbc.Connections;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import org.apache.commons.cli.CommandLine;
@@ -35,7 +40,7 @@ import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Logger;
/**
- * PackageTool worker class, implements the "load" command.
+ * PackageTool worker class, implements the "unload" command.
*
* It is called by class MasterTols and unloads the database schema and initial
* content.
@@ -47,31 +52,78 @@ import org.apache.log4j.Logger;
* PACKAGE-KEYS one or more space separated names of modules (package-key, e.g.
* ccm-cms-types-event) which should be loaded into database and
* configuration registry
- * Options: [--config] Removes entries in the registry (configuration repo)
- * if set prevents any of the three data load steps
- * described before to be executed!
+ * Options: [-usage] Display a usage message for load command
+ * [-help|--help] Display a help message for load command
+ * [--packagekeys-file FILE] Reads list of packages to load from
+ * File (in addition to command line)
+ * [--schema] Loads just the schema for a package into the
+ * database, no data, no initializer
+ * [--data] Loads just data into the database, schema must
+ * exist already, initializers are not recorded
+ * [--init] Records the initializer and classes into database
+ * [--config] Removes entries in the registry (configuration
+ * repo) if set prevents any of the three data
+ * load steps described before to be executed!
+ * [--recursive] Recursively load required packages
*
- * @author Rafael H. Schloming <rhs@mit.edu> tosmers;
- * @version $Revision: #7 $ $Date: 2015/03/29 $
- * @version $Id: Unload.java 736 2015-03-29 14:22:20Z tosmers $
+ * @author Tobias Osmers
+ * @version $Revision: #11 $ $Date: 2015/04/27 $
*/
-class Unload extends Command {
-
+class Unload extends Command implements LoadCenter {
+
+ private static final LoadCenterDelegate delegate = new LoadCenterDelegate();
+
private static final Logger logger = Logger.getLogger(Unload.class);
-
private static final Options OPTIONS = new Options();
+
+ //for OLD unloadConfig Method
+ private static final Set EXCLUDE = new HashSet();
+
+ //Initializes all option-flags.
static {
logger.debug("Static initalizer starting...");
+ OPTIONS.addOption
+ (OptionBuilder
+ .hasArg()
+ .withLongOpt("packagekeys-file")
+ .withArgName("FILE")
+ .withDescription(
+ "Use PACKAGE_KEYS from FILE instead of command line")
+ .create());
OPTIONS.addOption
(OptionBuilder
.hasArg(false)
.withLongOpt("config")
.withDescription("Unload configuration")
.create());
+ OPTIONS.addOption
+ (OptionBuilder
+ .hasArg(false)
+ .withLongOpt("schema")
+ .withDescription("Unload schema")
+ .create());
+ OPTIONS.addOption
+ (OptionBuilder
+ .hasArg(false)
+ .withLongOpt("data")
+ .withDescription("Unload data")
+ .create());
+ OPTIONS.addOption
+ (OptionBuilder
+ .hasArg(false)
+ .withLongOpt("init")
+ .withDescription("Unload initializers")
+ .create());
+// OPTIONS.addOption
+// (OptionBuilder
+// .hasArg(false)
+// .withLongOpt("recursive")
+// .withDescription("Recursively load required packages")
+// .create());
logger.debug("Static initalizer finished.");
}
- private static final Set EXCLUDE = new HashSet();
+ //Initializes all excluded files.
static {
logger.debug("Static initalizer starting...");
EXCLUDE.add("resin.conf");
@@ -90,12 +142,16 @@ class Unload extends Command {
}
/**
- * Invoked from the central tool "MasterTool" to execute the load process.
+ * Invoked from the central tool "MasterTool" to execute the unload process.
*
- * @param args
- * @return
+ * @param args The parameters and option-flags
+ * @return true if successful, false otherwise
*/
+ @Override
public boolean run(String[] args) {
+
+ //Takes the option-set and the arguments and parses
+ //them into a command-line
CommandLine line;
try {
line = new PosixParser().parse(OPTIONS, args);
@@ -104,27 +160,258 @@ class Unload extends Command {
return false;
}
- String[] packages = line.getArgs();
- if (packages.length == 0) {
- usage(OPTIONS, System.err);
+ //[--usage || --help]
+ //If set, prints an info-output and returns the function
+ //with true
+ if (line.hasOption("usage") || line.hasOption("help")) {
+ usage(OPTIONS, System.out, "PACKAGE-KEYS");
+ return true;
+ }
+
+ //Gets all packages which will be unloaded and assures
+ //that this list is not empty.
+ List packages;
+ try {
+ packages = getAllPackages(line);
+ if (packages.isEmpty()) {
+ usage(OPTIONS, System.err, "PACKAGE-KEYS");
+ return false;
+ }
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
return false;
}
-
- if (line.hasOption("config")) {
- // XXX: This just deletes everything.
- File conf = CCMResourceManager.getConfigDirectory();
- File[] files = conf.listFiles(new FileFilter() {
- public boolean accept(File file) {
- return !EXCLUDE.contains(file.getName());
- }
- });
-
- for (int i = 0; i < files.length; i++) {
- Files.delete(files[i]);
- }
+
+ //Gets all unloaders corresponding to the packages which
+ //will be unloaded.
+ Loader[] unloaders;
+ try {
+ unloaders = getAllLoaders(line, packages, LoadType.UNLOAD);
+ } catch (Error e) {
+ System.err.println(e.getMessage());
+ return false;
}
-
- return true;
+
+ //Determines if all steps have to be performed.
+ final boolean all = hasAllOptions(line);
+
+ //Checks for existence and accessibility of a database.
+ if (!checkDatabase()) {
+ return false;
+ }
+
+ Connection conn = Connections.acquire(
+ RuntimeConfig.getConfig().getJDBCURL());
+ Session ssn = null;
+
+ //Unload
+ boolean result = true;
+ if (all || line.hasOption("init")) {
+ result &= unloadInits(conn, ssn, unloaders);
+ }
+ //TODO: Recursivly changing the reading of the ExternalLinkUnloader.java
+ if (all || line.hasOption("data")) {
+ result &= unloadData(ssn, unloaders);
+ }
+ //Finished
+ if (all || line.hasOption("schema")) {
+ result &= unloadSchema(conn, unloaders);
+ }
+ //Finished
+ if (all || line.hasOption("config")) {
+ //Removes the configurations for the packages to be unloaded.
+ result &= unloadConfig(packages);
+ //result &= unloadConfig(); --OLD
+ }
+
+ return result;
}
-}
+ /**
+ * Gets all packages to be unloaded either from the command-line or a file,
+ * if the option flag [--packagekeys-file FILE] has been set and puts them
+ * in a list of packages (by their package-keys).
+ *
+ * @param line The command-line with all options and arguments
+ * @return The list of packages to be unloaded
+ * @throws IOException
+ */
+ @Override
+ public List getAllPackages(CommandLine line) throws IOException {
+ return delegate.getAllPackages(line);
+ }
+
+ /**
+ * Gets all loaders to the given package-list and sorts them before re-
+ * turning. Creates a map that assigns to every package-key an equivalent
+ * loader. This loader contains a bunch of informations (required,
+ * provided, scripts) provided by an ".load"-file. Then all loaders from
+ * the map (pkg-key -> loader) are composed into an array of loaders and
+ * sorted.
+ *
+ * @param line The command-line with all options and arguments
+ * @param packages The list of packages to be loaded
+ * @param loadType Weather packages are been loaded or unloaded
+ * @return A sorted list of loaders
+ * @throws Error
+ */
+ @Override
+ public Loader[] getAllLoaders(CommandLine line, List packages,
+ LoadType loadType) throws Error {
+ return delegate.getAllLoaders(line, packages, loadType);
+ }
+
+ /**
+ * Determines if all steps (config, schema, data, inits) have to be
+ * performed.
+ *
+ * @param line The command-line with all options and arguments
+ * @return True if all options need to be performed
+ */
+ @Override
+ public boolean hasAllOptions(CommandLine line) {
+ return delegate.hasAllOptions(line);
+ }
+
+ /**
+ * Checks existence and accessibility of the database and does a rollback
+ * if necessary.
+ *
+ * @return True on success, otherwise false
+ */
+ @Override
+ public boolean checkDatabase() {
+ return delegate.checkDatabase();
+ }
+
+ /**
+ * Sets back the configuration to the original packages. Goes through
+ * all packages from the configuration-context and removes the ones
+ * contained in the list of packages which will be loaded.
+ *
+ * @param config The configuration
+ * @param packages The packages to be loaded
+ * @return True on success, otherwise false
+ */
+ @Override
+ public boolean rollbackConfig(Config config, List packages) {
+ return delegate.rollbackConfig(config, packages);
+ }
+
+ /**
+ * Checks the initializer dependencies set in the ".load"-file.
+ *
+ * @param loaders A list of loaders to the corresponding packages
+ * to-be-loaded
+ * @param sessionName Name of the session
+ * @return true on success, otherwise false
+ */
+ @Override
+ public boolean checkInitializerDependencies(final Loader[] loaders,
+ String sessionName) {
+ return delegate.checkInitializerDependencies(loaders, sessionName);
+ }
+
+ /**
+ * Unloads the initializers. needed?
+ *
+ * @param ssn The session for the db-connection
+ * @param unloaders The list of unloaders from the packages to be unloaded
+ * @return true on success, otherwise false
+ */
+ private boolean unloadInits(Connection conn, Session ssn, Loader[] unloaders) {
+ if (ssn == null) {
+ new Runtime().startup();
+ ssn = SessionManager.getSession();
+ }
+ boolean passed = true;
+ if (PackageLoader.exists(conn, "inits")) {
+ passed &= checkInitializerDependencies(unloaders, "unloader");
+ if (!passed) {
+ return false;
+ }
+ }
+ for (Loader unloader : unloaders) {
+ unloader.unloadInits(ssn);
+ }
+ return true;
+ }
+
+ /**
+ * Unloads the data.
+ *
+ * @param ssn The session for the db-connection
+ * @param unloaders The list of unloaders from the packages to be unloaded
+ * @return true on success, otherwise false
+ */
+ private boolean unloadData(Session ssn, Loader[] unloaders) {
+ if (ssn == null) {
+ new Runtime().startup();
+ ssn = SessionManager.getSession();
+ }
+ boolean passed = true;
+ for (Loader unloader : unloaders) {
+ passed &= unloader.checkData(ssn);
+ if (!passed) {
+ return false;
+ }
+ unloader.unloadData(ssn);
+ }
+ return true;
+ }
+
+ /**
+ * Unloads the schema.
+ *
+ * @param conn The connection to the database
+ * @param unloaders The list of unloaders from the packages to be unloaded
+ * @return true on success, otherwise false
+ */
+ private boolean unloadSchema(Connection conn, Loader[] unloaders) {
+ boolean passed = true;
+ for (Loader unloader : unloaders) {
+ passed &= unloader.checkSchema();
+ if (!passed) {
+ return false;
+ }
+ unloader.unloadSchema(conn);
+ }
+ try {
+ conn.commit();
+ } catch (SQLException e) {
+ System.err.println(e.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Unloads the configuration by running a rollback.
+ *
+ * @param packages The packages to be loaded
+ * @return true on success, otherwise false
+ */
+ private boolean unloadConfig(List packages) {
+ return rollbackConfig(null, packages);
+ }
+
+ /**
+ * OLD VERSION
+ * Unloads the configuration. Useful???????
+ *
+ * @return true on success, otherwise false
+ */
+// private boolean unloadConfig() {
+// File conf = CCMResourceManager.getConfigDirectory();
+// File[] files = conf.listFiles(new FileFilter() {
+// public boolean accept(File file) {
+// return !EXCLUDE.contains(file.getName());
+// }
+// });
+//
+// for (int i = 0; i < files.length; i++) {
+// Files.delete(files[i]);
+// }
+// return true;
+// }
+}
\ No newline at end of file
diff --git a/ccm-core/src/com/arsdigita/packaging/Upgrade.java b/ccm-core/src/com/arsdigita/packaging/Upgrade.java
index 01fe4f053..77f1fe566 100755
--- a/ccm-core/src/com/arsdigita/packaging/Upgrade.java
+++ b/ccm-core/src/com/arsdigita/packaging/Upgrade.java
@@ -188,10 +188,10 @@ class Upgrade extends Command {
String[] params = line.getOptionValues("parameters");
LinkedList ll = new LinkedList();
if (params != null) {
- for (int i = 0; i < params.length; i++) {
- String[] split = StringUtils.split(params[i], ',');
- for (int j = 0; j < split.length; j++) {
- ll.add(split[j]);
+ for (String param : params) {
+ String[] split = StringUtils.split(param, ',');
+ for (String split1 : split) {
+ ll.add(split1);
}
}
}
diff --git a/ccm-core/src/com/arsdigita/runtime/AbstractScript.java b/ccm-core/src/com/arsdigita/runtime/AbstractScript.java
index 04e3c748e..fe7fcea27 100755
--- a/ccm-core/src/com/arsdigita/runtime/AbstractScript.java
+++ b/ccm-core/src/com/arsdigita/runtime/AbstractScript.java
@@ -49,6 +49,7 @@ public abstract class AbstractScript extends AbstractParameterContext
* @param context the context in which to run the script
*/
+ @Override
public abstract void run(ScriptContext context);
}
diff --git a/tools-ng/ecdc/scriptlib/build-ccm.xml b/tools-ng/ecdc/scriptlib/build-ccm.xml
index 7d1ad5b15..b6592c567 100644
--- a/tools-ng/ecdc/scriptlib/build-ccm.xml
+++ b/tools-ng/ecdc/scriptlib/build-ccm.xml
@@ -242,7 +242,64 @@
-
+
+
+
+ Unloading bundle from ${this.bundle.folder} from ${ccmhome}
+
+
+
+
+
+
+
+
+
+
+ Unload ${applications} without further configuration specifications but using build in defaults.
+
+
+
+
+
+
+
+
+
+ Unload initializers for ${applications} (--init)
+
+
+
+
+
+
+
+
+ Unload schema only for ${applications} (--schema)
+
+
+
+
+
+
+
+
+ Unregisters configuration from ${this.bundle.folder} for ${applications} from registry
+
+
+
+
+
+