diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/test-user-model.owl b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/test-user-model.owl
index c6e9a3523..a84b13707 100644
--- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/test-user-model.owl
+++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/test-user-model.owl
@@ -16,7 +16,7 @@
ACTIVE10
-
+
@@ -28,7 +28,7 @@
ACTIVE10
-
+
@@ -40,7 +40,7 @@
ACTIVE10
-
+
@@ -52,7 +52,7 @@
ACTIVE10
-
+
diff --git a/webapp/config/example.developer.properties b/webapp/config/example.developer.properties
index 482cecd21..78a1d2a72 100644
--- a/webapp/config/example.developer.properties
+++ b/webapp/config/example.developer.properties
@@ -32,6 +32,7 @@
#
# developer.permitAnonymousControl
+
#------------------------------------------------------------------------------
# Freemarker
#------------------------------------------------------------------------------
@@ -52,6 +53,25 @@
#
# developer.defeatFreemarkerCache = true
+
+#------------------------------------------------------------------------------
+# Page configuration
+#------------------------------------------------------------------------------
+
+#
+# Turn on logging of custom list view configuration files. Each time a property
+# uses a list view other than the default, note it in the log. The default is
+# 'false'.
+#
+# developer.pageContents.logCustomListView = true
+
+#
+# Turn on logging of custom short views. Each time an individual uses a short
+# view other than the default, note it in the log. The default is 'false'.
+#
+# developer.pageContents.logCustomShortView = true
+
+
#------------------------------------------------------------------------------
# Internationalization
#------------------------------------------------------------------------------
@@ -98,10 +118,18 @@
# developer.loggingRDFService.stackTrace = true
#
-# If SPARQL query logging is enabled, a regular expression can be used to
-# restrict the number of entries that are produced. The expression is
-# tested against each line in the (unabridged) stack trace. If the
-# expression doesn't match any line in the stack trace, then no log entry
-# is made. The default is 'false'.
+# If SPARQL query logging is enabled, restrict the number of log entries by
+# matching a regular expression against the query string. If the expression
+# doesn't match the string, then no log entry is made. The default is "",
+# which means no restriction.
#
-# developer.loggingRDFService.restriction = true
+# developer.loggingRDFService.queryRestriction = .*
+
+#
+# If SPARQL query logging is enabled, restrict the number of log entries by
+# matching a regular expression against the stack trace. The abridged stack
+# trace is concatenated into a single string of fully qualified class names
+# and method names. If the expression doesn't match the string, then no log
+# entry is made. The default is "", which means no restriction.
+#
+# developer.loggingRDFService.stackRestriction = .*
diff --git a/webapp/languages/es_GO/i18n/all_es_GO.properties b/webapp/languages/es_GO/i18n/all_es_GO.properties
index 85e25c9cf..5544aafb0 100644
--- a/webapp/languages/es_GO/i18n/all_es_GO.properties
+++ b/webapp/languages/es_GO/i18n/all_es_GO.properties
@@ -444,7 +444,7 @@ please_create = Por favor, cree
a_classgroup = un grupo de clase
associate_classes_with_group = y las clases asociadas con el grupo creado.
-refresh_content = Actualizar contenido
+site_maintenance = Mantenimiento del sitio
rebuild_search_index = Reconstruir índice de búsqueda
rebuild_vis_cache = Reconstruir caché de visualización
recompute_inferences_mixed_caps = Inferencias Recompute
diff --git a/webapp/rdf/auth/everytime/permission_config.n3 b/webapp/rdf/auth/everytime/permission_config.n3
index c4a88018a..e0b1c1960 100644
--- a/webapp/rdf/auth/everytime/permission_config.n3
+++ b/webapp/rdf/auth/everytime/permission_config.n3
@@ -12,6 +12,7 @@ auth:ADMIN
# ADMIN-only permissions
auth:hasPermission simplePermission:AccessSpecialDataModels ;
+ auth:hasPermission simplePermission:EnableDeveloperPanel ;
auth:hasPermission simplePermission:LoginDuringMaintenance ;
auth:hasPermission simplePermission:ManageMenus ;
auth:hasPermission simplePermission:ManageProxies ;
@@ -23,8 +24,12 @@ auth:ADMIN
auth:hasPermission simplePermission:UseAdvancedDataToolsPages ;
auth:hasPermission simplePermission:UseMiscellaneousAdminPages ;
auth:hasPermission simplePermission:UseSparqlQueryPage ;
- auth:hasPermission simplePermission:PageViewableAdmin ;
- auth:hasPermission simplePermission:EnableDeveloperPanel ;
+ auth:hasPermission simplePermission:PageViewableAdmin ;
+
+ # Uncomment the following permission line to enable the SPARQL update API.
+ # Before enabling, be sure that the URL api/sparqlUpdate is secured by SSH,
+ # so passwords will not be sent in clear text.
+# auth:hasPermission simplePermission:UseSparqlUpdateApi ;
# permissions for CURATOR and above.
auth:hasPermission simplePermission:EditOntology ;
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/permissions/SimplePermission.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/permissions/SimplePermission.java
index 33c609c5b..0484638bd 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/permissions/SimplePermission.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/permissions/SimplePermission.java
@@ -38,6 +38,8 @@ public class SimplePermission extends Permission {
NAMESPACE + "EditOwnAccount");
public static final SimplePermission EDIT_SITE_INFORMATION = new SimplePermission(
NAMESPACE + "EditSiteInformation");
+ public static final SimplePermission ENABLE_DEVELOPER_PANEL = new SimplePermission(
+ NAMESPACE + "EnableDeveloperPanel");
public static final SimplePermission LOGIN_DURING_MAINTENANCE = new SimplePermission(
NAMESPACE + "LoginDuringMaintenance");
public static final SimplePermission MANAGE_MENUS = new SimplePermission(
@@ -76,9 +78,8 @@ public class SimplePermission extends Permission {
NAMESPACE + "UseAdvancedDataToolsPages");
public static final SimplePermission USE_SPARQL_QUERY_PAGE = new SimplePermission(
NAMESPACE + "UseSparqlQueryPage");
- public static final SimplePermission ENABLE_DEVELOPER_PANEL = new SimplePermission(
- NAMESPACE + "EnableDeveloperPanel");
-
+ public static final SimplePermission USE_SPARQL_UPDATE_API = new SimplePermission(
+ NAMESPACE + "UseSparqlUpdateApi");
// ----------------------------------------------------------------------
// These instances are "catch all" permissions to cover poorly defined
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java
index d8a606efb..b1250a855 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java
@@ -83,11 +83,11 @@ public class PolicyHelper {
}
try{
- Authenticator basicAuth = new BasicAuthenticator(req);
- UserAccount user = basicAuth.getAccountForInternalAuth( email );
+ Authenticator auth = Authenticator.getInstance(req);
+ UserAccount user = auth.getAccountForInternalAuth( email );
log.debug("userAccount is " + user==null?"null":user.getUri() );
- if( ! basicAuth.isCurrentPassword( user, password ) ){
+ if( ! auth.isCurrentPassword( user, password ) ){
log.debug(String.format("UNAUTHORIZED, password not accepted for %s, account URI: %s",
user.getEmailAddress(), user.getUri()));
return false;
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/api/SparqlUpdateApiController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/api/SparqlUpdateApiController.java
new file mode 100644
index 000000000..60a0e6af0
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/api/SparqlUpdateApiController.java
@@ -0,0 +1,201 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.controller.api;
+
+import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
+import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.hp.hpl.jena.query.Dataset;
+import com.hp.hpl.jena.update.GraphStore;
+import com.hp.hpl.jena.update.GraphStoreFactory;
+import com.hp.hpl.jena.update.UpdateAction;
+import com.hp.hpl.jena.update.UpdateFactory;
+import com.hp.hpl.jena.update.UpdateRequest;
+
+import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
+import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
+import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
+import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceDataset;
+import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder;
+
+/**
+ * This extends HttpServlet instead of VitroHttpServlet because we want to have
+ * full control over the response:
+ *
+ *
No redirecting to the login page if not authorized
+ *
No redirecting to the home page on insufficient authorization
+ *
No support for GET or HEAD requests, only POST.
+ *
+ *
+ * So these responses will be produced:
+ *
+ *
+ * 200 Success
+ * 400 Failed to parse SPARQL update
+ * 400 SPARQL update must specify a GRAPH URI.
+ * 403 username/password combination is not valid
+ * 403 Account is not authorized
+ * 405 Method not allowed
+ * 500 Unknown error
+ *
");
+ }
+
+ // ----------------------------------------------------------------------
+ // Helper classes
+ // ----------------------------------------------------------------------
+
+ private static class AuthException extends Exception {
+ private AuthException(String message) {
+ super(message);
+ }
+ }
+
+ private static class ParseException extends Exception {
+ private ParseException(String message) {
+ super(message);
+ }
+
+ private ParseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java
index fd988add8..1a10c92a3 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java
@@ -53,14 +53,14 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet {
body.put("dataInput", getDataInputData(vreq));
body.put("siteConfig", getSiteConfigData(vreq));
- body.put("indexCacheRebuild", getIndexCacheRebuildUrls(vreq));
+ body.put("siteMaintenance", getSiteMaintenanceUrls(vreq));
body.put("ontologyEditor", getOntologyEditorData(vreq));
body.put("dataTools", getDataToolsUrls(vreq));
return new TemplateResponseValues(TEMPLATE_DEFAULT, body);
}
- protected Map getIndexCacheRebuildUrls(VitroRequest vreq) {
+ protected Map getSiteMaintenanceUrls(VitroRequest vreq) {
Map urls = new HashMap();
@@ -73,6 +73,10 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet {
urls.put("rebuildSearchIndex", UrlBuilder.getUrl("/SearchIndex"));
}
+ if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.LOGIN_DURING_MAINTENANCE.ACTIONS)) {
+ urls.put("restrictLogins", UrlBuilder.getUrl("/admin/restrictLogins"));
+ }
+
if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.ENABLE_DEVELOPER_PANEL.ACTIONS)) {
urls.put("activateDeveloperPanel", "javascript:new DeveloperPanel(developerAjaxUrl).setupDeveloperPanel({developerEnabled: true});");
}
@@ -147,10 +151,6 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet {
data.put("startupStatusAlert", !StartupStatus.getBean(getServletContext()).allClear());
}
- if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.LOGIN_DURING_MAINTENANCE.ACTIONS)) {
- data.put("restrictLogins", UrlBuilder.getUrl("/admin/restrictLogins"));
- }
-
return data;
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java
index 785bb031b..fe08c7d95 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java
@@ -58,15 +58,16 @@ public class PageController extends FreemarkerHttpServlet{
if( pageActs == null && dgActs == null){
return Actions.AUTHORIZED;
- }else if( pageActs == null && dgActs != null ){
+ }else if( pageActs == null ){
return dgActs;
+ }else if( dgActs == null ){
+ return pageActs;
}else{
- return pageActs;
+ return pageActs.and(dgActs);
}
} catch (Exception e) {
- // TODO Auto-generated catch block
- log.debug(e);
+ log.warn(e);
return Actions.UNAUTHORIZED;
}
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PageDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PageDaoJena.java
index 23e300013..fd333560b 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PageDaoJena.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PageDaoJena.java
@@ -537,13 +537,14 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
List actions = new ArrayList();
Model dModel = getOntModelSelector().getDisplayModel();
+ dModel.enterCriticalSection(false);
try{
QueryExecution qe =
QueryExecutionFactory.create( requiredActionsQuery, dModel, initialBindings);
actions = executeQueryToList( qe );
qe.close();
}finally{
- dModel.enterCriticalSection(false);
+ dModel.leaveCriticalSection();
}
return actions;
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java
index 617a09f6c..7d2c05c9d 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java
@@ -3,6 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.freemarker.config;
import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -35,28 +36,52 @@ import freemarker.template.utility.DeepUnwrap;
* Extend the Freemarker Configuration class to include some information that is
* particular to the current request.
*
- * Takes advantage of the fact that each servlet request runs in a separate
- * thread. Stores the request-based information in a ThreadLocal. Override any
- * methods that should return that information instead of (or in addition to)
- * the common info.
+ * A reference to the current request is not always available to the Freemarker
+ * Configuration, so we take advantage of the fact that each request runs in a
+ * separate thread, and store a reference to that request in a ThreadLocal
+ * object.
+ *
+ * Then, we override any methods that should return that request-based
+ * information instead of (or in addition to) the common info.
*
* Only the getters are overridden, not the setters. So if you call
* setAllSharedVariables(), for example, it will have no effect on the
* request-based information.
+ *
+ * Notice that the reference to the current request is actually stored through a
+ * WeakReference. This is because the ThreadLocal will not be cleared when the
+ * webapp is stopped, so none of the references from that ThreadLocal are
+ * eligible for garbage collection. If any of those references is an instance of
+ * a class that is loaded by the webapp, then the webapp ClassLoader is not
+ * eligible for garbage collection. This would be a huge memory leak.
+ *
+ * Thanks to the WeakReference, the request is eligible for garbage collection
+ * if nothing else refers to it. In theory, this means that the WeakReference
+ * could return a null, but if the garbage collector has taken the request, then
+ * who is invoking this object?
*/
public class FreemarkerConfigurationImpl extends Configuration {
private static final Log log = LogFactory
.getLog(FreemarkerConfigurationImpl.class);
- private final ThreadLocal rbiRef = new ThreadLocal<>();
+ private static final String ATTRIBUTE_NAME = RequestBasedInformation.class
+ .getName();
+
+ private final ThreadLocal> reqRef = new ThreadLocal<>();
void setRequestInfo(HttpServletRequest req) {
- rbiRef.set(new RequestBasedInformation(req, this));
+ reqRef.set(new WeakReference<>(req));
+ req.setAttribute(ATTRIBUTE_NAME, new RequestBasedInformation(req, this));
+ }
+
+ private RequestBasedInformation getRequestInfo() {
+ HttpServletRequest req = reqRef.get().get();
+ return (RequestBasedInformation) req.getAttribute(ATTRIBUTE_NAME);
}
@Override
public Object getCustomAttribute(String name) {
- Map attribs = rbiRef.get().getCustomAttributes();
+ Map attribs = getRequestInfo().getCustomAttributes();
if (attribs.containsKey(name)) {
return attribs.get(name);
} else {
@@ -66,13 +91,13 @@ public class FreemarkerConfigurationImpl extends Configuration {
@Override
public String[] getCustomAttributeNames() {
- Set rbiNames = rbiRef.get().getCustomAttributes().keySet();
+ Set rbiNames = getRequestInfo().getCustomAttributes().keySet();
return joinNames(rbiNames, super.getCustomAttributeNames());
}
@Override
public TemplateModel getSharedVariable(String name) {
- Map vars = rbiRef.get().getSharedVariables();
+ Map vars = getRequestInfo().getSharedVariables();
if (vars.containsKey(name)) {
return vars.get(name);
} else {
@@ -82,7 +107,7 @@ public class FreemarkerConfigurationImpl extends Configuration {
@Override
public Set getSharedVariableNames() {
- Set rbiNames = rbiRef.get().getSharedVariables().keySet();
+ Set rbiNames = getRequestInfo().getSharedVariables().keySet();
@SuppressWarnings("unchecked")
Set superNames = super.getSharedVariableNames();
@@ -94,7 +119,7 @@ public class FreemarkerConfigurationImpl extends Configuration {
@Override
public Locale getLocale() {
- return rbiRef.get().getReq().getLocale();
+ return getRequestInfo().getReq().getLocale();
}
private String[] joinNames(Set nameSet, String[] nameArray) {
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoader.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoader.java
index 33adcb152..0bef38b30 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoader.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/loader/FreemarkerTemplateLoader.java
@@ -15,6 +15,8 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
@@ -178,64 +180,71 @@ public class FreemarkerTemplateLoader implements TemplateLoader {
* search term, and how well they match.
*/
static class PathPieces {
+ static final Pattern PATTERN = Pattern.compile("(.+?)" // base name
+ + "(_[a-z]{2})?" // optional language
+ + "(_[A-Z]{2})?" // optional country
+ + "(\\.\\w+)?" // optional extension
+ );
+
final Path path;
final String base;
final String language;
final String region;
final String extension;
- public PathPieces(String searchTerm) {
- this(Paths.get(searchTerm));
+ public PathPieces(String pathString) {
+ this(Paths.get(pathString));
}
public PathPieces(Path path) {
this.path = path;
String filename = path.getFileName().toString();
- int dotHere = filename.lastIndexOf('.');
- String basename;
- if (dotHere != -1) {
- basename = filename.substring(0, dotHere);
- this.extension = filename.substring(dotHere);
- } else {
- basename = filename;
- this.extension = "";
- }
- int break2 = basename.lastIndexOf('_');
- int break1 = basename.lastIndexOf('_', break2 - 1);
- if (break1 != -1) {
- this.base = basename.substring(0, break1);
- this.language = basename.substring(break1, break2);
- this.region = basename.substring(break2);
- } else if (break2 != -1) {
- this.base = basename.substring(0, break2);
- this.language = basename.substring(break2);
- this.region = "";
+ Matcher m = PATTERN.matcher(filename);
+ if (m.matches()) {
+ base = getGroup(m, 1);
+ language = getGroup(m, 2);
+ region = getGroup(m, 3);
+ extension = getGroup(m, 4);
} else {
- this.base = basename;
- this.language = "";
- this.region = "";
+ base = filename;
+ language = "";
+ region = "";
+ extension = "";
}
}
- /** This is the search term. Does that candidate qualify as a result? */
+ private String getGroup(Matcher m, int i) {
+ return (m.start(i) == -1) ? "" : m.group(i);
+ }
+
+ /**
+ * If I'm searching for this, is that an acceptable match?
+ *
+ * Note that this is asymetrical -- a search term without a region will
+ * match a candidate with a region, but not vice versa. Same with
+ * language.
+ */
public boolean matches(PathPieces that) {
return base.equals(that.base) && extension.equals(that.extension)
&& (language.isEmpty() || language.equals(that.language))
&& (region.isEmpty() || region.equals(that.region));
}
+ /**
+ * How good a match is that to this?
+ */
public int score(PathPieces that) {
if (matches(that)) {
if (that.language.equals(language)) {
if (that.region.equals(region)) {
- return 3; // match language and region
+ return 3; // exact match.
} else {
- return 2; // match language, default region.
+ return 2; // same language, approximate region.
}
} else {
- return 1; // default language.
+ return 1; // approximate language.
}
} else {
return -1; // doesn't match.
@@ -276,7 +285,7 @@ public class FreemarkerTemplateLoader implements TemplateLoader {
}
public boolean fileQualifies(Path path) {
- return Files.isRegularFile(path) && Files.isReadable(path);
+ return Files.isReadable(path) && !Files.isDirectory(path);
}
public SortedSet getMatches() {
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/RDFServiceLogger.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/RDFServiceLogger.java
index d7f0ffa7a..c0950e967 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/RDFServiceLogger.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/RDFServiceLogger.java
@@ -23,9 +23,12 @@ import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings.Keys;
*
* If not enabled, or if the logging level is insufficient, this does nothing.
*
- * If enabled, it checks for restrictions. If there is a restriction pattern
- * (regular expression), the a log message will only be printed if one of the
- * fully-qualified class names in the stack trace matches that pattern.
+ * If enabled, it checks for restrictions. If there is a restriction on the call
+ * stack (regular expression), then a log message will only be printed if the
+ * pattern is found in the concatenated call stack (fully-qualified class names
+ * and method names). If there is a restriction on the query string (regular
+ * expression) then a log message will only be printed if the pattern is found
+ * in the query string.
*
* If everything passes muster, the constructor will record the time that the
* instance was created.
@@ -47,7 +50,8 @@ public class RDFServiceLogger implements AutoCloseable {
private boolean isEnabled;
private boolean traceRequested;
- private Pattern restriction;
+ private Pattern queryStringRestriction;
+ private Pattern callStackRestriction;
private String methodName;
private List trace = Collections.emptyList();
@@ -62,7 +66,7 @@ public class RDFServiceLogger implements AutoCloseable {
if (isEnabled && log.isInfoEnabled()) {
loadStackTrace();
- if (passesRestrictions()) {
+ if (passesQueryRestriction() && passesStackRestriction()) {
this.startTime = System.currentTimeMillis();
}
}
@@ -72,20 +76,23 @@ public class RDFServiceLogger implements AutoCloseable {
DeveloperSettings settings = DeveloperSettings.getBean(ctx);
isEnabled = settings.getBoolean(Keys.LOGGING_RDF_ENABLE);
traceRequested = settings.getBoolean(Keys.LOGGING_RDF_STACK_TRACE);
+ queryStringRestriction = patternFromSettings(settings,
+ Keys.LOGGING_RDF_QUERY_RESTRICTION);
+ callStackRestriction = patternFromSettings(settings,
+ Keys.LOGGING_RDF_STACK_RESTRICTION);
+ }
- String restrictionString = settings
- .getString(Keys.LOGGING_RDF_RESTRICTION);
- if (StringUtils.isBlank(restrictionString)) {
- restriction = null;
- } else {
- try {
- restriction = Pattern.compile(restrictionString);
- } catch (Exception e) {
- log.error("Failed to compile the pattern for "
- + Keys.LOGGING_RDF_RESTRICTION + " = " + restriction
- + " " + e);
- isEnabled = false;
- }
+ private Pattern patternFromSettings(DeveloperSettings settings, Keys key) {
+ String patternString = settings.getString(key);
+ if (StringUtils.isBlank(patternString)) {
+ return null;
+ }
+ try {
+ return Pattern.compile(patternString);
+ } catch (Exception e) {
+ log.error("Failed to compile the pattern for " + key + " = "
+ + patternString + " " + e);
+ return Pattern.compile("^_____NEVER MATCH_____$");
}
}
@@ -144,16 +151,39 @@ public class RDFServiceLogger implements AutoCloseable {
}
}
- private boolean passesRestrictions() {
- if (restriction == null) {
+ private boolean passesQueryRestriction() {
+ if (queryStringRestriction == null) {
return true;
}
- for (StackTraceElement ste : trace) {
- if (restriction.matcher(ste.getClassName()).find()) {
- return true;
+ String q = assembleQueryString();
+ return queryStringRestriction.matcher(q).find();
+ }
+
+ private String assembleQueryString() {
+ StringBuilder query = new StringBuilder();
+ for (Object arg : args) {
+ if (arg instanceof String) {
+ query.append((String) arg).append(" ");
}
}
- return false;
+ return query.deleteCharAt(query.length() - 1).toString();
+ }
+
+ private boolean passesStackRestriction() {
+ if (callStackRestriction == null) {
+ return true;
+ }
+ String q = assembleCallStackString();
+ return callStackRestriction.matcher(q).find();
+ }
+
+ private String assembleCallStackString() {
+ StringBuilder stack = new StringBuilder();
+ for (StackTraceElement ste : trace) {
+ stack.append(ste.getClassName()).append(" ")
+ .append(ste.getMethodName()).append(" ");
+ }
+ return stack.deleteCharAt(stack.length() - 1).toString();
}
@Override
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java
index b207f1681..b20c6cba3 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/sparql/RDFServiceSparql.java
@@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.sparql;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -14,7 +15,9 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -38,6 +41,7 @@ import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
+import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP;
import edu.cornell.mannlib.vitro.webapp.dao.jena.SparqlGraph;
import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener;
@@ -84,11 +88,11 @@ public class RDFServiceSparql extends RDFServiceImpl implements RDFService {
this.readRepository = new HTTPRepository(readEndpointURI);
this.updateRepository = new HTTPRepository(updateEndpointURI);
- testConnection();
-
MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
- mgr.getParams().setDefaultMaxConnectionsPerHost(10);
+ mgr.getParams().setDefaultMaxConnectionsPerHost(50);
this.httpClient = new HttpClient(mgr);
+
+ testConnection();
}
private void testConnection() {
@@ -278,13 +282,28 @@ public class RDFServiceSparql extends RDFServiceImpl implements RDFService {
*/
@Override
public InputStream sparqlSelectQuery(String queryStr, RDFService.ResultFormat resultFormat) throws RDFServiceException {
-
- Query query = createQuery(queryStr);
- QueryExecution qe = QueryExecutionFactory.sparqlService(readEndpointURI, query);
-
+
+ //QueryEngineHTTP qh = new QueryEngineHTTP(readEndpointURI, queryStr);
+
+ GetMethod meth = new GetMethod(readEndpointURI);
try {
- ResultSet resultSet = qe.execSelect();
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ meth.addRequestHeader("Accept", "application/sparql-results+xml");
+ NameValuePair param = new NameValuePair();
+ param.setName("query");
+ param.setValue(queryStr);
+ NameValuePair[] params = new NameValuePair[1];
+ params[0] = param;
+ meth.setQueryString(params);
+ int response = httpClient.executeMethod(meth);
+ if (response > 399) {
+ log.error("response " + response + " to query. \n");
+ log.debug("update string: \n" + queryStr);
+ throw new RDFServiceException("Unable to perform SPARQL UPDATE");
+ }
+
+ InputStream in = meth.getResponseBodyAsStream();
+ ResultSet resultSet = ResultSetFactory.fromXML(in);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
switch (resultFormat) {
case CSV:
@@ -301,12 +320,14 @@ public class RDFServiceSparql extends RDFServiceImpl implements RDFService {
break;
default:
throw new RDFServiceException("unrecognized result format");
- }
-
+ }
InputStream result = new ByteArrayInputStream(outputStream.toByteArray());
return result;
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
} finally {
- qe.close();
+ //qh.close();
+ meth.releaseConnection();
}
}
@@ -474,7 +495,7 @@ public class RDFServiceSparql extends RDFServiceImpl implements RDFService {
int response = httpClient.executeMethod(meth);
if (response > 399) {
log.error("response " + response + " to update. \n");
- log.debug("update string: \n" + updateString);
+ //log.debug("update string: \n" + updateString);
throw new RDFServiceException("Unable to perform SPARQL UPDATE");
}
} finally {
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/documentBuilding/ExcludeNonFlagVitro.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/documentBuilding/ExcludeNonFlagVitro.java
index 3381423d0..fdd2df365 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/documentBuilding/ExcludeNonFlagVitro.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/documentBuilding/ExcludeNonFlagVitro.java
@@ -1,44 +1,57 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.search.solr.documentBuilding;
+import static edu.cornell.mannlib.vitro.webapp.search.solr.documentBuilding.IndividualToSolrDocument.DONT_EXCLUDE;
+
import java.util.List;
-import org.apache.solr.common.SolrInputDocument;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
-import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
/**
- * Exclude individuals with types from the Vitro namespace from the
- * search index. (Other than old vitro Flag types).
+ * Exclude individuals with most specific types from the Vitro namespace from
+ * the search index. (Other than old vitro Flag types).
*/
public class ExcludeNonFlagVitro implements SearchIndexExcluder {
+ private static final Log log = LogFactory.getLog(ExcludeNonFlagVitro.class);
- @Override
- public String checkForExclusion(Individual ind) {
- if( ind != null && ind.getVClasses() != null ) {
- String excludeMsg = skipIfVitro(ind, ind.getVClasses() );
- if( excludeMsg != null)
- return excludeMsg;
- }
- return null;
- }
+ @Override
+ public String checkForExclusion(Individual ind) {
+ if (ind == null) {
+ return DONT_EXCLUDE;
+ }
+
+ List mostSpecificTypeUris = ind.getMostSpecificTypeURIs();
+ if (mostSpecificTypeUris == null) {
+ return DONT_EXCLUDE;
+ }
+
+ String message = skipIfVitro(ind, mostSpecificTypeUris);
+ if (!StringUtils.equals(DONT_EXCLUDE, message)) {
+ log.debug("msg=" + message + ", individual=" + ind.getURI() + " ("
+ + ind.getLabel() + "), types=" + mostSpecificTypeUris);
+ }
+ return message;
+ }
+
+ String skipIfVitro(Individual ind, List mostSpecificTypeUris) {
+ for (String typeUri : mostSpecificTypeUris) {
+ if (typeUri == null) {
+ continue;
+ }
+ if (typeUri.startsWith(VitroVocabulary.vitroURI + "Flag")) {
+ continue;
+ }
+ if (typeUri.startsWith(VitroVocabulary.vitroURI)) {
+ return "Skipped " + ind.getURI() + " because in "
+ + VitroVocabulary.vitroURI + " namespace";
+ }
+ }
+ return DONT_EXCLUDE;
+ }
- String skipIfVitro(Individual ind, List vclasses) {
- for( VClass type: vclasses ){
- if( type != null && type.getURI() != null ){
- String typeURI = type.getURI();
-
- if(typeURI.startsWith( VitroVocabulary.vitroURI )
- && ! typeURI.startsWith(VitroVocabulary.vitroURI + "Flag") ){
-
- return "Skipped " + ind.getURI()+" because in "
- + VitroVocabulary.vitroURI + " namespace";
- }
- }
- }
- return null;
- }
-
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/documentBuilding/IndividualToSolrDocument.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/documentBuilding/IndividualToSolrDocument.java
index c32bb2503..a2f62782c 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/documentBuilding/IndividualToSolrDocument.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/solr/documentBuilding/IndividualToSolrDocument.java
@@ -110,6 +110,9 @@ public class IndividualToSolrDocument {
for( SearchIndexExcluder excluder : excludes){
try{
String msg = excluder.checkForExclusion(ind);
+ log.debug("individual=" + ind.getURI() + " (" + ind.getLabel()
+ + "), excluder=" + excluder + ", types="
+ + ind.getMostSpecificTypeURIs() + ", msg=" + msg);
if( msg != DONT_EXCLUDE)
return msg;
}catch (Exception e) {
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/FakeApplicationOntologyService.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/FakeApplicationOntologyService.java
index 92fcc8ae7..a650620cc 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/FakeApplicationOntologyService.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/FakeApplicationOntologyService.java
@@ -380,6 +380,12 @@ public class FakeApplicationOntologyService {
return dataGetters;
}
+ @Override
+ public String toString() {
+ return "[template=" + templateName + ", dataGetters=" + dataGetters
+ + "]";
+ }
+
}
/** The view specifications that we read from the config file. */
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewLogger.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewLogger.java
new file mode 100644
index 000000000..220185445
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewLogger.java
@@ -0,0 +1,47 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.services.shortview;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import edu.cornell.mannlib.vitro.webapp.beans.Individual;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.services.shortview.FakeApplicationOntologyService.TemplateAndDataGetters;
+import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
+import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings.Keys;
+
+/**
+ * When we use a short view other than the default, log it.
+ */
+public class ShortViewLogger {
+ private static final Log log = LogFactory.getLog(ShortViewLogger.class);
+
+ public static void log(VitroRequest vreq, String contextName,
+ Individual individual, String classUri, TemplateAndDataGetters tdg) {
+ if (isLogging(vreq)) {
+ log.info("Using custom short view in " + contextName + " because '"
+ + individual.getURI() + "' (" + individual.getLabel()
+ + ") has type '" + classUri + "': " + tdg);
+ }
+ }
+
+ public static void log(VitroRequest vreq, String contextName,
+ Individual individual) {
+ if (isLogging(vreq)) {
+ log.info("Using default short view in " + contextName + " for '"
+ + individual.getURI() + "' (" + individual.getLabel() + ")");
+ }
+ }
+
+ private static boolean isLogging(VitroRequest vreq) {
+ if (!log.isInfoEnabled()) {
+ return false;
+ }
+ DeveloperSettings settings = DeveloperSettings.getBean(vreq);
+ return settings.getBoolean(Keys.ENABLED)
+ && settings
+ .getBoolean(Keys.PAGE_CONTENTS_LOG_CUSTOM_SHORT_VIEW);
+ }
+
+}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceImpl.java
index 8e18208a0..c072f866e 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceImpl.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/shortview/ShortViewServiceImpl.java
@@ -15,9 +15,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
-import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
-import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.services.freemarker.FreemarkerProcessingService;
import edu.cornell.mannlib.vitro.webapp.services.freemarker.FreemarkerProcessingService.TemplateParsingException;
import edu.cornell.mannlib.vitro.webapp.services.freemarker.FreemarkerProcessingService.TemplateProcessingException;
@@ -116,11 +114,13 @@ public class ShortViewServiceImpl implements ShortViewService {
TemplateAndDataGetters tdg = faker.getShortViewProperties(vreq,
individual, classUri, svContext.name());
if (tdg != null) {
+ ShortViewLogger.log(vreq, svContext.name(), individual, classUri, tdg);
return tdg;
}
}
// Didn't find one? Use the default values.
+ ShortViewLogger.log(vreq, svContext.name(), individual);
return new TemplateAndDataGetters(svContext.getDefaultTemplateName());
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ThemeInfoSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ThemeInfoSetup.java
index 6b917c43f..5ccea3bfd 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ThemeInfoSetup.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ThemeInfoSetup.java
@@ -73,8 +73,8 @@ public class ThemeInfoSetup implements ServletContextListener {
ApplicationBean.themeInfo = new ThemeInfo(themesBaseDir,
defaultThemeName, themeNames);
- ss.info(this, ", current theme: " + currentThemeName
- + "default theme: " + defaultThemeName + ", available themes: "
+ ss.info(this, "current theme: " + currentThemeName
+ + ", default theme: " + defaultThemeName + ", available themes: "
+ themeNames);
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlUpdate.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlUpdate.java
deleted file mode 100644
index 7bb33194b..000000000
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SparqlUpdate.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $This file is distributed under the terms of the license in /doc/license.txt$ */
-
-package edu.cornell.mannlib.vitro.webapp.utils.dataGetter;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import com.hp.hpl.jena.query.Dataset;
-import com.hp.hpl.jena.rdf.model.Model;
-import com.hp.hpl.jena.update.GraphStore;
-import com.hp.hpl.jena.update.GraphStoreFactory;
-import com.hp.hpl.jena.update.UpdateAction;
-
-import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
-import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
-import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
-import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequiresActions;
-import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
-import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceDataset;
-import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder;
-
-/**
- * Handle a SPARQL Update request. This uses Jena ARQ and the RDFServiceDataset to
- * evaluate a SPARQL Update with the RDFService.
- *
- * The reason to make this a DataGettere was to allow configuration in RDF of this
- * service.
- */
-public class SparqlUpdate implements DataGetter, RequiresActions{
-
- private static final Log log = LogFactory.getLog(SparqlUpdate.class);
-
- VitroRequest vreq;
- ServletContext context;
-
- public SparqlUpdate(
- VitroRequest vreq, Model displayModel, String dataGetterURI ) {
- if( vreq == null )
- throw new IllegalArgumentException("VitroRequest may not be null.");
- this.vreq = vreq;
- this.context = vreq.getSession().getServletContext();
- }
-
-
- /**
- * Gets the update from the request and then executes it on
- * the RDFService.
- */
- @Override
- public Map getData( Map valueMap ) {
- HashMap data = new HashMap();
-
- String update = vreq.getParameter("update");
-
- if( update != null && !update.trim().isEmpty()){
- try{
- IndexBuilder.getBuilder(context).pause();
- Dataset ds = new RDFServiceDataset( vreq.getUnfilteredRDFService() );
- GraphStore graphStore = GraphStoreFactory.create(ds);
- log.warn("The SPARQL update is '"+vreq.getParameter("update")+"'");
- UpdateAction.parseExecute( vreq.getParameter("update") , graphStore );
- }finally{
- IndexBuilder.getBuilder(context).unpause();
- }
-
- }
-
- data.put("bodyTemplate", "page-sparqlUpdateTest.ftl");
- return data;
- }
-
-
- /**
- * Check if this request is authorized by the email/password.
- * If not do normal authorization.
- */
- @Override
- public Actions requiredActions(VitroRequest vreq) {
- String email = vreq.getParameter("email");
- String password = vreq.getParameter("password");
-
- boolean isAuth = PolicyHelper.isAuthorizedForActions(vreq,
- email, password, SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS);
-
- if( isAuth )
- return Actions.AUTHORIZED;
- else
- return SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS;
- }
-
-}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettings.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettings.java
index 822e434e4..f883281f9 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettings.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettings.java
@@ -82,9 +82,29 @@ public class DeveloperSettings {
* Don't log with the LoggingRDFService unless the calling stack meets
* this restriction.
*/
- LOGGING_RDF_RESTRICTION("developer.loggingRDFService.restriction",
- false);
+ LOGGING_RDF_QUERY_RESTRICTION(
+ "developer.loggingRDFService.queryRestriction", false),
+ /**
+ * Don't log with the LoggingRDFService unless the calling stack meets
+ * this restriction.
+ */
+ LOGGING_RDF_STACK_RESTRICTION(
+ "developer.loggingRDFService.stackRestriction", false),
+
+ /**
+ * Tell the CustomListViewLogger to note the use of non-default custom
+ * list views.
+ */
+ PAGE_CONTENTS_LOG_CUSTOM_LIST_VIEW(
+ "developer.pageContents.logCustomListView", true),
+
+ /**
+ * Tell the ShortViewLogger to note the use of non-default short views.
+ */
+ PAGE_CONTENTS_LOG_CUSTOM_SHORT_VIEW(
+ "developer.pageContents.logCustomShortView", true);
+
private final String propertyName;
private final String elementId;
private final boolean bool;
@@ -159,7 +179,7 @@ public class DeveloperSettings {
// The factory
// ----------------------------------------------------------------------
- private static final String ATTRIBUTE_NAME = DeveloperSettings.class
+ protected static final String ATTRIBUTE_NAME = DeveloperSettings.class
.getName();
public static DeveloperSettings getBean(HttpServletRequest req) {
@@ -183,7 +203,7 @@ public class DeveloperSettings {
private final Map settings = new EnumMap<>(Keys.class);
- private DeveloperSettings(ServletContext ctx) {
+ protected DeveloperSettings(ServletContext ctx) {
updateFromFile(ctx);
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/CustomListViewLogger.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/CustomListViewLogger.java
new file mode 100644
index 000000000..2509af61c
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/CustomListViewLogger.java
@@ -0,0 +1,38 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
+import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings.Keys;
+
+/**
+ * If enabled in the developer settings (and log levels), log every non-default
+ * custom list view.
+ */
+public class CustomListViewLogger {
+ private static final Log log = LogFactory
+ .getLog(CustomListViewLogger.class);
+
+ public static void log(VitroRequest vreq, ObjectProperty op,
+ String configFileName) {
+ if (isLogging(vreq)) {
+ log.info("Using list view: '" + configFileName + "' for "
+ + op.getURI() + " (" + op.getLabel() + ")");
+
+ }
+ }
+
+ private static boolean isLogging(VitroRequest vreq) {
+ if (!log.isInfoEnabled()) {
+ return false;
+ }
+ DeveloperSettings settings = DeveloperSettings.getBean(vreq);
+ return settings.getBoolean(Keys.ENABLED)
+ && settings.getBoolean(Keys.PAGE_CONTENTS_LOG_CUSTOM_LIST_VIEW);
+ }
+}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java
index 651114aff..ad645f393 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/PropertyListConfig.java
@@ -61,6 +61,8 @@ public class PropertyListConfig {
String configFileName = wadf.getObjectPropertyDao().getCustomListViewConfigFileName(op);
if (configFileName == null) { // no custom config; use default config
configFileName = DEFAULT_CONFIG_FILE_NAME;
+ } else {
+ CustomListViewLogger.log(vreq, op, configFileName);
}
log.debug("Using list view config file " + configFileName + " for object property " + op.getURI());
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java
index 1240285c3..8235202a6 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java
@@ -81,7 +81,7 @@ public class GroupedPropertyList extends BaseTemplateModel {
// save applicable ranges before deduping to filter later
populatedObjectPropertyList = dedupe(populatedObjectPropertyList);
-
+
Collection additions = ApplicationConfigurationOntologyUtils
.getAdditionalFauxSubpropertiesForList(
populatedObjectPropertyList, subject, vreq);
@@ -121,13 +121,7 @@ public class GroupedPropertyList extends BaseTemplateModel {
if (editing) {
mergeAllPossibleDataProperties(propertyList);
}
-
-// Not currently necessary since the language-specific version is now added
-// during the merge
-// if (editing) {
-// propertyList = correctLanguageForProperties(propertyList);
-// }
-
+
sort(propertyList);
// Put the list into groups
@@ -176,35 +170,6 @@ public class GroupedPropertyList extends BaseTemplateModel {
return filteredAdditions;
}
- // Use the language-filtering WebappDaoFactory to get the right version of
- // each property. When editing, the methods that add to the property list
- // are blissfully (and intentionally) language-unaware.
- private List correctLanguageForProperties(List properties) {
- List languageCorrectedProps = new ArrayList();
- for (Property p : properties) {
- Property correctedProp = null;
- if (p instanceof ObjectProperty) {
- ObjectProperty op = (ObjectProperty) p;
- correctedProp = wdf.getObjectPropertyDao()
- .getObjectPropertyByURIs(op.getURI(),
- op.getDomainVClassURI(), op.getRangeVClassURI());
- } else if (p instanceof DataProperty) {
- correctedProp = wdf.getDataPropertyDao()
- .getDataPropertyByURI(((DataProperty) p).getURI());
- } else {
- log.warn("Ignoring " + p.getURI() + " which is neither an " +
- "ObjectProperty nor a DatatypeProperty.");
- }
- if (correctedProp != null) {
- languageCorrectedProps.add(correctedProp);
- } else {
- log.error("Unable to retrieve property " + p.getURI() +
- " using the WebappDaoFactory associated with the request.");
- }
- }
- return languageCorrectedProps;
- }
-
// It's possible that an object property retrieved in the call to getPopulatedObjectPropertyList()
// is now empty of statements, because if not editing, some statements without a linked individual
// are not retrieved by the query. (See elements in queries.)
@@ -281,16 +246,17 @@ public class GroupedPropertyList extends BaseTemplateModel {
continue;
}
boolean addToList = true;
- int opIndex = 0;
for(ObjectProperty op : populatedObjectPropertyList) {
- if(redundant(op, piOp)) {
+ RedundancyReason reason = redundant(op, piOp);
+ if(reason != null) {
addToList = false;
- if (moreRestrictiveRange(piOp, op, wadf)) {
- propertyList = replaceOpWithPiOpInList(piOp, op, opIndex, propertyList);
+ if (reason == RedundancyReason.LABEL_AND_URI_MATCH
+ && moreRestrictiveRange(piOp, op, wadf)) {
+ op.setRangeVClassURI(piOp.getRangeVClassURI());
+ op.setRangeVClass(piOp.getRangeVClass());
}
break;
}
- opIndex++;
}
if(addToList) {
propertyList.add(piOp);
@@ -315,6 +281,10 @@ public class GroupedPropertyList extends BaseTemplateModel {
return propertyList;
}
+ private enum RedundancyReason {
+ LABEL_AND_URI_MATCH, LABEL_URI_DOMAIN_AND_RANGE_MATCH
+ }
+
private boolean moreRestrictiveRange(ObjectProperty piOp, ObjectProperty op,
WebappDaoFactory wadf) {
if(piOp.getRangeVClassURI() == null) {
@@ -327,25 +297,9 @@ public class GroupedPropertyList extends BaseTemplateModel {
}
}
- private List replaceOpWithPiOpInList(ObjectProperty piOp,
- ObjectProperty op, int opIndex, List propertyList) {
-
- List returnList = new ArrayList();
- int index = 0;
- for(Property p : propertyList) {
- if(index == opIndex /* p.equals(op) */) {
- returnList.add(piOp);
- } else {
- returnList.add(p);
- }
- index++;
- }
- return returnList;
- }
-
- private boolean redundant(ObjectProperty op, ObjectProperty op2) {
+ private RedundancyReason redundant(ObjectProperty op, ObjectProperty op2) {
if (op2.getURI() == null) {
- return false;
+ return null;
}
boolean uriMatches = (op.getURI() != null
&& op.getURI().equals(op2.getURI()));
@@ -360,7 +314,7 @@ public class GroupedPropertyList extends BaseTemplateModel {
labelMatches = true;
}
if(uriMatches && labelMatches) {
- return true;
+ return RedundancyReason.LABEL_AND_URI_MATCH;
}
if(op.getDomainVClassURI() == null) {
if(op2.getDomainVClassURI() == null) {
@@ -377,9 +331,9 @@ public class GroupedPropertyList extends BaseTemplateModel {
rangeMatches = true;
}
if (uriMatches && domainMatches && rangeMatches) {
- return true;
+ return RedundancyReason.LABEL_URI_DOMAIN_AND_RANGE_MATCH;
}
- return false;
+ return null;
}
private void addObjectPropertyToPropertyList(String propertyUri, String domainUri, String rangeUri,
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyGroupTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyGroupTemplateModel.java
index b50469188..91d463f54 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyGroupTemplateModel.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyGroupTemplateModel.java
@@ -9,6 +9,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.display.DisplayDataProperty;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.display.DisplayObjectProperty;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
@@ -50,8 +51,15 @@ public class PropertyGroupTemplateModel extends BaseTemplateModel {
properties.add(tm);
}
+ } else if (p instanceof DataProperty){
+ DataProperty dp = (DataProperty) p;
+ RequestedAction dop = new DisplayDataProperty(dp);
+ if (!PolicyHelper.isAuthorizedForActions(vreq, dop)) {
+ continue;
+ }
+ properties.add(new DataPropertyTemplateModel(dp, subject, vreq, editing, populatedDataPropertyList));
} else {
- properties.add(new DataPropertyTemplateModel((DataProperty)p, subject, vreq, editing, populatedDataPropertyList));
+ log.debug(p.getURI() + " is neither an ObjectProperty nor a DataProperty; skipping display");
}
}
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyTemplateModel.java
index f7d5c603b..2fe95a71c 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyTemplateModel.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyTemplateModel.java
@@ -11,11 +11,14 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
+import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
+import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Property;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
+import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
@@ -94,6 +97,27 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
String editUrl = UrlBuilder.getUrl(getPropertyEditRoute(), "uri", property.getURI());
verboseDisplay.put("propertyEditUrl", editUrl);
+
+ if(isFauxProperty(property)) {
+ verboseDisplay.put("fauxProperty", "true");
+ }
+ }
+
+ private boolean isFauxProperty(Property prop) {
+ if(!(prop instanceof ObjectProperty)) {
+ return false;
+ }
+ ObjectPropertyDao opDao = vreq.getWebappDaoFactory().getObjectPropertyDao();
+ ObjectProperty baseProp = opDao.getObjectPropertyByURI(prop.getURI());
+ if(baseProp == null) {
+ return false;
+ }
+ ObjectProperty possibleFaux = (ObjectProperty) prop;
+ if (possibleFaux.getDomainPublic() == null) {
+ return (baseProp.getDomainPublic() != null);
+ } else {
+ return !possibleFaux.getDomainPublic().equals(baseProp.getDomainPublic());
+ }
}
protected abstract int getPropertyDisplayTier(Property p);
diff --git a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettingsStub.java b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettingsStub.java
new file mode 100644
index 000000000..6e2871596
--- /dev/null
+++ b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettingsStub.java
@@ -0,0 +1,33 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package stubs.edu.cornell.mannlib.vitro.webapp.utils.developer;
+
+import javax.servlet.ServletContext;
+
+import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
+
+/**
+ * Do everything that a standard DeveloperSettings would do, except loading from
+ * a properties file.
+ *
+ * That way, we don't require ConfigurationProperties to find the Vitro home
+ * directory, so we don't throw errors if there is no ConfigurationProperties.
+ */
+public class DeveloperSettingsStub extends DeveloperSettings {
+ /**
+ * Factory method. Create the stub and set it into the ServletContext.
+ */
+ public static void set(ServletContext ctx) {
+ ctx.setAttribute(ATTRIBUTE_NAME, new DeveloperSettingsStub(ctx));
+ }
+
+ protected DeveloperSettingsStub(ServletContext ctx) {
+ super(ctx);
+ }
+
+ @Override
+ protected void updateFromFile(ServletContext ctx) {
+ // Don't bother.
+ }
+
+}
diff --git a/webapp/test/stubs/javax/servlet/ServletContextStub.java b/webapp/test/stubs/javax/servlet/ServletContextStub.java
index 46e592d60..eb1e5eab7 100644
--- a/webapp/test/stubs/javax/servlet/ServletContextStub.java
+++ b/webapp/test/stubs/javax/servlet/ServletContextStub.java
@@ -21,6 +21,8 @@ import javax.servlet.ServletException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import stubs.edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettingsStub;
+
/**
* A simple stand-in for the {@link ServletContext}, for use in unit tests.
*/
@@ -36,6 +38,11 @@ public class ServletContextStub implements ServletContext {
private final Map mockResources = new HashMap();
private final Map realPaths = new HashMap();
+ public ServletContextStub() {
+ // Assume that unit tests won't want to use Developer mode.
+ DeveloperSettingsStub.set(this);
+ }
+
public void setContextPath(String contextPath) {
if (contextPath == null) {
throw new NullPointerException("contextPath may not be null.");
diff --git a/webapp/web/WEB-INF/web.xml b/webapp/web/WEB-INF/web.xml
index 3a5377bda..1d393a7b9 100644
--- a/webapp/web/WEB-INF/web.xml
+++ b/webapp/web/WEB-INF/web.xml
@@ -1025,6 +1025,16 @@
/admin/sparqlquery
+
+ SparqlUpdateApi
+ edu.cornell.mannlib.vitro.webapp.controller.api.SparqlUpdateApiController
+
+
+
+ SparqlUpdateApi
+ /api/sparqlUpdate
+
+
primitiveRdfEditedu.cornell.mannlib.vitro.webapp.controller.edit.PrimitiveRdfEdit
diff --git a/webapp/web/css/developer/developerPanel.css b/webapp/web/css/developer/developerPanel.css
new file mode 100644
index 000000000..ae61e5401
--- /dev/null
+++ b/webapp/web/css/developer/developerPanel.css
@@ -0,0 +1,48 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+/* Styles for the developer panel. */
+
+div.developer {
+ background-color: #f7dd8a;
+ padding: 0px 10px 0px 10px;
+ font-variant: small-caps;
+}
+
+div.developer #developerPanelBody {
+ display: none;
+ line-height: 1em;
+ font-size: small;
+}
+
+div.developer div.devleft {
+ width: 49%
+}
+
+div.developer div.devright {
+ float: right;
+ width: 49%
+}
+
+div.developer div.container {
+ border: thin groove black;
+ padding: 3px 10px 3px 10px;
+ margin: 3px 0px 3px 0px;
+}
+
+div.developer div.within {
+ padding-left: 1.5em;
+}
+
+div.developer input[type="text"] {
+ padding: 2px 10px 2px 10px;
+ line-height: 1em;
+ margin: 2px 2px 2px 2px;
+}
+
+div.developer input[type="text"]:disabled {
+ background-color: #f8eeae;
+}
+
+div.developer a {
+ margin: 3px;
+}
diff --git a/webapp/web/i18n/all.properties b/webapp/web/i18n/all.properties
index 336d1fefc..d201b66c9 100644
--- a/webapp/web/i18n/all.properties
+++ b/webapp/web/i18n/all.properties
@@ -456,7 +456,7 @@ please_create = Please create
a_classgroup = a class group
associate_classes_with_group = and associate classes with the group created.
-refresh_content = Refresh Content
+site_maintenance = Site Maintenance
rebuild_search_index = Rebuild search index
rebuild_vis_cache = Rebuild visualization cache
recompute_inferences_mixed_caps = Recompute inferences
diff --git a/webapp/web/js/developer/developerPanel.js b/webapp/web/js/developer/developerPanel.js
index 8c0c9a2b1..f7d881709 100644
--- a/webapp/web/js/developer/developerPanel.js
+++ b/webapp/web/js/developer/developerPanel.js
@@ -42,13 +42,16 @@ function DeveloperPanel(developerAjaxUrl) {
var developerEnabled = document.getElementById("developerEnabled").checked;
document.getElementById("developerDefeatFreemarkerCache").disabled = !developerEnabled;
document.getElementById("developerInsertFreemarkerDelimiters").disabled = !developerEnabled;
+ document.getElementById("developerPageContentsLogCustomListView").disabled = !developerEnabled;
+ document.getElementById("developerPageContentsLogCustomShortView").disabled = !developerEnabled;
document.getElementById("developerI18nDefeatCache").disabled = !developerEnabled;
document.getElementById("developerI18nLogStringRequests").disabled = !developerEnabled;
document.getElementById("developerLoggingRDFServiceEnable").disabled = !developerEnabled;
var rdfServiceEnabled = developerEnabled && document.getElementById("developerLoggingRDFServiceEnable").checked;
document.getElementById("developerLoggingRDFServiceStackTrace").disabled = !rdfServiceEnabled;
- document.getElementById("developerLoggingRDFServiceRestriction").disabled = !rdfServiceEnabled;
+ document.getElementById("developerLoggingRDFServiceQueryRestriction").disabled = !rdfServiceEnabled;
+ document.getElementById("developerLoggingRDFServiceStackRestriction").disabled = !rdfServiceEnabled;
}
function collectFormData() {
@@ -56,11 +59,14 @@ function DeveloperPanel(developerAjaxUrl) {
getCheckbox("developerEnabled", data);
getCheckbox("developerDefeatFreemarkerCache", data);
getCheckbox("developerInsertFreemarkerDelimiters", data);
+ getCheckbox("developerPageContentsLogCustomListView", data);
+ getCheckbox("developerPageContentsLogCustomShortView", data);
getCheckbox("developerI18nDefeatCache", data);
getCheckbox("developerI18nLogStringRequests", data);
getCheckbox("developerLoggingRDFServiceEnable", data);
getCheckbox("developerLoggingRDFServiceStackTrace", data);
- getText("developerLoggingRDFServiceRestriction", data);
+ getText("developerLoggingRDFServiceQueryRestriction", data);
+ getText("developerLoggingRDFServiceStackRestriction", data);
return data;
}
diff --git a/webapp/web/js/vitroUtils.js b/webapp/web/js/vitroUtils.js
index e910efa74..10e5f564b 100644
--- a/webapp/web/js/vitroUtils.js
+++ b/webapp/web/js/vitroUtils.js
@@ -13,20 +13,16 @@ $(document).ready(function(){
jQuery('section#flash-message').css('display', 'none').fadeIn(1500);
/////////////////////////////
- // Home search fiter
+ // Home search filter
// Toggle filter select list
var $searchFilterList = $('#filter-search-nav');
var $isFilterOpen = false;
- console.log("Filter is open = " + $isFilterOpen);
-
$('a.filter-search').click(function(e) {
e.preventDefault();
if (!$isFilterOpen) {
- console.log("Filter is closed = " + $isFilterOpen);
-
//Change button filter state to selected
//$(this).css('background','url(../../themes/vivo-cornell/images/filteredSearchActive.gif) no-repeat right top');
$(this).removeClass('filter-default');
@@ -37,7 +33,6 @@ $(document).ready(function(){
$isFilterOpen = true;
- console.log("open");
} else {
//Change button filter state to default
//$('a.filter-search').css('background','url(../../themes/vivo-cornell/images/filteredSearch.gif) no-repeat right top');
@@ -49,7 +44,6 @@ $(document).ready(function(){
$isFilterOpen = false;
- console.log("closed");
}
});
@@ -63,7 +57,6 @@ $(document).ready(function(){
//Selected filter feedback
$('.search-filter-selected').text('');
$('input[name="classgroup"]').val('');
- console.log("ALL");
} else {
$('.search-filter-selected').text($(this).text()).fadeIn('slow');
@@ -110,6 +103,5 @@ $(document).ready(function(){
}
- console.log("HIDE input value ") ;
});
});
diff --git a/webapp/web/templates/freemarker/body/menupage/page-sparqlUpdateTest.ftl b/webapp/web/templates/freemarker/body/menupage/page-sparqlUpdateTest.ftl
deleted file mode 100644
index 17274f829..000000000
--- a/webapp/web/templates/freemarker/body/menupage/page-sparqlUpdateTest.ftl
+++ /dev/null
@@ -1,12 +0,0 @@
-<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
-
-
SPARQL Update Test
-
-
This is an expermental SPARQL update service.
-
-
\ No newline at end of file
diff --git a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-indexCacheRebuild.ftl b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-indexCacheRebuild.ftl
deleted file mode 100644
index c2317ce27..000000000
--- a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-indexCacheRebuild.ftl
+++ /dev/null
@@ -1,27 +0,0 @@
-<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
-
-<#-- Template for the main Site Administration page -->
-
-<#if indexCacheRebuild?has_content>
-
-
#if>
diff --git a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteMaintenance.ftl b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteMaintenance.ftl
new file mode 100644
index 000000000..ab1a20189
--- /dev/null
+++ b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteMaintenance.ftl
@@ -0,0 +1,31 @@
+<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
+
+<#-- Template for the main Site Administration page -->
+
+<#if siteMaintenance?has_content>
+
+