Commit b963d8a4 authored by Michael Ritter's avatar Michael Ritter

Various bug fixes for endpoints on the audit manager module

ace-am/
  - pass the correct ReportPolicy when removing Reporting
  - instead of throwing exceptions, send HTTP 400s when missing parameters (ListItemDetailsServlet, CollectionSummaryServlet, DuplicateReportServlet)
  - allow browsing of the report servlet when none are found for a collection
parent 526c6bc5
......@@ -36,7 +36,9 @@ import edu.umiacs.ace.util.EntityManagerServlet;
import org.apache.log4j.Logger;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
......@@ -47,7 +49,7 @@ import java.util.List;
/**
* Show the current status of a collection, listing any non-active files
*
*
* @author toaster
*/
public class CollectionSummaryServlet extends EntityManagerServlet {
......@@ -63,15 +65,16 @@ public class CollectionSummaryServlet extends EntityManagerServlet {
public static final String PAGE_COUNT = "count";
public static final String PAGE_SESSION = "session";
/**
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
* @param request servlet request
*
* @param request servlet request
* @param response servlet response
*/
@Override
protected void processRequest( HttpServletRequest request,
HttpServletResponse response, EntityManager em )
throws ServletException, IOException {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response,
EntityManager em) throws ServletException, IOException {
RequestDispatcher dispatch;
long startid = getParameter(request, PARAM_START, 0);
long topid = getParameter(request, PARAM_TOP, 0);
......@@ -84,41 +87,47 @@ public class CollectionSummaryServlet extends EntityManagerServlet {
// determine start
String startquery = "";
if ( startid > 0 ) {
if (startid > 0) {
startquery = "AND m.id > :id ";
} else if ( topid > 0 ) {
} else if (topid > 0) {
startquery = "AND m.id < :id ";
}
// build query
Query q;
TypedQuery<MonitoredItem> q;
Collection c = getCollection(request, em);
// todo: if null should we return all error'd items from the db?
// probably a bad idea for this servlet
if (c == null) {
response.sendError(400, "collectionid must be present!");
return;
}
query += "m.parentCollection = :coll " + startquery;
q = em.createQuery(query);
q = em.createQuery(query, MonitoredItem.class);
q.setParameter("coll", c);
LOG.debug("query: " + query);
// fill in start ids if necessary
if ( startid > 0 ) {
if (startid > 0) {
q.setParameter("id", startid);
} else if ( topid > 0 ) {
} else if (topid > 0) {
q.setParameter("id", topid);
}
if ( count != -1 ) {
if (count != -1) {
q.setMaxResults(count);
}
List<MonitoredItem> miList = q.getResultList();
if ( miList != null && miList.size() > 0 ) {
request.setAttribute(PAGE_NEXT,
miList.get(miList.size() - 1).getId() + 1);
if (miList != null && miList.size() > 0) {
request.setAttribute(PAGE_NEXT, miList.get(miList.size() - 1).getId() + 1);
}
if ( listOnly ) {
if (listOnly) {
Writer writer = response.getWriter();
response.setContentType("text/plain");
for ( MonitoredItem mi : miList ) {
for (MonitoredItem mi : miList) {
writer.write(mi.getState() + ":" + mi.getPath() + "\r\n");
}
return;
......@@ -132,8 +141,7 @@ public class CollectionSummaryServlet extends EntityManagerServlet {
csb.setTotalFiles(CollectionCountContext.getFileCount(c));
csb.setActiveFiles(CollectionCountContext.getActiveCount(c));
csb.setCorruptFiles(CollectionCountContext.getCorruptCount(c));
csb.setInvalidDigests(CollectionCountContext.getTokenMismatchCount(
c));
csb.setInvalidDigests(CollectionCountContext.getTokenMismatchCount(c));
csb.setMissingFiles(CollectionCountContext.getMissingCount(c));
csb.setMissingTokens(CollectionCountContext.getMissingTokenCount(c));
csb.setTotalErrors(CollectionCountContext.getTotalErrors(c));
......@@ -145,7 +153,7 @@ public class CollectionSummaryServlet extends EntityManagerServlet {
request.setAttribute(PAGE_COLLECTION, csb);
request.setAttribute(PAGE_COUNT, count);
if ( hasJson(request) ) {
if (hasJson(request)) {
dispatch = request.getRequestDispatcher("report-json.jsp");
} else {
dispatch = request.getRequestDispatcher("report.jsp");
......@@ -160,6 +168,11 @@ public class CollectionSummaryServlet extends EntityManagerServlet {
Query q = em.createQuery(query);
q.setParameter("c", c);
q.setMaxResults(1);
return (Long) q.getSingleResult();
try {
return (Long) q.getSingleResult();
} catch (NoResultException e) {
LOG.warn("No sessions available for collection", e);
return null;
}
}
}
......@@ -30,23 +30,24 @@
// $Id$
package edu.umiacs.ace.monitor.access;
import edu.umiacs.ace.util.EntityManagerServlet;
import edu.umiacs.ace.monitor.core.Collection;
import edu.umiacs.ace.monitor.core.MonitoredItem;
import edu.umiacs.ace.monitor.core.MonitoredItemManager;
import edu.umiacs.ace.monitor.core.Collection;
import edu.umiacs.ace.util.EntityManagerServlet;
import edu.umiacs.util.Strings;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import javax.persistence.EntityManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
/**
* List details for a file or directory
*
*
* @author toaster
*/
public final class ListItemDetailsServlet extends EntityManagerServlet {
......@@ -56,30 +57,30 @@ public final class ListItemDetailsServlet extends EntityManagerServlet {
private static final String PARAM_PATH = "itempath";
@Override
protected void processRequest( HttpServletRequest request,
HttpServletResponse response, EntityManager em ) throws ServletException, IOException {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response,
EntityManager em) throws ServletException, IOException {
Collection coll = getCollection(request, em);
String path = getParameter(request, PARAM_PATH, "");
MonitoredItemManager mim = new MonitoredItemManager(em);
if ( coll == null ) {
throw new ServletException("No collection found");
if (coll == null) {
response.sendError(400, "collectionid must be present");
return;
}
if ( Strings.isEmpty(path) ) {
if (Strings.isEmpty(path)) {
request.setAttribute(PAGE_ITEMS, mim.getCollectionRoots(coll));
} else {
MonitoredItem item = mim.getItemByPath(path, coll);
if ( item == null ) {
throw new ServletException("No item for path " + path);
if (item == null) {
response.sendError(400, "No item for path " + path);
return;
}
List<MonitoredItem> childItems;
if ( item.isDirectory() ) {
childItems = mim.listChildren(item.getParentCollection(),
item.getPath());
if (item.isDirectory()) {
childItems = mim.listChildren(item.getParentCollection(), item.getPath());
} else {
childItems = Collections.emptyList();
}
......@@ -88,13 +89,12 @@ public final class ListItemDetailsServlet extends EntityManagerServlet {
}
RequestDispatcher dispatcher;
if ( hasJson(request) ) {
if (hasJson(request)) {
dispatcher = request.getRequestDispatcher("listitem-json.jsp");
} else {
dispatcher = request.getRequestDispatcher("listitem.jsp");
}
dispatcher.forward(request, response);
dispatcher.forward(request, response);
}
}
......@@ -32,10 +32,17 @@
package edu.umiacs.ace.monitor.compare;
import edu.umiacs.ace.monitor.access.CollectionCountContext;
import edu.umiacs.ace.monitor.core.Collection;
import edu.umiacs.ace.util.EntityManagerServlet;
import edu.umiacs.ace.util.PersistUtil;
import edu.umiacs.ace.monitor.core.Collection;
import edu.umiacs.sql.SQL;
import org.apache.log4j.Logger;
import javax.persistence.EntityManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
......@@ -46,15 +53,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.persistence.EntityManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
/**
*
* @author toaster
*/
public class DuplicateReportServlet extends EntityManagerServlet {
......@@ -68,8 +68,9 @@ public class DuplicateReportServlet extends EntityManagerServlet {
public static final String PAGE_TIME = "time";
@Override
protected void processRequest( HttpServletRequest request,
HttpServletResponse response, EntityManager em ) throws ServletException, IOException {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response,
EntityManager em) throws ServletException, IOException {
Collection collection = null;
RequestDispatcher dispatcher;
Connection conn = null;
......@@ -78,29 +79,29 @@ public class DuplicateReportServlet extends EntityManagerServlet {
// long totalFiles = 0;
// digest, # instances of digest
Set<MyEntry> duplicateCount = new TreeSet<MyEntry>();
Set<MyEntry> duplicateCount = new TreeSet<>();
// # digest instances, total over all digests
List<HistEntry> histogram = new ArrayList<HistEntry>();
List<HistEntry> histogram = new ArrayList<>();
long collectionId = getParameter(request, PARAM_COLLECTION_ID, 0);
if ( collectionId > 0 ) {
if (collectionId > 0) {
collection = em.getReference(Collection.class, collectionId);
try {
conn = PersistUtil.getDataSource().getConnection();
PreparedStatement pst =
conn.prepareStatement(
"SELECT monitored_item.FILEDIGEST, count(monitored_item.FILEDIGEST) "
+ "FROM monitored_item " + "WHERE monitored_item.PARENTCOLLECTION_ID = ? "
+ "GROUP BY monitored_item.FILEDIGEST HAVING COUNT(monitored_item.FILEDIGEST) > 1");
"SELECT monitored_item.FILEDIGEST, count(monitored_item.FILEDIGEST) "
+ "FROM monitored_item " + "WHERE monitored_item.PARENTCOLLECTION_ID = ? "
+ "GROUP BY monitored_item.FILEDIGEST HAVING COUNT(monitored_item.FILEDIGEST) > 1");
pst.setLong(1, collectionId);
ResultSet rs = pst.executeQuery();
while ( rs.next() ) {
while (rs.next()) {
String hash = rs.getString(1);
int count = rs.getInt(2);
// totalFiles += count;
if ( count > 1 ) {
if (count > 1) {
duplicateCount.add(new MyEntry(count, hash));
totalDups += count - 1;
increment(histogram, count);
......@@ -110,13 +111,17 @@ public class DuplicateReportServlet extends EntityManagerServlet {
rs.close();
pst.close();
LOG.info("Duplicate report on " + collection.getName() + " time "
+ (System.currentTimeMillis() - startTime) + " total dups " + totalDups);
+ (System.currentTimeMillis() - startTime) + " total dups " + totalDups);
} catch ( SQLException e ) {
} catch (SQLException e) {
throw new ServletException(e);
} finally {
SQL.release(conn);
}
} else {
// if there's no collectionid present, return with a bad request
response.sendError(400, "collectionid must be present");
return;
}
Collections.sort(histogram);
......@@ -127,9 +132,9 @@ public class DuplicateReportServlet extends EntityManagerServlet {
request.setAttribute(PAGE_LIST, duplicateCount);
request.setAttribute(PAGE_HISTO, histogram);
request.setAttribute(PAGE_TIME, (System.currentTimeMillis() - startTime));
if ( hasJson(request) ) {
if (hasJson(request)) {
dispatcher = request.getRequestDispatcher("duplicatereport-json.jsp");
} else {
dispatcher = request.getRequestDispatcher("duplicatereport.jsp");
......@@ -137,9 +142,9 @@ public class DuplicateReportServlet extends EntityManagerServlet {
dispatcher.forward(request, response);
}
private void increment( List<HistEntry> map, int idx ) {
for ( HistEntry e : map ) {
if ( e.digestCount == idx ) {
private void increment(List<HistEntry> map, int idx) {
for (HistEntry e : map) {
if (e.digestCount == idx) {
e.instances++;
return;
}
......@@ -153,7 +158,7 @@ public class DuplicateReportServlet extends EntityManagerServlet {
int digestCount;
int instances;
private HistEntry( int digestCount ) {
private HistEntry(int digestCount) {
this.digestCount = digestCount;
this.instances = 1;
}
......@@ -175,26 +180,26 @@ public class DuplicateReportServlet extends EntityManagerServlet {
}
@Override
public boolean equals( Object obj ) {
if ( obj == null ) {
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if ( getClass() != obj.getClass() ) {
if (getClass() != obj.getClass()) {
return false;
}
final HistEntry other = (HistEntry) obj;
if ( this.digestCount != other.digestCount ) {
if (this.digestCount != other.digestCount) {
return false;
}
if ( this.instances != other.instances ) {
if (this.instances != other.instances) {
return false;
}
return true;
}
@Override
public int compareTo( HistEntry o ) {
if ( digestCount == o.digestCount ) {
public int compareTo(HistEntry o) {
if (digestCount == o.digestCount) {
return digestCount - o.digestCount;
}
return instances - o.instances;
......@@ -206,7 +211,7 @@ public class DuplicateReportServlet extends EntityManagerServlet {
int count;
String digest;
private MyEntry( int count, String digest ) {
private MyEntry(int count, String digest) {
this.count = count;
this.digest = digest;
}
......@@ -220,26 +225,26 @@ public class DuplicateReportServlet extends EntityManagerServlet {
}
@Override
public boolean equals( Object obj ) {
if ( obj == null ) {
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if ( getClass() != obj.getClass() ) {
if (getClass() != obj.getClass()) {
return false;
}
final MyEntry other = (MyEntry) obj;
if ( this.count != other.count ) {
return false;
}
if ( (this.digest == null) ? (other.digest != null) : !this.digest.equals(other.digest) ) {
if (this.count != other.count) {
return false;
}
return true;
return (this.digest == null)
? (other.digest == null)
: this.digest.equals(other.digest);
}
@Override
public int compareTo( MyEntry o ) {
if ( o.count != count ) {
public int compareTo(MyEntry o) {
if (o.count != count) {
return o.count - count;
} else {
return o.digest.compareTo(digest);
......
......@@ -199,6 +199,7 @@ public class Collection implements Serializable {
return state.asChar();
}
@JsonIgnore
public CollectionState getStateEnum() {
return state;
}
......
......@@ -31,11 +31,12 @@
package edu.umiacs.ace.monitor.reporting;
import edu.umiacs.ace.util.EntityManagerServlet;
import edu.umiacs.ace.monitor.core.Collection;
import edu.umiacs.ace.util.EntityManagerServlet;
import edu.umiacs.util.Strings;
import java.io.IOException;
import java.text.ParseException;
import org.apache.log4j.Logger;
import org.quartz.CronExpression;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.EntityTransaction;
......@@ -44,8 +45,8 @@ import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.quartz.CronExpression;
import java.io.IOException;
import java.text.ParseException;
/**
* Servlet to configure automated generation of ReportSummarys .
......@@ -55,7 +56,6 @@ import org.quartz.CronExpression;
* month = month list to run
* day = day of month to run
* reportid = id of existing to modify, if empty this will create a new one
*
*
* @author toaster
*/
......@@ -76,54 +76,54 @@ public class ReportConfigurationServlet extends EntityManagerServlet {
ReportConfigurationServlet.class);
@Override
protected void processRequest( HttpServletRequest request,
HttpServletResponse response, EntityManager em ) throws ServletException, IOException {
long removeid = getParameter(request, PARAM_REMOVEID, 0);
protected void processRequest(HttpServletRequest request,
HttpServletResponse response,
EntityManager em) throws ServletException, IOException {
Collection coll;
ReportPolicy rp = getReportPolicy(request, em);
Collection coll = null;
if ( rp != null ) {
long removeid = getParameter(request, PARAM_REMOVEID, 0);
if (rp != null) {
coll = rp.getCollection();
} else {
coll = getCollection(request, em);
}
if ( removeid > 0 ) {
ReportPolicy removePolicy = em.getReference(ReportPolicy.class,
removeid);
if ( removePolicy != null ) {
if (removeid > 0) {
ReportPolicy removePolicy = em.getReference(ReportPolicy.class, removeid);
if (removePolicy != null) {
LOG.debug("Removing report policy " + removePolicy.getName());
coll = removePolicy.getCollection();
EntityTransaction trans = em.getTransaction();
trans.begin();
try {
SchedulerContextListener.removeJob(rp);
SchedulerContextListener.removeJob(removePolicy);
em.remove(removePolicy);
trans.commit();
} catch ( Exception e ) {
} catch (Exception e) {
LOG.error("Error removing report", e);
}
}
} // are we saving a new or modifying existing
else if ( !Strings.isEmpty(request.getParameter(PARAM_SUBMIT)) ) {
else if (!Strings.isEmpty(request.getParameter(PARAM_SUBMIT))) {
String name = getParameter(request, PARAM_NAME, null);
CronExpression ce = null;
CronExpression ce;
try {
ce = extractCronString(request);
} catch ( Exception e ) {
} catch (Exception e) {
LOG.error("Bad regex", e);
throw new ServletException(e);
}
LOG.debug("Extracted cron string " + ce.getCronExpression());
if ( rp != null ) {
if (rp != null) {
if ( !Strings.isEmpty(name) ) {
if (!Strings.isEmpty(name)) {
rp.setName(name);
}
rp.setEmailList(getParameter(request, PARAM_EMAIL, null));
rp.setCronString(ce.getCronExpression());
EntityTransaction trans = em.getTransaction();
......@@ -133,23 +133,22 @@ public class ReportConfigurationServlet extends EntityManagerServlet {
trans.commit();
SchedulerContextListener.removeJob(rp);
SchedulerContextListener.addJob(rp);
} catch ( Exception e ) {
} catch (Exception e) {
LOG.error("Error merging report", e);
}
} else {
rp = new ReportPolicy();
// if name is null && months are null, do not persist
if ( Strings.isEmpty(name) ) {
if (Strings.isEmpty(name)) {
name = "unnamed";
}
rp.setName(name);
rp.setCronString(ce.getCronExpression());
rp.setEmailList(getParameter(request, PARAM_EMAIL, null));
if ( coll == null ) {
throw new ServletException(
"No collection included for report");
if (coll == null) {
throw new ServletException("No collection included for report");
}
rp.setCollection(coll);
......@@ -159,7 +158,7 @@ public class ReportConfigurationServlet extends EntityManagerServlet {
em.persist(rp);
trans.commit();
SchedulerContextListener.addJob(rp);
} catch ( Exception e ) {
} catch (Exception e) {
LOG.error("Error saving report", e);
}
}
......@@ -173,7 +172,7 @@ public class ReportConfigurationServlet extends EntityManagerServlet {
request.setAttribute(PAGE_REPORTS, q.getResultList());
request.setAttribute(PAGE_COLLECTION, coll);
request.setAttribute(PAGE_REPORT, rp);
if ( rp != null ) {
if (rp != null) {
LOG.debug("Shoving report policy into page context: " + rp.getName());
// hack for now to extract day/month string and set months
//TODO: this should be moved into a taglib if we decide to support
......@@ -181,44 +180,41 @@ public class ReportConfigurationServlet extends EntityManagerServlet {
// request.setAttribute(name, );
request.setAttribute(PAGE_DAY, extractDay(rp.getCronString()));
for ( String s : extractMonthList(rp.getCronString()) ) {
for (String s : extractMonthList(rp.getCronString())) {
request.setAttribute(s, "checked");
}
}
RequestDispatcher dispatcher = request.getRequestDispatcher(
"reportpolicy.jsp");
RequestDispatcher dispatcher = request.getRequestDispatcher("reportpolicy.jsp");
dispatcher.forward(request, response);
}
public String extractDay( String c ) {
public String extractDay(String c) {
String cronList[] = c.split("\\s");
return cronList[3];
}
public String[] extractMonthList( String c ) {
public String[] extractMonthList(String c) {
String cronList[] = c.split("\\s");
return cronList[4].split(",");
}
public CronExpression extractCronString( HttpServletRequest request ) throws ParseException {
public CronExpression extractCronString(HttpServletRequest request) throws ParseException {
StringBuilder sb = new StringBuilder();