com.mirth.connect.plugins.messagepruner.MessagePrunerService.java Source code

Java tutorial

Introduction

Here is the source code for com.mirth.connect.plugins.messagepruner.MessagePrunerService.java

Source

/*
 * Copyright (c) Mirth Corporation. All rights reserved.
 * http://www.mirthcorp.com
 *
 * The software in this package is published under the terms of the MPL
 * license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 */

package com.mirth.connect.plugins.messagepruner;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.swing.text.DateFormatter;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;

import com.mirth.connect.client.core.Operations;
import com.mirth.connect.client.core.TaskConstants;
import com.mirth.connect.model.Channel;
import com.mirth.connect.model.Event;
import com.mirth.connect.model.Event.Level;
import com.mirth.connect.model.Event.Outcome;
import com.mirth.connect.model.ExtensionPermission;
import com.mirth.connect.model.filters.MessageObjectFilter;
import com.mirth.connect.plugins.ServicePlugin;
import com.mirth.connect.server.controllers.ChannelController;
import com.mirth.connect.server.controllers.ControllerFactory;
import com.mirth.connect.server.controllers.EventController;
import com.mirth.connect.util.PropertyLoader;

public class MessagePrunerService implements ServicePlugin, Job {
    private Logger logger = Logger.getLogger(this.getClass());
    private ChannelController channelController = ControllerFactory.getFactory().createChannelController();
    private EventController eventController = ControllerFactory.getFactory().createEventController();
    private Scheduler sched = null;
    private SchedulerFactory schedFact = null;
    private JobDetail jobDetail = null;
    private static final int DEFAULT_PRUNING_BLOCK_SIZE = 0;
    private static boolean allowBatchPruning;
    private static int pruningBlockSize;

    public static final String PLUGINPOINT = "Message Pruner";

    @Override
    public String getPluginPointName() {
        return PLUGINPOINT;
    }

    public void init(Properties properties) {
        jobDetail = new JobDetail("prunerJob", Scheduler.DEFAULT_GROUP, MessagePrunerService.class);

        try {
            if (properties.getProperty("allowBatchPruning") != null
                    && properties.getProperty("allowBatchPruning").equals("1")) {
                allowBatchPruning = true;
            } else {
                allowBatchPruning = false;
            }

            if (StringUtils.isNotEmpty(properties.getProperty("pruningBlockSize"))) {
                pruningBlockSize = Integer.parseInt(properties.getProperty("pruningBlockSize"));
            } else {
                pruningBlockSize = DEFAULT_PRUNING_BLOCK_SIZE;
            }

            schedFact = new StdSchedulerFactory();
            sched = schedFact.getScheduler();
            sched.scheduleJob(jobDetail, createTrigger(properties));
        } catch (Exception e) {
            logger.error("error encountered in database pruner initialization", e);
        }
    }

    private Trigger createTrigger(Properties properties) throws ParseException {
        Trigger trigger = null;
        String interval = PropertyLoader.getProperty(properties, "interval");

        if (interval.equals("hourly"))
            trigger = TriggerUtils.makeHourlyTrigger();
        else {
            SimpleDateFormat timeDateFormat = new SimpleDateFormat("hh:mm aa");
            DateFormatter timeFormatter = new DateFormatter(timeDateFormat);

            String time = PropertyLoader.getProperty(properties, "time");
            Date timeDate = (Date) timeFormatter.stringToValue(time);
            Calendar timeCalendar = Calendar.getInstance();
            timeCalendar.setTime(timeDate);

            if (interval.equals("daily")) {
                trigger = TriggerUtils.makeDailyTrigger(timeCalendar.get(Calendar.HOUR_OF_DAY),
                        timeCalendar.get(Calendar.MINUTE));
            } else if (interval.equals("weekly")) {
                SimpleDateFormat dayDateFormat = new SimpleDateFormat("EEEEEEEE");
                DateFormatter dayFormatter = new DateFormatter(dayDateFormat);

                String dayOfWeek = PropertyLoader.getProperty(properties, "dayOfWeek");
                Date dayDate = (Date) dayFormatter.stringToValue(dayOfWeek);
                Calendar dayCalendar = Calendar.getInstance();
                dayCalendar.setTime(dayDate);

                trigger = TriggerUtils.makeWeeklyTrigger(dayCalendar.get(Calendar.DAY_OF_WEEK),
                        timeCalendar.get(Calendar.HOUR_OF_DAY), timeCalendar.get(Calendar.MINUTE));
            } else if (interval.equals("monthly")) {
                SimpleDateFormat dayDateFormat = new SimpleDateFormat("DD");
                DateFormatter dayFormatter = new DateFormatter(dayDateFormat);

                String dayOfMonth = PropertyLoader.getProperty(properties, "dayOfMonth");
                Date dayDate = (Date) dayFormatter.stringToValue(dayOfMonth);
                Calendar dayCalendar = Calendar.getInstance();
                dayCalendar.setTime(dayDate);

                trigger = TriggerUtils.makeMonthlyTrigger(dayCalendar.get(Calendar.DAY_OF_MONTH),
                        timeCalendar.get(Calendar.HOUR_OF_DAY), timeCalendar.get(Calendar.MINUTE));
            }
        }

        trigger.setStartTime(new Date());
        trigger.setName("prunerTrigger");
        trigger.setJobName("prunerJob");
        return trigger;
    }

    @Override
    public void start() {
        try {
            sched.start();
        } catch (Exception e) {
            logger.error("could not start message pruner", e);
        }
    }

