http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceMailetLoader.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceMailetLoader.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceMailetLoader.java new file mode 100644 index 0000000..f979ac2 --- /dev/null +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceMailetLoader.java @@ -0,0 +1,53 @@ +/**************************************************************** + * 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 javax.mail.MessagingException; + +import org.apache.james.mailetcontainer.api.MailetLoader; +import org.apache.mailet.Mailet; +import org.apache.mailet.MailetConfig; + +import com.google.inject.Inject; +import com.google.inject.Injector; + +public class GuiceMailetLoader implements MailetLoader { + + private static final String STANDARD_PACKAGE = "org.apache.james.transport.mailets."; + + private final GuiceGenericLoader<Mailet> genericLoader; + + @Inject + public GuiceMailetLoader(Injector injector) { + this.genericLoader = new GuiceGenericLoader<>(injector, STANDARD_PACKAGE); + } + + @Override + public Mailet getMailet(MailetConfig config) throws MessagingException { + try { + Mailet result = genericLoader.instanciate(config.getMailetName()); + result.init(config); + return result; + } catch (Exception e) { + throw new MessagingException("Can not load mailet " + config.getMailetName(), e); + } + } + +}
http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java new file mode 100644 index 0000000..10e7cd6 --- /dev/null +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceMatcherLoader.java @@ -0,0 +1,53 @@ +/**************************************************************** + * 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 javax.mail.MessagingException; + +import org.apache.james.mailetcontainer.api.MatcherLoader; +import org.apache.mailet.Matcher; +import org.apache.mailet.MatcherConfig; + +import com.google.inject.Inject; +import com.google.inject.Injector; + +public class GuiceMatcherLoader implements MatcherLoader { + + private static final String STANDARD_PACKAGE = "org.apache.james.transport.matchers."; + + private final GuiceGenericLoader<Matcher> genericLoader; + + @Inject + public GuiceMatcherLoader(Injector injector) { + this.genericLoader = new GuiceGenericLoader<>(injector, STANDARD_PACKAGE); + } + + @Override + public Matcher getMatcher(MatcherConfig config) throws MessagingException { + try { + Matcher result = genericLoader.instanciate(config.getMatcherName()); + result.init(config); + return result; + } catch (Exception e) { + throw new MessagingException("Can not load matcher " + config.getMatcherName(), e); + } + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java new file mode 100644 index 0000000..281f341 --- /dev/null +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceProtocolHandlerLoader.java @@ -0,0 +1,61 @@ +/**************************************************************** + * 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 org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.james.protocols.api.handler.ProtocolHandler; +import org.apache.james.protocols.lib.handler.ProtocolHandlerLoader; + +import com.google.common.base.Throwables; +import com.google.inject.Inject; +import com.google.inject.Injector; + +public class GuiceProtocolHandlerLoader implements ProtocolHandlerLoader { + + private final Injector injector; + + @Inject + public GuiceProtocolHandlerLoader(Injector injector) { + this.injector = injector; + } + + @Override + public ProtocolHandler load(String name, Configuration config) throws LoadingException { + ProtocolHandler handler = createProtocolHandler(name); + try { + handler.init(config); + } catch (ConfigurationException e) { + throw Throwables.propagate(e); + } + return handler; + } + + private ProtocolHandler createProtocolHandler(String name) throws LoadingException { + try { + @SuppressWarnings("unchecked") + Class<ProtocolHandler> clazz = (Class<ProtocolHandler>) ClassLoader.getSystemClassLoader().loadClass(name); + return injector.getInstance(clazz); + } catch (ClassNotFoundException e) { + throw new LoadingException("Can not load " + name); + } + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java new file mode 100644 index 0000000..a2d687e --- /dev/null +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/GuiceServerProbe.java @@ -0,0 +1,344 @@ +/**************************************************************** + * 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.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.inject.Inject; +import javax.mail.Flags; + +import org.apache.commons.lang.NotImplementedException; +import org.apache.james.adapter.mailbox.SerializableQuota; +import org.apache.james.domainlist.api.DomainList; +import org.apache.james.mailbox.MailboxManager; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.MessageManager; +import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.model.MailboxConstants; +import org.apache.james.mailbox.model.MailboxMetaData; +import org.apache.james.mailbox.model.MailboxPath; +import org.apache.james.mailbox.model.MailboxQuery; +import org.apache.james.mailbox.store.mail.MailboxMapper; +import org.apache.james.mailbox.store.mail.MailboxMapperFactory; +import org.apache.james.mailbox.store.mail.model.Mailbox; +import org.apache.james.mailbox.store.mail.model.MailboxId; +import org.apache.james.rrt.lib.Mappings; +import org.apache.james.sieverepository.api.SieveRepository; +import org.apache.james.user.api.UsersRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +public class GuiceServerProbe<Id extends MailboxId> implements ExtendedServerProbe<Id> { + + private static final Logger LOGGER = LoggerFactory.getLogger(GuiceServerProbe.class); + + private final MailboxManager mailboxManager; + private final MailboxMapperFactory<Id> mailboxMapperFactory; + private final DomainList domainList; + private final UsersRepository usersRepository; + private final SieveRepository sieveRepository; + + @Inject + private GuiceServerProbe(MailboxManager mailboxManager, MailboxMapperFactory<Id> mailboxMapperFactory, + DomainList domainList, UsersRepository usersRepository, SieveRepository sieveRepository) { + this.mailboxManager = mailboxManager; + this.mailboxMapperFactory = mailboxMapperFactory; + this.domainList = domainList; + this.usersRepository = usersRepository; + this.sieveRepository = sieveRepository; + } + + @Override + public void close() throws IOException { + } + + @Override + public void addUser(String userName, String password) throws Exception { + usersRepository.addUser(userName, password); + } + + @Override + public void removeUser(String username) throws Exception { + usersRepository.removeUser(username); + } + + @Override + public String[] listUsers() throws Exception { + return Iterables.toArray(ImmutableList.copyOf(usersRepository.list()), String.class); + } + + @Override + public void setPassword(String userName, String password) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void addDomain(String domain) throws Exception { + domainList.addDomain(domain); + } + + @Override + public boolean containsDomain(String domain) throws Exception { + return domainList.containsDomain(domain); + } + + @Override + public void removeDomain(String domain) throws Exception { + domainList.removeDomain(domain); + } + + @Override + public String[] listDomains() throws Exception { + return domainList.getDomains(); + } + + @Override + public Map<String, Mappings> listMappings() throws Exception { + throw new NotImplementedException(); + } + + @Override + public void addAddressMapping(String user, String domain, String toAddress) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void removeAddressMapping(String user, String domain, String fromAddress) throws Exception { + throw new NotImplementedException(); + } + + @Override + public Mappings listUserDomainMappings(String user, String domain) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void addRegexMapping(String user, String domain, String regex) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void removeRegexMapping(String user, String domain, String regex) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void copyMailbox(String srcBean, String dstBean) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void deleteUserMailboxesNames(String user) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void createMailbox(String namespace, String user, String name) { + MailboxSession mailboxSession = null; + try { + mailboxSession = mailboxManager.createSystemSession(user, LOGGER); + mailboxManager.startProcessingRequest(mailboxSession); + mailboxManager.createMailbox(new MailboxPath(namespace, user, name), mailboxSession); + } catch (MailboxException e) { + throw Throwables.propagate(e); + } finally { + closeSession(mailboxSession); + } + } + + @Override + public Mailbox<Id> getMailbox(String namespace, String user, String name) { + MailboxSession mailboxSession = null; + try { + mailboxSession = mailboxManager.createSystemSession(user, LOGGER); + MailboxMapper<Id> mailboxMapper = mailboxMapperFactory.getMailboxMapper(mailboxSession); + return mailboxMapper.findMailboxByPath(new MailboxPath(namespace, user, name)); + } catch (MailboxException e) { + throw Throwables.propagate(e); + } finally { + closeSession(mailboxSession); + } + } + + private void closeSession(MailboxSession session) { + if (session != null) { + mailboxManager.endProcessingRequest(session); + try { + mailboxManager.logout(session, true); + } catch (MailboxException e) { + throw Throwables.propagate(e); + } + } + } + + @Override + public Collection<String> listUserMailboxes(String user) { + MailboxSession mailboxSession = null; + try { + mailboxSession = mailboxManager.createSystemSession(user, LOGGER); + mailboxManager.startProcessingRequest(mailboxSession); + return searchUserMailboxes(user, mailboxSession) + .stream() + .map(MailboxMetaData::getPath) + .map(MailboxPath::getName) + .collect(Collectors.toList()); + } catch (MailboxException e) { + throw Throwables.propagate(e); + } finally { + closeSession(mailboxSession); + } + } + + private List<MailboxMetaData> searchUserMailboxes(String username, MailboxSession session) throws MailboxException { + return mailboxManager.search( + new MailboxQuery(new MailboxPath(MailboxConstants.USER_NAMESPACE, username, ""), + "*", + session.getPathDelimiter()), + session); + } + + @Override + public void deleteMailbox(String namespace, String user, String name) { + MailboxSession mailboxSession = null; + try { + mailboxSession = mailboxManager.createSystemSession(user, LOGGER); + mailboxManager.startProcessingRequest(mailboxSession); + mailboxManager.deleteMailbox(new MailboxPath(namespace, user, name), mailboxSession); + } catch (MailboxException e) { + throw Throwables.propagate(e); + } finally { + closeSession(mailboxSession); + } + } + + @Override + public String getQuotaRoot(String namespace, String user, String name) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public SerializableQuota getMessageCountQuota(String quotaRoot) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public SerializableQuota getStorageQuota(String quotaRoot) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public long getMaxMessageCount(String quotaRoot) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public long getMaxStorage(String quotaRoot) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public long getDefaultMaxMessageCount() throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public long getDefaultMaxStorage() throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public void setMaxMessageCount(String quotaRoot, long maxMessageCount) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public void setMaxStorage(String quotaRoot, long maxSize) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public void setDefaultMaxMessageCount(long maxDefaultMessageCount) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public void setDefaultMaxStorage(long maxDefaultSize) throws MailboxException { + throw new NotImplementedException(); + } + + @Override + public void appendMessage(String username, MailboxPath mailboxPath, InputStream message, Date internalDate, boolean isRecent, Flags flags) + throws MailboxException { + + MailboxSession mailboxSession = mailboxManager.createSystemSession(username, LOGGER); + MessageManager messageManager = mailboxManager.getMailbox(mailboxPath, mailboxSession); + messageManager.appendMessage(message, internalDate, mailboxSession, isRecent, flags); + } + + @Override + public void reIndexMailbox(String namespace, String user, String name) throws Exception { + throw new NotImplementedException(); + } + + @Override + public void reIndexAll() throws Exception { + throw new NotImplementedException(); + } + + @Override + public long getSieveQuota() throws Exception { + return sieveRepository.getQuota(); + } + + @Override + public void setSieveQuota(long quota) throws Exception { + sieveRepository.setQuota(quota); + } + + @Override + public void removeSieveQuota() throws Exception { + sieveRepository.removeQuota(); + } + + @Override + public long getSieveQuota(String user) throws Exception { + return sieveRepository.getQuota(user); + } + + @Override + public void setSieveQuota(String user, long quota) throws Exception { + sieveRepository.setQuota(user, quota); + } + + @Override + public void removeSieveQuota(String user) throws Exception { + sieveRepository.removeQuota(user); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java new file mode 100644 index 0000000..066f57a --- /dev/null +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java @@ -0,0 +1,164 @@ +/**************************************************************** + * 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 javax.inject.Singleton; + +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; + +@Singleton +public class InMemoryMailRepositoryStore implements MailRepositoryStore { + + 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()); + } + + 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); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java new file mode 100644 index 0000000..035f574 --- /dev/null +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProvider.java @@ -0,0 +1,29 @@ +/**************************************************************** + * 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 javax.inject.Provider; + +import org.apache.james.mailrepository.api.MailRepository; + +public interface MailRepositoryProvider extends Provider<MailRepository> { + + String canonicalName(); +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailboxManagerDefinition.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailboxManagerDefinition.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailboxManagerDefinition.java new file mode 100644 index 0000000..211398a --- /dev/null +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailboxManagerDefinition.java @@ -0,0 +1,57 @@ +/**************************************************************** + * 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 org.apache.james.mailbox.MailboxManager; + +import com.google.common.base.Objects; + +public class MailboxManagerDefinition { + + private final String name; + private final MailboxManager manager; + + public MailboxManagerDefinition(String name, MailboxManager manager) { + this.name = name; + this.manager = manager; + } + + public MailboxManager getManager() { + return manager; + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return Objects.hashCode(name, manager); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MailboxManagerDefinition) { + MailboxManagerDefinition other = (MailboxManagerDefinition) obj; + return Objects.equal(name, other.name) && Objects.equal(manager, other.manager); + } + return false; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/main/java/org/apache/james/utils/PropertiesReader.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/PropertiesReader.java b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/PropertiesReader.java new file mode 100644 index 0000000..cbf981d --- /dev/null +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/PropertiesReader.java @@ -0,0 +1,43 @@ +/**************************************************************** + * 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.io.IOException; +import java.util.Properties; + +import com.google.common.base.Throwables; + +public class PropertiesReader { + + private final Properties properties; + + public PropertiesReader(String fileName) { + properties = new Properties(); + try { + properties.load(ClassLoader.getSystemResourceAsStream(fileName)); + } catch (IOException e) { + throw Throwables.propagate(e); + } + } + + public String getProperty(String key) { + return properties.getProperty(key); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/java/org/apache/james/AbstractJamesServerTest.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/AbstractJamesServerTest.java b/server/container/guice/guice-common/src/test/java/org/apache/james/AbstractJamesServerTest.java new file mode 100644 index 0000000..cdb408c --- /dev/null +++ b/server/container/guice/guice-common/src/test/java/org/apache/james/AbstractJamesServerTest.java @@ -0,0 +1,117 @@ +/**************************************************************** + * 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; + +import static com.jayway.restassured.RestAssured.given; +import static com.jayway.restassured.config.EncoderConfig.encoderConfig; +import static com.jayway.restassured.config.RestAssuredConfig.newConfig; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.nio.charset.Charset; + +import org.apache.james.mailbox.store.mail.model.MailboxId; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.base.Charsets; +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.http.ContentType; + +public abstract class AbstractJamesServerTest<Id extends MailboxId> { + + private static final int IMAP_PORT = 1143; // You need to be root (superuser) to bind to ports under 1024. + private static final int IMAP_PORT_SSL = 1993; + private static final int POP3_PORT = 1110; + private static final int SMTP_PORT = 1025; + private static final int LMTP_PORT = 1024; + + private GuiceJamesServer<Id> server; + private SocketChannel socketChannel; + + @Before + public void setup() throws Exception { + server = createJamesServer(); + socketChannel = SocketChannel.open(); + server.start(); + + RestAssured.port = server.getJmapPort(); + RestAssured.config = newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)); + } + + protected abstract GuiceJamesServer<Id> createJamesServer(); + + @After + public void tearDown() throws Exception { + server.stop(); + } + + @Test + public void connectIMAPServerShouldSendShabangOnConnect() throws Exception { + socketChannel.connect(new InetSocketAddress("127.0.0.1", IMAP_PORT)); + assertThat(getServerConnectionResponse(socketChannel)).startsWith("* OK JAMES IMAP4rev1 Server"); + } + + @Test + public void connectOnSecondaryIMAPServerIMAPServerShouldSendShabangOnConnect() throws Exception { + socketChannel.connect(new InetSocketAddress("127.0.0.1", IMAP_PORT_SSL)); + assertThat(getServerConnectionResponse(socketChannel)).startsWith("* OK JAMES IMAP4rev1 Server"); + } + + @Test + public void connectPOP3ServerShouldSendShabangOnConnect() throws Exception { + socketChannel.connect(new InetSocketAddress("127.0.0.1", POP3_PORT)); + assertThat(getServerConnectionResponse(socketChannel)).contains("POP3 server (JAMES POP3 Server ) ready"); + } + + @Test + public void connectSMTPServerShouldSendShabangOnConnect() throws Exception { + socketChannel.connect(new InetSocketAddress("127.0.0.1", SMTP_PORT)); + assertThat(getServerConnectionResponse(socketChannel)).startsWith("220 JAMES Linagora's SMTP awesome Server"); + } + + @Test + public void connectLMTPServerShouldSendShabangOnConnect() throws Exception { + socketChannel.connect(new InetSocketAddress("127.0.0.1", LMTP_PORT)); + assertThat(getServerConnectionResponse(socketChannel)).contains("LMTP Server (JAMES Protocols Server) ready"); + } + + @Test + public void connectJMAPServerShouldRespondBadRequest() throws Exception { + given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body("{\"badAttributeName\": \"value\"}") + .when() + .post("/authentication") + .then() + .statusCode(400); + } + + private String getServerConnectionResponse(SocketChannel socketChannel) throws IOException { + ByteBuffer byteBuffer = ByteBuffer.allocate(1000); + socketChannel.read(byteBuffer); + byte[] bytes = byteBuffer.array(); + return new String(bytes, Charset.forName("UTF-8")); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/java/org/apache/james/modules/TestFilesystemModule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/modules/TestFilesystemModule.java b/server/container/guice/guice-common/src/test/java/org/apache/james/modules/TestFilesystemModule.java new file mode 100644 index 0000000..9f5bba4 --- /dev/null +++ b/server/container/guice/guice-common/src/test/java/org/apache/james/modules/TestFilesystemModule.java @@ -0,0 +1,61 @@ +/**************************************************************** + * 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.modules; + +import java.io.File; +import java.io.IOException; +import java.util.function.Supplier; + +import org.apache.james.core.JamesServerResourceLoader; +import org.apache.james.filesystem.api.FileSystem; +import org.apache.james.filesystem.api.JamesDirectoriesProvider; +import org.junit.rules.TemporaryFolder; + +import com.google.common.base.Throwables; +import com.google.inject.AbstractModule; +import com.google.inject.name.Names; + +public class TestFilesystemModule extends AbstractModule { + + private final Supplier<File> workingDirectory; + + private static File createTempDir(TemporaryFolder temporaryFolder) { + try { + return temporaryFolder.newFolder(); + } catch (IOException e) { + throw Throwables.propagate(e); + } + } + + public TestFilesystemModule(TemporaryFolder temporaryFolder) { + this(() -> TestFilesystemModule.createTempDir(temporaryFolder)); + } + + public TestFilesystemModule(Supplier<File> workingDirectory) { + this.workingDirectory = workingDirectory; + } + + @Override + protected void configure() { + bind(JamesDirectoriesProvider.class).toInstance(new JamesServerResourceLoader(workingDirectory.get().getAbsolutePath())); + bindConstant().annotatedWith(Names.named(CommonServicesModule.CONFIGURATION_PATH)).to(FileSystem.CLASSPATH_PROTOCOL); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/java/org/apache/james/modules/TestJMAPServerModule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/modules/TestJMAPServerModule.java b/server/container/guice/guice-common/src/test/java/org/apache/james/modules/TestJMAPServerModule.java new file mode 100644 index 0000000..6512fac --- /dev/null +++ b/server/container/guice/guice-common/src/test/java/org/apache/james/modules/TestJMAPServerModule.java @@ -0,0 +1,68 @@ +/**************************************************************** + * 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.modules; + +import java.io.FileNotFoundException; +import java.util.Optional; + +import javax.inject.Singleton; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.james.jmap.JMAPConfiguration; +import org.apache.james.jmap.methods.GetMessageListMethod; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.name.Names; + +public class TestJMAPServerModule extends AbstractModule{ + + private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" + + "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" + + "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" + + "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" + + "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" + + "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" + + "kwIDAQAB\n" + + "-----END PUBLIC KEY-----"; + + private final int maximumLimit; + + public TestJMAPServerModule(int maximumLimit) { + this.maximumLimit = maximumLimit; + } + + @Override + protected void configure() { + bindConstant().annotatedWith(Names.named(GetMessageListMethod.MAXIMUM_LIMIT)).to(maximumLimit); + } + + @Provides + @Singleton + JMAPConfiguration provideConfiguration() throws FileNotFoundException, ConfigurationException{ + return JMAPConfiguration.builder() + .keystore("keystore") + .secret("james72laBalle") + .jwtPublicKeyPem(Optional.of(PUBLIC_PEM_KEY)) + .randomPort() + .build(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/java/org/apache/james/utils/FileConfigurationProviderTest.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/FileConfigurationProviderTest.java b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/FileConfigurationProviderTest.java new file mode 100644 index 0000000..4fe0360 --- /dev/null +++ b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/FileConfigurationProviderTest.java @@ -0,0 +1,119 @@ +/**************************************************************** + * 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 static org.assertj.core.api.Assertions.assertThat; + +import org.apache.commons.cli.MissingArgumentException; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.HierarchicalConfiguration; +import org.apache.james.core.JamesServerResourceLoader; +import org.apache.james.core.filesystem.FileSystemImpl; +import org.apache.james.filesystem.api.FileSystem; +import org.junit.Before; +import org.junit.Test; + +public class FileConfigurationProviderTest { + + private static final String CONFIG_KEY_1 = "test2"; + private static final String CONFIG_KEY_2 = "property"; + private static final String CONFIG_KEY_4 = "james"; + private static final String CONFIG_KEY_5 = "internal"; + private static final String VALUE_1 = "0"; + private static final String VALUE_2 = "awesome"; + private static final String VALUE_3 = "james"; + private static final String FAKE_CONFIG_KEY = "fake"; + private static final String ROOT_CONFIG_KEY = "test"; + private static final String CONFIG_SEPARATOR = "."; + + private FileConfigurationProvider configurationProvider; + + @Before + public void setUp() throws MissingArgumentException { + FileSystemImpl fileSystem = new FileSystemImpl(new JamesServerResourceLoader("../")); + configurationProvider = new FileConfigurationProvider(fileSystem, FileSystem.CLASSPATH_PROTOCOL); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyArgumentShouldThrow() throws Exception { + configurationProvider.getConfiguration(""); + } + + @Test(expected = NullPointerException.class) + public void nullArgumentShouldThrow() throws Exception { + configurationProvider.getConfiguration(null); + } + + @Test(expected = IllegalArgumentException.class) + public void configSeparatorArgumentShouldThrow() throws Exception { + configurationProvider.getConfiguration(CONFIG_SEPARATOR); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyFileNameShouldThrow() throws Exception { + configurationProvider.getConfiguration(CONFIG_SEPARATOR + ROOT_CONFIG_KEY); + } + + @Test + public void getConfigurationShouldLoadCorrespondingXMLFile() throws Exception { + HierarchicalConfiguration hierarchicalConfiguration = configurationProvider.getConfiguration(ROOT_CONFIG_KEY); + assertThat(hierarchicalConfiguration.getKeys()).containsOnly(CONFIG_KEY_1, + String.join(CONFIG_SEPARATOR, CONFIG_KEY_4, CONFIG_KEY_2), + String.join(CONFIG_SEPARATOR, CONFIG_KEY_4, CONFIG_KEY_5, CONFIG_KEY_2)); + assertThat(hierarchicalConfiguration.getProperty(CONFIG_KEY_1)).isEqualTo(VALUE_1); + } + + @Test + public void getConfigurationShouldLoadCorrespondingXMLFilePart() throws Exception { + HierarchicalConfiguration hierarchicalConfiguration = configurationProvider.getConfiguration( + String.join(CONFIG_SEPARATOR, ROOT_CONFIG_KEY, CONFIG_KEY_4)); + assertThat(hierarchicalConfiguration.getKeys()).containsOnly(CONFIG_KEY_2, + String.join(CONFIG_SEPARATOR, CONFIG_KEY_5, CONFIG_KEY_2)); + assertThat(hierarchicalConfiguration.getProperty(CONFIG_KEY_2)).isEqualTo(VALUE_2); + } + + @Test + public void getConfigurationShouldLoadCorrespondingXMLFileWhenAPathIsProvidedPart() throws Exception { + HierarchicalConfiguration hierarchicalConfiguration = configurationProvider.getConfiguration( + String.join(CONFIG_SEPARATOR, ROOT_CONFIG_KEY, CONFIG_KEY_4, CONFIG_KEY_5)); + assertThat(hierarchicalConfiguration.getKeys()).containsOnly(CONFIG_KEY_2); + assertThat(hierarchicalConfiguration.getProperty(CONFIG_KEY_2)).isEqualTo(VALUE_3); + } + + @Test + public void multiplesSeparatorsShouldBeTolerated() throws Exception { + HierarchicalConfiguration hierarchicalConfiguration = configurationProvider.getConfiguration( + ROOT_CONFIG_KEY + CONFIG_SEPARATOR + CONFIG_SEPARATOR + CONFIG_KEY_4); + assertThat(hierarchicalConfiguration.getKeys()).containsOnly(CONFIG_KEY_2, + String.join(CONFIG_SEPARATOR, CONFIG_KEY_5, CONFIG_KEY_2)); + assertThat(hierarchicalConfiguration.getProperty(CONFIG_KEY_2)).isEqualTo(VALUE_2); + } + + @Test(expected = ConfigurationException.class) + public void getConfigurationShouldThrowOnNonExistingXMLFile() throws Exception { + assertThat(configurationProvider.getConfiguration(FAKE_CONFIG_KEY)).isNotNull(); + } + + @Test(expected = IllegalArgumentException.class) + public void getConfigurationShouldThrowOnNonExistingXMLFilePart() throws Exception { + configurationProvider.getConfiguration(String.join(CONFIG_SEPARATOR, ROOT_CONFIG_KEY, FAKE_CONFIG_KEY)); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java new file mode 100644 index 0000000..d8582b3 --- /dev/null +++ b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java @@ -0,0 +1,109 @@ +/**************************************************************** + * 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 static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.james.core.JamesServerResourceLoader; +import org.apache.james.core.filesystem.FileSystemImpl; +import org.apache.james.filesystem.api.FileSystem; +import org.apache.james.mailrepository.api.MailRepositoryStore; +import org.apache.james.mailrepository.file.FileMailRepository; +import org.apache.james.modules.server.MailStoreRepositoryModule; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.Sets; + +public class InMemoryMailRepositoryStoreTest { + + private InMemoryMailRepositoryStore repositoryStore; + private FileSystemImpl fileSystem; + + @Before + public void setUp() throws Exception { + fileSystem = new FileSystemImpl(new JamesServerResourceLoader("../")); + repositoryStore = new InMemoryMailRepositoryStore(Sets.newHashSet( + new MailStoreRepositoryModule.FileMailRepositoryProvider( + fileSystem))); + repositoryStore.configure(new FileConfigurationProvider(fileSystem, FileSystem.CLASSPATH_PROTOCOL).getConfiguration("mailrepositorystore")); + repositoryStore.init(); + } + + @Test(expected = MailRepositoryStore.MailRepositoryStoreException.class) + public void selectingANonRegisteredProtocolShouldFail() throws Exception { + repositoryStore.select("proto://repo"); + } + + @Test + public void selectingARegisteredProtocolShouldWork() throws Exception { + assertThat(repositoryStore.select("file://repo")).isInstanceOf(FileMailRepository.class); + } + + @Test + public void selectingTwiceARegisteredProtocolWithSameDestinationShouldReturnTheSameResult() throws Exception { + assertThat(repositoryStore.select("file://repo")).isEqualTo(repositoryStore.select("file://repo")); + } + + @Test + public void selectingTwiceARegisteredProtocolWithDifferentDestinationShouldReturnDifferentResults() throws Exception { + assertThat(repositoryStore.select("file://repo")).isNotEqualTo(repositoryStore.select("file://repo1")); + } + + @Test(expected = ConfigurationException.class) + public void configureShouldThrowWhenNonValidClassesAreProvided() throws Exception { + try { + repositoryStore = new InMemoryMailRepositoryStore(Sets.newHashSet( + new MailStoreRepositoryModule.FileMailRepositoryProvider( + fileSystem))); + repositoryStore.configure(new FileConfigurationProvider(fileSystem, FileSystem.CLASSPATH_PROTOCOL).getConfiguration("fakemailrepositorystore")); + } catch (ConfigurationException e) { + fail("Unexpected failure : ", e); + } + repositoryStore.init(); + } + + @Test + public void getUrlsShouldBeEmptyIfNoSelectWerePerformed() { + assertThat(repositoryStore.getUrls()).isEmpty(); + } + + @Test + public void getUrlsShouldReturnUsedUrls() throws Exception { + String url1 = "file://repo1"; + String url2 = "file://repo2"; + String url3 = "file://repo3"; + repositoryStore.select(url1); + repositoryStore.select(url2); + repositoryStore.select(url3); + assertThat(repositoryStore.getUrls()).containsOnly(url1, url2, url3); + } + + @Test + public void getUrlsResultsShouldNotBeDuplicated() throws Exception { + String url1 = "file://repo1"; + repositoryStore.select(url1); + repositoryStore.select(url1); + assertThat(repositoryStore.getUrls()).containsExactly(url1); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/java/org/apache/james/utils/PropertiesReadTest.java ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/PropertiesReadTest.java b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/PropertiesReadTest.java new file mode 100644 index 0000000..1d3de34 --- /dev/null +++ b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/PropertiesReadTest.java @@ -0,0 +1,44 @@ +/**************************************************************** + * 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 static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class PropertiesReadTest { + + @Test + public void getPropertyShouldWork() throws Exception { + PropertiesReader propertiesReader = new PropertiesReader("test.properties"); + assertThat(propertiesReader.getProperty("cassandra.ip")).isEqualTo("127.0.0.1"); + } + + @Test + public void getAbsentPropertyShouldReturnNull() throws Exception { + PropertiesReader propertiesReader = new PropertiesReader("test.properties"); + assertThat(propertiesReader.getProperty("cassandra.isslow")).isNull(); + } + + @Test(expected = RuntimeException.class) + public void buildingAPropertiesReaderOnNonExistingValuesShouldThrow() throws Exception { + new PropertiesReader("fake.properties"); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/resources/fakemailrepositorystore.xml ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/resources/fakemailrepositorystore.xml b/server/container/guice/guice-common/src/test/resources/fakemailrepositorystore.xml new file mode 100644 index 0000000..2d19a80 --- /dev/null +++ b/server/container/guice/guice-common/src/test/resources/fakemailrepositorystore.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> + +<!-- + 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. + --> + +<mailrepositorystore> + <mailrepositories> + <mailrepository class="org.apache.james.mailrepository.None"> + <protocols> + <protocol>file</protocol> + </protocols> + <config FIFO="false" CACHEKEYS="true"/> + </mailrepository> + </mailrepositories> +</mailrepositorystore> http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/resources/mailrepositorystore.xml ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/resources/mailrepositorystore.xml b/server/container/guice/guice-common/src/test/resources/mailrepositorystore.xml new file mode 100644 index 0000000..3ca4a1d --- /dev/null +++ b/server/container/guice/guice-common/src/test/resources/mailrepositorystore.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> + +<!-- + 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. + --> + +<mailrepositorystore> + <mailrepositories> + <mailrepository class="org.apache.james.mailrepository.file.FileMailRepository"> + <protocols> + <protocol>file</protocol> + </protocols> + <config FIFO="false" CACHEKEYS="true"/> + </mailrepository> + </mailrepositories> +</mailrepositorystore> http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/resources/test.properties ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/resources/test.properties b/server/container/guice/guice-common/src/test/resources/test.properties new file mode 100644 index 0000000..b4db9c1 --- /dev/null +++ b/server/container/guice/guice-common/src/test/resources/test.properties @@ -0,0 +1,6 @@ +# Configuration file for cassandra mailbox + +cassandra.ip=127.0.0.1 +cassandra.port=9142 +cassandra.keyspace=apache_james +cassandra.replication.factor=1 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/guice-common/src/test/resources/test.xml ---------------------------------------------------------------------- diff --git a/server/container/guice/guice-common/src/test/resources/test.xml b/server/container/guice/guice-common/src/test/resources/test.xml new file mode 100644 index 0000000..8d89ecc --- /dev/null +++ b/server/container/guice/guice-common/src/test/resources/test.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<!-- + 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. + --> +<test> + <test2>0</test2> + <james> + <property>awesome</property> + <internal> + <property>james</property> + </internal> + </james> +</test> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/memory-guice/README.adoc ---------------------------------------------------------------------- diff --git a/server/container/guice/memory-guice/README.adoc b/server/container/guice/memory-guice/README.adoc new file mode 100644 index 0000000..b896354 --- /dev/null +++ b/server/container/guice/memory-guice/README.adoc @@ -0,0 +1,38 @@ += Guice-Memory Module How-to + +== Building + +=== Requirements + + * Java 8 SDK + * Docker + * Maven + +=== Building the artifacts + +An usual compilation using maven will produce two artifacts into target directory : + + * james-server-memory-guice-${version}.jar + * james-server-memory-guice-${version}.lib + +== Running + +=== James Launch + +To run james, you have to create a directory containing required configuration files. + +A sample directory (appropriately named sample-directory) is provided with some +default values you may need to replace. + +You also need to generate a keystore with the following command : +[source] +---- +$ keytool -genkey -alias james -keyalg RSA -keystore conf/keystore +---- + +Once everything is set up, you just have to run the jar with : + +[source] +---- +$ java -Dworking.directory=sample-configuration -jar target/james-server-memory-guice-${version}.jar +---- http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/memory-guice/pom.xml ---------------------------------------------------------------------- diff --git a/server/container/guice/memory-guice/pom.xml b/server/container/guice/memory-guice/pom.xml new file mode 100644 index 0000000..83aec4a --- /dev/null +++ b/server/container/guice/memory-guice/pom.xml @@ -0,0 +1,261 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.james</groupId> + <artifactId>james-server</artifactId> + <version>3.0.0-beta5-SNAPSHOT</version> + <relativePath>../../../pom.xml</relativePath> + </parent> + + <artifactId>james-server-memory-guice</artifactId> + <packaging>jar</packaging> + + <name>Apache James :: Server :: Memory - guice injection</name> + <description>An advanced email server - Memory backend with guice injection</description> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>disable-build-for-older-jdk</id> + <activation> + <jdk>(,1.8)</jdk> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <id>default-jar</id> + <phase>none</phase> + </execution> + <execution> + <id>jar</id> + <phase>none</phase> + </execution> + <execution> + <id>test-jar</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <executions> + <execution> + <id>default-compile</id> + <phase>none</phase> + </execution> + <execution> + <id>default-testCompile</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <executions> + <execution> + <id>default-test</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <executions> + <execution> + <id>attach-sources</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-install-plugin</artifactId> + <executions> + <execution> + <id>default-install</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>default-resources</id> + <phase>none</phase> + </execution> + <execution> + <id>default-testResources</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-site-plugin</artifactId> + <executions> + <execution> + <id>attach-descriptor</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>build-for-jdk-8</id> + <activation> + <jdk>[1.8,)</jdk> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <outputDirectory>${project.build.directory}/${project.build.finalName}.lib</outputDirectory> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <id>default-jar</id> + <goals> + <goal>jar</goal> + </goals> + <configuration> + <archive> + <manifest> + <addClasspath>true</addClasspath> + <classpathPrefix>${project.build.finalName}.lib/</classpathPrefix> + <mainClass>org.apache.james.MemoryJamesServerMain</mainClass> + <useUniqueVersions>false</useUniqueVersions> + </manifest> + </archive> + </configuration> + </execution> + <execution> + <id>test-jar</id> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>apache-james-mailbox-memory</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>apache-james-mailbox-tika</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>james-server-data-memory</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>james-server-guice-common</artifactId> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>james-server-guice-common</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency><dependency> + <groupId>${project.groupId}</groupId> + <artifactId>apache-mailet-base</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.jayway.restassured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>${assertj-3.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + </profile> + <profile> + <id>disable-animal-sniffer</id> + <activation> + <jdk>[1.6,)</jdk> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>animal-sniffer-maven-plugin</artifactId> + <executions> + <execution> + <id>check_java_6</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> http://git-wip-us.apache.org/repos/asf/james-project/blob/517a4cfe/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java ---------------------------------------------------------------------- diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java new file mode 100644 index 0000000..991ba1e --- /dev/null +++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java @@ -0,0 +1,49 @@ +/**************************************************************** + * 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; + +import org.apache.james.mailbox.inmemory.InMemoryId; +import org.apache.james.modules.data.MemoryDataModule; +import org.apache.james.modules.mailbox.MemoryMailboxModule; +import org.apache.james.modules.server.ActiveMQQueueModule; +import org.apache.james.modules.server.JMXServerModule; +import org.apache.james.modules.server.QuotaModule; + +import com.google.inject.Module; +import com.google.inject.TypeLiteral; +import com.google.inject.util.Modules; + +public class MemoryJamesServerMain { + + private static final TypeLiteral<InMemoryId> inMemoryId = new TypeLiteral<InMemoryId>(){}; + + public static final Module inMemoryServerModule = Modules.combine( + new MemoryDataModule(), + new MemoryMailboxModule(), + new QuotaModule(), + new ActiveMQQueueModule<>(inMemoryId)); + + public static void main(String[] args) throws Exception { + new GuiceJamesServer<>(inMemoryId) + .combineWith(inMemoryServerModule, new JMXServerModule()) + .start(); + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org