This commit is contained in:
anupsawant 2011-06-17 16:30:47 +00:00
commit e5f73e181c
82 changed files with 1842 additions and 1072 deletions

View file

@ -46,4 +46,11 @@ public class RequestIdentifiers {
return (IdentifierBundle) obj;
}
/**
* The login status has changed, so discard the cached Identifiers.
*/
public static void resetIdentifiers(ServletRequest request) {
request.removeAttribute(ATTRIBUTE_ID_BUNDLE);
}
}

View file

@ -24,7 +24,6 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.SelfEditingConfiguration;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
/**
@ -73,7 +72,7 @@ public class CommonIdentifierBundleFactory implements IdentifierBundleFactory {
private Collection<? extends Identifier> createRootUserIdentifiers(
HttpServletRequest req) {
UserAccount user = LoginStatusBean.getCurrentUser(req);
if (isRootUser(user)) {
if ((user != null) && user.isRootUser()) {
return Collections.singleton(new IsRootUser());
} else {
return Collections.emptySet();
@ -143,25 +142,6 @@ public class CommonIdentifierBundleFactory implements IdentifierBundleFactory {
return individuals;
}
/**
* Is this user a root user?
*/
private boolean isRootUser(UserAccount user) {
if (user == null) {
return false;
}
WebappDaoFactory wdf = (WebappDaoFactory) context
.getAttribute("webappDaoFactory");
if (wdf == null) {
log.error("Could not get a WebappDaoFactory from the ServletContext");
return false;
}
UserAccountsDao uaDao = wdf.getUserAccountsDao();
return uaDao.isRootUser(user);
}
@Override
public String toString() {
return this.getClass().getSimpleName() + " - " + hashCode();

View file

@ -9,11 +9,6 @@ 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.Resource;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.vocabulary.RDF;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.IsRootUser;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
@ -25,9 +20,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
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.dao.jena.ModelContext;
import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup;
/**
@ -73,10 +66,11 @@ public class RootUserPolicy implements PolicyIface {
try {
UserAccountsDao uaDao = getUserAccountsDao(ctx);
OntModel userAccountsModel = getUserAccountsModel(ctx);
checkForWrongRootUser(ctx, uaDao);
if (!rootUserExists(uaDao)) {
createRootUser(ctx, uaDao, userAccountsModel);
createRootUser(ctx, uaDao);
}
ServletPolicyList.addPolicy(ctx, new RootUserPolicy());
@ -98,26 +92,41 @@ public class RootUserPolicy implements PolicyIface {
return wadf.getUserAccountsDao();
}
private OntModel getUserAccountsModel(ServletContext ctx) {
return ModelContext.getBaseOntModelSelector(ctx)
.getUserAccountsModel();
private void checkForWrongRootUser(ServletContext ctx,
UserAccountsDao uaDao) {
UserAccount root = getRootUser(uaDao);
if (root == null) {
return;
}
String actualRootEmail = root.getEmailAddress();
String configRootEmail = ConfigurationProperties.getBean(ctx)
.getProperty(PROPERTY_ROOT_USER_EMAIL);
if (actualRootEmail.equals(configRootEmail)) {
return;
}
log.warn("Root user '" + actualRootEmail + "' already exists.");
}
private boolean rootUserExists(UserAccountsDao uaDao) {
return (getRootUser(uaDao) != null);
}
private UserAccount getRootUser(UserAccountsDao uaDao) {
for (UserAccount ua : uaDao.getAllUserAccounts()) {
if (uaDao.isRootUser(ua)) {
return true;
if (ua.isRootUser()) {
return ua;
}
}
return false;
return null;
}
/**
* TODO The first and last name should be left blank, so the user will
* be forced to edit them. However, that's not in place yet.
*/
private void createRootUser(ServletContext ctx, UserAccountsDao uaDao,
OntModel userAccountsModel) {
private void createRootUser(ServletContext ctx, UserAccountsDao uaDao) {
String emailAddress = ConfigurationProperties.getBean(ctx)
.getProperty(PROPERTY_ROOT_USER_EMAIL);
if (emailAddress == null) {
@ -147,19 +156,10 @@ public class RootUserPolicy implements PolicyIface {
.applyMd5Encoding(ROOT_USER_INITIAL_PASSWORD));
ua.setPasswordChangeRequired(true);
ua.setStatus(Status.ACTIVE);
ua.setRootUser(true);
uaDao.insertUserAccount(ua);
userAccountsModel.enterCriticalSection(Lock.WRITE);
try {
Resource r = userAccountsModel.getResource(ua.getUri());
Resource t = userAccountsModel
.getResource(VitroVocabulary.USERACCOUNT_ROOT_USER);
userAccountsModel.add(r, RDF.type, t);
} finally {
userAccountsModel.leaveCriticalSection();
}
log.info("Created root user as '" + emailAddress + "'");
}

View file

@ -60,6 +60,8 @@ public class UserAccount {
/** This may be empty, but should never be null. */
private Set<String> permissionSetUris = Collections.emptySet();
private boolean rootUser = false;
public String getUri() {
return uri;
}
@ -172,10 +174,18 @@ public class UserAccount {
this.permissionSetUris = new HashSet<String>(permissionSetUris);
}
public boolean isRootUser() {
return rootUser;
}
public void setRootUser(boolean rootUser) {
this.rootUser = rootUser;
}
private <T> T nonNull(T value, T defaultValue) {
return (value == null) ? defaultValue : value;
}
private String limitStringLength(int limit, String s) {
if (s == null) {
return "";
@ -196,6 +206,7 @@ public class UserAccount {
+ (", passwordChangeRequired=" + passwordChangeRequired)
+ (", loginCount=" + loginCount) + (", status=" + status)
+ (", externalAuthId=" + externalAuthId)
+ (", rootUser=" + rootUser)
+ (", permissionSetUris=" + permissionSetUris) + "]";
}
}

View file

@ -1,352 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Date;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.email.FreemarkerEmailFactory;
public class ContactMailServlet extends VitroHttpServlet {
private static final Log log = LogFactory.getLog(ContactMailServlet.class);
private final static String CONFIRM_PAGE = "/templates/parts/thankyou.jsp";
private final static String ERR_PAGE = "/templates/parts/contact_err.jsp";
private final static String SPAM_MESSAGE = "Your message was flagged as spam.";
private final static String EMAIL_BACKUP_FILE_PATH = "/WEB-INF/LatestMessage.html";
private final static String WEB_USERNAME_PARAM = "webusername";
private final static String WEB_USEREMAIL_PARAM = "webuseremail";
private final static String COMMENTS_PARAM = "s34gfd88p9x1";
@Override
public void doGet( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException {
VitroRequest vreq = new VitroRequest(request);
ApplicationBean appBean = vreq.getAppBean();
String statusMsg = null; // holds the error status
if (!FreemarkerEmailFactory.isConfigured(vreq)) {
statusMsg = "This application has not yet been configured to send mail. "
+ "Email properties must be specified in the configuration properties file.";
redirectToError(response, statusMsg);
return;
}
String webusername = vreq.getParameter(WEB_USERNAME_PARAM);
String webuseremail = vreq.getParameter(WEB_USEREMAIL_PARAM);
String comments = vreq.getParameter(COMMENTS_PARAM);
String validationMessage = validateInput(webusername, webuseremail,
comments);
if (validationMessage != null) {
redirectToError(response, validationMessage);
return;
}
webusername = webusername.trim();
webuseremail = webuseremail.trim();
comments = comments.trim();
String spamReason = null;
String originalReferer = (String) request.getSession()
.getAttribute("commentsFormReferer");
if (originalReferer != null) {
request.getSession().removeAttribute("commentsFormReferer");
/* does not support legitimate clients that don't send the Referer header
String referer = request.getHeader("Referer");
if (referer == null ||
(referer.indexOf("comments") <0
&& referer.indexOf("correction") <0) ) {
spamReason = "The form was not submitted from the " +
"Contact Us or Corrections page.";
statusMsg = SPAM_MESSAGE;
}
*/
} else {
originalReferer = "none";
}
if (spamReason == null) {
spamReason = checkForSpam(comments);
if (spamReason != null) {
statusMsg = SPAM_MESSAGE;
}
}
String formType = vreq.getParameter("DeliveryType");
String[] deliverToArray = null;
int recipientCount = 0;
String deliveryfrom = null;
if ("comment".equals(formType)) {
if (appBean.getContactMail() == null || appBean.getContactMail().trim().length()==0) {
log.error("No contact mail address defined in current application");
throw new Error(
"To establish the Contact Us mail capability the system administrators must "
+ "specify an email address in the current portal.");
} else {
deliverToArray = appBean.getContactMail().split(",");
}
deliveryfrom = "Message from the "+appBean.getApplicationName()+" Contact Form";
} else if ("correction".equals(formType)) {
if (appBean.getCorrectionMail() == null || appBean.getCorrectionMail().trim().length()==0) {
log.error("Expecting one or more correction email addresses to be specified in current application; will attempt to use contact mail address");
if (appBean.getContactMail() == null || appBean.getContactMail().trim().length()==0) {
log.error("No contact mail address or correction mail address defined in current application");
} else {
deliverToArray = appBean.getContactMail().split(",");
}
} else {
deliverToArray = appBean.getCorrectionMail().split(",");
}
deliveryfrom = "Message from the "+appBean.getApplicationName()+" Correction Form (ARMANN-nospam)";
} else {
deliverToArray = appBean.getContactMail().split(",");
statusMsg = SPAM_MESSAGE ;
spamReason = "The form specifies no delivery type.";
}
recipientCount=(deliverToArray == null) ? 0 : deliverToArray.length;
if (recipientCount == 0) {
log.error("recipientCount is 0 when DeliveryType specified as \""+formType+"\"");
throw new Error(
"To establish the Contact Us mail capability the system administrators must "
+ "specify at least one email address in the current portal.");
}
String msgText = composeEmail(webusername, webuseremail, comments,
deliveryfrom, originalReferer, request.getRemoteAddr());
// debugging
PrintWriter outFile = new PrintWriter
(new FileWriter(request.getSession().getServletContext()
.getRealPath(EMAIL_BACKUP_FILE_PATH),true)); //autoflush
writeBackupCopy(outFile, msgText, spamReason);
Session s = FreemarkerEmailFactory.getEmailSession(vreq);
//s.setDebug(true);
try {
if (spamReason == null) {
sendMessage(s, webuseremail, deliverToArray, deliveryfrom,
recipientCount, msgText);
}
} catch (AddressException e) {
statusMsg = "Please supply a valid email address.";
outFile.println( statusMsg );
outFile.println( e.getMessage() );
} catch (SendFailedException e) {
statusMsg = "The system was unable to deliver your mail. Please try again later. [SEND FAILED]";
outFile.println( statusMsg );
outFile.println( e.getMessage() );
} catch (MessagingException e) {
statusMsg = "The system was unable to deliver your mail. Please try again later. [MESSAGING]";
outFile.println( statusMsg );
outFile.println( e.getMessage() );
e.printStackTrace();
}
outFile.flush();
outFile.close();
// Redirect to the appropriate confirmation page
if (statusMsg == null && spamReason == null) {
// message was sent successfully
redirectToConfirmation(response, statusMsg);
} else {
// exception occurred
redirectToError( response, statusMsg);
}
}
@Override
public void doPost( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException
{
doGet( request, response );
}
private void redirectToConfirmation(HttpServletResponse response,
String statusMsg) throws IOException {
response.sendRedirect( "test?bodyJsp=" + CONFIRM_PAGE + "&home=" );
}
private void redirectToError(HttpServletResponse response, String statusMsg)
throws IOException {
response.sendRedirect("test?bodyJsp=" + ERR_PAGE + "&ERR=" + statusMsg);
}
/** Intended to mangle url so it can get through spam filtering
* http://host/dir/servlet?param=value -> host: dir/servlet?param=value */
public String stripProtocol( String in ){
if( in == null )
return "";
else
return in.replaceAll("http://", "host: " );
}
private String composeEmail(String webusername, String webuseremail,
String comments, String deliveryfrom,
String originalReferer, String ipAddr) {
StringBuffer msgBuf = new StringBuffer();
// contains the intro copy for the body of the email message
String lineSeparator = System.getProperty("line.separator");
// \r\n on windows, \n on unix
// from MyLibrary
msgBuf.setLength(0);
msgBuf.append("Content-Type: text/html; charset='us-ascii'" + lineSeparator);
msgBuf.append("<html>" + lineSeparator );
msgBuf.append("<head>" + lineSeparator );
msgBuf.append("<style>a {text-decoration: none}</style>" + lineSeparator );
msgBuf.append("<title>" + deliveryfrom + "</title>" + lineSeparator );
msgBuf.append("</head>" + lineSeparator );
msgBuf.append("<body>" + lineSeparator );
msgBuf.append("<h4>" + deliveryfrom + "</h4>" + lineSeparator );
msgBuf.append("<h4>From: "+webusername +" (" + webuseremail + ")" +
" at IP address " + ipAddr + "</h4>"+lineSeparator);
if (!(originalReferer == null || originalReferer.equals("none"))){
//The spam filter that is being used by the listsrv is rejecting <a href="...
//so try with out the markup, if that sill doesn't work,
//uncomment the following line to strip the http://
//msgBuf.append("<p><i>likely viewing page " + stripProtocol(originalReferer) );
msgBuf.append("<p><i>likely viewing page " + originalReferer );
}
msgBuf.append(lineSeparator + "</i></p><h3>Comments:</h3>" + lineSeparator );
if (comments==null || comments.equals("")) {
msgBuf.append("<p>BLANK MESSAGE</p>");
} else {
msgBuf.append("<p>"+comments+"</p>");
}
msgBuf.append("</body>" + lineSeparator );
msgBuf.append("</html>" + lineSeparator );
return msgBuf.toString();
}
private void writeBackupCopy(PrintWriter outFile, String msgText,
String spamReason) {
Calendar cal = Calendar.getInstance();
outFile.println("<hr/>");
outFile.println();
outFile.println("<p>"+cal.getTime()+"</p>");
outFile.println();
if (spamReason != null) {
outFile.println("<p>REJECTED - SPAM</p>");
outFile.println("<p>"+spamReason+"</p>");
outFile.println();
}
outFile.print( msgText );
outFile.println();
outFile.println();
outFile.flush();
// outFile.close();
}
private void sendMessage(Session s, String webuseremail,
String[] deliverToArray, String deliveryfrom, int recipientCount,
String msgText)
throws AddressException, SendFailedException, MessagingException {
// Construct the message
MimeMessage msg = new MimeMessage( s );
//System.out.println("trying to send message from servlet");
// Set the from address
msg.setFrom( new InternetAddress( webuseremail ));
// Set the recipient address
if (recipientCount>0){
InternetAddress[] address=new InternetAddress[recipientCount];
for (int i=0; i<recipientCount; i++){
address[i] = new InternetAddress(deliverToArray[i]);
}
msg.setRecipients( Message.RecipientType.TO, address );
}
// Set the subject and text
msg.setSubject( deliveryfrom );
// add the multipart to the message
msg.setContent(msgText,"text/html");
// set the Date: header
msg.setSentDate( new Date() );
Transport.send( msg ); // try to send the message via smtp - catch error exceptions
}
private String validateInput(String webusername, String webuseremail,
String comments) {
if( webusername == null || "".equals(webusername.trim()) ){
return "A proper webusername field was not found in the form submitted.";
}
if( webuseremail == null || "".equals(webuseremail.trim()) ){
return "A proper webuser email field was not found in the form submitted.";
}
if (comments==null || "".equals(comments.trim())) {
return "The proper comments field was not found in the form submitted.";
}
return null;
}
/**
* @param request
* @return null if message not judged to be spam, otherwise a String
* containing the reason the message was flagged as spam.
*/
private String checkForSpam(String comments) {
/* if this blog markup is found, treat comment as blog spam */
if (
(comments.indexOf("[/url]") > -1
|| comments.indexOf("[/URL]") > -1
|| comments.indexOf("[url=") > -1
|| comments.indexOf("[URL=") > -1)) {
return "The message contained blog link markup.";
}
/* if message is absurdly short, treat as blog spam */
if (comments.length()<15) {
return "The message was too short.";
}
return null;
}
}

View file

@ -0,0 +1,753 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.hp.hpl.jena.vocabulary.OWL;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Datatype;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Ontology;
import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.DatatypeDao;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.search.SearchException;
import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc;
import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc.VitroLuceneTermNames;
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneIndexFactory;
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneSetup;
/**
* This servlet is for servicing Google Refine's
* "Add columns from VIVO" requests.
*
* @author Eliza Chan (elc2013@med.cornell.edu)
*
*/
public class GrefinePropertyListServlet extends VitroHttpServlet {
private int MAXDEPTH = 7;
private int NUM_COLS = 9;
private static String QUERY_PARAMETER_NAME = "term";
public static final int MAX_QUERY_LENGTH = 500;
private static final Log log = LogFactory.getLog(GrefinePropertyListServlet.class.getName());
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//resp.setContentType("application/json");
super.doPost(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
super.doGet(req, resp);
resp.setContentType("application/json");
VitroRequest vreq = new VitroRequest(req);
try {
String callbackStr = (vreq.getParameter("callback") == null) ? ""
: vreq.getParameter("callback");
ServletOutputStream out = resp.getOutputStream();
// *******
// methodology adopted from DatatypePropertiesListingController and ClassHierarchyListingController
// *******
VClassDao vcDao = vreq.getFullWebappDaoFactory().getVClassDao();
DataPropertyDao dao = vreq.getFullWebappDaoFactory().getDataPropertyDao();
String topUri = vreq.getParameter("type");
VClass topClass = vcDao.getVClassByURI(topUri);
HashSet<String> propURIs = new HashSet<String>();
HashMap<VClass, List<DataProperty>> classPropertiesMap =
populateClassPropertiesMap(vcDao, dao, topUri, propURIs);
// Construct json String
JSONObject completeJson = new JSONObject();
JSONArray propertiesJsonArr = new JSONArray();
if (classPropertiesMap.size() > 0) {
for (Iterator<VClass> iter = classPropertiesMap.keySet().iterator(); iter.hasNext();) { // add results to schema
VClass vc = (VClass) iter.next();
System.out.println("vc uri: " + vc.getURI());
System.out.println("vc name: " + vc.getName());
ArrayList<DataProperty> vcProps = (ArrayList<DataProperty>)classPropertiesMap.get(vc);
for (DataProperty prop: vcProps) {
String nameStr = prop.getPublicName()==null ? prop.getName()==null ? null : prop.getName() : prop.getPublicName();
System.out.println("--- uri: " + prop.getURI());
System.out.println("--- name: " + nameStr);
// top level
JSONObject propertiesItemJson = new JSONObject();
JSONObject rootSchemaJson = new JSONObject();
rootSchemaJson.put("id", vc.getURI());
rootSchemaJson.put("name", vc.getName());
rootSchemaJson.put("alias", new JSONArray());
propertiesItemJson.put("schema", rootSchemaJson);
// second level
propertiesItemJson.put("id", prop.getURI());
propertiesItemJson.put("name", nameStr);
propertiesItemJson.put("alias", new JSONArray());
JSONObject expectsJson = new JSONObject();
expectsJson.put("id", prop.getURI());
expectsJson.put("name", nameStr);
expectsJson.put("alias", new JSONArray());
propertiesItemJson.put("expects", expectsJson);
propertiesJsonArr.put(propertiesItemJson);
}
}
}
// get data properties from subclasses
List<VClass> lvl2Classes = new ArrayList<VClass>();
List roots = null;
String requestType = vreq.getParameter("type");
if (requestType != null) {
roots = new LinkedList<VClass>();
roots.add(vcDao.getVClassByURI(requestType));
}
if (roots != null) {
String ontologyUri = null;
Collections.sort(roots);
Iterator rootIt = roots.iterator();
if (rootIt.hasNext()) {
while (rootIt.hasNext()) {
VClass root = (VClass) rootIt.next();
if (root != null) {
List<VClass> lvl2ChildClasses = new ArrayList<VClass>();
addChildren(vcDao, vreq.getFullWebappDaoFactory(), root, lvl2ChildClasses, 0, ontologyUri);
lvl2Classes.addAll(lvl2ChildClasses);
}
}
}
}
for (VClass lvl2Class: lvl2Classes) {
HashMap<VClass, List<DataProperty>> lvl2ClassPropertiesMap =
populateClassPropertiesMap(vcDao, dao, lvl2Class.getURI(), propURIs);
if (lvl2ClassPropertiesMap.size() > 0) {
for (Iterator<VClass> iter = lvl2ClassPropertiesMap.keySet().iterator(); iter.hasNext();) { // add results to schema
VClass vc = (VClass) iter.next();
ArrayList<DataProperty> vcProps = (ArrayList<DataProperty>)lvl2ClassPropertiesMap.get(vc);
for (DataProperty prop: vcProps) {
String nameStr = prop.getPublicName()==null ? prop.getName()==null ? null : prop.getName() : prop.getPublicName();
// top level
JSONObject propertiesItemJson = new JSONObject();
JSONObject rootSchemaJson = new JSONObject();
rootSchemaJson.put("id", topClass.getURI());
rootSchemaJson.put("name", topClass.getName());
rootSchemaJson.put("alias", new JSONArray());
propertiesItemJson.put("schema", rootSchemaJson);
// second level
propertiesItemJson.put("id", vc.getURI());
propertiesItemJson.put("name", vc.getName());
propertiesItemJson.put("alias", new JSONArray());
propertiesItemJson.put("id2", prop.getURI());
propertiesItemJson.put("name2", nameStr);
propertiesItemJson.put("alias2", new JSONArray());
JSONObject expectsJson = new JSONObject();
expectsJson.put("id", prop.getURI());
expectsJson.put("name", nameStr);
expectsJson.put("alias", new JSONArray());
propertiesItemJson.put("expects", expectsJson);
propertiesJsonArr.put(propertiesItemJson);
}
}
}
}
completeJson.put("properties", propertiesJsonArr);
out.print(callbackStr + "(" + completeJson.toString() + ")");
} catch (Exception ex) {
log.warn(ex, ex);
}
}
private HashMap<VClass, List<DataProperty>> populateClassPropertiesMap (
VClassDao vcDao,
DataPropertyDao dao,
String uri,
HashSet<String> propURIs) {
HashMap<VClass, List<DataProperty>> classPropertiesMap = new HashMap<VClass, List<DataProperty>>();
List<DataProperty> props = new ArrayList<DataProperty>();
VClass topVc = vcDao.getVClassByURI(uri);
Collection <DataProperty> dataProps = dao.getDataPropertiesForVClass(uri);
Iterator<DataProperty> dataPropIt = dataProps.iterator();
while (dataPropIt.hasNext()) {
DataProperty dp = dataPropIt.next();
if (!(propURIs.contains(dp.getURI()))) {
propURIs.add(dp.getURI());
DataProperty prop = dao.getDataPropertyByURI(dp.getURI());
if (prop != null) {
props.add(prop);
}
}
}
if (props.size() > 0) {
Collections.sort(props);
for (DataProperty prop: props) {
String nameStr = prop.getPublicName()==null ? prop.getName()==null ? null : prop.getName() : prop.getPublicName();
if (nameStr != null) {
if (prop.getDomainClassURI() != null) {
VClass vc = vcDao.getVClassByURI(prop.getDomainClassURI());
if (classPropertiesMap.get(vc) != null) {
ArrayList<DataProperty> existingList = (ArrayList<DataProperty>)classPropertiesMap.get(vc);
existingList.add(prop);
} else {
ArrayList<DataProperty> newList = new ArrayList<DataProperty>();
newList.add(prop);
classPropertiesMap.put(vc, newList);
}
} else { // some properties have no domain, belong to top vc by default
if (classPropertiesMap.get(topVc) != null) {
ArrayList<DataProperty> existingList = (ArrayList<DataProperty>)classPropertiesMap.get(topVc);
existingList.add(prop);
} else {
ArrayList<DataProperty> newList = new ArrayList<DataProperty>();
newList.add(prop);
classPropertiesMap.put(topVc, newList);
}
}
}
}
}
return classPropertiesMap;
}
private void addChildren(VClassDao vcDao, WebappDaoFactory wadf, VClass parent, List<VClass> list, int position, String ontologyUri) {
List<VClass> rowElts = addVClassDataToResultsList(wadf, parent, position, ontologyUri);
int childShift = (rowElts.size() > 0) ? 1 : 0; // if addVClassDataToResultsList filtered out the result, don't shift the children over
list.addAll(rowElts);
List childURIstrs = vcDao.getSubClassURIs(parent.getURI());
if ((childURIstrs.size()>0) && position<MAXDEPTH) {
List childClasses = new ArrayList();
Iterator childURIstrIt = childURIstrs.iterator();
while (childURIstrIt.hasNext()) {
String URIstr = (String) childURIstrIt.next();
try {
VClass child = (VClass) vcDao.getVClassByURI(URIstr);
if (!child.getURI().equals(OWL.Nothing.getURI())) {
childClasses.add(child);
}
} catch (Exception e) {}
}
Collections.sort(childClasses);
Iterator childClassIt = childClasses.iterator();
while (childClassIt.hasNext()) {
VClass child = (VClass) childClassIt.next();
addChildren(vcDao, wadf, child, list, position + childShift, ontologyUri);
}
}
}
private List<VClass> addVClassDataToResultsList(WebappDaoFactory wadf, VClass vcw, int position, String ontologyUri) {
List<VClass> results = new ArrayList<VClass>();
if (ontologyUri == null || ( (vcw.getNamespace()!=null) && (vcw.getNamespace().equals(ontologyUri)) ) ) {
results.add(vcw);
/*
for (int i=0; i<position; i++) {
results.add("@@entities");
}
if (position==0)
results.add("XX"); // column 1
Integer numCols = (NUM_COLS-1)-position;
try {
numCols = addColToResults(((vcw.getLocalNameWithPrefix() == null) ? "" : "<a href=\"vclassEdit?uri="+URLEncoder.encode(vcw.getURI(),"UTF-8")+"\">"+vcw.getLocalNameWithPrefix()+"</a>"), results, numCols);
} catch (Exception e) {
numCols = addColToResults(((vcw.getLocalNameWithPrefix() == null) ? "" : vcw.getLocalNameWithPrefix()), results, numCols); // column 2
}
numCols = addColToResults(((vcw.getShortDef() == null) ? "" : vcw.getShortDef()), results, numCols); // column 3
numCols = addColToResults(((vcw.getExample() == null) ? "" : vcw.getExample()), results, numCols); // column 4
// Get group name if it exists
VClassGroupDao groupDao= wadf.getVClassGroupDao();
String groupURI = vcw.getGroupURI();
String groupName = null;
VClassGroup classGroup = null;
if(groupURI != null) {
classGroup = groupDao.getGroupByURI(groupURI);
if (classGroup != null) {
groupName = classGroup.getPublicName();
}
}
numCols = addColToResults(((groupName == null) ? "" : groupName), results, numCols); // column 5
// Get ontology name
String ontName = null;
try {
OntologyDao ontDao = wadf.getOntologyDao();
Ontology ont = ontDao.getOntologyByURI(vcw.getNamespace());
ontName = ont.getName();
} catch (Exception e) {}
numCols = addColToResults(((ontName == null) ? "" : ontName), results, numCols); // column 6
numCols = addColToResults(vcw.getHiddenFromDisplayBelowRoleLevel() == null ? "unspecified" : vcw.getHiddenFromDisplayBelowRoleLevel().getShorthand(), results, numCols); // column 7
numCols = addColToResults(vcw.getProhibitedFromUpdateBelowRoleLevel() == null ? "unspecified" : vcw.getProhibitedFromUpdateBelowRoleLevel().getShorthand(), results, numCols); // column 8
results.add("XX"); // column 9
*/
}
return results;
}
private Integer addColToResults (String value, List results, Integer colIndex) {
if (colIndex>0) {
results.add(value);
}
return colIndex-1;
}
protected JSONObject getResult(VitroRequest vreq, HttpServletRequest req,
HttpServletResponse resp) throws ServletException {
HashMap<String, JSONObject> searchWithTypeMap = new HashMap<String, JSONObject>();
HashMap<String, JSONObject> searchNoTypeMap = new HashMap<String, JSONObject>();
ArrayList<String> queries = new ArrayList<String>();
Object qObj = vreq.getParameter("queries");
if (qObj == null) {
qObj = vreq.getParameter("query");
}
if (qObj != null && qObj instanceof String) {
// e.g.
// {"q0":{"query":"Cathleen","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"},
// "q1":{"query":"Geoffrey","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"},
// "q2":{"query":"Dina","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"}}
String qStr = (String) qObj;
queries.add(qStr);
}
try {
for (int i = 0; i < queries.size(); i++) {
String queryStr = (String) queries.get(i);
JSONObject json = new JSONObject(queryStr);
if (json.has("query")) { // single query
if (json.has("type")) {
searchWithTypeMap.put("query", json);
} else {
// user did not specify a type
searchNoTypeMap.put("query", json);
}
} else { // multiple queries
for (Iterator<String> iter = json.keys(); iter.hasNext();) {
ArrayList<JSONObject> jsonList = new ArrayList<JSONObject>();
String key = (String) iter.next();
Object obj = json.get(key);
JSONObject jsonLvl2 = (JSONObject) obj;
if (jsonLvl2.has("query")) {
if (jsonLvl2.has("type")) {
searchWithTypeMap.put(key, jsonLvl2);
} else {
// user did not specify a type
searchNoTypeMap.put(key, jsonLvl2);
}
}
}
}
}
} catch (JSONException ex) {
System.err.println("JSONReconcileServlet JSONException: " + ex);
throw new ServletException("JSONReconcileServlet JSONException: "
+ ex);
}
// Run index search
JSONObject qJson = null;
if (searchWithTypeMap.size() > 0) {
qJson = runSearch(searchWithTypeMap, vreq);
} else {
qJson = runSearch(searchNoTypeMap, vreq);
}
return qJson;
}
/**
* Returns a default JSON response.
*
* @param req
* @param resp
* @return
* @throws ServletException
*/
protected JSONObject getMetadata(HttpServletRequest req, HttpServletResponse resp, String defaultNamespace,
String defaultTypeList, String serverName, int serverPort) throws ServletException {
JSONObject json = new JSONObject();
try {
json.put("name", "VIVO Reconciliation Service");
if (defaultNamespace != null) {
json.put("identifierSpace", defaultNamespace);
json.put("schemaSpace", defaultNamespace);
}
JSONObject viewJson = new JSONObject();
StringBuffer urlBuf = new StringBuffer();
urlBuf.append("http://" + serverName);
if (serverPort == 8080) {
urlBuf.append(":" + serverPort);
}
if (req.getContextPath() != null) {
urlBuf.append(req.getContextPath());
}
viewJson.put("url", urlBuf.toString() + "/individual?uri={{id}}");
json.put("view", viewJson);
// parse defaultTypeList from deploy.properties
if (defaultTypeList != null) {
String[] splitList = defaultTypeList.split(";");
String[][] idNameArray = new String[splitList.length][splitList.length];
for(int i = 0; i<splitList.length; i++) {
idNameArray[i] = splitList[i].split(",");
}
// process and add to json defaultTypes
JSONArray defaultTypesJsonArr = new JSONArray();
for (int i = 0; i<idNameArray.length; i++) {
JSONObject defaultTypesJson = new JSONObject();
defaultTypesJson.put("id", idNameArray[i][0].trim());
defaultTypesJson.put("name", idNameArray[i][1].trim());
defaultTypesJsonArr.put(defaultTypesJson);
}
json.put("defaultTypes", defaultTypesJsonArr);
}
} catch (JSONException ex) {
throw new ServletException(
"JSONReconcileServlet: Could not create metadata: " + ex);
}
return json;
}
private JSONObject runSearch(HashMap<String, JSONObject> currMap,
VitroRequest vreq) throws ServletException {
JSONObject qJson = new JSONObject();
try {
Analyzer analyzer = getAnalyzer(getServletContext());
IndexSearcher searcherForRequest = LuceneIndexFactory
.getIndexSearcher(getServletContext());
for (Map.Entry<String, JSONObject> entry : currMap.entrySet()) {
JSONObject resultAllJson = new JSONObject();
String key = entry.getKey();
JSONObject json = (JSONObject) entry.getValue();
String queryVal = json.getString("query");
// continue with properties list
String searchType = null;
int limit = 3; // default
String typeStrict = "should"; // default
ArrayList<String[]> propertiesList = new ArrayList<String[]>();
if (json.has("type")) {
searchType = json.getString("type");
}
if (json.has("limit")) {
limit = json.getInt("limit");
}
if (json.has("type_strict")) { // Not sure what this variable
// represents. Skip for now.
typeStrict = json.getString("type_strict");
}
if (json.has("properties")) {
JSONArray properties = json.getJSONArray("properties");
for (int i = 0; i < properties.length(); i++) {
String[] pvPair = new String[2];
JSONObject jsonProperty = properties.getJSONObject(i);
String pid = jsonProperty.getString("pid");
String v = jsonProperty.getString("v");
pvPair[0] = pid;
pvPair[1] = v;
propertiesList.add(pvPair);
}
}
// begin search
JSONArray resultJsonArr = new JSONArray();
Query query = getReconcileQuery(vreq, analyzer,
queryVal, searchType, propertiesList);
TopDocs topDocs = searcherForRequest.search(query, null, limit);
if (topDocs != null && topDocs.scoreDocs != null) {
int hitsLength = topDocs.scoreDocs.length;
if (hitsLength > 0) {
for (int i = 0; i < topDocs.scoreDocs.length; i++) {
JSONObject resultJson = new JSONObject();
float score = topDocs.scoreDocs[i].score;
resultJson.put("score", score);
Document doc = searcherForRequest
.doc(topDocs.scoreDocs[i].doc);
String uri = doc.get(Entity2LuceneDoc.term.URI);
IndividualDao iDao = vreq.getWebappDaoFactory()
.getIndividualDao();
Individual ind = iDao.getIndividualByURI(uri);
if (ind != null) {
String name = ind.getName();
// encode # to %23
String modUri = uri.replace("#", "%23");
resultJson.put("id", modUri);
resultJson.put("name", name);
}
List fields = doc.getFields();
JSONArray typesJsonArr = new JSONArray();
for (int j = 0; j < fields.size(); j++) {
Field field = (Field) fields.get(j);
String fieldName = field.name();
if ("type".equals(fieldName)) {
// e.g. http://aims.fao.org/aos/geopolitical.owl#area
String type = field.stringValue();
int lastIndex2 = type.lastIndexOf('/') + 1;
String typeName = type
.substring(lastIndex2);
typeName = typeName.replace("#", ":");
JSONObject typesJson = new JSONObject();
typesJson.put("id", type);
typesJson.put("name", typeName);
typesJsonArr.put(typesJson);
}
}
resultJson.put("type", typesJsonArr);
resultJson.put("match", "false");
resultJsonArr.put(resultJson);
}
}
}
resultAllJson.put("result", resultJsonArr);
qJson.put(key, resultAllJson);
}
} catch (JSONException ex) {
System.err.println("JSONReconcileServlet JSONException: " + ex);
throw new ServletException("JSONReconcileServlet JSONException: "
+ ex);
} catch (SearchException ex) {
System.err.println("JSONReconcileServlet SearchException: " + ex);
throw new ServletException("JSONReconcileServlet SearchException: "
+ ex);
} catch (IOException ex) {
System.err.println("JSONReconcileServlet IOException: " + ex);
throw new ServletException("JSONReconcileServlet IOException: "
+ ex);
}
return qJson;
}
private Analyzer getAnalyzer(ServletContext servletContext)
throws SearchException {
Object obj = servletContext.getAttribute(LuceneSetup.ANALYZER);
if (obj == null || !(obj instanceof Analyzer))
throw new SearchException("Could not get anlyzer");
else
return (Analyzer) obj;
}
private Query makeReconcileNameQuery(String querystr, Analyzer analyzer, HttpServletRequest request) {
/* Original code
String tokenizeParam = (String) request.getParameter("tokenize");
boolean tokenize = "true".equals(tokenizeParam);
// Note: Stemming is only relevant if we are tokenizing: an untokenized name
// query will not be stemmed. So we don't look at the stem parameter until we get to
// makeTokenizedNameQuery().
if (tokenize) {
return makeTokenizedNameQuery(querystr, analyzer, request);
} else {
return makeUntokenizedNameQuery(querystr);
}
*/
// modified code for reconciliation service
request.setAttribute("stem", true);
return makeTokenizedNameQuery(querystr, analyzer, request);
}
private Query makeTokenizedNameQuery(String querystr, Analyzer analyzer, HttpServletRequest request) {
String stemParam = (String) request.getParameter("stem");
boolean stem = "true".equals(stemParam);
String termName = stem ? VitroLuceneTermNames.NAME_STEMMED : VitroLuceneTermNames.NAME_UNSTEMMED;
BooleanQuery boolQuery = new BooleanQuery();
// Use the query parser to analyze the search term the same way the indexed text was analyzed.
// For example, text is lowercased, and function words are stripped out.
QueryParser parser = getQueryParser(termName, analyzer);
// The wildcard query doesn't play well with stemming. Query term name:tales* doesn't match
// "tales", which is indexed as "tale", while query term name:tales does. Obviously we need
// the wildcard for name:tal*, so the only way to get them all to match is use a disjunction
// of wildcard and non-wildcard queries. The query will look have only an implicit disjunction
// operator: e.g., +(name:tales name:tales*)
try {
log.debug("Adding non-wildcard query for " + querystr);
Query query = parser.parse(querystr);
boolQuery.add(query, BooleanClause.Occur.SHOULD);
// Prevent ParseException here when adding * after a space.
// If there's a space at the end, we don't need the wildcard query.
if (! querystr.endsWith(" ")) {
log.debug("Adding wildcard query for " + querystr);
Query wildcardQuery = parser.parse(querystr + "*");
boolQuery.add(wildcardQuery, BooleanClause.Occur.SHOULD);
}
log.debug("Name query is: " + boolQuery.toString());
} catch (ParseException e) {
log.warn(e, e);
}
return boolQuery;
}
private Query makeUntokenizedNameQuery(String querystr) {
querystr = querystr.toLowerCase();
String termName = VitroLuceneTermNames.NAME_LOWERCASE;
BooleanQuery query = new BooleanQuery();
log.debug("Adding wildcard query on unanalyzed name");
query.add(
new WildcardQuery(new Term(termName, querystr + "*")),
BooleanClause.Occur.MUST);
return query;
}
private QueryParser getQueryParser(String searchField, Analyzer analyzer){
// searchField indicates which field to search against when there is no term
// indicated in the query string.
// The analyzer is needed so that we use the same analyzer on the search queries as
// was used on the text that was indexed.
QueryParser qp = new QueryParser(searchField,analyzer);
//this sets the query parser to AND all of the query terms it finds.
qp.setDefaultOperator(QueryParser.AND_OPERATOR);
return qp;
}
private Query getReconcileQuery(VitroRequest request, Analyzer analyzer,
String querystr, String typeParam, ArrayList<String[]> propertiesList) throws SearchException{
Query query = null;
try {
if( querystr == null){
log.error("There was no Parameter '"+ QUERY_PARAMETER_NAME
+"' in the request.");
return null;
}else if( querystr.length() > MAX_QUERY_LENGTH ){
log.debug("The search was too long. The maximum " +
"query length is " + MAX_QUERY_LENGTH );
return null;
}
query = makeReconcileNameQuery(querystr, analyzer, request);
// filter by type
if (typeParam != null) {
BooleanQuery boolQuery = new BooleanQuery();
boolQuery.add( new TermQuery(
new Term(VitroLuceneTermNames.RDFTYPE,
typeParam)),
BooleanClause.Occur.MUST);
boolQuery.add(query, BooleanClause.Occur.MUST);
query = boolQuery;
}
// if propertiesList has elements, add extra queries to query
Iterator<String[]> it = propertiesList.iterator();
while (it.hasNext()) {
String[] pvPair = it.next();
Query extraQuery = makeReconcileNameQuery(pvPair[1], analyzer, request);
if (!"".equals(pvPair[0]) && pvPair[0] != null) {
BooleanQuery boolQuery = new BooleanQuery();
boolQuery.add(new TermQuery(new Term(
VitroLuceneTermNames.RDFTYPE, pvPair[0])),
BooleanClause.Occur.MUST);
boolQuery.add(extraQuery, BooleanClause.Occur.MUST);
extraQuery = boolQuery;
}
((BooleanQuery)query).add(extraQuery, BooleanClause.Occur.MUST);
}
} catch (Exception ex) {
throw new SearchException(ex.getMessage());
}
return query;
}
}

View file

@ -15,6 +15,7 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
@ -53,7 +54,8 @@ import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneSetup;
*/
public class JSONReconcileServlet extends VitroHttpServlet {
private static String QUERY_PARAMETER_NAME = "term";
private static final long serialVersionUID = 1L;
private static String QUERY_PARAMETER_NAME = "term";
public static final int MAX_QUERY_LENGTH = 500;
private static final Log log = LogFactory.getLog(JSONReconcileServlet.class.getName());
@ -70,14 +72,14 @@ public class JSONReconcileServlet extends VitroHttpServlet {
super.doGet(req, resp);
resp.setContentType("application/json");
VitroRequest vreq = new VitroRequest(req);
System.out.println("vreq");
System.out.println(vreq.getWebappDaoFactory());
//log.debug("vreq");
//log.debug(vreq.getWebappDaoFactory());
try {
if (vreq.getParameter("query") != null
|| vreq.getParameter("queries") != null) {
JSONObject qJson = getResult(vreq, req, resp);
System.out.println("result: " + qJson.toString());
log.debug("result: " + qJson.toString());
String responseStr = (vreq.getParameter("callback") == null) ? qJson
.toString() : vreq.getParameter("callback") + "("
+ qJson.toString() + ")";
@ -124,8 +126,7 @@ public class JSONReconcileServlet extends VitroHttpServlet {
// "q2":{"query":"Dina","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"}}
String qStr = (String) qObj;
queries.add(qStr);
System.out.println();
System.out.println("query: " + qStr + "\n");
log.debug("\nquery: " + qStr + "\n");
}
try {
@ -158,7 +159,7 @@ public class JSONReconcileServlet extends VitroHttpServlet {
}
}
} catch (JSONException ex) {
System.err.println("JSONReconcileServlet JSONException: " + ex);
log.error("JSONException: " + ex);
throw new ServletException("JSONReconcileServlet JSONException: "
+ ex);
}
@ -327,15 +328,15 @@ public class JSONReconcileServlet extends VitroHttpServlet {
}
} catch (JSONException ex) {
System.err.println("JSONReconcileServlet JSONException: " + ex);
log.error("JSONException: " + ex);
throw new ServletException("JSONReconcileServlet JSONException: "
+ ex);
} catch (SearchException ex) {
System.err.println("JSONReconcileServlet SearchException: " + ex);
log.error("SearchException: " + ex);
throw new ServletException("JSONReconcileServlet SearchException: "
+ ex);
} catch (IOException ex) {
System.err.println("JSONReconcileServlet IOException: " + ex);
log.error("IOException: " + ex);
throw new ServletException("JSONReconcileServlet IOException: "
+ ex);
}
@ -354,30 +355,12 @@ public class JSONReconcileServlet extends VitroHttpServlet {
private Query makeReconcileNameQuery(String querystr, Analyzer analyzer, HttpServletRequest request) {
/* Original code
String tokenizeParam = (String) request.getParameter("tokenize");
boolean tokenize = "true".equals(tokenizeParam);
// Note: Stemming is only relevant if we are tokenizing: an untokenized name
// query will not be stemmed. So we don't look at the stem parameter until we get to
// makeTokenizedNameQuery().
if (tokenize) {
return makeTokenizedNameQuery(querystr, analyzer, request);
} else {
return makeUntokenizedNameQuery(querystr);
}
*/
// modified code for reconciliation service
request.setAttribute("stem", true);
return makeTokenizedNameQuery(querystr, analyzer, request);
}
private Query makeTokenizedNameQuery(String querystr, Analyzer analyzer, HttpServletRequest request) {
String stemParam = (String) request.getParameter("stem");
boolean stem = "true".equals(stemParam);
String termName = stem ? VitroLuceneTermNames.NAME_STEMMED : VitroLuceneTermNames.NAME_UNSTEMMED;
String termName = VitroLuceneTermNames.NAME_STEMMED;
BooleanQuery boolQuery = new BooleanQuery();
@ -407,23 +390,9 @@ public class JSONReconcileServlet extends VitroHttpServlet {
} catch (ParseException e) {
log.warn(e, e);
}
return boolQuery;
}
private Query makeUntokenizedNameQuery(String querystr) {
querystr = querystr.toLowerCase();
String termName = VitroLuceneTermNames.NAME_LOWERCASE;
BooleanQuery query = new BooleanQuery();
log.debug("Adding wildcard query on unanalyzed name");
query.add(
new WildcardQuery(new Term(termName, querystr + "*")),
BooleanClause.Occur.MUST);
return query;
}
private QueryParser getQueryParser(String searchField, Analyzer analyzer){
// searchField indicates which field to search against when there is no term
@ -450,10 +419,8 @@ public class JSONReconcileServlet extends VitroHttpServlet {
"query length is " + MAX_QUERY_LENGTH );
return null;
}
query = makeReconcileNameQuery(querystr, analyzer, request);
// filter by type
if (typeParam != null) {
@ -471,7 +438,7 @@ public class JSONReconcileServlet extends VitroHttpServlet {
while (it.hasNext()) {
String[] pvPair = it.next();
Query extraQuery = makeReconcileNameQuery(pvPair[1], analyzer, request);
if (!"".equals(pvPair[0]) && pvPair[0] != null) {
if ( ! StringUtils.isEmpty(pvPair[0]) ) {
BooleanQuery boolQuery = new BooleanQuery();
boolQuery.add(new TermQuery(new Term(
VitroLuceneTermNames.RDFTYPE, pvPair[0])),
@ -489,3 +456,4 @@ public class JSONReconcileServlet extends VitroHttpServlet {
}
}

View file

@ -39,7 +39,7 @@ public class UserAccountsSelector {
+ "PREFIX fn: <http://www.w3.org/2005/xpath-functions#> \n"
+ "PREFIX auth: <http://vitro.mannlib.cornell.edu/ns/vitro/authorization#> \n";
private static final String ALL_VARIABLES = "?uri ?email ?firstName ?lastName ?pwd ?expire ?count ?status";
private static final String ALL_VARIABLES = "?uri ?email ?firstName ?lastName ?pwd ?expire ?count ?status ?isRoot";
private static final String COUNT_VARIABLE = "?uri";
@ -169,7 +169,8 @@ public class UserAccountsSelector {
+ " OPTIONAL { ?uri auth:md5password ?pwd } \n"
+ " OPTIONAL { ?uri auth:passwordChangeExpires ?expire } \n"
+ " OPTIONAL { ?uri auth:loginCount ?count } \n"
+ " OPTIONAL { ?uri auth:status ?status }";
+ " OPTIONAL { ?uri auth:status ?status } \n"
+ " OPTIONAL { ?uri ?isRoot auth:RootUserAccount }";
}
private String filterClauses() {
@ -201,11 +202,10 @@ public class UserAccountsSelector {
}
/**
* Escape any regex special characters in the string.
* Escape any regex special characters in the string.
*
* Note that the SPARQL
* parser requires two backslashes, in order to pass a single backslash to
* the REGEX function.
* Note that the SPARQL parser requires two backslashes, in order to pass a
* single backslash to the REGEX function.
*/
private String escapeForRegex(String raw) {
StringBuilder clean = new StringBuilder();
@ -327,6 +327,7 @@ public class UserAccountsSelector {
user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L));
user.setLoginCount(ifIntPresent(solution, "count", 0));
user.setStatus(parseStatus(solution, "status", null));
user.setRootUser(solution.contains("isRoot"));
return user;
}

View file

@ -22,6 +22,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Tem
public class UserAccountsAddPage extends UserAccountsPage {
private static final String PARAMETER_SUBMIT = "submitAdd";
private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress";
private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId";
private static final String PARAMETER_FIRST_NAME = "firstName";
private static final String PARAMETER_LAST_NAME = "lastName";
private static final String PARAMETER_ROLE = "role";
@ -30,6 +31,7 @@ public class UserAccountsAddPage extends UserAccountsPage {
private static final String ERROR_NO_EMAIL = "errorEmailIsEmpty";
private static final String ERROR_EMAIL_IN_USE = "errorEmailInUse";
private static final String ERROR_EMAIL_INVALID_FORMAT = "errorEmailInvalidFormat";
private static final String ERROR_EXTERNAL_AUTH_ID_IN_USE = "errorExternalAuthIdInUse";
private static final String ERROR_NO_FIRST_NAME = "errorFirstNameIsEmpty";
private static final String ERROR_NO_LAST_NAME = "errorLastNameIsEmpty";
private static final String ERROR_NO_ROLE = "errorNoRoleSelected";
@ -41,6 +43,7 @@ public class UserAccountsAddPage extends UserAccountsPage {
/* The request parameters */
private boolean submit;
private String emailAddress = "";
private String externalAuthId = "";
private String firstName = "";
private String lastName = "";
private String selectedRoleUri = "";
@ -68,6 +71,7 @@ public class UserAccountsAddPage extends UserAccountsPage {
private void parseRequestParameters() {
submit = isFlagOnRequest(PARAMETER_SUBMIT);
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, "");
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
selectedRoleUri = getStringParameter(PARAMETER_ROLE, "");
@ -88,6 +92,8 @@ public class UserAccountsAddPage extends UserAccountsPage {
errorCode = ERROR_EMAIL_IN_USE;
} else if (!isEmailValidFormat()) {
errorCode = ERROR_EMAIL_INVALID_FORMAT;
} else if (isExternalAuthIdInUse()) {
errorCode = ERROR_EXTERNAL_AUTH_ID_IN_USE;
} else if (firstName.isEmpty()) {
errorCode = ERROR_NO_FIRST_NAME;
} else if (lastName.isEmpty()) {
@ -103,10 +109,17 @@ public class UserAccountsAddPage extends UserAccountsPage {
return userAccountsDao.getUserAccountByEmail(emailAddress) != null;
}
private boolean isExternalAuthIdInUse() {
if (externalAuthId.isEmpty()) {
return false;
}
return userAccountsDao.getUserAccountByExternalAuthId(externalAuthId) != null;
}
private boolean isEmailValidFormat() {
return Authenticator.isValidEmailAddress(emailAddress);
}
public boolean isValid() {
return errorCode.isEmpty();
}
@ -116,7 +129,7 @@ public class UserAccountsAddPage extends UserAccountsPage {
u.setEmailAddress(emailAddress);
u.setFirstName(firstName);
u.setLastName(lastName);
u.setExternalAuthId("");
u.setExternalAuthId(externalAuthId);
u.setMd5Password("");
u.setOldPassword("");
@ -139,6 +152,7 @@ public class UserAccountsAddPage extends UserAccountsPage {
Map<String, Object> body = new HashMap<String, Object>();
body.put("emailAddress", emailAddress);
body.put("externalAuthId", externalAuthId);
body.put("firstName", firstName);
body.put("lastName", lastName);
body.put("selectedRole", selectedRoleUri);

View file

@ -57,6 +57,7 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
private static class EmailStrategy extends UserAccountsAddPageStrategy {
public static final String CREATE_PASSWORD_URL = "/accounts/createPassword";
private static final String EMAIL_TEMPLATE = "userAccounts-acctCreatedEmail.ftl";
private boolean sentEmail;
@ -91,15 +92,14 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage {
Map<String, Object> body = new HashMap<String, Object>();
body.put("userAccount", page.getAddedAccount());
body.put("passwordLink", buildCreatePasswordLink());
body.put("subjectLine", "Your VIVO account has been created.");
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, page.getAddedAccount().getEmailAddress());
email.setSubject("Your VIVO account has been created.");
email.setHtmlTemplate("userAccounts-acctCreatedEmail-html.ftl");
email.setTextTemplate("userAccounts-acctCreatedEmail-text.ftl");
email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
email.processTemplate();
email.send();
sentEmail = true;

View file

@ -57,9 +57,9 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
if (page.isSubmit() && page.isValid()) {
page.createNewAccount();
UserAccountsListPage listPage = new UserAccountsListPage(vreq);
return listPage.showPageWithNewAccount(page.getAddedAccount(),
page.wasPasswordEmailSent());
UserAccountsListPage.Message.showNewAccount(vreq,
page.getAddedAccount(), page.wasPasswordEmailSent());
return redirectToList();
} else {
return page.showPage();
}
@ -71,9 +71,10 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
return showHomePage(vreq, page.getBogusMessage());
} else if (page.isSubmit() && page.isValid()) {
page.updateAccount();
UserAccountsListPage listPage = new UserAccountsListPage(vreq);
return listPage.showPageWithUpdatedAccount(
UserAccountsListPage.Message.showUpdatedAccount(vreq,
page.getUpdatedAccount(), page.wasPasswordEmailSent());
return redirectToList();
} else {
return page.showPage();
}
@ -83,8 +84,8 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
UserAccountsDeleter deleter = new UserAccountsDeleter(vreq);
Collection<String> deletedUris = deleter.delete();
return new UserAccountsListPage(vreq)
.showPageWithDeletions(deletedUris);
UserAccountsListPage.Message.showDeletions(vreq, deletedUris);
return redirectToList();
}
private ResponseValues handleListRequest(VitroRequest vreq) {
@ -92,6 +93,14 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
return page.showPage();
}
/**
* After an successful change, redirect to the list instead of forwarding.
* That way, a browser "refresh" won't try to repeat the operation.
*/
private ResponseValues redirectToList() {
return new RedirectResponseValues("/accountsAdmin/list");
}
private ResponseValues showHomePage(VitroRequest vreq, String message) {
DisplayMessage.setMessage(vreq, message);
return new RedirectResponseValues("/");

View file

@ -28,6 +28,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
private static final String PARAMETER_SUBMIT = "submitEdit";
private static final String PARAMETER_USER_URI = "editAccount";
private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress";
private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId";
private static final String PARAMETER_FIRST_NAME = "firstName";
private static final String PARAMETER_LAST_NAME = "lastName";
private static final String PARAMETER_ROLE = "role";
@ -36,6 +37,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
private static final String ERROR_NO_EMAIL = "errorEmailIsEmpty";
private static final String ERROR_EMAIL_IN_USE = "errorEmailInUse";
private static final String ERROR_EMAIL_INVALID_FORMAT = "errorEmailInvalidFormat";
private static final String ERROR_EXTERNAL_AUTH_ID_IN_USE = "errorExternalAuthIdInUse";
private static final String ERROR_NO_FIRST_NAME = "errorFirstNameIsEmpty";
private static final String ERROR_NO_LAST_NAME = "errorLastNameIsEmpty";
private static final String ERROR_NO_ROLE = "errorNoRoleSelected";
@ -48,6 +50,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
private boolean submit;
private String userUri = "";
private String emailAddress = "";
private String externalAuthId = "";
private String firstName = "";
private String lastName = "";
private String selectedRoleUri = "";
@ -79,6 +82,7 @@ public class UserAccountsEditPage extends UserAccountsPage {
submit = isFlagOnRequest(PARAMETER_SUBMIT);
userUri = getStringParameter(PARAMETER_USER_URI, "");
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, "");
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
selectedRoleUri = getStringParameter(PARAMETER_ROLE, "");
@ -117,11 +121,13 @@ public class UserAccountsEditPage extends UserAccountsPage {
errorCode = ERROR_EMAIL_IN_USE;
} else if (!isEmailValidFormat()) {
errorCode = ERROR_EMAIL_INVALID_FORMAT;
} else if (externalAuthIdIsChanged() && isExternalAuthIdInUse()) {
errorCode = ERROR_EXTERNAL_AUTH_ID_IN_USE;
} else if (firstName.isEmpty()) {
errorCode = ERROR_NO_FIRST_NAME;
} else if (lastName.isEmpty()) {
errorCode = ERROR_NO_LAST_NAME;
} else if (selectedRoleUri.isEmpty()) {
} else if (!isRootUser() && selectedRoleUri.isEmpty()) {
errorCode = ERROR_NO_ROLE;
} else {
errorCode = strategy.additionalValidations();
@ -139,7 +145,22 @@ public class UserAccountsEditPage extends UserAccountsPage {
private boolean isEmailValidFormat() {
return Authenticator.isValidEmailAddress(emailAddress);
}
private boolean externalAuthIdIsChanged() {
return !externalAuthId.equals(userAccount.getExternalAuthId());
}
private boolean isExternalAuthIdInUse() {
if (externalAuthId.isEmpty()) {
return false;
}
return userAccountsDao.getUserAccountByExternalAuthId(externalAuthId) != null;
}
private boolean isRootUser() {
return ((userAccount != null) && userAccount.isRootUser());
}
public boolean isValid() {
return errorCode.isEmpty();
}
@ -149,16 +170,22 @@ public class UserAccountsEditPage extends UserAccountsPage {
if (isSubmit()) {
body.put("emailAddress", emailAddress);
body.put("externalAuthId", externalAuthId);
body.put("firstName", firstName);
body.put("lastName", lastName);
body.put("selectedRole", selectedRoleUri);
} else {
body.put("emailAddress", userAccount.getEmailAddress());
body.put("externalAuthId", userAccount.getExternalAuthId());
body.put("firstName", userAccount.getFirstName());
body.put("lastName", userAccount.getLastName());
body.put("selectedRole", getExistingRoleUri());
}
body.put("roles", buildRolesList());
if (!isRootUser()) {
body.put("roles", buildRolesList());
}
if (associateWithProfile) {
body.put("associate", Boolean.TRUE);
}
@ -192,9 +219,14 @@ public class UserAccountsEditPage extends UserAccountsPage {
userAccount.setEmailAddress(emailAddress);
userAccount.setFirstName(firstName);
userAccount.setLastName(lastName);
userAccount.setExternalAuthId(externalAuthId);
userAccount
.setPermissionSetUris(Collections.singleton(selectedRoleUri));
if (isRootUser()) {
userAccount.setPermissionSetUris(Collections.<String> emptySet());
} else {
userAccount.setPermissionSetUris(Collections
.singleton(selectedRoleUri));
}
strategy.setAdditionalProperties(userAccount);

View file

@ -9,8 +9,8 @@ import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
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;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
@ -57,7 +57,8 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
private static class EmailStrategy extends UserAccountsEditPageStrategy {
private static final String PARAMETER_RESET_PASSWORD = "resetPassword";
private static final String EMAIL_TEMPLATE = "userAccounts-resetPasswordEmail.ftl";
public static final String RESET_PASSWORD_URL = "/accounts/resetPassword";
private boolean resetPassword;
@ -102,19 +103,23 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage {
Map<String, Object> body = new HashMap<String, Object>();
body.put("userAccount", page.getUpdatedAccount());
body.put("passwordLink", buildResetPasswordLink());
body.put("subjectLine", "Reset password request");
body.put("siteName", getSiteName());
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, page.getUpdatedAccount().getEmailAddress());
email.setSubject("Reset password request");
email.setHtmlTemplate("userAccounts-resetPasswordEmail-html.ftl");
email.setTextTemplate("userAccounts-resetPasswordEmail-text.ftl");
email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
email.processTemplate();
email.send();
sentEmail = true;
}
private String getSiteName() {
ApplicationBean appBean = vreq.getAppBean();
return appBean.getApplicationName();
}
private String buildResetPasswordLink() {
try {

View file

@ -11,6 +11,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -19,12 +22,12 @@ 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;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Direction;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelection;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelectionCriteria;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelector;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Direction;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
@ -91,55 +94,7 @@ public class UserAccountsListPage extends UserAccountsPage {
UserAccountsSelection selection = UserAccountsSelector.select(
userAccountsModel, criteria);
Map<String, Object> body = buildTemplateBodyMap(selection);
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
/**
* We just came from adding a new account. Show the list with a message.
*/
public ResponseValues showPageWithNewAccount(UserAccount userAccount,
boolean emailWasSent) {
UserAccountsSelection selection = UserAccountsSelector.select(
userAccountsModel, criteria);
Map<String, Object> body = buildTemplateBodyMap(selection);
body.put("newUserAccount", new UserAccountWrapper(userAccount,
Collections.<String> emptyList()));
if (emailWasSent) {
body.put("emailWasSent", Boolean.TRUE);
}
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
/**
* We just came from editing an account. Show the list with a message.
*/
public ResponseValues showPageWithUpdatedAccount(UserAccount userAccount,
boolean emailWasSent) {
UserAccountsSelection selection = UserAccountsSelector.select(
userAccountsModel, criteria);
Map<String, Object> body = buildTemplateBodyMap(selection);
body.put("updatedUserAccount", new UserAccountWrapper(userAccount,
Collections.<String> emptyList()));
if (emailWasSent) {
body.put("emailWasSent", Boolean.TRUE);
}
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
/**
* We just came from deleting accounts. Show the list with a message.
*/
public ResponseValues showPageWithDeletions(Collection<String> deletedUris) {
UserAccountsSelection selection = UserAccountsSelector.select(
userAccountsModel, criteria);
Map<String, Object> body = buildTemplateBodyMap(selection);
body.put("deletedAccountCount", deletedUris.size());
Message.applyToBodyMap(vreq, body);
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
@ -238,10 +193,15 @@ public class UserAccountsListPage extends UserAccountsPage {
private List<String> findPermissionSetLabels(UserAccount account) {
List<String> labels = new ArrayList<String>();
for (String uri : account.getPermissionSetUris()) {
PermissionSet pSet = userAccountsDao.getPermissionSetByUri(uri);
if (pSet != null) {
labels.add(pSet.getLabel());
if (account.isRootUser()) {
labels.add("ROOT");
} else {
for (String uri : account.getPermissionSetUris()) {
PermissionSet pSet = userAccountsDao.getPermissionSetByUri(uri);
if (pSet != null) {
labels.add(pSet.getLabel());
}
}
}
return labels;
@ -301,4 +261,84 @@ public class UserAccountsListPage extends UserAccountsPage {
}
/**
* Message info that lives in the session. Another request can store this,
* and it will be displayed (once) by the list page.
*/
public static class Message {
private static final String ATTRIBUTE = Message.class.getName();
private static final Collection<String> EMPTY = Collections.emptySet();
public static void showNewAccount(HttpServletRequest req,
UserAccount userAccount, boolean emailWasSent) {
Message message = new Message(Type.NEW_ACCOUNT, userAccount,
emailWasSent, EMPTY);
setMessage(req, message);
}
public static void showUpdatedAccount(HttpServletRequest req,
UserAccount userAccount, boolean emailWasSent) {
Message message = new Message(Type.UPDATED_ACCOUNT, userAccount,
emailWasSent, EMPTY);
setMessage(req, message);
}
public static void showDeletions(HttpServletRequest req,
Collection<String> deletedUris) {
Message message = new Message(Type.DELETIONS, null, false,
deletedUris);
setMessage(req, message);
}
private static void setMessage(HttpServletRequest req, Message message) {
req.getSession().setAttribute(ATTRIBUTE, message);
}
public static void applyToBodyMap(HttpServletRequest req,
Map<String, Object> body) {
HttpSession session = req.getSession();
Object o = session.getAttribute(ATTRIBUTE);
session.removeAttribute(ATTRIBUTE);
if (o instanceof Message) {
((Message) o).applyToBodyMap(body);
}
}
enum Type {
NEW_ACCOUNT, UPDATED_ACCOUNT, DELETIONS
}
private final Type type;
private final UserAccount userAccount;
private final boolean emailWasSent;
private final Collection<String> deletedUris;
public Message(Type type, UserAccount userAccount,
boolean emailWasSent, Collection<String> deletedUris) {
this.type = type;
this.userAccount = userAccount;
this.emailWasSent = emailWasSent;
this.deletedUris = deletedUris;
}
private void applyToBodyMap(Map<String, Object> body) {
if (type == Type.NEW_ACCOUNT) {
body.put("newUserAccount", new UserAccountWrapper(userAccount,
Collections.<String> emptyList()));
if (emailWasSent) {
body.put("emailWasSent", Boolean.TRUE);
}
} else if (type == Type.UPDATED_ACCOUNT) {
body.put("updatedUserAccount", new UserAccountWrapper(
userAccount, Collections.<String> emptyList()));
if (emailWasSent) {
body.put("emailWasSent", Boolean.TRUE);
}
} else {
body.put("deletedAccountCount", deletedUris.size());
}
}
}
}

View file

@ -26,6 +26,7 @@ public class UserAccountsCreatePasswordPage extends
.getLog(UserAccountsCreatePasswordPage.class);
private static final String TEMPLATE_NAME = "userAccounts-createPassword.ftl";
private static final String EMAIL_TEMPLATE = "userAccounts-passwordCreatedEmail.ftl";
public UserAccountsCreatePasswordPage(VitroRequest vreq) {
super(vreq);
@ -39,7 +40,7 @@ public class UserAccountsCreatePasswordPage extends
userAccountsDao.updateUserAccount(userAccount);
log.debug("Set password on '" + userAccount.getEmailAddress()
+ "' to '" + newPassword + "'");
notifyUser();
}
@ -56,15 +57,14 @@ public class UserAccountsCreatePasswordPage extends
private void notifyUser() {
Map<String, Object> body = new HashMap<String, Object>();
body.put("userAccount", userAccount);
body.put("subjectLine", "Password successfully created.");
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, userAccount.getEmailAddress());
email.setSubject("Password successfully created.");
email.setHtmlTemplate("userAccounts-passwordCreatedEmail-html.ftl");
email.setTextTemplate("userAccounts-passwordCreatedEmail-text.ftl");
email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
email.processTemplate();
email.send();
}
}

View file

@ -9,6 +9,8 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
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.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status;
@ -22,13 +24,14 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Tem
* Handle the first-time login of an Externally Authenticated user who has no
* UserAccount - let's create one!
*
* If they get here from the login, there should an externalAuthId waiting in
* the session. Otherwise, they should get here by submitting the form, which
* will have the externalAuthId as a hidden field.
* If they get here from the login, there should be an ExternalLoginInfo waiting
* in the session. Otherwise, they should get here by submitting the form, which
* will have the info in hidden fields.
*/
public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
private static final String PARAMETER_SUBMIT = "submit";
private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId";
private static final String PARAMETER_AFTER_LOGIN_URL = "afterLoginUrl";
private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress";
private static final String PARAMETER_FIRST_NAME = "firstName";
private static final String PARAMETER_LAST_NAME = "lastName";
@ -41,23 +44,25 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
private static final String TEMPLATE_NAME = "userAccounts-firstTimeExternal.ftl";
private static final String ATTRIBUTE_EXTERNAL_AUTH_ID = UserAccountsFirstTimeExternalPage.class
private static final String ATTRIBUTE_EXTERNAL_LOGIN_INFO = UserAccountsFirstTimeExternalPage.class
.getName();
/**
* Let some other request set the External Auth ID before redirecting to
* here.
* Let some other request set the External Auth ID and the afterLogin URL
* before redirecting to here.
*/
public static void setExternalAuthId(HttpServletRequest req,
String externalAuthId) {
req.getSession().setAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID,
externalAuthId);
public static void setExternalLoginInfo(HttpServletRequest req,
String externalAuthId, String afterLoginUrl) {
req.getSession().setAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO,
new ExternalLoginInfo(externalAuthId, afterLoginUrl));
}
private final UserAccountsFirstTimeExternalPageStrategy strategy;
private boolean submit = false;
private String externalAuthId = "";
private String afterLoginUrl = "";
private boolean submit = false;
private String emailAddress = "";
private String firstName = "";
private String lastName = "";
@ -71,7 +76,7 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
this.strategy = UserAccountsFirstTimeExternalPageStrategy.getInstance(
vreq, this, isEmailEnabled());
checkSessionForExternalAuthId();
checkSessionForExternalLoginInfo();
if (externalAuthId.isEmpty()) {
parseRequestParameters();
}
@ -83,20 +88,26 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
}
}
private void checkSessionForExternalAuthId() {
private void checkSessionForExternalLoginInfo() {
HttpSession session = vreq.getSession();
Object o = session.getAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID);
session.removeAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID);
Object o = session.getAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO);
session.removeAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO);
if (o instanceof String) {
externalAuthId = (String) o;
if (o instanceof ExternalLoginInfo) {
externalAuthId = ((ExternalLoginInfo) o).externalAuthId;
afterLoginUrl = ((ExternalLoginInfo) o).afterLoginUrl;
if (afterLoginUrl == null) {
afterLoginUrl = "";
}
}
}
private void parseRequestParameters() {
submit = isFlagOnRequest(PARAMETER_SUBMIT);
externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, "");
afterLoginUrl = getStringParameter(PARAMETER_AFTER_LOGIN_URL, "");
submit = isFlagOnRequest(PARAMETER_SUBMIT);
emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, "");
firstName = getStringParameter(PARAMETER_FIRST_NAME, "");
lastName = getStringParameter(PARAMETER_LAST_NAME, "");
@ -156,10 +167,12 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
public final ResponseValues showPage() {
Map<String, Object> body = new HashMap<String, Object>();
body.put("externalAuthId", externalAuthId);
body.put("afterLoginUrl", afterLoginUrl);
body.put("emailAddress", emailAddress);
body.put("firstName", firstName);
body.put("lastName", lastName);
body.put("externalAuthId", externalAuthId);
body.put("formUrls", buildUrlsMap());
if (!errorCode.isEmpty()) {
@ -191,4 +204,25 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage {
return u;
}
/**
* If the afterLoginUrl is missing, go to the home page. If it is relative,
* make sure it doesn't start with the cotext path.
*/
public String getAfterLoginUrl() {
if (StringUtils.isEmpty(afterLoginUrl)) {
return null;
}
return afterLoginUrl;
}
private static class ExternalLoginInfo {
final String externalAuthId;
final String afterLoginUrl;
public ExternalLoginInfo(String externalAuthId, String afterLoginUrl) {
this.externalAuthId = externalAuthId;
this.afterLoginUrl = afterLoginUrl;
}
}
}

View file

@ -52,6 +52,8 @@ public abstract class UserAccountsFirstTimeExternalPageStrategy extends
public static class EmailStrategy extends
UserAccountsFirstTimeExternalPageStrategy {
private static final String EMAIL_TEMPLATE = "userAccounts-firstTimeExternalEmail.ftl";
public EmailStrategy(VitroRequest vreq,
UserAccountsFirstTimeExternalPage page) {
super(vreq, page);
@ -66,15 +68,14 @@ public abstract class UserAccountsFirstTimeExternalPageStrategy extends
public void notifyUser(UserAccount ua) {
Map<String, Object> body = new HashMap<String, Object>();
body.put("userAccount", ua);
body.put("subjectLine", "Your VIVO account has been created.");
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, ua.getEmailAddress());
email.setSubject("Your VIVO account has been created.");
email.setHtmlTemplate("userAccounts-firstTimeExternalEmail-html.ftl");
email.setTextTemplate("userAccounts-firstTimeExternalEmail-text.ftl");
email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
email.processTemplate();
email.send();
}

View file

@ -107,6 +107,8 @@ public abstract class UserAccountsMyAccountPageStrategy extends
private static final String ERROR_WRONG_PASSWORD_LENGTH = "errorPasswordIsWrongLength";
private static final String ERROR_PASSWORDS_DONT_MATCH = "errorPasswordsDontMatch";
private static final String EMAIL_TEMPLATE = "userAccounts-confirmEmailChangedEmail.ftl";
private final String originalEmail;
@ -167,15 +169,14 @@ public abstract class UserAccountsMyAccountPageStrategy extends
Map<String, Object> body = new HashMap<String, Object>();
body.put("userAccount", page.getUserAccount());
body.put("subjectLine", "Your VIVO email account has been changed.");
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, page.getUserAccount().getEmailAddress());
email.setSubject("Your VIVO email account has been changed.");
email.setHtmlTemplate("userAccounts-confirmEmailChangedEmail-html.ftl");
email.setTextTemplate("userAccounts-confirmEmailChangedEmail-text.ftl");
email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
email.processTemplate();
email.send();
emailSent = true;

View file

@ -26,6 +26,8 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
private static final String TEMPLATE_NAME = "userAccounts-resetPassword.ftl";
private static final String EMAIL_TEMPLATE = "userAccounts-passwordResetEmail.ftl";
protected UserAccountsResetPasswordPage(VitroRequest vreq) {
super(vreq);
}
@ -38,7 +40,7 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
userAccountsDao.updateUserAccount(userAccount);
log.debug("Set password on '" + userAccount.getEmailAddress()
+ "' to '" + newPassword + "'");
notifyUser();
}
@ -55,15 +57,14 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage
private void notifyUser() {
Map<String, Object> body = new HashMap<String, Object>();
body.put("userAccount", userAccount);
body.put("subjectLine", "Password changed.");
FreemarkerEmailMessage email = FreemarkerEmailFactory
.createNewMessage(vreq);
email.addRecipient(TO, userAccount.getEmailAddress());
email.setSubject("Password changed.");
email.setHtmlTemplate("userAccounts-passwordResetEmail-html.ftl");
email.setTextTemplate("userAccounts-passwordResetEmail-text.ftl");
email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
email.processTemplate();
email.send();
}

View file

@ -4,10 +4,10 @@ package edu.cornell.mannlib.vitro.webapp.controller.accounts.user;
import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.EXTERNAL;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOwnAccount;
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
@ -115,9 +115,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
UserAccount userAccount = page.createAccount();
Authenticator auth = Authenticator.getInstance(vreq);
auth.recordLoginAgainstUserAccount(userAccount, EXTERNAL);
LoginProcessBean.removeBean(vreq);
return showLoginRedirection(vreq);
return showLoginRedirection(vreq, page.getAfterLoginUrl());
} else {
return page.showPage();
}
@ -132,10 +130,31 @@ public class UserAccountsUserController extends FreemarkerHttpServlet {
return new RedirectResponseValues("/");
}
private ResponseValues showLoginRedirection(VitroRequest vreq) {
LoginRedirector lr = new LoginRedirector(vreq);
private ResponseValues showLoginRedirection(VitroRequest vreq,
String afterLoginUrl) {
LoginRedirector lr = new LoginRedirector(vreq, afterLoginUrl);
DisplayMessage.setMessage(vreq, lr.assembleWelcomeMessage());
String uri = lr.getRedirectionUriForLoggedInUser();
return new RedirectResponseValues(uri);
return new RedirectResponseValues(stripContextPath(vreq, uri));
}
/**
* TODO The LoginRedirector gives a URI that includes the context path. But
* the RedirectResponseValues wants a URI that does not include the context
* path.
*
* Bridge the gap.
*/
private String stripContextPath(VitroRequest vreq, String uri) {
if ((uri == null) || uri.isEmpty() || uri.equals(vreq.getContextPath())) {
return "/";
}
if (uri.contains("://")) {
return uri;
}
if (uri.startsWith(vreq.getContextPath() + '/')) {
return uri.substring(vreq.getContextPath().length());
}
return uri;
}
}

View file

@ -51,10 +51,10 @@ public abstract class Authenticator {
// ----------------------------------------------------------------------
/** Maximum inactive interval for a ordinary logged-in session, in seconds. */
public static final int LOGGED_IN_TIMEOUT_INTERVAL = 300;
public static final int LOGGED_IN_TIMEOUT_INTERVAL = 60 * 60;
/** Maximum inactive interval for a editor (or better) session, in seconds. */
public static final int PRIVILEGED_TIMEOUT_INTERVAL = 32000;
public static final int PRIVILEGED_TIMEOUT_INTERVAL = 60 * 60 * 8;
/**
* Get the UserAccount for this external ID, or null if there is none.
@ -96,8 +96,9 @@ public abstract class Authenticator {
* <pre>
* Record that the user has logged in, with all of the housekeeping that
* goes with it:
* - updating the user record
* - setting login status and timeout limit in the session
* - update the user record
* - set login status and timeout limit in the session
* - refresh the Identifiers on the request
* - record the user in the session map
* - notify other users of the model
* </pre>
@ -105,17 +106,6 @@ public abstract class Authenticator {
public abstract void recordLoginAgainstUserAccount(UserAccount userAccount,
AuthenticationSource authSource);
/**
* <pre>
* Record that the user has logged in but with only external authentication
* info, so no internal user account.
* - this involves everything except updating the user record.
* </pre>
*
* TODO JB This goes away.
*/
public abstract void recordLoginWithoutUserAccount(String individualUri);
/**
* <pre>
* Record that the current user has logged out: - notify other users of the

View file

@ -3,7 +3,6 @@
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -16,6 +15,7 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.SelfEditingConfiguration;
@ -123,24 +123,13 @@ public class BasicAuthenticator extends Authenticator {
}
recordLoginOnUserRecord(userAccount);
recordLoginWithOrWithoutUserAccount(userAccount.getUri(), authSource);
}
// TODO JB This goes away.
@Override
public void recordLoginWithoutUserAccount(String individualUri) {
recordLoginWithOrWithoutUserAccount(individualUri,
AuthenticationSource.EXTERNAL);
}
/** This much is in common on login, whether or not you have a user account. */
private void recordLoginWithOrWithoutUserAccount(String userUri,
AuthenticationSource authSource) {
HttpSession session = request.getSession();
createLoginStatusBean(userUri, authSource, session);
setSessionTimeoutLimit(session);
recordInUserSessionMap(userUri, session);
notifyOtherUsers(userUri, session);
createLoginStatusBean(userAccount.getUri(), authSource, session);
RequestIdentifiers.resetIdentifiers(request);
setSessionTimeoutLimit(userAccount, session);
recordInUserSessionMap(userAccount.getUri(), session);
notifyOtherUsers(userAccount.getUri(), session);
}
/**
@ -164,11 +153,14 @@ public class BasicAuthenticator extends Authenticator {
/**
* Editors and other privileged users get a longer timeout interval.
*/
private void setSessionTimeoutLimit(HttpSession session) {
private void setSessionTimeoutLimit(UserAccount userAccount,
HttpSession session) {
RoleLevel role = RoleLevel.getRoleFromLoginStatus(request);
if (role == RoleLevel.EDITOR || role == RoleLevel.CURATOR
|| role == RoleLevel.DB_ADMIN) {
session.setMaxInactiveInterval(PRIVILEGED_TIMEOUT_INTERVAL);
} else if (userAccount.isRootUser()) {
session.setMaxInactiveInterval(PRIVILEGED_TIMEOUT_INTERVAL);
} else {
session.setMaxInactiveInterval(LOGGED_IN_TIMEOUT_INTERVAL);
}

View file

@ -5,7 +5,6 @@ package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
import static edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginExternalAuthSetup.ATTRIBUTE_REFERRER;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -16,6 +15,9 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsFirstTimeExternalPage;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
/**
* Handle the return from the external authorization login server. If we are
@ -36,6 +38,13 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
* - User corresponds to a User acocunt. Record the login.
* - User corresponds to an Individual (self-editor).
* - User is not recognized.
*
* On entry, we expect to find:
* - A LoginProcessBean, which will give us the afterLoginUrl if the login
* succeeds.
* - A referrer URL, to which we will redirect if the login fails.
* TODO: is this equal to LoginProcessBean.getLoginPageUrl()?
* These are removed on exit.
* </pre>
*/
@Override
@ -50,39 +59,30 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
return;
}
String afterLoginUrl = LoginProcessBean.getBean(req).getAfterLoginUrl();
removeLoginProcessArtifacts(req);
UserAccount userAccount = getAuthenticator(req)
.getAccountForExternalAuth(externalAuthId);
if (userAccount != null) {
if (userAccount == null) {
log.debug("Creating new account for " + externalAuthId
+ ", return to '" + afterLoginUrl + "'");
UserAccountsFirstTimeExternalPage.setExternalLoginInfo(req,
externalAuthId, afterLoginUrl);
resp.sendRedirect(UrlBuilder.getUrl("/accounts/firstTimeExternal"));
return;
} else {
log.debug("Logging in as " + userAccount.getUri());
getAuthenticator(req).recordLoginAgainstUserAccount(userAccount,
AuthenticationSource.EXTERNAL);
removeLoginProcessArtifacts(req);
new LoginRedirector(req).redirectLoggedInUser(resp);
new LoginRedirector(req, afterLoginUrl).redirectLoggedInUser(resp);
return;
}
List<String> associatedUris = getAuthenticator(req)
.getAssociatedIndividualUris(userAccount);
// TODO JB - this case should lead to creating a new account.
if (!associatedUris.isEmpty()) {
log.debug("Recognize '" + externalAuthId + "' as self-editor for "
+ associatedUris);
String uri = associatedUris.get(0);
getAuthenticator(req).recordLoginWithoutUserAccount(uri);
removeLoginProcessArtifacts(req);
new LoginRedirector(req).redirectLoggedInUser(resp);
return;
}
log.debug("User is not recognized: " + externalAuthId);
removeLoginProcessArtifacts(req);
new LoginRedirector(req).redirectUnrecognizedExternalUser(resp,
externalAuthId);
}
private void removeLoginProcessArtifacts(HttpServletRequest req) {
req.getSession().removeAttribute(ATTRIBUTE_REFERRER);
LoginProcessBean.removeBean(req);
}
@Override

View file

@ -16,11 +16,14 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
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.identifier.common.HasRoleLevel;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.IsRootUser;
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
/**
* A user has just completed the login process. What page do we direct them to?
@ -34,15 +37,12 @@ public class LoginRedirector {
private final String uriOfAssociatedIndividual;
private final String afterLoginPage;
public LoginRedirector(HttpServletRequest request) {
public LoginRedirector(HttpServletRequest request, String afterLoginPage) {
this.request = request;
this.session = request.getSession();
this.afterLoginPage = afterLoginPage;
uriOfAssociatedIndividual = getAssociatedIndividualUri();
LoginProcessBean processBean = LoginProcessBean.getBean(request);
log.debug("process bean is: " + processBean);
afterLoginPage = processBean.getAfterLoginUrl();
}
/** Is there an Individual associated with this user? */
@ -106,7 +106,6 @@ public class LoginRedirector {
try {
DisplayMessage.setMessage(request, assembleWelcomeMessage());
response.sendRedirect(getRedirectionUriForLoggedInUser());
LoginProcessBean.removeBean(request);
} catch (IOException e) {
log.debug("Problem with re-direction", e);
response.sendRedirect(getApplicationHomePageUrl());
@ -142,7 +141,6 @@ public class LoginRedirector {
throws IOException {
try {
response.sendRedirect(getRedirectionUriForCancellingUser());
LoginProcessBean.removeBean(request);
} catch (IOException e) {
log.debug("Problem with re-direction", e);
response.sendRedirect(getApplicationHomePageUrl());
@ -158,7 +156,12 @@ public class LoginRedirector {
}
private boolean isMerelySelfEditor() {
RoleLevel role = RoleLevel.getRoleFromLoginStatus(request);
IdentifierBundle ids = RequestIdentifiers.getIdBundleForRequest(request);
if (IsRootUser.isRootUser(ids)) {
return false;
}
RoleLevel role = HasRoleLevel.getUsersRoleLevel(ids);
return role == RoleLevel.PUBLIC || role == RoleLevel.SELF;
}

View file

@ -124,7 +124,7 @@ public class Authenticate extends VitroHttpServlet {
// Send them on their way.
switch (exitState) {
case NOWHERE:
new LoginRedirector(vreq).redirectCancellingUser(response);
showLoginCanceled(response, vreq);
break;
case LOGGING_IN:
showLoginScreen(vreq, response);
@ -133,7 +133,7 @@ public class Authenticate extends VitroHttpServlet {
showLoginScreen(vreq, response);
break;
default: // LOGGED_IN:
new LoginRedirector(vreq).redirectLoggedInUser(response);
showLoginComplete(response, vreq);
break;
}
} catch (Exception e) {
@ -477,6 +477,31 @@ public class Authenticate extends VitroHttpServlet {
response.sendRedirect(loginProcessPage);
return;
}
/**
* Exit: user has completed the login. Redirect appropriately and clear the bean.
*/
private void showLoginComplete(HttpServletResponse response,
VitroRequest vreq) throws IOException {
getLoginRedirector(vreq).redirectLoggedInUser(response);
LoginProcessBean.removeBean(vreq);
}
/**
* Exit: user has canceled. Redirect and clear the bean.
*/
private void showLoginCanceled(HttpServletResponse response,
VitroRequest vreq) throws IOException {
getLoginRedirector(vreq).redirectCancellingUser(response);
LoginProcessBean.removeBean(vreq);
}
private LoginRedirector getLoginRedirector(VitroRequest vreq) {
String afterLoginUrl = LoginProcessBean.getBean(vreq).getAfterLoginUrl();
return new LoginRedirector(vreq, afterLoginUrl);
}
/** Get a reference to the Authenticator. */
private Authenticator getAuthenticator(HttpServletRequest request) {

View file

@ -184,16 +184,24 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
templateDataModel.put("body", bodyString);
// Tell the template and any directives it uses that we're processing a page template.
templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE);
writePage(templateDataModel, config, vreq, response);
templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE);
writePage(templateDataModel, config, vreq, response, values.getStatusCode());
}
protected void doRedirect(HttpServletRequest request, HttpServletResponse response, ResponseValues values)
throws ServletException, IOException {
String redirectUrl = values.getRedirectUrl();
setResponseStatus(response, values.getStatusCode());
response.sendRedirect(redirectUrl);
}
private void setResponseStatus(HttpServletResponse response, int statusCode) {
if (statusCode > 0) {
response.setStatus(statusCode);
}
}
protected void doForward(HttpServletRequest request, HttpServletResponse response, ResponseValues values)
throws ServletException, IOException {
String forwardUrl = values.getForwardUrl();
@ -306,11 +314,18 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
*/
public 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.putAll(getDirectivesForAllEnvironments());
map.put("url", new edu.cornell.mannlib.vitro.webapp.web.directives.UrlDirective());
map.put("widget", new edu.cornell.mannlib.vitro.webapp.web.directives.WidgetDirective());
return map;
}
public static Map<String, Object> getDirectivesForAllEnvironments() {
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());
return map;
}
@ -330,9 +345,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
Map<String, Object> map = new HashMap<String, Object>();
ApplicationBean appBean = vreq.getAppBean();
// Ideally, templates wouldn't need portal id. Currently used as a hidden input value
// in the site search box, so needed for now.
String siteName = appBean.getApplicationName();
map.put("siteName", siteName);
@ -365,11 +377,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
// This value is used only in stylesheets.ftl and already contains the context path.
map.put("stylesheetPath", UrlBuilder.getUrl(themeDir + "/css"));
// String bannerImage = portal.getBannerImage();
// if ( ! StringUtils.isEmpty(bannerImage)) {
// map.put("bannerImage", UrlBuilder.getUrl(themeDir + "site_icons/" + bannerImage));
// }
String flashMessage = DisplayMessage.getMessageAndClear(vreq);
if (! flashMessage.isEmpty()) {
map.put("flash", flashMessage);
@ -448,18 +455,24 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
}
protected void writePage(Map<String, Object> root, Configuration config,
HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException {
writeTemplate(getPageTemplateName(), root, config, request, response);
HttpServletRequest request, HttpServletResponse response, int statusCode) throws TemplateProcessingException {
writeTemplate(getPageTemplateName(), root, config, request, response, statusCode);
}
protected void writeTemplate(String templateName, Map<String, Object> map, Configuration config,
HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException {
StringWriter sw = processTemplate(templateName, map, config, request);
write(sw, response);
HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException {
writeTemplate(templateName, map, config, request, response, 0);
}
protected void writeTemplate(String templateName, Map<String, Object> map, Configuration config,
HttpServletRequest request, HttpServletResponse response, int statusCode) throws TemplateProcessingException {
StringWriter sw = processTemplate(templateName, map, config, request);
write(sw, response, statusCode);
}
protected void write(StringWriter sw, HttpServletResponse response) {
protected void write(StringWriter sw, HttpServletResponse response, int statusCode) {
try {
setResponseStatus(response, statusCode);
PrintWriter out = response.getWriter();
out.print(sw);
} catch (IOException e) {

View file

@ -100,7 +100,7 @@ public class IndividualController extends FreemarkerHttpServlet {
// Check to see if the request is for a non-information resource, redirect if it is.
String redirectURL = checkForRedirect ( url, vreq );
if( redirectURL != null ){
return new RedirectResponseValues(redirectURL);
return new RedirectResponseValues(redirectURL, HttpServletResponse.SC_SEE_OTHER);
}
Individual individual = null;
@ -463,12 +463,19 @@ public class IndividualController extends FreemarkerHttpServlet {
return null;
}
private static Pattern URI_PATTERN = Pattern.compile("^/individual/([^/]*)$");
//Redirect if the request is for http://hostname/individual/localname
// if accept is nothing or text/html redirect to ???
// if accept is some RDF thing redirect to the URL for RDF
/*
* Following recipe 3 from "Best Practice Recipes for Publishing RDF Vocabularies."
* See http://www.w3.org/TR/swbp-vocab-pub/#recipe3.
* The basic idea is that a URI like http://vivo.cornell.edu/individual/n1234
* identifies a real world individual. HTTP cannot send that as the response
* to a GET request because it can only send bytes and not things. The server
* sends a 303, to mean "you asked for something I cannot send you, but I can
* send you this other stream of bytes about that thing."
* In the case of a request like http://vivo.cornell.edu/individual/n1234/n1234.rdf,
* the request is for a set of bytes rather than an individual, so no 303 is needed.
*/
private static Pattern URI_PATTERN = Pattern.compile("^/individual/([^/]*)$");
private String checkForRedirect(String url, VitroRequest vreq) {
Matcher m = URI_PATTERN.matcher(url);
if( m.matches() && m.groupCount() == 1 ){
@ -506,7 +513,11 @@ public class IndividualController extends FreemarkerHttpServlet {
protected ContentType checkForLinkedDataRequest(String url, VitroRequest vreq ) {
try {
Matcher m;
// Check for url param specifying format
/*
* Check for url param specifying format.
* Example: http://vivo.cornell.edu/individual/n23?format=rdfxml
* This request will trigger a redirect with a 303.
*/
String formatParam = (String) vreq.getParameter("format");
if (formatParam != null) {
m = RDFXML_FORMAT.matcher(formatParam);
@ -523,7 +534,11 @@ public class IndividualController extends FreemarkerHttpServlet {
}
}
//check the accept header
/*
* Check the accept header. This request will trigger a
* redirect with a 303, because the request is for an individual
* but the server can only provide a set of bytes.
*/
String acceptHeader = vreq.getHeader("accept");
if (acceptHeader != null) {
String ctStr = ContentType.getBestContentType(
@ -538,10 +553,12 @@ public class IndividualController extends FreemarkerHttpServlet {
}
/*
* check for parts of URL that indicate request for RDF
http://vivo.cornell.edu/individual/n23/n23.rdf
http://vivo.cornell.edu/individual/n23/n23.n3
http://vivo.cornell.edu/individual/n23/n23.ttl
* Check for parts of URL that indicate request for RDF
* http://vivo.cornell.edu/individual/n23/n23.rdf
* http://vivo.cornell.edu/individual/n23/n23.n3
* http://vivo.cornell.edu/individual/n23/n23.ttl
* This request will not trigger a redirect and 303, because
* the request is for a set of bytes rather than an individual.
*/
m = RDF_REQUEST.matcher(url);
if( m.matches() ) {
@ -555,8 +572,7 @@ public class IndividualController extends FreemarkerHttpServlet {
if( m.matches() ) {
return ContentType.TURTLE;
}
} catch (Throwable th) {
log.error("problem while checking accept header " , th);
}

View file

@ -22,6 +22,11 @@ public abstract class BaseResponseValues implements ResponseValues {
BaseResponseValues(ContentType contentType) {
this.contentType = contentType;
}
BaseResponseValues(ContentType contentType, int statusCode) {
this.contentType = contentType;
this.statusCode = statusCode;
}
@Override
public int getStatusCode() {
@ -38,6 +43,7 @@ public abstract class BaseResponseValues implements ResponseValues {
return contentType;
}
@Override
public void setContentType(ContentType contentType) {
this.contentType = contentType;
}

View file

@ -14,6 +14,11 @@ public class RdfResponseValues extends BaseResponseValues {
this.model = model;
}
public RdfResponseValues(ContentType contentType, Model model, int statusCode) {
super(contentType, statusCode);
this.model = model;
}
@Override
public Model getModel() {
return model;

View file

@ -28,6 +28,8 @@ public interface ResponseValues {
public ContentType getContentType();
public void setContentType(ContentType contentType);
public Model getModel();
}

View file

@ -49,7 +49,9 @@ public class TemplateResponseValues extends BaseResponseValues {
}
public static TemplateResponseValues getTemplateResponseValuesFromException(ExceptionResponseValues responseValues) {
return new TemplateResponseValues(responseValues.getTemplateName(), responseValues.getMap());
return new TemplateResponseValues(responseValues.getTemplateName(),
responseValues.getMap(),
responseValues.getStatusCode());
}
}

View file

@ -14,6 +14,14 @@ import org.apache.commons.logging.LogFactory;
/**
* Where are we in the process of logging on? What message should we show to the
* user?
*
* TODO: the contents loginPageUrl is not explicitly defined, but it is assumed
* to be either null, absolute, or relative to the host. It would be better if
* it were explicitly defined, and either null, absolute or relative to the
* context path. Then, the context path could be applied when the URL is used.
* Later for that.
*
* TODO: similar for afterLoginUrl, I presume.
*/
public class LoginProcessBean {
private static final Log log = LogFactory.getLog(LoginProcessBean.class);

View file

@ -40,11 +40,6 @@ public interface UserAccountsDao {
*/
UserAccount getUserAccountByExternalAuthId(String externalAuthId);
/**
* Is this UserAccount a root user?
*/
boolean isRootUser(UserAccount userAccount);
/**
* Create a new UserAccount in the model.
*

View file

@ -47,11 +47,6 @@ public class UserAccountsDaoFiltering extends BaseFiltering implements
return innerDao.getUserAccountByExternalAuthId(externalAuthId);
}
@Override
public boolean isRootUser(UserAccount userAccount) {
return innerDao.isRootUser(userAccount);
}
@Override
public String insertUserAccount(UserAccount userAccount) {
return innerDao.insertUserAccount(userAccount);

View file

@ -57,15 +57,13 @@ public class DataPropertyStatementDaoSDB extends DataPropertyStatementDaoJena
}
else
{
String[] graphVars = { "?g" };
String query =
"CONSTRUCT { \n" +
" <" + entity.getURI() + "> ?p ?o . \n" +
"} WHERE { GRAPH ?g { \n" +
"} WHERE { \n" +
" <" + entity.getURI() + "> ?p ?o . \n" +
" FILTER(isLiteral(?o)) \n" +
WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) +
"} }" ;
"}" ;
Model results = null;
DatasetWrapper w = dwf.getDatasetWrapper();
Dataset dataset = w.getDataset();

View file

@ -781,7 +781,7 @@ public class IndividualJena extends IndividualImpl implements Individual {
if (stmt.getObject().isURIResource()) {
String typeURI = ((Resource)stmt.getObject()).getURI();
if (pfs.isClassProhibitedFromSearch(typeURI)) {
return false;
return true;
}
}
}

View file

@ -395,8 +395,8 @@ public class IndividualSDB extends IndividualImpl implements Individual {
String[] graphVars = { "?g" };
String queryStr =
"CONSTRUCT { <"+ind.getURI()+"> <" + propertyURI + "> ?value } \n" +
"WHERE { GRAPH ?g { \n" +
"<" + ind.getURI() +"> <" + propertyURI + "> ?value } \n" +
"WHERE { \n" +
"<" + ind.getURI() +"> <" + propertyURI + "> ?value \n" +
WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) +
"\n} ";
Query query = QueryFactory.create(queryStr);
@ -456,13 +456,13 @@ public class IndividualSDB extends IndividualImpl implements Individual {
if (this.mainImageUri != NOT_INITIALIZED) {
return mainImageUri;
} else {
for (ObjectPropertyStatement stmt : getObjectPropertyStatements()) {
if (stmt.getPropertyURI()
.equals(VitroVocabulary.IND_MAIN_IMAGE)) {
mainImageUri = stmt.getObjectURI();
return mainImageUri;
}
}
List<ObjectPropertyStatement> mainImgStmts =
getObjectPropertyStatements(VitroVocabulary.IND_MAIN_IMAGE);
if (mainImgStmts != null && mainImgStmts.size() > 0) {
// arbitrarily return the first value in the list
mainImageUri = mainImgStmts.get(0).getObjectURI();
return mainImageUri;
}
return null;
}
}
@ -502,14 +502,11 @@ public class IndividualSDB extends IndividualImpl implements Individual {
if( _hasThumb != null ){
return _hasThumb;
}else{
String[] graphVars = { "?g" };
String ask =
"ASK { GRAPH ?g " +
" { <" + individualURI + "> <http://vitro.mannlib.cornell.edu/ns/vitro/public#mainImage> ?mainImage . \n" +
" ?mainImage <http://vitro.mannlib.cornell.edu/ns/vitro/public#thumbnailImage> ?thumbImage . }\n" +
WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) +
"}";
DatasetWrapper w = getDatasetWrapper();
"ASK { " +
" <" + individualURI + "> <http://vitro.mannlib.cornell.edu/ns/vitro/public#mainImage> ?mainImage . \n" +
" ?mainImage <http://vitro.mannlib.cornell.edu/ns/vitro/public#thumbnailImage> ?thumbImage . }\n" ;
DatasetWrapper w = getDatasetWrapper();
Dataset dataset = w.getDataset();
dataset.getLock().enterCriticalSection(Lock.READ);
try{
@ -552,10 +549,8 @@ public class IndividualSDB extends IndividualImpl implements Individual {
Dataset dataset = w.getDataset();
dataset.getLock().enterCriticalSection(Lock.READ);
try {
String graphVars[] = { "?g" };
StringBuffer selectPrimaryLinkQueryBuff = new StringBuffer().append(
"SELECT ?url ?anchor \n" ).append(
"WHERE{ GRAPH ?g { \n " ).append(
"SELECT ?url ?anchor \n" ).append(" WHERE { \n").append(
" <" + this.individualURI + "> ").append(
"<" + VitroVocabulary.PRIMARY_LINK + "> " ).append(
"?link . \n").append(
@ -563,9 +558,7 @@ public class IndividualSDB extends IndividualImpl implements Individual {
).append(
" ?link <" + VitroVocabulary.LINK_ANCHOR + "> ?anchor . \n"
).append(
"} \n")
.append(WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode))
.append("}");
"} \n");
QueryExecution qexec = QueryExecutionFactory.create(
QueryFactory.create(selectPrimaryLinkQueryBuff.toString())
, dataset);
@ -678,12 +671,9 @@ public class IndividualSDB extends IndividualImpl implements Individual {
Dataset dataset = w.getDataset();
dataset.getLock().enterCriticalSection(Lock.READ);
try {
String[] graphVars = { "?g" };
String valuesOfProperty =
"CONSTRUCT{<" + this.individualURI + "> <" + propertyURI + "> ?object}" +
"WHERE{ GRAPH ?g { <" + this.individualURI + "> <" + propertyURI + "> ?object} \n" +
WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) +
"}";
"CONSTRUCT{ <" + this.individualURI + "> <" + propertyURI + "> ?object }" +
"WHERE{ <" + this.individualURI + "> <" + propertyURI + "> ?object } \n";
tempModel = QueryExecutionFactory.create(QueryFactory.create(valuesOfProperty), dataset).execConstruct();
ontModel.add(tempModel.listStatements());
Resource ontRes = ontModel.getResource(this.individualURI);
@ -727,13 +717,10 @@ public class IndividualSDB extends IndividualImpl implements Individual {
Dataset dataset = w.getDataset();
dataset.getLock().enterCriticalSection(Lock.READ);
try {
String[] graphVars = { "?g" };
String valuesOfProperty =
"SELECT ?object" +
"WHERE{ GRAPH ?g { <" + this.individualURI + "> <" +
propertyURI + "> ?object} \n" +
WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) +
"}";
"WHERE{ <" + this.individualURI + "> <" +
propertyURI + "> ?object } \n";
ResultSet values = QueryExecutionFactory.create(
QueryFactory.create(valuesOfProperty), dataset)
.execSelect();
@ -767,13 +754,10 @@ public class IndividualSDB extends IndividualImpl implements Individual {
Dataset dataset = w.getDataset();
dataset.getLock().enterCriticalSection(Lock.READ);
try {
String[] graphVars = { "?g" };
String valueOfProperty =
"SELECT ?object " +
"WHERE{ GRAPH ?g { <" + this.individualURI + "> <" +
propertyURI + "> ?object} \n" +
WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) +
"}";
"WHERE{ <" + this.individualURI + "> <" +
propertyURI + "> ?object } \n";
QueryExecution qe = QueryExecutionFactory.create(
QueryFactory.create(valueOfProperty), dataset);
try {

View file

@ -103,6 +103,7 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
USERACCOUNT_EXTERNAL_AUTH_ID));
u.setPermissionSetUris(getPropertyResourceURIValues(r,
USERACCOUNT_HAS_PERMISSION_SET));
u.setRootUser(isResourceOfType(r, USERACCOUNT_ROOT_USER));
return u;
} finally {
getOntModel().leaveCriticalSection();
@ -157,21 +158,6 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
return getUserAccountByUri(userUri);
}
@Override
public boolean isRootUser(UserAccount userAccount) {
if (userAccount == null) {
return false;
}
getOntModel().enterCriticalSection(Lock.READ);
try {
OntResource r = getOntModel().getOntResource(userAccount.getUri());
return isResourceOfType(r, USERACCOUNT_ROOT_USER);
} finally {
getOntModel().leaveCriticalSection();
}
}
@Override
public String insertUserAccount(UserAccount userAccount) {
if (userAccount == null) {
@ -214,6 +200,10 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
USERACCOUNT_HAS_PERMISSION_SET,
userAccount.getPermissionSetUris(), model);
if (userAccount.isRootUser()) {
model.add(res, RDF.type, USERACCOUNT_ROOT_USER);
}
userAccount.setUri(userUri);
return userUri;
} catch (InsertException e) {
@ -268,6 +258,13 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
updatePropertyResourceURIValues(res,
USERACCOUNT_HAS_PERMISSION_SET,
userAccount.getPermissionSetUris(), model);
if (userAccount.isRootUser()) {
model.add(res, RDF.type, USERACCOUNT_ROOT_USER);
} else {
model.remove(res, RDF.type, USERACCOUNT_ROOT_USER);
}
} finally {
model.leaveCriticalSection();
}
@ -367,7 +364,7 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
throw new InsertException("Could not create URI for individual: "
+ errMsg);
}
private boolean isUriUsed(String uri) {
return (getOntModel().getOntResource(uri) != null);
}
@ -385,7 +382,7 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
if (type == null) {
return false;
}
StmtIterator stmts = getOntModel().listStatements(r, RDF.type, type);
if (stmts.hasNext()) {
stmts.close();

View file

@ -2,6 +2,8 @@
package edu.cornell.mannlib.vitro.webapp.email;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
@ -21,22 +23,30 @@ import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
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.controller.freemarker.TemplateProcessingHelper;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective;
import freemarker.core.Environment;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* A framework that makes it simpler to send email messages with a body built
* from a Freemarker template.
*
* In fact, the body can be plain text from a template, HTML from a template, or
* both.
* The template must contain the @email directive, which may provide the subject
* line, the HTML content, and the plain text content. If these values are not
* provided by the directive, they default to empty strings, or to values that
* were set by the controller.
*
* The directive also calls the send() method here.
*
* @see EmailDirective
*/
public class FreemarkerEmailMessage {
private static final Log log = LogFactory
@ -47,15 +57,15 @@ public class FreemarkerEmailMessage {
private final HttpServletRequest req;
private final Session session;
private final Configuration config;
private final ServletContext ctx;
private final List<Recipient> recipients = new ArrayList<Recipient>();
private final InternetAddress replyToAddress;
private InternetAddress fromAddress = null;
private String subject = "";
private String htmlTemplateName;
private String textTemplateName;
private String templateName = "";
private String htmlContent = "";
private String textContent = "";
private Map<String, Object> bodyMap = Collections.emptyMap();
/**
@ -67,8 +77,6 @@ public class FreemarkerEmailMessage {
this.session = session;
this.replyToAddress = replyToAddress;
this.ctx = req.getSession().getServletContext();
Object o = req.getAttribute(ATTRIBUTE_NAME);
if (!(o instanceof Configuration)) {
String oClass = (o == null) ? "null" : o.getClass().getName();
@ -115,10 +123,6 @@ public class FreemarkerEmailMessage {
try {
recipients.add(new Recipient(type, emailAddress, personalName));
} catch (AddressException e) {
log.warn("invalid recipient address: " + type + ", '"
+ emailAddress + "', personal name '" + personalName + "'");
return;
} catch (UnsupportedEncodingException e) {
log.warn("invalid recipient address: " + type + ", '"
+ emailAddress + "', personal name '" + personalName + "'");
@ -130,27 +134,41 @@ public class FreemarkerEmailMessage {
this.subject = nonNull(subject, "");
}
public void setHtmlTemplate(String templateName) {
this.htmlTemplateName = nonNull(templateName, "");
public void setHtmlContent(String htmlContent) {
this.htmlContent = nonNull(htmlContent, "");
}
public void setTextTemplate(String templateName) {
this.textTemplateName = nonNull(templateName, "");
public void setTextContent(String textContent) {
this.textContent = nonNull(textContent, "");
}
public void setTemplate(String templateName) {
this.templateName = nonNull(templateName, "");
}
public void setBodyMap(Map<String, Object> body) {
if (body == null) {
this.bodyMap = Collections.emptyMap();
} else {
this.bodyMap = Collections
.unmodifiableMap(new HashMap<String, Object>(body));
this.bodyMap = new HashMap<String, Object>(body);
}
}
public void processTemplate() {
bodyMap.putAll(FreemarkerHttpServlet.getDirectivesForAllEnvironments());
bodyMap.put("email", new EmailDirective(this));
try {
Template template = config.getTemplate(templateName);
template.process(bodyMap, new StringWriter());
} catch (TemplateException e) {
log.error(e, e);
} catch (IOException e) {
log.error(e, e);
}
}
public void send() {
String textBody = figureMessageBody(textTemplateName);
String htmlBody = figureMessageBody(htmlTemplateName);
try {
MimeMessage msg = new MimeMessage(session);
msg.setReplyTo(new Address[] { replyToAddress });
@ -167,19 +185,19 @@ public class FreemarkerEmailMessage {
msg.setSubject(subject);
if (textBody.isEmpty()) {
if (htmlBody.isEmpty()) {
if (textContent.isEmpty()) {
if (htmlContent.isEmpty()) {
log.error("Message has neither text body nor HTML body");
} else {
msg.setContent(htmlBody, "text/html");
msg.setContent(htmlContent, "text/html");
}
} else {
if (htmlBody.isEmpty()) {
msg.setContent(textBody, "text/plain");
if (htmlContent.isEmpty()) {
msg.setContent(textContent, "text/plain");
} else {
MimeMultipart content = new MimeMultipart("alternative");
addBodyPart(content, textBody, "text/plain");
addBodyPart(content, htmlBody, "text/html");
addBodyPart(content, textContent, "text/plain");
addBodyPart(content, htmlContent, "text/html");
msg.setContent(content);
}
}
@ -193,26 +211,6 @@ public class FreemarkerEmailMessage {
}
}
/**
* Process the template. If there is no template name or if there is a
* problem with the process, return an empty string.
*/
private String figureMessageBody(String templateName) {
if (templateName.isEmpty()) {
return "";
}
try {
TemplateProcessingHelper helper = new TemplateProcessingHelper(
config, req, ctx);
return helper.processTemplate(templateName, bodyMap).toString();
} catch (TemplateProcessingException e) {
log.warn("Exception while processing email template '"
+ templateName + "'", e);
return "";
}
}
private void addBodyPart(MimeMultipart content, String textBody, String type)
throws MessagingException {
MimeBodyPart bodyPart = new MimeBodyPart();
@ -235,7 +233,7 @@ public class FreemarkerEmailMessage {
}
public Recipient(RecipientType type, String address, String personalName)
throws AddressException, UnsupportedEncodingException {
throws UnsupportedEncodingException {
this.type = type;
this.address = new InternetAddress(address, personalName);
}

View file

@ -0,0 +1,98 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.directives;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
import freemarker.core.Environment;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
/**
* Process the inputs for a FreemarkerEmailMessage.
*
* @see FreemarkerEmailMessage
*/
public class EmailDirective extends BaseTemplateDirectiveModel {
private static final Log log = LogFactory.getLog(EmailDirective.class);
private final FreemarkerEmailMessage message;
public EmailDirective(FreemarkerEmailMessage message) {
this.message = message;
}
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException {
String subject = getOptionalSimpleScalarParameter(params, "subject");
if (subject != null) {
message.setSubject(subject);
}
String htmlContent = getOptionalSimpleScalarParameter(params, "html");
if (htmlContent != null) {
message.setHtmlContent(htmlContent);
}
String textContent = getOptionalSimpleScalarParameter(params, "text");
if (textContent != null) {
message.setTextContent(textContent);
}
if ((htmlContent == null) && (textContent == null)) {
throw new TemplateModelException("The email directive must have "
+ "either a 'html' parameter or a 'text' parameter.");
}
}
private String getOptionalSimpleScalarParameter(Map<?, ?> params,
String name) throws TemplateModelException {
Object o = params.get(name);
if (o == null) {
return null;
}
if (!(o instanceof SimpleScalar)) {
throw new TemplateModelException("The '" + name + "' parameter "
+ "for the email directive must be a string value.");
}
return o.toString();
}
@Override
public Map<String, Object> help(String name) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("effect",
"Create an email message from the parameters set in the invoking template.");
Map<String, String> params = new HashMap<String, String>();
params.put("subject", "email subject (optional)");
params.put("html", "HTML version of email message (optional)");
params.put("text", "Plain text version of email message (optional)");
map.put("parameters", params);
List<String> examples = new ArrayList<String>();
examples.add("&lt;email subject=\"Password reset confirmation\" html=html text=text&gt;");
examples.add("&lt;email html=html text=text&gt;");
map.put("examples", examples);
return map;
}
}

View file

@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import freemarker.core.Environment;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
@ -44,12 +45,19 @@ public class UrlDirective extends BaseTemplateDirectiveModel {
"The url directive doesn't allow nested content.");
}
String path = params.get("path").toString();
if (path == null) {
Object o = params.get("path");
if (o == null) {
throw new TemplateModelException(
"The url directive requires a value for parameter 'path'.");
}
if (! ( o instanceof SimpleScalar)) {
throw new TemplateModelException(
"The url directive requires a string value for parameter 'path'.");
}
String path = o.toString();
if (!path.startsWith("/")) {
throw new TemplateModelException(
"The url directive requires that the value of parameter 'path' is an absolute path starting with '/'.");
@ -60,6 +68,7 @@ public class UrlDirective extends BaseTemplateDirectiveModel {
out.write(url);
}
@Override
public Map<String, Object> help(String name) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
@ -77,6 +86,5 @@ public class UrlDirective extends BaseTemplateDirectiveModel {
return map;
}
}

View file

@ -94,6 +94,7 @@ public class WidgetDirective extends BaseTemplateDirectiveModel {
}
@Override
public Map<String, Object> help(String name) {
Map<String, Object> map = new LinkedHashMap<String, Object>();

View file

@ -32,13 +32,27 @@ public class User extends BaseTemplateModel {
return "";
}
String firstName = currentUser.getFirstName();
String lastName = currentUser.getLastName();
if (firstName.isEmpty() && lastName.isEmpty()) {
return currentUser.getEmailAddress();
}
return firstName + " " + lastName;
if (currentUser.getFirstName().isEmpty()) {
return currentUser.getEmailAddress();
}
return currentUser.getFirstName();
}
public String getFirstName() {
if (currentUser == null) {
return "";
} else {
return currentUser.getFirstName();
}
}
public String getLastName() {
if (currentUser == null) {
return "";
} else {
return currentUser.getLastName();
}
}
public boolean getHasSiteAdminAccess() {

View file

@ -6,6 +6,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
@ -36,7 +37,8 @@ public class VClassTemplateModel extends BaseTemplateModel {
return vclass.getEntityCount();
}
public VClassGroupTemplateModel getGroup(){
return new VClassGroupTemplateModel(vclass.getGroup());
public VClassGroupTemplateModel getGroup() {
VClassGroup group = vclass.getGroup();
return (group == null) ? null : new VClassGroupTemplateModel(vclass.getGroup());
}
}

View file

@ -2,26 +2,19 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;
import com.hp.hpl.jena.rdf.model.Literal;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.DropDataPropStmt;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.EditDataPropStmt;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash;