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    }