    @Override
    public void update(Properties properties) {
        try {
            if (properties.getProperty("allowBatchPruning") != null
                    && properties.getProperty("allowBatchPruning").equals("1")) {
                allowBatchPruning = true;
            } else {
                allowBatchPruning = false;
            }

            if (StringUtils.isNotEmpty(properties.getProperty("pruningBlockSize"))) {
                pruningBlockSize = Integer.parseInt(properties.getProperty("pruningBlockSize"));
            } else {
                pruningBlockSize = DEFAULT_PRUNING_BLOCK_SIZE;
            }

            sched.deleteJob("prunerJob", Scheduler.DEFAULT_GROUP);
            sched.scheduleJob(jobDetail, createTrigger(properties));

            // for some reason, this does not work
            // sched.rescheduleJob("prunerJob", Scheduler.DEFAULT_GROUP,
            // createTrigger(properties));
        } catch (Exception e) {
            logger.error("could not reschedule the message pruner", e);
        }
    }

    @Override
    public void stop() {
        try {
            sched.shutdown();
        } catch (Exception e) {
            logger.error("could not exit message pruner", e);
        }
    }

    @Override
    public Object invoke(String method, Object object, String sessionId) {
        return null;
    }

    @Override
    public Properties getDefaultProperties() {
        Properties properties = new Properties();
        properties.put("interval", "daily");
        properties.put("time", "12:00 AM");
        properties.put("allowBatchPruning", "1");
        properties.put("pruningBlockSize", String.valueOf(DEFAULT_PRUNING_BLOCK_SIZE));
        return properties;
    }

    private Map<String, List<Channel>> getBatchedChannelMap() throws Exception {
        Map<String, List<Channel>> batchedChannelMap = new HashMap<String, List<Channel>>();

        for (Channel channel : channelController.getChannel(null)) {
            if ((channel.getProperties().getProperty("store_messages") != null)
                    && channel.getProperties().getProperty("store_messages").equals("true")) {
                if ((channel.getProperties().getProperty("max_message_age") != null)
                        && !channel.getProperties().getProperty("max_message_age").equals("-1")) {
                    String numDays = channel.getProperties().getProperty("max_message_age");
                    if (batchedChannelMap.get(numDays) == null) {
                        batchedChannelMap.put(numDays, new ArrayList<Channel>());
                    }

                    batchedChannelMap.get(numDays).add(channel);
                }
            }
        }

        return batchedChannelMap;
    }

    // just get a map with one key and the list of all the channels
    private Map<String, List<Channel>> getChannelMap() throws Exception {
        Map<String, List<Channel>> channelMap = new HashMap<String, List<Channel>>();

        for (Channel channel : channelController.getChannel(null)) {
            if ((channel.getProperties().getProperty("store_messages") != null)
                    && channel.getProperties().getProperty("store_messages").equals("true")) {
                if ((channel.getProperties().getProperty("max_message_age") != null)
                        && !channel.getProperties().getProperty("max_message_age").equals("-1")) {
                    String key = channel.getId();
                    if (channelMap.get(key) == null) {
                        channelMap.put(key, new ArrayList<Channel>());
                    }

                    channelMap.get(key).add(channel);
                }
            }
        }

        return channelMap;
    }

    public void execute(JobExecutionContext context) throws JobExecutionException {
        logger.debug("pruning message database");

        try {
            Map<String, List<Channel>> channelMap;

            if (allowBatchPruning) {
                channelMap = getBatchedChannelMap();
            } else {
                channelMap = getChannelMap();
            }

            for (List<Channel> channels : channelMap.values()) {
                // just check the first one
                int numDays = Integer.parseInt(channels.get(0).getProperties().getProperty("max_message_age"));
                String channelName;

                Calendar endDate = Calendar.getInstance();
                endDate.set(Calendar.DATE, endDate.get(Calendar.DATE) - numDays);

                MessageObjectFilter filter = new MessageObjectFilter();

                if (allowBatchPruning) {
                    List<String> channelIdList = new ArrayList<String>();
                    for (Channel channel : channels) {
                        channelIdList.add(channel.getId());
                    }
                    filter.setChannelIdList(channelIdList);
                    channelName = "Batch pruning: messages older than " + numDays + " days.";
                } else {
                    filter.setChannelId(channels.get(0).getId());
                    channelName = channels.get(0).getName();
                }

                filter.setEndDate(endDate);
                filter.setIgnoreQueued(true);

                int numMessagesPruned = ControllerFactory.getFactory().createMessageObjectController()
                        .pruneMessages(filter, pruningBlockSize);

                Event event = new Event();
                event.setLevel(Level.INFORMATION);
                event.setOutcome(Outcome.SUCCESS);
                event.setName(PLUGINPOINT);

                Map<String, String> attributes = new HashMap<String, String>();
                attributes.put("channel", channelName);
                attributes.put("messages pruned", Integer.toString(numMessagesPruned));
                event.setAttributes(attributes);
                eventController.addEvent(event);
            }
        } catch (Exception e) {
            logger.warn("could not prune message database", e);
        }
    }

    @Override
    public ExtensionPermission[] getExtensionPermissions() {
        ExtensionPermission viewPermission = new ExtensionPermission(PLUGINPOINT, "View Settings",
                "Displays the Message Pruner settings.",
                new String[] { Operations.PLUGIN_PROPERTIES_GET.getName() },
                new String[] { TaskConstants.SETTINGS_REFRESH });
        ExtensionPermission savePermission = new ExtensionPermission(PLUGINPOINT, "Save Settings",
                "Allows changing the Message Pruner settings.",
                new String[] { Operations.PLUGIN_PROPERTIES_SET.getName() },
                new String[] { TaskConstants.SETTINGS_SAVE });

        return new ExtensionPermission[] { viewPermission, savePermission };
    }
}