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
020package org.apache.james.mailrepository.lib;
021
022import java.io.IOException;
023import java.util.Collection;
024
025import javax.mail.MessagingException;
026
027import org.apache.commons.configuration.ConfigurationException;
028import org.apache.commons.configuration.HierarchicalConfiguration;
029import org.apache.james.lifecycle.api.Configurable;
030import org.apache.james.lifecycle.api.LogEnabled;
031import org.apache.james.mailrepository.api.MailRepository;
032import org.apache.james.repository.api.Initializable;
033import org.apache.mailet.Mail;
034import org.slf4j.Logger;
035
036/**
037 * This class represent an AbstractMailRepository. All MailRepositories should
038 * extend this class.
039 */
040public abstract class AbstractMailRepository implements MailRepository, LogEnabled, Configurable, Initializable {
041
042    /**
043     * Whether 'deep debugging' is turned on.
044     */
045    protected static final boolean DEEP_DEBUG = false;
046
047    /**
048     * A lock used to control access to repository elements, locking access
049     * based on the key
050     */
051    private final Lock lock = new Lock();
052
053    private Logger logger;
054
055    public void setLog(Logger logger) {
056        this.logger = logger;
057    }
058
059    protected Logger getLogger() {
060        return logger;
061    }
062
063    public void configure(HierarchicalConfiguration configuration) throws ConfigurationException {
064        doConfigure(configuration);
065    }
066
067    protected void doConfigure(HierarchicalConfiguration config) throws ConfigurationException {
068
069    }
070
071    /**
072     * @see org.apache.james.mailrepository.api.MailRepository#unlock(String)
073     */
074    public boolean unlock(String key) {
075        return lock.unlock(key);
076    }
077
078    /**
079     * @see org.apache.james.mailrepository.api.MailRepository#lock(String)
080     */
081    public boolean lock(String key) {
082        return lock.lock(key);
083    }
084
085    /**
086     * @see org.apache.james.mailrepository.api.MailRepository#store(Mail)
087     */
088    public void store(Mail mc) throws MessagingException {
089        boolean wasLocked = true;
090        String key = mc.getName();
091        try {
092            synchronized (this) {
093                wasLocked = lock.isLocked(key);
094                if (!wasLocked) {
095                    // If it wasn't locked, we want a lock during the store
096                    lock(key);
097                }
098            }
099            internalStore(mc);
100        } catch (MessagingException e) {
101            getLogger().error("Exception caught while storing mail " + key, e);
102            throw e;
103        } catch (Exception e) {
104            getLogger().error("Exception caught while storing mail " + key, e);
105            throw new MessagingException("Exception caught while storing mail " + key, e);
106        } finally {
107            if (!wasLocked) {
108                // If it wasn't locked, we need to unlock now
109                unlock(key);
110                synchronized (this) {
111                    notify();
112                }
113            }
114        }
115    }
116
117    /**
118     * @see #store(Mail)
119     */
120    protected abstract void internalStore(Mail mc) throws MessagingException, IOException;
121
122    /**
123     * @see org.apache.james.mailrepository.api.MailRepository#remove(Mail)
124     */
125    public void remove(Mail mail) throws MessagingException {
126        remove(mail.getName());
127    }
128
129    /**
130     * @see org.apache.james.mailrepository.api.MailRepository#remove(Collection)
131     */
132    public void remove(Collection<Mail> mails) throws MessagingException {
133        for (Mail mail : mails) {
134            remove(mail);
135        }
136    }
137
138    /**
139     * @see org.apache.james.mailrepository.api.MailRepository#remove(String)
140     */
141    public void remove(String key) throws MessagingException {
142        if (lock(key)) {
143            try {
144                internalRemove(key);
145            } finally {
146                unlock(key);
147            }
148        } else {
149            String exceptionBuffer = "Cannot lock " + key + " to remove it";
150            throw new MessagingException(exceptionBuffer.toString());
151        }
152    }
153
154    /**
155     * @see #remove(String)
156     */
157    protected abstract void internalRemove(String key) throws MessagingException;
158
159}