NIHVIVO-1810 Change the way that the default theme and the list of available themes are handled. If the application is configured to use a theme that is not found, it will throw a warning on the StartupStatus and use the default theme instead.
This commit is contained in:
parent
0ed27c1d51
commit
3f6b6a7d28
6 changed files with 200 additions and 150 deletions
|
@ -2,21 +2,10 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.beans;
|
package edu.cornell.mannlib.vitro.webapp.beans;
|
||||||
|
|
||||||
/**
|
|
||||||
* @version 2 2005-09-14
|
|
||||||
* @author Brian Caruso, Jon Corson-Rikert
|
|
||||||
*
|
|
||||||
* UPDATES:
|
|
||||||
* 2006-03-13 jcr minor changes having to do with browse functionality; removing old commented out code and comments
|
|
||||||
* 2005-10-19 jcr added variables and methods to retrieve MAX PORTAL ID from database and use that and minSharedPortalId/maxSharedPortalId
|
|
||||||
* to get rid of need for ALL CALS RESEARCH
|
|
||||||
* 2005-09-14 bdc34 modified to initialize itself from database and store static instance in class
|
|
||||||
* 2005-07-05 JCR added onlyCurrent and onlyPublic to get rid of constants stuck here and there in the code
|
|
||||||
* 2005-06-14 JCR added boolean initialized value to help detect when settings come from current site database
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
@ -25,12 +14,8 @@ import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This object is intended to represent the single row of data in the table application.
|
* This object is intended to represent the single row of data in the table application.
|
||||||
*
|
|
||||||
* @author jc55
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class ApplicationBean {
|
public class ApplicationBean {
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(ApplicationBean.class);
|
private static final Log log = LogFactory.getLog(ApplicationBean.class);
|
||||||
|
|
||||||
public final static int CALS_SEARCHBOX_SIZE = 25;
|
public final static int CALS_SEARCHBOX_SIZE = 25;
|
||||||
|
@ -43,7 +28,7 @@ public class ApplicationBean {
|
||||||
private final static String DEFAULT_ROOT_LOGOTYPE_TITLE = "";
|
private final static String DEFAULT_ROOT_LOGOTYPE_TITLE = "";
|
||||||
|
|
||||||
// Value gets set in default theme setup context listener at application startup
|
// Value gets set in default theme setup context listener at application startup
|
||||||
public static String DEFAULT_THEME_DIR_FROM_CONTEXT = null;
|
public static ThemeInfo themeInfo = new ThemeInfo(null, "no_default_theme", new ArrayList<String>());
|
||||||
|
|
||||||
// Default initializations, which may be overwritten in the AppBeanMapper
|
// Default initializations, which may be overwritten in the AppBeanMapper
|
||||||
// but are otherwise not changed there
|
// but are otherwise not changed there
|
||||||
|
@ -136,17 +121,9 @@ public class ApplicationBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThemeDir(String string_val) {
|
public void setThemeDir(String string_val) {
|
||||||
if( string_val == null || string_val.length() == 0
|
|
||||||
|| "default".equalsIgnoreCase(string_val)
|
|
||||||
|| "portal".equalsIgnoreCase(string_val)
|
|
||||||
|| "null".equalsIgnoreCase(string_val)
|
|
||||||
|| " ".equalsIgnoreCase(string_val) )
|
|
||||||
themeDir = DEFAULT_THEME_DIR_FROM_CONTEXT;
|
|
||||||
else
|
|
||||||
themeDir = string_val;
|
themeDir = string_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************** GET functions ****************************/
|
/*************************** GET functions ****************************/
|
||||||
|
|
||||||
public String getSessionIdStr() {
|
public String getSessionIdStr() {
|
||||||
|
@ -217,37 +194,71 @@ public class ApplicationBean {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getThemeDir(){
|
public String getThemeDir(){
|
||||||
return (themeDir != null && themeDir.length()>0)
|
if (themeInfo.isValidThemeDir(themeDir)) {
|
||||||
? themeDir
|
return themeDir;
|
||||||
: DEFAULT_THEME_DIR_FROM_CONTEXT;
|
} else {
|
||||||
|
return themeInfo.getDefaultThemeDir();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
public boolean themeDirExists(){
|
/**
|
||||||
String themeDir = this.getThemeDir();
|
* Hold the names of the available themes, the name of the default theme,
|
||||||
if( themeDir == null || themeDir.length() < 1 ){
|
* and the base directory that contains the theme directories.
|
||||||
log.error("Application has no themeDir/stylesheet set in the db." );
|
*
|
||||||
return false;
|
* The theme names are stored as simple strings, like "wilma".
|
||||||
|
*
|
||||||
|
* To be backwards compatible, we need to be able to test a string like
|
||||||
|
* "themes/wilma/ to see whether it is available, or to return the default
|
||||||
|
* directory in that form.
|
||||||
|
*/
|
||||||
|
public static class ThemeInfo {
|
||||||
|
private final File themesBaseDir;
|
||||||
|
private final String defaultThemeName;
|
||||||
|
private final List<String> themeNames;
|
||||||
|
|
||||||
|
public ThemeInfo(File themesBaseDir, String defaultThemeName,
|
||||||
|
List<String> themeNames) {
|
||||||
|
this.themesBaseDir = themesBaseDir;
|
||||||
|
this.defaultThemeName = defaultThemeName;
|
||||||
|
this.themeNames = Collections
|
||||||
|
.unmodifiableList(new ArrayList<String>(themeNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
File dir = new File(themeDir);
|
public static String themeNameFromDir(String themeDir) {
|
||||||
if( !dir.exists() ){
|
if (themeDir == null) {
|
||||||
log.error("Application: the themeDir/stylesheet "
|
return themeDir;
|
||||||
+ dir.getAbsolutePath()+ " does not exist.");
|
}
|
||||||
|
if (!themeDir.startsWith("themes/") || !themeDir.endsWith("/")) {
|
||||||
|
return themeDir;
|
||||||
|
}
|
||||||
|
return themeDir.substring(7, themeDir.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValidThemeDir(String themeDir) {
|
||||||
|
if (themeDir == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if( !dir.isDirectory() ){
|
return themeNames.contains(themeNameFromDir(themeDir));
|
||||||
log.error("Application: themeDir/stylesheet "
|
|
||||||
+ dir.getAbsolutePath() + " is not a directory.");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if( !dir.canRead() ){
|
|
||||||
log.error("Application: themeDir/stylesheet "
|
public String getDefaultThemeDir() {
|
||||||
+ dir.getAbsolutePath() + " is not readable.");
|
return "themes/" + defaultThemeName + "/";
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
public File getThemesBaseDir() {
|
||||||
|
return themesBaseDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultThemeName() {
|
||||||
|
return defaultThemeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getThemeNames() {
|
||||||
|
return themeNames;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
|
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.ApplicationDao;
|
import edu.cornell.mannlib.vitro.webapp.dao.ApplicationDao;
|
||||||
import edu.cornell.mannlib.vitro.webapp.utils.ThemeUtils;
|
|
||||||
|
|
||||||
public class ApplicationBeanRetryController extends BaseEditController {
|
public class ApplicationBeanRetryController extends BaseEditController {
|
||||||
|
|
||||||
|
@ -118,7 +117,7 @@ public class ApplicationBeanRetryController extends BaseEditController {
|
||||||
// Get the available themes
|
// Get the available themes
|
||||||
ServletContext sc = getServletContext();
|
ServletContext sc = getServletContext();
|
||||||
boolean doSort = true;
|
boolean doSort = true;
|
||||||
ArrayList<String> themeNames = ThemeUtils.getThemes(sc, doSort);
|
List<String> themeNames = ApplicationBean.themeInfo.getThemeNames();
|
||||||
|
|
||||||
// Create the list of theme Options
|
// Create the list of theme Options
|
||||||
String currentThemeDir = application.getThemeDir();
|
String currentThemeDir = application.getThemeDir();
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletContextEvent;
|
|
||||||
import javax.servlet.ServletContextListener;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.utils.ThemeUtils;
|
|
||||||
|
|
||||||
public class DefaultThemeSetup implements ServletContextListener {
|
|
||||||
|
|
||||||
// Set default theme based on themes present on the file system
|
|
||||||
@Override
|
|
||||||
public void contextInitialized(ServletContextEvent event) {
|
|
||||||
// Find the themes directory in the file system
|
|
||||||
ServletContext sc = event.getServletContext();
|
|
||||||
boolean doSort = true;
|
|
||||||
ArrayList<String> themeNames = ThemeUtils.getThemes(sc, doSort);
|
|
||||||
|
|
||||||
String defaultTheme;
|
|
||||||
if (themeNames.contains("vitro")) {
|
|
||||||
defaultTheme = "vitro";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
defaultTheme = themeNames.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
String defaultThemeDir = "themes/" + defaultTheme + "/";
|
|
||||||
// Define as a static variable of Portal so getThemeDir() method of portal can access it.
|
|
||||||
ApplicationBean.DEFAULT_THEME_DIR_FROM_CONTEXT = defaultThemeDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void contextDestroyed(ServletContextEvent event) {
|
|
||||||
// nothing to do here
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Literal;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Property;
|
||||||
|
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||||
|
import com.hp.hpl.jena.shared.Lock;
|
||||||
|
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean.ThemeInfo;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||||
|
|
||||||
|
public class ThemeInfoSetup implements ServletContextListener {
|
||||||
|
private static final Log log = LogFactory.getLog(ThemeInfoSetup.class);
|
||||||
|
|
||||||
|
// Set default theme based on themes present on the file system
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
ServletContext ctx = sce.getServletContext();
|
||||||
|
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||||
|
|
||||||
|
String themeDirPath = ctx.getRealPath("/themes");
|
||||||
|
if (themeDirPath == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Application does not have a /themes directory.");
|
||||||
|
}
|
||||||
|
File themesBaseDir = new File(themeDirPath);
|
||||||
|
|
||||||
|
List<String> themeNames = getThemeNames(themesBaseDir);
|
||||||
|
log.debug("themeNames: " + themeNames);
|
||||||
|
if (themeNames.isEmpty()) {
|
||||||
|
ss.fatal(this, "The application contains no themes. '"
|
||||||
|
+ themesBaseDir.getAbsolutePath()
|
||||||
|
+ "' has no child directories.");
|
||||||
|
}
|
||||||
|
|
||||||
|
String defaultThemeName = "vitro";
|
||||||
|
if (!themeNames.contains(defaultThemeName)) {
|
||||||
|
defaultThemeName = themeNames.get(0);
|
||||||
|
}
|
||||||
|
log.debug("defaultThemeName: " + defaultThemeName);
|
||||||
|
|
||||||
|
String currentThemeName = getCurrentThemeName(ctx);
|
||||||
|
log.debug("currentThemeName: " + currentThemeName);
|
||||||
|
if ((currentThemeName != null) && (!currentThemeName.isEmpty())
|
||||||
|
&& (!themeNames.contains(currentThemeName))) {
|
||||||
|
ss.warning(this, "The current theme selection is '"
|
||||||
|
+ currentThemeName
|
||||||
|
+ "', but that theme is not available. The '"
|
||||||
|
+ defaultThemeName + "' theme will be used instead. "
|
||||||
|
+ "Go to the Site Admin page and choose "
|
||||||
|
+ "\"Site Information\" to select a theme.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationBean.themeInfo = new ThemeInfo(themesBaseDir,
|
||||||
|
defaultThemeName, themeNames);
|
||||||
|
ss.info(this, ", current theme: " + currentThemeName
|
||||||
|
+ "default theme: " + defaultThemeName + ", available themes: "
|
||||||
|
+ themeNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a list of the names of available themes, sorted alphabetically. */
|
||||||
|
private List<String> getThemeNames(File themesBaseDir) {
|
||||||
|
ArrayList<String> themeNames = new ArrayList<String>();
|
||||||
|
|
||||||
|
for (File child : themesBaseDir.listFiles()) {
|
||||||
|
if (child.isDirectory()) {
|
||||||
|
themeNames.add(child.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(themeNames, String.CASE_INSENSITIVE_ORDER);
|
||||||
|
return themeNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCurrentThemeName(ServletContext ctx) {
|
||||||
|
OntModel ontModel = ModelContext.getBaseOntModelSelector(ctx)
|
||||||
|
.getApplicationMetadataModel();
|
||||||
|
|
||||||
|
ontModel.enterCriticalSection(Lock.READ);
|
||||||
|
try {
|
||||||
|
Property property = ontModel
|
||||||
|
.getProperty(VitroVocabulary.PORTAL_THEMEDIR);
|
||||||
|
ClosableIterator<RDFNode> nodes = ontModel
|
||||||
|
.listObjectsOfProperty(property);
|
||||||
|
try {
|
||||||
|
if (nodes.hasNext()) {
|
||||||
|
String themeDir = ((Literal) nodes.next()).getString();
|
||||||
|
return ThemeInfo.themeNameFromDir(themeDir);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
nodes.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e, e);
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
ontModel.leaveCriticalSection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent event) {
|
||||||
|
// nothing to do here
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,45 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.utils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
|
|
||||||
public class ThemeUtils {
|
|
||||||
|
|
||||||
private ThemeUtils() {
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ArrayList<String> getThemes(ServletContext sc, boolean doSort) {
|
|
||||||
|
|
||||||
// Find the themes directory on the file system
|
|
||||||
String themesDirName = sc.getRealPath("/themes");
|
|
||||||
File themesDir = new File(themesDirName);
|
|
||||||
|
|
||||||
// Get the children of the themes directory and their names
|
|
||||||
File[] children = themesDir.listFiles();
|
|
||||||
String[] childNames = themesDir.list();
|
|
||||||
|
|
||||||
// Create a list of valid themes
|
|
||||||
ArrayList<String> themeNames = new ArrayList<String>(childNames.length);
|
|
||||||
for (int i = 0; i < children.length; i++) {
|
|
||||||
// Get only directories, not files
|
|
||||||
if (children[i].isDirectory()) {
|
|
||||||
themeNames.add(childNames[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// File.list() does not guarantee a specific order, so sort alphabetically
|
|
||||||
if (doSort) {
|
|
||||||
Collections.sort(themeNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
return themeNames;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -11,9 +11,6 @@ edu.cornell.mannlib.vitro.webapp.config.RevisionInfoSetup
|
||||||
|
|
||||||
edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory$Setup
|
edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory$Setup
|
||||||
|
|
||||||
# DefaultThemeSetup needs to run before the JenaDataSourceSetup to allow creation of default portal and tab
|
|
||||||
edu.cornell.mannlib.vitro.webapp.servlet.setup.DefaultThemeSetup
|
|
||||||
|
|
||||||
# Comment out this listener to run Vitro without a database
|
# Comment out this listener to run Vitro without a database
|
||||||
# If used, this listener must be run before JenaDataSourceSetup
|
# If used, this listener must be run before JenaDataSourceSetup
|
||||||
edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaPersistentDataSourceSetup
|
edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaPersistentDataSourceSetup
|
||||||
|
@ -37,6 +34,9 @@ edu.cornell.mannlib.vitro.webapp.servlet.setup.FileGraphSetup
|
||||||
|
|
||||||
edu.cornell.mannlib.vitro.webapp.servlet.setup.SimpleReasonerSetup
|
edu.cornell.mannlib.vitro.webapp.servlet.setup.SimpleReasonerSetup
|
||||||
|
|
||||||
|
# Must run after JenaDataSourceSetup
|
||||||
|
edu.cornell.mannlib.vitro.webapp.servlet.setup.ThemeInfoSetup
|
||||||
|
|
||||||
edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader
|
edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader
|
||||||
|
|
||||||
edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper$Setup
|
edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper$Setup
|
||||||
|
|
Loading…
Add table
Reference in a new issue