/* * RHQ Management Platform * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * 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 Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.rhq.enterprise.server.plugin.pc.alert; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import org.rhq.core.domain.alert.Alert; import org.rhq.core.domain.alert.notification.SenderResult; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.Property; import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent; import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment; /** * Abstract base class for all Alert senders. In order to implement your * AlertSender, you need to at least overwrite #send(). When the AlertSenderManager * constructs this object, it will inject the preferences for your specific alert sender * type. * For each Alert a new instance of your implementation will be called and destroyed * afterwards. * * @author Heiko W. Rupp * */ public abstract class AlertSender<T extends ServerPluginComponent> { /** Configuration from the global per plugin type preferences */ protected Configuration preferences; /** Configuration from the per alert definition parameters */ protected Configuration alertParameters; /** Configuration from the per alert definition parameters */ protected Configuration extraParameters; /** Global component holding persistent resources */ protected T pluginComponent; /** Environement of the plugin to e.g. get the classloader */ protected ServerPluginEnvironment serverPluginEnvironment; /** * This method is called to actually send an alert notification. * This is where you implement all functionality. * * The return value is a SenderResult object, which encodes a log message, * success or failure and can contain email addresses that got computed by * your AlertSender and which will be sent by the system after *all* senders * have been run. * @param alert the Alert to operate on * @return result of sending - a ResultState and a message for auditing */ public abstract SenderResult send(Alert alert); /** * Allow users to see a preview of the stored configuration data without having to edit it. * A default implementation is already provided which will print the properties in alphabetical * order, one per line, each followed by a string representation of that property's data. */ public String previewConfiguration() { StringBuilder builder = new StringBuilder(); List<Property> properties = new ArrayList<Property>(alertParameters.getProperties()); Collections.sort(properties); // alpha sort by property name boolean first = true; for (Property next : properties) { if (first) { first = false; } else { builder.append(" | "); } builder.append(next.getName()); builder.append(": "); builder.append(printProperty(next)); } return builder.toString(); } /** * Validates the alert and extra parameters. The results should be initialized with the current * parameters of this alert sender and the erroneous properties should have their * {@link Property#getErrorMessage() error messages} set. * <p> * The implementation is free to change (add/update/delete) properties in either of the configurations * (i.e. finalize them). This is to support scenarios where the user inputs values that need to be * further processed in an alert sender specific way before they get stored into the database. * <p> * The default implementation makes no changes to the configurations. * * @param subject the subject requesting the changes in the configuration * @return the validation results */ public AlertSenderValidationResults validateAndFinalizeConfiguration(Subject subject) { return new AlertSenderValidationResults(alertParameters, extraParameters); } private String printProperty(Property property) { if (property instanceof PropertySimple) { return ((PropertySimple) property).getStringValue(); } else if (property instanceof PropertyMap) { Map<String, Property> map = ((PropertyMap) property).getMap(); StringBuilder builder = new StringBuilder(); for (Property next : map.values()) { builder.append(printProperty(next)); } return builder.toString(); } return "no preview available"; } /** * Presumes the data is in the format "|a|b|c|d|e|" * where '|' delimits all elements as well as wraps * the entire expression. */ public static <T> List<T> unfence(String fencedData, Class<T> type) { return unfence(fencedData, type, "\\|"); } @SuppressWarnings("unchecked") public static <T> List<T> unfence(String fencedData, Class<T> type, String delimiter) { String[] elements = fencedData.split(delimiter); List<T> results = new ArrayList<T>(elements.length); if (Integer.class.equals(type)) { for (String next : elements) { if (next.length() != 0) { results.add((T) Integer.valueOf(next)); } } } else if (String.class.equals(type)) { for (String next : elements) { if (next.length() != 0) { results.add((T) next); } } } else { throw new IllegalArgumentException("No support for unfencing data of type " + type); } return results; } /** * Takes the list of elements e1, e2, e3 and fences * them with '|' delimiters such that the result looks * like "|e1|e2|e3|" */ public static String fence(List<?> elements) { if (elements.size() == 0) { return ""; } StringBuilder builder = new StringBuilder(); builder.append('|'); for (Object next : elements) { builder.append(String.valueOf(next)).append('|'); } return builder.toString(); } }