/** * 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.portlet.rendering; import java.util.Collection; import java.util.Iterator; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; import javax.portlet.Event; import org.apereo.portal.portlet.om.IPortletWindowId; import org.apereo.portal.utils.ConcurrentMapUtils; /** * Used to track events generated for a specific portlet window in a thread safe manner. The event * source adds events to the queue for a specific {@link IPortletWindowId} and the event consumer * can iterate over the {@link IPortletWindowId}s that have events and get a {@link Queue} of * un-processed events for each {@link IPortletWindowId} * * <p>This class and all data structures returned by it are thread safe * */ public class PortletEventQueue implements Iterable<IPortletWindowId> { /** Queue of portlet events that have not been resolved to target specific portlet windows */ private final Queue<QueuedEvent> rawEventQueue = new ConcurrentLinkedQueue<QueuedEvent>(); /** * Map for portlet windows where the value is a queue of events that need to be dispatched to * the portlet */ private final ConcurrentMap<IPortletWindowId, Queue<QueuedEvent>> resolvedEventQueues = new ConcurrentHashMap<IPortletWindowId, Queue<QueuedEvent>>(); PortletEventQueue() { //Only allow code in the same package to create the queue } /** Add the collection of events to the raw event queue */ public void addEvents(Collection<? extends QueuedEvent> events) { this.rawEventQueue.addAll(events); } /** @return The Queue of unresolved events */ public Queue<QueuedEvent> getUnresolvedEvents() { return this.rawEventQueue; } /** Queue an {@link Event} for the specified {@link IPortletWindowId} */ public void offerEvent(IPortletWindowId portletWindowId, QueuedEvent event) { Queue<QueuedEvent> events = resolvedEventQueues.get(portletWindowId); if (events == null) { events = ConcurrentMapUtils.putIfAbsent( resolvedEventQueues, portletWindowId, new ConcurrentLinkedQueue<QueuedEvent>()); } events.offer(event); } /** Remove the oldest {@link Event} from the Queue for the specified {@link IPortletWindowId} */ public QueuedEvent pollEvent(IPortletWindowId portletWindowId) { final Queue<QueuedEvent> queue = this.resolvedEventQueues.get(portletWindowId); return queue != null ? queue.poll() : null; } /** Get an {@link Iterator} of all {@link IPortletWindowId}s that have {@link Event}s queued. */ @Override public Iterator<IPortletWindowId> iterator() { return this.resolvedEventQueues.keySet().iterator(); } }