Author: sskracic Date: 2005-11-09 18:10:48 +0100 (Wed, 09 Nov 2005) New Revision: 988 Added: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/oracle-se/ trunk/ccm-ldn-theme/sql/ccm-ldn-theme/oracle-se/upgrade/ trunk/ccm-ldn-theme/sql/ccm-ldn-theme/oracle-se/upgrade/6.3.0-6.3.1/ trunk/ccm-ldn-theme/sql/ccm-ldn-theme/oracle-se/upgrade/6.3.0-6.3.1/add-is_deleted.sql trunk/ccm-ldn-theme/sql/ccm-ldn-theme/postgres/upgrade/6.3.0-6.3.1/ trunk/ccm-ldn-theme/sql/ccm-ldn-theme/postgres/upgrade/6.3.0-6.3.1/add-is_deleted.sql trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/oracle-se-6.3.0-6.3.1.sql trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/postgres-6.3.0-6.3.1.sql trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/listeners/FileRemovalRequestListener.java Modified: trunk/ccm-ldn-theme/application.xml trunk/ccm-ldn-theme/pdl/com/arsdigita/london/themes/ThemeFile.pdl trunk/ccm-ldn-theme/src/ccm-ldn-theme.upgrade trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ThemeFile.java trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ThemeFileCollection.java trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/ThemeFilesList.java trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/util/ThemeFileManager.java trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/util/ThemeFileUtil.java trunk/ccm-ldn-theme/web/__ccm__/apps/theme/xsl/index.xsl Log: First pass at theme enhancements. It is now possible to schedule theme files for removal (through theme admin UI). Further, all files with extensions not on the whitelist (configuration parameter) are ignored and exempt from being mirrorred to the database and, ultimately, to other cluster peers. Still work in progress, though. Modified: trunk/ccm-ldn-theme/application.xml =================================================================== --- trunk/ccm-ldn-theme/application.xml 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/application.xml 2005-11-09 17:10:48 UTC (rev 988) @@ -2,8 +2,8 @@ <ccm:application xmlns:ccm="http://ccm.redhat.com/ccm-project" name="ccm-ldn-theme" prettyName="Theme" - version="6.3.0" - release="3"> + version="6.3.1" + release="1"> <ccm:dependencies> <ccm:requires name="ccm-core" version="6.2.0" relation="ge"/> <ccm:requires name="ccm-ldn-subsite" version="6.2.0" relation="ge"/> Modified: trunk/ccm-ldn-theme/pdl/com/arsdigita/london/themes/ThemeFile.pdl =================================================================== --- trunk/ccm-ldn-theme/pdl/com/arsdigita/london/themes/ThemeFile.pdl 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/pdl/com/arsdigita/london/themes/ThemeFile.pdl 2005-11-09 17:10:48 UTC (rev 988) @@ -17,9 +17,6 @@ model com.arsdigita.london.theme; -import com.arsdigita.web.Application; -import com.arsdigita.kernel.ACSObject; -import com.arsdigita.kernel.Party; object type ThemeFile { BigDecimal[1..1] id = theme_files.file_id INTEGER; @@ -33,6 +30,8 @@ Date[1..1] lastModifiedDate = theme_files.last_modified_date TIMESTAMP; + Boolean[1..1] deleted = theme_files.is_deleted; + // each theme should only have one file per filePath // we cannot add this here becuase persistence does not know how to // map the association column back to the column in this table and Added: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/oracle-se/upgrade/6.3.0-6.3.1/add-is_deleted.sql =================================================================== --- trunk/ccm-ldn-theme/sql/ccm-ldn-theme/oracle-se/upgrade/6.3.0-6.3.1/add-is_deleted.sql 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/sql/ccm-ldn-theme/oracle-se/upgrade/6.3.0-6.3.1/add-is_deleted.sql 2005-11-09 17:10:48 UTC (rev 988) @@ -0,0 +1,7 @@ + +alter table theme_files add is_deleted char(1); +update theme_files set is_deleted = '0'; +alter table theme_files add constraint theme_files_is_deleted_c_gadn2 + check(is_deleted in ('0', '1')); +alter table theme_files modify is_deleted not null; + Property changes on: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/oracle-se/upgrade/6.3.0-6.3.1/add-is_deleted.sql ___________________________________________________________________ Name: svn:keywords + Id Author URL Added: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/postgres/upgrade/6.3.0-6.3.1/add-is_deleted.sql =================================================================== --- trunk/ccm-ldn-theme/sql/ccm-ldn-theme/postgres/upgrade/6.3.0-6.3.1/add-is_deleted.sql 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/sql/ccm-ldn-theme/postgres/upgrade/6.3.0-6.3.1/add-is_deleted.sql 2005-11-09 17:10:48 UTC (rev 988) @@ -0,0 +1,5 @@ + +alter table theme_files add is_deleted boolean; +update theme_files set is_deleted = 'f'; +alter table theme_files alter is_deleted set not null; + Property changes on: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/postgres/upgrade/6.3.0-6.3.1/add-is_deleted.sql ___________________________________________________________________ Name: svn:keywords + Id Author URL Added: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/oracle-se-6.3.0-6.3.1.sql =================================================================== --- trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/oracle-se-6.3.0-6.3.1.sql 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/oracle-se-6.3.0-6.3.1.sql 2005-11-09 17:10:48 UTC (rev 988) @@ -0,0 +1 @@ +@@ ../oracle-se/upgrade/6.3.0-6.3.1/add-is_deleted.sql Property changes on: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/oracle-se-6.3.0-6.3.1.sql ___________________________________________________________________ Name: svn:keywords + Id Author URL Added: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/postgres-6.3.0-6.3.1.sql =================================================================== --- trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/postgres-6.3.0-6.3.1.sql 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/postgres-6.3.0-6.3.1.sql 2005-11-09 17:10:48 UTC (rev 988) @@ -0,0 +1,5 @@ +begin; + +\i ../postgres/upgrade/6.3.0-6.3.1/add-is_deleted.sql + +commit; Property changes on: trunk/ccm-ldn-theme/sql/ccm-ldn-theme/upgrade/postgres-6.3.0-6.3.1.sql ___________________________________________________________________ Name: svn:keywords + Id Author URL Modified: trunk/ccm-ldn-theme/src/ccm-ldn-theme.upgrade =================================================================== --- trunk/ccm-ldn-theme/src/ccm-ldn-theme.upgrade 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/src/ccm-ldn-theme.upgrade 2005-11-09 17:10:48 UTC (rev 988) @@ -5,4 +5,7 @@ <version from="1.0.1" to="1.0.2"> <script sql="ccm-ldn-theme/upgrade/::database::-1.0.1-1.0.2.sql"/> </version> + <version from="6.3.0" to="6.3.1"> + <script sql="ccm-ldn-theme/upgrade/::database::-6.3.0-6.3.1.sql"/> + </version> </upgrade> Modified: trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ThemeFile.java =================================================================== --- trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ThemeFile.java 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ThemeFile.java 2005-11-09 17:10:48 UTC (rev 988) @@ -19,7 +19,6 @@ package com.arsdigita.london.theme; import com.arsdigita.util.Assert; -import com.arsdigita.kernel.ACSObject; import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.OID; import com.arsdigita.domain.DataObjectNotFoundException; @@ -42,7 +41,7 @@ public class ThemeFile extends DomainObject { private static final Logger s_log = - Logger.getLogger(ACSObject.class); + Logger.getLogger(ThemeFile.class); public static final String BASE_DATA_OBJECT_TYPE = "com.arsdigita.london.theme.ThemeFile"; @@ -53,6 +52,7 @@ public static final String LAST_MODIFIED_DATE = "lastModifiedDate"; public static final String CONTENT = "content"; public static final String THEME = "theme"; + public static final String DELETED = "deleted"; /** @@ -167,4 +167,12 @@ return null; } } + + public void setDeleted(boolean deleted) { + set(DELETED, new Boolean(deleted)); + } + + public boolean isDeleted() { + return Boolean.TRUE.equals(get(DELETED)); + } } Modified: trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ThemeFileCollection.java =================================================================== --- trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ThemeFileCollection.java 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ThemeFileCollection.java 2005-11-09 17:10:48 UTC (rev 988) @@ -63,4 +63,8 @@ public Date getLastModifiedDate() { return(Date)m_dataCollection.get(ThemeFile.LAST_MODIFIED_DATE); } + + public boolean isDeleted() { + return Boolean.TRUE.equals(m_dataCollection.get(ThemeFile.DELETED)); + } } Modified: trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/ThemeFilesList.java =================================================================== --- trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/ThemeFilesList.java 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/ThemeFilesList.java 2005-11-09 17:10:48 UTC (rev 988) @@ -5,12 +5,12 @@ * 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 @@ -18,19 +18,26 @@ package com.arsdigita.london.theme.ui; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; import com.arsdigita.bebop.PageState; -import com.arsdigita.london.theme.util.GlobalizationUtil; import com.arsdigita.bebop.SimpleContainer; -import com.arsdigita.bebop.Label; -import com.arsdigita.bebop.PageState; +import com.arsdigita.london.theme.Theme; import com.arsdigita.london.theme.ThemeConstants; -import com.arsdigita.london.theme.Theme; -import com.arsdigita.xml.Element; +import com.arsdigita.london.theme.ThemeFile; +import com.arsdigita.london.theme.ThemeFileCollection; +import com.arsdigita.london.theme.ui.listeners.FileRemovalRequestListener; +import com.arsdigita.london.theme.util.GlobalizationUtil; +import com.arsdigita.london.theme.util.ThemeFileUtil; +import com.arsdigita.toolbox.ui.FormatStandards; import com.arsdigita.util.Files; -import com.arsdigita.toolbox.ui.FormatStandards; import com.arsdigita.web.Web; +import com.arsdigita.xml.Element; import java.io.File; import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import org.apache.log4j.Logger; /** @@ -39,7 +46,10 @@ * @author Randy Graebner <ra...@re...> */ class ThemeFilesList extends SimpleContainer implements ThemeConstants { - + + private static final Logger s_log = + Logger.getLogger(ThemeFilesList.class); + private final static String XML_FOLDER = THEME_XML_PREFIX + "folder"; private final static String XML_FILE = THEME_XML_PREFIX + "file"; @@ -53,22 +63,38 @@ add(heading); } + public void register(Page page) { + page.addRequestListener(new FileRemovalRequestListener()); + } + public void generateChildrenXML(PageState state, Element root) { super.generateChildrenXML(state, root); File currentRoot = new File(Web.getServletContext().getRealPath("/")); Theme theme = m_model.getSelectedTheme(state); - File themes = new File(currentRoot, DEV_THEMES_BASE_DIR + + File themes = new File(currentRoot, DEV_THEMES_BASE_DIR + theme.getURL()); - + Element folder = root.newChildElement(XML_FOLDER, XML_NS); folder.addAttribute("name", theme.getURL()); folder.addAttribute("depth", ""); - generateFolderXML(themes, folder, "-"); + HashMap themeFiles = new HashMap(); + ThemeFileCollection collection = theme.getDraftThemeFiles(); + if (collection != null) { + while (collection.next()) { + ThemeFile tfile = collection.getThemeFile(); + String tfilePath = themes.getAbsolutePath() + File.separator + tfile.getFilePath(); + themeFiles.put(tfilePath, tfile); + } + } + + generateFolderXML(state, themes, folder, themeFiles, "-"); } - - private void generateFolderXML(File baseDirectory, + + private void generateFolderXML(PageState state, + File baseDirectory, Element folderElement, + Map themeFiles, String depth) { File tempFile = null; String[] list = baseDirectory.list(); @@ -78,12 +104,25 @@ tempFile = new File(baseDirectory, list[i]); if (tempFile.isDirectory()) { childElement = folderElement.newChildElement(XML_FOLDER, XML_NS); - generateFolderXML(tempFile, childElement, depth+"-"); + generateFolderXML(state, tempFile, childElement, themeFiles, depth+"-"); } else { childElement = folderElement.newChildElement(XML_FILE, XML_NS); + childElement.addAttribute("inWhiteList", + String.valueOf(ThemeFileUtil.inWhiteList(tempFile))); + ThemeFile dbtFile = (ThemeFile) themeFiles.get(tempFile.getAbsolutePath()); + childElement.addAttribute("inDatabase", String.valueOf(dbtFile != null)); + if (dbtFile != null) { + childElement.addAttribute("fileID", dbtFile.getID().toString()); + boolean scheduledForRemoval = dbtFile.isDeleted() + && dbtFile.getLastModifiedDate().after(new Date(tempFile.lastModified())); + childElement.addAttribute("isDeleted", String.valueOf(scheduledForRemoval)); + if (!scheduledForRemoval) { + childElement.addAttribute("removeURL", state.toURL() + "&fileID=" + dbtFile.getID()); + } + } } childElement.addAttribute - ("lastModified", + ("lastModified", FormatStandards.formatDateTime(new Date(tempFile.lastModified()))); childElement.addAttribute("size", Files.getPrettySize(tempFile)); childElement.addAttribute("name", tempFile.getName()); Added: trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/listeners/FileRemovalRequestListener.java =================================================================== --- trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/listeners/FileRemovalRequestListener.java 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/listeners/FileRemovalRequestListener.java 2005-11-09 17:10:48 UTC (rev 988) @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2001-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.london.theme.ui.listeners; + +import com.arsdigita.bebop.event.RequestEvent; +import com.arsdigita.bebop.event.RequestListener; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.london.theme.ThemeConstants; +import com.arsdigita.london.theme.ThemeFile; +import com.arsdigita.persistence.OID; +import java.math.BigDecimal; +import java.util.Date; +import org.apache.log4j.Logger; + +/** + * This listener schedules selected theme file for removal. + * On the next run of development file theme manager, it will be erased + * from the disk. + * + * @author Sebastian Skracic ssk...@re... + */ +public class FileRemovalRequestListener implements ThemeConstants, RequestListener { + + private static final Logger s_log = + Logger.getLogger(FileRemovalRequestListener.class); + + public void pageRequested(RequestEvent e) { + String fileID = e.getPageState().getRequest().getParameter("fileID"); + if (fileID != null) { + ThemeFile tf = (ThemeFile) DomainObjectFactory.newInstance( + new OID(ThemeFile.BASE_DATA_OBJECT_TYPE, new BigDecimal(fileID))); + tf.setDeleted(true); + tf.setLastModifiedDate(new Date()); + tf.save(); + } + } +} + Property changes on: trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/ui/listeners/FileRemovalRequestListener.java ___________________________________________________________________ Name: svn:keywords + Id Author URL Modified: trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/util/ThemeFileManager.java =================================================================== --- trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/util/ThemeFileManager.java 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/util/ThemeFileManager.java 2005-11-09 17:10:48 UTC (rev 988) @@ -35,9 +35,9 @@ /** - * Class for polling the database to look for new/updated files in - * the ThemeFile table. - * + * Class for polling the database to look for new/updated files in + * the ThemeFile table. + * * For "published" files, It goes through each Theme and looks at the * last time it was published. If the last time published > last * time thread was run then it examines those files. When the thread @@ -59,7 +59,7 @@ private static Logger s_log = Logger.getLogger(ThemeFileManager.class); - // The code in this class borrows heavily from + // The code in this class borrows heavily from // com.arsdigita.cms.publishToFile.FileManager @@ -78,7 +78,7 @@ private Date m_lastRunDate; - protected ThemeFileManager(int startupDelay, int pollDelay, + protected ThemeFileManager(int startupDelay, int pollDelay, String baseDirectory) { m_startupDelay = startupDelay; m_pollDelay = pollDelay; @@ -120,13 +120,13 @@ while ( (sleepSeconds(m_pollDelay) || m_ignoreInterrupt) && m_keepWatchingFiles ) { // Get the last run date before we do anything, - // so we can be sure that we do not miss any themes - // published while we run. But only store it after - // we have processed all themes, because it will be + // so we can be sure that we do not miss any themes + // published while we run. But only store it after + // we have processed all themes, because it will be // used in ThemePublishedFileManager.updateTheme(). Date lastRunDate = new Date(); - TransactionContext txn = + TransactionContext txn = SessionManager.getSession().getTransactionContext(); try { @@ -134,7 +134,7 @@ if (!txn.inTxn()) { txn.beginTxn(); startedTransaction = true; - } + } ThemeCollection collection = ThemeCollection.getAllThemes(); while (collection.next()) { updateTheme(collection.getTheme()); @@ -142,7 +142,7 @@ if (startedTransaction) { txn.commitTxn(); } - + m_lastRunDate = lastRunDate; } catch (Exception e) { s_log.warn("Ignoring uncaught exception", e); @@ -163,7 +163,7 @@ * instead of making it wait for the thread to wake up. */ public void updateAllThemesNow() { - // this call to interrupt should kill the current "run" that is + // this call to interrupt should kill the current "run" that is // occurring and break out of the sleep m_ignoreInterrupt = true; interrupt(); @@ -187,7 +187,7 @@ * hack is removed. * THIS IS A HACK BECAUSE IT REQUIRES A SERVER TO BE RUNNING */ - public String getBaseDirectory() { + public String getBaseDirectory() { if (m_baseDirectory == null) { ApplicationCollection collection = Application.retrieveAllApplications(); collection.filterToApplicationType(ThemeApplication.BASE_DATA_OBJECT_TYPE); @@ -205,7 +205,7 @@ ServletContext themeCtx = rootCtx.getContext(webapp); m_baseDirectory = themeCtx.getRealPath("/"); } - + return m_baseDirectory; } @@ -223,7 +223,7 @@ /* TODO: 1. provide a link to allow the user to force a sync of draft files - When the user syncs the draft files, do we tell all servers to + When the user syncs the draft files, do we tell all servers to insert in to the db and then tell all servers to sync with the db? Maybe outline this in the "known problems" which can be solved by only developing on one machine. @@ -243,7 +243,7 @@ In order for files to correctly propagate, all of the servers need to have clocks that are close to synchronized (at the very least, they must be set for the same time zone). - + */ /** @@ -255,32 +255,43 @@ String stub = getManagerSpecificDirectory(); // sync the files that have the correct dates s_log.debug("Looking at theme " + theme.getURL()); - + ThemeFileCollection files = getThemeFilesCollection(theme); if (files == null) { return; } while (files.next()) { - File temp = new File(stub + theme.getURL() + "/" + + File temp = new File(stub + theme.getURL() + "/" + files.getFilePath()); - // if the file in the db is newer than the file - // on the FS then write it out. + // if the file timestamp in the db is newer than the file + // on the FS then write it out (or delete). if (new Date(temp.lastModified()).before(files.getLastModifiedDate())) { - // now, we need to write out the file and + if (files.isDeleted()) { + if (temp.exists()) { + boolean success = temp.delete(); + if (success) { + s_log.info("Deletion of " + temp + " succeeded"); + } else { + s_log.error("Deletion of " + temp + " failed"); + } + } + continue; + } + // now, we need to write out the file and // log any errors we encounter FileOutputStream out = null; try { // make sure all of the directories exist temp.getParentFile().mkdirs(); s_log.debug("Writing file " + temp.getAbsolutePath()); - + byte[] content = files.getThemeFile().getContent(); out = new FileOutputStream(temp); out.write(content); temp.setLastModified(files.getLastModifiedDate().getTime()); } catch (IOException e) { - s_log.error("Error writing file " + + s_log.error("Error writing file " + temp.getAbsolutePath(), e); } finally { try { Modified: trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/util/ThemeFileUtil.java =================================================================== --- trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/util/ThemeFileUtil.java 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/src/com/arsdigita/london/theme/util/ThemeFileUtil.java 2005-11-09 17:10:48 UTC (rev 988) @@ -16,12 +16,14 @@ package com.arsdigita.london.theme.util; import com.arsdigita.london.theme.Theme; +import com.arsdigita.london.theme.ThemeApplication; import com.arsdigita.london.theme.ThemeFile; import com.arsdigita.london.theme.ThemeFileCollection; import com.arsdigita.util.Assert; import org.apache.log4j.Logger; import java.util.Date; import java.util.Map; +import java.util.Collection; import java.util.HashMap; import java.io.File; import java.io.IOException; @@ -43,9 +45,17 @@ private static Logger s_log = Logger.getLogger(ThemeFileUtil.class); + public static boolean inWhiteList(File file) { + Collection extensions = ThemeApplication.getConfig().getDownloadFileExtensions(); + String filename = file.getName(); + int extIndex = filename.lastIndexOf(".") + 1; + return extIndex > 0 + && filename.length() > extIndex + && extensions.contains(filename.substring(extIndex).toLowerCase()); + } /** - * this copies the files from the file system to the database. + * this copies the files from the file system to the database. * * @param currentFile The directory to search recursively for files * to put in the database or the single file to add to the db. @@ -63,7 +73,7 @@ * the database. * @param fileType The type of file this is. * ThemeFile.LIVE and ThemeFile.DRAFT are the two allowed values. - * + * */ public static void updateDatabaseFiles(File currentFile, Theme currentTheme, @@ -110,27 +120,32 @@ * the database. * @param fileType The type of file this is. * ThemeFile.LIVE and ThemeFile.DRAFT are the two allowed values. - * + * */ - private static void updateDatabaseFiles(File currentFile, - Theme currentTheme, - String serverSpecificPath, + private static void updateDatabaseFiles(File currentFile, + Theme currentTheme, + String serverSpecificPath, Map themeFiles, boolean overwriteNewerFiles, String fileType) { if (currentFile.isDirectory()) { File[] files = currentFile.listFiles(); for (int i = 0; i < files.length; i++) { - updateDatabaseFiles(files[i], currentTheme, + updateDatabaseFiles(files[i], currentTheme, serverSpecificPath, themeFiles, overwriteNewerFiles, fileType); - } + } } else { if (currentFile.exists()) { + // Skip the file if its extension is not in white list + if (!inWhiteList(currentFile)) { + s_log.warn("Not updating db: " + currentFile); + return; + } String fullFilePath = currentFile.getAbsolutePath(); String filePath = null; int beginIndex = fullFilePath.indexOf(serverSpecificPath); - if (beginIndex > -1 && + if (beginIndex > -1 && fullFilePath.length() > serverSpecificPath.length()) { filePath = fullFilePath.substring (beginIndex + serverSpecificPath.length() + 1); @@ -149,10 +164,18 @@ return; } } + // Undelete the file if it reappeared + if (themeFile != null + && themeFile.isDeleted() + && themeFile.getLastModifiedDate() + .before(new Date(currentFile.lastModified()))) { + themeFile.setDeleted(false); + s_log.warn("Undeleting the file: " + currentFile); + } try { FileInputStream in = new FileInputStream(currentFile); ByteArrayOutputStream os = new ByteArrayOutputStream(); - + byte[] buffer = new byte[8]; int length = -1; while ((length = in.read(buffer)) != -1) { @@ -160,7 +183,7 @@ } byte[] content = os.toByteArray(); - + if (themeFile == null) { themeFile = new ThemeFile(currentTheme, filePath); themeFiles.put(filePath, themeFile); @@ -180,7 +203,7 @@ currentFile.getAbsolutePath(), fnfe); } catch (IOException ex) { s_log.error("Error working with either the input or " + - " output stream for " + + " output stream for " + currentFile.getAbsolutePath(), ex); } } Modified: trunk/ccm-ldn-theme/web/__ccm__/apps/theme/xsl/index.xsl =================================================================== --- trunk/ccm-ldn-theme/web/__ccm__/apps/theme/xsl/index.xsl 2005-11-09 12:49:31 UTC (rev 987) +++ trunk/ccm-ldn-theme/web/__ccm__/apps/theme/xsl/index.xsl 2005-11-09 17:10:48 UTC (rev 988) @@ -24,16 +24,46 @@ </td> <xsl:if test="name()='theme:folder'"> - <td colspan="3"> + <td colspan="4"> <i><xsl:value-of select="@name"/></i> </td> </xsl:if> <xsl:if test="name()='theme:file'"> - <td><xsl:value-of select="@name"/></td> - <td><xsl:value-of select="@size"/></td> - <td><xsl:value-of select="@lastModified"/></td> + <xsl:choose> + <xsl:when test="@isDeleted='true' or @inWhiteList!='true'"> + <td><strike><xsl:value-of select="@name"/></strike></td> + <td><strike><xsl:value-of select="@size"/></strike></td> + <td><strike><xsl:value-of select="@lastModified"/></strike></td> + <td> + <xsl:choose> + <xsl:when test="@isDeleted='true'"> + <font color="red">(scheduled for removal)</font> + </xsl:when> + <xsl:otherwise> + (ignored) + </xsl:otherwise> + </xsl:choose> + </td> + </xsl:when> + <xsl:otherwise> + <td><xsl:value-of select="@name"/></td> + <td><xsl:value-of select="@size"/></td> + <td><xsl:value-of select="@lastModified"/></td> + <td> + <xsl:if test="@removeURL"> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="@removeURL"/> + </xsl:attribute> + Remove + </a> + </xsl:if> + </td> + </xsl:otherwise> + </xsl:choose> </xsl:if> + </tr> <xsl:apply-templates select="theme:file"> <xsl:sort select="./@name" data-type="text" order="ascending"/> |