org.apache.james.utils.InMemoryMailRepositoryStore.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.james.utils.InMemoryMailRepositoryStore.java

Source

/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you under the Apache License, Version 2.0 (the            *
 * "License"); you may not use this file except in compliance   *
 * with the License.  You may obtain a copy of the License at   *
 *                                                              *
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
 *                                                              *
 * Unless required by applicable law or agreed to in writing,   *
 * software distributed under the License is distributed on an  *
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
 * KIND, either express or implied.  See the License for the    *
 * specific language governing permissions and limitations      *
 * under the License.                                           *
 ****************************************************************/

package org.apache.james.utils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

import org.apache.commons.configuration.CombinedConfiguration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.DefaultConfigurationBuilder;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.james.lifecycle.api.Configurable;
import org.apache.james.lifecycle.api.LogEnabled;
import org.apache.james.mailrepository.api.MailRepository;
import org.apache.james.mailrepository.api.MailRepositoryStore;
import org.apache.james.repository.api.Initializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;

public class InMemoryMailRepositoryStore implements MailRepositoryStore, Configurable {

    private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryMailRepositoryStore.class);

    private final Set<MailRepositoryProvider> mailRepositories;
    private final ConcurrentMap<String, MailRepository> destinationToRepositoryAssociations;
    private final Map<String, MailRepositoryProvider> protocolToRepositoryProvider;
    private final Map<String, HierarchicalConfiguration> perProtocolMailRepositoryDefaultConfiguration;
    private HierarchicalConfiguration configuration;

    @Inject
    public InMemoryMailRepositoryStore(Set<MailRepositoryProvider> mailRepositories) {
        this.mailRepositories = mailRepositories;
        this.destinationToRepositoryAssociations = new ConcurrentHashMap<>();
        this.protocolToRepositoryProvider = new HashMap<>();
        this.perProtocolMailRepositoryDefaultConfiguration = new HashMap<>();
    }

    @Override
    public List<String> getUrls() {
        return destinationToRepositoryAssociations.keySet().stream().collect(Collectors.toList());
    }

    @Override
    public void configure(HierarchicalConfiguration configuration) throws ConfigurationException {
        this.configuration = configuration;
    }

    public void init() throws Exception {
        LOGGER.info("JamesMailStore init... " + this);
        List<HierarchicalConfiguration> registeredClasses = configuration
                .configurationsAt("mailrepositories.mailrepository");
        for (HierarchicalConfiguration registeredClass : registeredClasses) {
            readConfigurationEntry(registeredClass);
        }
    }

    @Override
    public MailRepository select(String destination) throws MailRepositoryStoreException {
        MailRepository mailRepository = destinationToRepositoryAssociations.get(destination);
        if (mailRepository != null) {
            return mailRepository;
        }
        String protocol = retrieveProtocol(destination);
        mailRepository = retrieveMailRepository(protocol);
        mailRepository = initialiseNewRepository(mailRepository,
                createRepositoryCombinedConfig(destination, protocol));
        destinationToRepositoryAssociations.putIfAbsent(destination, mailRepository);
        return mailRepository;
    }

    private void readConfigurationEntry(HierarchicalConfiguration repositoryConfiguration)
            throws ConfigurationException {
        String className = repositoryConfiguration.getString("[@class]");
        MailRepositoryProvider usedMailRepository = mailRepositories.stream()
                .filter(mailRepositoryProvider -> mailRepositoryProvider.canonicalName().equals(className))
                .findAny().orElseThrow(() -> new ConfigurationException(
                        "MailRepository " + className + " has not been registered"));
        for (String protocol : repositoryConfiguration.getStringArray("protocols.protocol")) {
            protocolToRepositoryProvider.put(protocol, usedMailRepository);
            registerRepositoryDefaultConfiguration(repositoryConfiguration, protocol);
        }
    }

    private void registerRepositoryDefaultConfiguration(HierarchicalConfiguration repositoryConfiguration,
            String protocol) {
        HierarchicalConfiguration defConf = null;
        if (repositoryConfiguration.getKeys("config").hasNext()) {
            defConf = repositoryConfiguration.configurationAt("config");
        }
        if (defConf != null) {
            perProtocolMailRepositoryDefaultConfiguration.put(protocol, defConf);
        }
    }

    private CombinedConfiguration createRepositoryCombinedConfig(String destination, String protocol) {
        final CombinedConfiguration config = new CombinedConfiguration();
        HierarchicalConfiguration defaultProtocolConfig = perProtocolMailRepositoryDefaultConfiguration
                .get(protocol);
        if (defaultProtocolConfig != null) {
            config.addConfiguration(defaultProtocolConfig);
        }
        DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
        builder.addProperty("[@destinationURL]", destination);
        config.addConfiguration(builder);
        return config;
    }

    private MailRepository initialiseNewRepository(MailRepository mailRepository, CombinedConfiguration config)
            throws MailRepositoryStoreException {
        try {
            if (mailRepository instanceof LogEnabled) {
                ((LogEnabled) mailRepository).setLog(LOGGER);
            }
            if (mailRepository instanceof Configurable) {
                ((Configurable) mailRepository).configure(config);
            }
            if (mailRepository instanceof Initializable) {
                ((Initializable) mailRepository).init();
            }
            return mailRepository;
        } catch (Exception e) {
            throw new MailRepositoryStoreException("Cannot init mail repository", e);
        }
    }

    private MailRepository retrieveMailRepository(String protocol) throws MailRepositoryStoreException {
        MailRepositoryProvider repositoryProvider = protocolToRepositoryProvider.get(protocol);
        if (repositoryProvider == null) {
            throw new MailRepositoryStoreException("No Mail Repository associated with " + protocol);
        }
        return repositoryProvider.get();
    }

    private String retrieveProtocol(String destination) throws MailRepositoryStoreException {
        int protocolSeparatorPosition = destination.indexOf(':');
        if (protocolSeparatorPosition == -1) {
            throw new MailRepositoryStoreException("Destination is malformed. Must be a valid URL: " + destination);
        }
        return destination.substring(0, protocolSeparatorPosition);
    }

}