PageRenderTime 27ms CodeModel.GetById 14ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/opennms-ackd/src/main/java/org/opennms/netmgt/ackd/readers/DefaultAckReader.java

https://github.com/ajakubo1/opennms
Java | 319 lines | 164 code | 40 blank | 115 comment | 20 complexity | 1cf082c1b99ab7b634e15e8121824455 MD5 | raw file
  1/*******************************************************************************
  2 * This file is part of OpenNMS(R).
  3 *
  4 * Copyright (C) 2010-2012 The OpenNMS Group, Inc.
  5 * OpenNMS(R) is Copyright (C) 1999-2012 The OpenNMS Group, Inc.
  6 *
  7 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
  8 *
  9 * OpenNMS(R) is free software: you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License as published
 11 * by the Free Software Foundation, either version 3 of the License,
 12 * or (at your option) any later version.
 13 *
 14 * OpenNMS(R) is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17 * GNU General Public License for more details.
 18 *
 19 * You should have received a copy of the GNU General Public License
 20 * along with OpenNMS(R).  If not, see:
 21 *      http://www.gnu.org/licenses/
 22 *
 23 * For more information contact:
 24 *     OpenNMS(R) Licensing <license@opennms.org>
 25 *     http://www.opennms.org/
 26 *     http://www.opennms.com/
 27 *******************************************************************************/
 28
 29package org.opennms.netmgt.ackd.readers;
 30
 31import java.util.concurrent.Future;
 32import java.util.concurrent.ScheduledThreadPoolExecutor;
 33
 34import org.opennms.core.spring.BeanUtils;
 35import org.opennms.netmgt.ackd.AckReader;
 36import org.opennms.netmgt.dao.api.AckdConfigurationDao;
 37import org.slf4j.Logger;
 38import org.slf4j.LoggerFactory;
 39import org.springframework.beans.factory.InitializingBean;
 40import org.springframework.beans.factory.annotation.Autowired;
 41import org.springframework.util.Assert;
 42
 43
 44/**
 45 * Acknowledgment Reader implementation using Java Mail
 46 *
 47 * DONE: Identify acknowledgments for sent notifications
 48 * DONE: Identify acknowledgments for alarm IDs (how the send knows the ID, good question)
 49 * DONE: Persist acknowledgments
 50 * DONE: Identify escalation reply
 51 * DONE: Identify clear reply
 52 * DOND: Identify unacknowledged reply
 53 * DONE: Formalize Acknowledgment parameters (ack-type, id)
 54 * DONE: JavaMail configuration factory
 55 * DONE: Ackd configuration factory
 56 * TODO: Associate email replies with openNMS user
 57 * DONE: Finish scheduling component of JavaAckReader
 58 * DONE: Configurable Schedule
 59 * DONE: Identify Java Mail configuration element to use for reading replies
 60 * TODO: Migrate JavaMailNotificationStrategy to new JavaMail Configuration and JavaSendMailer
 61 * TODO: Migrate Availability Reports send via JavaMail to new JavaMail Configuration and JavaSendMailer
 62 * TODO: Move reading email messages from MTM to JavaReadMailer class
 63 * DONE: Need an event to cause re-loading of schedules based on changes to ackd-configuration
 64 * DONE: Do some proper logging
 65 * DONE: Handle "enabled" flag of the readers in ackd-configuration
 66 * DONE: Move executor to Ackd daemon
 67 *
 68 * @author <a href=mailto:david@opennms.org>David Hustace</a>
 69 * @version $Id: $
 70 */
 71public class DefaultAckReader implements AckReader, InitializingBean {
 72    private static final Logger LOG = LoggerFactory.getLogger(DefaultAckReader.class);
 73    private volatile String m_name;
 74
 75    private volatile Future<?> m_future;
 76    private AckProcessor m_ackProcessor;
 77    private ReaderSchedule m_schedule;
 78
 79    private volatile AckReaderState m_state = AckReaderState.STOPPED;
 80
 81    @Autowired
 82    private volatile AckdConfigurationDao m_ackdConfigDao;
 83
 84    /**
 85     * <p>afterPropertiesSet</p>
 86     *
 87     * @throws java.lang.Exception if any.
 88     */
 89    @Override
 90    public void afterPropertiesSet() throws Exception {
 91        BeanUtils.assertAutowiring(this);
 92        boolean state = (m_ackProcessor != null);
 93        Assert.state(state, "Dependency injection failed; one or more fields are null.");
 94    }
 95
 96    private synchronized void start(final ScheduledThreadPoolExecutor executor) {
 97        if (m_schedule == null) {
 98            m_schedule = ReaderSchedule.createSchedule();
 99        }
100        this.start(executor, m_schedule, true);
101    }
102
103    /** {@inheritDoc} */
104    @Override
105    public synchronized void start(final ScheduledThreadPoolExecutor executor, final ReaderSchedule schedule, boolean reloadConfig) throws IllegalStateException {
106        if (reloadConfig) {
107            //FIXME:The reload of JavaMailConfiguration is made here because the DAO is there. Perhaps that should be changed.
108            LOG.info("start: reloading ack processor configuration...");
109            m_ackProcessor.reloadConfigs();
110            LOG.info("start: ack processor configuration reloaded.");
111        }
112
113        if (AckReaderState.STOPPED.equals(getState())) {
114            this.setState(AckReaderState.START_PENDING);
115            this.setSchedule(executor, schedule, false);
116            LOG.info("start: Starting reader...");
117
118            this.scheduleReads(executor);
119
120            this.setState(AckReaderState.STARTED);
121            LOG.info("start: Reader started.");
122        } else {
123            IllegalStateException e = new IllegalStateException("Reader is not in a stopped state.  Reader state is: "+getState());
124            LOG.error("start error", e);
125            throw e;
126        }
127    }
128
129    /**
130     * <p>pause</p>
131     *
132     * @throws java.lang.IllegalStateException if any.
133     */
134    @Override
135    public synchronized void pause() throws IllegalStateException {
136        if (AckReaderState.STARTED.equals(getState()) || AckReaderState.RESUMED.equals(getState())) {
137            LOG.info("pause: lock acquired; pausing reader...");
138            setState(AckReaderState.PAUSE_PENDING);
139
140            if (m_future != null) {
141                m_future.cancel(false);
142                m_future = null;
143            }
144
145            setState(AckReaderState.PAUSED);
146            LOG.info("pause: Reader paused.");
147        } else {
148            IllegalStateException e = new IllegalStateException("Reader is not in a running state (STARTED or RESUMED).  Reader state is: "+getState());
149            LOG.error("pause error", e);
150            throw e;
151        }
152    }
153
154    /** {@inheritDoc} */
155    @Override
156    public synchronized void resume(final ScheduledThreadPoolExecutor executor) throws IllegalStateException {
157        if (AckReaderState.PAUSED.equals(getState())) {
158            setState(AckReaderState.RESUME_PENDING);
159            LOG.info("resume: lock acquired; resuming reader...");
160
161            scheduleReads(executor);
162
163            setState(AckReaderState.RESUMED);
164            LOG.info("resume: reader resumed.");
165        } else {
166            IllegalStateException e = new IllegalStateException("Reader is not in a paused state, cannot resume.  Reader state is: "+getState());
167            LOG.error("resume error", e);
168            throw e;
169        }
170    }
171
172    /**
173     * <p>stop</p>
174     *
175     * @throws java.lang.IllegalStateException if any.
176     */
177    @Override
178    public synchronized void stop() throws IllegalStateException {
179        if (!AckReaderState.STOPPED.equals(getState())) {
180            setState(AckReaderState.STOP_PENDING);
181            LOG.info("stop: lock acquired; stopping reader...");
182
183            if (m_future != null) {
184                m_future.cancel(false);
185                m_future = null;
186            }
187
188            setState(AckReaderState.STOPPED);
189            LOG.info("stop: Reader stopped.");
190        } else {
191            IllegalStateException e = new IllegalStateException("Reader is already stopped.");
192            LOG.error("stop error", e);
193            throw e;
194        }
195    }
196
197    private synchronized void scheduleReads(final ScheduledThreadPoolExecutor executor) {
198        LOG.debug("scheduleReads: acquired lock, creating schedule...");
199
200        executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
201        executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
202        m_future = executor.scheduleWithFixedDelay(this.getAckProcessor(), getSchedule().getInitialDelay(), 
203                getSchedule().getInterval(), getSchedule().getUnit());
204        LOG.debug("scheduleReads: exited lock, schedule updated.");
205        LOG.debug("scheduleReads: schedule is: attempts remaining: {}; initial delay: {}; interval: {}; unit: {}",
206                  getSchedule().getAttemptsRemaining(),
207                  getSchedule().getInitialDelay(),
208                  getSchedule().getInterval(),
209                  getSchedule().getUnit());
210
211        LOG.debug("scheduleReads: executor details: active count: {}; completed task count: {}; task count: {}; queue size: {}", executor.getActiveCount(), executor.getCompletedTaskCount(), executor.getTaskCount(), executor.getQueue().size());
212    }
213
214    /** {@inheritDoc} */
215    @Override
216    public String toString() {
217        return getClass().getCanonicalName();
218    }
219
220    /** {@inheritDoc} */
221    @Override
222    public void setAckProcessor(AckProcessor ackProcessor) {
223        m_ackProcessor = ackProcessor;
224    }
225
226    /**
227     * <p>getAckProcessor</p>
228     *
229     * @return a {@link org.opennms.netmgt.ackd.readers.AckProcessor} object.
230     */
231    @Override
232    public AckProcessor getAckProcessor() {
233        return m_ackProcessor;
234    }
235
236    /**
237     * <p>setAckdConfigDao</p>
238     *
239     * @param ackdConfigDao a {@link org.opennms.netmgt.dao.api.AckdConfigurationDao} object.
240     */
241    public void setAckdConfigDao(AckdConfigurationDao ackdConfigDao) {
242        m_ackdConfigDao = ackdConfigDao;
243    }
244
245    /**
246     * <p>getAckdConfigDao</p>
247     *
248     * @return a {@link org.opennms.netmgt.dao.api.AckdConfigurationDao} object.
249     */
250    public AckdConfigurationDao getAckdConfigDao() {
251        return m_ackdConfigDao;
252    }
253
254    /**
255     * Gets a new schedule and optionally reschedules <code>MailAckProcessor</code>
256     * @param schedule
257     * @param reschedule
258     */
259    private synchronized void setSchedule(final ScheduledThreadPoolExecutor executor, ReaderSchedule schedule, boolean reschedule) {
260        m_schedule = schedule;
261
262        if (reschedule) {
263            stop();
264            start(executor);
265        }
266    }
267
268    private ReaderSchedule getSchedule() {
269        if (m_schedule == null) {
270            m_schedule = ReaderSchedule.createSchedule();
271        }
272        return m_schedule;
273    }
274
275    /**
276     * Anything calling this method should already have the lock.
277     * 
278     * @param state
279     */
280    private synchronized void setState(AckReaderState state) {
281        m_state = state;
282    }
283
284    /**
285     * <p>getState</p>
286     *
287     * @return a AckReaderState object.
288     */
289    @Override
290    public AckReaderState getState() {
291        return m_state;
292    }
293
294    /**
295     * <p>getFuture</p>
296     *
297     * @return a {@link java.util.concurrent.Future} object.
298     */
299    public Future<?> getFuture() {
300        return m_future;
301    }
302
303    /**
304     * <p>getName</p>
305     *
306     * @return a {@link java.lang.String} object.
307     */
308    @Override
309    public String getName() {
310        return m_name;
311    }
312
313    /** {@inheritDoc} */
314    @Override
315    public synchronized void setName(String name) {
316        m_name = name;
317    }
318
319}