[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-94f89814c4dfmaster
parent
431f2b7040
commit
44d378da59
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -12,5 +12,6 @@
|
|||
<scripts>
|
||||
<schema directory="ccm-cms-types-externallink"/>
|
||||
<data class="com.arsdigita.cms.contenttypes.ExternalLinkLoader"/>
|
||||
<data-unload class="com.arsdigita.cms.contenttypes.ExternalLinkUnloader"/>
|
||||
</scripts>
|
||||
</load>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import java.math.BigDecimal;
|
|||
*
|
||||
* 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 $
|
||||
*/
|
||||
public class ExternalLink extends ContentPage {
|
||||
|
|
@ -105,7 +105,7 @@ public class ExternalLink extends ContentPage {
|
|||
/**
|
||||
* 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) {
|
||||
super(type);
|
||||
|
|
@ -159,7 +159,7 @@ public class ExternalLink extends ContentPage {
|
|||
/**
|
||||
* 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) {
|
||||
set(SHOW_COMMENT, show);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import com.arsdigita.cms.contenttypes.ContentTypeInitializer;
|
|||
* This is done by runtimeRuntime startup method which runs the init() methods
|
||||
* 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 $
|
||||
*/
|
||||
public class ExternalLinkInitializer extends ContentTypeInitializer {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ import java.io.InputStream;
|
|||
* from AbstractConfig). They will (and can) not be persisted into
|
||||
* an registry object (file).
|
||||
*
|
||||
* @author tosmers
|
||||
* @author Tobias Osmers <tosmers@uni-bremen.de>
|
||||
* @version $Revision: #1 $ $Date: 2015/02/22 $
|
||||
*/
|
||||
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
|
||||
* select box and the authoring steps. These are loaded into database.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ import com.arsdigita.toolbox.ui.DomainObjectPropertySheet;
|
|||
* Authoring step to view/edit the simple attributes of the
|
||||
* ExternalLink content type (and its subclasses).
|
||||
*
|
||||
* @author tosmers
|
||||
* @author Tobias Osmers <tosmers@uni-bremen.de>
|
||||
* @version $Revision: #1 $ $Date: 2015/02/22 $
|
||||
*/
|
||||
public class ExternalLinkPropertiesStep extends SimpleEditStep {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import com.arsdigita.cms.ui.authoring.BasicPageForm;
|
|||
* <br />
|
||||
* 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 $
|
||||
*/
|
||||
public class ExternalLinkPropertyForm extends BasicPageForm
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import com.arsdigita.globalization.GlobalizedMessage;
|
|||
* globalize methods and forwards to GlobalizedMessage, shortening the
|
||||
* method invocation in the various application classes.
|
||||
*
|
||||
* @author tosmers
|
||||
* @author Tobias Osmers <tosmers@uni-bremen.de>
|
||||
* @version $Revision: #1 $ $Date: 2015/02/22 $
|
||||
*/
|
||||
public class ExternalLinkGlobalizationUtil implements Globalized {
|
||||
|
|
|
|||
|
|
@ -65,10 +65,12 @@ import org.apache.log4j.Logger;
|
|||
*/
|
||||
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
|
||||
* 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(
|
||||
AbstractContentTypeLoader.class);
|
||||
|
||||
|
|
@ -77,7 +79,7 @@ public abstract class AbstractContentTypeLoader extends PackageLoader {
|
|||
* this method any required parameters registered by the noargs
|
||||
* 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.
|
||||
*
|
||||
* @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) {
|
||||
|
||||
|
|
@ -111,13 +117,12 @@ public abstract class AbstractContentTypeLoader extends PackageLoader {
|
|||
|
||||
List types = handler.getContentTypes();
|
||||
Session ssn = ctx.getSession();
|
||||
DataCollection sections = ssn.retrieve(ContentSection
|
||||
.BASE_DATA_OBJECT_TYPE);
|
||||
DataCollection sections = ssn.retrieve(
|
||||
ContentSection.BASE_DATA_OBJECT_TYPE);
|
||||
|
||||
while (sections.next()) {
|
||||
ContentSection section = (ContentSection)
|
||||
DomainObjectFactory.newInstance(
|
||||
sections.getDataObject());
|
||||
DomainObjectFactory.newInstance(sections.getDataObject());
|
||||
if (!isLoadableInto(section)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -176,7 +181,8 @@ public abstract class AbstractContentTypeLoader extends PackageLoader {
|
|||
* content types's.
|
||||
* Must be implemented by each content type loader to provide its
|
||||
* specific definition files.
|
||||
* @return
|
||||
*
|
||||
* @return This content type's property definitions through the ".xml"-file
|
||||
*/
|
||||
protected abstract String[] getTypes();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
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 LoaderInfo m_info;
|
||||
private Checklist m_checks;
|
||||
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_info = info;
|
||||
m_info = info; //all the stuff form .load-file
|
||||
m_checks = checks;
|
||||
m_scripts = new ArrayList();
|
||||
for (Iterator it = m_info.getDataScripts().iterator();
|
||||
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), 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);
|
||||
|
|
@ -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) {
|
||||
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());
|
||||
|
|
@ -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) {
|
||||
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 =
|
||||
|
|
@ -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();
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -94,7 +94,13 @@ class Set extends Command {
|
|||
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(); ) {
|
||||
|
|
|
|||
|
|
@ -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 <tosmers@uni-bremen.de>
|
||||
* @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);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
//[--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;
|
||||
}
|
||||
|
||||
//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;
|
||||
// }
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -244,6 +244,63 @@
|
|||
</java>
|
||||
</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">
|
||||
<fail message="Please specify -Dnew.app.name=<name> at the command line">
|
||||
<condition>
|
||||
|
|
|
|||
Loading…
Reference in New Issue