/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the License at the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apereo.portal.events;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.portlet.PortletMode;
import javax.portlet.WindowState;
import javax.xml.namespace.QName;
import org.apereo.portal.concurrency.CallableWithoutResult;
import org.apereo.portal.concurrency.FunctionWithoutResult;
import org.apereo.portal.events.handlers.db.IPortalEventDao;
import org.apereo.portal.mock.portlet.om.MockPortletWindowId;
import org.apereo.portal.security.SystemPerson;
import org.apereo.portal.test.BaseRawEventsJpaDaoTest;
import org.joda.time.DateTime;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:jpaRawEventsTestApplicationContext.xml")
public class JpaPortalEventStoreTest extends BaseRawEventsJpaDaoTest {
@Autowired private IPortalEventDao portalEventDao;
@Test
public void testStoreSingleEvents() throws Exception {
final DateTime startDate = DateTime.now().minusDays(1);
final DateTime endDate = DateTime.now().plusDays(1);
final List<PortalEvent> originalEvents = generateEvents();
execute(
new CallableWithoutResult() {
@Override
protected void callWithoutResult() {
for (final PortalEvent event : originalEvents) {
portalEventDao.storePortalEvent(event);
}
}
});
verifyGetEvents(originalEvents, startDate, endDate);
verifyAggregateEvents(originalEvents, startDate, endDate);
verifyAggregateEvents(Collections.<PortalEvent>emptyList(), startDate, endDate);
deleteEvents(originalEvents, startDate, endDate);
verifyGetEvents(Collections.<PortalEvent>emptyList(), startDate, endDate);
verifyAggregateEvents(Collections.<PortalEvent>emptyList(), startDate, endDate);
}
@Test
public void testStoreBatchEvents() throws Exception {
final DateTime startDate = DateTime.now().minusDays(1);
final DateTime endDate = DateTime.now().plusDays(1);
final List<PortalEvent> originalEvents = generateEvents();
execute(
new CallableWithoutResult() {
@Override
protected void callWithoutResult() {
final DateTime oldestPortalEventTimestamp =
portalEventDao.getOldestPortalEventTimestamp();
assertNull(oldestPortalEventTimestamp);
final DateTime newestPortalEventTimestamp =
portalEventDao.getNewestPortalEventTimestamp();
assertNull(newestPortalEventTimestamp);
}
});
execute(
new CallableWithoutResult() {
@Override
protected void callWithoutResult() {
portalEventDao.storePortalEvents(originalEvents);
}
});
Collections.sort(
originalEvents,
new Comparator<PortalEvent>() {
@Override
public int compare(PortalEvent o1, PortalEvent o2) {
return o1.getTimestampAsDate().compareTo(o2.getTimestampAsDate());
}
});
execute(
new CallableWithoutResult() {
@Override
protected void callWithoutResult() {
final DateTime oldestPortalEventTimestamp =
portalEventDao.getOldestPortalEventTimestamp();
final DateTime newestPortalEventTimestamp =
portalEventDao.getNewestPortalEventTimestamp();
assertNotNull(oldestPortalEventTimestamp);
assertNotNull(newestPortalEventTimestamp);
assertEquals(
originalEvents.get(0).getTimestampAsDate().getMillis(),
oldestPortalEventTimestamp.getMillis());
assertEquals(
originalEvents
.get(originalEvents.size() - 1)
.getTimestampAsDate()
.getMillis(),
newestPortalEventTimestamp.getMillis());
}
});
verifyGetEvents(originalEvents, startDate, endDate);
verifyAggregateEvents(originalEvents, startDate, endDate);
verifyAggregateEvents(Collections.<PortalEvent>emptyList(), startDate, endDate);
deleteEvents(originalEvents, startDate, endDate);
verifyGetEvents(Collections.<PortalEvent>emptyList(), startDate, endDate);
verifyAggregateEvents(Collections.<PortalEvent>emptyList(), startDate, endDate);
}
protected void verifyGetEvents(
final List<PortalEvent> originalEvents,
final DateTime startDate,
final DateTime endDate) {
execute(
new CallableWithoutResult() {
@Override
protected void callWithoutResult() {
//Get all events
final List<PortalEvent> portalEvents = new LinkedList<PortalEvent>();
portalEventDao.getPortalEvents(
startDate,
endDate,
new FunctionWithoutResult<PortalEvent>() {
@Override
protected void applyWithoutResult(PortalEvent input) {
portalEvents.add(input);
}
});
assertEquals(originalEvents.size(), portalEvents.size());
final Iterator<PortalEvent> originalEventItr = originalEvents.iterator();
final Iterator<PortalEvent> eventItr = portalEvents.iterator();
while (originalEventItr.hasNext()) {
assertEquals(
originalEventItr.next().getClass(), eventItr.next().getClass());
}
}
});
}
protected void verifyAggregateEvents(
final List<PortalEvent> originalEvents,
final DateTime startDate,
final DateTime endDate) {
execute(
new CallableWithoutResult() {
@Override
protected void callWithoutResult() {
//Get all events
final List<PortalEvent> portalEvents = new LinkedList<PortalEvent>();
final AtomicReference<DateTime> nextStart =
new AtomicReference<DateTime>(startDate);
//aggregate all events, 5 at a time.
final int loadSize = 10;
int startSize;
do {
startSize = portalEvents.size();
portalEventDao.aggregatePortalEvents(
nextStart.get(),
endDate,
loadSize,
new Function<PortalEvent, Boolean>() {
@Override
public Boolean apply(PortalEvent input) {
portalEvents.add(input);
nextStart.set(input.getTimestampAsDate());
return Boolean.TRUE;
}
});
} while (loadSize + startSize == portalEvents.size());
assertEquals(originalEvents.size(), portalEvents.size());
final Iterator<PortalEvent> originalEventItr = originalEvents.iterator();
final Iterator<PortalEvent> eventItr = portalEvents.iterator();
while (originalEventItr.hasNext()) {
assertEquals(
originalEventItr.next().getClass(), eventItr.next().getClass());
}
}
});
}
protected void deleteEvents(
final List<PortalEvent> originalEvents,
final DateTime startDate,
final DateTime endDate) {
execute(
new CallableWithoutResult() {
@Override
protected void callWithoutResult() {
//Delete the events
portalEventDao.deletePortalEventsBefore(endDate);
}
});
}
private static final long EVENT_DELAY = 100;
protected List<PortalEvent> generateEvents() throws Exception {
final String sessionId = "1234567890123_system_AAAAAAAAAAA";
final PortalEvent.PortalEventBuilder eventBuilder =
new PortalEvent.PortalEventBuilder(
this, "example.com", sessionId, SystemPerson.INSTANCE, null);
final Set<String> groups = ImmutableSet.of("Student", "Employee");
final Map<String, List<String>> attributes =
ImmutableMap.of(
"username",
(List<String>) ImmutableList.of("system"),
"roles",
(List<String>) ImmutableList.of("student", "employee"));
final List<PortalEvent> events = new LinkedList<PortalEvent>();
events.add(new LoginEvent(eventBuilder, groups, attributes));
Thread.sleep(EVENT_DELAY);
events.add(
new FolderAddedToLayoutPortalEvent(eventBuilder, SystemPerson.INSTANCE, 1, "n32"));
Thread.sleep(EVENT_DELAY);
events.add(
new FolderMovedInLayoutPortalEvent(
eventBuilder, SystemPerson.INSTANCE, 1, "n12", "n32"));
Thread.sleep(EVENT_DELAY);
events.add(
new FolderDeletedFromLayoutPortalEvent(
eventBuilder, SystemPerson.INSTANCE, 1, "n24", "n32", "My Tab"));
Thread.sleep(EVENT_DELAY);
events.add(
new PortletAddedToLayoutPortalEvent(
eventBuilder, SystemPerson.INSTANCE, 1, "n32", "portletA"));
Thread.sleep(EVENT_DELAY);
events.add(
new PortletMovedInLayoutPortalEvent(
eventBuilder, SystemPerson.INSTANCE, 1, "n32", "n24", "portletA"));
Thread.sleep(EVENT_DELAY);
events.add(
new PortletDeletedFromLayoutPortalEvent(
eventBuilder, SystemPerson.INSTANCE, 1, "n24", "portletA"));
final PortletExecutionEvent.PortletExecutionEventBuilder portletExecutionEventBuilder =
new PortletExecutionEvent.PortletExecutionEventBuilder(
eventBuilder,
new MockPortletWindowId("pw1"),
"fname",
12345,
Collections.EMPTY_MAP,
WindowState.NORMAL,
PortletMode.VIEW);
Thread.sleep(EVENT_DELAY);
events.add(new PortletActionExecutionEvent(portletExecutionEventBuilder));
Thread.sleep(EVENT_DELAY);
events.add(
new PortletEventExecutionEvent(
portletExecutionEventBuilder,
new QName("http://www.jasig.org/foo", "event", "e")));
Thread.sleep(EVENT_DELAY);
events.add(new PortletRenderExecutionEvent(portletExecutionEventBuilder, true, false));
Thread.sleep(EVENT_DELAY);
events.add(
new PortletResourceExecutionEvent(
portletExecutionEventBuilder, "someImage.jpg", false, false));
Thread.sleep(EVENT_DELAY);
events.add(new LogoutEvent(eventBuilder));
return events;
}
}