org.apache.james.jmap.JMAPModule.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.james.jmap.JMAPModule.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.jmap;

import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.james.filesystem.api.FileSystem;
import org.apache.james.jmap.mailet.VacationMailet;
import org.apache.james.jmap.methods.RequestHandler;
import org.apache.james.jmap.utils.HtmlTextExtractor;
import org.apache.james.jmap.utils.MailboxBasedHtmlTextExtractor;
import org.apache.james.jmap.utils.SystemMailboxesProvider;
import org.apache.james.jmap.utils.SystemMailboxesProviderImpl;
import org.apache.james.lifecycle.api.Configurable;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxManager.SearchCapabilities;
import org.apache.james.mailetcontainer.impl.MatcherMailetPair;
import org.apache.james.modules.server.CamelMailetContainerModule;
import org.apache.james.transport.mailets.RemoveMimeHeader;
import org.apache.james.transport.matchers.All;
import org.apache.james.transport.matchers.RecipientIsLocal;
import org.apache.james.utils.ConfigurationPerformer;
import org.apache.james.utils.PropertiesProvider;

import com.github.fge.lambdas.Throwing;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.Singleton;
import com.google.inject.multibindings.Multibinder;

public class JMAPModule extends AbstractModule {
    private static final int DEFAULT_JMAP_PORT = 80;

    @Override
    protected void configure() {
        install(new JMAPCommonModule());
        install(new MethodsModule());
        bind(JMAPServer.class).in(Scopes.SINGLETON);
        bind(RequestHandler.class).in(Scopes.SINGLETON);
        bind(UploadHandler.class).in(Scopes.SINGLETON);
        bind(MailboxBasedHtmlTextExtractor.class).in(Scopes.SINGLETON);

        bind(HtmlTextExtractor.class).to(MailboxBasedHtmlTextExtractor.class);
        Multibinder.newSetBinder(binder(), ConfigurationPerformer.class).addBinding()
                .to(RequiredCapabilitiesPrecondition.class);

        Multibinder<CamelMailetContainerModule.TransportProcessorCheck> transportProcessorChecks = Multibinder
                .newSetBinder(binder(), CamelMailetContainerModule.TransportProcessorCheck.class);
        transportProcessorChecks.addBinding().to(VacationMailetCheck.class);
        transportProcessorChecks.addBinding().to(BccMailetCheck.class);

        bind(SystemMailboxesProvider.class).to(SystemMailboxesProviderImpl.class);
    }

    @Provides
    @Singleton
    JMAPConfiguration provideConfiguration(PropertiesProvider propertiesProvider, FileSystem fileSystem)
            throws ConfigurationException, IOException {
        PropertiesConfiguration configuration = propertiesProvider.getConfiguration("jmap");
        return JMAPConfiguration.builder().keystore(configuration.getString("tls.keystoreURL"))
                .secret(configuration.getString("tls.secret"))
                .jwtPublicKeyPem(loadPublicKey(fileSystem,
                        Optional.ofNullable(configuration.getString("jwt.publickeypem.url"))))
                .port(configuration.getInt("jmap.port", DEFAULT_JMAP_PORT)).build();
    }

    private Optional<String> loadPublicKey(FileSystem fileSystem, Optional<String> jwtPublickeyPemUrl) {
        return jwtPublickeyPemUrl
                .map(Throwing.function(url -> FileUtils.readFileToString(fileSystem.getFile(url))));
    }

    @Singleton
    public static class RequiredCapabilitiesPrecondition implements ConfigurationPerformer {

        private final MailboxManager mailboxManager;

        @Inject
        public RequiredCapabilitiesPrecondition(MailboxManager mailboxManager) {
            this.mailboxManager = mailboxManager;
        }

        @Override
        public void initModule() {
            Preconditions.checkArgument(mailboxManager.hasCapability(MailboxManager.MailboxCapabilities.Move),
                    "MOVE support in MailboxManager is required by JMAP Module");
            Preconditions.checkArgument(
                    mailboxManager.getSupportedMessageCapabilities()
                            .contains(MailboxManager.MessageCapabilities.Attachment),
                    "Attachment support in MailboxManager is required by JMAP Module");

            EnumSet<SearchCapabilities> searchCapabilities = mailboxManager.getSupportedSearchCapabilities();
            Preconditions.checkArgument(
                    searchCapabilities.contains(MailboxManager.SearchCapabilities.MultimailboxSearch),
                    "Multimailbox search in MailboxManager is required by JMAP Module");
            Preconditions.checkArgument(searchCapabilities.contains(MailboxManager.SearchCapabilities.Text),
                    "Text support in MailboxManager is required by JMAP Module");
        }

        @Override
        public List<Class<? extends Configurable>> forClasses() {
            return ImmutableList.of();
        }
    }

    public static class VacationMailetCheck implements CamelMailetContainerModule.TransportProcessorCheck {
        @Override
        public void check(List<MatcherMailetPair> pairs) throws ConfigurationException {
            Preconditions.checkNotNull(pairs);
            pairs.stream().filter(pair -> pair.getMailet().getClass().equals(VacationMailet.class))
                    .filter(pair -> pair.getMatcher().getClass().equals(RecipientIsLocal.class)).findAny()
                    .orElseThrow(() -> new ConfigurationException("Missing " + VacationMailet.class.getName()
                            + " in mailets configuration (mailetcontainer -> processors -> transport)"));
        }
    }

    public static class BccMailetCheck implements CamelMailetContainerModule.TransportProcessorCheck {
        @Override
        public void check(List<MatcherMailetPair> pairs) throws ConfigurationException {
            Preconditions.checkNotNull(pairs);
            pairs.stream().filter(pair -> pair.getMailet().getClass().equals(RemoveMimeHeader.class))
                    .filter(pair -> pair.getMatcher().getClass().equals(All.class))
                    .filter(pair -> pair.getMailet().getMailetConfig().getInitParameter("name").equals("bcc"))
                    .findAny().orElseThrow(() -> new ConfigurationException(
                            "Missing RemoveMimeHeader in mailets configuration (mailetcontainer -> processors -> transport). Should be configured to remove Bcc header"));
        }
    }
}