Fixed problem with copying default theme to new theme's directory. Added Label as Widget attribute (but not evaluated by Mandalay theme engine). Still a NPE if theme evaluation detects an error, e.g. duplicate theme url.
git-svn-id: https://svn.libreccm.org/ccm/trunk@2681 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
e4823ae780
commit
6c272debdd
|
|
@ -65,7 +65,10 @@ import org.apache.log4j.Logger;
|
|||
*/
|
||||
public abstract class BaseApplicationServlet extends BaseServlet {
|
||||
|
||||
/** Logger instance for debugging purpose. */
|
||||
/** Internal logger instance to faciliate debugging. Enable logging output
|
||||
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
|
||||
* and set com.arsdigita.web.BaseApplicationServlet=DEBUG by uncommenting
|
||||
* or adding the line. */
|
||||
private static final Logger s_log = Logger.getLogger(BaseApplicationServlet.class);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,13 +34,14 @@ import org.apache.log4j.LogManager;
|
|||
import org.apache.log4j.PropertyConfigurator;
|
||||
|
||||
/**
|
||||
* Web application lifecycle listener, used to perform central initialisation tasks at CCM startup
|
||||
* in a Servlet container / web application server, expecially setting the runtime context (file
|
||||
* locations) and (in the future) the database connection.
|
||||
* Web application lifecycle listener, used to perform central initialisation
|
||||
* tasks at CCM startup in a Servlet container / web application server,
|
||||
* expecially setting the runtime context (file locations) and (in the future)
|
||||
* the database connection.
|
||||
*
|
||||
* The methods of this classes are by definition only invoked by the Servlet container / web
|
||||
* application server, not by any Servlet or java class of the application itself! Invocation is
|
||||
* managed by the deployment descriptor.
|
||||
* The methods of this classes are by definition only invoked by the Servlet
|
||||
* container / web application server, not by any Servlet or java class of the
|
||||
* application itself! Invocation is managed by the deployment descriptor.
|
||||
*
|
||||
* Note! Don't forget to configure it in web.xml deployment descriptor!
|
||||
* <listener>
|
||||
|
|
@ -48,25 +49,31 @@ import org.apache.log4j.PropertyConfigurator;
|
|||
* com.arsdigita.runtime.CCMApplicationContextListener
|
||||
* </listener-class>
|
||||
* </listener>
|
||||
* According to the 2.3 specification these tags must be placed after the filter tags and before the
|
||||
* Servlet tags!
|
||||
* According to the 2.3 specification these tags must be placed after the
|
||||
* filter tags and before the Servlet tags!
|
||||
*
|
||||
* @author pboy
|
||||
* @version $Id: $
|
||||
*/
|
||||
public class CCMApplicationContextListener implements ServletContextListener {
|
||||
|
||||
private static Logger s_log = Logger.getLogger(CCMApplicationContextListener.class);
|
||||
/** Internal logger instance to faciliate debugging. Enable logging output
|
||||
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
|
||||
* and set com.arsdigita.web.CCMApplicationContextListener=DEBUG by
|
||||
* uncommenting or adding the line. */
|
||||
private static final Logger s_log = Logger.getLogger(
|
||||
CCMApplicationContextListener.class);
|
||||
|
||||
private static Runtime runtime;
|
||||
|
||||
/**
|
||||
* Used to initialise classes at startup of the application, most of which needs to be plain
|
||||
* java objects (because they are also used by command line interface - installation,
|
||||
* configuration, maintenance).
|
||||
* Used to initialise classes at startup of the application, most of which
|
||||
* needs to be plain java objects (because they are also used by command
|
||||
* line interface - installation, configuration, maintenance).
|
||||
*
|
||||
* Here we provide one of the two supported ways to bring up the CCM application. This handles
|
||||
* the startup inside a Servlet container. The command line utilities handle the startup there.
|
||||
* Here we provide one of the two supported ways to bring up the CCM
|
||||
* application. This handles the startup inside a Servlet container.
|
||||
* The command line utilities handle the startup there.
|
||||
* Both initialise the same set of classes needed for CCM operations
|
||||
*
|
||||
* @param applicationStartEvent
|
||||
|
|
@ -124,6 +131,7 @@ public class CCMApplicationContextListener implements ServletContextListener {
|
|||
*
|
||||
* @param applicationEndEvent
|
||||
*/
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent applicationEndEvent) {
|
||||
s_log.info("Shutdown procedure started.");
|
||||
|
||||
|
|
|
|||
|
|
@ -115,8 +115,7 @@ public class Web {
|
|||
/**
|
||||
* Gets the servlet request object of the current thread.
|
||||
*
|
||||
* @return The current <code>HttpServletRequest</code>; it can be
|
||||
* null
|
||||
* @return The current <code>HttpServletRequest</code>; it can be null
|
||||
*/
|
||||
public static HttpServletRequest getRequest() {
|
||||
return (HttpServletRequest) s_request.get();
|
||||
|
|
@ -126,7 +125,6 @@ public class Web {
|
|||
* Gets the servlet context of the current thread.
|
||||
*
|
||||
* @return The current <code>ServletContext</code>; it can be null
|
||||
*
|
||||
*/
|
||||
public static ServletContext getServletContext() {
|
||||
return (ServletContext) s_servletContext.get();
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ public class ThemeDirectorConfig extends AbstractConfig {
|
|||
return s_conf;
|
||||
}
|
||||
|
||||
// set of configuration parameters
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
// Set of Configuration Parameters
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Directory that all of the default themes are copied from. */
|
||||
|
|
@ -74,19 +75,19 @@ public class ThemeDirectorConfig extends AbstractConfig {
|
|||
("themedirector.default_theme_path",
|
||||
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, "");
|
||||
// /** 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
|
||||
|
|
@ -143,10 +144,11 @@ public class ThemeDirectorConfig extends AbstractConfig {
|
|||
*/
|
||||
public ThemeDirectorConfig() {
|
||||
|
||||
register(m_fileExtParam);
|
||||
register(m_defaultThemeContext);
|
||||
register(m_defaultThemeManifest);
|
||||
register(m_defaultThemePath);
|
||||
// register(m_defaultThemeContext);
|
||||
register(m_defaultThemeManifest);
|
||||
register(m_fileExtParam);
|
||||
|
||||
register(m_themeDevFileWatchStartupDelay);
|
||||
register(m_themeDevFileWatchPollDelay);
|
||||
register(m_themePubFileWatchStartupDelay);
|
||||
|
|
@ -155,6 +157,88 @@ public class ThemeDirectorConfig extends AbstractConfig {
|
|||
loadInfo();
|
||||
}
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
// Set of Configuration Parameters
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the path to a directory containing a complete set of theme
|
||||
* files to copy into a new theme as a default implementation.
|
||||
* By default it is set to a master directory containing the distribution's
|
||||
* default theme. When creating a new theme it is copied over to provide
|
||||
* a default for the new theme.
|
||||
*
|
||||
* Developer's note:
|
||||
* Previously it was used as a string to filter a files directory stored in
|
||||
* the Manifest file. Matching files were copied to the new theme's directory.
|
||||
* The reason to use this approach is not documented. As a guess: it enables
|
||||
* to copy from more than one directory, if those directories share a common
|
||||
* name part which is specified here. But because all files must be present
|
||||
* at deploy time to be included into the Manifest file it makes no sense.
|
||||
* From original comment: "Specifically, if this is not null
|
||||
* (or the empty string) than any file that is used as part of
|
||||
* the default directory must start with this string."
|
||||
*
|
||||
* @return name of a directory containing a default theme implementation
|
||||
*/
|
||||
public String getDefaultThemePath() {
|
||||
String defaultThemePath = (String)get(m_defaultThemePath);
|
||||
if (defaultThemePath == null || defaultThemePath.trim().length() == 0) {
|
||||
return null;
|
||||
}
|
||||
// remove leading slashwhich is already included in themedirector's
|
||||
// constants of the directory layout.
|
||||
if (defaultThemePath.startsWith("/")) {
|
||||
defaultThemePath = defaultThemePath.substring(1);
|
||||
}
|
||||
return defaultThemePath;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * This returns the name of the servlet context containing
|
||||
// * the default theme.
|
||||
// *
|
||||
// * @return
|
||||
// * @deprecated without direct replacement, See note above
|
||||
// */
|
||||
// public String getDefaultThemeContext() {
|
||||
// String ctx = (String)get(m_defaultThemeContext);
|
||||
// if (ctx == null) {
|
||||
// ctx = "/";
|
||||
// }
|
||||
// if (!ctx.endsWith("/")) {
|
||||
// ctx = ctx + "/";
|
||||
// }
|
||||
// if (!ctx.startsWith("/")) {
|
||||
// ctx = "/" + ctx;
|
||||
// }
|
||||
// return ctx;
|
||||
// }
|
||||
|
||||
/**
|
||||
* This returns the name of the manifest file containing a list of default
|
||||
* theme.
|
||||
*
|
||||
* @return
|
||||
* @deprecated replaced by a direct copy from the default directory
|
||||
*/
|
||||
public String getDefaultThemeManifest() {
|
||||
return (String)get(m_defaultThemeManifest);
|
||||
}
|
||||
|
||||
|
||||
private static final String DEFAULT_THEME_URL =
|
||||
ThemeDirector.DEFAULT_THEME + "." + Theme.URL;
|
||||
private static final String DEFAULT_THEME_URL_ATTRIBUTE =
|
||||
"defaultThemeURLAttribute";
|
||||
|
||||
/**
|
||||
* Purpose uncodumented.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Collection getDownloadFileExtensions() {
|
||||
if (m_downloadFileExtensions == null) {
|
||||
String extensions = (String)get(m_fileExtParam);
|
||||
|
|
@ -171,89 +255,7 @@ public class ThemeDirectorConfig extends AbstractConfig {
|
|||
|
||||
|
||||
/**
|
||||
* The number of seconds to wait before checking the database
|
||||
* for the first time. A value of 0 means that the thread
|
||||
* should not be started. This checks for published files.
|
||||
*/
|
||||
public Integer getThemePubFileWatchStartupDelay() {
|
||||
return (Integer)get(m_themePubFileWatchStartupDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of seconds between checking for updated
|
||||
* files in the file system. This checks for published files.
|
||||
*/
|
||||
public Integer getThemePubFileWatchPollDelay() {
|
||||
return (Integer)get(m_themePubFileWatchPollDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of seconds to wait before checking the database
|
||||
* for the first time. A value of 0 means that the thread
|
||||
* should not be started. This checks for development files.
|
||||
*/
|
||||
public Integer getThemeDevFileWatchStartupDelay() {
|
||||
return (Integer)get(m_themeDevFileWatchStartupDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of seconds between checking for updated
|
||||
* files in the file system. This checks for development files.
|
||||
*/
|
||||
public Integer getThemeDevFileWatchPollDelay() {
|
||||
return (Integer)get(m_themeDevFileWatchPollDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the name of the servlet context containing
|
||||
* the default theme
|
||||
*/
|
||||
public String getDefaultThemeContext() {
|
||||
String ctx = (String)get(m_defaultThemeContext);
|
||||
if (ctx == null) {
|
||||
ctx = "/";
|
||||
}
|
||||
if (!ctx.endsWith("/")) {
|
||||
ctx = ctx + "/";
|
||||
}
|
||||
if (!ctx.startsWith("/")) {
|
||||
ctx = "/" + ctx;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the name of the manifest file containing
|
||||
* the default theme.
|
||||
*/
|
||||
public String getDefaultThemeManifest() {
|
||||
return (String)get(m_defaultThemeManifest);
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a string that can be used as a file filter for
|
||||
* the default directory. Specifically, if this is not null
|
||||
* (or the empty string) than any file that is used as part of
|
||||
* the default directory must start with this string
|
||||
*/
|
||||
public String getDefaultThemePath() {
|
||||
String defaultThemePath = (String)get(m_defaultThemePath);
|
||||
if (defaultThemePath == null || defaultThemePath.trim().length() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (defaultThemePath.startsWith("/")) {
|
||||
defaultThemePath = defaultThemePath.substring(1);
|
||||
}
|
||||
return defaultThemePath;
|
||||
}
|
||||
|
||||
|
||||
private static final String DEFAULT_THEME_URL =
|
||||
ThemeDirector.DEFAULT_THEME + "." + Theme.URL;
|
||||
private static final String DEFAULT_THEME_URL_ATTRIBUTE =
|
||||
"defaultThemeURLAttribute";
|
||||
|
||||
/**
|
||||
* Purpose undocumented.
|
||||
*
|
||||
* @param req
|
||||
* @return
|
||||
|
|
@ -285,4 +287,45 @@ public class ThemeDirectorConfig extends AbstractConfig {
|
|||
req.setAttribute( DEFAULT_THEME_URL_ATTRIBUTE, themeURL );
|
||||
return themeURL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The number of seconds to wait before checking the database
|
||||
* for the first time. A value of 0 means that the thread
|
||||
* should not be started. This checks for published files.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Integer getThemePubFileWatchStartupDelay() {
|
||||
return (Integer)get(m_themePubFileWatchStartupDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of seconds between checking for updated
|
||||
* files in the file system. This checks for published files.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Integer getThemePubFileWatchPollDelay() {
|
||||
return (Integer)get(m_themePubFileWatchPollDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of seconds to wait before checking the database
|
||||
* for the first time. A value of 0 means that the thread
|
||||
* should not be started. This checks for development files.
|
||||
* @return
|
||||
*/
|
||||
public Integer getThemeDevFileWatchStartupDelay() {
|
||||
return (Integer)get(m_themeDevFileWatchStartupDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of seconds between checking for updated
|
||||
* files in the file system. This checks for development files.
|
||||
* @return
|
||||
*/
|
||||
public Integer getThemeDevFileWatchPollDelay() {
|
||||
return (Integer)get(m_themeDevFileWatchPollDelay);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,27 +35,29 @@ public interface ThemeDirectorConstants {
|
|||
public final static String DEV_DIR_STUB = "/devel-themedir";
|
||||
|
||||
/** Path stub into directory for production themes (sub-dir of THEMES_DIR).
|
||||
* According to JavaEE spec with leading but without trailing "/"! */
|
||||
* According to JavaEE spec with leading "/", but deviating from the
|
||||
* JavaEE spec we add a trailing "/" for backwards compatibility to
|
||||
* versions of CCM! */
|
||||
public final static String
|
||||
PROD_THEMES_BASE_DIR = THEMES_DIR + PROD_DIR_STUB;
|
||||
PROD_THEMES_BASE_DIR = THEMES_DIR + PROD_DIR_STUB + "/";
|
||||
/** Path stub into directory for production themes (sub-dir of THEMES_DIR).
|
||||
* According to JavaEE spec with leading but without trailing "/"! */
|
||||
* According to JavaEE spec with leading "/", but deviating from the
|
||||
* JavaEE spec we add a trailing "/" for backwards compatibility to
|
||||
* versions of CCM! */
|
||||
public final static String
|
||||
DEV_THEMES_BASE_DIR = THEMES_DIR + DEV_DIR_STUB ;
|
||||
DEV_THEMES_BASE_DIR = THEMES_DIR + DEV_DIR_STUB + "/";
|
||||
|
||||
// ccm-themedirector (formerly ccm-ldn-theme) is no longer installed in its
|
||||
// own web context (ROOT or ccm-ldn-theme/ccm-themedirector) so it is not
|
||||
// needed anymore. We we want to install it in its own context again, we
|
||||
// should find a way to determin the context from a central configuration.
|
||||
// public final static String WEB_APP_NAME = "ROOT";
|
||||
// Developers NOTE:
|
||||
// ================
|
||||
// We should consider to use the theme's url as entered by the user with
|
||||
// a leading slash according to the specification and for sake of
|
||||
// consistency within CCM.
|
||||
// We would have to adjust the validation listener and the process listener
|
||||
// in class ui/ThemeForm and to update the existing themes in the database.
|
||||
|
||||
/** The location of the sync jsp used to sync up the multiple servers. */
|
||||
public final static String SYNC_JSP = "sync-theme.jsp";
|
||||
|
||||
/** This can be used to find the root webapp directory that is used
|
||||
by default for most of the applications in CCM */
|
||||
public final static String ROOT_WEBAPP_PATH = "/ROOT";
|
||||
|
||||
public static final String THEME_XML_PREFIX = "theme:";
|
||||
public final static String XML_NS =
|
||||
"http://ccm.redhat.com/themedirector/1.0";
|
||||
|
|
|
|||
|
|
@ -32,3 +32,9 @@ theme.undo.default_style=Default Style
|
|||
theme.none=None
|
||||
theme.save=Save
|
||||
theme.set_default_theme=Default Theme
|
||||
theme.title_hint=Enter the title of the theme, up to 80 characters.
|
||||
theme.description_hint=Enter a short description for the theme, up to 4000 characters.
|
||||
theme.url_hint=Enter the LAST part of the url for the theme, eg 'holiday'. Should NOT include a leading nor a trailing slash!
|
||||
theme.save_button_hint=Save the details in the form
|
||||
theme.cancel_button_hint=Abort changes & reset the form.
|
||||
theme.cancel_button_pressed_msg=cancel pressed
|
||||
|
|
|
|||
|
|
@ -32,3 +32,9 @@ theme.undo.default_style=Standard-Theme
|
|||
theme.none=Keines
|
||||
theme.save=Speichern
|
||||
theme.set_default_theme=Standard-Theme
|
||||
theme.title_hint=Der Titel des Themes, kann bis zu 80 Zeichen lang sein.
|
||||
theme.description_hint=Geben Sie eine kurze Beschreibung ein, bis zu 4000 Zeichen lang.
|
||||
theme.url_hint=Geben Sie den LETZTEN Teil der URL ein, z.B. 'ferien'. Der Eintrag darf weder ein f\u00fchrendes noch ein abschlie\u00dfendes '/' enthalten!
|
||||
theme.save_button_hint=Speichern der Angaben in dem Formular.
|
||||
theme.cancel_button_hint=Verwerfen der Eintragungen und R\u00fccksetzen des Formulars.
|
||||
theme.cancel_button_pressed_msg=Vorgang abgebrochen
|
||||
|
|
|
|||
|
|
@ -32,3 +32,9 @@ theme.undo.default_style=Default Style
|
|||
theme.none=None
|
||||
theme.save=Save
|
||||
theme.set_default_theme=Default Theme
|
||||
theme.title_hint=Enter the title of the theme, up to 80 characters.
|
||||
theme.description_hint=Enter a short description for the theme, up to 4000 characters.
|
||||
theme.url_hint=Enter the LAST part of tht url for the theme, eg 'holiday'. Should NOT include a leading nor a trailing slash!
|
||||
theme.save_button_hint=Save the details in the form
|
||||
theme.cancel_button_hint=Abort changes & reset the form.
|
||||
theme.cancel_button_pressed_msg=cancel pressed
|
||||
|
|
|
|||
|
|
@ -32,3 +32,9 @@ theme.undo.default_style=Default Style
|
|||
theme.none=None
|
||||
theme.save=Save
|
||||
theme.set_default_theme=Default Theme
|
||||
theme.title_hint=Enter the title of the theme, up to 80 characters.
|
||||
theme.description_hint=Enter a short description for the theme, up to 4000 characters.
|
||||
theme.url_hint=Enter the LAST part of tht url for the theme, eg 'holiday'. Should NOT include a leading nor a trailing slash!
|
||||
theme.save_button_hint=Save the details in the form
|
||||
theme.cancel_button_hint=Abort changes & reset the form.
|
||||
theme.cancel_button_pressed_msg=cancel pressed
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ import java.io.File;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.filefilter.DirectoryFileFilter;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
|
@ -64,50 +66,68 @@ import org.apache.log4j.Logger;
|
|||
*/
|
||||
public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstants {
|
||||
|
||||
/** Internal logger instance to faciliate debugging. Enable logging output
|
||||
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
|
||||
* and set com.arsdigita.themedirector.ui.ThemeForm=DEBUG by uncommenting
|
||||
* or adding the line. */
|
||||
private static final Logger s_log = Logger.getLogger(ThemeForm.class);
|
||||
|
||||
private ThemeSelectionModel m_theme;
|
||||
private TextField m_title;
|
||||
private TextArea m_description;
|
||||
private TextField m_url;
|
||||
private SaveCancelSection m_buttons;
|
||||
private final ThemeSelectionModel m_theme;
|
||||
private final TextField m_title;
|
||||
private final TextArea m_description;
|
||||
private final TextField m_url;
|
||||
private final SaveCancelSection m_buttons;
|
||||
|
||||
/**
|
||||
* Constructor creats the input form to create a new theme or edit an
|
||||
* existing one.
|
||||
*
|
||||
* @param name
|
||||
* @param theme
|
||||
*/
|
||||
public ThemeForm(String name,
|
||||
ThemeSelectionModel theme) {
|
||||
super(name, new GridPanel(2));
|
||||
setClassAttr("simpleThemeForm");
|
||||
setRedirecting(true);
|
||||
|
||||
m_theme = theme;
|
||||
m_theme = theme; // Initialize ThemeSelectionModel
|
||||
|
||||
// Add the Title input field
|
||||
add(new Label(GlobalizationUtil.globalize("theme.title")));
|
||||
m_title = new TextField(new StringParameter("title"));
|
||||
// Experimental. We are migrating the Label if a widget as part of the
|
||||
// widgets's xml properties.
|
||||
m_title.setLabel(GlobalizationUtil.globalize("theme.title"));
|
||||
m_title.addValidationListener(new NotEmptyValidationListener());
|
||||
m_title.setHint("Enter the title of the theme, up to 80 characters");
|
||||
m_title.setHint(GlobalizationUtil.globalize("theme.title_hint"));
|
||||
m_title.setSize(40);
|
||||
add(m_title);
|
||||
|
||||
add(new Label(GlobalizationUtil.globalize("theme.description")));
|
||||
m_description = new TextArea(new StringParameter("description"));
|
||||
// Experimental, see above
|
||||
m_description.setLabel(GlobalizationUtil.globalize("theme.description"));
|
||||
m_description.setCols(40);
|
||||
m_description.setRows(4);
|
||||
m_description.setHint(
|
||||
"Enter a short description for the theme, up to 4000 characters"
|
||||
);
|
||||
m_description.setHint(GlobalizationUtil
|
||||
.globalize("theme.description_hint"));
|
||||
add(m_description);
|
||||
|
||||
add(new Label(GlobalizationUtil.globalize("theme.url")));
|
||||
m_url = new TextField(new StringParameter("url"));
|
||||
// Experimental, see above
|
||||
m_url.setLabel(GlobalizationUtil.globalize("theme.url"));
|
||||
m_url.addValidationListener(new NotEmptyValidationListener());
|
||||
m_title.setSize(40);
|
||||
m_url.setHint(
|
||||
"Enter the url for the theme, eg 'holiday'"
|
||||
);
|
||||
m_url.setHint(GlobalizationUtil.globalize("theme.url_hint"));
|
||||
add(m_url);
|
||||
|
||||
m_buttons = new SaveCancelSection();
|
||||
m_buttons.getSaveButton().setHint("Save the details in the form");
|
||||
m_buttons.getCancelButton().setHint("Abort changes & reset the form");
|
||||
m_buttons.getSaveButton().setHint(GlobalizationUtil
|
||||
.globalize("theme.save_button_hint"));
|
||||
m_buttons.getCancelButton().setHint(GlobalizationUtil
|
||||
.globalize("theme.cancel_button_hint"));
|
||||
add(m_buttons);
|
||||
|
||||
addSubmissionListener(new ThemeSubmissionListener());
|
||||
|
|
@ -116,23 +136,47 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
addValidationListener(new ThemeValidationListener());
|
||||
}
|
||||
|
||||
// if this form is cancelled
|
||||
/**
|
||||
* Processed if this form is cancelled.
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isCancelled(PageState s) {
|
||||
return m_buttons.getCancelButton().isSelected(s);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private class ThemeSubmissionListener implements FormSubmissionListener {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param e
|
||||
* @throws FormProcessException
|
||||
*/
|
||||
@Override
|
||||
public void submitted(FormSectionEvent e)
|
||||
throws FormProcessException {
|
||||
throws FormProcessException {
|
||||
PageState state = e.getPageState();
|
||||
|
||||
if (m_buttons.getCancelButton().isSelected(state)) {
|
||||
throw new FormProcessException("cancel pressed");
|
||||
throw new FormProcessException(
|
||||
"cancel pressed",
|
||||
GlobalizationUtil.globalize("theme.cancel_button_hint")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the theme form with appropriate values if theme already
|
||||
* exists.
|
||||
*/
|
||||
private class ThemeInitListener implements FormInitListener {
|
||||
@Override
|
||||
public void init(FormSectionEvent e)
|
||||
throws FormProcessException {
|
||||
PageState state = e.getPageState();
|
||||
|
|
@ -150,15 +194,34 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ProcessListener class to act upon the themedirector form input (after
|
||||
* successful input validation if any). It's process method is the entry
|
||||
* point.
|
||||
*/
|
||||
private class ThemeProcessListener implements FormProcessListener {
|
||||
|
||||
/**
|
||||
* Process the form input data. The data are first stored into the
|
||||
* database and than the file system is synced if required. In case of
|
||||
* a new theme the default theme files (if existent) are copied. If for
|
||||
* an existing theme the name (url) has changed, the filesystem
|
||||
* directories are modified accordingly.
|
||||
*
|
||||
* @param e
|
||||
* @throws FormProcessException
|
||||
*/
|
||||
@Override
|
||||
public void process(FormSectionEvent e)
|
||||
throws FormProcessException {
|
||||
throws FormProcessException {
|
||||
|
||||
PageState state = e.getPageState();
|
||||
|
||||
Theme theme = m_theme.getSelectedTheme(state);
|
||||
String oldURL = null;
|
||||
String newURL = null;
|
||||
if (theme == null) {
|
||||
/* We handle a new (created) theme. No previous values exist.*/
|
||||
newURL = (String)m_url.getValue(state);
|
||||
theme = new Theme((String)m_title.getValue(state),
|
||||
(String)m_description.getValue(state),
|
||||
|
|
@ -171,7 +234,7 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
theme.setURL(newURL);
|
||||
}
|
||||
|
||||
// only add the theme if it is published
|
||||
// only add to the theme if it is published
|
||||
if (theme.getLastPublishedUser() != null) {
|
||||
Subsite.getConfig().addTheme(theme.getURL(), theme.getTitle());
|
||||
}
|
||||
|
|
@ -180,24 +243,23 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
Subsite.getConfig().removeTheme(oldURL);
|
||||
}
|
||||
|
||||
theme.save();
|
||||
theme.save(); // save theme to database
|
||||
m_theme.setSelectedObject(state, theme);
|
||||
|
||||
// now that the db part is done, we do the file IO
|
||||
File newDirectory = null;
|
||||
File oldDirectory = null;
|
||||
try {
|
||||
// The WebAppRoot should be something like this:
|
||||
// /var/ccm-devel/web/<username>/<projectname>/webapps/ccm-ldn-theme;
|
||||
// Determine the WebAppRoot should be something like this:
|
||||
// /var/ccm-devel/web/<username>/<projectname>/webapps/libreccm;
|
||||
File currentRoot = new File(Web.getServletContext().getRealPath("/"));
|
||||
|
||||
newDirectory = new File(currentRoot, DEV_THEMES_BASE_DIR +
|
||||
newURL);
|
||||
if (newDirectory.exists() && !newURL.equals(oldURL)) {
|
||||
// this means there is a file in the file system
|
||||
// but not in the database
|
||||
// this should never happen because "validate" should
|
||||
// catch it.
|
||||
// this means there is a file in the file system but not in
|
||||
// the database this should never happen because "validate"
|
||||
// should catch it.
|
||||
throw new UncheckedWrapperException
|
||||
("The file " + newDirectory.getName() + " already " +
|
||||
"exists in the file system but not in the " +
|
||||
|
|
@ -210,16 +272,17 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
oldURL);
|
||||
}
|
||||
|
||||
if (oldURL == null || !oldDirectory.exists()) {
|
||||
// we make sure that the base directory exists and
|
||||
// then we copy the files over.
|
||||
if ( oldURL == null || !oldDirectory.exists()) {
|
||||
// we make sure that the base directory exists and then we
|
||||
// copy the files over.
|
||||
File baseDirectory = new File(currentRoot,
|
||||
DEV_THEMES_BASE_DIR);
|
||||
if (!baseDirectory.exists()) {
|
||||
baseDirectory.mkdirs();
|
||||
}
|
||||
|
||||
copyDefaultFiles(newDirectory);
|
||||
copyDefaultTheme(newDirectory,null);
|
||||
// copyDefaultFiles(newDirectory);
|
||||
|
||||
if (oldDirectory != null && !oldDirectory.exists()) {
|
||||
s_log.warn("We were asked to move files from " +
|
||||
|
|
@ -251,8 +314,9 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
// the old directory...we need them to point to the
|
||||
// new directory
|
||||
DataCollection collection =
|
||||
SessionManager.getSession().retrieve
|
||||
(Site.BASE_DATA_OBJECT_TYPE);
|
||||
SessionManager
|
||||
.getSession()
|
||||
.retrieve(Site.BASE_DATA_OBJECT_TYPE);
|
||||
collection.addEqualsFilter(Site.STYLE_DIRECTORY,
|
||||
oldURL);
|
||||
while (collection.next()) {
|
||||
|
|
@ -270,10 +334,23 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ValöidatgionListener class to check the themedirector form input data.
|
||||
* It's validate method is the entry point and executed when submitting
|
||||
* the form.
|
||||
*/
|
||||
private class ThemeValidationListener implements FormValidationListener {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param e
|
||||
* @throws FormProcessException
|
||||
*/
|
||||
@Override
|
||||
public void validate(FormSectionEvent e)
|
||||
throws FormProcessException {
|
||||
throws FormProcessException {
|
||||
PageState state = e.getPageState();
|
||||
|
||||
String url = (String)m_url.getValue(state);
|
||||
validateURLForm(state, url);
|
||||
validateURLUniqueness(state, url);
|
||||
|
|
@ -298,6 +375,9 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
/**
|
||||
* This checks the form of the url...specifically, we are only allowing
|
||||
* [A-Z,a-z,0-9,_,-].
|
||||
* @param state
|
||||
* @param url
|
||||
* @throws com.arsdigita.bebop.FormProcessException
|
||||
*/
|
||||
public void validateURLForm(PageState state, String url)
|
||||
throws FormProcessException {
|
||||
|
|
@ -316,13 +396,14 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This makes sure no other theme has the same URL
|
||||
* This makes sure no other theme has the same URL
|
||||
* @param state
|
||||
* @param url
|
||||
* @throws com.arsdigita.bebop.FormProcessException
|
||||
*/
|
||||
public void validateURLUniqueness(PageState state, String url)
|
||||
throws FormProcessException {
|
||||
throws FormProcessException {
|
||||
|
||||
if ( url != null ) {
|
||||
DataCollection collection = SessionManager.getSession()
|
||||
|
|
@ -341,10 +422,39 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a complete directory containing the default theme to a newly
|
||||
* created theme's directory without any filtering or other processing.
|
||||
* It assumes, that the source directory contains a complete and working
|
||||
* set of theme files.
|
||||
*
|
||||
* @param newThemeDirectory specifies the target directory. Must not
|
||||
* be null.
|
||||
* @param defaultThemeDirectory Directory containing a complete set of
|
||||
* theme files intended as default theme.
|
||||
* If null the default theme directory is
|
||||
* retrieved from ThemeDirector config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void copyDefaultTheme(File newThemeDirectory,
|
||||
File defaultThemeDirectory) throws IOException {
|
||||
if (defaultThemeDirectory == null) {
|
||||
defaultThemeDirectory = new File(
|
||||
Web.getServletContext().getRealPath("/")
|
||||
+ ThemeDirector.getConfig().getDefaultThemePath());
|
||||
}
|
||||
|
||||
FileUtils.copyDirectory(defaultThemeDirectory,
|
||||
newThemeDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* This copies the default theme files to the new directory that
|
||||
* is specified by the pass in File
|
||||
* Copies the default theme files to the new directory using a
|
||||
* Manifest file to determine the files to copy.
|
||||
*
|
||||
* @param newDirectory specifies the target directory
|
||||
* @throws IOException
|
||||
*/
|
||||
private void copyDefaultFiles(File newDirectory) throws IOException {
|
||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
|
|
@ -358,7 +468,8 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
}
|
||||
|
||||
if ( !newDirectory.mkdirs() ) {
|
||||
throw new UncheckedWrapperException("Cannot create theme directory "+newDirectory.getAbsolutePath());
|
||||
throw new UncheckedWrapperException("Cannot create theme directory "
|
||||
+newDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
ManifestReader reader =
|
||||
|
|
@ -367,10 +478,19 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private class FileWriterManifestReader extends ManifestReader {
|
||||
private File m_newDirectory;
|
||||
private String m_directoryFilter;
|
||||
private final File m_newDirectory;
|
||||
private final String m_directoryFilter;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param stream
|
||||
* @param newDirectory
|
||||
*/
|
||||
FileWriterManifestReader(InputStream stream, File newDirectory) {
|
||||
super(stream);
|
||||
m_newDirectory = newDirectory;
|
||||
|
|
@ -378,6 +498,13 @@ public class ThemeForm extends Form implements Cancellable, ThemeDirectorConstan
|
|||
m_directoryFilter = ThemeDirector.getConfig().getDefaultThemePath();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param is
|
||||
* @param filePath
|
||||
* @param isStyleFile
|
||||
*/
|
||||
@Override
|
||||
public void processManifestFileLine(InputStream is,
|
||||
String filePath,
|
||||
boolean isStyleFile) {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import java.util.Collection;
|
|||
import java.util.Iterator;
|
||||
import com.arsdigita.templating.XSLTemplate;
|
||||
import com.arsdigita.templating.WrappedTransformerException;
|
||||
import java.net.MalformedURLException;
|
||||
import javax.xml.transform.ErrorListener;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
|
@ -49,14 +50,19 @@ import javax.xml.transform.TransformerException;
|
|||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* This displays information about the results of running a validation
|
||||
* test on all of the stylesheets for a given theme. It also includes
|
||||
* links to "revalidate" and to return the viewing the theme.
|
||||
* This displays information about the results of running a validation test
|
||||
* on all of the stylesheets for a given theme. It also includes
|
||||
* links to "revalidate" and to return the viewing the theme.
|
||||
*
|
||||
* @author Randy Graebner <randyg@redhat.com>
|
||||
* @author Randy Graebner <randyg@redhat.com>
|
||||
*/
|
||||
class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
||||
|
||||
/** Internal logger instance to faciliate debugging. Enable logging output
|
||||
* by editing /WEB-INF/conf/log4j.properties int the runtime environment
|
||||
* and set
|
||||
* com.arsdigita.themedirector.ui.ThemeValidationPanel=DEBUG
|
||||
* by uncommenting or adding the line. */
|
||||
private static final Logger s_log =
|
||||
Logger.getLogger(ThemeValidationPanel.class);
|
||||
|
||||
|
|
@ -65,14 +71,16 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
RequestLocal m_listener;
|
||||
|
||||
/**
|
||||
* This creates a new validation panel
|
||||
* This creates a new validation panel.
|
||||
*
|
||||
* @param model This is the selection model so that the panel knows
|
||||
* which theme to operation on
|
||||
* which theme to operation on
|
||||
* @param container This is the parent container that holds this theme.
|
||||
* When the user wants to quit validation and return to where they were,
|
||||
* the visibility of the passed in container inverted (if it is visible
|
||||
* then it becomes invisible, if it is invisible, it becomes visible) and
|
||||
* this item becomes invisible.
|
||||
* When the user wants to quit validation and return
|
||||
* to where they were, the visibility of the passed in
|
||||
* container inverted (if it is visible then it becomes
|
||||
* invisible, if it is invisible, it becomes visible) and
|
||||
* this item becomes invisible.
|
||||
*/
|
||||
// TODO: passing in the container is a hackish way to do the visibility...
|
||||
// is there a better way to do this?
|
||||
|
|
@ -80,8 +88,8 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
SimpleComponent parentContainer) {
|
||||
super(1);
|
||||
m_model = model;
|
||||
Label results =
|
||||
new Label(GlobalizationUtil.globalize("theme.validation_results"));
|
||||
Label results = new Label(GlobalizationUtil
|
||||
.globalize("theme.validation_results"));
|
||||
results.setFontWeight(Label.BOLD);
|
||||
add(results);
|
||||
m_listener = new RequestLocal();
|
||||
|
|
@ -92,14 +100,16 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
new ActionLink(new Label(GlobalizationUtil.globalize
|
||||
("theme.revalidate_theme")));
|
||||
revalidateLink.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
validateStylesheets(e.getPageState());
|
||||
}
|
||||
});
|
||||
add(revalidateLink);
|
||||
|
||||
ToggleActionLink returnLink = new ToggleActionLink
|
||||
(new Label(GlobalizationUtil.globalize("theme.return_to_previous")));
|
||||
ToggleActionLink returnLink = new ToggleActionLink(new Label(
|
||||
GlobalizationUtil
|
||||
.globalize("theme.return_to_previous")));
|
||||
returnLink.addToggleComponent(this);
|
||||
returnLink.addToggleComponent(parentContainer);
|
||||
add(returnLink);
|
||||
|
|
@ -112,7 +122,7 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
* class but this is more clear as to what is being done.
|
||||
*/
|
||||
private class ToggleActionLink extends ActionLink implements ActionListener {
|
||||
private ArrayList m_components;
|
||||
private final ArrayList m_components;
|
||||
|
||||
ToggleActionLink(Label name) {
|
||||
super(name);
|
||||
|
|
@ -120,6 +130,7 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
addActionListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Iterator iter = m_components.iterator();
|
||||
PageState state = e.getPageState();
|
||||
|
|
@ -149,35 +160,45 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
|
||||
|
||||
/**
|
||||
* This method sets up the validation by finding the correct base
|
||||
* directory and setting up other necessary initialization variables
|
||||
* This method sets up the validation by finding the correct base
|
||||
* directory and setting up other necessary initialization variables.
|
||||
*
|
||||
* @param state
|
||||
* @param listener
|
||||
*/
|
||||
private boolean validateStylesheets(PageState state,
|
||||
LoggingErrorListener listener) {
|
||||
// this should verify the stylesheets and then present
|
||||
// any error messages that are found
|
||||
|
||||
/* Determine the theme to check */
|
||||
Theme theme = m_model.getSelectedTheme(state);
|
||||
|
||||
// The call to resolve returns a url similar to this:
|
||||
// http://localhost:9008/resource/ccm-ldn-theme,ROOT/themes/heirloom/apps/theme/xsl/index.xs
|
||||
//
|
||||
// TODO: This is VERY UGLY! Bad style to code a path into source code!
|
||||
// String base = "http://" + Web.getConfig().getHost().toString() +
|
||||
// "/resource/ccm-ldn-theme/";
|
||||
String base = "http://" + Web.getConfig().getHost().toString() +
|
||||
"/resource/ROOT/";
|
||||
/* Determine the location in the servers file system */
|
||||
File currentRoot = new File(Web.getServletContext().getRealPath("/"));
|
||||
File devDir = new File(currentRoot, DEV_THEMES_BASE_DIR +
|
||||
theme.getURL());
|
||||
File devDir = new File(currentRoot,
|
||||
DEV_THEMES_BASE_DIR + theme.getURL() );
|
||||
|
||||
// TODO: There has to be a better way to do this
|
||||
String stylesheetPath = base +
|
||||
DEV_THEMES_BASE_DIR + theme.getURL();
|
||||
/* Determine the URL to the stylesheets. Usually the URL is determined
|
||||
by the templating system, based on a stylesheetPath.txt file
|
||||
containing patterns to search for.
|
||||
|
||||
Developer's Note:
|
||||
We used to use a 'resource' tag involing a resource servlet to
|
||||
deliver the correct file either from database or filesystem. Ir would
|
||||
require an URL similar to
|
||||
http://localhost:9008/libreccm/resource/themes/heirloom/apps/theme/xsl/index.xs
|
||||
where librecms is the context ccm happpens to be installed in.
|
||||
Currently we bypass the resource servlet and access the filesystem
|
||||
directly. Must be modified as soon as we deliver the theme from db. */
|
||||
String stylesheetPath = "http://" + Web.getConfig().getHost().toString()
|
||||
+ Web.getWebappContextPath()
|
||||
+ DEV_THEMES_BASE_DIR + theme.getURL() ;
|
||||
|
||||
if (s_log.isDebugEnabled()) {
|
||||
s_log.debug("Path is " + stylesheetPath);
|
||||
}
|
||||
|
||||
// this should verify the stylesheets and then present
|
||||
// any error messages that are found
|
||||
checkFiles(devDir, stylesheetPath, listener);
|
||||
|
||||
return !listener.hasErrors();
|
||||
|
|
@ -189,7 +210,8 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
* the entire folder subtree, loading every single available xsl
|
||||
* file.
|
||||
*/
|
||||
private void checkFiles(File baseDirectory, String basePath,
|
||||
private void checkFiles(File baseDirectory,
|
||||
String basePath,
|
||||
ErrorListener listener) {
|
||||
File[] list = baseDirectory.listFiles(new XSLFileFilter());
|
||||
if (list == null) {
|
||||
|
|
@ -203,43 +225,39 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
// future caught errors. This is sort of a hack but I am not
|
||||
// sure of a better way around it
|
||||
boolean transformUsesListener = true;
|
||||
|
||||
for (int i = 0; i < list.length; i ++) {
|
||||
if (list[i].isDirectory()) {
|
||||
// Only check top level XSL - the rest are xsl:import'd
|
||||
//checkFiles(list[i], basePath + "/" + list[i].getName(),
|
||||
// listener);
|
||||
for (File list1 : list) {
|
||||
if (list1.isDirectory()) {
|
||||
} else {
|
||||
String filePath = basePath + "/" + list[i].getName();
|
||||
String filePath = basePath + "/" + list1.getName();
|
||||
try {
|
||||
URL stylesheetURL = new URL(filePath);
|
||||
if (s_log.isDebugEnabled()) {
|
||||
s_log.debug("Validating " + stylesheetURL);
|
||||
}
|
||||
XSLTemplate template = new XSLTemplate(stylesheetURL,
|
||||
listener);
|
||||
listener);
|
||||
} catch (WrappedTransformerException we) {
|
||||
if (transformUsesListener &&
|
||||
listener instanceof LoggingErrorListener &&
|
||||
!((LoggingErrorListener)listener).hasErrors()) {
|
||||
listener instanceof LoggingErrorListener &&
|
||||
!((LoggingErrorListener)listener).hasErrors()) {
|
||||
transformUsesListener = false;
|
||||
}
|
||||
if (!transformUsesListener) {
|
||||
TransformerException transEx =
|
||||
(TransformerException)we.getRootCause();
|
||||
(TransformerException)we.getRootCause();
|
||||
try {
|
||||
listener.error(transEx);
|
||||
} catch (TransformerException transformerEx) {
|
||||
s_log.error("Error logging the exception " +
|
||||
transEx.getMessage(),
|
||||
transformerEx);
|
||||
transEx.getMessage(),
|
||||
transformerEx);
|
||||
transEx.printStackTrace();
|
||||
}
|
||||
}
|
||||
s_log.debug("Wrapper excpetion thrown");
|
||||
} catch (Exception exp) {
|
||||
s_log.warn("Error creating template that was not a " +
|
||||
" standard wrapper transformer exception.",
|
||||
} catch (MalformedURLException exp) {
|
||||
s_log.warn("Error creating template that was not a "
|
||||
+ "standard wrapper transformer exception.",
|
||||
exp);
|
||||
}
|
||||
}
|
||||
|
|
@ -249,9 +267,10 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
|
||||
/**
|
||||
* This is simply used so that only directories and xsl files are
|
||||
* examined
|
||||
* examined.
|
||||
*/
|
||||
private static class XSLFileFilter implements FileFilter {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
return pathname.isDirectory() ||
|
||||
pathname.getName().endsWith(".xsl");
|
||||
|
|
@ -260,8 +279,8 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
|
||||
|
||||
private class ValidationResults extends SimpleContainer {
|
||||
private Label m_noErrorsLabel;
|
||||
private Label m_errorsLabel;
|
||||
private final Label m_noErrorsLabel;
|
||||
private final Label m_errorsLabel;
|
||||
|
||||
ValidationResults() {
|
||||
super();
|
||||
|
|
@ -299,8 +318,8 @@ class ThemeValidationPanel extends GridPanel implements ThemeDirectorConstants {
|
|||
|
||||
|
||||
/**
|
||||
* if the collection size > 0 then it prints out the xml
|
||||
* to display the messages
|
||||
* If the collection size > 0 then it prints out the xml
|
||||
* to display the messages.
|
||||
*/
|
||||
private void printMessages(String name, Element parent,
|
||||
Collection messages) {
|
||||
|
|
|
|||
|
|
@ -44,23 +44,40 @@ import java.util.TreeSet;
|
|||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* This approves the theme and pushes it to the production file location
|
||||
* This action means that the user wants to approve the themes and
|
||||
* push them live. This is done by copying the files from
|
||||
* This approves the theme and pushes it to the production file location
|
||||
* This action means that the user wants to approve the themes and
|
||||
* push them live. This is done by copying the files from the devel directory
|
||||
* into the published directory.
|
||||
*
|
||||
* @author Randy Graebner <randyg@redhat.com>
|
||||
*/
|
||||
public class ApproveThemeActionListener implements ThemeDirectorConstants, ActionListener {
|
||||
public class ApproveThemeActionListener implements ThemeDirectorConstants,
|
||||
ActionListener {
|
||||
|
||||
private static final Logger s_log =
|
||||
Logger.getLogger(ApproveThemeActionListener.class);
|
||||
/** Internal logger instance to faciliate debugging. Enable logging output
|
||||
* by editing /WEB-INF/conf/log4j.properties int the runtime environment
|
||||
* and set
|
||||
* com.arsdigita.themedirector.ui.listeners.ApproveThemeActionListener=DEBUG
|
||||
* by uncommenting or adding the line. */
|
||||
private static final Logger s_log = Logger.getLogger(
|
||||
ApproveThemeActionListener.class);
|
||||
|
||||
private ThemeSelectionModel m_model;
|
||||
private final ThemeSelectionModel m_model;
|
||||
|
||||
/**
|
||||
* Constructor, just stores the ThemeSelectionModel.
|
||||
*
|
||||
* @param model the ThemeSelectionModel
|
||||
*/
|
||||
public ApproveThemeActionListener(ThemeSelectionModel model) {
|
||||
m_model = model;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// First, we rename the current production directory
|
||||
// so that if there is an exception, we can try to move it
|
||||
|
|
|
|||
|
|
@ -19,32 +19,37 @@
|
|||
package com.arsdigita.themedirector.util;
|
||||
|
||||
|
||||
import com.arsdigita.themedirector.ThemeDirector;
|
||||
import com.arsdigita.themedirector.ThemeDirectorConstants;
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
import com.arsdigita.web.Web;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.LineNumberReader;
|
||||
import java.util.HashMap;
|
||||
import com.arsdigita.web.Web;
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
import java.util.Collection;
|
||||
import com.arsdigita.themedirector.ThemeDirector;
|
||||
import com.arsdigita.themedirector.ThemeDirectorConstants;
|
||||
import java.util.HashMap;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* This is a utility class that will take in a manifest file and
|
||||
* read it and then make calls to methods for each file that is found.
|
||||
* In a typical usage, code will subclass this so that certain methods
|
||||
* will write to different places. For instance, some code may
|
||||
* override the "processManifestFileLine" to write the contents to
|
||||
* the file system while another may write it to a zip file.
|
||||
* This is a utility class that will take in a manifest file, read it, and
|
||||
* then make calls to methods for each file that is found.
|
||||
* In a typical usage, code will subclass this so that certain methods will
|
||||
* write to different places. For instance, some code may override the
|
||||
* "processManifestFileLine" to write the contents to the file system
|
||||
* while another may write it to a zip file.
|
||||
*/
|
||||
public abstract class ManifestReader implements ThemeDirectorConstants {
|
||||
|
||||
private static final Logger s_log =
|
||||
Logger.getLogger(ManifestReader.class);
|
||||
/** Internal logger instance to faciliate debugging. Enable logging output
|
||||
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
|
||||
* and set com.arsdigita.themedirector.util.ManifestReader=DEBUG by
|
||||
* uncommenting or adding the line. */
|
||||
private static final Logger s_log = Logger.getLogger(ManifestReader.class);
|
||||
|
||||
private InputStream m_stream;
|
||||
private String m_fileName;
|
||||
|
|
@ -52,8 +57,10 @@ public abstract class ManifestReader implements ThemeDirectorConstants {
|
|||
private HashMap m_actualContextList;
|
||||
|
||||
/**
|
||||
* This takes in the actual input stream that is the Manifest File
|
||||
* so that the input stream can be correctly read
|
||||
* This takes in the actual input stream that is the Manifest File
|
||||
* so that the input stream can be correctly read.
|
||||
*
|
||||
* @param stream the input stream to read
|
||||
*/
|
||||
public ManifestReader(InputStream stream) {
|
||||
this(stream, null);
|
||||
|
|
@ -64,6 +71,8 @@ public abstract class ManifestReader implements ThemeDirectorConstants {
|
|||
* so that the input stream can be correctly read. It also
|
||||
* takes in the fileName so that it can be used in error messages
|
||||
* if there is an error.
|
||||
* @param stream the input stream to read
|
||||
* @param fileName
|
||||
*/
|
||||
public ManifestReader(InputStream stream, String fileName) {
|
||||
this(stream, fileName, null);
|
||||
|
|
@ -77,11 +86,11 @@ public abstract class ManifestReader implements ThemeDirectorConstants {
|
|||
* @param stream The input stream to read
|
||||
* @param fileName The name of the file we are reading that will
|
||||
* be displayed in the case of an error.
|
||||
* @param possibleServletContext The servlet context to try to use
|
||||
* when looking for files listed in the Manifest. This should be
|
||||
* set when it is know that the manifest file specifies files
|
||||
* that are located under a different webapps. If the
|
||||
* file is not found under this context or this context is null
|
||||
* @param possibleServletContext The servlet context to try to use when
|
||||
* looking for files listed in the Manifest. This should be set
|
||||
* when it is known that the manifest file specifies files that
|
||||
* are located under a different webapps. If the file ist not
|
||||
* found under this context or this context is null
|
||||
* then the file tries to use the default ServletContext
|
||||
*/
|
||||
public ManifestReader(InputStream stream, String fileName,
|
||||
|
|
@ -94,13 +103,20 @@ public abstract class ManifestReader implements ThemeDirectorConstants {
|
|||
|
||||
|
||||
/**
|
||||
* this is the name of the file that is being parsed. This will
|
||||
* return null if the name has not been set
|
||||
* Retrieves the name of the file that is being parsed. Will return null
|
||||
* if the name has not been set.
|
||||
*
|
||||
* @return file name if set, otherwise null
|
||||
*/
|
||||
public String getFileName() {
|
||||
return m_fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the file that is being parsed.
|
||||
*
|
||||
* @param fileName
|
||||
*/
|
||||
public void setFileName(String fileName) {
|
||||
m_fileName = fileName;
|
||||
}
|
||||
|
|
@ -112,17 +128,18 @@ public abstract class ManifestReader implements ThemeDirectorConstants {
|
|||
* this method will only really do anything once.
|
||||
*/
|
||||
public void processFile() {
|
||||
LineNumberReader lines =
|
||||
new LineNumberReader(new InputStreamReader(m_stream));
|
||||
Collection extensions = ThemeDirector.getConfig()
|
||||
.getDownloadFileExtensions();
|
||||
|
||||
try {
|
||||
String line = lines.readLine();
|
||||
while (line != null) {
|
||||
line = line.trim();
|
||||
LineNumberReader lines = new LineNumberReader(
|
||||
new InputStreamReader(m_stream));
|
||||
Collection extensions = ThemeDirector.getConfig()
|
||||
.getDownloadFileExtensions();
|
||||
|
||||
int fileExtensionIndex = line.lastIndexOf(".");
|
||||
try {
|
||||
String line = lines.readLine();
|
||||
while (line != null) {
|
||||
line = line.trim();
|
||||
|
||||
int fileExtensionIndex = line.lastIndexOf(".");
|
||||
|
||||
// We check the following things to set the boolean
|
||||
// indicating if it is a file that should
|
||||
|
|
@ -134,70 +151,77 @@ public abstract class ManifestReader implements ThemeDirectorConstants {
|
|||
// extensions as specified in the config file
|
||||
// 4. the file starts with the default directory and is
|
||||
// not just the directory itself
|
||||
boolean fileForDownload = fileExtensionIndex > -1 &&
|
||||
line.length() > (fileExtensionIndex+1) &&
|
||||
extensions.contains(line.substring(fileExtensionIndex+1)
|
||||
.toLowerCase());
|
||||
boolean fileForDownload = fileExtensionIndex > -1
|
||||
&& line.length() > (fileExtensionIndex+1)
|
||||
&& extensions.contains(line.substring(fileExtensionIndex+1)
|
||||
.toLowerCase());
|
||||
|
||||
// get the stream from the WAR or file system
|
||||
InputStream stream =
|
||||
getResourceAsStream(line, m_possibleServletContext);
|
||||
// get the stream from the WAR or file system
|
||||
InputStream stream = getResourceAsStream(line,
|
||||
m_possibleServletContext);
|
||||
|
||||
if (stream == null) {
|
||||
s_log.debug
|
||||
(m_fileName + ": " +
|
||||
lines.getLineNumber() +
|
||||
": no such resource '" + line + "'");
|
||||
} else {
|
||||
processManifestFileLine(stream, line, fileForDownload);
|
||||
|
||||
stream.close();
|
||||
}
|
||||
line = lines.readLine();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedWrapperException
|
||||
("Error with " + m_fileName + ": " +
|
||||
lines.getLineNumber(), e);
|
||||
} finally {
|
||||
try {
|
||||
m_stream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new UncheckedWrapperException(e);
|
||||
if (stream == null) {
|
||||
s_log.debug(m_fileName + ": " + lines.getLineNumber()
|
||||
+ ": no such resource '" + line + "'");
|
||||
} else {
|
||||
processManifestFileLine(stream, line, fileForDownload);
|
||||
stream.close();
|
||||
}
|
||||
line = lines.readLine();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedWrapperException("Error with " + m_fileName
|
||||
+ ": "
|
||||
+ lines.getLineNumber(), e);
|
||||
} finally {
|
||||
try {
|
||||
m_stream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new UncheckedWrapperException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This provides a way for child classes to look for the resource
|
||||
* in multiple places. By default, it only looks in the ServletContext
|
||||
* This provides a way for child classes to look for the resource in
|
||||
* multiple places. By default, it only looks in the ServletContext.
|
||||
*
|
||||
* @param line
|
||||
* @param possibleServletContext
|
||||
* @return stream, may be null
|
||||
*/
|
||||
protected InputStream getResourceAsStream(String line,
|
||||
String possibleServletContext) {
|
||||
InputStream stream = null;
|
||||
|
||||
if (possibleServletContext != null) {
|
||||
stream = Web.getServletContext().getContext(possibleServletContext)
|
||||
.getResourceAsStream(line);
|
||||
stream = Web.getServletContext() // gets the servlet context of
|
||||
// the current thread
|
||||
.getContext(possibleServletContext)
|
||||
.getResourceAsStream(line);
|
||||
}
|
||||
if (stream != null) {
|
||||
setActualContext
|
||||
(line,
|
||||
Web.getServletContext().getContext(possibleServletContext));
|
||||
setActualContext(line,
|
||||
Web.getServletContext()
|
||||
.getContext(possibleServletContext));
|
||||
} else {
|
||||
stream = Web.getServletContext().getResourceAsStream(line);
|
||||
stream = Web.getServletContext() // servlet ctx of actual thread
|
||||
.getResourceAsStream(line);
|
||||
|
||||
if (stream == null) {
|
||||
// this means that the file is not under the passed in
|
||||
// context or the default context so let's check the "ROOT"
|
||||
// context nor the default context so let's check the "ROOT"
|
||||
// context
|
||||
stream = Web.getServletContext().getContext(ROOT_WEBAPP_PATH)
|
||||
.getResourceAsStream(line);
|
||||
if (stream != null) {
|
||||
setActualContext(line, Web.getServletContext()
|
||||
.getContext(ROOT_WEBAPP_PATH));
|
||||
}
|
||||
// DEPRECATED. CCM may be installed at any context, in many
|
||||
// cases dedicatedly no longer in ROOT
|
||||
// stream = Web.getServletContext().getContext(ROOT_WEBAPP_PATH)
|
||||
// .getResourceAsStream(line);
|
||||
// if (stream != null) {
|
||||
// setActualContext(line, Web.getServletContext()
|
||||
// .getContext(ROOT_WEBAPP_PATH));
|
||||
// }
|
||||
} else {
|
||||
setActualContext(line, Web.getServletContext());
|
||||
}
|
||||
|
|
@ -207,14 +231,22 @@ public abstract class ManifestReader implements ThemeDirectorConstants {
|
|||
|
||||
|
||||
/**
|
||||
* This provides subclasses with access to the actual ServletContext
|
||||
* where the line is found. The info for the line should be available
|
||||
* when processManifestFileLine is called for a given line
|
||||
* This provides subclasses with access to the actual ServletContext
|
||||
* where the line is found. The info for the line should be available
|
||||
* when processManifestFileLine is called for a given line.
|
||||
*
|
||||
* @param line
|
||||
* @return
|
||||
*/
|
||||
protected ServletContext getActualContext(String line) {
|
||||
return (ServletContext)m_actualContextList.get(line);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param line
|
||||
* @param context
|
||||
*/
|
||||
protected void setActualContext(String line, ServletContext context) {
|
||||
m_actualContextList.put(line, context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,12 @@ import org.apache.log4j.Logger;
|
|||
*/
|
||||
public class ThemeDevelopmentFileManager extends ThemeFileManager {
|
||||
|
||||
private static Logger s_log =
|
||||
Logger.getLogger(ThemeDevelopmentFileManager.class);
|
||||
/** Internal logger instance to faciliate debugging. Enable logging output
|
||||
* by editing /WEB-INF/conf/log4j.properties int hte runtime environment
|
||||
* and set com.arsdigita.themedirector.util.ThemeDevelopmentFileManager=DEBUG
|
||||
* by uncommenting or adding the line. */
|
||||
private static Logger s_log = Logger
|
||||
.getLogger(ThemeDevelopmentFileManager.class);
|
||||
|
||||
// The code in this class borrows heavily from
|
||||
// com.arsdigita.cms.publishToFile.FileManager
|
||||
|
|
@ -51,13 +55,16 @@ public class ThemeDevelopmentFileManager extends ThemeFileManager {
|
|||
|
||||
/**
|
||||
* Constructor just delegates to super class.
|
||||
*
|
||||
* @param startupDelay
|
||||
* @param pollDelay
|
||||
* @param baseDirectory
|
||||
*/
|
||||
protected ThemeDevelopmentFileManager(int startupDelay, int pollDelay,
|
||||
String baseDirectory) {
|
||||
super(s_log, startupDelay, pollDelay, baseDirectory);
|
||||
|
||||
super(s_log, // Injects it's own logger
|
||||
startupDelay, pollDelay, baseDirectory); // to the parent class methods!
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,16 +16,12 @@
|
|||
package com.arsdigita.themedirector.util;
|
||||
|
||||
import com.arsdigita.themedirector.Theme;
|
||||
import com.arsdigita.themedirector.ThemeDirector;
|
||||
import com.arsdigita.themedirector.ThemeCollection;
|
||||
import com.arsdigita.themedirector.ThemeDirectorConstants;
|
||||
import com.arsdigita.themedirector.ThemeFileCollection;
|
||||
import com.arsdigita.persistence.SessionManager;
|
||||
import com.arsdigita.persistence.TransactionContext;
|
||||
import com.arsdigita.themedirector.dispatcher.InternalThemePrefixerServlet;
|
||||
import com.arsdigita.web.Application;
|
||||
import com.arsdigita.web.ApplicationCollection;
|
||||
import com.arsdigita.web.Web;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
|
@ -38,8 +34,9 @@ import org.apache.log4j.Logger;
|
|||
|
||||
|
||||
/**
|
||||
* Class for polling the database to look for new/updated files in
|
||||
* the ThemeFile table.
|
||||
* Class providing client classes (as FileManager for development and published
|
||||
* themes) with base methods 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
|
||||
|
|
@ -52,15 +49,14 @@ import org.apache.log4j.Logger;
|
|||
* 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>
|
||||
*
|
||||
* @version $Revision: #2 $ $DateTime: 2004/01/30 17:24:49 $
|
||||
*/
|
||||
public abstract class ThemeFileManager extends Thread
|
||||
implements ThemeDirectorConstants {
|
||||
|
||||
/** Internal logger instance to faciliate debugging */
|
||||
/** Internal logger instance to faciliate debugging. Carries over the
|
||||
* logger instance from the client child which actually does the work. */
|
||||
private final Logger m_log;
|
||||
|
||||
// The code in this class borrows heavily from
|
||||
|
|
@ -89,8 +85,10 @@ public abstract class ThemeFileManager extends Thread
|
|||
* @param pollDelay
|
||||
* @param baseDirectory
|
||||
*/
|
||||
protected ThemeFileManager(Logger log, int startupDelay, int pollDelay,
|
||||
String baseDirectory) {
|
||||
protected ThemeFileManager(Logger log,
|
||||
int startupDelay,
|
||||
int pollDelay,
|
||||
String baseDirectory) {
|
||||
m_log = log;
|
||||
m_startupDelay = startupDelay;
|
||||
m_pollDelay = pollDelay;
|
||||
|
|
@ -122,6 +120,7 @@ public abstract class ThemeFileManager extends Thread
|
|||
* Watch file for entries to process. The main routine that starts
|
||||
* file processing.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
m_log.info("Start polling file in " + m_startupDelay + "s.");
|
||||
if (m_lastRunDate == null) {
|
||||
|
|
@ -129,7 +128,7 @@ public abstract class ThemeFileManager extends Thread
|
|||
sleepSeconds(m_startupDelay);
|
||||
}
|
||||
m_log.info("Polling file every " + m_pollDelay + "s.");
|
||||
while ( (sleepSeconds(m_pollDelay) || m_ignoreInterrupt)
|
||||
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
|
||||
|
|
@ -186,6 +185,8 @@ public abstract class ThemeFileManager extends Thread
|
|||
* This allows an outside piece of code to force an automatic update
|
||||
* on a single theme instead of making it wait for the thread to wake
|
||||
* up.
|
||||
*
|
||||
* @param theme
|
||||
*/
|
||||
public void updateThemeNow(Theme theme) {
|
||||
updateTheme(theme);
|
||||
|
|
@ -194,13 +195,15 @@ public abstract class ThemeFileManager extends Thread
|
|||
|
||||
|
||||
/**
|
||||
* This returns the base directory to use when writing out files
|
||||
* THIS IS A HACK BECAUSE IT REQUIRES A SERVER TO BE RUNNING
|
||||
* This returns the base directory to use when writing out files.
|
||||
* THIS IS A HACK BECAUSE IT REQUIRES A SERVER TO BE RUNNING.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected String getBaseDirectory() {
|
||||
|
||||
if (m_baseDirectory == null) {
|
||||
// Because the constructor sets the base deirectory this should
|
||||
// Because the constructor sets the base directory this should
|
||||
// never happen, but just in case ....
|
||||
// ThemeDirector may execute in a different web application context
|
||||
// as core oder CMS. To determine the actual context we may ask
|
||||
|
|
@ -231,13 +234,18 @@ public abstract class ThemeFileManager extends Thread
|
|||
}
|
||||
|
||||
/**
|
||||
* this typically returns something like "getBaseDirectory() + PUB_DIR"
|
||||
* This typically returns something like "getBaseDirectory() + PUB_DIR".
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract String getManagerSpecificDirectory();
|
||||
|
||||
/**
|
||||
* This allows subclasses to filter the collection as appropriate
|
||||
* (e.g. only return "live" files or only "draft" files).
|
||||
* This allows subclasses to filter the collection as appropriate.
|
||||
* (e.g. only return "live" files or only "draft" files).
|
||||
*
|
||||
* @param theme
|
||||
* @return
|
||||
*/
|
||||
protected abstract ThemeFileCollection getThemeFilesCollection(Theme theme);
|
||||
|
||||
|
|
@ -268,9 +276,11 @@ public abstract class ThemeFileManager extends Thread
|
|||
*/
|
||||
|
||||
/**
|
||||
* This looks at all of the files in the db for the passed in theme
|
||||
* and makes sure that this servers file system has all of the
|
||||
* updated files.
|
||||
* This looks at all of the files in the db for the passed in theme
|
||||
* and makes sure that this servers file system has all of the
|
||||
* updated files.
|
||||
*
|
||||
* @param theme
|
||||
*/
|
||||
protected void updateTheme(Theme theme) {
|
||||
String stub = getManagerSpecificDirectory();
|
||||
|
|
@ -329,7 +339,10 @@ public abstract class ThemeFileManager extends Thread
|
|||
|
||||
|
||||
/***
|
||||
* Sleep for n seconds
|
||||
* Sleep for n seconds.
|
||||
*
|
||||
* @param n
|
||||
* @return
|
||||
***/
|
||||
protected boolean sleepSeconds(long n) {
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in New Issue