Merge commit 'f129f727a7
' into dev-isf
This commit is contained in:
commit
a520878b1d
122 changed files with 6031 additions and 3353 deletions
|
@ -0,0 +1,20 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
|
||||
|
||||
import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.VITRO_AUTH;
|
||||
|
||||
/**
|
||||
* Constants and static methods to help manipulate PermissionSet instances.
|
||||
*/
|
||||
public class PermissionSets {
|
||||
public static final String URI_SELF_EDITOR = VITRO_AUTH + "SELF_EDITOR";
|
||||
public static final String URI_EDITOR = VITRO_AUTH + "EDITOR";
|
||||
public static final String URI_CURATOR = VITRO_AUTH + "CURATOR";
|
||||
public static final String URI_DBA = VITRO_AUTH + "ADMIN";
|
||||
|
||||
/** No need to create an instance. */
|
||||
private PermissionSets() {
|
||||
// Nothing to initialize.
|
||||
}
|
||||
}
|
|
@ -1,355 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
|
||||
|
||||
import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.VITRO_AUTH;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
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.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Selector;
|
||||
import com.hp.hpl.jena.rdf.model.SimpleSelector;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||
import com.hp.hpl.jena.vocabulary.RDF;
|
||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
|
||||
/**
|
||||
* Load the initial configuration of PermissionSets and Permissions.
|
||||
*
|
||||
* The UserAccounts model must be created before this runs.
|
||||
*
|
||||
* The PermissionRegistry must be created before this runs.
|
||||
*/
|
||||
public class PermissionSetsLoader implements ServletContextListener {
|
||||
private static final Log log = LogFactory
|
||||
.getLog(PermissionSetsLoader.class);
|
||||
|
||||
public static final String FILE_OF_PERMISSION_SETS_INFO = "/WEB-INF/resources/permission_config.n3";
|
||||
|
||||
public static final String URI_SELF_EDITOR = VITRO_AUTH + "SELF_EDITOR";
|
||||
public static final String URI_EDITOR = VITRO_AUTH + "EDITOR";
|
||||
public static final String URI_CURATOR = VITRO_AUTH + "CURATOR";
|
||||
public static final String URI_DBA = VITRO_AUTH + "ADMIN";
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext ctx = sce.getServletContext();
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
|
||||
try {
|
||||
new Loader(this, ctx, ss).load();
|
||||
new SmokeTester(this, ctx, ss).test();
|
||||
} catch (Exception e) {
|
||||
ss.fatal(this, "Failed to load the PermissionSets", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
// Nothing to tear down.
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Loader class
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private static class Loader {
|
||||
private static final int MAX_STATEMENTS_IN_WARNING = 5;
|
||||
|
||||
private ServletContextListener listener;
|
||||
private final ServletContext ctx;
|
||||
private final StartupStatus ss;
|
||||
|
||||
private final OntModel userAccountsModel;
|
||||
private final Property permissionSetType;
|
||||
|
||||
private Model modelFromFile;
|
||||
private Model filteredModel;
|
||||
|
||||
private int howManyNewPermissionSets;
|
||||
private int howManyOldPermissionSets;
|
||||
|
||||
public Loader(ServletContextListener listener, ServletContext ctx,
|
||||
StartupStatus ss) {
|
||||
this.listener = listener;
|
||||
this.ctx = ctx;
|
||||
this.ss = ss;
|
||||
|
||||
this.userAccountsModel = ModelAccess.on(ctx).getUserAccountsModel();
|
||||
this.permissionSetType = this.userAccountsModel
|
||||
.getProperty(VitroVocabulary.PERMISSIONSET);
|
||||
|
||||
}
|
||||
|
||||
public void load() {
|
||||
try {
|
||||
createModelFromFile();
|
||||
filterModelFromFile();
|
||||
checkForLeftoverStatements();
|
||||
removeExistingPermissionSetsFromUserAccountsModel();
|
||||
addNewStatementsToUserAccountsModel();
|
||||
|
||||
ss.info(listener, buildInfoMessage());
|
||||
} catch (LoaderException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
ss.warning(listener, e.getMessage());
|
||||
} else {
|
||||
ss.warning(listener, e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createModelFromFile() throws LoaderException {
|
||||
InputStream stream = ctx
|
||||
.getResourceAsStream(FILE_OF_PERMISSION_SETS_INFO);
|
||||
|
||||
if (stream == null) {
|
||||
throw new LoaderException("The permission sets config file "
|
||||
+ "doesn't exist in the servlet context: '"
|
||||
+ FILE_OF_PERMISSION_SETS_INFO + "'");
|
||||
}
|
||||
|
||||
try {
|
||||
modelFromFile = ModelFactory.createDefaultModel();
|
||||
modelFromFile.read(stream, null, "N3");
|
||||
} finally {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("Loaded " + modelFromFile.size() + " statements");
|
||||
}
|
||||
|
||||
/**
|
||||
* Move all statements that relate to PermissionSets from the loaded
|
||||
* model to the filtered model.
|
||||
*/
|
||||
private void filterModelFromFile() {
|
||||
filteredModel = ModelFactory.createDefaultModel();
|
||||
|
||||
for (Resource r : iterable(modelFromFile.listResourcesWithProperty(
|
||||
RDF.type, permissionSetType))) {
|
||||
moveStatementsToFilteredModel(r);
|
||||
howManyNewPermissionSets++;
|
||||
}
|
||||
|
||||
log.debug("Filtered " + filteredModel.size() + " statements for "
|
||||
+ howManyNewPermissionSets + " PermissionSets; "
|
||||
+ modelFromFile.size() + " extraneous statements.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the statements about this PermissionSet from the loaded model to
|
||||
* the filtered model.
|
||||
*/
|
||||
private void moveStatementsToFilteredModel(Resource ps) {
|
||||
Selector sel = new SimpleSelector(ps, null, (String) null);
|
||||
for (Statement stmt : iterable(modelFromFile.listStatements(sel))) {
|
||||
filteredModel.add(stmt);
|
||||
modelFromFile.remove(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complain about any statements that were not moved to the filtered
|
||||
* model.
|
||||
*/
|
||||
private void checkForLeftoverStatements() {
|
||||
List<Statement> list = iterable(modelFromFile.listStatements());
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message = "The PermissionSets configuration file contained "
|
||||
+ list.size()
|
||||
+ " statements that didn't describe PermissionSets: ";
|
||||
for (int i = 0; i < Math
|
||||
.min(list.size(), MAX_STATEMENTS_IN_WARNING); i++) {
|
||||
Statement stmt = list.get(i);
|
||||
message += "(" + stmt.asTriple() + ") ";
|
||||
}
|
||||
if (list.size() > MAX_STATEMENTS_IN_WARNING) {
|
||||
message += ", ...";
|
||||
}
|
||||
|
||||
ss.warning(listener, message);
|
||||
}
|
||||
|
||||
private void removeExistingPermissionSetsFromUserAccountsModel() {
|
||||
userAccountsModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
for (Resource r : iterable(userAccountsModel
|
||||
.listResourcesWithProperty(RDF.type, permissionSetType))) {
|
||||
Selector sel = new SimpleSelector(r, null, (String) null);
|
||||
StmtIterator stmts = userAccountsModel.listStatements(sel);
|
||||
userAccountsModel.remove(stmts);
|
||||
howManyOldPermissionSets++;
|
||||
}
|
||||
} finally {
|
||||
userAccountsModel.leaveCriticalSection();
|
||||
}
|
||||
|
||||
log.debug("Deleted " + howManyOldPermissionSets
|
||||
+ " old PermissionSets from the user model.");
|
||||
}
|
||||
|
||||
private void addNewStatementsToUserAccountsModel() {
|
||||
userAccountsModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
userAccountsModel.add(filteredModel);
|
||||
} finally {
|
||||
userAccountsModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
private String buildInfoMessage() {
|
||||
String message = "Loaded " + howManyNewPermissionSets
|
||||
+ " PermissionSets: ";
|
||||
Selector sel = new SimpleSelector(null, RDFS.label, (String) null);
|
||||
for (Statement stmt : iterable(filteredModel.listStatements(sel))) {
|
||||
String label = stmt.getObject().asLiteral().getString();
|
||||
message += "'" + label + "' ";
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private <T> List<T> iterable(ClosableIterator<T> iterator) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
try {
|
||||
while (iterator.hasNext()) {
|
||||
list.add(iterator.next());
|
||||
}
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// SmokeTester class
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private static class SmokeTester {
|
||||
private ServletContextListener listener;
|
||||
private final ServletContext ctx;
|
||||
private final StartupStatus ss;
|
||||
|
||||
private final UserAccountsDao uaDao;
|
||||
|
||||
public SmokeTester(ServletContextListener listener, ServletContext ctx,
|
||||
StartupStatus ss) {
|
||||
this.listener = listener;
|
||||
this.ctx = ctx;
|
||||
this.ss = ss;
|
||||
|
||||
WebappDaoFactory wadf = ModelAccess.on(ctx).getWebappDaoFactory();
|
||||
if (wadf == null) {
|
||||
throw new IllegalStateException(
|
||||
"No webappDaoFactory on the servlet context");
|
||||
}
|
||||
this.uaDao = wadf.getUserAccountsDao();
|
||||
}
|
||||
|
||||
public void test() {
|
||||
checkForPermissionSetsWithoutLabels();
|
||||
checkForReferencesToNonexistentPermissionSets();
|
||||
checkForReferencesToNonexistentPermissions();
|
||||
warnIfNoPermissionSetsForNewUsers();
|
||||
}
|
||||
|
||||
private void checkForPermissionSetsWithoutLabels() {
|
||||
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
|
||||
if (ps.getLabel().isEmpty()) {
|
||||
ss.warning(listener, "This PermissionSet has no label: "
|
||||
+ ps.getUri());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForReferencesToNonexistentPermissionSets() {
|
||||
for (UserAccount user : uaDao.getAllUserAccounts()) {
|
||||
for (String psUri : user.getPermissionSetUris()) {
|
||||
if (uaDao.getPermissionSetByUri(psUri) == null) {
|
||||
ss.warning(listener, "The user '" + user.getFirstName()
|
||||
+ " " + user.getLastName()
|
||||
+ "' has the PermissionSet '" + psUri
|
||||
+ "', but the PermissionSet doesn't exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForReferencesToNonexistentPermissions() {
|
||||
PermissionRegistry registry = PermissionRegistry.getRegistry(ctx);
|
||||
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
|
||||
for (String pUri : ps.getPermissionUris()) {
|
||||
if (!registry.isPermission(pUri)) {
|
||||
ss.warning(listener,
|
||||
"The PermissionSet '" + ps.getLabel()
|
||||
+ "' has the Permission '" + pUri
|
||||
+ "', but the Permission "
|
||||
+ "is not found in the registry.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void warnIfNoPermissionSetsForNewUsers() {
|
||||
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
|
||||
if (ps.isForNewUsers()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ss.warning(listener, "No PermissionSet has been declared to be a "
|
||||
+ "PermissionSet for new users.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handy dandy exception.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private static class LoaderException extends Exception {
|
||||
|
||||
public LoaderException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public LoaderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
|
||||
|
||||
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 edu.cornell.mannlib.vitro.webapp.beans.PermissionSet;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
|
||||
/**
|
||||
* Load the initial configuration of PermissionSets and Permissions.
|
||||
*
|
||||
* The UserAccounts model must be created before this runs.
|
||||
*
|
||||
* The PermissionRegistry must be created before this runs.
|
||||
*/
|
||||
public class PermissionSetsSmokeTest implements ServletContextListener {
|
||||
@SuppressWarnings("unused")
|
||||
private static final Log log = LogFactory
|
||||
.getLog(PermissionSetsSmokeTest.class);
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext ctx = sce.getServletContext();
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
|
||||
try {
|
||||
new SmokeTester(this, ctx, ss).test();
|
||||
} catch (Exception e) {
|
||||
ss.fatal(this, "Found a problem while testing the PermissionSets",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
// Nothing to tear down.
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// SmokeTester class
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private static class SmokeTester {
|
||||
private ServletContextListener listener;
|
||||
private final ServletContext ctx;
|
||||
private final StartupStatus ss;
|
||||
|
||||
private final UserAccountsDao uaDao;
|
||||
|
||||
public SmokeTester(ServletContextListener listener, ServletContext ctx,
|
||||
StartupStatus ss) {
|
||||
this.listener = listener;
|
||||
this.ctx = ctx;
|
||||
this.ss = ss;
|
||||
|
||||
this.uaDao = ModelAccess.on(ctx).getWebappDaoFactory()
|
||||
.getUserAccountsDao();
|
||||
}
|
||||
|
||||
public void test() {
|
||||
checkForPermissionSetsWithoutLabels();
|
||||
checkForReferencesToNonexistentPermissionSets();
|
||||
checkForReferencesToNonexistentPermissions();
|
||||
warnIfNoPermissionSetsForNewUsers();
|
||||
}
|
||||
|
||||
private void checkForPermissionSetsWithoutLabels() {
|
||||
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
|
||||
if (ps.getLabel().isEmpty()) {
|
||||
ss.warning(listener, "This PermissionSet has no label: "
|
||||
+ ps.getUri());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForReferencesToNonexistentPermissionSets() {
|
||||
for (UserAccount user : uaDao.getAllUserAccounts()) {
|
||||
for (String psUri : user.getPermissionSetUris()) {
|
||||
if (uaDao.getPermissionSetByUri(psUri) == null) {
|
||||
ss.warning(listener, "The user '" + user.getFirstName()
|
||||
+ " " + user.getLastName()
|
||||
+ "' has the PermissionSet '" + psUri
|
||||
+ "', but the PermissionSet doesn't exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForReferencesToNonexistentPermissions() {
|
||||
PermissionRegistry registry = PermissionRegistry.getRegistry(ctx);
|
||||
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
|
||||
for (String pUri : ps.getPermissionUris()) {
|
||||
if (!registry.isPermission(pUri)) {
|
||||
ss.warning(listener,
|
||||
"The PermissionSet '" + ps.getLabel()
|
||||
+ "' has the Permission '" + pUri
|
||||
+ "', but the Permission "
|
||||
+ "is not found in the registry.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void warnIfNoPermissionSetsForNewUsers() {
|
||||
for (PermissionSet ps : uaDao.getAllPermissionSets()) {
|
||||
if (ps.isForNewUsers()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ss.warning(listener, "No PermissionSet has been declared to be a "
|
||||
+ "PermissionSet for new users.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -27,55 +27,55 @@ public class SimplePermission extends Permission {
|
|||
private static final Map<String, SimplePermission> allInstances = new HashMap<String, SimplePermission>();
|
||||
|
||||
public static final SimplePermission ACCESS_SPECIAL_DATA_MODELS = new SimplePermission(
|
||||
"AccessSpecialDataModels");
|
||||
NAMESPACE + "AccessSpecialDataModels");
|
||||
public static final SimplePermission DO_BACK_END_EDITING = new SimplePermission(
|
||||
"DoBackEndEditing");
|
||||
NAMESPACE + "DoBackEndEditing");
|
||||
public static final SimplePermission DO_FRONT_END_EDITING = new SimplePermission(
|
||||
"DoFrontEndEditing");
|
||||
NAMESPACE + "DoFrontEndEditing");
|
||||
public static final SimplePermission EDIT_ONTOLOGY = new SimplePermission(
|
||||
"EditOntology");
|
||||
NAMESPACE + "EditOntology");
|
||||
public static final SimplePermission EDIT_OWN_ACCOUNT = new SimplePermission(
|
||||
"EditOwnAccount");
|
||||
NAMESPACE + "EditOwnAccount");
|
||||
public static final SimplePermission EDIT_SITE_INFORMATION = new SimplePermission(
|
||||
"EditSiteInformation");
|
||||
NAMESPACE + "EditSiteInformation");
|
||||
public static final SimplePermission LOGIN_DURING_MAINTENANCE = new SimplePermission(
|
||||
"LoginDuringMaintenance");
|
||||
NAMESPACE + "LoginDuringMaintenance");
|
||||
public static final SimplePermission MANAGE_MENUS = new SimplePermission(
|
||||
"ManageMenus");
|
||||
NAMESPACE + "ManageMenus");
|
||||
public static final SimplePermission MANAGE_OWN_PROXIES = new SimplePermission(
|
||||
"ManageOwnProxies");
|
||||
NAMESPACE + "ManageOwnProxies");
|
||||
public static final SimplePermission MANAGE_PORTALS = new SimplePermission(
|
||||
"ManagePortals");
|
||||
NAMESPACE + "ManagePortals");
|
||||
public static final SimplePermission MANAGE_PROXIES = new SimplePermission(
|
||||
"ManageProxies");
|
||||
NAMESPACE + "ManageProxies");
|
||||
public static final SimplePermission MANAGE_SEARCH_INDEX = new SimplePermission(
|
||||
"ManageSearchIndex");
|
||||
NAMESPACE + "ManageSearchIndex");
|
||||
public static final SimplePermission MANAGE_TABS = new SimplePermission(
|
||||
"ManageTabs");
|
||||
NAMESPACE + "ManageTabs");
|
||||
public static final SimplePermission MANAGE_USER_ACCOUNTS = new SimplePermission(
|
||||
"ManageUserAccounts");
|
||||
NAMESPACE + "ManageUserAccounts");
|
||||
public static final SimplePermission QUERY_FULL_MODEL = new SimplePermission(
|
||||
"QueryFullModel");
|
||||
NAMESPACE + "QueryFullModel");
|
||||
public static final SimplePermission QUERY_USER_ACCOUNTS_MODEL = new SimplePermission(
|
||||
"QueryUserAccountsModel");
|
||||
NAMESPACE + "QueryUserAccountsModel");
|
||||
public static final SimplePermission REBUILD_VCLASS_GROUP_CACHE = new SimplePermission(
|
||||
"RebuildVClassGroupCache");
|
||||
NAMESPACE + "RebuildVClassGroupCache");
|
||||
public static final SimplePermission REFRESH_VISUALIZATION_CACHE = new SimplePermission(
|
||||
"RefreshVisualizationCache");
|
||||
NAMESPACE + "RefreshVisualizationCache");
|
||||
public static final SimplePermission SEE_INDVIDUAL_EDITING_PANEL = new SimplePermission(
|
||||
"SeeIndividualEditingPanel");
|
||||
NAMESPACE + "SeeIndividualEditingPanel");
|
||||
public static final SimplePermission SEE_REVISION_INFO = new SimplePermission(
|
||||
"SeeRevisionInfo");
|
||||
NAMESPACE + "SeeRevisionInfo");
|
||||
public static final SimplePermission SEE_SITE_ADMIN_PAGE = new SimplePermission(
|
||||
"SeeSiteAdminPage");
|
||||
NAMESPACE + "SeeSiteAdminPage");
|
||||
public static final SimplePermission SEE_STARTUP_STATUS = new SimplePermission(
|
||||
"SeeStartupStatus");
|
||||
NAMESPACE + "SeeStartupStatus");
|
||||
public static final SimplePermission SEE_VERBOSE_PROPERTY_INFORMATION = new SimplePermission(
|
||||
"SeeVerbosePropertyInformation");
|
||||
NAMESPACE + "SeeVerbosePropertyInformation");
|
||||
public static final SimplePermission USE_ADVANCED_DATA_TOOLS_PAGES = new SimplePermission(
|
||||
"UseAdvancedDataToolsPages");
|
||||
NAMESPACE + "UseAdvancedDataToolsPages");
|
||||
public static final SimplePermission USE_SPARQL_QUERY_PAGE = new SimplePermission(
|
||||
"UseSparqlQueryPage");
|
||||
NAMESPACE + "UseSparqlQueryPage");
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// These instances are "catch all" permissions to cover poorly defined
|
||||
|
@ -84,33 +84,35 @@ public class SimplePermission extends Permission {
|
|||
// ----------------------------------------------------------------------
|
||||
|
||||
public static final SimplePermission USE_BASIC_AJAX_CONTROLLERS = new SimplePermission(
|
||||
"UseBasicAjaxControllers");
|
||||
NAMESPACE + "UseBasicAjaxControllers");
|
||||
public static final SimplePermission USE_MISCELLANEOUS_ADMIN_PAGES = new SimplePermission(
|
||||
"UseMiscellaneousAdminPages");
|
||||
NAMESPACE + "UseMiscellaneousAdminPages");
|
||||
public static final SimplePermission USE_MISCELLANEOUS_CURATOR_PAGES = new SimplePermission(
|
||||
"UseMiscellaneousCuratorPages");
|
||||
NAMESPACE + "UseMiscellaneousCuratorPages");
|
||||
public static final SimplePermission USE_MISCELLANEOUS_EDITOR_PAGES = new SimplePermission(
|
||||
"UseMiscellaneousEditorPages");
|
||||
NAMESPACE + "UseMiscellaneousEditorPages");
|
||||
public static final SimplePermission USE_MISCELLANEOUS_PAGES = new SimplePermission(
|
||||
"UseMiscellaneousPages");
|
||||
NAMESPACE + "UseMiscellaneousPages");
|
||||
|
||||
public static List<SimplePermission> getAllInstances() {
|
||||
return new ArrayList<SimplePermission>(allInstances.values());
|
||||
}
|
||||
|
||||
private final String localName;
|
||||
//private final String localName;
|
||||
private final String uri;
|
||||
public final RequestedAction ACTION;
|
||||
public final Actions ACTIONS;
|
||||
|
||||
public SimplePermission(String localName) {
|
||||
super(NAMESPACE + localName);
|
||||
public SimplePermission(String uri) {
|
||||
super(uri);
|
||||
|
||||
if (localName == null) {
|
||||
throw new NullPointerException("name may not be null.");
|
||||
if (uri == null) {
|
||||
throw new NullPointerException("uri may not be null.");
|
||||
}
|
||||
|
||||
this.localName = localName;
|
||||
this.ACTION = new SimpleRequestedAction(localName);
|
||||
//this.localName = localName;
|
||||
this.uri = uri;
|
||||
this.ACTION = new SimpleRequestedAction(uri);
|
||||
this.ACTIONS = new Actions(this.ACTION);
|
||||
|
||||
if (allInstances.containsKey(this.uri)) {
|
||||
|
@ -120,14 +122,6 @@ public class SimplePermission extends Permission {
|
|||
allInstances.put(uri, this);
|
||||
}
|
||||
|
||||
public String getLocalName() {
|
||||
return this.localName;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return NAMESPACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(RequestedAction whatToAuth) {
|
||||
if (whatToAuth != null) {
|
||||
|
@ -142,7 +136,7 @@ public class SimplePermission extends Permission {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimplePermission['" + localName + "']";
|
||||
return "SimplePermission['" + uri+ "']";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
||||
|
||||
/**
|
||||
* Policy decision that is made from some analysis of a set of decisions.
|
||||
* @author bdc34
|
||||
*
|
||||
*/
|
||||
public class CompositPolicyDecision extends BasicPolicyDecision implements PolicyDecision {
|
||||
List<PolicyDecision> subDecisions;
|
||||
|
||||
public CompositPolicyDecision(Authorization auth, String message, List<PolicyDecision> subDecisions){
|
||||
super( auth, message);
|
||||
this.subDecisions = subDecisions;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,8 +17,10 @@ import com.hp.hpl.jena.rdf.model.Resource;
|
|||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.ActiveIdentifierBundleFactories;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
|
@ -26,6 +28,9 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddDataPro
|
|||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddObjectPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.DropDataPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.DropObjectPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.BasicAuthenticator;
|
||||
|
||||
/**
|
||||
* A collection of static methods to help determine whether requested actions
|
||||
|
@ -53,7 +58,7 @@ public class PolicyHelper {
|
|||
IdentifierBundle ids = RequestIdentifiers.getIdBundleForRequest(req);
|
||||
return isAuthorizedForActions(ids, policy, actions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Are these actions authorized for these identifiers by these policies?
|
||||
*/
|
||||
|
@ -62,6 +67,48 @@ public class PolicyHelper {
|
|||
return Actions.notNull(actions).isAuthorized(policy, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the email/password authorized for these actions?
|
||||
* This should be used when a controller or something needs allow
|
||||
* actions if the user passes in their email and password.
|
||||
*
|
||||
* It may be better to check this as part of a servlet Filter and
|
||||
* add an identifier bundle.
|
||||
*/
|
||||
public static boolean isAuthorizedForActions( HttpServletRequest req,
|
||||
String email, String password,
|
||||
Actions actions){
|
||||
|
||||
if( password == null || email == null ||
|
||||
password.isEmpty() || email.isEmpty()){
|
||||
return false;
|
||||
}
|
||||
|
||||
try{
|
||||
Authenticator basicAuth = new BasicAuthenticator(req);
|
||||
UserAccount user = basicAuth.getAccountForInternalAuth( email );
|
||||
log.debug("userAccount is " + user==null?"null":user.getUri() );
|
||||
|
||||
if( ! basicAuth.isCurrentPassword( user, password ) ){
|
||||
log.debug(String.format("UNAUTHORIZED, password not accepted for %s, account URI: %s",
|
||||
user.getEmailAddress(), user.getUri()));
|
||||
return false;
|
||||
}else{
|
||||
log.debug(String.format("password accepted for %s, account URI: %s",
|
||||
user.getEmailAddress(), user.getUri() ));
|
||||
// figure out if that account can do the actions
|
||||
IdentifierBundle ids =
|
||||
ActiveIdentifierBundleFactories.getUserIdentifierBundle(req,user);
|
||||
PolicyIface policy = ServletPolicyList.getPolicies(req);
|
||||
return PolicyHelper.isAuthorizedForActions( ids, policy, actions );
|
||||
}
|
||||
|
||||
}catch(Exception ex){
|
||||
log.error("Error while attempting to authorize actions " + actions.toString(), ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the current policies authorize the current user to add this statement
|
||||
* to this model?
|
||||
|
@ -263,6 +310,7 @@ public class PolicyHelper {
|
|||
+ stmt.getObject() + ">";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* No need to instantiate this helper class - all methods are static.
|
||||
*/
|
||||
|
|
|
@ -4,6 +4,8 @@ package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
@ -12,6 +14,8 @@ import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
|||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AllRequestedAction;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AnyRequestedAction;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
|
||||
/**
|
||||
|
@ -38,8 +42,68 @@ public class PolicyList extends ArrayList<PolicyIface> implements PolicyIface{
|
|||
|
||||
@Override
|
||||
public PolicyDecision isAuthorized(IdentifierBundle whoToAuth, RequestedAction whatToAuth) {
|
||||
PolicyDecision pd = null;
|
||||
for(PolicyIface policy : this){
|
||||
|
||||
if( whatToAuth instanceof AllRequestedAction ){
|
||||
return doAllAction( whoToAuth, ((AllRequestedAction)whatToAuth));
|
||||
}else if ( whatToAuth instanceof AnyRequestedAction ){
|
||||
return doAnyAction(whoToAuth, ((AnyRequestedAction)whatToAuth));
|
||||
}else{
|
||||
return checkAgainstPolicys( whoToAuth , whatToAuth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that at least one of the subRequestedActions are authorized.
|
||||
*/
|
||||
private PolicyDecision doAnyAction(IdentifierBundle whoToAuth,
|
||||
AnyRequestedAction whatToAuth) {
|
||||
boolean anyAuth = false;
|
||||
List<PolicyDecision> subPd = new LinkedList<PolicyDecision>();
|
||||
for( RequestedAction subAct : whatToAuth.getRequestedActions()){
|
||||
PolicyDecision pd = isAuthorized(whoToAuth,subAct);
|
||||
subPd.add(pd);
|
||||
if( pd.getAuthorized() == Authorization.AUTHORIZED){
|
||||
anyAuth = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( anyAuth )
|
||||
return new CompositPolicyDecision( Authorization.AUTHORIZED,
|
||||
"Some sub-RequestedAction authorized", subPd);
|
||||
else
|
||||
return new CompositPolicyDecision( Authorization.UNAUTHORIZED,
|
||||
"None of the sub-RequestedAction were authorized", subPd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all the subRequestedActions are authorized.
|
||||
*/
|
||||
private PolicyDecision doAllAction(IdentifierBundle whoToAuth, AllRequestedAction whatToAuth) {
|
||||
boolean allAuth = true;
|
||||
|
||||
List<PolicyDecision> subPd = new LinkedList<PolicyDecision>();
|
||||
for( RequestedAction subAct : whatToAuth.getRequestedActions()){
|
||||
PolicyDecision pd = isAuthorized( whoToAuth, subAct) ;
|
||||
subPd.add( pd );
|
||||
if( pd.getAuthorized() != Authorization.AUTHORIZED ){
|
||||
allAuth = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( allAuth )
|
||||
return new CompositPolicyDecision(
|
||||
Authorization.AUTHORIZED,
|
||||
"All sub-RequestedActions authorized.", subPd );
|
||||
else
|
||||
return new CompositPolicyDecision(
|
||||
Authorization.UNAUTHORIZED,
|
||||
"Not all sub-RequestedActions authorized.", subPd );
|
||||
}
|
||||
|
||||
protected PolicyDecision checkAgainstPolicys( IdentifierBundle whoToAuth, RequestedAction whatToAuth){
|
||||
PolicyDecision pd = null;
|
||||
for(PolicyIface policy : this){
|
||||
try{
|
||||
pd = policy.isAuthorized(whoToAuth, whatToAuth);
|
||||
if( pd != null ){
|
||||
|
@ -47,8 +111,8 @@ public class PolicyList extends ArrayList<PolicyIface> implements PolicyIface{
|
|||
break;
|
||||
if( pd.getAuthorized() == Authorization.UNAUTHORIZED )
|
||||
break;
|
||||
// if( pd.getAuthorized() == Authorization.INCONCLUSIVE )
|
||||
// continue;
|
||||
if( pd.getAuthorized() == Authorization.INCONCLUSIVE )
|
||||
continue;
|
||||
} else{
|
||||
log.debug("policy " + policy.toString() + " returned a null PolicyDecision");
|
||||
}
|
||||
|
@ -58,6 +122,6 @@ public class PolicyList extends ArrayList<PolicyIface> implements PolicyIface{
|
|||
}
|
||||
log.debug("decision " + pd + " for " + whatToAuth);
|
||||
return pd;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces;
|
||||
|
||||
/**
|
||||
* Object to represent a decision from a policy. The intent is
|
||||
* that the message would be presented to users to indicate why
|
||||
* they are not authorized for some action.
|
||||
*/
|
||||
public interface PolicyDecision {
|
||||
public Authorization getAuthorized();
|
||||
|
||||
|
|
|
@ -21,12 +21,16 @@ import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
|||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
|
||||
/**
|
||||
* An immutable list of OR and AND relationships for the required
|
||||
* authorizations. A group of AND relationships is a "clause", and the list of
|
||||
* clauses are in an OR relationship.
|
||||
* A list of RequiredAction objects.
|
||||
*
|
||||
* Authorization is successful if ALL of the actions in ANY of the clauses are
|
||||
* Authorization is considered successful if ALL of the actions are
|
||||
* authorized, or if there are NO clauses.
|
||||
*
|
||||
* A previous version of this class had a capability to do OR clauses but
|
||||
* this feature was unused and hindered composition of Actions
|
||||
* objects. The ability to do an OR has been moved to AnyRequestedAction
|
||||
* and AllRequestedAction.
|
||||
*
|
||||
*/
|
||||
public class Actions {
|
||||
private static final Log log = LogFactory.getLog(Actions.class);
|
||||
|
@ -39,104 +43,194 @@ public class Actions {
|
|||
return (actions == null) ? AUTHORIZED : actions;
|
||||
}
|
||||
|
||||
private final List<Set<RequestedAction>> clauseList;
|
||||
/**
|
||||
* This is a set of RequestedActions that get ANDed together.
|
||||
*
|
||||
* If all of the RequestedAction objects from the
|
||||
* Sets are authorized, then the Actions object should
|
||||
* be considered authorized.
|
||||
*/
|
||||
private Set<RequestedAction> requestedActions;
|
||||
|
||||
public Actions(){
|
||||
requestedActions= Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* AND together all the RequestedAction from all the actions.
|
||||
*/
|
||||
public Actions(Actions... actions){
|
||||
Set<RequestedAction> newActs = new HashSet<RequestedAction>();
|
||||
|
||||
for( Actions actionToAnd : actions){
|
||||
if( actionToAnd != null && actionToAnd.requestedActions != null ){
|
||||
newActs.addAll( actionToAnd.requestedActions );
|
||||
}
|
||||
}
|
||||
|
||||
this.requestedActions = Collections.unmodifiableSet( newActs );
|
||||
}
|
||||
|
||||
public Actions(RequestedAction... actions) {
|
||||
this(Arrays.asList(actions));
|
||||
}
|
||||
|
||||
|
||||
public Actions(Collection<RequestedAction> actions) {
|
||||
this(Collections.<Set<RequestedAction>> emptyList(), actions);
|
||||
this(Collections.<RequestedAction> emptySet(), actions);
|
||||
}
|
||||
|
||||
private Actions(List<Set<RequestedAction>> oldList,
|
||||
Collection<RequestedAction> newActions) {
|
||||
List<Set<RequestedAction>> newList = new ArrayList<Set<RequestedAction>>();
|
||||
newList.addAll(oldList);
|
||||
|
||||
Set<RequestedAction> newActionSet = new HashSet<RequestedAction>(
|
||||
newActions);
|
||||
if (!newActionSet.isEmpty()) {
|
||||
newList.add(Collections.unmodifiableSet(newActionSet));
|
||||
|
||||
private Actions(Set<RequestedAction> oldList,
|
||||
Collection<RequestedAction> newActions) {
|
||||
|
||||
Set<RequestedAction> newActs = new HashSet<RequestedAction>();
|
||||
|
||||
if( oldList != null ){
|
||||
newActs.addAll(oldList);
|
||||
}
|
||||
this.clauseList = Collections.unmodifiableList(newList);
|
||||
|
||||
if ( newActions != null ) {
|
||||
newActs.addAll( newActions );
|
||||
}
|
||||
|
||||
this.requestedActions = Collections.unmodifiableSet(newActs);
|
||||
}
|
||||
|
||||
|
||||
/** require all RequestedActions on this and the ones in newActions to authorize.*/
|
||||
public Actions and(RequestedAction... newActions){
|
||||
return and(Arrays.asList( newActions));
|
||||
}
|
||||
|
||||
/** require all RequestedActions on this and the ones in newActions to authorize.*/
|
||||
public Actions and(Collection<RequestedAction> newActions){
|
||||
if( newActions == null || newActions.size() == 0)
|
||||
return this;
|
||||
else
|
||||
return new Actions( this.requestedActions, newActions);
|
||||
}
|
||||
|
||||
/** require all RequestedActions on this and the ones in newActions to authorize.*/
|
||||
public Actions and(Actions newActions){
|
||||
return new Actions( this.requestedActions, newActions.requestedActions);
|
||||
}
|
||||
|
||||
public Actions or(RequestedAction... newActions) {
|
||||
return or(Arrays.asList(newActions));
|
||||
}
|
||||
|
||||
public Actions or(Collection<RequestedAction> newActions) {
|
||||
return new Actions(this.clauseList, newActions);
|
||||
/**
|
||||
* OR together this.requestedActions and newActions.
|
||||
*/
|
||||
public Actions or(Collection<RequestedAction> newActions) {
|
||||
RequestedAction acts;
|
||||
|
||||
if( newActions == null || newActions.size() == 0 ){
|
||||
return this;
|
||||
}
|
||||
|
||||
int thisActionCount = this.requestedActions.size();
|
||||
int newActionCount = newActions.size();
|
||||
|
||||
/* This minimizes the number of extra RequestedActions
|
||||
* that get created when there is only one in this
|
||||
* or newActions.*/
|
||||
if( thisActionCount == 1 && newActionCount == 1 ){
|
||||
return new Actions(
|
||||
new AnyRequestedAction(
|
||||
this.requestedActions.iterator().next(),
|
||||
newActions.iterator().next() ));
|
||||
}
|
||||
|
||||
if( thisActionCount == 1 && newActionCount > 1 ){
|
||||
return new Actions(
|
||||
new AnyRequestedAction(
|
||||
this.requestedActions.iterator().next(),
|
||||
new AllRequestedAction( newActions )));
|
||||
}
|
||||
|
||||
if( thisActionCount > 1 && newActionCount == 1){
|
||||
return new Actions( new AnyRequestedAction(
|
||||
new AllRequestedAction( this.requestedActions),
|
||||
newActions.iterator().next()));
|
||||
}
|
||||
|
||||
if( thisActionCount > 1 && newActionCount > 1 ){
|
||||
return new Actions(
|
||||
new AnyRequestedAction(
|
||||
new AllRequestedAction( this.requestedActions ),
|
||||
new AllRequestedAction( newActions )));
|
||||
}
|
||||
//should never be reached.
|
||||
log.error("Could not properly create disjunction");
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
for (Set<RequestedAction> clause : clauseList) {
|
||||
if (!clause.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return this.requestedActions.isEmpty();
|
||||
}
|
||||
|
||||
/** No clauses means everything is authorized */
|
||||
|
||||
/**
|
||||
* Are the RequestedAction objects for this Actions authorized
|
||||
* with the ids and policy?
|
||||
*/
|
||||
public boolean isAuthorized(PolicyIface policy, IdentifierBundle ids) {
|
||||
if (clauseList.isEmpty()) {
|
||||
/* No clauses means everything is authorized */
|
||||
if (requestedActions.isEmpty()) {
|
||||
log.debug("Empty Actions is authorized");
|
||||
return true;
|
||||
}
|
||||
return isAuthorizedForClauseList(policy, ids);
|
||||
}
|
||||
|
||||
/** Any entire clause is good enough. */
|
||||
private boolean isAuthorizedForClauseList(PolicyIface policy,
|
||||
IdentifierBundle ids) {
|
||||
for (Set<RequestedAction> clause : clauseList) {
|
||||
if (isAuthorizedForClause(policy, ids, clause)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Are all the RequestedAction object authorized? */
|
||||
List<PolicyDecision> decisions = new ArrayList<PolicyDecision>();
|
||||
for (RequestedAction action : requestedActions) {
|
||||
PolicyDecision decision = policy.isAuthorized(ids, action);
|
||||
log.debug("decision for '" + action.getClass().getSimpleName() + "' was: "
|
||||
+ decision);
|
||||
decisions.add( decision );
|
||||
}
|
||||
return false;
|
||||
return areAllAuthorized( decisions );
|
||||
}
|
||||
|
||||
/** All actions in a clause must be authorized. */
|
||||
private static boolean isAuthorizedForClause(PolicyIface policy,
|
||||
IdentifierBundle ids, Set<RequestedAction> clause) {
|
||||
for (RequestedAction action : clause) {
|
||||
if (!isAuthorizedForAction(policy, ids, action)) {
|
||||
log.debug("not authorized");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Is this action authorized? */
|
||||
private static boolean isAuthorizedForAction(PolicyIface policy,
|
||||
IdentifierBundle ids, RequestedAction action) {
|
||||
PolicyDecision decision = policy.isAuthorized(ids, action);
|
||||
log.debug("decision for '" + action.getClass().getSimpleName() + "' was: "
|
||||
+ decision);
|
||||
return (decision != null)
|
||||
&& (decision.getAuthorized() == Authorization.AUTHORIZED);
|
||||
private boolean areAllAuthorized( List<PolicyDecision> decisions ){
|
||||
for( PolicyDecision dec : decisions){
|
||||
if( dec == null || dec.getAuthorized() != Authorization.AUTHORIZED ){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// /** All actions in a clause must be authorized. */
|
||||
// private static boolean isAuthorizedForClause(PolicyIface policy,
|
||||
// IdentifierBundle ids, Set<RequestedAction> clause) {
|
||||
// for (RequestedAction action : clause) {
|
||||
// if (!isAuthorizedForAction(policy, ids, action)) {
|
||||
// log.debug("not authorized");
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// /** Is this action authorized? */
|
||||
// private static boolean isAuthorizedForAction(PolicyIface policy,
|
||||
// IdentifierBundle ids, RequestedAction action) {
|
||||
// PolicyDecision decision = policy.isAuthorized(ids, action);
|
||||
// log.debug("decision for '" + action.getClass().getSimpleName() + "' was: "
|
||||
// + decision);
|
||||
// return (decision != null)
|
||||
// && (decision.getAuthorized() == Authorization.AUTHORIZED);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer("Actions[");
|
||||
for (Iterator<Set<RequestedAction>> cit = clauseList.iterator(); cit.hasNext();) {
|
||||
Set<RequestedAction> clause = cit.next();
|
||||
sb.append("(");
|
||||
for (Iterator<RequestedAction> it = clause.iterator(); it.hasNext();) {
|
||||
RequestedAction action = it.next();
|
||||
sb.append(action.getClass().getSimpleName());
|
||||
if (it.hasNext()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
if (cit.hasNext()) {
|
||||
sb.append(" or ");
|
||||
Iterator<RequestedAction> it = this.requestedActions.iterator();
|
||||
while( it.hasNext() ){
|
||||
RequestedAction act = it.next();
|
||||
sb.append( act.toString() );
|
||||
if (it.hasNext()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append("]");
|
||||
|
@ -144,10 +238,46 @@ public class Actions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Nobody knows about this action class, so only the root user should be
|
||||
* authorized for it.
|
||||
* AND for Actions.
|
||||
* ANDing with an Action with multiple disjoint clauses is not supported.
|
||||
*
|
||||
* To do the AND, we take each ORed clause, and add all of the RequestedActions
|
||||
* so now in each of the alternative clauses, all of the singleClauseToAnd
|
||||
* RequestedActions are required.
|
||||
*
|
||||
* @throws Exception when multiple disjoint clauses are present on both Actions.
|
||||
*/
|
||||
private static class UnauthorizedAction extends RequestedAction {
|
||||
// no members
|
||||
}
|
||||
//private void andWithAction( Actions otherAct ) throws Exception{
|
||||
// Set<RequestedAction> singleClauseToAnd;
|
||||
// List<Set<RequestedAction>> clauses;
|
||||
//
|
||||
// if( otherAct.singleAndClause() ){
|
||||
// clauses = this.requestedActions;
|
||||
// singleClauseToAnd = otherAct.requestedActions.get(0);
|
||||
// }else if( this.singleAndClause() ){
|
||||
// clauses = new ArrayList<Set<RequestedAction>>( otherAct.requestedActions );
|
||||
// singleClauseToAnd = this.requestedActions.get(0);
|
||||
// }else{
|
||||
// //both have multiple ORed clauses, give up
|
||||
// throw new Exception("ANDing with an Action with multiple disjoint clauses is not supported.");
|
||||
// }
|
||||
//
|
||||
// //
|
||||
// for( Set<RequestedAction> clause : clauses){
|
||||
// clause.addAll( singleClauseToAnd );
|
||||
// }
|
||||
// this.requestedActions = clauses;
|
||||
//}
|
||||
|
||||
// private boolean singleAndClause(){
|
||||
// return requestedActions.size() == 1;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Nobody knows about this action class, so only the root user should be
|
||||
// * authorized for it.
|
||||
// */
|
||||
// private static class UnauthorizedAction extends RequestedAction {
|
||||
// // no members
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.requestedAction;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
|
||||
/**
|
||||
* This action should be authorized if all of its subActions are authorized.
|
||||
* @author bdc34
|
||||
*/
|
||||
public class AllRequestedAction extends RequestedAction{
|
||||
private final Collection<RequestedAction> subActions ;
|
||||
|
||||
public AllRequestedAction(RequestedAction... actions ){
|
||||
this( Arrays.asList( actions ));
|
||||
}
|
||||
public AllRequestedAction(Collection <RequestedAction> subActions){
|
||||
this.subActions = Collections.unmodifiableCollection( subActions );
|
||||
}
|
||||
|
||||
public Collection<RequestedAction> getRequestedActions(){
|
||||
return subActions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.requestedAction;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
|
||||
public class AnyRequestedAction extends RequestedAction {
|
||||
private final Collection<RequestedAction> subActions ;
|
||||
|
||||
public AnyRequestedAction(RequestedAction... acts){
|
||||
this( Arrays.asList( acts) );
|
||||
}
|
||||
|
||||
public AnyRequestedAction(Collection<RequestedAction> subActions){
|
||||
this.subActions = Collections.unmodifiableCollection( subActions );
|
||||
}
|
||||
|
||||
public Collection<RequestedAction> getRequestedActions(){
|
||||
return subActions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.requestedAction;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
|
||||
/**
|
||||
* Action that should always be authorized. Mainly for testing.
|
||||
* @author bdc34
|
||||
*/
|
||||
public class AuthorizedAction extends RequestedAction{
|
||||
|
||||
}
|
|
@ -8,31 +8,31 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAct
|
|||
* A RequestedAction that can be recognized by a SimplePermission.
|
||||
*/
|
||||
public class SimpleRequestedAction extends RequestedAction {
|
||||
private final String localName;
|
||||
private final String uri;
|
||||
|
||||
public SimpleRequestedAction(String localName) {
|
||||
if (localName == null) {
|
||||
throw new NullPointerException("localName may not be null.");
|
||||
public SimpleRequestedAction(String uri) {
|
||||
if (uri == null) {
|
||||
throw new NullPointerException("uri may not be null.");
|
||||
}
|
||||
|
||||
this.localName = localName;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getURI() {
|
||||
return "java:" + this.getClass().getName() + "#" + localName;
|
||||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (localName == null) ? 0 : localName.hashCode();
|
||||
return uri.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof SimpleRequestedAction) {
|
||||
SimpleRequestedAction that = (SimpleRequestedAction) o;
|
||||
return equivalent(this.localName, that.localName);
|
||||
return equivalent(this.uri, that.uri);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class SimpleRequestedAction extends RequestedAction {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleRequestedAction['" + localName + "']";
|
||||
return "SimpleRequestedAction['" + uri + "']";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.requestedAction;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
|
||||
/**
|
||||
* Action that is always unauthorized. Mainly for testing.
|
||||
* @author bdc34
|
||||
*/
|
||||
public class UnauthorizedAction extends RequestedAction{
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
|
||||
/**
|
||||
* Interface to objects that provide a list of Actions that are
|
||||
* required for the object to be used.
|
||||
*
|
||||
* This is intended to provide a way to setup DataGetter
|
||||
* objects to be used with the FreemarkerHttpServlet.requiredActions()
|
||||
* method.
|
||||
*
|
||||
* @author bdc34
|
||||
*/
|
||||
public interface RequiresActions {
|
||||
|
||||
/**
|
||||
* Returns Actions that are required to be authorized for
|
||||
* the object to be used.
|
||||
*
|
||||
* The code that is calling this method
|
||||
* could use methods from PolicyHelper to check if the
|
||||
* request has authorization to do these Actions. The code
|
||||
* calling this method would then have the ability to
|
||||
* deny the action if it is not authorized.
|
||||
*
|
||||
* @param vreq
|
||||
* @return Should not be null. Return Actions.AUTHORIZED
|
||||
* if no authorization is required to do use the object.
|
||||
*/
|
||||
public Actions requiredActions(VitroRequest vreq) ;
|
||||
|
||||
}
|
|
@ -13,7 +13,7 @@ import com.hp.hpl.jena.rdf.model.Resource;
|
|||
import com.hp.hpl.jena.rdf.model.ResourceFactory;
|
||||
|
||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSets;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
|
||||
public class BaseResourceBean implements ResourceBean {
|
||||
|
@ -80,13 +80,13 @@ public class BaseResourceBean implements ResourceBean {
|
|||
}
|
||||
|
||||
Set<String> roles = u.getPermissionSetUris();
|
||||
if (roles.contains(PermissionSetsLoader.URI_DBA)) {
|
||||
if (roles.contains(PermissionSets.URI_DBA)) {
|
||||
return DB_ADMIN;
|
||||
} else if (roles.contains(PermissionSetsLoader.URI_CURATOR)) {
|
||||
} else if (roles.contains(PermissionSets.URI_CURATOR)) {
|
||||
return CURATOR;
|
||||
} else if (roles.contains(PermissionSetsLoader.URI_EDITOR)) {
|
||||
} else if (roles.contains(PermissionSets.URI_EDITOR)) {
|
||||
return EDITOR;
|
||||
} else if (roles.contains(PermissionSetsLoader.URI_SELF_EDITOR)) {
|
||||
} else if (roles.contains(PermissionSets.URI_SELF_EDITOR)) {
|
||||
return SELF;
|
||||
} else {
|
||||
// Logged in but with no recognized role? Make them SELF
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
|
@ -21,6 +22,10 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.github.jsonldjava.core.JSONLD;
|
||||
import com.github.jsonldjava.core.JSONLDProcessingError;
|
||||
import com.github.jsonldjava.impl.JenaRDFParser;
|
||||
import com.github.jsonldjava.utils.JSONUtils;
|
||||
import com.hp.hpl.jena.query.Query;
|
||||
import com.hp.hpl.jena.query.QuerySolution;
|
||||
import com.hp.hpl.jena.query.ResultSet;
|
||||
|
@ -37,6 +42,8 @@ import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
|||
import edu.cornell.mannlib.vitro.webapp.beans.Ontology;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService.ModelSerializationFormat;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService.ResultFormat;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
|
||||
|
@ -44,42 +51,40 @@ import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
|
|||
|
||||
/**
|
||||
* Services a sparql query. This will return a simple error message and a 501 if
|
||||
* there is no jena Model.
|
||||
* there is no Model.
|
||||
*
|
||||
* @author bdc34
|
||||
*
|
||||
*/
|
||||
public class SparqlQueryServlet extends BaseEditController {
|
||||
private static final Log log = LogFactory.getLog(SparqlQueryServlet.class.getName());
|
||||
|
||||
protected static HashMap<String,ResultSetFormat>formatSymbols = new HashMap<String,ResultSetFormat>();
|
||||
static{
|
||||
formatSymbols.put( ResultSetFormat.syntaxXML.getSymbol(), ResultSetFormat.syntaxXML);
|
||||
formatSymbols.put( ResultSetFormat.syntaxRDF_XML.getSymbol(), ResultSetFormat.syntaxRDF_XML);
|
||||
formatSymbols.put( ResultSetFormat.syntaxRDF_N3.getSymbol(), ResultSetFormat.syntaxRDF_N3);
|
||||
formatSymbols.put( ResultSetFormat.syntaxText.getSymbol() , ResultSetFormat.syntaxText);
|
||||
formatSymbols.put( ResultSetFormat.syntaxJSON.getSymbol() , ResultSetFormat.syntaxJSON);
|
||||
formatSymbols.put( "vitro:csv", null);
|
||||
}
|
||||
|
||||
protected static HashMap<String,String> rdfFormatSymbols = new HashMap<String,String>();
|
||||
static {
|
||||
rdfFormatSymbols.put( "RDF/XML", "application/rdf+xml" );
|
||||
rdfFormatSymbols.put( "RDF/XML-ABBREV", "application/rdf+xml" );
|
||||
rdfFormatSymbols.put( "N3", "text/n3" );
|
||||
rdfFormatSymbols.put( "N-TRIPLE", "text/plain" );
|
||||
rdfFormatSymbols.put( "TTL", "application/x-turtle" );
|
||||
}
|
||||
|
||||
protected static HashMap<String, String>mimeTypes = new HashMap<String,String>();
|
||||
static{
|
||||
mimeTypes.put( ResultSetFormat.syntaxXML.getSymbol() , "text/xml" );
|
||||
mimeTypes.put( ResultSetFormat.syntaxRDF_XML.getSymbol(), "application/rdf+xml" );
|
||||
mimeTypes.put( ResultSetFormat.syntaxRDF_N3.getSymbol(), "text/plain" );
|
||||
mimeTypes.put( ResultSetFormat.syntaxText.getSymbol() , "text/plain");
|
||||
mimeTypes.put( ResultSetFormat.syntaxJSON.getSymbol(), "application/javascript" );
|
||||
mimeTypes.put( "vitro:csv", "text/csv");
|
||||
}
|
||||
private final static boolean CONVERT = true;
|
||||
|
||||
/**
|
||||
* format configurations for SELECT queries.
|
||||
*/
|
||||
protected static HashMap<String,RSFormatConfig> rsFormats = new HashMap<String,RSFormatConfig>();
|
||||
|
||||
private static RSFormatConfig[] rsfs = {
|
||||
new RSFormatConfig( "RS_XML", !CONVERT, ResultFormat.XML, null, "text/xml"),
|
||||
new RSFormatConfig( "RS_TEXT", !CONVERT, ResultFormat.TEXT, null, "text/plain"),
|
||||
new RSFormatConfig( "vitro:csv", !CONVERT, ResultFormat.CSV, null, "text/csv"),
|
||||
new RSFormatConfig( "RS_JSON", !CONVERT, ResultFormat.JSON, null, "application/javascript") };
|
||||
|
||||
/**
|
||||
* format configurations for CONSTRUCT/DESCRIBE queries.
|
||||
*/
|
||||
protected static HashMap<String,ModelFormatConfig> modelFormats =
|
||||
new HashMap<String,ModelFormatConfig>();
|
||||
|
||||
private static ModelFormatConfig[] fmts = {
|
||||
new ModelFormatConfig("RDF/XML", !CONVERT, ModelSerializationFormat.RDFXML, null, "application/rdf+xml" ),
|
||||
new ModelFormatConfig("RDF/XML-ABBREV", CONVERT, ModelSerializationFormat.N3, "RDF/XML-ABBREV", "application/rdf+xml" ),
|
||||
new ModelFormatConfig("N3", !CONVERT, ModelSerializationFormat.N3, null, "text/n3" ),
|
||||
new ModelFormatConfig("N-TRIPLE", !CONVERT, ModelSerializationFormat.NTRIPLE, null, "text/plain" ),
|
||||
new ModelFormatConfig("TTL", CONVERT, ModelSerializationFormat.N3, "TTL", "application/x-turtle" ),
|
||||
new ModelFormatConfig("JSON-LD", CONVERT, ModelSerializationFormat.N3, "JSON-LD", "application/javascript" ) };
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
|
@ -119,9 +124,9 @@ public class SparqlQueryServlet extends BaseEditController {
|
|||
|
||||
if( queryParam == null || "".equals(queryParam) ||
|
||||
resultFormatParam == null || "".equals(resultFormatParam) ||
|
||||
!formatSymbols.containsKey(resultFormatParam) ||
|
||||
!rsFormats.containsKey( resultFormatParam ) ||
|
||||
rdfResultFormatParam == null || "".equals(rdfResultFormatParam) ||
|
||||
!rdfFormatSymbols.keySet().contains(rdfResultFormatParam) ) {
|
||||
!modelFormats.containsKey( rdfResultFormatParam ) ) {
|
||||
doHelp(request,response);
|
||||
return;
|
||||
}
|
||||
|
@ -135,68 +140,128 @@ public class SparqlQueryServlet extends BaseEditController {
|
|||
String resultFormatParam,
|
||||
String rdfResultFormatParam,
|
||||
String queryParam,
|
||||
RDFService rdfService ) throws IOException {
|
||||
|
||||
ResultSetFormat rsf = null;
|
||||
RDFService rdfService ) throws IOException {
|
||||
/* BJL23 2008-11-06
|
||||
* modified to support CSV output.
|
||||
* Unfortunately, ARQ doesn't make it easy to
|
||||
* do this by implementing a new ResultSetFormat, because
|
||||
* ResultSetFormatter is hardwired with expected values.
|
||||
* This slightly ugly approach will have to do for now.
|
||||
*/
|
||||
if ( !("vitro:csv").equals(resultFormatParam) ) {
|
||||
rsf = formatSymbols.get(resultFormatParam);
|
||||
}
|
||||
String mimeType = mimeTypes.get(resultFormatParam);
|
||||
* This slightly ugly approach will have to do for now.
|
||||
*/
|
||||
// if ( !("vitro:csv").equals(resultFormatParam) ) {
|
||||
// rsf = selectFormatSymbols.get(resultFormatParam);
|
||||
// }
|
||||
// String mimeType = rdfFormatToMimeType.get(resultFormatParam);
|
||||
|
||||
try{
|
||||
Query query = SparqlQueryUtils.create(queryParam);
|
||||
if( query.isSelectType() ){
|
||||
ResultSet results = null;
|
||||
results = ResultSetFactory.fromJSON(rdfService.sparqlSelectQuery(
|
||||
queryParam, RDFService.ResultFormat.JSON));
|
||||
response.setContentType(mimeType);
|
||||
if (rsf != null) {
|
||||
OutputStream out = response.getOutputStream();
|
||||
ResultSetFormatter.output(out, results, rsf);
|
||||
} else {
|
||||
Writer out = response.getWriter();
|
||||
toCsv(out, results);
|
||||
}
|
||||
} else {
|
||||
Model resultModel = null;
|
||||
if( query.isConstructType() ){
|
||||
resultModel = RDFServiceUtils.parseModel(
|
||||
rdfService.sparqlConstructQuery(
|
||||
queryParam,
|
||||
RDFService.ModelSerializationFormat.N3),
|
||||
RDFService.ModelSerializationFormat.N3);
|
||||
}else if ( query.isDescribeType() ){
|
||||
resultModel = RDFServiceUtils.parseModel(
|
||||
rdfService.sparqlDescribeQuery(
|
||||
queryParam,
|
||||
RDFService.ModelSerializationFormat.N3),
|
||||
RDFService.ModelSerializationFormat.N3);
|
||||
}else if(query.isAskType()){
|
||||
// Irrespective of the ResultFormatParam,
|
||||
// this always prints a boolean to the default OutputStream.
|
||||
String result = (rdfService.sparqlAskQuery(queryParam) == true)
|
||||
? "true"
|
||||
: "false";
|
||||
PrintWriter p = response.getWriter();
|
||||
p.write(result);
|
||||
return;
|
||||
}
|
||||
response.setContentType(rdfFormatSymbols.get(rdfResultFormatParam));
|
||||
OutputStream out = response.getOutputStream();
|
||||
resultModel.write(out, rdfResultFormatParam);
|
||||
doSelectQuery( queryParam, rdfService, resultFormatParam, response);
|
||||
} else if(query.isAskType()){
|
||||
// Irrespective of the ResultFormatParam,
|
||||
// this always prints a boolean to the default OutputStream.
|
||||
String result = (rdfService.sparqlAskQuery(queryParam) == true)
|
||||
? "true"
|
||||
: "false";
|
||||
PrintWriter p = response.getWriter();
|
||||
p.write(result);
|
||||
return;
|
||||
} else {
|
||||
doModelResultQuery( query, rdfService, rdfResultFormatParam, response);
|
||||
}
|
||||
} catch (RDFServiceException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and send the result to out. Attempt to
|
||||
* send the RDFService the same format as the rdfResultFormatParam
|
||||
* so that the results from the RDFService can be directly piped to the client.
|
||||
* @param rdfService
|
||||
* @throws IOException
|
||||
* @throws RDFServiceException
|
||||
*/
|
||||
private void doSelectQuery( String queryParam,
|
||||
RDFService rdfService, String resultFormatParam,
|
||||
HttpServletResponse response) throws IOException, RDFServiceException{
|
||||
RSFormatConfig config = rsFormats.get( resultFormatParam );
|
||||
|
||||
if( ! config.converstionFromWireFormat ){
|
||||
response.setContentType( config.responseMimeType );
|
||||
InputStream results = rdfService.sparqlSelectQuery(queryParam, config.wireFormat );
|
||||
pipe( results, response.getOutputStream() );
|
||||
}else{
|
||||
//always use JSON when conversion is needed.
|
||||
InputStream results = rdfService.sparqlSelectQuery(queryParam, ResultFormat.JSON );
|
||||
|
||||
response.setContentType( config.responseMimeType );
|
||||
|
||||
ResultSet rs = ResultSetFactory.fromJSON( results );
|
||||
OutputStream out = response.getOutputStream();
|
||||
ResultSetFormatter.output(out, rs, config.jenaResponseFormat);
|
||||
|
||||
// } else {
|
||||
// Writer out = response.getWriter();
|
||||
// toCsv(out, results);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and send the result to out. Attempt to
|
||||
* send the RDFService the same format as the rdfResultFormatParam
|
||||
* so that the results from the RDFService can be directly piped to the client.
|
||||
* @param rdfService
|
||||
* @throws IOException
|
||||
* @throws RDFServiceException
|
||||
* @throws
|
||||
*/
|
||||
private void doModelResultQuery( Query query,
|
||||
RDFService rdfService, String rdfResultFormatParam,
|
||||
HttpServletResponse response) throws IOException, RDFServiceException{
|
||||
|
||||
//config drives what formats and conversions to use
|
||||
ModelFormatConfig config = modelFormats.get( rdfResultFormatParam );
|
||||
|
||||
InputStream rawResult = null;
|
||||
if( query.isConstructType() ){
|
||||
rawResult= rdfService.sparqlConstructQuery( query.toString(), config.wireFormat );
|
||||
}else if ( query.isDescribeType() ){
|
||||
rawResult = rdfService.sparqlDescribeQuery( query.toString(), config.wireFormat );
|
||||
}
|
||||
|
||||
response.setContentType( config.responseMimeType );
|
||||
|
||||
if( config.converstionFromWireFormat ){
|
||||
Model resultModel = RDFServiceUtils.parseModel( rawResult, config.wireFormat );
|
||||
if( "JSON-LD".equals( config.jenaResponseFormat )){
|
||||
//since jena 2.6.4 doesn't support JSON-LD we do it
|
||||
try {
|
||||
JenaRDFParser parser = new JenaRDFParser();
|
||||
Object json = JSONLD.fromRDF(resultModel, parser);
|
||||
JSONUtils.write(response.getWriter(), json);
|
||||
} catch (JSONLDProcessingError e) {
|
||||
throw new RDFServiceException("Could not convert from Jena model to JSON-LD", e);
|
||||
}
|
||||
}else{
|
||||
OutputStream out = response.getOutputStream();
|
||||
resultModel.write(out, config.jenaResponseFormat );
|
||||
}
|
||||
}else{
|
||||
OutputStream out = response.getOutputStream();
|
||||
pipe( rawResult, out );
|
||||
}
|
||||
}
|
||||
|
||||
private void pipe( InputStream in, OutputStream out) throws IOException{
|
||||
int size;
|
||||
byte[] buffer = new byte[4096];
|
||||
while( (size = in.read(buffer)) > -1 ) {
|
||||
out.write(buffer,0,size);
|
||||
}
|
||||
}
|
||||
|
||||
private void doNoModelInContext(HttpServletResponse res){
|
||||
try {
|
||||
res.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
|
||||
|
@ -290,8 +355,6 @@ public class SparqlQueryServlet extends BaseEditController {
|
|||
|
||||
req.setAttribute("prefixList", prefixList);
|
||||
|
||||
// nac26: 2009-09-25 - this was causing problems in safari on localhost installations because the href did not include the context. The edit.css is not being used here anyway (or anywhere else for that matter)
|
||||
// req.setAttribute("css", "<link rel=\"stylesheet\" type=\"text/css\" href=\""+portal.getThemeDir()+"css/edit.css\"/>");
|
||||
req.setAttribute("title","SPARQL Query");
|
||||
req.setAttribute("bodyJsp", "/admin/sparqlquery/sparqlForm.jsp");
|
||||
|
||||
|
@ -299,4 +362,55 @@ public class SparqlQueryServlet extends BaseEditController {
|
|||
rd.forward(req,res);
|
||||
}
|
||||
|
||||
|
||||
public static class ModelFormatConfig{
|
||||
public String valueFromForm;
|
||||
public boolean converstionFromWireFormat;
|
||||
public RDFService.ModelSerializationFormat wireFormat;
|
||||
public String jenaResponseFormat;
|
||||
public String responseMimeType;
|
||||
|
||||
public ModelFormatConfig( String valueFromForm,
|
||||
boolean converstionFromWireFormat,
|
||||
RDFService.ModelSerializationFormat wireFormat,
|
||||
String jenaResponseFormat,
|
||||
String responseMimeType){
|
||||
this.valueFromForm = valueFromForm;
|
||||
this.converstionFromWireFormat = converstionFromWireFormat;
|
||||
this.wireFormat = wireFormat;
|
||||
this.jenaResponseFormat = jenaResponseFormat;
|
||||
this.responseMimeType = responseMimeType;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RSFormatConfig{
|
||||
public String valueFromForm;
|
||||
public boolean converstionFromWireFormat;
|
||||
public ResultFormat wireFormat;
|
||||
public ResultSetFormat jenaResponseFormat;
|
||||
public String responseMimeType;
|
||||
|
||||
public RSFormatConfig( String valueFromForm,
|
||||
boolean converstionFromWireFormat,
|
||||
ResultFormat wireFormat,
|
||||
ResultSetFormat jenaResponseFormat,
|
||||
String responseMimeType ){
|
||||
this.valueFromForm = valueFromForm;
|
||||
this.converstionFromWireFormat = converstionFromWireFormat;
|
||||
this.wireFormat = wireFormat;
|
||||
this.jenaResponseFormat = jenaResponseFormat;
|
||||
this.responseMimeType = responseMimeType;
|
||||
}
|
||||
}
|
||||
|
||||
static{
|
||||
/* move the lists of configs into maps for easy lookup */
|
||||
for( RSFormatConfig rsfc : rsfs ){
|
||||
rsFormats.put( rsfc.valueFromForm, rsfc );
|
||||
}
|
||||
for( ModelFormatConfig mfc : fmts ){
|
||||
modelFormats.put( mfc.valueFromForm, mfc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ public class VitroHttpServlet extends HttpServlet {
|
|||
public final static String HTML_MIMETYPE = "text/html";
|
||||
|
||||
public final static String RDFXML_MIMETYPE = "application/rdf+xml";
|
||||
public final static String JSON_MIMETYPE = "application/json";
|
||||
public final static String N3_MIMETYPE = "text/n3"; // unofficial and unregistered
|
||||
public final static String TTL_MIMETYPE = "text/turtle"; // unofficial and unregistered
|
||||
|
||||
|
|
|
@ -95,6 +95,14 @@ public class VitroRequest extends HttpServletRequestWrapper {
|
|||
setAttribute("dataset", dataset);
|
||||
}
|
||||
|
||||
public Dataset getUnfilteredDataset() {
|
||||
return (Dataset) getAttribute("unfilteredDataset");
|
||||
}
|
||||
|
||||
public void setUnfilteredDataset(Dataset dataset) {
|
||||
setAttribute("unfilteredDataset", dataset);
|
||||
}
|
||||
|
||||
//Method that retrieves write model, returns special model in case of write model
|
||||
public OntModel getWriteModel() {
|
||||
//if special write model doesn't exist use get ont model
|
||||
|
@ -171,6 +179,18 @@ public class VitroRequest extends HttpServletRequestWrapper {
|
|||
return getWebappDaoFactory().getApplicationDao().getApplicationBean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the the ip of the client.
|
||||
* This will be X-forwarded-for header or, if that header is not
|
||||
* set, getRemoteAddr(). This still may not be the client's address
|
||||
* as they may be using a proxy.
|
||||
*
|
||||
*/
|
||||
public String getClientAddr(){
|
||||
String xff = getHeader("x-forwarded-for");
|
||||
return ( xff == null || xff.trim().isEmpty() ) ? getRemoteAddr() : xff;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
|
|
|
@ -11,7 +11,7 @@ import javax.servlet.http.HttpSession;
|
|||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSets;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
|
@ -200,7 +200,7 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
|
|||
u.setLoginCount(0);
|
||||
u.setStatus(Status.ACTIVE);
|
||||
u.setPermissionSetUris(Collections
|
||||
.singleton(PermissionSetsLoader.URI_SELF_EDITOR));
|
||||
.singleton(PermissionSets.URI_SELF_EDITOR));
|
||||
|
||||
userAccountsDao.insertUserAccount(u);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.apache.commons.logging.LogFactory;
|
|||
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
|
||||
|
@ -73,8 +73,8 @@ public abstract class VitroAjaxController extends HttpServlet {
|
|||
* Process data through a Freemarker template and output the result.
|
||||
*/
|
||||
protected void writeTemplate(String templateName, Map<String, Object> map,
|
||||
VitroRequest vreq, HttpServletResponse response) {
|
||||
Configuration config = FreemarkerConfigurationLoader.getConfig(vreq);
|
||||
HttpServletRequest req, HttpServletResponse response) {
|
||||
Configuration config = FreemarkerConfiguration.getConfig(req);
|
||||
try {
|
||||
Template template = config.getTemplate(templateName);
|
||||
PrintWriter out = response.getWriter();
|
||||
|
|
|
@ -65,13 +65,10 @@ public class ClassgroupRetryController extends BaseEditController {
|
|||
} catch (NullPointerException e) {
|
||||
log.error("Need to implement 'record not found' error message.");
|
||||
}
|
||||
if (vclassGroupForEditing == null) {
|
||||
try {
|
||||
String uriToFind = new String(request.getParameter("uri").getBytes("ISO-8859-1"),"UTF-8");
|
||||
vclassGroupForEditing = (VClassGroup)cgDao.getGroupByURI(uriToFind);
|
||||
} catch (java.io.UnsupportedEncodingException uee) {
|
||||
// forget it
|
||||
}
|
||||
if (vclassGroupForEditing == null) {
|
||||
//UTF-8 expected due to URIEncoding on Connector in server.xml
|
||||
String uriToFind = new String(request.getParameter("uri"));
|
||||
vclassGroupForEditing = (VClassGroup)cgDao.getGroupByURI(uriToFind);
|
||||
}
|
||||
} else {
|
||||
vclassGroupForEditing = new VClassGroup();
|
||||
|
|
|
@ -65,12 +65,9 @@ public class PropertyGroupRetryController extends BaseEditController {
|
|||
log.error("Need to implement 'record not found' error message.");
|
||||
}
|
||||
if (propertyGroupForEditing == null) {
|
||||
try {
|
||||
String uriToFind = new String(request.getParameter("uri").getBytes("ISO-8859-1"),"UTF-8");
|
||||
propertyGroupForEditing = (PropertyGroup)pgDao.getGroupByURI(uriToFind);
|
||||
} catch (java.io.UnsupportedEncodingException uee) {
|
||||
// forget it
|
||||
}
|
||||
// UTF-8 expected due to URIEncoding on Connector element in server.xml
|
||||
String uriToFind = new String(request.getParameter("uri"));
|
||||
propertyGroupForEditing = (PropertyGroup)pgDao.getGroupByURI(uriToFind);
|
||||
}
|
||||
} else {
|
||||
propertyGroupForEditing = new PropertyGroup();
|
||||
|
|
|
@ -61,6 +61,8 @@ public class FreemarkerComponentGenerator extends FreemarkerHttpServlet {
|
|||
return get(templateName, root, request);
|
||||
}
|
||||
|
||||
// JB Because this is pretending to be a servlet, but the init method has not been called, providing the context.
|
||||
// Do that in the constructor, and we should be fine. VIVO-251
|
||||
// RY We need the servlet context in getConfig(). For some reason using the method inherited from
|
||||
// GenericServlet bombs.
|
||||
@Override
|
||||
|
|
|
@ -1,379 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants;
|
||||
import edu.cornell.mannlib.vitro.webapp.i18n.freemarker.I18nMethodModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.directives.IndividualShortViewDirective;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.directives.UrlDirective;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.directives.WidgetDirective;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualLocalNameMethod;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualPlaceholderImageUrlMethod;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualProfileUrlMethod;
|
||||
import freemarker.cache.ClassTemplateLoader;
|
||||
import freemarker.cache.FileTemplateLoader;
|
||||
import freemarker.cache.MultiTemplateLoader;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.ext.beans.BeansWrapper;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapper;
|
||||
import freemarker.template.ObjectWrapper;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModelException;
|
||||
import freemarker.template.utility.DeepUnwrap;
|
||||
|
||||
public class FreemarkerConfiguration extends Configuration {
|
||||
|
||||
private static final Log log = LogFactory.getLog(FreemarkerConfiguration.class);
|
||||
|
||||
private static final String PROPERTY_DEVELOPER_DEFEAT_CACHE = "developer.defeatFreemarkerCache";
|
||||
private static final String PROPERTY_DEVELOPER_INSERT_DELIMITERS = "developer.insertFreemarkerDelimiters";
|
||||
|
||||
private final String themeDir;
|
||||
private final ServletContext context;
|
||||
private final ApplicationBean appBean;
|
||||
private final ConfigurationProperties props;
|
||||
|
||||
FreemarkerConfiguration(String themeDir, ApplicationBean appBean, ServletContext context) {
|
||||
|
||||
this.themeDir = themeDir;
|
||||
this.context = context;
|
||||
this.appBean = appBean;
|
||||
this.props = ConfigurationProperties.getBean(context);
|
||||
|
||||
String flag = props.getProperty(PROPERTY_DEVELOPER_DEFEAT_CACHE, "false");
|
||||
if (Boolean.valueOf(flag.trim())) {
|
||||
log.debug("Disabling Freemarker template caching in development build.");
|
||||
setTemplateUpdateDelay(0); // no template caching in development
|
||||
} else {
|
||||
int delay = 60;
|
||||
log.debug("Setting Freemarker template cache update delay to " + delay + ".");
|
||||
setTemplateUpdateDelay(delay); // in seconds; Freemarker default is 5
|
||||
}
|
||||
|
||||
// Specify how templates will see the data model.
|
||||
// The Freemarker default wrapper exposes set methods and get methods that take
|
||||
// arguments. We block exposure to these methods by default.
|
||||
BeansWrapper wrapper = new DefaultObjectWrapper();
|
||||
wrapper.setExposureLevel(BeansWrapper.EXPOSE_PROPERTIES_ONLY);
|
||||
setObjectWrapper(wrapper);
|
||||
|
||||
// Set some formatting defaults. These can be overridden at the template
|
||||
// or environment (template-processing) level, or for an individual
|
||||
// token by using built-ins.
|
||||
setLocale(java.util.Locale.US);
|
||||
|
||||
String dateFormat = "M/d/yyyy";
|
||||
setDateFormat(dateFormat);
|
||||
String timeFormat = "h:mm a";
|
||||
setTimeFormat(timeFormat);
|
||||
setDateTimeFormat(dateFormat + " " + timeFormat);
|
||||
|
||||
//config.setNumberFormat("#,##0.##");
|
||||
|
||||
try {
|
||||
setSetting("url_escaping_charset", "ISO-8859-1");
|
||||
} catch (TemplateException e) {
|
||||
log.error("Error setting value for url_escaping_charset.");
|
||||
}
|
||||
|
||||
setTemplateLoader(createTemplateLoader());
|
||||
|
||||
setSharedVariables();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* These are values that are accessible to all
|
||||
* templates loaded by the Configuration's TemplateLoader. They
|
||||
* should be application- rather than request-specific.
|
||||
*/
|
||||
private void setSharedVariables() {
|
||||
|
||||
Map<String, Object> sharedVariables = new HashMap<String, Object>();
|
||||
|
||||
sharedVariables.put("siteName", appBean.getApplicationName());
|
||||
sharedVariables.put("version", getRevisionInfo());
|
||||
sharedVariables.put("urls", getSiteUrls());
|
||||
sharedVariables.put("themeDir", themeDir);
|
||||
sharedVariables.put("currentTheme", themeDir.substring(themeDir.lastIndexOf('/')+1));
|
||||
|
||||
sharedVariables.putAll(getDirectives());
|
||||
sharedVariables.putAll(getMethods());
|
||||
sharedVariables.put("siteTagline", appBean.getShortHand());
|
||||
|
||||
//Put in edit configuration constants - useful for freemarker templates/editing
|
||||
sharedVariables.put("editConfigurationConstants", EditConfigurationConstants.exportConstants());
|
||||
|
||||
for ( Map.Entry<String, Object> variable : sharedVariables.entrySet() ) {
|
||||
try {
|
||||
setSharedVariable(variable.getKey(), variable.getValue());
|
||||
} catch (TemplateModelException e) {
|
||||
log.error("Could not set shared variable '" + variable.getKey() + "' in Freemarker configuration");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<String, Object> getRevisionInfo() {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("label", RevisionInfoBean.getBean(context)
|
||||
.getReleaseLabel());
|
||||
map.put("moreInfoUrl", UrlBuilder.getUrl("/revisionInfo"));
|
||||
return map;
|
||||
}
|
||||
|
||||
private final Map<String, String> getSiteUrls() {
|
||||
Map<String, String> urls = new HashMap<String, String>();
|
||||
|
||||
// Templates use this to construct urls.
|
||||
urls.put("base", context.getContextPath());
|
||||
|
||||
urls.put("home", UrlBuilder.getHomeUrl());
|
||||
urls.put("about", UrlBuilder.getUrl(Route.ABOUT));
|
||||
urls.put("search", UrlBuilder.getUrl(Route.SEARCH));
|
||||
urls.put("termsOfUse", UrlBuilder.getUrl(Route.TERMS_OF_USE));
|
||||
urls.put("login", UrlBuilder.getLoginUrl());
|
||||
urls.put("logout", UrlBuilder.getLogoutUrl());
|
||||
urls.put("siteAdmin", UrlBuilder.getUrl(Route.SITE_ADMIN));
|
||||
urls.put("themeImages", UrlBuilder.getUrl(themeDir + "/images"));
|
||||
urls.put("images", UrlBuilder.getUrl("/images"));
|
||||
urls.put("theme", UrlBuilder.getUrl(themeDir));
|
||||
urls.put("index", UrlBuilder.getUrl("/browse"));
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
private static Map<String, Object> getDirectives() {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("dump", new freemarker.ext.dump.DumpDirective());
|
||||
map.put("dumpAll", new freemarker.ext.dump.DumpAllDirective());
|
||||
map.put("help", new freemarker.ext.dump.HelpDirective());
|
||||
map.put("shortView", new IndividualShortViewDirective());
|
||||
map.put("url", new UrlDirective());
|
||||
map.put("widget", new WidgetDirective());
|
||||
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Map<String, Object> getMethods() {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("profileUrl", new IndividualProfileUrlMethod());
|
||||
map.put("localName", new IndividualLocalNameMethod());
|
||||
map.put("placeholderImageUrl", new IndividualPlaceholderImageUrlMethod());
|
||||
map.put("i18n", new I18nMethodModel());
|
||||
return map;
|
||||
}
|
||||
|
||||
// Define template locations. Template loader will look first in the theme-specific
|
||||
// location, then in the vitro location.
|
||||
protected final TemplateLoader createTemplateLoader() {
|
||||
|
||||
List<TemplateLoader> loaders = new ArrayList<TemplateLoader>();
|
||||
MultiTemplateLoader mtl = null;
|
||||
try {
|
||||
// Theme template loader
|
||||
String themeTemplatePath = context.getRealPath(themeDir) + "/templates";
|
||||
File themeTemplateDir = new File(themeTemplatePath);
|
||||
// Handle the case where there's no theme template directory gracefully
|
||||
if (themeTemplateDir.exists()) {
|
||||
FileTemplateLoader themeFtl = new FileTemplateLoader(themeTemplateDir);
|
||||
loaders.add(themeFtl);
|
||||
}
|
||||
|
||||
// Vitro template loader
|
||||
String vitroTemplatePath = context.getRealPath("/templates/freemarker");
|
||||
loaders.add(new FlatteningTemplateLoader(new File(vitroTemplatePath)));
|
||||
|
||||
loaders.add(new ClassTemplateLoader(getClass(), ""));
|
||||
|
||||
TemplateLoader[] loaderArray = loaders.toArray(new TemplateLoader[loaders.size()]);
|
||||
mtl = new MultiTemplateLoader(loaderArray);
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("Error creating template loaders");
|
||||
}
|
||||
|
||||
// Add the ability to add delimiters to the templates, based on
|
||||
// settings.
|
||||
if (Boolean.valueOf(props.getProperty(PROPERTY_DEVELOPER_INSERT_DELIMITERS))) {
|
||||
return new DelimitingTemplateLoader(mtl);
|
||||
} else {
|
||||
return mtl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override getTemplate(), so we can apply DataGetters to all included
|
||||
* templates.
|
||||
*
|
||||
* This won't work for top-level Templates, since the Environment hasn't
|
||||
* been created yet. When TemplateProcessingHelper creates the Environment,
|
||||
* it must call retrieveAndRunDataGetters() for the top-level Template.
|
||||
*/
|
||||
@Override
|
||||
public Template getTemplate(String name, Locale locale, String encoding,
|
||||
boolean parse) throws IOException {
|
||||
Template template = super.getTemplate(name, locale, encoding, parse);
|
||||
|
||||
if (template == null) {
|
||||
log.debug("Template '" + name + "' not found for locale '" + locale + "'.");
|
||||
return template;
|
||||
}
|
||||
|
||||
Environment env = getEnvironment();
|
||||
if (env == null) {
|
||||
log.debug("Not fetching data getters for template '" + template.getName() + "'. No environment.");
|
||||
return template;
|
||||
}
|
||||
|
||||
retrieveAndRunDataGetters(env, template.getName());
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the DataGetters for this template, and apply them to the Freemarker
|
||||
* environment.
|
||||
*/
|
||||
public static void retrieveAndRunDataGetters(Environment env, String templateName) {
|
||||
HttpServletRequest req = (HttpServletRequest) env.getCustomAttribute("request");
|
||||
VitroRequest vreq = new VitroRequest(req);
|
||||
|
||||
if (dataGettersAlreadyApplied(env, templateName)) {
|
||||
log.debug("DataGetters for '" + templateName+"' have already been applied");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<DataGetter> dgList = DataGetterUtils.getDataGettersForTemplate(
|
||||
vreq, vreq.getDisplayModel(), templateName);
|
||||
log.debug("Retrieved " + dgList.size() + " data getters for template '" + templateName + "'");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> dataMap = (Map<String, Object>) DeepUnwrap.permissiveUnwrap(env.getDataModel());
|
||||
for (DataGetter dg : dgList) {
|
||||
applyDataGetter(dg, env, dataMap);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn(e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the DataGetters for this template already been applied to this environment?
|
||||
* If not, record that they are being applied now.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static boolean dataGettersAlreadyApplied(Environment env, String templateName) {
|
||||
Set<String> names;
|
||||
Object o = env.getCustomAttribute("dataGettersApplied");
|
||||
if (o instanceof Set) {
|
||||
names = (Set<String>) o;
|
||||
} else {
|
||||
names = new HashSet<String>();
|
||||
}
|
||||
|
||||
boolean added = names.add(templateName);
|
||||
if (added) {
|
||||
env.setCustomAttribute("dataGettersApplied", names);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data from a DataGetter, and store it in global variables in the
|
||||
* Freemarker environment.
|
||||
*/
|
||||
private static void applyDataGetter(DataGetter dg, Environment env,
|
||||
Map<String, Object> dataMap) throws TemplateModelException {
|
||||
Map<String, Object> moreData = dg.getData(dataMap);
|
||||
ObjectWrapper wrapper = env.getObjectWrapper();
|
||||
if (moreData != null) {
|
||||
for (String key : moreData.keySet()) {
|
||||
Object value = moreData.get(key);
|
||||
env.setGlobalVariable(key, wrapper.wrap(value));
|
||||
log.debug("Stored in environment: '" + key + "' = '" + value + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Request info and overrides
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private ThreadLocal<FreemarkerRequestInfo> reqInfo = new ThreadLocal<>();
|
||||
|
||||
void setRequestInfo(HttpServletRequest req) {
|
||||
reqInfo.set(new FreemarkerRequestInfo(req));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCustomAttribute(String name) {
|
||||
if ("request".equals(name)) {
|
||||
return reqInfo.get().getRequest();
|
||||
} else {
|
||||
return super.getCustomAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCustomAttributeNames() {
|
||||
String[] nameArray = super.getCustomAttributeNames();
|
||||
Set<String> nameSet = new HashSet<String>(Arrays.asList(nameArray));
|
||||
nameSet.add("request");
|
||||
return nameSet.toArray(new String[nameSet.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return reqInfo.get().getLocale();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class FreemarkerRequestInfo {
|
||||
private final HttpServletRequest req;
|
||||
|
||||
public FreemarkerRequestInfo(HttpServletRequest req) {
|
||||
this.req = req;
|
||||
}
|
||||
|
||||
public HttpServletRequest getRequest() {
|
||||
return req;
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return req.getLocale();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||
|
||||
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 edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
|
||||
public class FreemarkerConfigurationLoader {
|
||||
private static final Log log = LogFactory
|
||||
.getLog(FreemarkerConfigurationLoader.class);
|
||||
|
||||
private static final Map<String, FreemarkerConfiguration> themeToConfigMap = new HashMap<String, FreemarkerConfiguration>();
|
||||
|
||||
public static FreemarkerConfiguration getConfig(VitroRequest vreq) {
|
||||
String themeDir = getThemeDir(vreq.getAppBean());
|
||||
FreemarkerConfiguration config = getConfigForTheme(themeDir, vreq.getAppBean(), vreq.getSession().getServletContext());
|
||||
config.setRequestInfo(vreq);
|
||||
return config;
|
||||
}
|
||||
|
||||
private static String getThemeDir(ApplicationBean appBean) {
|
||||
if (appBean == null) {
|
||||
log.error("Cannot get themeDir from null application bean");
|
||||
return null;
|
||||
}
|
||||
|
||||
String themeDir = appBean.getThemeDir();
|
||||
if (themeDir == null) {
|
||||
log.error("themeDir is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
return themeDir.replaceAll("/$", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* The Configuration is theme-specific because:
|
||||
*
|
||||
* 1. The template loader is theme-specific, since it specifies a theme
|
||||
* directory to load templates from.
|
||||
*
|
||||
* 2. Some shared variables are theme-specific.
|
||||
*/
|
||||
private static FreemarkerConfiguration getConfigForTheme(String themeDir,
|
||||
ApplicationBean appBean, ServletContext context) {
|
||||
synchronized (themeToConfigMap) {
|
||||
if (themeToConfigMap.containsKey(themeDir)) {
|
||||
return themeToConfigMap.get(themeDir);
|
||||
} else {
|
||||
FreemarkerConfiguration config = new FreemarkerConfiguration(
|
||||
themeDir, appBean, context);
|
||||
themeToConfigMap.put(themeDir, config);
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||
|
||||
import static javax.mail.Message.RecipientType.TO;
|
||||
import static javax.mail.Message.RecipientType.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
@ -20,6 +20,11 @@ import org.apache.commons.lang.StringUtils;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.github.jsonldjava.core.JSONLD;
|
||||
import com.github.jsonldjava.core.JSONLDProcessingError;
|
||||
import com.github.jsonldjava.impl.JenaRDFParser;
|
||||
import com.github.jsonldjava.utils.JSONUtils;
|
||||
|
||||
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;
|
||||
|
@ -37,16 +42,19 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Res
|
|||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.Tags;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.User;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.menu.MainMenu;
|
||||
import freemarker.ext.beans.BeansWrapper;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapper;
|
||||
import freemarker.template.TemplateModel;
|
||||
import freemarker.template.TemplateModelException;
|
||||
import freemarker.template.utility.DeepUnwrap;
|
||||
|
||||
public class FreemarkerHttpServlet extends VitroHttpServlet {
|
||||
public class FreemarkerHttpServlet extends VitroHttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Log log = LogFactory.getLog(FreemarkerHttpServlet.class);
|
||||
|
@ -201,7 +209,8 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
|
|||
* NB This method can't be static, because then the superclass method gets called rather than
|
||||
* the subclass method. For the same reason, it can't refer to a static or instance field
|
||||
* REQUIRED_ACTIONS which is overridden in the subclass.
|
||||
*/
|
||||
*
|
||||
*/
|
||||
protected Actions requiredActions(VitroRequest vreq) {
|
||||
return Actions.AUTHORIZED;
|
||||
}
|
||||
|
@ -304,17 +313,29 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
|
|||
|
||||
String mediaType = values.getContentType().getMediaType();
|
||||
response.setContentType(mediaType);
|
||||
|
||||
String format = "";
|
||||
if ( RDFXML_MIMETYPE.equals(mediaType)) {
|
||||
format = "RDF/XML";
|
||||
} else if( N3_MIMETYPE.equals(mediaType)) {
|
||||
format = "N3";
|
||||
} else if ( TTL_MIMETYPE.equals(mediaType)) {
|
||||
format ="TTL";
|
||||
|
||||
if ( JSON_MIMETYPE.equals(mediaType)){
|
||||
//json-ld is not supported by jena v2.6.4
|
||||
try {
|
||||
JenaRDFParser parser = new JenaRDFParser();
|
||||
Object json = JSONLD.fromRDF( values.getModel() , parser);
|
||||
JSONUtils.write(response.getWriter(), json);
|
||||
} catch (JSONLDProcessingError e) {
|
||||
throw new IOException("Could not convert from Jena model to JSON-LD", e);
|
||||
}
|
||||
}else{
|
||||
String format = "";
|
||||
if ( RDFXML_MIMETYPE.equals(mediaType)) {
|
||||
format = "RDF/XML";
|
||||
} else if( N3_MIMETYPE.equals(mediaType)) {
|
||||
format = "N3";
|
||||
} else if ( TTL_MIMETYPE.equals(mediaType)) {
|
||||
format ="TTL";
|
||||
}
|
||||
values.getModel().write( response.getOutputStream(), format );
|
||||
}
|
||||
|
||||
values.getModel().write( response.getOutputStream(), format );
|
||||
|
||||
}
|
||||
|
||||
protected void doException(VitroRequest vreq, HttpServletResponse response,
|
||||
|
@ -336,7 +357,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
|
|||
private Map<String, Object> buildRequestUrls(VitroRequest vreq) {
|
||||
Map<String, Object> requestUrls = new HashMap<String, Object>();
|
||||
|
||||
FreemarkerConfiguration config = FreemarkerConfigurationLoader.getConfig(vreq);
|
||||
Configuration config = FreemarkerConfiguration.getConfig(vreq);
|
||||
TemplateModel urlModel = config.getSharedVariable("urls");
|
||||
|
||||
try {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -17,6 +18,10 @@ 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.auth.requestedAction.Actions;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.SimpleRequestedAction;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequiresActions;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||
|
@ -41,6 +46,79 @@ public class PageController extends FreemarkerHttpServlet{
|
|||
|
||||
protected static final String DATA_GETTER_MAP = "pageTypeToDataGetterMap";
|
||||
|
||||
/**
|
||||
* Get the required actions for all the data getters then
|
||||
* AND them together.
|
||||
*/
|
||||
@Override
|
||||
protected Actions requiredActions(VitroRequest vreq) {
|
||||
try {
|
||||
Actions pageActs = getActionsForPage( vreq );
|
||||
Actions dgActs = getActionsForDataGetters( vreq );
|
||||
|
||||
if( pageActs == null && dgActs == null){
|
||||
return Actions.AUTHORIZED;
|
||||
}else if( pageActs == null && dgActs != null ){
|
||||
return dgActs;
|
||||
}else{
|
||||
return pageActs;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
log.debug(e);
|
||||
return Actions.UNAUTHORIZED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the required actions directly required for the page.
|
||||
*/
|
||||
private Actions getActionsForPage( VitroRequest vreq ) throws Exception{
|
||||
List<String> simplePremUris = vreq.getWebappDaoFactory().getPageDao()
|
||||
.getRequiredActions( getPageUri(vreq) );
|
||||
|
||||
List<RequestedAction> actions = new ArrayList<RequestedAction>();
|
||||
|
||||
for( String uri : simplePremUris ){
|
||||
actions.add( new SimpleRequestedAction(uri) );
|
||||
}
|
||||
|
||||
return new Actions( actions );
|
||||
}
|
||||
/**
|
||||
* Get Actions object for the data getters for the page.
|
||||
*/
|
||||
private Actions getActionsForDataGetters(VitroRequest vreq ){
|
||||
try {
|
||||
Actions dgActs = null;
|
||||
|
||||
List<DataGetter> dgList =
|
||||
DataGetterUtils.getDataGettersForPage(
|
||||
vreq, vreq.getDisplayModel(), getPageUri(vreq));
|
||||
|
||||
for( DataGetter dg : dgList){
|
||||
if( dg instanceof RequiresActions ){
|
||||
RequiresActions ra = (RequiresActions) dg;
|
||||
Actions newActions = ra.requiredActions(vreq);
|
||||
if( newActions != null ){
|
||||
if( dgActs != null ){
|
||||
dgActs = dgActs.and( newActions );
|
||||
}else{
|
||||
dgActs = newActions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dgActs;
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
log.debug(e);
|
||||
return Actions.UNAUTHORIZED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResponseValues processRequest(VitroRequest vreq) throws Exception {
|
||||
|
||||
|
@ -65,8 +143,7 @@ public class PageController extends FreemarkerHttpServlet{
|
|||
return doNotFound(vreq);
|
||||
}
|
||||
|
||||
//executePageDataGetters( pageUri, vreq, getServletContext(), mapForTemplate );
|
||||
//these should all be data getters now
|
||||
//these should all be DataGetters now, not PageDataGetters
|
||||
executeDataGetters( pageUri, vreq, mapForTemplate);
|
||||
|
||||
mapForTemplate.putAll( getPageControllerValues( pageUri, vreq, getServletContext(), mapForTemplate));
|
||||
|
|
|
@ -13,7 +13,8 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfigurationImpl;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
|
@ -26,7 +27,7 @@ public class TemplateProcessingHelper {
|
|||
private Configuration config = null;
|
||||
|
||||
public TemplateProcessingHelper(HttpServletRequest request, ServletContext context) {
|
||||
this.config = FreemarkerConfigurationLoader.getConfig(new VitroRequest(request));
|
||||
this.config = FreemarkerConfiguration.getConfig(request);
|
||||
}
|
||||
|
||||
public StringWriter processTemplate(String templateName, Map<String, Object> map)
|
||||
|
@ -50,7 +51,8 @@ public class TemplateProcessingHelper {
|
|||
}
|
||||
|
||||
// Apply any data-getters that are associated with this template.
|
||||
FreemarkerConfiguration.retrieveAndRunDataGetters(env, template.getName());
|
||||
// TODO clean this up VIVO-249
|
||||
FreemarkerConfigurationImpl.retrieveAndRunDataGetters(env, template.getName());
|
||||
|
||||
// Now process it.
|
||||
env.process();
|
||||
|
|
|
@ -242,23 +242,12 @@ public class UrlBuilder {
|
|||
}
|
||||
|
||||
public static String getIndividualProfileUrl(Individual individual, VitroRequest vreq) {
|
||||
return getIndividualProfileUrl(individual, individual.getURI(),vreq);
|
||||
}
|
||||
|
||||
public static String getIndividualProfileUrl(String individualUri, VitroRequest vreq) {
|
||||
Individual individual = new IndividualImpl(individualUri);
|
||||
return getIndividualProfileUrl(individual, individualUri, vreq);
|
||||
}
|
||||
|
||||
private static String getIndividualProfileUrl(Individual individual, String individualUri, VitroRequest vreq) {
|
||||
WebappDaoFactory wadf = vreq.getWebappDaoFactory();
|
||||
String profileUrl = null;
|
||||
try {
|
||||
URI uri = new URIImpl(individualUri); // throws exception if individualUri is invalid
|
||||
String namespace = uri.getNamespace();
|
||||
String defaultNamespace = wadf.getDefaultNamespace();
|
||||
|
||||
String localName = individual.getLocalName();
|
||||
String namespace = individual.getNamespace();
|
||||
String defaultNamespace = wadf.getDefaultNamespace();
|
||||
|
||||
if (defaultNamespace.equals(namespace)) {
|
||||
profileUrl = getUrl(Route.INDIVIDUAL.path() + "/" + localName);
|
||||
|
@ -267,7 +256,7 @@ public class UrlBuilder {
|
|||
log.debug("Found externally linked namespace " + namespace);
|
||||
profileUrl = namespace + localName;
|
||||
} else {
|
||||
ParamMap params = new ParamMap("uri", individualUri);
|
||||
ParamMap params = new ParamMap("uri", individual.getURI());
|
||||
profileUrl = getUrl("/individual", params);
|
||||
}
|
||||
}
|
||||
|
@ -276,25 +265,56 @@ public class UrlBuilder {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (profileUrl != null) {
|
||||
LinkedHashMap<String, String> specialParams = getModelParams(vreq);
|
||||
if(specialParams.size() != 0) {
|
||||
profileUrl = addParams(profileUrl, new ParamMap(specialParams));
|
||||
}
|
||||
}
|
||||
|
||||
return profileUrl;
|
||||
if (profileUrl != null) {
|
||||
LinkedHashMap<String, String> specialParams = getModelParams(vreq);
|
||||
if(specialParams.size() != 0) {
|
||||
profileUrl = addParams(profileUrl, new ParamMap(specialParams));
|
||||
}
|
||||
}
|
||||
|
||||
return profileUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* If you already have an Individual object around,
|
||||
* call getIndividualProfileUrl(Individual, VitroRequest)
|
||||
* instead of this method.
|
||||
*/
|
||||
public static String getIndividualProfileUrl(String individualUri, VitroRequest vreq) {
|
||||
return getIndividualProfileUrl(new IndividualImpl(individualUri), vreq);
|
||||
}
|
||||
|
||||
protected static String getIndividualProfileUrl(
|
||||
String individualUri,
|
||||
String namespace, String localName,
|
||||
String defaultNamespace){
|
||||
String profileUrl = "";
|
||||
try{
|
||||
if ( isUriInDefaultNamespace( individualUri, defaultNamespace) ) {
|
||||
profileUrl = getUrl(Route.INDIVIDUAL.path() + "/" + localName);
|
||||
} else {
|
||||
ParamMap params = new ParamMap("uri", individualUri);
|
||||
profileUrl = getUrl("/individual", params);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn(e);
|
||||
return null;
|
||||
}
|
||||
return profileUrl;
|
||||
}
|
||||
|
||||
public static boolean isUriInDefaultNamespace(String individualUri, VitroRequest vreq) {
|
||||
return isUriInDefaultNamespace(individualUri, vreq.getWebappDaoFactory());
|
||||
}
|
||||
|
||||
public static boolean isUriInDefaultNamespace(String individualUri, WebappDaoFactory wadf) {
|
||||
public static boolean isUriInDefaultNamespace(String individualUri, WebappDaoFactory wadf) {
|
||||
return isUriInDefaultNamespace( individualUri, wadf.getDefaultNamespace());
|
||||
}
|
||||
|
||||
public static boolean isUriInDefaultNamespace(String individualUri, String defaultNamespace){
|
||||
try {
|
||||
URI uri = new URIImpl(individualUri); // throws exception if individualUri is invalid
|
||||
String namespace = uri.getNamespace();
|
||||
String defaultNamespace = wadf.getDefaultNamespace();
|
||||
Individual ind = new IndividualImpl(individualUri);
|
||||
String namespace = ind.getNamespace();
|
||||
return defaultNamespace.equals(namespace);
|
||||
} catch (Exception e) {
|
||||
log.warn(e);
|
||||
|
|
|
@ -39,6 +39,8 @@ public class IndividualController extends FreemarkerHttpServlet {
|
|||
map.put(HTML_MIMETYPE, 0.5f);
|
||||
map.put(XHTML_MIMETYPE, 0.5f);
|
||||
map.put("application/xml", 0.5f);
|
||||
map.put(JSON_MIMETYPE, 1.0f);
|
||||
map.put(RDFXML_MIMETYPE, 1.0f);
|
||||
map.put(RDFXML_MIMETYPE, 1.0f);
|
||||
map.put(N3_MIMETYPE, 1.0f);
|
||||
map.put(TTL_MIMETYPE, 1.0f);
|
||||
|
|
|
@ -5,6 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.individual;
|
|||
import static edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet.N3_MIMETYPE;
|
||||
import static edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet.RDFXML_MIMETYPE;
|
||||
import static edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet.TTL_MIMETYPE;
|
||||
import static edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet.JSON_MIMETYPE;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -117,7 +118,9 @@ public class IndividualRequestAnalyzer {
|
|||
return "/individual/" + m.group(1) + "/" + m.group(1) + ".n3";
|
||||
} else if (TTL_MIMETYPE.equals(mediaType)) {
|
||||
return "/individual/" + m.group(1) + "/" + m.group(1) + ".ttl";
|
||||
}
|
||||
} else if (JSON_MIMETYPE.equals(mediaType)){
|
||||
return "/individual/" + m.group(1) + "/" + m.group(1) + ".jsonld";
|
||||
}
|
||||
}
|
||||
// or redirect to the canonical URL for HTML representation.
|
||||
return "/display/" + m.group(1);
|
||||
|
@ -244,7 +247,10 @@ public class IndividualRequestAnalyzer {
|
|||
if (formatParam.contains("ttl")) {
|
||||
return ContentType.TURTLE;
|
||||
}
|
||||
|
||||
if (formatParam.contains("jsonld") || formatParam.contains("json")){
|
||||
return ContentType.JSON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for parts of URL that indicate request for RDF. Examples:
|
||||
* http://vivo.cornell.edu/individual/n23/n23.rdf
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.lang.Integer;
|
|||
import java.lang.String;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -31,6 +33,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
|
|||
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ExecuteDataRetrieval;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.beanswrappers.ReadOnlyBeansWrapper;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.IndividualTemplateModel;
|
||||
|
@ -108,6 +111,8 @@ class IndividualResponseBuilder {
|
|||
*/
|
||||
// body.put("individual", wrap(itm, BeansWrapper.EXPOSE_SAFE));
|
||||
body.put("labelCount", getLabelCount(itm.getUri(), vreq));
|
||||
//We also need to know the number of available locales
|
||||
body.put("localesCount", SelectedLocale.getSelectableLocales(vreq).size());
|
||||
body.put("profileType", getProfileType(itm.getUri(), vreq));
|
||||
body.put("individual", wrap(itm, new ReadOnlyBeansWrapper()));
|
||||
|
||||
|
@ -279,7 +284,9 @@ class IndividualResponseBuilder {
|
|||
log.debug("queryStr = " + queryStr);
|
||||
int theCount = 0;
|
||||
try {
|
||||
ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
|
||||
//ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
|
||||
//Get query results across all languages in order for template to show manage labels link correctly
|
||||
ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
|
||||
if (results.hasNext()) {
|
||||
QuerySolution soln = results.nextSolution();
|
||||
String countStr = soln.get("labelCount").toString();
|
||||
|
|
|
@ -48,6 +48,7 @@ public class DisplayVocabulary {
|
|||
public static final String ITEM_TO_PAGE = NS + "toPage";
|
||||
public static final String HAS_ELEMENT = NS + "hasElement";
|
||||
public static final String USES_DATAGETTER_CLASS = NS + "usesDataGetterClass";
|
||||
public static final String REQUIRED_ACTIONS = NS + "requiredAction";
|
||||
|
||||
/**Data Getter object properties **/
|
||||
public static final String HAS_DATA_GETTER = NS + "hasDataGetter";
|
||||
|
|
|
@ -29,4 +29,10 @@ public interface PageDao {
|
|||
|
||||
List<String> getDataGetterClass(String pageUri);
|
||||
|
||||
/**
|
||||
* Gets the required actions directly associated with a page.
|
||||
* Does not get required actions for any data getters that are
|
||||
* related to the page.
|
||||
*/
|
||||
List<String> getRequiredActions(String pageUri);
|
||||
}
|
||||
|
|
|
@ -874,7 +874,7 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp
|
|||
*/
|
||||
|
||||
protected static final List<String> EXCLUDED_NAMESPACES = Arrays.asList(
|
||||
"http://www.w3.org/2002/07/owl#"
|
||||
//"http://www.w3.org/2002/07/owl#"
|
||||
);
|
||||
/*
|
||||
* This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -10,6 +11,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
@ -34,6 +36,7 @@ import com.hp.hpl.jena.rdf.model.Statement;
|
|||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||
import com.hp.hpl.jena.vocabulary.OWL;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
|
||||
|
@ -353,7 +356,7 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
|
|||
return null;
|
||||
}
|
||||
|
||||
Model constructedModel = ModelFactory.createDefaultModel();
|
||||
Model constructedModel = ModelFactory.createDefaultModel();
|
||||
|
||||
for (String queryString : constructQueries) {
|
||||
|
||||
|
@ -408,13 +411,24 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
|
|||
w.close();
|
||||
}
|
||||
} else {
|
||||
constructedModel.read(
|
||||
rdfService.sparqlConstructQuery(
|
||||
queryString, RDFService.ModelSerializationFormat.N3), null, "N3");
|
||||
|
||||
String parseFormat = "N3";
|
||||
RDFService.ModelSerializationFormat resultFormat = RDFService.ModelSerializationFormat.N3;
|
||||
|
||||
/* If the test ObjectPropertyStatementDaoJenaTest.testN3WithSameAs() fails
|
||||
* this code can be removed: */
|
||||
if( OWL.sameAs.getURI().equals( propertyUri )){
|
||||
// VIVO-111: owl:sameAs can be represented as = in n3 but Jena's parser does not recognize it.
|
||||
// Switch to rdf/xml only for sameAs since it seems like n3 would be faster the rest of the time.
|
||||
parseFormat = "RDF/XML";
|
||||
resultFormat = RDFService.ModelSerializationFormat.RDFXML;
|
||||
}
|
||||
/* end of removal */
|
||||
|
||||
InputStream is = rdfService.sparqlConstructQuery(queryString, resultFormat);
|
||||
constructedModel.read( is, null, parseFormat);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting constructed model for subject " + subjectUri + " and property " + propertyUri);
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting constructed model for subject " + subjectUri + " and property " + propertyUri, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -77,7 +78,14 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
|
|||
" ?pageUri display:hasDataGetter ?dg .\n"+
|
||||
" ?dg rdf:type ?dataGetterType . \n" +
|
||||
"} \n" ;
|
||||
|
||||
|
||||
//Get the required actions directly associated with a page
|
||||
static final protected String requiredActionsQuery =
|
||||
prefixes + "\n" +
|
||||
"SELECT ?requiredAction WHERE{\n" +
|
||||
" ?pageUri <" + DisplayVocabulary.REQUIRED_ACTIONS + "> ?requiredAction .\n"+
|
||||
"}";
|
||||
|
||||
//Get data getter URIs
|
||||
static final protected String dataGetterURIsQueryString =
|
||||
prefixes + "\n" +
|
||||
|
@ -519,10 +527,54 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
|
|||
return dataGetterClasses;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the requiredActions directly associated with page.
|
||||
*/
|
||||
public List<String> getRequiredActions(String pageUri){
|
||||
QuerySolutionMap initialBindings = new QuerySolutionMap();
|
||||
initialBindings.add("pageUri", ResourceFactory.createResource(pageUri));
|
||||
List<String> actions = new ArrayList<String>();
|
||||
|
||||
Model dModel = getOntModelSelector().getDisplayModel();
|
||||
try{
|
||||
QueryExecution qe =
|
||||
QueryExecutionFactory.create( requiredActionsQuery, dModel, initialBindings);
|
||||
actions = executeQueryToList( qe );
|
||||
qe.close();
|
||||
}finally{
|
||||
dModel.enterCriticalSection(false);
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
/* *************************** Utility methods ********************************* */
|
||||
|
||||
|
||||
/**
|
||||
* Assumes single bound variable in solution.
|
||||
*/
|
||||
protected List<String> executeQueryToList(QueryExecution qex){
|
||||
List<String> rv = new LinkedList<String>();
|
||||
ResultSet results = qex.execSelect();
|
||||
while (results.hasNext()) {
|
||||
rv.add(querySolutionToString( results.nextSolution() ));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes single bound variable in solution.
|
||||
*/
|
||||
protected String querySolutionToString( QuerySolution soln ){
|
||||
Iterator<String> varNames = soln.varNames();
|
||||
if(varNames.hasNext()){
|
||||
String name = varNames.next();
|
||||
return nodeToString( soln.get(name) );
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a sparql query that returns a multiple rows to a list of maps.
|
||||
* The maps will have column names as keys to the values.
|
||||
|
@ -548,7 +600,9 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
|
|||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static protected Object nodeToObject( RDFNode node ){
|
||||
if( node == null ){
|
||||
return "";
|
||||
|
@ -582,11 +636,6 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
|
|||
return "";
|
||||
}
|
||||
}
|
||||
protected Map<String,Object> resultsToMap(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
|||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.ontology.OntProperty;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.ResourceFactory;
|
||||
|
@ -39,7 +40,8 @@ public class PropertyInstanceDaoJena extends PropertyDaoJena implements
|
|||
deleteObjectPropertyStatement(subjectURI, propertyURI, objectURI, getOntModelSelector());
|
||||
}
|
||||
|
||||
public void deleteObjectPropertyStatement(String subjectURI, String propertyURI, String objectURI, OntModelSelector ontModelSelector) {
|
||||
public void deleteObjectPropertyStatement(String subjectURI, String propertyURI, String objectURI,
|
||||
OntModelSelector ontModelSelector) {
|
||||
OntModel ontModel = ontModelSelector.getABoxModel();
|
||||
OntModel tboxModel = ontModelSelector.getTBoxModel();
|
||||
ontModel.enterCriticalSection(Lock.WRITE);
|
||||
|
@ -51,29 +53,31 @@ public class PropertyInstanceDaoJena extends PropertyDaoJena implements
|
|||
invPred = pred.as(OntProperty.class).getInverse();
|
||||
}
|
||||
Resource objRes = ontModel.getResource(objectURI);
|
||||
Model baseModel = getOntModel().getBaseModel();
|
||||
String userUri = getWebappDaoFactory().getUserURI();
|
||||
if ( (subjRes != null) && (pred != null) && (objRes != null) ) {
|
||||
getOntModel().getBaseModel().notifyEvent(new IndividualUpdateEvent(getWebappDaoFactory().getUserURI(),true,subjectURI));
|
||||
baseModel.notifyEvent(new IndividualUpdateEvent(userUri,true,subjectURI));
|
||||
try {
|
||||
ontModel.remove(subjRes,pred,objRes);
|
||||
|
||||
updatePropertyDateTimeValue(subjRes,MODTIME,Calendar.getInstance().getTime(),getOntModel());
|
||||
ontModel.remove(subjRes,pred,objRes);
|
||||
updatePropertyDateTimeValue(subjRes,MODTIME,Calendar.getInstance().getTime(),ontModel);
|
||||
} finally {
|
||||
getOntModel().getBaseModel().notifyEvent(new IndividualUpdateEvent(getWebappDaoFactory().getUserURI(),false,subjectURI));
|
||||
baseModel.notifyEvent(new IndividualUpdateEvent(userUri,false,subjectURI));
|
||||
}
|
||||
try{
|
||||
getOntModel().getBaseModel().notifyEvent(new IndividualDeletionEvent(getWebappDaoFactory().getUserURI(),true,objectURI));
|
||||
List<Statement> depResStmts = DependentResourceDeleteJena.getDependentResourceDeleteList(ResourceFactory.createStatement(subjRes, pred, objRes),ontModel);
|
||||
getOntModel().remove(depResStmts);
|
||||
baseModel.notifyEvent(new IndividualDeletionEvent(userUri,true,objectURI));
|
||||
List<Statement> depResStmts = DependentResourceDeleteJena
|
||||
.getDependentResourceDeleteList(ResourceFactory.createStatement(subjRes, pred, objRes),ontModel);
|
||||
ontModel.remove(depResStmts);
|
||||
} finally {
|
||||
getOntModel().getBaseModel().notifyEvent(new IndividualDeletionEvent(getWebappDaoFactory().getUserURI(),false,objectURI));
|
||||
baseModel.notifyEvent(new IndividualDeletionEvent(userUri,false,objectURI));
|
||||
}
|
||||
if (invPred != null) {
|
||||
getOntModel().getBaseModel().notifyEvent(new IndividualUpdateEvent(getWebappDaoFactory().getUserURI(),true,objectURI));
|
||||
baseModel.notifyEvent(new IndividualUpdateEvent(userUri,true,objectURI));
|
||||
try {
|
||||
ontModel.remove(objRes,invPred,subjRes);
|
||||
updatePropertyDateTimeValue(objRes,MODTIME,Calendar.getInstance().getTime(),getOntModel());
|
||||
updatePropertyDateTimeValue(objRes,MODTIME,Calendar.getInstance().getTime(),ontModel);
|
||||
} finally {
|
||||
getOntModel().getBaseModel().notifyEvent(new IndividualUpdateEvent(getWebappDaoFactory().getUserURI(),false,subjectURI));
|
||||
baseModel.notifyEvent(new IndividualUpdateEvent(userUri,false,subjectURI));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,9 +115,16 @@ public class QueryUtils {
|
|||
}
|
||||
|
||||
public static ResultSet getQueryResults(String queryStr, VitroRequest vreq) {
|
||||
|
||||
Dataset dataset = vreq.getDataset();
|
||||
dataset.getLock().enterCriticalSection(Lock.READ);
|
||||
return getQueryResults(queryStr, vreq.getDataset());
|
||||
}
|
||||
|
||||
public static ResultSet getLanguageNeutralQueryResults(String queryStr, VitroRequest vreq) {
|
||||
return getQueryResults(queryStr, vreq.getUnfilteredDataset());
|
||||
}
|
||||
|
||||
/** Already have the dataset, so process the query and return the results. */
|
||||
private static ResultSet getQueryResults(String queryStr, Dataset dataset) {
|
||||
dataset.getLock().enterCriticalSection(Lock.READ);
|
||||
QueryExecution qexec = null;
|
||||
ResultSet results = null;
|
||||
try {
|
||||
|
@ -133,6 +140,6 @@ public class QueryUtils {
|
|||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,11 +23,11 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
|||
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
|
||||
import freemarker.template.Configuration;
|
||||
|
||||
public class EditConfigurationUtils {
|
||||
|
@ -282,7 +282,7 @@ public class EditConfigurationUtils {
|
|||
//Generate HTML for a specific field name given
|
||||
public static String generateHTMLForElement(VitroRequest vreq, String fieldName, EditConfigurationVTwo editConfig) {
|
||||
String html = "";
|
||||
Configuration fmConfig = FreemarkerConfigurationLoader.getConfig(vreq);
|
||||
Configuration fmConfig = FreemarkerConfiguration.getConfig(vreq);
|
||||
|
||||
FieldVTwo field = editConfig == null ? null : editConfig.getField(fieldName);
|
||||
MultiValueEditSubmission editSub = EditSubmissionUtils.getEditSubmissionFromSession(vreq.getSession(), editConfig);
|
||||
|
|
|
@ -0,0 +1,576 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.query.Dataset;
|
||||
import com.hp.hpl.jena.query.QueryExecution;
|
||||
import com.hp.hpl.jena.query.QueryExecutionFactory;
|
||||
import com.hp.hpl.jena.query.QuerySolution;
|
||||
import com.hp.hpl.jena.query.ResultSet;
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
import com.hp.hpl.jena.sparql.resultset.ResultSetMem;
|
||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||
import com.hp.hpl.jena.vocabulary.XSD;
|
||||
|
||||
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.RequestActionConstants;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddDataPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddObjectPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||
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.ParamMap;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.FoafNameToRdfsLabelPreprocessor;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.ManageLabelsForIndividualPreprocessor;
|
||||
import edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionDataGetter;
|
||||
import edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectorUtilities;
|
||||
import edu.cornell.mannlib.vitro.webapp.i18n.selection.SelectedLocale;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.DataPropertyStatementTemplateModel;
|
||||
|
||||
/**
|
||||
*This allows the page to show all the labels for a particular individual and sets up code
|
||||
*enabling the addition of a new label. Links on the page will allow for removal or editing of a given label.
|
||||
*/
|
||||
public class ManageLabelsForIndividualGenerator extends BaseEditConfigurationGenerator implements EditConfigurationGenerator {
|
||||
public static Log log = LogFactory.getLog(ManageLabelsForIndividualGenerator.class);
|
||||
private static String template = "manageLabelsForIndividual.ftl";
|
||||
private HashMap<String, List<LabelInformation>> labelsSortedByLanguage = null;
|
||||
private List<Literal> existingLabelLiterals = null;
|
||||
//list of language names sorted alphabetically
|
||||
private List<String> existingSortedLanguageNameList = null;
|
||||
//This would be for the full list and can be used for the existing labels list as well
|
||||
|
||||
private HashMap<String, String> fullLanguageNameToCodeMap = null;
|
||||
private static String predicateUri = RDFS.label.getURI();
|
||||
@Override
|
||||
public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) {
|
||||
|
||||
EditConfigurationVTwo config = new EditConfigurationVTwo();
|
||||
config.setTemplate(this.getTemplate());
|
||||
|
||||
initBasics(config, vreq);
|
||||
initPropertyParameters(vreq, session, config);
|
||||
|
||||
//This form is technically not an object property form in the true sense
|
||||
//or a data property form because it is used to list the various labels
|
||||
//and allow for adding new labels
|
||||
//URL to return to is the same page once addition is complete
|
||||
this.setUrlToReturnTo(config, vreq);
|
||||
|
||||
config.setSubjectUri(EditConfigurationUtils.getSubjectUri(vreq));
|
||||
|
||||
setVarNames(config);
|
||||
config.setDatapropKey( EditConfigurationUtils.getDataHash(vreq) );
|
||||
//Add n3, fields, etc. in the case where the user wants to add a label
|
||||
//N3 required should be empty since the addition of a label is optional in this case
|
||||
config.setN3Required(this.generateN3Required(vreq));
|
||||
config.setN3Optional(this.generateN3Optional(vreq));
|
||||
this.setUrisAndLiteralsOnForm(config, vreq);
|
||||
setUrisAndLiteralsInScope(config);
|
||||
this.setFields(config, vreq, EditConfigurationUtils
|
||||
.getPredicateUri(vreq));
|
||||
|
||||
//Get existing labels
|
||||
//this.initExistingLabels(config, vreq);
|
||||
|
||||
//Add form specific data used to populate template
|
||||
addFormSpecificData(config, vreq);
|
||||
//This preprocessor handles getting the correct label language and putting the attribute on the label
|
||||
config.addEditSubmissionPreprocessor(
|
||||
new ManageLabelsForIndividualPreprocessor(config));
|
||||
//This will handle generating the label from the first name and last name and also make sure to associate
|
||||
//a language with that label
|
||||
config.addModelChangePreprocessor(new FoafNameToRdfsLabelPreprocessor());
|
||||
|
||||
prepare(vreq, config);
|
||||
return config;
|
||||
}
|
||||
|
||||
private void setUrlToReturnTo(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
|
||||
editConfiguration.setUrlPatternToReturnTo(EditConfigurationUtils.getFormUrlWithoutContext(vreq));
|
||||
}
|
||||
|
||||
private void setVarNames(EditConfigurationVTwo editConfiguration) {
|
||||
editConfiguration.setVarNameForSubject("subject");
|
||||
editConfiguration.setVarNameForPredicate("predicate");
|
||||
|
||||
}
|
||||
|
||||
|
||||
private List<String> generateN3Required(VitroRequest vreq) {
|
||||
List<String> n3Required = new ArrayList<String>();
|
||||
return n3Required;
|
||||
}
|
||||
|
||||
private List<String> generateN3Optional(VitroRequest vreq) {
|
||||
List<String> n3Optional = new ArrayList<String>();
|
||||
String predicateUri = EditConfigurationUtils.getPredicateUri(vreq);
|
||||
String n3 = "?subject <" + predicateUri + "> ?label ";
|
||||
//n3 used if the subject is a person
|
||||
String personN3 = this.N3_PREFIX + "?subject foaf:firstName ?firstName ; foaf:lastName ?lastName .";
|
||||
n3Optional.add(n3);
|
||||
n3Optional.add(personN3);
|
||||
return n3Optional;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void setFields(EditConfigurationVTwo editConfiguration, VitroRequest vreq, String predicateUri) {
|
||||
Map<String, FieldVTwo> fields = new HashMap<String, FieldVTwo>();
|
||||
editConfiguration.setFields(fields);
|
||||
editConfiguration.addField(new FieldVTwo().
|
||||
setName("label").
|
||||
setValidators(getLabelValidators(vreq, editConfiguration)));
|
||||
editConfiguration.addField(new FieldVTwo(
|
||||
).setName("newLabelLanguage"));
|
||||
//no validators since all of this is optional
|
||||
//there should be error-checking client side though
|
||||
editConfiguration.addField(new FieldVTwo().
|
||||
setName("firstName").
|
||||
setValidators(getFirstNameValidators(vreq, editConfiguration)));
|
||||
|
||||
editConfiguration.addField(new FieldVTwo().
|
||||
setName("lastName").
|
||||
setValidators(getLastNameValidators(vreq, editConfiguration)));
|
||||
}
|
||||
|
||||
//first and last name have validators if is person is true
|
||||
private List<String> getFirstNameValidators(VitroRequest vreq, EditConfigurationVTwo config) {
|
||||
List<String> validators = new ArrayList<String>();
|
||||
if(isPersonType(vreq, config)) {
|
||||
validators.add("nonempty");
|
||||
}
|
||||
return validators;
|
||||
}
|
||||
|
||||
private List<String> getLastNameValidators(VitroRequest vreq, EditConfigurationVTwo config) {
|
||||
List<String> validators = new ArrayList<String>();
|
||||
if(isPersonType(vreq, config)) {
|
||||
validators.add("nonempty");
|
||||
}
|
||||
return validators;
|
||||
}
|
||||
|
||||
//validate label if person is not true
|
||||
private List<String> getLabelValidators(VitroRequest vreq, EditConfigurationVTwo config) {
|
||||
List<String> validators = new ArrayList<String>();
|
||||
if(!isPersonType(vreq, config)) {
|
||||
validators.add("nonempty");
|
||||
}
|
||||
return validators;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void setUrisAndLiteralsOnForm(EditConfigurationVTwo config,
|
||||
VitroRequest vreq) {
|
||||
List<String> literalsOnForm = new ArrayList<String>();
|
||||
literalsOnForm.add("label");
|
||||
literalsOnForm.add("newLabelLanguage");
|
||||
//optional for person
|
||||
literalsOnForm.add("firstName");
|
||||
literalsOnForm.add("lastName");
|
||||
config.setLiteralsOnForm(literalsOnForm);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void setUrisAndLiteralsInScope(EditConfigurationVTwo editConfiguration) {
|
||||
HashMap<String, List<String>> urisInScope = new HashMap<String, List<String>>();
|
||||
//note that at this point the subject, predicate, and object var parameters have already been processed
|
||||
urisInScope.put(editConfiguration.getVarNameForSubject(),
|
||||
Arrays.asList(new String[]{editConfiguration.getSubjectUri()}));
|
||||
urisInScope.put(editConfiguration.getVarNameForPredicate(),
|
||||
Arrays.asList(new String[]{editConfiguration.getPredicateUri()}));
|
||||
editConfiguration.setUrisInScope(urisInScope);
|
||||
//Uris in scope include subject, predicate, and object var
|
||||
|
||||
editConfiguration.setLiteralsInScope(new HashMap<String, List<Literal>>());
|
||||
}
|
||||
|
||||
private void initExistingLabels(EditConfigurationVTwo config,
|
||||
VitroRequest vreq) {
|
||||
this.existingLabelLiterals = this.getExistingLabels(config.getSubjectUri(), vreq);
|
||||
// this.labelsSortedByLanguage = this.getLabelsSortedByLanguage(config,vreq);
|
||||
//language names sorted for the existing languages
|
||||
// this.existingSortedLanguageNameList = getExistingSortedLanguageNamesList();
|
||||
|
||||
//Generate a label to language code hash map
|
||||
//TODO:
|
||||
|
||||
//HashMap<String, String> labelToLanguageCode = new HashMap<String, String>();
|
||||
|
||||
//this.labels = getExistingLabels(config.getSubjectUri(), vreq);
|
||||
//this.labelsSortedByLanguage = getLabelsSortedByLanguage(config.getSubjectUri(), vreq);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private List<String> getExistingSortedLanguageNamesList() {
|
||||
HashSet<String> existingLanguages = new HashSet<String>();
|
||||
for(Literal l: this.existingLabelLiterals) {
|
||||
String language = l.getLanguage();
|
||||
if(!existingLanguages.contains(language)) {
|
||||
existingLanguages.add(language);
|
||||
}
|
||||
}
|
||||
List<String> sortedNames = new ArrayList<String>(existingLanguages);
|
||||
//sort alphabetically
|
||||
Collections.sort(sortedNames);
|
||||
return sortedNames;
|
||||
}
|
||||
|
||||
|
||||
private void addFormSpecificData(EditConfigurationVTwo config,
|
||||
VitroRequest vreq) {
|
||||
//Get all language codes/labels in the system, and this list is sorted by language name
|
||||
List<HashMap<String, String>> locales = this.getLocales(vreq);
|
||||
//Get code to label hashmap - we use this to get the language name for the language code returned in the rdf literal
|
||||
HashMap<String, String> localeCodeToNameMap = this.getFullCodeToLanguageNameMap(locales);
|
||||
//the labels already added by the user
|
||||
ArrayList<Literal> existingLabels = this.getExistingLabels(config.getSubjectUri(), vreq);
|
||||
int numberExistingLabels = existingLabels.size();
|
||||
//existing labels keyed by language name and each of the list of labels is sorted by language name
|
||||
HashMap<String, List<LabelInformation>> existingLabelsByLanguageName = this.getLabelsSortedByLanguageName(existingLabels, localeCodeToNameMap, config, vreq);
|
||||
//Get available locales for the drop down for adding a new label, also sorted by language name
|
||||
HashSet<String> existingLanguageNames = new HashSet<String>(existingLabelsByLanguageName.keySet());
|
||||
List<HashMap<String, String>> availableLocalesForAdd = getAvailableLocales(locales, existingLanguageNames);
|
||||
|
||||
|
||||
//Save all locales
|
||||
config.addFormSpecificData("selectLocaleFullList", locales);
|
||||
//Save labels sorted by language name, untyped have "untyped" as the language name value
|
||||
config.addFormSpecificData("labelsSortedByLanguageName", existingLabelsByLanguageName);
|
||||
config.addFormSpecificData("selectLocale",availableLocalesForAdd);
|
||||
config.addFormSpecificData("displayRemoveLink", (numberExistingLabels > 1));
|
||||
|
||||
|
||||
//How do we edit? Will need to see
|
||||
config.addFormSpecificData("deleteWebpageUrl", "/edit/primitiveDelete");
|
||||
|
||||
|
||||
Individual subject = vreq.getWebappDaoFactory().getIndividualDao().getIndividualByURI(config.getSubjectUri());
|
||||
if( subject != null && subject.getName() != null ){
|
||||
config.addFormSpecificData("subjectName", subject.getName());
|
||||
}else{
|
||||
config.addFormSpecificData("subjectName", null);
|
||||
}
|
||||
|
||||
//Put in whether or not person type
|
||||
if(isPersonType(vreq, config)) {
|
||||
//Doing this b/c unsure how freemarker will handle boolean value from JAVA
|
||||
config.addFormSpecificData("isPersonType", "true");
|
||||
} else {
|
||||
config.addFormSpecificData("isPersonType", "false");
|
||||
|
||||
}
|
||||
|
||||
//Include whether or not editable to enable edit/remove links and add to show up
|
||||
config.addFormSpecificData("editable", isEditable(vreq, config));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Based on what locales have already been selected for labels, return a list of
|
||||
//locales for which new labels can be added and have these sorted by the name of the language
|
||||
private List<HashMap<String, String>> getAvailableLocales(List<HashMap<String, String>> allLocales,
|
||||
HashSet<String> existingLabelsLanguageNames) {
|
||||
List<HashMap<String, String>> availableLocales = new ArrayList<HashMap<String, String>>();
|
||||
for(HashMap<String, String> localeInfo: allLocales) {
|
||||
String languageName = (String) localeInfo.get("label");
|
||||
//If this language label is NOT in the labels sorted by language, then available
|
||||
//for selection when creating a new label
|
||||
//The assumption here is we don't want to allow the user to add a new label when a label
|
||||
//already exists in that language
|
||||
if(languageName != "untyped" && !existingLabelsLanguageNames.contains(languageName)) {
|
||||
availableLocales.add(localeInfo);
|
||||
}
|
||||
}
|
||||
//Sort list by language label and return
|
||||
Collections.sort(availableLocales, new Comparator<HashMap<String, String>>() {
|
||||
public int compare(HashMap<String, String> h1, HashMap<String, String> h2) {
|
||||
String languageName1 = (String) h1.get("label");
|
||||
String languageName2 = (String) h2.get("label");
|
||||
return languageName1.compareTo(languageName2);
|
||||
}
|
||||
});
|
||||
|
||||
return availableLocales;
|
||||
}
|
||||
|
||||
|
||||
private Object isEditable(VitroRequest vreq, EditConfigurationVTwo config) {
|
||||
Individual individual = EditConfigurationUtils.getIndividual(vreq, config.getSubjectUri());
|
||||
AddDataPropertyStatement adps = new AddDataPropertyStatement(
|
||||
vreq.getJenaOntModel(), individual.getURI(),
|
||||
RequestActionConstants.SOME_URI);
|
||||
AddObjectPropertyStatement aops = new AddObjectPropertyStatement(
|
||||
vreq.getJenaOntModel(), individual.getURI(),
|
||||
RequestActionConstants.SOME_URI,
|
||||
RequestActionConstants.SOME_URI);
|
||||
return PolicyHelper.isAuthorizedForActions(vreq, new Actions(adps).or(aops));
|
||||
}
|
||||
|
||||
|
||||
//Copied from NewIndividualFormGenerator
|
||||
//TODO: Refactor so common code can be used by both generators
|
||||
public String getFOAFPersonClassURI() {
|
||||
return "http://xmlns.com/foaf/0.1/Person";
|
||||
}
|
||||
|
||||
public boolean isPersonType(VitroRequest vreq, EditConfigurationVTwo config) {
|
||||
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
|
||||
Boolean isPersonType = Boolean.FALSE;
|
||||
String foafPersonType = getFOAFPersonClassURI();
|
||||
List<VClass> vclasses = this.getVClasses(config, vreq);
|
||||
if( vclasses != null ){
|
||||
for( VClass v: vclasses){
|
||||
String typeUri = v.getURI();
|
||||
if( foafPersonType.equals(typeUri)) {
|
||||
isPersonType = Boolean.TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isPersonType;
|
||||
}
|
||||
|
||||
//how to get the type of the individual in question
|
||||
public List<VClass> getVClasses(EditConfigurationVTwo config, VitroRequest vreq) {
|
||||
Individual subject = EditConfigurationUtils.getIndividual(vreq, config.getSubjectUri());
|
||||
//Get the vclasses appropriate for this subject
|
||||
return subject.getVClasses();
|
||||
}
|
||||
|
||||
//Languages sorted by language name
|
||||
private HashMap<String, List<LabelInformation>> getLabelsSortedByLanguageName(List<Literal> labels, Map<String, String> localeCodeToNameMap, EditConfigurationVTwo config,
|
||||
VitroRequest vreq) {
|
||||
String subjectUri = config.getSubjectUri();
|
||||
String propertyUri = config.getPredicateUri();
|
||||
|
||||
|
||||
//Iterate through the labels and create a hashmap
|
||||
HashMap<String, List<LabelInformation>> labelsHash= new HashMap<String, List<LabelInformation>>();
|
||||
|
||||
for(Literal l: labels) {
|
||||
String languageTag = l.getLanguage();
|
||||
String languageName = "";
|
||||
if(languageTag == "") {
|
||||
languageName = "untyped";
|
||||
}
|
||||
else if(localeCodeToNameMap.containsKey(languageTag)) {
|
||||
languageName = localeCodeToNameMap.get(languageTag);
|
||||
} else {
|
||||
log.warn("This language tag " + languageTag + " does not have corresponding name in the system and was not processed");
|
||||
}
|
||||
|
||||
if(languageName != "") {
|
||||
if(!labelsHash.containsKey(languageName)) {
|
||||
labelsHash.put(languageName, new ArrayList<LabelInformation>());
|
||||
}
|
||||
ArrayList<LabelInformation> labelsList = (ArrayList<LabelInformation>)labelsHash.get(languageName);
|
||||
//This should put the label in the list
|
||||
//Create label information instance with the required information
|
||||
//To generate link
|
||||
DataPropertyStatementTemplateModel dpstm = new DataPropertyStatementTemplateModel(subjectUri, propertyUri, l,
|
||||
template, vreq);
|
||||
labelsList.add(new LabelInformation(
|
||||
l, dpstm.getEditUrl(), dpstm.getDeleteUrl(), languageTag, languageName));
|
||||
}
|
||||
}
|
||||
|
||||
//Sort each label list
|
||||
LabelInformationComparator lic = new LabelInformationComparator();
|
||||
for(String languageName: labelsHash.keySet()) {
|
||||
List<LabelInformation> labelInfo = labelsHash.get(languageName);
|
||||
Collections.sort(labelInfo, lic);
|
||||
}
|
||||
return labelsHash;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class LabelInformationComparator implements Comparator<LabelInformation> {
|
||||
|
||||
public int compare(LabelInformation l1, LabelInformation l2) {
|
||||
return l1.getLabelStringValue().compareTo(l2.getLabelStringValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String LABEL_QUERY = ""
|
||||
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
|
||||
+ "SELECT DISTINCT ?label WHERE { \n"
|
||||
+ " ?subject rdfs:label ?label \n"
|
||||
+ "} ORDER BY ?label";
|
||||
|
||||
|
||||
private ArrayList<Literal> getExistingLabels(String subjectUri, VitroRequest vreq) {
|
||||
String queryStr = QueryUtils.subUriForQueryVar(LABEL_QUERY, "subject", subjectUri);
|
||||
log.debug("queryStr = " + queryStr);
|
||||
|
||||
ArrayList<Literal> labels = new ArrayList<Literal>();
|
||||
try {
|
||||
//We want to get the labels for all the languages, not just the display language
|
||||
ResultSet results = QueryUtils.getLanguageNeutralQueryResults(queryStr, vreq);
|
||||
while (results.hasNext()) {
|
||||
QuerySolution soln = results.nextSolution();
|
||||
Literal nodeLiteral = soln.get("label").asLiteral();
|
||||
labels.add(nodeLiteral);
|
||||
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e, e);
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Putting this into a method allows overriding it in subclasses
|
||||
protected String getEditForm() {
|
||||
return null;
|
||||
//return AddEditWebpageFormGenerator.class.getName();
|
||||
}
|
||||
|
||||
|
||||
protected String getTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//get locales
|
||||
public List<HashMap<String, String>> getLocales(VitroRequest vreq) {
|
||||
List<Locale> selectables = SelectedLocale.getSelectableLocales(vreq);
|
||||
if (selectables.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
|
||||
Locale currentLocale = SelectedLocale.getCurrentLocale(vreq);
|
||||
for (Locale locale : selectables) {
|
||||
try {
|
||||
list.add(buildLocaleMap(locale, currentLocale));
|
||||
} catch (FileNotFoundException e) {
|
||||
log.warn("Can't show the Locale selector for '" + locale
|
||||
+ "': " + e);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public HashMap<String, String> getFullCodeToLanguageNameMap(List<HashMap<String, String>> localesList) {
|
||||
HashMap<String, String> codeToLanguageMap = new HashMap<String, String>();
|
||||
for(Map<String, String> locale: localesList) {
|
||||
String code = (String) locale.get("code");
|
||||
String label = (String) locale.get("label");
|
||||
if(!codeToLanguageMap.containsKey(code)) {
|
||||
codeToLanguageMap.put(code, label);
|
||||
}
|
||||
else {
|
||||
log.warn("Language code " + code + " for " + label + " was not associated in map becayse label already exists");
|
||||
}
|
||||
}
|
||||
return codeToLanguageMap;
|
||||
}
|
||||
|
||||
public List<String> getFullLanguagesNamesSortedList(List<Map<String, Object>> localesList) {
|
||||
HashSet<String> languageNamesSet = new HashSet<String>();
|
||||
for(Map<String, Object> locale: localesList) {
|
||||
String label = (String) locale.get("label");
|
||||
if(!languageNamesSet.contains(label)) {
|
||||
languageNamesSet.add(label);
|
||||
}
|
||||
|
||||
}
|
||||
List<String> languageNames = new ArrayList<String>(languageNamesSet);
|
||||
Collections.sort(languageNames);
|
||||
return languageNames;
|
||||
}
|
||||
|
||||
//copied from locale selection data getter but don't need all this information
|
||||
private HashMap<String, String> buildLocaleMap(Locale locale,
|
||||
Locale currentLocale) throws FileNotFoundException {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
//Replacing the underscore with a hyphen because that is what is represented in the actual literals
|
||||
map.put("code", locale.toString().replace("_", "-"));
|
||||
map.put("label", locale.getDisplayName(currentLocale));
|
||||
return map;
|
||||
}
|
||||
|
||||
//Class used to store the information needed for the template, such as the labels, their languages, their edit links
|
||||
public class LabelInformation {
|
||||
private Literal labelLiteral = null;
|
||||
private String editLinkURL;
|
||||
private String deleteLinkURL;
|
||||
private String languageCode; //languageCode
|
||||
private String languageName;
|
||||
public LabelInformation(Literal inputLiteral, String inputEditLinkURL, String inputDeleteLinkURL, String inputLanguageCode, String inputLanguageName) {
|
||||
this.labelLiteral = inputLiteral;
|
||||
this.editLinkURL = inputEditLinkURL;
|
||||
this.deleteLinkURL = inputDeleteLinkURL;
|
||||
this.languageCode = inputLanguageCode;
|
||||
this.languageName = inputLanguageName;
|
||||
}
|
||||
|
||||
|
||||
public Literal getLabelLiteral() {
|
||||
return this.labelLiteral;
|
||||
}
|
||||
|
||||
public String getLabelStringValue() {
|
||||
return this.labelLiteral.getString();
|
||||
}
|
||||
|
||||
public String getEditLinkURL() {
|
||||
return this.editLinkURL;
|
||||
}
|
||||
|
||||
public String getDeleteLinkURL() {
|
||||
return this.deleteLinkURL;
|
||||
}
|
||||
public String getLanguageCode() {
|
||||
return this.languageCode;
|
||||
}
|
||||
|
||||
public String getLanguageName() {
|
||||
return this.languageName;
|
||||
}
|
||||
}
|
||||
|
||||
private String N3_PREFIX = "@prefix foaf:<http://xmlns.com/foaf/0.1/> .\n";
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocess
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.ResIterator;
|
||||
|
@ -30,7 +31,21 @@ public class FoafNameToRdfsLabelPreprocessor implements ModelChangePreprocessor
|
|||
Statement fname = sub.getProperty( firstNameP );
|
||||
Statement lname = sub.getProperty( lastNameP );
|
||||
if( fname != null && lname != null && fname.getString() != null && lname.getString() != null ){
|
||||
additionsModel.add(sub, rdfsLabelP, lname.getString() + ", " + fname.getString() );
|
||||
//Check if there are languages associated with first name and last name and add the language
|
||||
//attribute to the label
|
||||
//This preprocessor is used in multiple places, including for managing labels
|
||||
Literal firstNameLiteral = fname.getLiteral();
|
||||
Literal lastNameLiteral = lname.getLiteral();
|
||||
String firstNameLanguage = firstNameLiteral.getLanguage();
|
||||
String lastNameLanguage = lastNameLiteral.getLanguage();
|
||||
String newLabel = lname.getString() + ", " + fname.getString();
|
||||
if(firstNameLanguage != null && lastNameLanguage != null && firstNameLanguage.equals(lastNameLanguage)) {
|
||||
//create a literal with the appropriate value and the language
|
||||
Literal labelWithLanguage = additionsModel.createLiteral(newLabel, firstNameLanguage);
|
||||
additionsModel.add(sub, rdfsLabelP, labelWithLanguage);
|
||||
} else {
|
||||
additionsModel.add(sub, rdfsLabelP, newLabel );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.ResIterator;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
/*
|
||||
* This preprocessor is used to set the language attribute on the label based on the user selection
|
||||
* on the manage labels page when adding a new label.
|
||||
*/
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.BaseEditSubmissionPreprocessorVTwo;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.MultiValueEditSubmission;
|
||||
|
||||
public class ManageLabelsForIndividualPreprocessor extends BaseEditSubmissionPreprocessorVTwo {
|
||||
|
||||
|
||||
|
||||
|
||||
public ManageLabelsForIndividualPreprocessor(EditConfigurationVTwo editConfig) {
|
||||
super(editConfig);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocess(MultiValueEditSubmission inputSubmission) {
|
||||
//Check and see if a language was selected by the user, and this is the regular label submission
|
||||
//TODO: Check if firstname and lastname should be changed here or elsewhere
|
||||
if(inputSubmission.hasLiteralValue("label") && inputSubmission.hasLiteralValue("newLabelLanguage")) {
|
||||
Map<String, List<Literal>> literalsFromForm = inputSubmission.getLiteralsFromForm();
|
||||
List<Literal> newLabelLanguages = literalsFromForm.get("newLabelLanguage");
|
||||
List<Literal> labels = literalsFromForm.get("label");
|
||||
|
||||
//Expecting only one language
|
||||
if(labels.size() > 0 && newLabelLanguages.size() > 0) {
|
||||
Literal newLabelLanguage = newLabelLanguages.get(0);
|
||||
Literal labelLiteral = labels.get(0);
|
||||
//Get the string
|
||||
String lang = this.getLanguage(newLabelLanguage.getString());
|
||||
String label = labelLiteral.getString();
|
||||
//Now add the language category to the literal
|
||||
Literal labelWithLanguage = inputSubmission.createLiteral(label,
|
||||
newLabelLanguage.getDatatypeURI(),
|
||||
lang);
|
||||
labels = new ArrayList<Literal>();
|
||||
labels.add(labelWithLanguage);
|
||||
//replace the label with one with language, again assuming only one label being returned
|
||||
literalsFromForm.put("label", labels);
|
||||
inputSubmission.setLiteralsFromForm(literalsFromForm);
|
||||
}
|
||||
}
|
||||
//First name and last name would also have a language selected so make sure those literals are also
|
||||
//correctly typed
|
||||
if(inputSubmission.hasLiteralValue("firstName") && inputSubmission.hasLiteralValue("lastName") && inputSubmission.hasLiteralValue("newLabelLanguage")) {
|
||||
Map<String, List<Literal>> literalsFromForm = inputSubmission.getLiteralsFromForm();
|
||||
List<Literal> newLabelLanguages = literalsFromForm.get("newLabelLanguage");
|
||||
List<Literal> firstNames = literalsFromForm.get("firstName");
|
||||
List<Literal> lastNames = literalsFromForm.get("lastName");
|
||||
|
||||
//Expecting only one language
|
||||
if(firstNames.size() > 0 && lastNames.size() > 0 && newLabelLanguages.size() > 0) {
|
||||
Literal newLabelLanguage = newLabelLanguages.get(0);
|
||||
Literal firstNameLiteral = firstNames.get(0);
|
||||
Literal lastNameLiteral = lastNames.get(0);
|
||||
//Get the string
|
||||
String lang = this.getLanguage(newLabelLanguage.getString());
|
||||
String firstNameValue = firstNameLiteral.getString();
|
||||
String lastNameValue = lastNameLiteral.getString();
|
||||
//Now add the language category to the literal
|
||||
Literal firstNameWithLanguage = inputSubmission.createLiteral(firstNameValue,
|
||||
null,
|
||||
lang);
|
||||
Literal lastNameWithLanguage = inputSubmission.createLiteral(lastNameValue,
|
||||
null,
|
||||
lang);
|
||||
firstNames = new ArrayList<Literal>();
|
||||
lastNames = new ArrayList<Literal>();
|
||||
firstNames.add(firstNameWithLanguage);
|
||||
lastNames.add(lastNameWithLanguage);
|
||||
//replace the label with one with language, again assuming only one label being returned
|
||||
literalsFromForm.put("firstName", firstNames);
|
||||
literalsFromForm.put("lastName", lastNames);
|
||||
inputSubmission.setLiteralsFromForm(literalsFromForm);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//The language code returned from JAVA locales has an underscore whereas we need a hyphen
|
||||
private String getLanguage(String inputLanguageCode) {
|
||||
if(inputLanguageCode.contains("_")) {
|
||||
return inputLanguageCode.replace("_", "-");
|
||||
}
|
||||
return inputLanguageCode;
|
||||
}
|
||||
|
||||
}
|
|
@ -25,9 +25,9 @@ import org.apache.commons.logging.LogFactory;
|
|||
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
import freemarker.template.Configuration;
|
||||
|
||||
/**
|
||||
* A factory that creates Freemarker-based email messages.
|
||||
|
@ -59,8 +59,7 @@ public class FreemarkerEmailFactory {
|
|||
}
|
||||
|
||||
FreemarkerEmailFactory factory = getFactory(vreq);
|
||||
FreemarkerConfiguration fConfig = FreemarkerConfigurationLoader
|
||||
.getConfig(vreq);
|
||||
Configuration fConfig = FreemarkerConfiguration.getConfig(vreq);
|
||||
return new FreemarkerEmailMessage(vreq, fConfig,
|
||||
factory.getEmailSession(), factory.getReplyToAddress());
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.TemplateException;
|
||||
|
||||
/**
|
||||
|
@ -49,7 +49,7 @@ public class FreemarkerEmailMessage {
|
|||
|
||||
private final VitroRequest vreq;
|
||||
private final Session mailSession;
|
||||
private final FreemarkerConfiguration config;
|
||||
private final Configuration config;
|
||||
|
||||
private final List<Recipient> recipients = new ArrayList<Recipient>();
|
||||
private final InternetAddress replyToAddress;
|
||||
|
@ -64,7 +64,7 @@ public class FreemarkerEmailMessage {
|
|||
/**
|
||||
* Package access - should only be created by the factory.
|
||||
*/
|
||||
FreemarkerEmailMessage(VitroRequest vreq, FreemarkerConfiguration fConfig,
|
||||
FreemarkerEmailMessage(VitroRequest vreq, Configuration fConfig,
|
||||
Session mailSession, InternetAddress replyToAddress) {
|
||||
this.vreq = vreq;
|
||||
this.mailSession = mailSession;
|
||||
|
|
|
@ -131,6 +131,7 @@ public class RequestModelsPrep implements Filter {
|
|||
VitroRequest vreq = new VitroRequest(req);
|
||||
|
||||
vreq.setUnfilteredRDFService(rawRdfService);
|
||||
vreq.setUnfilteredDataset(new RDFServiceDataset(rawRdfService));
|
||||
|
||||
List<String> langs = getPreferredLanguages(req);
|
||||
RDFService rdfService = addLanguageAwareness(langs, rawRdfService);
|
||||
|
|
|
@ -0,0 +1,293 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.freemarker.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.DelimitingTemplateLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FlatteningTemplateLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants;
|
||||
import edu.cornell.mannlib.vitro.webapp.i18n.freemarker.I18nMethodModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.directives.IndividualShortViewDirective;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.directives.UrlDirective;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.directives.WidgetDirective;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualLocalNameMethod;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualPlaceholderImageUrlMethod;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualProfileUrlMethod;
|
||||
import freemarker.cache.ClassTemplateLoader;
|
||||
import freemarker.cache.FileTemplateLoader;
|
||||
import freemarker.cache.MultiTemplateLoader;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import freemarker.ext.beans.BeansWrapper;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapper;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModelException;
|
||||
|
||||
/**
|
||||
* Access point for a singleton Configuration instance.
|
||||
*
|
||||
* The instance is created at system startup, so we can fail early if there are
|
||||
* any problems.
|
||||
*
|
||||
* The Configuration is slightly extended to hold request-based information in a
|
||||
* ThreadLocal. The net result is although there is only one configuration (and
|
||||
* hence only one template cache), each request gets a customization with its
|
||||
* own locale, etc.
|
||||
*
|
||||
* Each time a request asks for the configuration, check to see whether the
|
||||
* cache is still valid, and whether the theme has changed (needs a new
|
||||
* TemplateLoader). Store the request info to the ThreadLocal.
|
||||
*/
|
||||
public abstract class FreemarkerConfiguration {
|
||||
private static final Log log = LogFactory
|
||||
.getLog(FreemarkerConfiguration.class);
|
||||
|
||||
private static final String PROPERTY_DEFEAT_CACHE = "developer.defeatFreemarkerCache";
|
||||
private static final String PROPERTY_INSERT_DELIMITERS = "developer.insertFreemarkerDelimiters";
|
||||
|
||||
private static volatile FreemarkerConfigurationImpl instance;
|
||||
private static volatile String previousThemeDir;
|
||||
|
||||
public static Configuration getConfig(HttpServletRequest req) {
|
||||
confirmInstanceIsSet();
|
||||
|
||||
synchronized (instance) {
|
||||
clearTemplateCacheIfRequested(req);
|
||||
keepTemplateLoaderCurrentWithThemeDirectory(req);
|
||||
setThreadLocalsForRequest(req);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static void confirmInstanceIsSet() {
|
||||
if (instance == null) {
|
||||
throw new IllegalStateException(
|
||||
"VitroFreemarkerConfiguration has not been set.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void clearTemplateCacheIfRequested(HttpServletRequest req) {
|
||||
if (isTemplateCacheInvalid(req)) {
|
||||
instance.clearTemplateCache();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isTemplateCacheInvalid(HttpServletRequest req) {
|
||||
ConfigurationProperties props = ConfigurationProperties.getBean(req);
|
||||
|
||||
// If the developer doesn't want the cache, it's invalid.
|
||||
if (Boolean.valueOf(props.getProperty(PROPERTY_DEFEAT_CACHE))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of the theme directory. If it changes, create an appropriate
|
||||
* new TemplateLoader.
|
||||
*
|
||||
* Note that setting a new TemplateLoader on the context Configuration also
|
||||
* creates a new, empty TemplateCache.
|
||||
*/
|
||||
private static void keepTemplateLoaderCurrentWithThemeDirectory(
|
||||
HttpServletRequest req) {
|
||||
String themeDir = getThemeDirectory(req);
|
||||
if (hasThemeDirectoryChanged(themeDir)) {
|
||||
TemplateLoader tl = createTemplateLoader(req, themeDir);
|
||||
instance.setTemplateLoader(tl);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getThemeDirectory(HttpServletRequest req) {
|
||||
return new VitroRequest(req).getAppBean().getThemeDir();
|
||||
}
|
||||
|
||||
private static boolean hasThemeDirectoryChanged(String themeDir) {
|
||||
synchronized (instance) {
|
||||
if (StringUtils.equals(themeDir, previousThemeDir)) {
|
||||
return false;
|
||||
} else {
|
||||
previousThemeDir = themeDir;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TemplateLoader createTemplateLoader(HttpServletRequest req,
|
||||
String themeDir) {
|
||||
ServletContext ctx = req.getSession().getServletContext();
|
||||
ConfigurationProperties props = ConfigurationProperties.getBean(ctx);
|
||||
|
||||
List<TemplateLoader> loaders = new ArrayList<TemplateLoader>();
|
||||
|
||||
// Theme template loader
|
||||
String themeTemplatePath = ctx.getRealPath(themeDir) + "/templates";
|
||||
File themeTemplateDir = new File(themeTemplatePath);
|
||||
// A theme need not contain a template directory.
|
||||
if (themeTemplateDir.exists()) {
|
||||
try {
|
||||
FileTemplateLoader themeFtl = new FileTemplateLoader(
|
||||
themeTemplateDir);
|
||||
loaders.add(themeFtl);
|
||||
} catch (IOException e) {
|
||||
log.error("Error creating theme template loader", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Vitro template loader
|
||||
String vitroTemplatePath = ctx.getRealPath("/templates/freemarker");
|
||||
loaders.add(new FlatteningTemplateLoader(new File(vitroTemplatePath)));
|
||||
|
||||
// TODO VIVO-243 Why is this here?
|
||||
loaders.add(new ClassTemplateLoader(FreemarkerConfiguration.class, ""));
|
||||
|
||||
TemplateLoader[] loaderArray = loaders
|
||||
.toArray(new TemplateLoader[loaders.size()]);
|
||||
MultiTemplateLoader mtl = new MultiTemplateLoader(loaderArray);
|
||||
|
||||
// If requested, add delimiters to the templates.
|
||||
if (Boolean.valueOf(props.getProperty(PROPERTY_INSERT_DELIMITERS))) {
|
||||
return new DelimitingTemplateLoader(mtl);
|
||||
} else {
|
||||
return mtl;
|
||||
}
|
||||
}
|
||||
|
||||
private static void setThreadLocalsForRequest(HttpServletRequest req) {
|
||||
instance.setRequestInfo(req);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Setup class
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
public static class Setup implements ServletContextListener {
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext ctx = sce.getServletContext();
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
try {
|
||||
instance = createConfiguration(ctx);
|
||||
ss.info(this, "Initialized the Freemarker configuration.");
|
||||
} catch (Exception e) {
|
||||
ss.fatal(this,
|
||||
"Failed to initialize the Freemarker configuration.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private FreemarkerConfigurationImpl createConfiguration(
|
||||
ServletContext ctx) throws TemplateModelException {
|
||||
FreemarkerConfigurationImpl c = new FreemarkerConfigurationImpl();
|
||||
|
||||
setMiscellaneousProperties(c);
|
||||
setSharedVariables(c, ctx);
|
||||
addDirectives(c);
|
||||
addMethods(c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private void setMiscellaneousProperties(FreemarkerConfigurationImpl c) {
|
||||
/*
|
||||
* Lengthen the cache time.
|
||||
*/
|
||||
c.setTemplateUpdateDelay(60); // increase from the 5-second default
|
||||
|
||||
/*
|
||||
* On most template models, hide the getters and setters that take
|
||||
* arguments.
|
||||
*/
|
||||
BeansWrapper wrapper = new DefaultObjectWrapper();
|
||||
wrapper.setExposureLevel(BeansWrapper.EXPOSE_PROPERTIES_ONLY);
|
||||
c.setObjectWrapper(wrapper);
|
||||
|
||||
/*
|
||||
* Set a default Locale, but expect it to be overridden by the
|
||||
* request.
|
||||
*/
|
||||
c.setLocale(java.util.Locale.US);
|
||||
|
||||
/*
|
||||
* This is how we like our date and time strings to look.
|
||||
*/
|
||||
String dateFormat = "M/d/yyyy";
|
||||
c.setDateFormat(dateFormat);
|
||||
String timeFormat = "h:mm a";
|
||||
c.setTimeFormat(timeFormat);
|
||||
c.setDateTimeFormat(dateFormat + " " + timeFormat);
|
||||
|
||||
/*
|
||||
* What character set is used when escaping special characters in a
|
||||
* URL?
|
||||
*/
|
||||
try {
|
||||
c.setSetting("url_escaping_charset", "UTF-8");
|
||||
} catch (TemplateException e) {
|
||||
log.error("Error setting value for url_escaping_charset.");
|
||||
}
|
||||
}
|
||||
|
||||
private void setSharedVariables(FreemarkerConfigurationImpl c,
|
||||
ServletContext ctx) throws TemplateModelException {
|
||||
c.setSharedVariable("version", getRevisionInfo(ctx));
|
||||
|
||||
/*
|
||||
* Put in edit configuration constants - useful for freemarker
|
||||
* templates/editing
|
||||
*/
|
||||
c.setSharedVariable("editConfigurationConstants",
|
||||
EditConfigurationConstants.exportConstants());
|
||||
}
|
||||
|
||||
private void addDirectives(FreemarkerConfigurationImpl c) {
|
||||
c.setSharedVariable("dump", new freemarker.ext.dump.DumpDirective());
|
||||
c.setSharedVariable("dumpAll",
|
||||
new freemarker.ext.dump.DumpAllDirective());
|
||||
c.setSharedVariable("help", new freemarker.ext.dump.HelpDirective());
|
||||
c.setSharedVariable("shortView", new IndividualShortViewDirective());
|
||||
c.setSharedVariable("url", new UrlDirective());
|
||||
c.setSharedVariable("widget", new WidgetDirective());
|
||||
}
|
||||
|
||||
private void addMethods(FreemarkerConfigurationImpl c) {
|
||||
c.setSharedVariable("profileUrl", new IndividualProfileUrlMethod());
|
||||
c.setSharedVariable("localName", new IndividualLocalNameMethod());
|
||||
c.setSharedVariable("placeholderImageUrl",
|
||||
new IndividualPlaceholderImageUrlMethod());
|
||||
c.setSharedVariable("i18n", new I18nMethodModel());
|
||||
}
|
||||
|
||||
private Map<String, Object> getRevisionInfo(ServletContext ctx) {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("label", RevisionInfoBean.getBean(ctx).getReleaseLabel());
|
||||
map.put("moreInfoUrl", UrlBuilder.getUrl("/revisionInfo"));
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.freemarker.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||
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.utils.dataGetter.DataGetter;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.ObjectWrapper;
|
||||
import freemarker.template.SimpleScalar;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateModel;
|
||||
import freemarker.template.TemplateModelException;
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
public class FreemarkerConfigurationImpl extends Configuration {
|
||||
private static final Log log = LogFactory
|
||||
.getLog(FreemarkerConfigurationImpl.class);
|
||||
|
||||
private final ThreadLocal<RequestBasedInformation> rbiRef = new ThreadLocal<>();
|
||||
|
||||
void setRequestInfo(HttpServletRequest req) {
|
||||
rbiRef.set(new RequestBasedInformation(req, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCustomAttribute(String name) {
|
||||
Map<String, Object> attribs = rbiRef.get().getCustomAttributes();
|
||||
if (attribs.containsKey(name)) {
|
||||
return attribs.get(name);
|
||||
} else {
|
||||
return super.getCustomAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCustomAttributeNames() {
|
||||
Set<String> rbiNames = rbiRef.get().getCustomAttributes().keySet();
|
||||
return joinNames(rbiNames, super.getCustomAttributeNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateModel getSharedVariable(String name) {
|
||||
Map<String, TemplateModel> vars = rbiRef.get().getSharedVariables();
|
||||
if (vars.containsKey(name)) {
|
||||
return vars.get(name);
|
||||
} else {
|
||||
return super.getSharedVariable(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSharedVariableNames() {
|
||||
Set<String> rbiNames = rbiRef.get().getSharedVariables().keySet();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> superNames = super.getSharedVariableNames();
|
||||
|
||||
Set<String> allNames = new HashSet<>(superNames);
|
||||
allNames.addAll(rbiNames);
|
||||
return allNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return rbiRef.get().getReq().getLocale();
|
||||
}
|
||||
|
||||
private String[] joinNames(Set<String> nameSet, String[] nameArray) {
|
||||
Set<String> allNames = new HashSet<>(nameSet);
|
||||
for (String n : nameArray) {
|
||||
allNames.add(n);
|
||||
}
|
||||
return (String[]) allNames.toArray();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Apply DataGetters to templates when loading.
|
||||
//
|
||||
// TODO Clean this up VIVO-249
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Override getTemplate(), so we can apply DataGetters to all included
|
||||
* templates.
|
||||
*
|
||||
* This won't work for top-level Templates, since the Environment hasn't
|
||||
* been created yet. When TemplateProcessingHelper creates the Environment,
|
||||
* it must call retrieveAndRunDataGetters() for the top-level Template.
|
||||
*/
|
||||
@Override
|
||||
public Template getTemplate(String name, Locale locale, String encoding,
|
||||
boolean parse) throws IOException {
|
||||
Template template = super.getTemplate(name, locale, encoding, parse);
|
||||
|
||||
if (template == null) {
|
||||
log.debug("Template '" + name + "' not found for locale '" + locale
|
||||
+ "'.");
|
||||
return template;
|
||||
}
|
||||
|
||||
Environment env = getEnvironment();
|
||||
if (env == null) {
|
||||
log.debug("Not fetching data getters for template '"
|
||||
+ template.getName() + "'. No environment.");
|
||||
return template;
|
||||
}
|
||||
|
||||
retrieveAndRunDataGetters(env, template.getName());
|
||||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the DataGetters for this template, and apply them to the Freemarker
|
||||
* environment.
|
||||
*/
|
||||
public static void retrieveAndRunDataGetters(Environment env,
|
||||
String templateName) {
|
||||
HttpServletRequest req = (HttpServletRequest) env
|
||||
.getCustomAttribute("request");
|
||||
VitroRequest vreq = new VitroRequest(req);
|
||||
|
||||
if (dataGettersAlreadyApplied(env, templateName)) {
|
||||
log.debug("DataGetters for '" + templateName
|
||||
+ "' have already been applied");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<DataGetter> dgList = DataGetterUtils
|
||||
.getDataGettersForTemplate(vreq, vreq.getDisplayModel(),
|
||||
templateName);
|
||||
log.debug("Retrieved " + dgList.size()
|
||||
+ " data getters for template '" + templateName + "'");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> dataMap = (Map<String, Object>) DeepUnwrap
|
||||
.permissiveUnwrap(env.getDataModel());
|
||||
for (DataGetter dg : dgList) {
|
||||
applyDataGetter(dg, env, dataMap);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn(e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the DataGetters for this template already been applied to this
|
||||
* environment? If not, record that they are being applied now.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static boolean dataGettersAlreadyApplied(Environment env,
|
||||
String templateName) {
|
||||
Set<String> names;
|
||||
Object o = env.getCustomAttribute("dataGettersApplied");
|
||||
if (o instanceof Set) {
|
||||
names = (Set<String>) o;
|
||||
} else {
|
||||
names = new HashSet<String>();
|
||||
}
|
||||
|
||||
boolean added = names.add(templateName);
|
||||
if (added) {
|
||||
env.setCustomAttribute("dataGettersApplied", names);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data from a DataGetter, and store it in global variables in the
|
||||
* Freemarker environment.
|
||||
*/
|
||||
private static void applyDataGetter(DataGetter dg, Environment env,
|
||||
Map<String, Object> dataMap) throws TemplateModelException {
|
||||
Map<String, Object> moreData = dg.getData(dataMap);
|
||||
ObjectWrapper wrapper = env.getObjectWrapper();
|
||||
if (moreData != null) {
|
||||
for (String key : moreData.keySet()) {
|
||||
Object value = moreData.get(key);
|
||||
env.setGlobalVariable(key, wrapper.wrap(value));
|
||||
log.debug("Stored in environment: '" + key + "' = '" + value
|
||||
+ "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Helper class
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Holds the request-based information. Currently, it's shared variables, a
|
||||
* custom attribute, and the locale. In the future, it could be more.
|
||||
*/
|
||||
private static class RequestBasedInformation {
|
||||
private final HttpServletRequest req;
|
||||
private final Configuration c;
|
||||
private final Map<String, Object> customAttributes = new HashMap<>();
|
||||
private final Map<String, TemplateModel> sharedVariables = new HashMap<>();
|
||||
|
||||
public RequestBasedInformation(HttpServletRequest req, Configuration c) {
|
||||
this.req = req;
|
||||
this.c = c;
|
||||
|
||||
setSharedVariables(req);
|
||||
setCustomAttributes(req);
|
||||
}
|
||||
|
||||
public HttpServletRequest getReq() {
|
||||
return req;
|
||||
}
|
||||
|
||||
public Map<String, Object> getCustomAttributes() {
|
||||
return customAttributes;
|
||||
}
|
||||
|
||||
public Map<String, TemplateModel> getSharedVariables() {
|
||||
return sharedVariables;
|
||||
}
|
||||
|
||||
private void setSharedVariables(HttpServletRequest req) {
|
||||
ServletContext ctx = req.getSession().getServletContext();
|
||||
VitroRequest vreq = new VitroRequest(req);
|
||||
ApplicationBean appBean = vreq.getAppBean();
|
||||
String siteName = appBean.getApplicationName();
|
||||
String tagLine = appBean.getShortHand();
|
||||
String themeDir = appBean.getThemeDir().replaceAll("/$", "");
|
||||
String currentTheme = themeDir
|
||||
.substring(themeDir.lastIndexOf('/') + 1);
|
||||
Map<String, String> siteUrls = getSiteUrls(ctx, themeDir);
|
||||
|
||||
sharedVariables.put("siteName", wrap(siteName));
|
||||
sharedVariables.put("themeDir", wrap(themeDir));
|
||||
sharedVariables.put("currentTheme", wrap(currentTheme));
|
||||
sharedVariables.put("siteTagline", wrap(tagLine));
|
||||
sharedVariables.put("urls", wrap(siteUrls));
|
||||
}
|
||||
|
||||
private Map<String, String> getSiteUrls(ServletContext ctx,
|
||||
String themeDir) {
|
||||
Map<String, String> urls = new HashMap<String, String>();
|
||||
|
||||
// Templates use this to construct urls.
|
||||
urls.put("base", ctx.getContextPath());
|
||||
urls.put("home", UrlBuilder.getHomeUrl());
|
||||
urls.put("about", UrlBuilder.getUrl(Route.ABOUT));
|
||||
urls.put("search", UrlBuilder.getUrl(Route.SEARCH));
|
||||
urls.put("termsOfUse", UrlBuilder.getUrl(Route.TERMS_OF_USE));
|
||||
urls.put("login", UrlBuilder.getLoginUrl());
|
||||
urls.put("logout", UrlBuilder.getLogoutUrl());
|
||||
urls.put("siteAdmin", UrlBuilder.getUrl(Route.SITE_ADMIN));
|
||||
|
||||
urls.put("themeImages", UrlBuilder.getUrl(themeDir + "/images"));
|
||||
urls.put("images", UrlBuilder.getUrl("/images"));
|
||||
urls.put("theme", UrlBuilder.getUrl(themeDir));
|
||||
urls.put("index", UrlBuilder.getUrl("/browse"));
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
private TemplateModel wrap(Object o) {
|
||||
try {
|
||||
return c.getObjectWrapper().wrap(o);
|
||||
} catch (TemplateModelException e) {
|
||||
log.error("Failed to wrap this "
|
||||
+ "for the Freemarker configuration: " + o, e);
|
||||
return new SimpleScalar(String.valueOf(o));
|
||||
}
|
||||
}
|
||||
|
||||
private void setCustomAttributes(HttpServletRequest req) {
|
||||
customAttributes.put("request", req);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -60,11 +60,11 @@ public class LocaleSelectionDataGetter implements DataGetter {
|
|||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("selectLocaleUrl", UrlBuilder.getUrl("/selectLocale"));
|
||||
result.put("locales", buildLocalesList(selectables));
|
||||
|
||||
Map<String, Object> bodyMap = new HashMap<String, Object>();
|
||||
Map<String, Object> bodyMap = new HashMap<>();
|
||||
bodyMap.put("selectLocale", result);
|
||||
log.debug("Sending these values: " + bodyMap);
|
||||
return bodyMap;
|
||||
|
@ -72,7 +72,7 @@ public class LocaleSelectionDataGetter implements DataGetter {
|
|||
|
||||
private List<Map<String, Object>> buildLocalesList(List<Locale> selectables) {
|
||||
Locale currentLocale = SelectedLocale.getCurrentLocale(vreq);
|
||||
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (Locale locale : selectables) {
|
||||
try {
|
||||
list.add(buildLocaleMap(locale, currentLocale));
|
||||
|
@ -86,10 +86,12 @@ public class LocaleSelectionDataGetter implements DataGetter {
|
|||
|
||||
private Map<String, Object> buildLocaleMap(Locale locale,
|
||||
Locale currentLocale) throws FileNotFoundException {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("code", locale.toString());
|
||||
map.put("label", locale.getDisplayName(currentLocale));
|
||||
map.put("imageUrl", LocaleSelectorUtilities.getImageUrl(vreq, locale));
|
||||
map.put("selected", currentLocale.equals(locale));
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,58 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.reasoner.plugin;
|
||||
|
||||
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.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.reasoner.ReasonerPlugin;
|
||||
import edu.cornell.mannlib.vitro.webapp.reasoner.SimpleReasoner;
|
||||
|
||||
/**
|
||||
* Disables sameAs in associated SimpleReasoner.
|
||||
*/
|
||||
public abstract class DisableSameAs implements ReasonerPlugin {
|
||||
|
||||
private static final Log log = LogFactory.getLog(DisableSameAs.class);
|
||||
|
||||
private SimpleReasoner simpleReasoner;
|
||||
|
||||
public void setSimpleReasoner(SimpleReasoner simpleReasoner) {
|
||||
this.simpleReasoner = simpleReasoner;
|
||||
this.simpleReasoner.setSameAsEnabled( false );
|
||||
log.info("owl:sameAs disabled in SimpleReasoner.");
|
||||
}
|
||||
|
||||
public SimpleReasoner getSimpleReasoner() {
|
||||
return this.simpleReasoner;
|
||||
}
|
||||
|
||||
public boolean isInterestedInAddedStatement(Statement stmt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isInterestedInRemovedStatement(Statement stmt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addedABoxStatement(Statement stmt,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel,
|
||||
OntModel TBoxInferencesModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public void removedABoxStatement(Statement stmt,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel,
|
||||
OntModel TBoxInferencesModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,12 +3,10 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.search.beans;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase;
|
||||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.RDFFilesLoader;
|
||||
|
||||
public class FileBasedProhibitedFromSearch extends ProhibitedFromSearch {
|
||||
|
||||
|
@ -19,7 +17,7 @@ public class FileBasedProhibitedFromSearch extends ProhibitedFromSearch {
|
|||
* @param dir to find N3 files in.
|
||||
*/
|
||||
public FileBasedProhibitedFromSearch(String uri, File dir){
|
||||
super( uri, JenaDataSourceSetupBase.getModelFromDir(dir));
|
||||
super( uri, RDFFilesLoader.getModelFromDir(dir));
|
||||
}
|
||||
|
||||
public FileBasedProhibitedFromSearch(String URI, OntModel model) {
|
||||
|
|
|
@ -43,7 +43,7 @@ public class SearchServiceController extends FreemarkerHttpServlet {
|
|||
* userAccount associated with the email.
|
||||
*/
|
||||
@Override
|
||||
protected Actions requiredActions(VitroRequest vreq) {
|
||||
public Actions requiredActions(VitroRequest vreq) {
|
||||
try{
|
||||
// Works by side effect: parse the multi-part request and stash FileItems in request
|
||||
FileUploadServletRequest.parseRequest(vreq, 0);
|
||||
|
@ -52,42 +52,21 @@ public class SearchServiceController extends FreemarkerHttpServlet {
|
|||
String pw = vreq.getParameter("password");
|
||||
String email = vreq.getParameter("email");
|
||||
|
||||
log.debug(String.format("email: '%s' password: '%s' ",email,pw));
|
||||
|
||||
if( pw == null || email == null || pw.isEmpty() || email.isEmpty()){
|
||||
return SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS;
|
||||
}
|
||||
|
||||
Authenticator basicAuth = new BasicAuthenticator(vreq);
|
||||
UserAccount user = basicAuth.getAccountForInternalAuth( email );
|
||||
log.debug("userAccount is " + user==null?"null":user.getUri() );
|
||||
|
||||
if( ! basicAuth.isCurrentPassword( user, pw ) ){
|
||||
log.debug(String.format("UNAUTHORIZED, password not accepted for %s, account URI: %s",
|
||||
user.getEmailAddress(), user.getUri()));
|
||||
return Actions.UNAUTHORIZED;
|
||||
}else{
|
||||
log.debug(String.format("password accepted for %s, account URI: %s",
|
||||
user.getEmailAddress(), user.getUri() ));
|
||||
}
|
||||
|
||||
//then figure out if that account can manage the search index.
|
||||
IdentifierBundle ids =
|
||||
ActiveIdentifierBundleFactories.getUserIdentifierBundle(vreq,user);
|
||||
PolicyIface policy = ServletPolicyList.getPolicies(vreq);
|
||||
boolean canManageSearchIndex =
|
||||
PolicyHelper.isAuthorizedForActions( ids, policy,
|
||||
SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS );
|
||||
if( canManageSearchIndex ){
|
||||
if( PolicyHelper.isAuthorizedForActions(vreq, email, pw,
|
||||
SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS ) ){
|
||||
return Actions.AUTHORIZED;
|
||||
}else{
|
||||
log.debug(String.format("userAccount is unauthorized to" +
|
||||
" manage the search index.",user.getUri()));
|
||||
log.debug(email + " is unauthorized to manage the search index. " +
|
||||
"client IP "+vreq.getClientAddr());
|
||||
return Actions.UNAUTHORIZED;
|
||||
}
|
||||
|
||||
}catch(Exception ex){
|
||||
log.error("Error while attempting to log in " +
|
||||
log.error("Error while client IP "+ vreq.getClientAddr() + " attempting to log in " +
|
||||
"to SearchServiceController: " + ex.getMessage());
|
||||
return Actions.UNAUTHORIZED;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -61,7 +59,10 @@ public class IndexBuilder extends VitroBackgroundThread {
|
|||
|
||||
/** Indicates that a stop of the indexing objects has been requested. */
|
||||
private volatile boolean stopRequested = false;
|
||||
|
||||
|
||||
/** Indicates that new updates should not be started. */
|
||||
private boolean deferNewUpdates = false;
|
||||
|
||||
/** Length of time to wait before looking for work (if not wakened sooner). */
|
||||
public static final long MAX_IDLE_INTERVAL = 1000 * 60 /* msec */ ;
|
||||
|
||||
|
@ -163,7 +164,7 @@ public class IndexBuilder extends VitroBackgroundThread {
|
|||
* This will re-index Individuals were added with addToChanged().
|
||||
*/
|
||||
public synchronized void doUpdateIndex() {
|
||||
log.debug("callto doUpdateIndex()");
|
||||
log.debug("call to doUpdateIndex()");
|
||||
//wake up thread and it will attempt to index anything in changedUris
|
||||
this.notifyAll();
|
||||
}
|
||||
|
@ -184,12 +185,33 @@ public class IndexBuilder extends VitroBackgroundThread {
|
|||
this.notifyAll();
|
||||
this.interrupt();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calling this will cause the IndexBuider to no start a new index update
|
||||
* until unpuase is called. This is intended to allow a large change
|
||||
* without slowing it down with incremental search index updates.
|
||||
*/
|
||||
public synchronized void pause(){
|
||||
this.deferNewUpdates = true;
|
||||
}
|
||||
|
||||
public synchronized void unpause(){
|
||||
if( deferNewUpdates == true ){
|
||||
this.deferNewUpdates = false;
|
||||
this.notifyAll();
|
||||
this.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(! stopRequested ){
|
||||
try{
|
||||
if( reindexRequested ){
|
||||
if ( deferNewUpdates ){
|
||||
log.debug("there is no indexing working to do, waiting for work");
|
||||
synchronized (this) { this.wait(MAX_IDLE_INTERVAL); }
|
||||
}
|
||||
else if ( reindexRequested ){
|
||||
setWorkLevel(WorkLevel.WORKING, FLAG_REBUILDING);
|
||||
log.debug("full re-index requested");
|
||||
|
||||
|
@ -198,7 +220,8 @@ public class IndexBuilder extends VitroBackgroundThread {
|
|||
notifyListeners( IndexingEventListener.EventTypes.FINISH_FULL_REBUILD );
|
||||
|
||||
setWorkLevel(WorkLevel.IDLE);
|
||||
}else{
|
||||
}
|
||||
else{
|
||||
boolean workToDo = false;
|
||||
synchronized (changedStmts ){
|
||||
workToDo = !changedStmts.isEmpty();
|
||||
|
|
|
@ -12,8 +12,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.log.LogUtils;
|
||||
import freemarker.core.ParseException;
|
||||
import freemarker.template.Configuration;
|
||||
|
@ -51,8 +50,7 @@ public class FreemarkerProcessingServiceImpl implements
|
|||
throws TemplateProcessingException {
|
||||
Template template = null;
|
||||
try {
|
||||
Configuration config = FreemarkerConfigurationLoader
|
||||
.getConfig(new VitroRequest(req));
|
||||
Configuration config = FreemarkerConfiguration.getConfig(req);
|
||||
template = config.getTemplate(templateName);
|
||||
} catch (ParseException e) {
|
||||
log.warn("Failed to parse the template at '" + templateName + "'"
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
/* $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.io.FileOutputStream;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
@ -11,14 +8,8 @@ import javax.sql.DataSource;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.query.Query;
|
||||
import com.hp.hpl.jena.query.QueryExecution;
|
||||
import com.hp.hpl.jena.query.QueryExecutionFactory;
|
||||
import com.hp.hpl.jena.query.QueryFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
|
||||
|
@ -58,16 +49,15 @@ implements ServletContextListener {
|
|||
try {
|
||||
Model displayDbModel = makeDBModel(bds,
|
||||
JENA_DISPLAY_METADATA_MODEL, DB_ONT_MODEL_SPEC, ctx);
|
||||
if (displayDbModel.size() == 0) {
|
||||
readOntologyFilesInPathSet(APPPATH, ctx,displayDbModel);
|
||||
}
|
||||
RDFFilesLoader.loadFirstTimeFiles(ctx, "display", displayDbModel, displayDbModel.isEmpty());
|
||||
|
||||
OntModel displayModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC);
|
||||
displayModel.add(displayDbModel);
|
||||
displayModel.getBaseModel().register(new ModelSynchronizer(displayDbModel));
|
||||
ModelAccess.on(ctx).setDisplayModel(displayModel);
|
||||
|
||||
//at each startup load all RDF files from directory to sub-models of display model
|
||||
initializeDisplayLoadedAtStartup(ctx, displayModel);
|
||||
//at each startup load all RDF files from directory to sub-models of display model
|
||||
RDFFilesLoader.loadEveryTimeFiles(ctx, "display", displayModel);
|
||||
} catch (Throwable t) {
|
||||
log.error("Unable to load user application configuration model", t);
|
||||
ss.fatal(this, "Unable to load user application configuration model", t);
|
||||
|
@ -78,158 +68,35 @@ implements ServletContextListener {
|
|||
Model displayTboxModel = makeDBModel(bds,
|
||||
JENA_DISPLAY_TBOX_MODEL, DB_ONT_MODEL_SPEC, ctx);
|
||||
|
||||
//Reading in single file every time, needs to be cleared/removed every time
|
||||
readOntologyFileFromPath(APPPATH_LOAD + "displayTBOX.n3", displayTboxModel, ctx);
|
||||
OntModel appTBOXModel = ModelFactory.createOntologyModel(
|
||||
MEM_ONT_MODEL_SPEC);
|
||||
OntModel appTBOXModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC);
|
||||
appTBOXModel.add(displayTboxModel);
|
||||
appTBOXModel.getBaseModel().register(new ModelSynchronizer(displayTboxModel));
|
||||
ModelAccess.on(ctx).setOntModel(ModelID.DISPLAY_TBOX, appTBOXModel);
|
||||
log.debug("Loaded file " + APPPATH_LOAD + "displayTBOX.n3 into display tbox model");
|
||||
|
||||
//Reading in every time, needs to be cleared/removed every time
|
||||
RDFFilesLoader.loadEveryTimeFiles(ctx, "displayTbox", appTBOXModel);
|
||||
} catch (Throwable t) {
|
||||
log.error("Unable to load user application configuration model TBOX", t);
|
||||
ss.fatal(this, "Unable to load user application configuration model TBOX", t);
|
||||
}
|
||||
|
||||
//Display Display model, currently empty, create if doesn't exist but no files to load
|
||||
//Display Display model, currently reading in every time
|
||||
try {
|
||||
Model displayDisplayModel = makeDBModel(bds,
|
||||
JENA_DISPLAY_DISPLAY_MODEL, DB_ONT_MODEL_SPEC, ctx);
|
||||
|
||||
//Reading in single file every time, needs to be cleared/removed every
|
||||
readOntologyFileFromPath(APPPATH_LOAD + "displayDisplay.n3", displayDisplayModel, ctx);
|
||||
OntModel appDisplayDisplayModel = ModelFactory.createOntologyModel(
|
||||
MEM_ONT_MODEL_SPEC);
|
||||
OntModel appDisplayDisplayModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC);
|
||||
appDisplayDisplayModel.add(displayDisplayModel);
|
||||
appDisplayDisplayModel.getBaseModel().register(new ModelSynchronizer(displayDisplayModel));
|
||||
ModelAccess.on(ctx).setOntModel(ModelID.DISPLAY_DISPLAY, appDisplayDisplayModel);
|
||||
log.debug("Loaded file " + APPPATH_LOAD + "displayDisplay.n3 into display display model");
|
||||
|
||||
//Reading in every time, needs to be cleared/removed every time
|
||||
RDFFilesLoader.loadEveryTimeFiles(ctx, "displayDisplay", appDisplayDisplayModel);
|
||||
} catch (Throwable t) {
|
||||
log.error("Unable to load user application configuration model Display Model", t);
|
||||
ss.fatal(this, "Unable to load user application configuration model Display Model", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the RDF found in the directory DISPLAY_MODEL_LOAD_AT_STARTUP_DIR
|
||||
* a sub-models of displayModel. The RDF from thes files will not be saved
|
||||
* in the database and it will be reloaded each time the system starts up.
|
||||
*/
|
||||
private void initializeDisplayLoadedAtStartup(ServletContext ctx, OntModel displayModel){
|
||||
log.info("loading display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) );
|
||||
Model displayLoadAtStartup = readInDisplayModelLoadAtStartup(ctx);
|
||||
|
||||
if( log.isDebugEnabled() ){
|
||||
log.debug("loaded display model from files in " + ctx.getRealPath(DISPLAY_MODEL_LOAD_AT_STARTUP_DIR) );
|
||||
displayLoadAtStartup.write(System.out, "N3-PP");
|
||||
}
|
||||
|
||||
checkForOldListViews(ctx,displayModel,displayLoadAtStartup);
|
||||
displayModel.addSubModel( displayLoadAtStartup );
|
||||
}
|
||||
|
||||
protected Model readInDisplayModelLoadAtStartup( ServletContext ctx ){
|
||||
return getModelFromDir( new File( ctx.getRealPath( DISPLAY_MODEL_LOAD_AT_STARTUP_DIR )));
|
||||
}
|
||||
|
||||
/**
|
||||
* All of the list views should now reside in files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR.
|
||||
* This will check for custom list view annotation statements in the displayModel, check
|
||||
* if they exist in the files in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR, and write any that don't
|
||||
* exist there to a file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR. After that the statements
|
||||
* will be removed from the displayDBModel.
|
||||
*
|
||||
* returns true if there were old list view statements in the DB, returns false
|
||||
* if there were none. displayLoadAlways should be reloaded from the file system
|
||||
* if this returns true as this method may have changed the files.
|
||||
*
|
||||
* displayLoadAtStartup and displayModel may be modified.
|
||||
*/
|
||||
private void checkForOldListViews( ServletContext ctx, OntModel displayModel, Model displayLoadAtStartup){
|
||||
// run construct for old custom list view statements from displayModel
|
||||
Model oldListViewModel = getOldListViewStatements( displayModel );
|
||||
if( log.isDebugEnabled() ){
|
||||
log.debug("Printing the old list view statements from the display model to System.out.");
|
||||
oldListViewModel.write(System.out,"N3-PP");
|
||||
}
|
||||
|
||||
// find statements in old stmts that are not in loadedAtStartup and
|
||||
// save them in a new file in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR
|
||||
// so that in the future they will be in loadedAtStartup
|
||||
Model stmtsInOldAndFiles = displayLoadAtStartup.intersection( displayModel );
|
||||
Model unhandledOldListViewStmts = oldListViewModel.difference( stmtsInOldAndFiles );
|
||||
|
||||
boolean saved = false;
|
||||
boolean neededSave = false;
|
||||
|
||||
if( unhandledOldListViewStmts != null && !unhandledOldListViewStmts.isEmpty() ){
|
||||
log.debug("need to deal with old list view statements from the display model");
|
||||
neededSave = true;
|
||||
try{
|
||||
//create a file for the old statements in the loadAtStartup directory
|
||||
String newFileName = ctx.getRealPath(
|
||||
DISPLAY_MODEL_LOAD_AT_STARTUP_DIR + File.separator
|
||||
+ new DateTime().toString(ISODateTimeFormat.basicDateTime()) + ".n3" );
|
||||
File file = new File( newFileName );
|
||||
file.createNewFile();
|
||||
|
||||
log.info("Relocating " + unhandledOldListViewStmts.size() + " custom list view statements from DB and saving to "
|
||||
+ file.getAbsolutePath()+ File.separator + file.getName()
|
||||
+ ". These will be loaded from this file when the system starts up.");
|
||||
|
||||
FileOutputStream fileOut = new FileOutputStream(file);
|
||||
unhandledOldListViewStmts.write(fileOut, "N3-PP");
|
||||
fileOut.close();
|
||||
saved = true;
|
||||
}catch(Throwable th){
|
||||
log.warn("Could not save old list view statements. Leaving them in the DB",th);
|
||||
}
|
||||
|
||||
//need to reload displayLoadAlways because DISPLAY_MODEL_LOAD_AT_STARTUP_DIR may have changed
|
||||
displayLoadAtStartup.removeAll().add(readInDisplayModelLoadAtStartup(ctx));
|
||||
}
|
||||
|
||||
|
||||
if( oldListViewModel != null && ! oldListViewModel.isEmpty() ){
|
||||
//At this point, there are old list view statements in the DB but they
|
||||
//should are all redundant with ones in DISPLAY_MODEL_LOAD_AT_STARTUP_DIR
|
||||
if( (neededSave && saved) || (!neededSave) ){
|
||||
//if there was nothing to save, just remove the old stuff
|
||||
//if there was stuff to save, only remove if it was saved.
|
||||
log.debug("removing old statements from displayModel");
|
||||
displayModel.remove(oldListViewModel);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Model getOldListViewStatements(OntModel displayModel) {
|
||||
//run a construct on displayModel to get all list view statements
|
||||
Query query = QueryFactory.create ( listViewQuery );
|
||||
QueryExecution qexec = QueryExecutionFactory.create(query, displayModel) ;
|
||||
Model oldModel = null;
|
||||
|
||||
try {
|
||||
oldModel = qexec.execConstruct();
|
||||
} catch( Throwable th ){
|
||||
log.error("could not check for old custom list views, query exception",th);
|
||||
}finally {
|
||||
qexec.close() ;
|
||||
}
|
||||
|
||||
if( oldModel != null)
|
||||
return oldModel;
|
||||
else
|
||||
return ModelFactory.createDefaultModel();
|
||||
}
|
||||
|
||||
private static final String listViewQuery = "" +
|
||||
"PREFIX d: <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#>\n" +
|
||||
"CONSTRUCT { \n" +
|
||||
" ?a d:listViewConfigFile ?b . \n" +
|
||||
"} WHERE {\n" +
|
||||
" ?a d:listViewConfigFile ?b . \n" +
|
||||
"} ";
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent arg0) {
|
||||
|
|
|
@ -24,11 +24,13 @@ import com.hp.hpl.jena.rdf.model.ResIterator;
|
|||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
import com.hp.hpl.jena.util.ResourceUtils;
|
||||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||
import com.hp.hpl.jena.vocabulary.RDF;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess.FactoryID;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess.ModelID;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer;
|
||||
|
@ -40,7 +42,6 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
|||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.InitialJenaModelUtils;
|
||||
|
||||
/**
|
||||
* Sets up the content models, OntModelSelectors and webapp DAO factories.
|
||||
|
@ -79,9 +80,13 @@ public class ContentModelSetup extends JenaDataSourceSetupBase
|
|||
OntModel unionABoxModel = createCombinedBulkUpdatingModel(baseABoxModel, inferenceABoxModel);
|
||||
OntModel unionTBoxModel = createCombinedBulkUpdatingModel(baseTBoxModel, inferenceTBoxModel);
|
||||
|
||||
|
||||
if (isFirstStartup()) {
|
||||
loadInitialApplicationMetadataModel(applicationMetadataModel, ctx);
|
||||
loadDataFromFilesystem(baseABoxModel, baseTBoxModel, applicationMetadataModel, ctx);
|
||||
initializeApplicationMetadata(ctx, applicationMetadataModel);
|
||||
RDFFilesLoader.loadFirstTimeFiles(ctx, "abox", baseABoxModel, true);
|
||||
RDFFilesLoader.loadFirstTimeFiles(ctx, "tbox", baseTBoxModel, true);
|
||||
} else {
|
||||
checkForNamespaceMismatch( applicationMetadataModel, ctx );
|
||||
}
|
||||
|
||||
log.info("Setting up full models");
|
||||
|
@ -101,7 +106,6 @@ public class ContentModelSetup extends JenaDataSourceSetupBase
|
|||
models.setOntModel(ModelID.UNION_TBOX, unionTBoxModel);
|
||||
models.setOntModel(ModelID.UNION_FULL, unionFullModel);
|
||||
|
||||
checkForNamespaceMismatch( applicationMetadataModel, ctx );
|
||||
|
||||
log.info("Setting up DAO factories");
|
||||
|
||||
|
@ -159,35 +163,54 @@ public class ContentModelSetup extends JenaDataSourceSetupBase
|
|||
return ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC, unionModel);
|
||||
}
|
||||
|
||||
private void loadInitialApplicationMetadataModel(OntModel applicationMetadataModel,
|
||||
ServletContext ctx) {
|
||||
try {
|
||||
applicationMetadataModel.add(
|
||||
InitialJenaModelUtils.loadInitialModel(ctx, getDefaultNamespace(ctx)));
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Unable to load application metadata model cache from DB", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDataFromFilesystem(OntModel baseABoxModel, OntModel baseTBoxModel, OntModel applicationMetadataModel,
|
||||
ServletContext ctx) {
|
||||
Long startTime = System.currentTimeMillis();
|
||||
log.info("Initializing models from RDF files");
|
||||
|
||||
readOntologyFilesInPathSet(USER_ABOX_PATH, ctx, baseABoxModel);
|
||||
readOntologyFilesInPathSet(USER_TBOX_PATH, ctx, baseTBoxModel);
|
||||
readOntologyFilesInPathSet(USER_APPMETA_PATH, ctx, applicationMetadataModel);
|
||||
|
||||
log.debug(((System.currentTimeMillis() - startTime) / 1000)
|
||||
+ " seconds to read RDF files ");
|
||||
}
|
||||
|
||||
private long secondsSince(long startTime) {
|
||||
return (System.currentTimeMillis() - startTime) / 1000;
|
||||
}
|
||||
|
||||
/* ===================================================================== */
|
||||
|
||||
/**
|
||||
* We need to read the RDF files and change the Portal from a blank node to
|
||||
* one with a URI in the default namespace.
|
||||
*
|
||||
* Do this before adding the data to the RDFService-backed model, to avoid
|
||||
* warnings about editing a blank node.
|
||||
*/
|
||||
private void initializeApplicationMetadata(ServletContext ctx,
|
||||
OntModel applicationMetadataModel) {
|
||||
OntModel temporaryAMModel = ModelFactory.createOntologyModel(MEM_ONT_MODEL_SPEC);
|
||||
RDFFilesLoader.loadFirstTimeFiles(ctx, "applicationMetadata", temporaryAMModel, true);
|
||||
setPortalUriOnFirstTime(temporaryAMModel, ctx);
|
||||
applicationMetadataModel.add(temporaryAMModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* If we are loading the application metadata for the first time, set the
|
||||
* URI of the Portal based on the default namespace.
|
||||
*/
|
||||
private void setPortalUriOnFirstTime(OntModel model, ServletContext ctx) {
|
||||
// Only a single portal is permitted in the initialization data
|
||||
Resource portalResource = null;
|
||||
ClosableIterator<Resource> portalResIt = model
|
||||
.listSubjectsWithProperty(RDF.type,
|
||||
model.getResource(VitroVocabulary.PORTAL));
|
||||
try {
|
||||
if (portalResIt.hasNext()) {
|
||||
Resource portalRes = portalResIt.next();
|
||||
if (portalRes.isAnon()) {
|
||||
portalResource = portalRes;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
portalResIt.close();
|
||||
}
|
||||
|
||||
if (portalResource != null) {
|
||||
ResourceUtils.renameResource(portalResource, getDefaultNamespace(ctx) + "portal1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If we find a "portal1" portal (and we should), its URI should use the
|
||||
* default namespace.
|
||||
|
|
|
@ -2,13 +2,17 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -26,23 +30,36 @@ import com.hp.hpl.jena.query.Dataset;
|
|||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceModelMaker;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
|
||||
// This ContextListener must run after the JenaDataSourceSetup ContextListener
|
||||
|
||||
public class FileGraphSetup implements ServletContextListener {
|
||||
private static final Log log = LogFactory.getLog(FileGraphSetup.class);
|
||||
|
||||
private static final String RDF = "rdf";
|
||||
private static final String ABOX = "abox";
|
||||
private static final String TBOX = "tbox";
|
||||
private static final String PATH_ROOT = "/WEB-INF/filegraph/";
|
||||
private static final String FILEGRAPH = "filegraph";
|
||||
private static final String PROPERTY_VITRO_HOME = "vitro.home";
|
||||
|
||||
public static final String FILEGRAPH_URI_ROOT = "http://vitro.mannlib.cornell.edu/filegraph/";
|
||||
|
||||
/** Ignore hidden files when looking for filegraph RDF. */
|
||||
private static final DirectoryStream.Filter<Path> REJECT_HIDDEN_FILES = new DirectoryStream.Filter<Path>() {
|
||||
@Override
|
||||
public boolean accept(Path entry) throws IOException {
|
||||
return !Files.isHidden(entry);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Log log = LogFactory.getLog(FileGraphSetup.class);
|
||||
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
|
||||
boolean aboxChanged = false; // indicates whether any ABox file graph model has changed
|
||||
boolean tboxChanged = false; // indicates whether any TBox file graph model has changed
|
||||
|
@ -57,24 +74,20 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
RDFServiceModelMaker maker = new RDFServiceModelMaker(RDFServiceUtils.getRDFServiceFactory(ctx));
|
||||
|
||||
// ABox files
|
||||
Set<String> pathSet = ctx.getResourcePaths(PATH_ROOT + ABOX);
|
||||
Set<Path> paths = getFilegraphPaths(ctx, RDF, ABOX, FILEGRAPH);
|
||||
|
||||
cleanupDB(dataset, pathToURI(pathSet, ABOX), ABOX);
|
||||
cleanupDB(dataset, pathsToURIs(paths, ABOX), ABOX);
|
||||
|
||||
if (pathSet != null) {
|
||||
OntModel aboxBaseModel = baseOms.getABoxModel();
|
||||
aboxChanged = readGraphs(sce, pathSet, maker, ABOX, aboxBaseModel);
|
||||
}
|
||||
OntModel aboxBaseModel = baseOms.getABoxModel();
|
||||
aboxChanged = readGraphs(paths, maker, ABOX, aboxBaseModel);
|
||||
|
||||
// TBox files
|
||||
pathSet = ctx.getResourcePaths(PATH_ROOT + TBOX);
|
||||
paths = getFilegraphPaths(ctx, RDF, TBOX, FILEGRAPH);
|
||||
|
||||
cleanupDB(dataset, pathToURI(pathSet, TBOX),TBOX);
|
||||
cleanupDB(dataset, pathsToURIs(paths, TBOX),TBOX);
|
||||
|
||||
if (pathSet != null) {
|
||||
OntModel tboxBaseModel = baseOms.getTBoxModel();
|
||||
tboxChanged = readGraphs(sce, pathSet, maker, TBOX, tboxBaseModel);
|
||||
}
|
||||
OntModel tboxBaseModel = baseOms.getTBoxModel();
|
||||
tboxChanged = readGraphs(paths, maker, TBOX, tboxBaseModel);
|
||||
} catch (ClassCastException cce) {
|
||||
String errMsg = "Unable to cast servlet context attribute to the appropriate type " + cce.getLocalizedMessage();
|
||||
log.error(errMsg);
|
||||
|
@ -99,7 +112,35 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private Set<Path> getFilegraphPaths(ServletContext ctx, String... strings) {
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
|
||||
ConfigurationProperties props = ConfigurationProperties.getBean(ctx);
|
||||
String homeDirProperty = props.getProperty(PROPERTY_VITRO_HOME);
|
||||
Path filegraphDir = Paths.get(homeDirProperty, strings);
|
||||
|
||||
Set<Path> paths = new TreeSet<>();
|
||||
if (Files.isDirectory(filegraphDir)) {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(
|
||||
filegraphDir, REJECT_HIDDEN_FILES)) {
|
||||
for (Path p : stream) {
|
||||
paths.add(p);
|
||||
}
|
||||
ss.info(this, "Read " + paths.size() + " RDF files from '"
|
||||
+ filegraphDir + "'");
|
||||
} catch (IOException e) {
|
||||
ss.fatal(this, "Failed to read filegraph RDF from '"
|
||||
+ filegraphDir + "' directory.", e);
|
||||
}
|
||||
} else {
|
||||
ss.info(this, "Filegraph directory '" + filegraphDir
|
||||
+ "' doesn't exist.");
|
||||
}
|
||||
log.debug("Paths from '" + filegraphDir + "': " + paths);
|
||||
return paths;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads the graphs stored as files in sub-directories of
|
||||
* 1. updates the SDB store to reflect the current contents of the graph.
|
||||
* 2. adds the graph as an in-memory submodel of the base in-memory graph
|
||||
|
@ -107,7 +148,7 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
* Note: no connection needs to be maintained between the in-memory copy of the
|
||||
* graph and the DB copy.
|
||||
*/
|
||||
public boolean readGraphs(ServletContextEvent sce, Set<String> pathSet, RDFServiceModelMaker dataset, String type, OntModel baseModel) {
|
||||
public boolean readGraphs(Set<Path> pathSet, RDFServiceModelMaker dataset, String type, OntModel baseModel) {
|
||||
|
||||
int count = 0;
|
||||
|
||||
|
@ -115,18 +156,17 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
|
||||
// For each file graph in the target directory update or add that graph to
|
||||
// the Jena SDB, and attach the graph as a submodel of the base model
|
||||
for ( String p : pathSet ) {
|
||||
for ( Path p : pathSet ) {
|
||||
|
||||
count++; // note this will count the empty files too
|
||||
File file = new File(sce.getServletContext().getRealPath(p));
|
||||
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream( file );
|
||||
FileInputStream fis = new FileInputStream( p.toFile() );
|
||||
try {
|
||||
OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||
if ( p.endsWith(".n3") || p.endsWith(".N3") || p.endsWith(".ttl") || p.endsWith(".TTL") ) {
|
||||
String fn = p.getFileName().toString().toLowerCase();
|
||||
if ( fn.endsWith(".n3") || fn.endsWith(".ttl") ) {
|
||||
model.read( fis, null, "N3" );
|
||||
} else if ( p.endsWith(".owl") || p.endsWith(".OWL") || p.endsWith(".rdf") || p.endsWith(".RDF") || p.endsWith(".xml") || p.endsWith(".XML") ) {
|
||||
} else if ( fn.endsWith(".owl") || fn.endsWith(".rdf") || fn.endsWith(".xml") ) {
|
||||
model.read( fis, null, "RDF/XML" );
|
||||
} else {
|
||||
log.warn("Ignoring " + type + " file graph " + p + " because the file extension is unrecognized.");
|
||||
|
@ -134,7 +174,7 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
|
||||
if ( !model.isEmpty() ) {
|
||||
baseModel.addSubModel(model);
|
||||
log.info("Attached file graph as " + type + " submodel " + p);
|
||||
log.info("Attached file graph as " + type + " submodel " + pathToURI(p, type));
|
||||
}
|
||||
|
||||
modelChanged = modelChanged | updateGraphInDB(dataset, model, type, p);
|
||||
|
@ -155,8 +195,8 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
log.warn("Exception while trying to close file graph file: " + p,ioe);
|
||||
}
|
||||
} // end - for
|
||||
|
||||
System.out.println("Read " + count + " " + type + " file graph" + ((count == 1) ? "" : "s") + " from " + PATH_ROOT + type);
|
||||
|
||||
log.info("Read " + count + " " + type + " file graph" + ((count == 1) ? "" : "s"));
|
||||
|
||||
return modelChanged;
|
||||
}
|
||||
|
@ -171,7 +211,7 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
* Otherwise, if a graph with the given name is in the DB and is isomorphic with
|
||||
* the graph that was read from the files system, then do nothing.
|
||||
*/
|
||||
public boolean updateGraphInDB(RDFServiceModelMaker dataset, Model fileModel, String type, String path) {
|
||||
public boolean updateGraphInDB(RDFServiceModelMaker dataset, Model fileModel, String type, Path path) {
|
||||
String graphURI = pathToURI(path,type);
|
||||
Model dbModel = dataset.getModel(graphURI);
|
||||
boolean modelChanged = false;
|
||||
|
@ -224,46 +264,34 @@ public class FileGraphSetup implements ServletContextListener {
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes a set of paths for file graphs and returns a set containing a graph
|
||||
* uri for each path.
|
||||
*/
|
||||
private Set<String> pathsToURIs(Set<Path> paths, String type) {
|
||||
HashSet<String> uriSet = new HashSet<String>();
|
||||
for (Path path : paths) {
|
||||
uriSet.add(pathToURI(path, type));
|
||||
}
|
||||
log.debug("uriSet = " + uriSet);
|
||||
return uriSet;
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes a set of path names for file graphs and returns a set containing
|
||||
* a graph uri for each path name in the input set. If pathSet is null
|
||||
* returns an empty set.
|
||||
*/
|
||||
public Set<String> pathToURI (Set<String> pathSet, String type) {
|
||||
|
||||
HashSet<String> uriSet = new HashSet<String>();
|
||||
|
||||
if (pathSet != null) {
|
||||
for ( String path : pathSet ) {
|
||||
uriSet.add(pathToURI(path,type));
|
||||
}
|
||||
}
|
||||
|
||||
return uriSet;
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes a path name for a file graph and returns the corresponding SDB URI
|
||||
* Takes a path for a file graph and returns the corresponding SDB URI
|
||||
* for the graph. The correspondence is by defined convention.
|
||||
*/
|
||||
public String pathToURI(String path, String type) {
|
||||
|
||||
String uri = null;
|
||||
|
||||
if (path != null) {
|
||||
File file = new File(path);
|
||||
uri = FILEGRAPH_URI_ROOT + type + "/" + file.getName();
|
||||
}
|
||||
|
||||
return uri;
|
||||
private String pathToURI(Path path, String type) {
|
||||
return FILEGRAPH_URI_ROOT + type + "/" + path.getFileName();
|
||||
}
|
||||
|
||||
public void contextDestroyed( ServletContextEvent sce ) {
|
||||
|
||||
@Override
|
||||
public void contextDestroyed( ServletContextEvent sce ) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
private static boolean isUpdateRequired(ServletContext ctx) {
|
||||
return (ctx.getAttribute(UpdateKnowledgeBase.KBM_REQURIED_AT_STARTUP) != null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -3,11 +3,7 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
||||
|
||||
import java.beans.PropertyVetoException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.sql.DataSource;
|
||||
|
@ -69,21 +65,6 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon {
|
|||
protected final static boolean DEFAULT_TESTONBORROW = true,
|
||||
DEFAULT_TESTONRETURN = true, DEFAULT_TESTWHILEIDLE = true;
|
||||
|
||||
protected static String BASE = "/WEB-INF/ontologies/";
|
||||
protected static String USERPATH = BASE+"user/";
|
||||
protected static String USER_ABOX_PATH = BASE+"user/abox";
|
||||
protected static String USER_TBOX_PATH = BASE+"user/tbox";
|
||||
protected static String USER_APPMETA_PATH = BASE+"user/applicationMetadata";
|
||||
protected static String SYSTEMPATH = BASE+"system/";
|
||||
public static String APPPATH = BASE+"app/";
|
||||
//these files are loaded everytime the system starts up
|
||||
public static String APPPATH_LOAD = APPPATH + "menuload/";
|
||||
|
||||
//All files in this directory will be reloaded every startup
|
||||
//and attached as sub-models to the displayOntModel.
|
||||
static final String DISPLAY_MODEL_LOAD_AT_STARTUP_DIR =
|
||||
APPPATH + "loadedAtStartup";
|
||||
|
||||
protected static boolean firstStartup = false;
|
||||
|
||||
String DB_USER = "jenatest"; // database user id
|
||||
|
@ -395,45 +376,6 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon {
|
|||
return dbModel;
|
||||
}
|
||||
|
||||
public static void readOntologyFilesInPathSet(String path,
|
||||
ServletContext ctx, Model model) {
|
||||
log.debug("Reading ontology files from '" + path + "'");
|
||||
Set<String> paths = ctx.getResourcePaths(path);
|
||||
if (paths != null) {
|
||||
for (String p : paths) {
|
||||
readOntologyFileFromPath(p, model, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void readOntologyFileFromPath(String p,
|
||||
Model model,
|
||||
ServletContext ctx) {
|
||||
//Check that this is a file and not a directory
|
||||
File f = new File(ctx.getRealPath(p));
|
||||
if(f.exists() && f.isFile()){
|
||||
String format = getRdfFormat(p);
|
||||
log.info("Loading ontology file at " + p +
|
||||
" as format " + format);
|
||||
InputStream ontologyInputStream = ctx.getResourceAsStream(p);
|
||||
try {
|
||||
model.read(ontologyInputStream, null, format);
|
||||
log.debug("...successful");
|
||||
} catch (Throwable t) {
|
||||
log.error("Failed to load ontology file at '" + p +
|
||||
"' as format " + format, t);
|
||||
}
|
||||
} else {
|
||||
if(!f.exists()) {
|
||||
log.info("File for path " + p + " does not exist");
|
||||
}
|
||||
else if(f.isDirectory()) {
|
||||
log.info("Path " + p +
|
||||
" corresponds to directory and not file so was not read in");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getRdfFormat(String filename){
|
||||
String defaultformat = "RDF/XML";
|
||||
if( filename == null )
|
||||
|
@ -489,42 +431,6 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all the files in the directory as RDF files
|
||||
* and return a model build from all RDF data found in those files.
|
||||
* This will attempt to load formats supported by getRdfFormat().
|
||||
*/
|
||||
public static OntModel getModelFromDir( File dir){
|
||||
if( dir == null )
|
||||
throw new IllegalStateException("Must pass a File to getModelFromDir()");
|
||||
if( !dir.isDirectory() )
|
||||
throw new IllegalStateException(
|
||||
"Directory must be a File object for a directory");
|
||||
if( !dir.canRead() )
|
||||
throw new IllegalStateException("getModelFromDir(): Directory " +
|
||||
" must be readable, check premissions on "
|
||||
+ dir.getAbsolutePath());
|
||||
|
||||
OntModel model = ModelFactory.createOntologyModel();
|
||||
for( File file : dir.listFiles()){
|
||||
if( file.isFile()
|
||||
&& file.canRead()
|
||||
&& file.getName() != null ){
|
||||
String format = getRdfFormat( file.getName() );
|
||||
try{
|
||||
model.read( new FileInputStream(file), null, format);
|
||||
log.info("read in file " + file.getCanonicalPath() );
|
||||
}catch( Throwable th){
|
||||
log.warn("Could not load file " +
|
||||
file.getAbsolutePath() + file.separator + file.getName() +
|
||||
" check that it contains valid " + format + " data.",
|
||||
th);
|
||||
}
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
public static void setVitroJenaModelMaker(VitroJenaModelMaker vjmm,
|
||||
ServletContext ctx){
|
||||
ctx.setAttribute(rdbModelMaker, vjmm);
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/* $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.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.ontology.OntModelSpec;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Help to load RDF files on first time and on every startup.
|
||||
*/
|
||||
public class RDFFilesLoader {
|
||||
private static final Log log = LogFactory.getLog(RDFFilesLoader.class);
|
||||
|
||||
private static final String PROPERTY_VITRO_HOME = "vitro.home";
|
||||
private static final String DEFAULT_RDF_FORMAT = "RDF/XML";
|
||||
private static final String RDF = "rdf";
|
||||
private static final String FIRST_TIME = "firsttime";
|
||||
private static final String EVERY_TIME = "everytime";
|
||||
|
||||
/** Path filter that ignores sub-directories and hidden files. */
|
||||
private static final DirectoryStream.Filter<Path> RDF_FILE_FILTER = new DirectoryStream.Filter<Path>() {
|
||||
@Override
|
||||
public boolean accept(Path p) throws IOException {
|
||||
if (Files.isHidden(p)) {
|
||||
return false;
|
||||
}
|
||||
if (Files.isDirectory(p)) {
|
||||
log.warn("RDF files in subdirectories are not loaded. Directory '"
|
||||
+ p + "' ignored.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the "first time" files if we say it is the first time.
|
||||
*
|
||||
* The location is based on the home directory and the model path: "abox",
|
||||
* "display", etc.
|
||||
*
|
||||
* The files from the directory are added to the model.
|
||||
*/
|
||||
public static void loadFirstTimeFiles(ServletContext ctx, String modelPath,
|
||||
Model model, boolean firstTime) {
|
||||
if (firstTime) {
|
||||
Set<Path> paths = getPaths(locateHomeDirectory(ctx), RDF,
|
||||
modelPath, FIRST_TIME);
|
||||
for (Path p : paths) {
|
||||
readOntologyFileIntoModel(p, model);
|
||||
}
|
||||
} else {
|
||||
log.debug("Not loading first time files on '" + modelPath
|
||||
+ "', firstTime=false");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the "every time" files.
|
||||
*
|
||||
* The location is based on the home directory and the model path: "abox",
|
||||
* "display", etc.
|
||||
*
|
||||
* The files from the directory become a sub-model of the model.
|
||||
*/
|
||||
public static void loadEveryTimeFiles(ServletContext ctx, String modelPath,
|
||||
OntModel model) {
|
||||
OntModel everytimeModel = ModelFactory
|
||||
.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||
Set<Path> paths = getPaths(locateHomeDirectory(ctx), RDF, modelPath,
|
||||
EVERY_TIME);
|
||||
for (Path p : paths) {
|
||||
readOntologyFileIntoModel(p, everytimeModel);
|
||||
}
|
||||
model.addSubModel(everytimeModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a model from all the RDF files in the specified directory.
|
||||
*/
|
||||
public static OntModel getModelFromDir(File dir) {
|
||||
OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||
if (dir == null) {
|
||||
log.warn("Must pass a File to getModelFromDir()");
|
||||
return model;
|
||||
}
|
||||
if (!dir.isDirectory()) {
|
||||
log.warn("Directory must be a File object for a directory");
|
||||
return model;
|
||||
}
|
||||
if (!dir.canRead()) {
|
||||
log.warn("getModelFromDir(): Directory "
|
||||
+ " must be readable, check permissions on "
|
||||
+ dir.getAbsolutePath());
|
||||
return model;
|
||||
}
|
||||
|
||||
Set<Path> paths = getPaths(dir.getPath());
|
||||
for (Path p : paths) {
|
||||
readOntologyFileIntoModel(p, model);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the paths to RDF files in this directory. Sub-directories and hidden
|
||||
* files are ignored.
|
||||
*/
|
||||
private static Set<Path> getPaths(String parentDir, String... strings) {
|
||||
Path dir = Paths.get(parentDir, strings);
|
||||
|
||||
Set<Path> paths = new TreeSet<>();
|
||||
if (Files.isDirectory(dir)) {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir,
|
||||
RDF_FILE_FILTER)) {
|
||||
for (Path p : stream) {
|
||||
paths.add(p);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Failed to read directory '" + dir + "'", e);
|
||||
}
|
||||
} else {
|
||||
log.debug("Directory '" + dir + "' doesn't exist.");
|
||||
}
|
||||
log.debug("Paths from '" + dir + "': " + paths);
|
||||
return paths;
|
||||
}
|
||||
|
||||
private static void readOntologyFileIntoModel(Path p, Model model) {
|
||||
String format = getRdfFormat(p);
|
||||
log.info("Loading file at " + p + " as " + format);
|
||||
try (InputStream stream = new FileInputStream(p.toFile())) {
|
||||
model.read(stream, null, format);
|
||||
log.debug("...successful");
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not load file '" + p + "' as " + format
|
||||
+ ". Check that it contains valid data.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getRdfFormat(Path p) {
|
||||
String filename = p.getFileName().toString().toLowerCase();
|
||||
if (filename.endsWith("n3"))
|
||||
return "N3";
|
||||
else if (filename.endsWith("ttl"))
|
||||
return "TURTLE";
|
||||
else
|
||||
return DEFAULT_RDF_FORMAT;
|
||||
}
|
||||
|
||||
private static String locateHomeDirectory(ServletContext ctx) {
|
||||
return ConfigurationProperties.getBean(ctx).getProperty(
|
||||
PROPERTY_VITRO_HOME);
|
||||
}
|
||||
|
||||
/**
|
||||
* No need to create an instance -- all methods are static.
|
||||
*/
|
||||
private RDFFilesLoader() {
|
||||
// Nothing to initialize.
|
||||
}
|
||||
|
||||
}
|
|
@ -17,59 +17,60 @@ import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess;
|
|||
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelSynchronizer;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
|
||||
|
||||
/**
|
||||
* Setup the user account model. If it does not exist in the
|
||||
* database, create and populate it.
|
||||
/**
|
||||
* Setup the user account model. If it does not exist in the database, create
|
||||
* and populate it.
|
||||
*/
|
||||
public class UserModelSetup extends JenaDataSourceSetupBase
|
||||
implements ServletContextListener {
|
||||
protected static String AUTHPATH = BASE + "auth/";
|
||||
|
||||
private static final Log log = LogFactory.getLog(
|
||||
UserModelSetup.class.getName());
|
||||
public class UserModelSetup extends JenaDataSourceSetupBase implements
|
||||
ServletContextListener {
|
||||
private static final Log log = LogFactory.getLog(UserModelSetup.class
|
||||
.getName());
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext ctx = sce.getServletContext();
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
|
||||
DataSource bds = getApplicationDataSource(ctx);
|
||||
if( bds == null ){
|
||||
ss.fatal(this, "A DataSource must be setup before ModelSetup "+
|
||||
"is run. Make sure that JenaPersistentDataSourceSetup runs before "+
|
||||
"ModelSetup.");
|
||||
return;
|
||||
}
|
||||
|
||||
setupUserAccountModel(bds, ctx, ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent arg0) {
|
||||
// Does nothing.
|
||||
}
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext ctx = sce.getServletContext();
|
||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||
|
||||
private void setupUserAccountModel (DataSource bds, ServletContext ctx ,StartupStatus ss){
|
||||
try {
|
||||
Model userAccountsDbModel = makeDBModel(bds,
|
||||
JENA_USER_ACCOUNTS_MODEL, DB_ONT_MODEL_SPEC, ctx);
|
||||
OntModel userAccountsModel =
|
||||
ModelFactory.createOntologyModel( MEM_ONT_MODEL_SPEC);
|
||||
|
||||
// This is used in Selenium testing, when we load user accounts from a file.
|
||||
if (userAccountsDbModel.isEmpty()) {
|
||||
readOntologyFilesInPathSet(AUTHPATH, ctx, userAccountsDbModel);
|
||||
}
|
||||
DataSource bds = getApplicationDataSource(ctx);
|
||||
if (bds == null) {
|
||||
ss.fatal(
|
||||
this,
|
||||
"A DataSource must be setup before ModelSetup "
|
||||
+ "is run. Make sure that JenaPersistentDataSourceSetup runs before "
|
||||
+ "ModelSetup.");
|
||||
return;
|
||||
}
|
||||
|
||||
userAccountsModel.add(userAccountsDbModel);
|
||||
userAccountsModel.getBaseModel().register(
|
||||
new ModelSynchronizer(userAccountsDbModel));
|
||||
ModelAccess.on(ctx).setUserAccountsModel(userAccountsModel);
|
||||
|
||||
} catch (Throwable t) {
|
||||
log.error("Unable to load user accounts model from DB", t);
|
||||
ss.fatal(this, "Unable to load user accounts model from DB", t);
|
||||
}
|
||||
}
|
||||
setupUserAccountModel(bds, ctx, ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent arg0) {
|
||||
// Does nothing.
|
||||
}
|
||||
|
||||
private void setupUserAccountModel(DataSource bds, ServletContext ctx,
|
||||
StartupStatus ss) {
|
||||
try {
|
||||
Model userAccountsDbModel = makeDBModel(bds,
|
||||
JENA_USER_ACCOUNTS_MODEL, DB_ONT_MODEL_SPEC, ctx);
|
||||
OntModel userAccountsModel = ModelFactory
|
||||
.createOntologyModel(MEM_ONT_MODEL_SPEC);
|
||||
|
||||
userAccountsModel.add(userAccountsDbModel);
|
||||
userAccountsModel.getBaseModel().register(
|
||||
new ModelSynchronizer(userAccountsDbModel));
|
||||
|
||||
// This is used in Selenium testing, to load accounts from a file.
|
||||
RDFFilesLoader.loadFirstTimeFiles(ctx, "auth", userAccountsModel,
|
||||
userAccountsDbModel.isEmpty());
|
||||
// This gets the permissions configuration.
|
||||
RDFFilesLoader.loadEveryTimeFiles(ctx, "auth", userAccountsModel);
|
||||
|
||||
ModelAccess.on(ctx).setUserAccountsModel(userAccountsModel);
|
||||
} catch (Throwable t) {
|
||||
log.error("Unable to load user accounts model from DB", t);
|
||||
ss.fatal(this, "Unable to load user accounts model from DB", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,12 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache;
|
|||
public class DataGetterUtils {
|
||||
|
||||
final static Log log = LogFactory.getLog(DataGetterUtils.class);
|
||||
|
||||
|
||||
/**
|
||||
* Attribute name in request for DataGetters
|
||||
*/
|
||||
public final static String DATA_GETTERS_FOR_PAGE = "data_getters_for_page";
|
||||
|
||||
/**
|
||||
* Get a list of DataGetter objects that are associated with a page.
|
||||
* This should not return PageDataGetters and should not throw an
|
||||
|
@ -63,10 +68,16 @@ public class DataGetterUtils {
|
|||
*/
|
||||
public static List<DataGetter> getDataGettersForPage(VitroRequest vreq, Model displayModel, String pageURI)
|
||||
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException {
|
||||
List<String> dgUris = getDataGetterURIsForAssociatedURI(displayModel, pageURI);
|
||||
List<DataGetter> dgList = dataGettersForURIs(vreq, displayModel, dgUris);
|
||||
log.debug("getDataGettersForPage: " + dgList);
|
||||
return dgList;
|
||||
|
||||
if( vreq.getAttribute(DATA_GETTERS_FOR_PAGE) != null){
|
||||
return (List<DataGetter>) vreq.getAttribute(DATA_GETTERS_FOR_PAGE);
|
||||
}else{
|
||||
List<String> dgUris = getDataGetterURIsForAssociatedURI(displayModel, pageURI);
|
||||
List<DataGetter> dgList = dataGettersForURIs(vreq, displayModel, dgUris);
|
||||
log.debug("getDataGettersForPage: " + dgList);
|
||||
vreq.setAttribute( DATA_GETTERS_FOR_PAGE , dgList );
|
||||
return dgList;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/* $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<String,Object> getData( Map<String, Object> valueMap ) {
|
||||
HashMap<String, Object> data = new HashMap<String,Object>();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.utils.jena;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.ontology.OntModelSpec;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.util.ResourceUtils;
|
||||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||
import com.hp.hpl.jena.vocabulary.RDF;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase;
|
||||
|
||||
public class InitialJenaModelUtils {
|
||||
|
||||
private static final String INIT_DATA_DIRECTORY = "/WEB-INF/init-data";
|
||||
|
||||
private static final Log log = LogFactory.getLog(InitialJenaModelUtils.class);
|
||||
|
||||
public static Model loadInitialModel(ServletContext ctx, String defaultNamespace) {
|
||||
|
||||
OntModel initialModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||
|
||||
try {
|
||||
JenaDataSourceSetupBase.readOntologyFilesInPathSet(INIT_DATA_DIRECTORY, ctx, initialModel);
|
||||
} catch (Throwable t) {
|
||||
log.warn("Unable to read initial model data from " + INIT_DATA_DIRECTORY, t);
|
||||
}
|
||||
|
||||
if (initialModel.size() == 0) {
|
||||
return initialModel;
|
||||
}
|
||||
|
||||
//find and rename portal object
|
||||
//currently, only a single portal is permitted in the initialization data
|
||||
Resource portalResource = null;
|
||||
ClosableIterator<Resource> portalResIt = initialModel.listSubjectsWithProperty(RDF.type, initialModel.getResource(VitroVocabulary.PORTAL));
|
||||
try {
|
||||
if (portalResIt.hasNext()) {
|
||||
Resource portalRes = portalResIt.next();
|
||||
if (portalRes.isAnon()) {
|
||||
portalResource = portalRes;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
portalResIt.close();
|
||||
}
|
||||
if (portalResource != null) {
|
||||
ResourceUtils.renameResource(portalResource, defaultNamespace + "portal1");
|
||||
}
|
||||
|
||||
return initialModel;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -5,8 +5,6 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -21,13 +19,12 @@ import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
|
|||
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Property;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.InvalidConfigurationException;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.DataPropertyListConfig;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
|
||||
|
@ -136,7 +133,7 @@ public class DataPropertyTemplateModel extends PropertyTemplateModel {
|
|||
}
|
||||
|
||||
protected TemplateLoader getFreemarkerTemplateLoader() {
|
||||
return FreemarkerConfigurationLoader.getConfig(vreq).getTemplateLoader();
|
||||
return FreemarkerConfiguration.getConfig(vreq).getTemplateLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,12 +22,12 @@ 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.FreemarkerConfigurationLoader;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.InvalidConfigurationException;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.PropertyListConfig;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
|
@ -155,7 +155,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
|
|||
* This will do for now.
|
||||
*/
|
||||
protected TemplateLoader getFreemarkerTemplateLoader() {
|
||||
return FreemarkerConfigurationLoader.getConfig(vreq).getTemplateLoader();
|
||||
return FreemarkerConfiguration.getConfig(vreq).getTemplateLoader();
|
||||
}
|
||||
|
||||
protected List<Map<String, String>> getStatementData() {
|
||||
|
|
|
@ -22,10 +22,13 @@ public class PropertyGroupTemplateModel extends BaseTemplateModel {
|
|||
|
||||
private final String name;
|
||||
private final List<PropertyTemplateModel> properties;
|
||||
|
||||
|
||||
|
||||
|
||||
PropertyGroupTemplateModel(VitroRequest vreq, PropertyGroup group,
|
||||
Individual subject, boolean editing,
|
||||
List<DataProperty> populatedDataPropertyList, List<ObjectProperty> populatedObjectPropertyList) {
|
||||
List<DataProperty> populatedDataPropertyList,
|
||||
List<ObjectProperty> populatedObjectPropertyList) {
|
||||
|
||||
this.name = group.getName();
|
||||
|
||||
|
@ -54,6 +57,17 @@ public class PropertyGroupTemplateModel extends BaseTemplateModel {
|
|||
properties.remove(ptm);
|
||||
}
|
||||
|
||||
|
||||
public String toString(){
|
||||
String ptmStr ="";
|
||||
for( int i=0; i < properties.size() ; i ++ ){
|
||||
PropertyTemplateModel ptm = properties.get(i);
|
||||
String spacer = "\n ";
|
||||
if( ptm != null )
|
||||
ptmStr = ptmStr + spacer + ptm.toString();
|
||||
}
|
||||
return String.format("\nPropertyGroupTemplateModel %s[%s] ",name, ptmStr );
|
||||
}
|
||||
|
||||
/* Accessor methods for templates */
|
||||
// Add this so it's included in dumps for debugging. The templates will want to display
|
||||
|
@ -63,18 +77,14 @@ public class PropertyGroupTemplateModel extends BaseTemplateModel {
|
|||
}
|
||||
|
||||
public String getName(String otherGroupName) {
|
||||
String displayName = name;
|
||||
if (displayName == null) {
|
||||
displayName = "";
|
||||
} else if (displayName.isEmpty()) {
|
||||
displayName = otherGroupName;
|
||||
}
|
||||
return displayName;
|
||||
if (name == null || name.isEmpty()) {
|
||||
return otherGroupName;
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public List<PropertyTemplateModel> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,13 +39,14 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
|
|||
|
||||
private String name;
|
||||
|
||||
|
||||
|
||||
PropertyTemplateModel(Property property, Individual subject, VitroRequest vreq) {
|
||||
this.vreq = vreq;
|
||||
subjectUri = subject.getURI();
|
||||
this.property = property;
|
||||
propertyUri = property.getURI();
|
||||
localName = property.getLocalName();
|
||||
log.debug("Local name for property " + propertyUri + ": " + localName);
|
||||
localName = property.getLocalName();
|
||||
setVerboseDisplayValues(property);
|
||||
addUrl = "";
|
||||
|
||||
|
@ -57,14 +58,18 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
|
|||
protected void setVerboseDisplayValues(Property property) {
|
||||
|
||||
// No verbose display for vitro and vitro public properties.
|
||||
// This models previous behavior. In theory the verbose display can be provided, but we may not want
|
||||
// to give anyone access to these properties, since the application is dependent on them.
|
||||
// This models previous behavior. In theory the verbose display can be provided,
|
||||
// but we may not want to give anyone access to these properties, since the
|
||||
// application is dependent on them.
|
||||
String namespace = property.getNamespace();
|
||||
if (VitroVocabulary.vitroURI.equals(namespace) || VitroVocabulary.VITRO_PUBLIC.equals(namespace)) {
|
||||
if (VitroVocabulary.vitroURI.equals(namespace)
|
||||
|| VitroVocabulary.VITRO_PUBLIC.equals(namespace)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Boolean verboseDisplayValue = (Boolean) vreq.getSession().getAttribute("verbosePropertyDisplay");
|
||||
Boolean verboseDisplayValue =
|
||||
(Boolean) vreq.getSession().getAttribute("verbosePropertyDisplay");
|
||||
|
||||
if ( ! Boolean.TRUE.equals(verboseDisplayValue)) {
|
||||
return;
|
||||
}
|
||||
|
@ -98,6 +103,12 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s on %s",
|
||||
propertyUri != null ? propertyUri : "null Prop URI",
|
||||
subjectUri != null ? subjectUri : "null Sub URI" );
|
||||
}
|
||||
|
||||
/* Template properties */
|
||||
|
||||
public abstract String getType();
|
||||
|
@ -125,6 +136,5 @@ public abstract class PropertyTemplateModel extends BaseTemplateModel {
|
|||
|
||||
public Map<String, Object> getVerboseDisplay() {
|
||||
return verboseDisplay;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue