Fixed Synchronization bug, final synchronization with fedorahosted r3209.

git-svn-id: https://svn.libreccm.org/ccm/trunk@3994 8810af33-2d31-482b-a856-94f89814c4df
master
pb 2016-04-15 06:20:14 +00:00
parent ded7d5a275
commit db2966d3aa
9 changed files with 134 additions and 109 deletions

View File

@ -17,7 +17,8 @@
-- --
-- $Id: upd_system_tables.sql pboy $ -- $Id: upd_system_tables.sql pboy $
-- adjust various system tables to the new name of application -- converts ThemeDirector to a new application type and removes the old
-- compatibility eintries in system tables.
update application_types update application_types

View File

@ -31,11 +31,11 @@ import com.arsdigita.themedirector.util.ThemePublishedFileManager;
import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.pdl.ManifestSource; import com.arsdigita.persistence.pdl.ManifestSource;
import com.arsdigita.persistence.pdl.NameFilter; import com.arsdigita.persistence.pdl.NameFilter;
import com.arsdigita.runtime.CCMResourceManager;
import com.arsdigita.runtime.CompoundInitializer; import com.arsdigita.runtime.CompoundInitializer;
import com.arsdigita.runtime.ContextCloseEvent; import com.arsdigita.runtime.ContextCloseEvent;
import com.arsdigita.runtime.ContextInitEvent; import com.arsdigita.runtime.ContextInitEvent;
import com.arsdigita.runtime.DomainInitEvent; import com.arsdigita.runtime.DomainInitEvent;
// import com.arsdigita.runtime.LegacyInitEvent;
import com.arsdigita.runtime.PDLInitializer; import com.arsdigita.runtime.PDLInitializer;
import com.arsdigita.runtime.RuntimeConfig; import com.arsdigita.runtime.RuntimeConfig;
import com.arsdigita.templating.PatternStylesheetResolver; import com.arsdigita.templating.PatternStylesheetResolver;
@ -55,7 +55,7 @@ public class Initializer extends CompoundInitializer {
/** 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 the runtime environment * by editing /WEB-INF/conf/log4j.properties int the runtime environment
* and set com.arsdigita.themedirector.Initializer=DEBUG * and set com.arsdigita.themedirector.Initializer=DEBUG
* by uncommenting or adding the line. */ * by uncommenting or adding the line. */
private static final Logger s_log = Logger.getLogger(Initializer.class); private static final Logger s_log = Logger.getLogger(Initializer.class);
public Initializer() { public Initializer() {
@ -121,7 +121,9 @@ public class Initializer extends CompoundInitializer {
while (collection.next()) { while (collection.next()) {
config.addTheme(collection.getURL(), collection.getTitle()); config.addTheme(collection.getURL(), collection.getTitle());
} }
String baseDir=CCMResourceManager.getBaseDirectory().getPath();
s_log.info("ThemeDirector's application context directory: " + baseDir);
// start thread for monitoring queue // start thread for monitoring queue
int devStartupDelay = ThemeDirector.getConfig() int devStartupDelay = ThemeDirector.getConfig()
.getThemeDevFileWatchStartupDelay().intValue(); .getThemeDevFileWatchStartupDelay().intValue();
@ -132,9 +134,9 @@ public class Initializer extends CompoundInitializer {
int pubPollDelay = ThemeDirector.getConfig() int pubPollDelay = ThemeDirector.getConfig()
.getThemePubFileWatchPollDelay().intValue(); .getThemePubFileWatchPollDelay().intValue();
ThemePublishedFileManager.startWatchingFiles ThemePublishedFileManager.startWatchingFiles
(pubStartupDelay, pubPollDelay, null); (pubStartupDelay, pubPollDelay, baseDir);
ThemeDevelopmentFileManager.startWatchingFiles ThemeDevelopmentFileManager.startWatchingFiles
(devStartupDelay, devPollDelay, null); (devStartupDelay, devPollDelay, baseDir);
} }
/** /**

View File

@ -27,7 +27,6 @@ import com.arsdigita.ui.admin.applications.ApplicationInstanceAwareContainer;
/** /**
* *
* @author Jens Pelzetter <jens@jp-digital.de> * @author Jens Pelzetter <jens@jp-digital.de>
* @version $Id$
*/ */
public class ThemeDirectorAppManager extends AbstractSingletonApplicationManager<ThemeDirector> { public class ThemeDirectorAppManager extends AbstractSingletonApplicationManager<ThemeDirector> {

View File

@ -75,21 +75,6 @@ public class ThemeDirectorConfig extends AbstractConfig {
("themedirector.default_theme_path", ("themedirector.default_theme_path",
Parameter.OPTIONAL, "/themes/master/"); Parameter.OPTIONAL, "/themes/master/");
// /** Servlet context path containing the default theme.
// * Previously ccm-themedirector used to be installed in its own
// * web context. In this case the appropriate web context should
// * be specified.
// * Currently, it is installed as part of the main application,
// * therefore it is empty by default.
// * @deprecated without direct replacement. Themedirector's Webapp context
// * has to be determined at runtime.
// */
// private final Parameter m_defaultThemeContext =
// new StringParameter
// ("themedirector.default_theme_context",
// Parameter.OPTIONAL, "");
// Parameter.OPTIONAL, "/ccm-themedirector/");
/** File containing the default themes directory. Used in conjuntion with /** File containing the default themes directory. Used in conjuntion with
com.arsdigita.themedirectory.default_directory_filter to dictate the com.arsdigita.themedirectory.default_directory_filter to dictate the
final default directory. */ final default directory. */

View File

@ -147,9 +147,10 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
/** /**
* This validates the stylesheets for the selected theme (designated * This validates the stylesheets for the selected theme (designated by
* by the ThemeSelectionModel passed in to the constructor of this * the ThemeSelectionModel passed in to the constructor of this class).
* class). This should be called if the user wants the system * This should be called if the user wants the system
*
* @return true if the stylesheets are all valid and false otherwise * @return true if the stylesheets are all valid and false otherwise
*/ */
public boolean validateStylesheets(PageState state) { public boolean validateStylesheets(PageState state) {

View File

@ -44,10 +44,10 @@ import java.util.TreeSet;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* This approves the theme and pushes it to the production file location * This approves the theme and pushes it to the production file location. This
* This action means that the user wants to approve the themes and * action means that the user wants to approve the themes and push them live.
* push them live. This is done by copying the files from the devel directory * This is done by copying the files from the devel directory into the published
* into the published directory. * directory.
* *
* @author Randy Graebner &lt;randyg@redhat.com&gt; * @author Randy Graebner &lt;randyg@redhat.com&gt;
*/ */
@ -79,9 +79,8 @@ public class ApproveThemeActionListener implements ThemeDirectorConstants,
*/ */
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// First, we rename the current production directory // First, we rename the current production directory so that if there
// so that if there is an exception, we can try to move it // is an exception, we can try to move it back in to place
// back in to place
Theme theme = m_model.getSelectedTheme(e.getPageState()); Theme theme = m_model.getSelectedTheme(e.getPageState());
File currentRoot = new File(Web.getServletContext().getRealPath("/")); File currentRoot = new File(Web.getServletContext().getRealPath("/"));
File oldProd = new File(currentRoot, PROD_THEMES_BASE_DIR + File oldProd = new File(currentRoot, PROD_THEMES_BASE_DIR +
@ -114,10 +113,9 @@ public class ApproveThemeActionListener implements ThemeDirectorConstants,
} }
} }
// assuming that went well, we need to move the devDir in to // assuming that went well, we need to move the devDir in to the
// the database as the latest "live" files // database as the latest "live" files but before we do that, we
// but before we do that, we copy is_deleted flag from // copy is_deleted flag from development to published files
// development to published files
DataOperation op = SessionManager.getSession().retrieveDataOperation( DataOperation op = SessionManager.getSession().retrieveDataOperation(
"com.arsdigita.themedirector.bulkFileUpdate"); "com.arsdigita.themedirector.bulkFileUpdate");
op.setParameter("themeID", theme.getID()); op.setParameter("themeID", theme.getID());
@ -142,8 +140,9 @@ public class ApproveThemeActionListener implements ThemeDirectorConstants,
// delete the directory and move the oldProd back // delete the directory and move the oldProd back
Files.delete(new File(newProd + theme.getURL())); Files.delete(new File(newProd + theme.getURL()));
if (oldProd.exists()) { if (oldProd.exists()) {
oldProd.renameTo(new File(currentRoot, PROD_THEMES_BASE_DIR + oldProd.renameTo(new File(currentRoot,
theme.getURL())); PROD_THEMES_BASE_DIR + theme.getURL()
));
} }
throw new UncheckedWrapperException(errorMsg, ex); throw new UncheckedWrapperException(errorMsg, ex);
} }

View File

@ -1,17 +1,20 @@
/* /*
* Copyright (C) 2001, 2003 ArsDigita Corporation. All Rights Reserved. * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
* *
* The contents of this file are subject to the ArsDigita Public * This library is free software; you can redistribute it and/or
* License (the "License"); you may not use this file except in * modify it under the terms of the GNU Lesser General Public License
* compliance with the License. You may obtain a copy of * as published by the Free Software Foundation; either version 2.1 of
* the License at http://www.arsdigita.com/ADPL.txt * the License, or (at your option) any later version.
* *
* Software distributed under the License is distributed on an "AS * This library is distributed in the hope that it will be useful,
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* implied. See the License for the specific language governing * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* rights and limitations under the License. * 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.themedirector.util; package com.arsdigita.themedirector.util;
@ -24,27 +27,23 @@ import java.io.File;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* Class for polling the database to look for new/updated development files * Class for polling the database to look for new/updated development files
* in the ThemeFile table. * in the ThemeFile table.
*
* For "development" files, it looks at every file in the db and, if
* the timestamp is after the timestamp of the file on the file system (or
* there is no file on the file system)
* then it writes out the new file. If the timestamp on the file system
* is newer, it ignores the file.
* *
* For "development" files, it looks at every file in the db and, if the
* timestamp is after the timestamp of the file on the file system (or
* there is no file on the file system) then it writes out the new file.
* If the timestamp on the file system is newer, it ignores the file.
* *
* @author <a href="mailto:randyg@redhat.com">Randy Graebner</a> * @author <a href="mailto:randyg@redhat.com">Randy Graebner</a>
*
* @version $Revision: #2 $ $DateTime: 2004/03/17 09:56:37 $
*/ */
public class ThemeDevelopmentFileManager extends ThemeFileManager { public class ThemeDevelopmentFileManager extends ThemeFileManager {
/** 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 in the runtime environment and
* and set com.arsdigita.themedirector.util.ThemeDevelopmentFileManager=DEBUG * set com.arsdigita.themedirector.util.ThemeDevelopmentFileManager=DEBUG
* by uncommenting or adding the line. */ * by uncommenting or adding the line. */
private static Logger s_log = Logger private static final Logger s_log = Logger
.getLogger(ThemeDevelopmentFileManager.class); .getLogger(ThemeDevelopmentFileManager.class);
// The code in this class borrows heavily from // The code in this class borrows heavily from
@ -56,11 +55,23 @@ public class ThemeDevelopmentFileManager extends ThemeFileManager {
/** /**
* Constructor just delegates to super class. * Constructor just delegates to super class.
* *
* @param startupDelay * Usually Themedirector's Initializer() will setup a background thread to
* @param pollDelay * continuously watch for modifications and synchronize. Specifically the
* @param baseDirectory * Initializer() provides null as baseDirectory parameter because it
* doesn't know about servlet context and can not determine the directory.
*
*
* @param startupDelay number of seconds to wait before starting to process
* the file. A startupDelay of 0 means this is a no-op
* @param pollDelay number of seconds to wait between checks if the file
* has any entries.
* @param baseDirectory String with the file system path to document root
* for the application context ThemeDirector is running.
* (the directory containing WEB-INF subdir)
* May be null! (Specificall if invokel by Initializer!)
*/ */
protected ThemeDevelopmentFileManager(int startupDelay, int pollDelay, protected ThemeDevelopmentFileManager(int startupDelay,
int pollDelay,
String baseDirectory) { String baseDirectory) {
super(s_log, // Injects it's own logger super(s_log, // Injects it's own logger
@ -75,18 +86,23 @@ public class ThemeDevelopmentFileManager extends ThemeFileManager {
* thread that has been spawned. If there is already a running thread then * thread that has been spawned. If there is already a running thread then
* this is a no-op that returns a reference to the running thread. * this is a no-op that returns a reference to the running thread.
* *
* The thread starts processing after <code>startupDelay</code> seconds. * Specifically it is used by Themedirector's Initializer() to start a
* The db is checked for new/updated * continuous background process to synchronize database and filesystem.
* files every <code>pollDelay</code> seconds.
* *
* This will not start up multiple threads...if there is already * The thread starts processing after <code>startupDelay</code> seconds. The
* a thread running, it will return that thread to you. * db is checked for new/updated files every <code>pollDelay</code> seconds.
*
* This will not start up multiple threads...if there is already a thread
* running, it will return that thread to you.
* *
* @param startupDelay number of seconds to wait before starting to process * @param startupDelay number of seconds to wait before starting to process
* the file. A startupDelay of 0 means that this is a no-op * the file. A startupDelay of 0 means this is a no-op
* @param pollDelay number of seconds to wait between checks if the file * @param pollDelay number of seconds to wait between checks if the file
* has any entries. * has any entries.
* @param baseDirectory * @param baseDirectory String with the file system path to document root
* for the application context ThemeDirector is running.
* (the directory containing WEB-INF subdir)
* May be null! (Specificall if invokel by Initializer!)
* @return * @return
*/ */
public static ThemeFileManager startWatchingFiles(int startupDelay, public static ThemeFileManager startWatchingFiles(int startupDelay,
@ -128,20 +144,22 @@ public class ThemeDevelopmentFileManager extends ThemeFileManager {
*/ */
@Override @Override
protected String getManagerSpecificDirectory() { protected String getManagerSpecificDirectory() {
return getBaseDirectory() + DEV_THEMES_BASE_DIR; String devDir = getBaseDirectory() + DEV_THEMES_BASE_DIR;
s_log.info(devDir + " is the development themes directory used.");
return devDir;
} }
// TODO // TODO
// if we run the updateDatabaseFiles every time this runs then // if we run the updateDatabaseFiles every time this runs then
// it ends up doing an insert pretty much every time. So, // it ends up doing an insert pretty much every time. So,
// we only place the dev files in the db when the user specifically // we only place the dev files in the db when the user specifically
// tells us to by publishing the files or by clicking on the link // tells us to by publishing the files or by clicking on the link
// to place them in the db. I am leaving this code here since // to place them in the db. I am leaving this code here since
// it works if we want the thread to auto-update things for us. // it works if we want the thread to auto-update things for us.
// if we decide that we definitely do not want the auto-update // if we decide that we definitely do not want the auto-update
// then we should remove this. // then we should remove this.
@Override @Override
protected void updateTheme(Theme theme) { protected void updateTheme(Theme theme) {
// the first step is to make sure that all files from the theme // the first step is to make sure that all files from the theme

View File

@ -21,16 +21,15 @@ import com.arsdigita.themedirector.ThemeDirectorConstants;
import com.arsdigita.themedirector.ThemeFileCollection; import com.arsdigita.themedirector.ThemeFileCollection;
import com.arsdigita.persistence.SessionManager; import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.TransactionContext; import com.arsdigita.persistence.TransactionContext;
import com.arsdigita.runtime.CCMResourceManager;
//import com.arsdigita.themedirector.dispatcher.InternalThemePrefixerServlet; //import com.arsdigita.themedirector.dispatcher.InternalThemePrefixerServlet;
import com.arsdigita.web.Web; //import com.arsdigita.web.Web;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Date; import java.util.Date;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -70,6 +69,7 @@ public abstract class ThemeFileManager extends Thread
// Set to values other than default by calling methods from an initializer. // Set to values other than default by calling methods from an initializer.
private final int m_startupDelay; private final int m_startupDelay;
private final int m_pollDelay; private final int m_pollDelay;
/** Full path of the web application's base directory ("document root") */
private String m_baseDirectory = null; private String m_baseDirectory = null;
// the m_ignoreInterrupt allows us to use the "interrupt" command to // the m_ignoreInterrupt allows us to use the "interrupt" command to
@ -196,10 +196,10 @@ public abstract class ThemeFileManager extends Thread
/** /**
* This returns the base directory to use when writing out files. * This returns the base directory of the web applications ("document root")
* THIS IS A HACK BECAUSE IT REQUIRES A SERVER TO BE RUNNING. * used to construct the file system location when writing out files.
* *
* @return * @return Full path of the web application context directory
*/ */
protected String getBaseDirectory() { protected String getBaseDirectory() {
@ -217,8 +217,9 @@ public abstract class ThemeFileManager extends Thread
// .getThemedirectorContext(); // .getThemedirectorContext();
// We have to ensure the Servlet is initialized. // We have to ensure the Servlet is initialized.
ServletContext themeCtx = Web.getServletContext(); // ServletContext themeCtx = Web.getServletContext();
m_baseDirectory = themeCtx.getRealPath("/"); // m_baseDirectory = themeCtx.getRealPath("/");
m_baseDirectory = CCMResourceManager.getBaseDirectory().getPath();
} }
return m_baseDirectory; return m_baseDirectory;

View File

@ -49,6 +49,22 @@ public class ThemePublishedFileManager extends ThemeFileManager {
static private ThemeFileManager s_manager = null; static private ThemeFileManager s_manager = null;
/**
* Constructor just delegates to super class.
*
* Usually Themedirector's Initializer() will setup a background thread to
* continuously watch for modifications and synchronize. Specifically the
* Initializer() provides null as baseDirectory parameter because it
* doesn't know about servlet context and can not determine the directory.
*
* @param startupDelay number of seconds to wait before starting to process
* the file. A startupDelay of 0 means this is a no-op
* @param pollDelay number of seconds to wait between checks if the file
* has any entries.
* @param baseDirectory String with the path to theme files base directory
* (the directory containing devel and pub subdirs)
* May be null! (Most likely if invokel by Initializer!)
*/
protected ThemePublishedFileManager(int startupDelay, protected ThemePublishedFileManager(int startupDelay,
int pollDelay, int pollDelay,
String baseDirectory) { String baseDirectory) {
@ -57,24 +73,27 @@ public class ThemePublishedFileManager extends ThemeFileManager {
// is there a way to move this code up in to the parent class? // is there a way to move this code up in to the parent class?
/** /**
* Start watching the files. This method spawns a * Start watching the files. This method spawns a background thread that
* background thread that looks for changes in files in the database * looks for changes in files in the database if there is not already a
* if there is not already a thread that has been spawned. If there * thread that has been spawned. If there is already a running thread then
* is already a running thread then this is a no-op that returns a * this is a no-op that returns a reference to the running thread.
* reference to the running thread.
* *
* The thread starts processing after <code>startupDelay</code> seconds. * Specifically it is used by Themedirector's Initializer() to start a
* The db is checked for new/updated * continuous background process to synchronize database and filesystem.
* files every <code>pollDelay</code> seconds. *
* The thread starts processing after <code>startupDelay</code> seconds. The
* db is checked for new/updated files every <code>pollDelay</code> seconds.
* *
* This will not start up multiple threads...if there is already * This will not start up multiple threads...if there is already a thread
* a thread running, it will return that thread to you. * running, it will return that thread to you.
* *
* @param startupDelay number of seconds to wait before starting to * @param startupDelay number of seconds to wait before starting to process
* process the file. A startupDelay of 0 means that this is a no-op * the file. A startupDelay of 0 means this is a no-op
* @param pollDelay number of seconds to wait between checks if the file * @param pollDelay number of seconds to wait between checks if the file
* has any entries. * has any entries.
* @param baseDirectory * @param baseDirectory String with the path to theme files base directory
* (the directory containing devel and pub subdirs)
* May be null! (Specificall if invokel by Initializer!)
* @return * @return
*/ */
public static ThemeFileManager startWatchingFiles(int startupDelay, public static ThemeFileManager startWatchingFiles(int startupDelay,