001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020 package org.apache.james.fetchmail;
021
022 import java.util.ArrayList;
023 import java.util.Iterator;
024 import java.util.List;
025 import java.util.concurrent.ScheduledExecutorService;
026 import java.util.concurrent.ScheduledFuture;
027 import java.util.concurrent.TimeUnit;
028
029 import javax.annotation.PostConstruct;
030 import javax.annotation.PreDestroy;
031 import javax.annotation.Resource;
032
033 import org.apache.commons.configuration.ConfigurationException;
034 import org.apache.commons.configuration.HierarchicalConfiguration;
035 import org.apache.james.dnsservice.api.DNSService;
036 import org.apache.james.domainlist.api.DomainList;
037 import org.apache.james.lifecycle.api.Configurable;
038 import org.apache.james.lifecycle.api.LogEnabled;
039 import org.apache.james.queue.api.MailQueue;
040 import org.apache.james.queue.api.MailQueueFactory;
041 import org.apache.james.user.api.UsersRepository;
042 import org.apache.james.util.concurrent.JMXEnabledScheduledThreadPoolExecutor;
043 import org.slf4j.Logger;
044
045 /**
046 * A class to instantiate and schedule a set of mail fetching tasks
047 */
048 public class FetchScheduler implements FetchSchedulerMBean, LogEnabled, Configurable {
049
050 /**
051 * Configuration object for this service
052 */
053 private HierarchicalConfiguration conf;
054
055 /**
056 * The scheduler service that is used to trigger fetch tasks.
057 */
058 private ScheduledExecutorService scheduler;
059
060 /**
061 * Whether this service is enabled.
062 */
063 private volatile boolean enabled = false;
064
065 private List<ScheduledFuture<?>> schedulers = new ArrayList<ScheduledFuture<?>>();
066
067 private DNSService dns;
068
069 private UsersRepository urepos;
070
071 private Logger logger;
072
073 private MailQueue queue;
074 private MailQueueFactory queueFactory;
075
076 private DomainList domainList;
077
078 @Resource(name = "mailqueuefactory")
079 public void setMailQueueFactory(MailQueueFactory queueFactory) {
080 this.queueFactory = queueFactory;
081 }
082
083 @Resource(name = "dnsservice")
084 public void setDNSService(DNSService dns) {
085 this.dns = dns;
086 }
087
088 @Resource(name = "usersrepository")
089 public void setUsersRepository(UsersRepository urepos) {
090 this.urepos = urepos;
091 }
092
093 @Resource(name = "domainlist")
094 public void setDomainList(DomainList domainList) {
095 this.domainList = domainList;
096 }
097
098 /**
099 * @see org.apache.james.lifecycle.api.LogEnabled#setLog(org.slf4j.Logger)
100 */
101 public final void setLog(Logger logger) {
102 this.logger = logger;
103 }
104
105 /**
106 * @see
107 * org.apache.james.lifecycle.api.Configurable#configure(org.apache.commons.configuration.HierarchicalConfiguration)
108 */
109 public final void configure(HierarchicalConfiguration config) throws ConfigurationException {
110 this.conf = config;
111 }
112
113 @SuppressWarnings("unchecked")
114 @PostConstruct
115 public void init() throws Exception {
116 enabled = conf.getBoolean("[@enabled]", false);
117 if (enabled) {
118 int numThreads = conf.getInt("threads", 5);
119 String jmxName = conf.getString("jmxName", "fetchmail");
120 String jmxPath = "org.apache.james:type=component,name=" + jmxName + ",sub-type=threadpool";
121
122 scheduler = new JMXEnabledScheduledThreadPoolExecutor(numThreads, jmxPath, "scheduler");
123 queue = queueFactory.getQueue(MailQueueFactory.SPOOL);
124
125 List<HierarchicalConfiguration> fetchConfs = conf.configurationsAt("fetch");
126 for (int i = 0; i < fetchConfs.size(); i++) {
127 // read configuration
128 HierarchicalConfiguration fetchConf = fetchConfs.get(i);
129 Long interval = fetchConf.getLong("interval");
130
131 FetchMail fetcher = new FetchMail();
132
133 fetcher.setLog(logger);
134 fetcher.setDNSService(dns);
135 fetcher.setUsersRepository(urepos);
136 fetcher.setMailQueue(queue);
137 fetcher.setDomainList(domainList);
138
139 fetcher.configure(fetchConf);
140
141 // initialize scheduling
142 schedulers.add(scheduler.scheduleWithFixedDelay(fetcher, 0, interval, TimeUnit.MILLISECONDS));
143 }
144
145 if (logger.isInfoEnabled())
146 logger.info("FetchMail Started");
147 } else {
148 if (logger.isInfoEnabled())
149 logger.info("FetchMail Disabled");
150 }
151 }
152
153 @PreDestroy
154 public void dispose() {
155 if (enabled) {
156 logger.info("FetchMail dispose...");
157 Iterator<ScheduledFuture<?>> schedulersIt = schedulers.iterator();
158 while (schedulersIt.hasNext()) {
159 schedulersIt.next().cancel(false);
160 }
161 logger.info("FetchMail ...dispose end");
162 }
163 }
164
165 /**
166 * Describes whether this service is enabled by configuration.
167 *
168 * @return is the service enabled.
169 */
170 public final boolean isEnabled() {
171 return enabled;
172 }
173
174 }