001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.extensions;
028    import org.opends.messages.Message;
029    
030    
031    
032    import java.util.ArrayList;
033    import java.util.List;
034    
035    import org.opends.server.admin.server.ConfigurationChangeListener;
036    import org.opends.server.admin.std.server.AlertHandlerCfg;
037    import org.opends.server.admin.std.server.SMTPAlertHandlerCfg;
038    import org.opends.server.api.AlertGenerator;
039    import org.opends.server.api.AlertHandler;
040    import org.opends.server.core.DirectoryServer;
041    import org.opends.server.config.ConfigException;
042    import org.opends.server.loggers.debug.DebugTracer;
043    import org.opends.server.types.ConfigChangeResult;
044    import org.opends.server.types.DebugLogLevel;
045    import org.opends.server.types.InitializationException;
046    import org.opends.server.types.ResultCode;
047    import org.opends.server.util.EMailMessage;
048    
049    import static org.opends.server.loggers.debug.DebugLogger.*;
050    import org.opends.server.loggers.ErrorLogger;
051    import static org.opends.messages.ExtensionMessages.*;
052    
053    import org.opends.messages.MessageDescriptor;
054    import static org.opends.server.util.StaticUtils.*;
055    
056    
057    
058    /**
059     * This class implements a Directory Server alert handler that may be used to
060     * send administrative alerts via SMTP.
061     */
062    public class SMTPAlertHandler
063           implements AlertHandler<SMTPAlertHandlerCfg>,
064                      ConfigurationChangeListener<SMTPAlertHandlerCfg>
065    {
066      /**
067       * The tracer object for the debug logger.
068       */
069      private static final DebugTracer TRACER = getTracer();
070    
071    
072    
073      // The current configuration for this alert handler.
074      private SMTPAlertHandlerCfg currentConfig;
075    
076    
077    
078      /**
079       * Creates a new instance of this SMTP alert handler.
080       */
081      public SMTPAlertHandler()
082      {
083        super();
084    
085        // All initialization should be done in the initializeAlertHandler method.
086      }
087    
088    
089    
090      /**
091       * {@inheritDoc}
092       */
093      public void initializeAlertHandler(SMTPAlertHandlerCfg configuration)
094           throws ConfigException, InitializationException
095      {
096        // Make sure that the Directory Server is configured with information about
097        // at least one SMTP server.
098        if ((DirectoryServer.getMailServerPropertySets() == null) ||
099            DirectoryServer.getMailServerPropertySets().isEmpty())
100        {
101          Message message = ERR_SMTPALERTHANDLER_NO_SMTP_SERVERS.get();
102          throw new ConfigException(message);
103        }
104    
105        configuration.addSMTPChangeListener(this);
106        currentConfig = configuration;
107      }
108    
109    
110    
111      /**
112       * {@inheritDoc}
113       */
114      public AlertHandlerCfg getAlertHandlerConfiguration()
115      {
116        return currentConfig;
117      }
118    
119    
120    
121      /**
122       * {@inheritDoc}
123       */
124      public boolean isConfigurationAcceptable(AlertHandlerCfg configuration,
125                                               List<Message> unacceptableReasons)
126      {
127        return true;
128      }
129    
130    
131    
132      /**
133       * {@inheritDoc}
134       */
135      public void finalizeAlertHandler()
136      {
137        // No action is required.
138      }
139    
140    
141    
142      /**
143       * {@inheritDoc}
144       */
145      public void sendAlertNotification(AlertGenerator generator, String alertType,
146                                        Message alertMessage)
147      {
148        SMTPAlertHandlerCfg cfg = currentConfig;
149    
150        ArrayList<String> recipients =
151             new ArrayList<String>(cfg.getRecipientAddress());
152    
153        String alertIDStr;
154        String alertMessageStr;
155        if (alertMessage != null) {
156          alertIDStr = String.valueOf(alertMessage.getDescriptor().getId());
157          alertMessageStr = alertMessage.toString();
158        } else {
159          alertIDStr = String.valueOf(MessageDescriptor.NULL_ID);
160          alertMessageStr = "none";
161        }
162        String subject = replaceTokens(cfg.getMessageSubject(), alertType,
163                                       alertIDStr, alertMessageStr);
164    
165        String body = replaceTokens(cfg.getMessageBody(), alertType, alertIDStr,
166                                    alertMessageStr);
167    
168        EMailMessage message = new EMailMessage(cfg.getSenderAddress(), recipients,
169                                                subject);
170    
171        message.setBody(Message.raw(wrapText(body, 75)));
172    
173        try
174        {
175          message.send();
176        }
177        catch (Exception e)
178        {
179          if (debugEnabled())
180          {
181            TRACER.debugCaught(DebugLogLevel.ERROR, e);
182          }
183    
184          Message msg = WARN_SMTPALERTHANDLER_ERROR_SENDING_MESSAGE.get(
185              alertType, alertMessage, stackTraceToSingleLineString(e));
186          ErrorLogger.logError(msg);
187        }
188      }
189    
190    
191    
192      /**
193       * Replaces any occurrences of special tokens in the given string with the
194       * appropriate value.  Tokens supported include:
195       * <UL>
196       *   <LI>%%alert-type%% -- Will be replaced with the alert type string</LI>
197       *   <LI>%%alert-id%% -- Will be replaced with the alert ID value</LI>
198       *   <LI>%%alert-message%% -- Will be replaced with the alert message</LI>
199       *   <LI>\n -- Will be replaced with an end-of-line character.
200       * </UL>
201       *
202       * @param  s             The string to be processed.
203       * @param  alertType     The string to use to replace the "%%alert-type%%"
204       *                       token.
205       * @param  alertID       The string to use to replace the "%%alert-id%%"
206       *                       token.
207       * @param  alertMessage  The string to use to replace the "%%alert-message%%"
208       *                       token.
209       *
210       * @return  A processed version of the provided string.
211       */
212      private String replaceTokens(String s, String alertType, String alertID,
213                                   String alertMessage)
214      {
215        return s.replace("%%alert-type%%", alertType).
216                 replace("%%alert-id%%", alertID).
217                 replace("%%alert-message%%", alertMessage).
218                 replace("\\n", "\r\n");
219      }
220    
221    
222    
223      /**
224       * {@inheritDoc}
225       */
226      public boolean isConfigurationChangeAcceptable(
227                          SMTPAlertHandlerCfg configuration,
228                          List<Message> unacceptableReasons)
229      {
230        return true;
231      }
232    
233    
234    
235      /**
236       * {@inheritDoc}
237       */
238      public ConfigChangeResult applyConfigurationChange(
239                                     SMTPAlertHandlerCfg configuration)
240      {
241        currentConfig = configuration;
242    
243        return new ConfigChangeResult(ResultCode.SUCCESS, false);
244      }
245    }
246