[FEATURE][UPDATE]

Die Funktionalität ein Modul über "ccm unload..." zu deinstallieren ist jetzt verfügtbar (Achtung! funktioniert noch nicht). Dafür vorgenommene Modifikationen:
- neue Klasse Unload.java, die die Funktion des "ccm unload" bereitstellt
- neue Klassen LoadCenter.java und LoadCenterDelegate.java die das Designpattern "Delegate" umsetzen, um Coderedundanz zwischen Load.java und Unload.java zu beseitigen
- neue sql-skripte im Modul ExternalLink oracle-se-drop.sql und postgres-drop.sql, zum Löschung der ExternalLink spezifischen Tabellen in der Datenbank
- sämtliche Codemodifikationen und Java-Doc-Ergänzungen in beteiligten Klassen für die unload-Prozedur
- neue Klasse ExternalLinkUnloader.java (bisher noch wenig/keine Funktionalität) und AbstractContentTypeUnloader.java, die zusammen dafür sorgen sollen, die ContentTyp-Instanzen (z.B. von ExternalLink) aus den Tabellen der Datenbank zu entfernen. (-> work in progress)
- Ergänzung des unload-Datenskripts in ccm-cms-types-externallink.load
- Ergänzung der build-ccm.xml um die unload-Befehle

[WORK IN PROGRESS]
Das Entfernen von Instanzen derjenigen ContentTypes aus den Tabellen der Datenbank, die deinstalliert werden sollen über "ccm unload".

git-svn-id: https://svn.libreccm.org/ccm/trunk@3414 8810af33-2d31-482b-a856-94f89814c4df
master
tosmers 2015-05-18 18:20:18 +00:00
parent 431f2b7040
commit 44d378da59
26 changed files with 2214 additions and 600 deletions

View File

@ -0,0 +1,20 @@
--
-- Copyright (C) 2005 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
--
-- $Id: oracle-se-drop.sql 1 2015-04-15 13:47:30Z tosmers $
@ ddl/oracle-se/drop-constraints.sql
@ ddl/oracle-se/drop-tables.sql

View File

@ -0,0 +1,22 @@
--
-- Copyright (C) 2005 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
--
-- $Id: postgres-drop.sql 1 2015-04-15 13:47:30Z tosmers $
begin;
\i ddl/postgres/drop-constraints.sql
\i ddl/postgres/drop-tables.sql
end;

View File

@ -12,5 +12,6 @@
<scripts> <scripts>
<schema directory="ccm-cms-types-externallink"/> <schema directory="ccm-cms-types-externallink"/>
<data class="com.arsdigita.cms.contenttypes.ExternalLinkLoader"/> <data class="com.arsdigita.cms.contenttypes.ExternalLinkLoader"/>
<data-unload class="com.arsdigita.cms.contenttypes.ExternalLinkUnloader"/>
</scripts> </scripts>
</load> </load>

View File

