/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2013 ForgeRock AS. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * http://forgerock.org/license/CDDLv1.0.html * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at http://forgerock.org/license/CDDLv1.0.html * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" */ package org.forgerock.openidm.smartevent; import java.util.Arrays; import java.util.Map; import org.forgerock.guava.common.cache.CacheBuilder; import org.forgerock.guava.common.cache.CacheLoader; import org.forgerock.guava.common.cache.LoadingCache; import org.forgerock.openidm.smartevent.core.DisabledPublisher; import org.forgerock.openidm.smartevent.core.DisruptorReferringPublisher; import org.forgerock.openidm.smartevent.core.BlockingPublisher; import org.forgerock.openidm.smartevent.core.PluggablePublisher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** */ /** * Represents the name and additional configuration for an event type * * Allows callers to pre-construct, parse event hierarchies and set additional * configuration by declaring the Names outside of the publishing of the events * * The fluent API allows for easier set-up directly in the declaration example: * <code>public static final Name MY_EVENT = Name.get("internal/myevent").setTags(new String[] {MONITOR, APP_EVENT}).setXyz("dummy")</code> * * */ public class Name { private final static Logger logger = LoggerFactory.getLogger(Name.class); /** * The available publisher types for handling event pub/sub * BLOCKING uses a blocking queue for the events * DISRUPTOR uses a non-blocking library with a ring buffer */ enum PublisherType {BLOCKING, DISRUPTOR}; // Holds the event stringified name to the Name instance mapping static LoadingCache<String, Name> names = CacheBuilder.newBuilder() .maximumSize(Integer.valueOf(System.getProperty("openidm.smartevent.maxevents", "1000"))) .build( new CacheLoader<String, Name>() { @Override public Name load(String key) throws Exception { return new Name(key); } }); /** * Stringified version of the event name */ String stringifiedName; /** * Optional tags to associate with this event name */ String[] tags; /** * Whether event processing should be enabled or not for this event name */ boolean eventsEnabled = true; /** * Whether result details should be kept in the recent history */ boolean resultHistoryEnabled = false; PublisherType publisherType; PluggablePublisher publisherImpl; private Name(String stringifiedName) { this.stringifiedName = stringifiedName; // Default Setting setEventsEnabled(Boolean.valueOf(System.getProperty("openidm.smartevent.enabled", Boolean.FALSE.toString()))); this.publisherType = (PublisherType.valueOf(PublisherType.class, System.getProperty("openidm.smartevent.publishertype", PublisherType.BLOCKING.toString()))); // Name parsing can be added here } /** * Factory method to get the event Name object * * @param stringifiedName * The string representation of the event name * @return the event Name object representing the requested event type */ public final static Name get(String stringifiedName) { return names.getUnchecked(stringifiedName); } /** * Factory method to get the event Name object * * @param stringifiedName * The string representation of the event name * @param tags * optional additional tags to associate with this event type * @return the event Name object representing the requested event type */ public final static Name get(final String stringifiedName, final String[] tags) { return get(stringifiedName).setTags(tags); } /** * Fluent API to set Tags on this event name * * @param tags * the tags to set * @return this Name instance for use as a fluent API */ public Name setTags(final String[] tags) { if (tags != null) { this.tags = Arrays.copyOf(tags, tags.length); } return this; } /** * Fluent API to set events publishing type * * @param enabled * true to enable event publishing for this Name, false to * disable * @return this Name instance for use as a fluent API */ public Name setEventsEnabled(boolean enabled) { eventsEnabled = enabled; if (enabled == true) { publisherImpl = createPublisher(); } else { publisherImpl = DisabledPublisher.getInstance(); } return this; } /** * @return the events publishing state */ public boolean getEventsEnabled() { return eventsEnabled; } /** * Fluent API to set result history behavior * * @param enabled * true to enable keeping results in the recent event history * @return this Name instance for use as a fluent API */ public Name setResultHistoryEnabled(boolean enabled) { resultHistoryEnabled = enabled; return this; } /** * @return whether the result history is enabled */ public boolean getResultHistoryEnabled() { return resultHistoryEnabled; } /** * Get all currently registered event names The returned map should not be * directly modified. * * @return a map pointing from stringified event name representation to the * the event Name object for each event Name */ public final static Map<String, Name> getAllNames() { // TODO: consider making/wrapping as immutable return names.asMap(); } /** * @return the name in String representation */ public final String asString() { return stringifiedName; } /** * Factory method, could eventually be moved out */ private PluggablePublisher createPublisher() { if (PublisherType.DISRUPTOR.equals(publisherType)) { logger.debug("Event type: " + stringifiedName + " publisher: DISRUPTOR "); return DisruptorReferringPublisher.getInstance(); } else { logger.debug("Event type: " + stringifiedName + " publisher: BLOCKING"); return BlockingPublisher.getInstance(); } } }