Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public AuditTrailService(AuditTrailStore store, AuditTrailCollector collector, A

/**
* Constructor for audit trail service with disabled preservation.
*
* <p/>
* See {@link #AuditTrailService(AuditTrailStore, AuditTrailCollector, AuditTrailPreserver, ContributorMediator,
* Settings)} for param descriptions.
*/
Expand Down Expand Up @@ -119,9 +119,7 @@ public AuditEventIterator queryAuditTrailEventsByIterator(Date fromDate, Date to
}

/**
* Collects all the newest audit trails from the given collection.
* TODO this currently calls all collections. It should only call a specified collection, which should be given
* as argument.
* Collects all the newest audit trails from all collections.
*/
public void collectAuditTrails() {
for (org.bitrepository.settings.repositorysettings.Collection c
Expand All @@ -130,6 +128,13 @@ public void collectAuditTrails() {
}
}

/**
* Collects all the newest audit trails from a specific collection.
*/
public void collectAuditTrails(String collectionID) {
collector.collectNewestAudits(collectionID);
}

/**
* Get the list of {@link CollectorInfo}
*
Expand All @@ -151,7 +156,7 @@ public List<CollectorInfo> getCollectorInfos() {
* @return PreservationInfo or null if not enabled.
*/
public PreservationInfo getPreservationInfo() {
if (preserver == null ) {
if (preserver == null) {
return null;
}
return preserver.getPreservationInfo();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
Expand All @@ -52,6 +53,7 @@
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

@Path("/AuditTrailService")
Expand All @@ -68,8 +70,7 @@ public RestAuditTrailService() {
@Path("/queryAuditTrailEvents/")
@Consumes("application/x-www-form-urlencoded")
@Produces("application/json")
public StreamingOutput queryAuditTrailEvents(
@FormParam("fromDate") String fromDate,
public StreamingOutput queryAuditTrailEvents(@FormParam("fromDate") String fromDate,
@FormParam("toDate") String toDate,
@FormParam("fileID") String fileID,
@FormParam("reportingComponent") String reportingComponent,
Expand All @@ -83,9 +84,9 @@ public StreamingOutput queryAuditTrailEvents(
Date to = calendarUtils.makeEndDateObject(toDate);

final int maxAudits = maxResults;
final AuditEventIterator it = service.queryAuditTrailEventsByIterator(from, to, contentOrNull(fileID), collectionID,
contentOrNull(reportingComponent), contentOrNull(actor), filterAction(action), contentOrNull(fingerprint),
contentOrNull(operationID));
final AuditEventIterator it = service.queryAuditTrailEventsByIterator(from, to, contentOrNull(fileID),
collectionID, contentOrNull(reportingComponent), contentOrNull(actor), filterAction(action),
contentOrNull(fingerprint), contentOrNull(operationID));
if (it != null) {
return output -> {
JsonFactory jf = new JsonFactory();
Expand Down Expand Up @@ -114,17 +115,26 @@ public StreamingOutput queryAuditTrailEvents(
}
};
} else {
throw new WebApplicationException(Response.status(Response.Status.NO_CONTENT).entity("Failed to get audit trails from database")
.type(MediaType.TEXT_PLAIN).build());
throw new WebApplicationException(
Response.status(Response.Status.NO_CONTENT).entity("Failed to get audit trails from database")
.type(MediaType.TEXT_PLAIN).build());
}
}

@POST
@Path("/collectAuditTrails/")
@Path("/collectAuditTrails")
@Produces("text/html")
public String collectAuditTrails() {
service.collectAuditTrails();
return "Started audit trails collection";
return "Started audit trails collection.";
}

@POST
@Path("/collectSpecificAuditTrail")
@Produces("text/html")
public String collectSpecificAuditTrail(@QueryParam("collectionID") String collectionID) {
service.collectAuditTrails(collectionID);
return String.format(Locale.ROOT, "Started collecting audit trails for collection: %s.", collectionID);
}

@GET
Expand All @@ -143,7 +153,7 @@ public PreservationInfo getPreservationSchedule() {
return preservationInfo;
} else {
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND)
.entity("404: Preservation must be enabled in settings to use this endpoint")
.entity("404: Preservation must be enabled in settings to use this endpoint.")
.type(MediaType.TEXT_PLAIN).build());
}
}
Expand All @@ -154,7 +164,8 @@ private void writeAuditResult(AuditTrailEvent event, JsonGenerator jg) throws IO
jg.writeObjectField("reportingComponent", event.getReportingComponent());
jg.writeObjectField("actor", contentOrEmptyString(event.getActorOnFile()));
jg.writeObjectField("action", event.getActionOnFile().toString());
jg.writeObjectField("timeStamp", TimeUtils.shortDate(CalendarUtils.convertFromXMLGregorianCalendar(event.getActionDateTime())));
jg.writeObjectField("timeStamp",
TimeUtils.shortDate(CalendarUtils.convertFromXMLGregorianCalendar(event.getActionDateTime())));
jg.writeObjectField("info", contentOrEmptyString(event.getInfo()));
jg.writeObjectField("auditTrailInfo", contentOrEmptyString(event.getAuditTrailInformation()));
jg.writeObjectField("fingerprint", contentOrEmptyString(event.getCertificateID()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
* Copyright (C) 2010 - 2012 The State and University Library, The Royal Library and The State Archives, Denmark
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
Expand Down Expand Up @@ -54,75 +54,73 @@
import static org.mockito.Mockito.verify;

public class AuditTrailServiceTest extends ExtendedTestCase {
/** The settings for the tests. Should be instantiated in the setup.*/
/** The settings for the tests. Should be instantiated in the setup. */
Settings settings;

public static final String TEST_COLLECTION = "dummy-collection";
public static final String DEFAULT_CONTRIBUTOR = "Contributor1";
private ThreadFactory threadFactory;


@BeforeClass (alwaysRun = true)
@BeforeClass(alwaysRun = true)
public void setup() throws Exception {
settings = TestSettingsProvider.reloadSettings("AuditTrailServiceUnderTest");
Collection c = settings.getRepositorySettings().getCollections().getCollection().get(0);
settings.getRepositorySettings().getCollections().getCollection().clear();
c.setID(TEST_COLLECTION);
settings.getRepositorySettings().getCollections().getCollection().add(c);
threadFactory = new DefaultThreadFactory(this.getClass().getSimpleName(),Thread.NORM_PRIORITY);
threadFactory = new DefaultThreadFactory(this.getClass().getSimpleName(), Thread.NORM_PRIORITY);
}

@Test(groups = {"unstable"})
public void auditTrailServiceTest() throws Exception {
addDescription("Test the Audit Trail Service");
DatatypeFactory factory = DatatypeFactory.newInstance();
settings.getRepositorySettings().getGetAuditTrailSettings().getNonPillarContributorIDs().clear();
settings.getRepositorySettings().getGetAuditTrailSettings().getNonPillarContributorIDs().add(DEFAULT_CONTRIBUTOR);
settings.getRepositorySettings().getGetAuditTrailSettings().getNonPillarContributorIDs()
.add(DEFAULT_CONTRIBUTOR);
settings.getReferenceSettings().getAuditTrailServiceSettings()
.setCollectAuditInterval(factory.newDuration(800));
settings.getReferenceSettings().getAuditTrailServiceSettings().setTimerTaskCheckInterval(100L);
settings.getReferenceSettings().getAuditTrailServiceSettings()
.setGracePeriod(factory.newDuration(800));
settings.getReferenceSettings().getAuditTrailServiceSettings().setGracePeriod(factory.newDuration(800));

AuditTrailStore store = mock(AuditTrailStore.class);
AuditTrailClient client = mock(AuditTrailClient.class);
AlarmDispatcher alarmDispatcher = mock(AlarmDispatcher.class);

ContributorMediator mediator = mock(ContributorMediator.class);
AuditTrailCollector collector = new AuditTrailCollector(settings, client, store, alarmDispatcher);

addStep("Instantiate the service.", "Should work.");
AuditTrailService service = new AuditTrailService(store, collector, mediator, settings);
service.start();

addStep("Try to collect audit trails.", "Should make a call to the client.");
CollectionRunner collectionRunner = new CollectionRunner(service);
Thread t = threadFactory.newThread(collectionRunner);
t.start();

ArgumentCaptor<EventHandler> eventHandlerCaptor = ArgumentCaptor.forClass(EventHandler.class);
verify(client, timeout(3000).times(1)).getAuditTrails(eq(TEST_COLLECTION), any(AuditTrailQuery[].class),
isNull(), isNull(), eventHandlerCaptor.capture(), any(String.class));

AuditTrailResult event = new AuditTrailResult(DEFAULT_CONTRIBUTOR, TEST_COLLECTION, new ResultingAuditTrails(), false);

AuditTrailResult event = new AuditTrailResult(DEFAULT_CONTRIBUTOR, TEST_COLLECTION, new ResultingAuditTrails(),
false);
eventHandlerCaptor.getValue().handleEvent(event);
eventHandlerCaptor.getValue().handleEvent(new CompleteEvent(TEST_COLLECTION, null));

addStep("Retrieve audit trails with and without an action", "Should work.");

verify(store, times(1)).addAuditTrails(any(AuditTrailEvents.class), eq(TEST_COLLECTION), eq(DEFAULT_CONTRIBUTOR));

verify(store, times(1)).addAuditTrails(any(AuditTrailEvents.class), eq(TEST_COLLECTION),
eq(DEFAULT_CONTRIBUTOR));
service.queryAuditTrailEventsByIterator(null, null, null, null, null, null, null, null, null);
verify(store, times(1)).getAuditTrailsByIterator(isNull(), isNull(),
isNull(), isNull(), isNull(), isNull(),
isNull(), isNull(), isNull(), isNull(),
isNull());
verify(store, times(1)).getAuditTrailsByIterator(isNull(), isNull(), isNull(), isNull(), isNull(), isNull(),
isNull(), isNull(), isNull(), isNull(), isNull());
service.queryAuditTrailEventsByIterator(null, null, null, null, null, null, FileAction.FAILURE, null, null);
verify(store, times(1)).getAuditTrailsByIterator(isNull(), isNull(),
isNull(), isNull(), isNull(), isNull(),
eq(FileAction.FAILURE), isNull(), isNull(), isNull(),
isNull());
verify(store, times(1)).getAuditTrailsByIterator(isNull(), isNull(), isNull(), isNull(), isNull(), isNull(),
eq(FileAction.FAILURE), isNull(), isNull(), isNull(), isNull());



addStep("Shutdown", "");
service.shutdown();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
*/
package org.bitrepository.integrityservice.reports;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
* Class containing constants related to integrity reports
*/
Expand Down Expand Up @@ -59,4 +63,8 @@ public enum ReportPart {
public static final String SECTION_HEADER_START_STOP = "========";
public static final String PILLAR_HEADER_START_STOP = "--------";
public static final String NO_ISSUE_HEADER_START_STOP = "++++++++";

public static Set<ReportPart> getReportParts() {
return new HashSet<>(Arrays.asList(ReportPart.values()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public IntegrityReportProvider(File reportsDir) {
* @return IntegrityReportReader with the latest integrity report
* @throws FileNotFoundException if no report could be found
*/
public synchronized IntegrityReportReader getLatestIntegrityReportReader(String collectionID) throws FileNotFoundException {
public synchronized IntegrityReportReader getLatestIntegrityReportReader(String collectionID)
throws FileNotFoundException {
IntegrityReportReader reader = reports.get(collectionID);
if (reader == null) {
log.info("Trying to lookup the latest report on disk for collection {}", collectionID);
Expand All @@ -63,6 +64,26 @@ public synchronized IntegrityReportReader getLatestIntegrityReportReader(String
return reader;
}

/**
* Get the latest integrity report of a collection, for a specific report part and specific pillar.
*
* @param collectionID The specific collectionID.
* @param pillarID The specific pillarID.
* @param reportPart The specific ReportPart.
* @return Returns the given report part {@link File} if it exists.
* @throws FileNotFoundException If no such report part can be found for the given pillar and collection.
*/
public synchronized File getIntegrityReportPart(String collectionID, String pillarID, String reportPart)
throws FileNotFoundException {
log.info("Trying to lookup the '{}' report on disk for collection '{}'", reportPart, collectionID);
File latestReportPart = getReportPartFromDisk(collectionID, pillarID, reportPart);
if (latestReportPart != null) {
return latestReportPart;
} else {
throw new FileNotFoundException("Could not find latest integrity report");
}
}

/**
* Register the latest integrity report for a given collection
*
Expand All @@ -75,7 +96,7 @@ public synchronized void setLatestReport(String collectionID, File reportDir) {

private File getLatestReportFromDisk(String collectionID) {
File collectionReports = new File(reportsDir, collectionID);
log.info("Looking for latest report dir in {}", collectionReports);
log.info("Looking for latest report dir in '{}'", collectionReports);
File[] reports = collectionReports.listFiles(File::isDirectory);
long lastModification = Long.MIN_VALUE;
File latestReport = null;
Expand All @@ -87,7 +108,37 @@ private File getLatestReportFromDisk(String collectionID) {
latestReport = reportDir;
lastModification = latestReport.lastModified();
} else {
log.debug("Candidate report dir {} had no report file", reportDir);
log.debug("Candidate report dir '{}' had no report file", reportDir);
}
}
}

return latestReport;
}

/**
* Returns the latest report part for the given collection and pillar.
*
* @param collectionID The collection ID.
* @param pillarID The pillar ID.
* @param reportPart The wanted report part as {@link String}.
* @return Returns a {@link File} containing the latest report part for the given collection and pillar if such a file exists.
*/
private File getReportPartFromDisk(String collectionID, String pillarID, String reportPart) {
File collectionReports = new File(reportsDir, collectionID);
log.info("Looking for latest report dir in '{}'", collectionReports);
File[] reports = collectionReports.listFiles(File::isDirectory);
long lastModification = Long.MIN_VALUE;
File latestReport = null;
assert reports != null;
for (File reportDir : reports) {
if (reportDir.lastModified() > lastModification) {
File reportFile = new File(reportDir, reportPart + "-" + pillarID);
if (reportFile.exists()) {
latestReport = reportFile;
lastModification = latestReport.lastModified();
} else {
log.debug("Report dir '{}' had no '{}'-report for pillar '{}'", reportDir, reportPart, pillarID);
}
}
}
Expand Down
Loading