@ -33,7 +33,7 @@ import java.math.BigDecimal;
* *
* The item stores a description text about the link/resource and an URL. * The item stores a description text about the link/resource and an URL.
* *
* @author tosmers * @author Tobias Osmers <tosmers@uni-bremen.de>
* @version $Revision: #1 $ $Date: 2015/02/22 $ * @version $Revision: #1 $ $Date: 2015/02/22 $
*/ */
public class ExternalLink extends ContentPage { public class ExternalLink extends ContentPage {
@ -105,7 +105,7 @@ public class ExternalLink extends ContentPage {
/** /**
* Creates a new domain object for an subtype of ExternalLink. * Creates a new domain object for an subtype of ExternalLink.
* *
* @param type The subtype for witch a new domain object will be created. * @param type The subtype for which a new domain object will be created.
*/ */
public ExternalLink(final String type) { public ExternalLink(final String type) {
super(type); super(type);
@ -159,7 +159,7 @@ public class ExternalLink extends ContentPage {
/** /**
* Set the value weather the comment should be shown. * Set the value weather the comment should be shown.
* *
* @param showComment The value weather the comment should be shown. * @param show The value weather the comment should be shown.
*/ */
public void setShowComment(final String show) { public void setShowComment(final String show) {
set(SHOW_COMMENT, show); set(SHOW_COMMENT, show);

View File

@ -29,7 +29,7 @@ import com.arsdigita.cms.contenttypes.ContentTypeInitializer;
* This is done by runtimeRuntime startup method which runs the init() methods * This is done by runtimeRuntime startup method which runs the init() methods
* of all initializers (this one just using the parent implementation). * of all initializers (this one just using the parent implementation).
* *
* @author tosmers * @author Tobias Osmers <tosmers@uni-bremen.de>
* @version $Revision: #1 $ $Date: 2015/02/22 $ * @version $Revision: #1 $ $Date: 2015/02/22 $
*/ */
public class ExternalLinkInitializer extends ContentTypeInitializer { public class ExternalLinkInitializer extends ContentTypeInitializer {

View File

@ -39,7 +39,7 @@ import java.io.InputStream;
* from AbstractConfig). They will (and can) not be persisted into * from AbstractConfig). They will (and can) not be persisted into
* an registry object (file). * an registry object (file).
* *
* @author tosmers * @author Tobias Osmers <tosmers@uni-bremen.de>
* @version $Revision: #1 $ $Date: 2015/02/22 $ * @version $Revision: #1 $ $Date: 2015/02/22 $
*/ */
public class ExternalLinkLoader extends AbstractContentTypeLoader { public class ExternalLinkLoader extends AbstractContentTypeLoader {
@ -68,7 +68,7 @@ public class ExternalLinkLoader extends AbstractContentTypeLoader {
} }
/** /**
* Provides the of ExternalLink contenttype property definitions. * Provides the ExternalLink's contenttype property definitions.
* *
* The file defines the types name as displayed in content center * The file defines the types name as displayed in content center
* select box and the authoring steps. These are loaded into database. * select box and the authoring steps. These are loaded into database.

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2015 University of Bremen. 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.cms.contenttypes;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Tobias Osmers <tosmers@uni-bremen.de>
* @version $Revision: #1 $ $Date: 2015/04/08 $
*/
public class ExternalLinkUnloader extends AbstractContentTypeUnloader {
/**
* Defines the xml file containing the ExternalLink content types
* property definitions.
*/
private static final String[] TYPES = {
"/WEB-INF/content-types/com/arsdigita/cms/contenttypes/ExternalLink.xml"
};
/**
* Provides the ExternalLink's contenttype property definitions.
*
* The file defines the types name as displayed in content center
* select box and the authoring steps. These are loaded into database.
*
* Implements the method of the parent class.
*
* @return String array of fully qualified file names
*/
@Override
public String[] getTypes() {
return TYPES;
}
/**
* ??????????
*
* @return
*/
public List getAllInstances() {
return new ArrayList();
}
}

View File

@ -33,7 +33,7 @@ import com.arsdigita.toolbox.ui.DomainObjectPropertySheet;
* Authoring step to view/edit the simple attributes of the * Authoring step to view/edit the simple attributes of the
* ExternalLink content type (and its subclasses). * ExternalLink content type (and its subclasses).
* *
* @author tosmers * @author Tobias Osmers <tosmers@uni-bremen.de>
* @version $Revision: #1 $ $Date: 2015/02/22 $ * @version $Revision: #1 $ $Date: 2015/02/22 $
*/ */
public class ExternalLinkPropertiesStep extends SimpleEditStep { public class ExternalLinkPropertiesStep extends SimpleEditStep {

View File

@ -41,7 +41,7 @@ import com.arsdigita.cms.ui.authoring.BasicPageForm;
* <br /> * <br />
* This form can be extended to create forms for ExternalLink subclasses. * This form can be extended to create forms for ExternalLink subclasses.
* *
* @author tosmers * @author Tobias Osmers <tosmers@uni-bremen.de>
* @version $Revision: #1 $ $Date: 2015/02/22 $ * @version $Revision: #1 $ $Date: 2015/02/22 $
*/ */
public class ExternalLinkPropertyForm extends BasicPageForm public class ExternalLinkPropertyForm extends BasicPageForm

View File

@ -28,7 +28,7 @@ import com.arsdigita.globalization.GlobalizedMessage;
* globalize methods and forwards to GlobalizedMessage, shortening the * globalize methods and forwards to GlobalizedMessage, shortening the
* method invocation in the various application classes. * method invocation in the various application classes.
* *
* @author tosmers * @author Tobias Osmers <tosmers@uni-bremen.de>
* @version $Revision: #1 $ $Date: 2015/02/22 $ * @version $Revision: #1 $ $Date: 2015/02/22 $
*/ */
public class ExternalLinkGlobalizationUtil implements Globalized { public class ExternalLinkGlobalizationUtil implements Globalized {

View File

@ -65,10 +65,12 @@ import org.apache.log4j.Logger;
*/ */
public abstract class AbstractContentTypeLoader extends PackageLoader { public abstract class AbstractContentTypeLoader extends PackageLoader {
/** Internal logger instance to faciliate debugging. Enable logging output /**
* Internal logger instance to faciliate debugging. Enable logging output
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment * by editing /WEB-INF/conf/log4j.properties int hte runtime environment
* and set com.arsdigita.cms.contenttypes.AbstractContentTypeLoader=DEBUG * and set com.arsdigita.cms.contenttypes.AbstractContentTypeLoader=DEBUG
* by uncommenting or adding the line. */ * by uncommenting or adding the line.
*/
private static final Logger s_log = Logger.getLogger( private static final Logger s_log = Logger.getLogger(
AbstractContentTypeLoader.class); AbstractContentTypeLoader.class);
@ -77,7 +79,7 @@ public abstract class AbstractContentTypeLoader extends PackageLoader {
* this method any required parameters registered by the noargs * this method any required parameters registered by the noargs
* constructer should be set. * constructer should be set.
* *
* Overwrites the parent's class abstract method adding the tast specific * Overwrites the parent's class abstract method adding the task specific
* createTypes() method. * createTypes() method.
* *
* @param ctx * @param ctx
@ -97,8 +99,12 @@ public abstract class AbstractContentTypeLoader extends PackageLoader {
} }
/** /**
* 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 adds all the content-types stored in the list
* to the sections in that dataCollection.
* *
* @param ctx * @param ctx The context to the unload-script
*/ */
private void createTypes(ScriptContext ctx) { private void createTypes(ScriptContext ctx) {
@ -111,13 +117,12 @@ public abstract class AbstractContentTypeLoader extends PackageLoader {
List types = handler.getContentTypes(); List types = handler.getContentTypes();
Session ssn = ctx.getSession(); Session ssn = ctx.getSession();
DataCollection sections = ssn.retrieve(ContentSection DataCollection sections = ssn.retrieve(
.BASE_DATA_OBJECT_TYPE); ContentSection.BASE_DATA_OBJECT_TYPE);
while (sections.next()) { while (sections.next()) {
ContentSection section = (ContentSection) ContentSection section = (ContentSection)
DomainObjectFactory.newInstance( DomainObjectFactory.newInstance(sections.getDataObject());
sections.getDataObject());
if (!isLoadableInto(section)) { if (!isLoadableInto(section)) {
continue; continue;
} }
@ -176,7 +181,8 @@ public abstract class AbstractContentTypeLoader extends PackageLoader {
* content types's. * content types's.
* Must be implemented by each content type loader to provide its * Must be implemented by each content type loader to provide its
* specific definition files. * specific definition files.
* @return *
* @return This content type's property definitions through the ".xml"-file
*/ */
protected abstract String[] getTypes(); protected abstract String[] getTypes();

View File

@ -0,0 +1,170 @@
/*
* 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.cms.contenttypes;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.ContentType;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.KernelExcursion;
import com.arsdigita.loader.PackageLoader;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.Session;
import com.arsdigita.runtime.ScriptContext;
import com.arsdigita.xml.XML;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
/**
*
*
* @author Tobias Osmers <tosmers@uni-bremen.de>
* @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
* <pre>
* "/WEB-INF/content-types/com/arsdigita/cms/contenttypes/Event.xml"
* </pre>
* 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.
*
* <p>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()}.</p>
*
* <p>The default implementation returns an empty list.</p>
*
* @post return != null
*/
protected List getContentSections() {
return java.util.Collections.EMPTY_LIST;
}
}

View File

@ -116,8 +116,7 @@ public abstract class ContentTypeInitializer extends CompoundInitializer {
new ContentPageMetadataProvider()); new ContentPageMetadataProvider());
final String[] stylesheets = getStylesheets(); final String[] stylesheets = getStylesheets();
for (int i = 0; i < stylesheets.length; i++) { for (String stylesheet : stylesheets) {
String stylesheet = stylesheets[i];
ContentType.registerXSLFile(type, stylesheet); ContentType.registerXSLFile(type, stylesheet);
} }
} catch (com.arsdigita.domain.DataObjectNotFoundException e) { } 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 * Has to be overwritten by each specific content type to provide its
* TraversalXML if it uses one. * 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. * to traversal adapter.
*/ */
public String getTraversalXML() { public String getTraversalXML() {

View File

@ -46,6 +46,7 @@ public abstract class KernelExcursion implements Runnable {
private static final Logger s_log = Logger.getLogger private static final Logger s_log = Logger.getLogger
(KernelExcursion.class); (KernelExcursion.class);
@Override
public final void run() { public final void run() {
s_log.debug("Running excursion"); s_log.debug("Running excursion");

View File

@ -54,6 +54,14 @@ public abstract class PackageLoader extends AbstractScript {
private final static Logger s_log = Logger.getLogger(PackageLoader.class); 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) { public static boolean exists(Connection conn, String table) {
try { try {
DatabaseMetaData md = conn.getMetaData(); DatabaseMetaData md = conn.getMetaData();
@ -100,6 +108,7 @@ public abstract class PackageLoader extends AbstractScript {
public static void load(Connection conn, String script) { public static void load(Connection conn, String script) {
SQLLoader loader = new SQLLoader(conn) { SQLLoader loader = new SQLLoader(conn) {
@Override
protected Reader open(String name) { protected Reader open(String name) {
String resourceName = name.replace('\\', '/'); String resourceName = name.replace('\\', '/');
ClassLoader cload = getClass().getClassLoader(); ClassLoader cload = getClass().getClassLoader();
@ -128,8 +137,8 @@ public abstract class PackageLoader extends AbstractScript {
try { try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer w = new OutputStreamWriter(baos); Writer w = new OutputStreamWriter(baos);
for (int i = 0; i < args.length; i++) { for (String arg : args) {
w.write(args[i]); w.write(arg);
w.write("\n"); w.write("\n");
} }

File diff suppressed because it is too large Load Diff

View File

@ -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 <tosmers@uni-bremen.de>
* @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);
}

View File

@ -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 <tosmers@uni-bremen.de>
* @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;
}
}
}

View File

@ -22,6 +22,7 @@ import com.arsdigita.db.DbHelper;
import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.KernelExcursion; import com.arsdigita.kernel.KernelExcursion;
import com.arsdigita.loader.PackageLoader; import com.arsdigita.loader.PackageLoader;
import com.arsdigita.packaging.LoadCenter.LoadType;
import com.arsdigita.persistence.DataAssociation; import com.arsdigita.persistence.DataAssociation;
import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.OID; import com.arsdigita.persistence.OID;
@ -50,62 +51,101 @@ import org.apache.log4j.Logger;
/** /**
* Loader * Loader
* *
* Helper class for load which actually performs the loading of * Helper class for load and unload which actually performs the loading and
* the database schema and of the initial content. * unloading of the database schema, the data and of the initial content.
* *
* @author Rafael H. Schloming &lt;rhs@mit.edu&gt; * @author Rafael H. Schloming &lt;rhs@mit.edu&gt; tosmers;
* @version $Revision: #13 $ $Date: 2004/08/16 $ * @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 { class Loader {
private static final Logger s_log = Logger.getLogger(Loader.class); private static final Logger s_log = Logger.getLogger(Loader.class);
private static final String INIT = "com.arsdigita.runtime.Initializer"; private static final String INIT = "com.arsdigita.runtime.Initializer";
public static Loader get(String pkg) {
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;
}
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 String m_key;
private LoaderInfo m_info; private LoaderInfo m_info;
private Checklist m_checks; private Checklist m_checks;
private List m_scripts; private List m_scripts;
public Loader(String key, LoaderInfo info, Checklist checks) {
/**
* 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_key = key;
m_info = info; m_info = info; //all the stuff form .load-file
m_checks = checks; m_checks = checks;
m_scripts = new ArrayList(); m_scripts = new ArrayList();
for (Iterator it = m_info.getDataScripts().iterator(); for (Iterator it = m_info.getDataScripts(scriptType).iterator();
it.hasNext();) { it.hasNext();) {
String script = (String) it.next(); String script = (String) it.next();
m_scripts.add(Classes.newInstance(script)); 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), scriptType);
}
/**
* Getter for the package-key.
*
* @return The package-key
*/
public String getKey() { public String getKey() {
return m_key; return m_key;
} }
/**
* Getter for the loader-informations.
*
* @return The loader-informations
*/
public LoaderInfo getInfo() { public LoaderInfo getInfo() {
return m_info; return m_info;
} }
/**
* List of scripts for the loader, provided by the ".load"-file.
*
* @return A list of scripts
*/
public List getScripts() { public List getScripts() {
return m_scripts; return m_scripts;
} }
/**
* Checks the schema, set in the ".load"-file.
*
* @return true on success, otherwise false
*/
public boolean checkSchema() { public boolean checkSchema() {
if (m_checks == null) { if (m_checks == null) {
return true; 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) { public void loadSchema(Connection conn) {
int db = DbHelper.getDatabase(conn); int db = DbHelper.getDatabase(conn);
String dir = DbHelper.getDatabaseDirectory(db); String dir = DbHelper.getDatabaseDirectory(db);
@ -125,6 +170,28 @@ class Loader {
} }
} }
/**
* 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) { public boolean checkData(Session ssn) {
if (m_checks == null) { if (m_checks == null) {
return true; 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) { public void loadData(Session ssn, ParameterReader prd) {
final List inits = m_info.getProvidedInitializers(); final List inits = m_info.getProvidedInitializers();
CompoundInitializer ini = new CompoundInitializer(); CompoundInitializer ini = new CompoundInitializer();
@ -149,10 +222,10 @@ class Loader {
// final ScriptContext ctx = new ScriptContext(ssn, loader); // final ScriptContext ctx = new ScriptContext(ssn, loader);
final ScriptContext ctx = new ScriptContext(ssn, prd); final ScriptContext ctx = new ScriptContext(ssn, prd);
new KernelExcursion() { new KernelExcursion() {
@Override
protected void excurse() { protected void excurse() {
setEffectiveParty(Kernel.getSystemParty()); setEffectiveParty(Kernel.getSystemParty());
for (Iterator it = m_scripts.iterator(); it.hasNext();) { for (Iterator it = m_scripts.iterator(); it.hasNext(); ) {
Script script = (Script) it.next(); Script script = (Script) it.next();
s_log.info("Running data loader " + script.getClass(). s_log.info("Running data loader " + script.getClass().
getName()); getName());
@ -166,13 +239,53 @@ class Loader {
} }
} }
/**
* 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) { public void loadInits(final Session ssn) {
final TransactionContext txn = ssn.getTransactionContext(); final TransactionContext txn = ssn.getTransactionContext();
txn.beginTxn(); txn.beginTxn();
final List inits = m_info.getProvidedInitializers(); final List inits = m_info.getProvidedInitializers();
final List required = m_info.getRequiredInitializers(); 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(); String init = (String) it.next();
DataObject dataobject = ssn.create(new OID(INIT, init)); DataObject dataobject = ssn.create(new OID(INIT, init));
DataAssociation da = DataAssociation da =
@ -188,7 +301,45 @@ class Loader {
} }
} }
Set getRequired() { /**
* 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();
}
}
/**
* 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(); Set result = new HashSet();
result.addAll(m_info.getRequiredTables()); result.addAll(m_info.getRequiredTables());
result.addAll(m_info.getRequiredInitializers()); result.addAll(m_info.getRequiredInitializers());
@ -196,7 +347,13 @@ class Loader {
return result; 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(); Set result = new HashSet();
result.addAll(m_info.getProvidedTables()); result.addAll(m_info.getProvidedTables());
result.addAll(m_info.getProvidedInitializers()); result.addAll(m_info.getProvidedInitializers());

View File

@ -18,6 +18,7 @@
*/ */
package com.arsdigita.packaging; package com.arsdigita.packaging;
import com.arsdigita.packaging.LoadCenter.LoadType;
import com.arsdigita.xml.XML; import com.arsdigita.xml.XML;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
@ -42,6 +43,8 @@ class LoaderInfo {
private List m_providedInitializers = new ArrayList(); private List m_providedInitializers = new ArrayList();
private List m_schemaScripts = new ArrayList(); private List m_schemaScripts = new ArrayList();
private List m_dataScripts = 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(); private List m_requiredPackages = new ArrayList();
/** /**
@ -76,10 +79,19 @@ class LoaderInfo {
return m_schemaScripts; 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; return m_dataScripts;
} }
//Strings correspond to the tag names in the ".load"-files
private static final String PROVIDES = "provides"; private static final String PROVIDES = "provides";
private static final String REQUIRES = "requires"; private static final String REQUIRES = "requires";
private static final String TABLE = "table"; private static final String TABLE = "table";
@ -87,7 +99,8 @@ class LoaderInfo {
private static final String PACKAGE = "package"; private static final String PACKAGE = "package";
private static final String SCRIPTS = "scripts"; private static final String SCRIPTS = "scripts";
private static final String SCHEMA = "schema"; 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 // attributes
private static final String NAME = "name"; private static final String NAME = "name";
@ -98,6 +111,7 @@ class LoaderInfo {
private List m_context = new ArrayList(); private List m_context = new ArrayList();
@Override
public void startElement(String uri, String name, String qn, public void startElement(String uri, String name, String qn,
Attributes attrs) { Attributes attrs) {
if (name.equals(TABLE)) { if (name.equals(TABLE)) {
@ -165,7 +179,7 @@ class LoaderInfo {
m_schemaScripts.add(dir); m_schemaScripts.add(dir);
} }
if (name.equals(DATA)) { if (name.equals(DATA_LOAD)) {
if (!m_context.contains(SCRIPTS)) { if (!m_context.contains(SCRIPTS)) {
throw new IllegalStateException throw new IllegalStateException
("data element must appear inside scripts"); ("data element must appear inside scripts");
@ -177,12 +191,28 @@ class LoaderInfo {
("data element requires class attribute"); ("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); m_context.add(name);
} }
@Override
public void endElement(String uri, String name, String qn) { public void endElement(String uri, String name, String qn) {
m_context.remove(m_context.lastIndexOf(name)); m_context.remove(m_context.lastIndexOf(name));
} }

View File

@ -39,7 +39,7 @@ import java.util.Map;
* provided script implementation is ccm, a shell script (sh and bat) backed * provided script implementation is ccm, a shell script (sh and bat) backed
* by some PERL scripts, located in the tools directory of CCM trunk. * by some PERL scripts, located in the tools directory of CCM trunk.
* *
* @author Justin Ross &lt;jross@redhat.com&gt; * @author Justin Ross &lt;jross@redhat.com&gt; tosmers;
* @version $Id: MasterTool.java 2031 2009-12-10 03:34:04Z terry $ * @version $Id: MasterTool.java 2031 2009-12-10 03:34:04Z terry $
*/ */
public class MasterTool { public class MasterTool {

View File

@ -94,7 +94,13 @@ class Set extends Command {
Config config = new Config(reg); Config config = new Config(reg);
config.load(System.err); 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; boolean valid = true;
for (Iterator it = props.keySet().iterator(); it.hasNext(); ) { for (Iterator it = props.keySet().iterator(); it.hasNext(); ) {

View File

@ -18,12 +18,17 @@
*/ */
package com.arsdigita.packaging; package com.arsdigita.packaging;
import com.arsdigita.runtime.CCMResourceManager; import com.arsdigita.loader.PackageLoader;
import com.arsdigita.util.Files; import com.arsdigita.persistence.Session;
import com.arsdigita.persistence.SessionManager;
import java.io.File; import com.arsdigita.runtime.RuntimeConfig;
import java.io.FileFilter; 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.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
@ -35,7 +40,7 @@ import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Logger; 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 * It is called by class MasterTols and unloads the database schema and initial
* content. * content.
@ -47,31 +52,78 @@ import org.apache.log4j.Logger;
* PACKAGE-KEYS one or more space separated names of modules (package-key, e.g. * 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 * ccm-cms-types-event) which should be loaded into database and
* configuration registry * configuration registry
* Options: [--config] Removes entries in the registry (configuration repo) * Options: [-usage] Display a usage message for load command
* if set prevents any of the three data load steps * [-help|--help] Display a help message for load command
* described before to be executed! * [--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 &lt;rhs@mit.edu&gt; tosmers; * @author Tobias Osmers <tosmers@uni-bremen.de>
* @version $Revision: #7 $ $Date: 2015/03/29 $ * @version $Revision: #11 $ $Date: 2015/04/27 $
* @version $Id: Unload.java 736 2015-03-29 14:22:20Z tosmers $
*/ */
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 Logger logger = Logger.getLogger(Unload.class);
private static final Options OPTIONS = new Options(); private static final Options OPTIONS = new Options();
//for OLD unloadConfig Method
private static final Set EXCLUDE = new HashSet();
//Initializes all option-flags.
static { static {
logger.debug("Static initalizer starting..."); 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 OPTIONS.addOption
(OptionBuilder (OptionBuilder
.hasArg(false) .hasArg(false)
.withLongOpt("config") .withLongOpt("config")
.withDescription("Unload configuration") .withDescription("Unload configuration")
.create()); .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."); logger.debug("Static initalizer finished.");
} }
private static final Set EXCLUDE = new HashSet(); //Initializes all excluded files.
static { static {
logger.debug("Static initalizer starting..."); logger.debug("Static initalizer starting...");
EXCLUDE.add("resin.conf"); 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 * @param args The parameters and option-flags
* @return * @return true if successful, false otherwise
*/ */
@Override
public boolean run(String[] args) { public boolean run(String[] args) {
//Takes the option-set and the arguments and parses
//them into a command-line
CommandLine line; CommandLine line;
try { try {
line = new PosixParser().parse(OPTIONS, args); line = new PosixParser().parse(OPTIONS, args);
@ -104,27 +160,258 @@ class Unload extends Command {
return false; return false;
} }
String[] packages = line.getArgs(); //[--usage || --help]
if (packages.length == 0) { //If set, prints an info-output and returns the function
usage(OPTIONS, System.err); //with true
return false; if (line.hasOption("usage") || line.hasOption("help")) {
} usage(OPTIONS, System.out, "PACKAGE-KEYS");
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]);
}
}
return true; 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;
}
//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;
}
//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;
// }
} }

View File

@ -188,10 +188,10 @@ class Upgrade extends Command {
String[] params = line.getOptionValues("parameters"); String[] params = line.getOptionValues("parameters");
LinkedList ll = new LinkedList(); LinkedList ll = new LinkedList();
if (params != null) { if (params != null) {
for (int i = 0; i < params.length; i++) { for (String param : params) {
String[] split = StringUtils.split(params[i], ','); String[] split = StringUtils.split(param, ',');
for (int j = 0; j < split.length; j++) { for (String split1 : split) {
ll.add(split[j]); ll.add(split1);
} }
} }
} }

View File

@ -49,6 +49,7 @@ public abstract class AbstractScript extends AbstractParameterContext
* @param context the context in which to run the script * @param context the context in which to run the script
*/ */
@Override
public abstract void run(ScriptContext context); public abstract void run(ScriptContext context);
} }

View File

@ -244,6 +244,63 @@
</java> </java>
</target> </target>
<target name="unload-bundle" depends="prepare-load">
<echo>Unloading bundle from ${this.bundle.folder} from ${ccmhome}</echo>
<java classname="com.arsdigita.packaging.MasterTool" fork="true">
<classpath refid="ccm.classpath" />
<sysproperty key="ccm.home" value="${ccmhome}" />
<arg line="unload --packagekeys-file ${this.bundle.folder}/cfg/package-key.list" />
<jvmarg value="${app.server.debugger}" />
</java>
</target>
<target name="unload" depends="prepare-load">
<echo>Unload ${applications} without further configuration specifications but using build in defaults.</echo>
<java classname="com.arsdigita.packaging.MasterTool"
classpathref="ccm.classpath" fork="true">
<sysproperty key="ccm.home" value="${ccmhome}" />
<!--
<sysproperty key="log4j.configuration"
value="file:runtime/${app.server.bundles.name}/conf/log4j.xml" />
<sysproperty key="java.protocol.handler.pkgs"
value="${java.protocol.handler.pkgs}" />
-->
<arg line="unload ${applications}" />
<jvmarg value="${app.server.debugger}" />
</java>
</target>
<target name="unload-init" depends="prepare-load">
<echo>Unload initializers for ${applications} (--init)</echo>
<java classname="com.arsdigita.packaging.MasterTool"
classpathref="ccm.classpath" fork="true">
<sysproperty key="ccm.home" value="${ccmhome}" />
<arg line="unload --init ${applications}" />
<jvmarg value="${app.server.debugger}" />
</java>
</target>
<target name="unload-schema" depends="prepare-load">
<echo>Unload schema only for ${applications} (--schema)</echo>
<java classname="com.arsdigita.packaging.MasterTool"
classpathref="ccm.classpath" fork="true">
<sysproperty key="ccm.home" value="${ccmhome}" />
<arg line="unload --schema ${applications}" />
<jvmarg value="${app.server.debugger}" />
</java>
</target>
<target name="unload-config" depends="prepare-load">
<echo>Unregisters configuration from ${this.bundle.folder} for ${applications} from registry</echo>
<java classname="com.arsdigita.packaging.MasterTool"
classpathref="ccm.classpath" fork="true">
<sysproperty key="ccm.home" value="${ccmhome}" />
<arg line="unload --config ${applications}" />
<jvmarg value="${app.server.debugger}" />
</java>
</target>
<target name="new-app"> <target name="new-app">
<fail message="Please specify -Dnew.app.name=&lt;name&gt; at the command line"> <fail message="Please specify -Dnew.app.name=&lt;name&gt; at the command line">
<condition> <condition>