http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/app/pom.xml ---------------------------------------------------------------------- diff --git a/server/app/pom.xml b/server/app/pom.xml index 3fab093..1aef76e 100644 --- a/server/app/pom.xml +++ b/server/app/pom.xml @@ -73,17 +73,6 @@ <dependencies> <dependency> <groupId>${james.groupId}</groupId> - <artifactId>apache-james-mailbox-jcr</artifactId> - <scope>runtime</scope> - <exclusions> - <exclusion> - <groupId>javax.mail</groupId> - <artifactId>mail</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>${james.groupId}</groupId> <artifactId>apache-james-mailbox-jpa</artifactId> <scope>runtime</scope> <exclusions> @@ -168,17 +157,6 @@ </dependency> <dependency> <groupId>${james.groupId}</groupId> - <artifactId>james-server-data-jcr</artifactId> - <scope>runtime</scope> - <exclusions> - <exclusion> - <groupId>javax.mail</groupId> - <artifactId>mail</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>${james.groupId}</groupId> <artifactId>james-server-data-jdbc</artifactId> <scope>runtime</scope> <exclusions>
http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/app/src/main/app/var/README.txt ---------------------------------------------------------------------- diff --git a/server/app/src/main/app/var/README.txt b/server/app/src/main/app/var/README.txt index d7b371c..70f056e 100644 --- a/server/app/src/main/app/var/README.txt +++ b/server/app/src/main/app/var/README.txt @@ -12,7 +12,7 @@ There should be two folders in var: * store - This folder contains the files related to database, jcr, activemq,... needed by James. + This folder contains the files related to database, activemq,... needed by James. James Server default settings comes with a embedded Derby database that stores the users, domains and mailboxes (the user mails) (see store/derby folder). Of course, if you changed database.properties and still use a database for the mailboxes, http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/app/src/main/app/var/store/README.txt ---------------------------------------------------------------------- diff --git a/server/app/src/main/app/var/store/README.txt b/server/app/src/main/app/var/store/README.txt index 0fd3b41..f5c3f87 100644 --- a/server/app/src/main/app/var/store/README.txt +++ b/server/app/src/main/app/var/store/README.txt @@ -1,6 +1,6 @@ $JAMES_ROOT/var/store - This folder contains the files related to database, jcr, activemq,... needed by James. + This folder contains the files related to database, activemq,... needed by James. James Server default settings comes with a embedded Derby database that stores the users, domains and mailboxes (the user mails) (see store/derby folder). @@ -26,8 +26,3 @@ $JAMES_ROOT/var/store mailboxes. Use var/store/maildir folder to contain the user's mails. - * jackrabbit - - You can configure James to use JCR (Java Content Repository, based - on Apache Jackrabbit) as storage for the user mailboxes. Use - var/store/jackrabbit folder to contain the user's mails. http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/app/src/main/licensing/app/licensing.xml ---------------------------------------------------------------------- diff --git a/server/app/src/main/licensing/app/licensing.xml b/server/app/src/main/licensing/app/licensing.xml index 741e4be..04f71a6 100644 --- a/server/app/src/main/licensing/app/licensing.xml +++ b/server/app/src/main/licensing/app/licensing.xml @@ -1159,7 +1159,6 @@ The Apache Software Foundation (http://www.apache.org/). <resource name='domainlist.xml'/> <resource name='fetchmail.xml'/> <resource name='imapserver.xml'/> - <resource name='jcr-repository.xml'/> <resource name='jmx.properties'/> <resource name='lmtpserver.xml'/> <resource name='log4j.properties'/> @@ -1185,7 +1184,6 @@ The Apache Software Foundation (http://www.apache.org/). <within dir='conf/context'> <with-license id='ApacheLicenseVersion2'> <by-organisation id='apache.org'> - <resource name='james-mailbox-jcr-context.xml'/> <resource name='james-mailbox-jpa-context.xml'/> <resource name='james-mailbox-maildir-context.xml'/> <resource name='james-mailbox-memory-context.xml'/> @@ -1254,11 +1252,6 @@ The Apache Software Foundation (http://www.apache.org/). <resource name='wrapper.jar'/> </by-organisation> </with-license> - <with-license id='DaySpecLicensePlusAddendum'> - <by-organisation id='day.com'> - <resource name='jcr-2.0.jar'/> - </by-organisation> - </with-license> <with-license id='CDDL'> <by-organisation id='oracle.com'> <resource name='mail-1.4.4.jar' source='http://kenai.com/projects/javamail/downloads'/> @@ -1296,7 +1289,6 @@ All rights reserved. <resource name='apache-james-imap-message-0.2.1.jar'/> <resource name='apache-james-imap-processor-0.2.1.jar'/> <resource name='apache-james-mailbox-api-0.3.jar'/> - <resource name='apache-james-mailbox-jcr-0.3.jar'/> <resource name='apache-james-mailbox-jpa-0.3.jar'/> <resource name='apache-james-mailbox-maildir-0.3.jar'/> <resource name='apache-james-mailbox-memory-0.3.jar'/> @@ -1334,7 +1326,6 @@ All rights reserved. <resource name='geronimo-stax-api_1.0_spec-1.0.1.jar'/> <resource name='jackrabbit-api-2.2.5.jar'/> <resource name='jackrabbit-core-2.2.5.jar'/> - <resource name='jackrabbit-jcr-commons-2.2.5.jar'/> <resource name='jackrabbit-spi-2.2.5.jar'/> <resource name='jackrabbit-spi-commons-2.2.5.jar'/> <resource name='james-server-cli-3.0-beta3.jar'/> @@ -1349,7 +1340,6 @@ All rights reserved. <resource name='james-server-file-3.0-beta3.jar'/> <resource name='james-server-filesystem-api-3.0-beta3.jar'/> <resource name='james-server-imapserver-3.0-beta3.jar'/> - <resource name='james-server-jcr-3.0-beta3.jar'/> <resource name='james-server-jdbc-3.0-beta3.jar'/> <resource name='james-server-jpa-3.0-beta3.jar'/> <resource name='james-server-ldap-3.0-beta3.jar'/> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/app/src/main/licensing/war/licensing.xml ---------------------------------------------------------------------- diff --git a/server/app/src/main/licensing/war/licensing.xml b/server/app/src/main/licensing/war/licensing.xml index 27ffdbc..2a92e9d 100644 --- a/server/app/src/main/licensing/war/licensing.xml +++ b/server/app/src/main/licensing/war/licensing.xml @@ -1154,7 +1154,6 @@ The Apache Software Foundation (http://www.apache.org/). <resource name='domainlist.xml'/> <resource name='fetchmail.xml'/> <resource name='imapserver.xml'/> - <resource name='jcr-repository.xml'/> <resource name='jmx.properties'/> <resource name='lmtpserver.xml'/> <resource name='mailbox.xml'/> @@ -1179,7 +1178,6 @@ The Apache Software Foundation (http://www.apache.org/). <within dir='WEB-INF/conf/context'> <with-license id='ApacheLicenseVersion2'> <by-organisation id='apache.org'> - <resource name='james-mailbox-jcr-context.xml'/> <resource name='james-mailbox-jpa-context.xml'/> <resource name='james-mailbox-maildir-context.xml'/> <resource name='james-mailbox-memory-context.xml'/> @@ -1201,7 +1199,6 @@ The Apache Software Foundation (http://www.apache.org/). </public-domain> <with-license id='DaySpecLicensePlusAddendum'> <by-organisation id='day.com'> - <resource name='jcr-2.0.jar'/> </by-organisation> </with-license> <with-license id='CDDL'> @@ -1241,7 +1238,6 @@ All rights reserved. <resource name='apache-james-imap-message-0.2.1.jar'/> <resource name='apache-james-imap-processor-0.2.1.jar'/> <resource name='apache-james-mailbox-api-0.3.jar'/> - <resource name='apache-james-mailbox-jcr-0.3.jar'/> <resource name='apache-james-mailbox-jpa-0.3.jar'/> <resource name='apache-james-mailbox-maildir-0.3.jar'/> <resource name='apache-james-mailbox-memory-0.3.jar'/> @@ -1279,7 +1275,6 @@ All rights reserved. <resource name='geronimo-stax-api_1.0_spec-1.0.1.jar'/> <resource name='jackrabbit-api-2.2.5.jar'/> <resource name='jackrabbit-core-2.2.5.jar'/> - <resource name='jackrabbit-jcr-commons-2.2.5.jar'/> <resource name='jackrabbit-spi-2.2.5.jar'/> <resource name='jackrabbit-spi-commons-2.2.5.jar'/> <resource name='james-server-cli-3.0-beta3.jar'/> @@ -1294,7 +1289,6 @@ All rights reserved. <resource name='james-server-file-3.0-beta3.jar'/> <resource name='james-server-filesystem-api-3.0-beta3.jar'/> <resource name='james-server-imapserver-3.0-beta3.jar'/> - <resource name='james-server-jcr-3.0-beta3.jar'/> <resource name='james-server-jdbc-3.0-beta3.jar'/> <resource name='james-server-jpa-3.0-beta3.jar'/> <resource name='james-server-ldap-3.0-beta3.jar'/> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/app/src/main/resources/mailbox-jcr.cnd ---------------------------------------------------------------------- diff --git a/server/app/src/main/resources/mailbox-jcr.cnd b/server/app/src/main/resources/mailbox-jcr.cnd deleted file mode 100644 index fd625fd..0000000 --- a/server/app/src/main/resources/mailbox-jcr.cnd +++ /dev/null @@ -1,74 +0,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. - */ - -<!-- - This template file can be used as example for James Server configuration - DO NOT USE IT AS SUCH AND ADAPT IT TO YOUR NEEDS ---> - -<!-- See http://james.apache.org/server/3/config.html for usage --> - -<jamesMailbox = 'http://james.apache.org/imap/jcr/'> - -[jamesMailbox:user] > mix:created - mixin - - jamesMailbox:user (String) - - jamesMailbox:subscriptionMailboxes (STRING) multiple - + * (nt:unstructured) multiple - - -[jamesMailbox:messageHeader] > mix:created, mix:lockable - mixin - - jamesMailbox:headerFieldName (STRING) mandatory - - jamesMailbox:headerValue(STRING) mandatory - - jamesMailbox:headerLineNumber (LONG) mandatory - -[jamesMailbox:messageProperty] > mix:created - mixin - - jamesMailbox:propertyNamespace (STRING) mandatory - - jamesMailbox:propertyLocalName (STRING) mandatory - - jamesMailbox:propertyValue(STRING) mandatory - - jamesMailbox:propertyOrder (Long) mandatory - -[jamesMailbox:message] > mix:referenceable, mix:created, mix:created - mixin - - jamesMailbox:mailboxUUID (String) mandatory - - jamesMailbox:uid (LONG) mandatory - - jamesMailbox:modSeq (LONG) - - jamesMailbox:size (LONG) mandatory - - jamesMailbox:answered (BOOLEAN) - - jamesMailbox:deleted (BOOLEAN) - - jamesMailbox:draft (BOOLEAN) - - jamesMailbox:flagged (BOOLEAN) - - jamesMailbox:recent (BOOLEAN) - - jamesMailbox:seen (BOOLEAN) - - jamesMailbox:internalDate (DATE) - - jamesMailbox:userFlags (STRING) multiple - - jamesMailbox:messageBodyStartOctet (LONG) mandatory - - jamesMailbox:messageTextualLineCount (LONG) - - jamesMailbox:messageSubType (String) mandatory - + messageHeader (nt:unstructured) multiple - + messageProperty (nt:unstructured) multiple - -[jamesMailbox:mailbox] > mix:referenceable, mix:lockable, mix:created - mixin - - jamesMailbox:mailboxUidValidity (LONG) - - jamesMailbox:mailboxName (STRING) - - jamesMailbox:mailboxLastUid (LONG) - - jamesMailbox:mailboxNamespace (STRING) - - jamesMailbox:mailboxUser (STRING) - + * (nt:unstructured) multiple http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/app/src/main/resources/mailbox.xml ---------------------------------------------------------------------- diff --git a/server/app/src/main/resources/mailbox.xml b/server/app/src/main/resources/mailbox.xml index a557c96..0bb547d 100644 --- a/server/app/src/main/resources/mailbox.xml +++ b/server/app/src/main/resources/mailbox.xml @@ -27,7 +27,7 @@ <mailbox> <!-- supported providers are: --> - <!-- jpa, jcr, maildir, memory --> + <!-- jpa, maildir, memory --> <!-- --> <!-- Be aware that maildir will only work on unix like operation systems! --> <provider>jpa</provider> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/app/src/test/resources/mailbox.xml ---------------------------------------------------------------------- diff --git a/server/app/src/test/resources/mailbox.xml b/server/app/src/test/resources/mailbox.xml index 03ce5eb..4172558 100644 --- a/server/app/src/test/resources/mailbox.xml +++ b/server/app/src/test/resources/mailbox.xml @@ -25,7 +25,7 @@ <mailbox> <!-- supported providers are: --> - <!-- jpa, jcr, maildir, memory --> + <!-- jpa, maildir, memory --> <!-- --> <!-- Be aware that maildir will only work on unix like operation systems! --> <provider>jpa</provider> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/container/mailbox-adapter/src/main/resources/mailbox.xml ---------------------------------------------------------------------- diff --git a/server/container/mailbox-adapter/src/main/resources/mailbox.xml b/server/container/mailbox-adapter/src/main/resources/mailbox.xml index 4314234..6cb07d3 100644 --- a/server/container/mailbox-adapter/src/main/resources/mailbox.xml +++ b/server/container/mailbox-adapter/src/main/resources/mailbox.xml @@ -22,7 +22,7 @@ <mailbox> <!-- supported providers are: --> - <!-- jpa, jcr, maildir, memory --> + <!-- jpa, maildir, memory --> <!-- --> <!-- Be aware that maildir will only work on unix like operation systems! --> <provider>jpa</provider> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factorypostprocessor/MailboxConfigurationBeanFactoryPostProcessor.java ---------------------------------------------------------------------- diff --git a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factorypostprocessor/MailboxConfigurationBeanFactoryPostProcessor.java b/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factorypostprocessor/MailboxConfigurationBeanFactoryPostProcessor.java index 687772c..4ca6b8b 100644 --- a/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factorypostprocessor/MailboxConfigurationBeanFactoryPostProcessor.java +++ b/server/container/spring/src/main/java/org/apache/james/container/spring/bean/factorypostprocessor/MailboxConfigurationBeanFactoryPostProcessor.java @@ -41,12 +41,10 @@ public class MailboxConfigurationBeanFactoryPostProcessor implements BeanFactory private static final String JPA_MAILBOXMANAGER = "jpa-mailboxmanager"; private static final String MEMORY_MAILBOX_MANAGER = "memory-mailboxManager"; - private static final String JCR_MAILBOXMANAGER = "jcr-mailboxmanager"; private static final String MAILDIR_MAILBOXMANAGER = "maildir-mailboxmanager"; private static final String CASSANDRA_MAILBOXMANAGER = "cassandra-mailboxmanager"; private static final ImmutableSet<String> MAILBOX_MANAGER_IDS = ImmutableSet.of(JPA_MAILBOXMANAGER, MEMORY_MAILBOX_MANAGER, - JCR_MAILBOXMANAGER, MAILDIR_MAILBOXMANAGER, - CASSANDRA_MAILBOXMANAGER); + MAILDIR_MAILBOXMANAGER, CASSANDRA_MAILBOXMANAGER); @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { @@ -73,11 +71,6 @@ public class MailboxConfigurationBeanFactoryPostProcessor implements BeanFactory messageMapperFactory = "memory-sessionMapperFactory"; mailboxIdDeserializer = "memory-mailbox-id-deserializer"; mailboxIdFactory = "memory-mailboxIdFactory"; - } else if (provider.equalsIgnoreCase("jcr")) { - mailbox = JCR_MAILBOXMANAGER; - subscription = "jcr-subscriptionManager"; - messageMapperFactory = "jcr-sessionMapperFactory"; - mailboxIdDeserializer = "jcr-mailbox-id-deserializer"; } else if (provider.equalsIgnoreCase("maildir")) { mailbox = MAILDIR_MAILBOXMANAGER; subscription = "maildir-subscriptionManager"; http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/pom.xml ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/pom.xml b/server/data/data-jcr/pom.xml deleted file mode 100644 index e22b68a..0000000 --- a/server/data/data-jcr/pom.xml +++ /dev/null @@ -1,126 +0,0 @@ -<?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.2.0-SNAPSHOT</version> - <relativePath>../../pom.xml</relativePath> - </parent> - - <artifactId>james-server-data-jcr</artifactId> - <packaging>bundle</packaging> - - <name>Apache James :: Server :: Data :: JCR Persistence</name> - - <dependencies> - <dependency> - <groupId>${james.groupId}</groupId> - <artifactId>apache-mailet-api</artifactId> - </dependency> - <dependency> - <groupId>${james.groupId}</groupId> - <artifactId>james-server-core</artifactId> - </dependency> - <dependency> - <groupId>${james.groupId}</groupId> - <artifactId>james-server-data-api</artifactId> - </dependency> - <dependency> - <groupId>${james.groupId}</groupId> - <artifactId>james-server-data-library</artifactId> - </dependency> - <dependency> - <groupId>${james.groupId}</groupId> - <artifactId>james-server-data-library</artifactId> - <type>test-jar</type> - <scope>test</scope> - </dependency> - <dependency> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-classic</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava</artifactId> - </dependency> - <dependency> - <groupId>com.sun.mail</groupId> - <artifactId>javax.mail</artifactId> - </dependency> - <dependency> - <groupId>commons-configuration</groupId> - <artifactId>commons-configuration</artifactId> - </dependency> - <dependency> - <groupId>javax.inject</groupId> - <artifactId>javax.inject</artifactId> - </dependency> - <dependency> - <groupId>javax.jcr</groupId> - <artifactId>jcr</artifactId> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.geronimo.specs</groupId> - <artifactId>geronimo-annotation_1.1_spec</artifactId> - </dependency> - <dependency> - <groupId>org.apache.jackrabbit</groupId> - <artifactId>jackrabbit-core</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.jackrabbit</groupId> - <artifactId>jackrabbit-jcr-commons</artifactId> - </dependency> - <dependency> - <groupId>org.assertj</groupId> - <artifactId>assertj-core</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>jcl-over-slf4j</artifactId> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-api</artifactId> - </dependency> - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.apache.felix</groupId> - <artifactId>maven-bundle-plugin</artifactId> - <extensions>true</extensions> - </plugin> - </plugins> - </build> - -</project> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java b/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java deleted file mode 100644 index a2f6166..0000000 --- a/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java +++ /dev/null @@ -1,653 +0,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. - */ -package org.apache.james.mailrepository.jcr; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.Properties; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.PathNotFoundException; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; -import javax.jcr.Value; -import javax.jcr.query.Query; -import javax.jcr.query.QueryManager; -import javax.mail.MessagingException; -import javax.mail.internet.MimeMessage; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.HierarchicalConfiguration; -import org.apache.jackrabbit.commons.cnd.CndImporter; -import org.apache.jackrabbit.util.ISO9075; -import org.apache.jackrabbit.util.Text; -import org.apache.james.core.MailAddress; -import org.apache.james.core.MaybeSender; -import org.apache.james.mailrepository.api.MailKey; -import org.apache.james.mailrepository.api.MailRepository; -import org.apache.james.mailrepository.lib.AbstractMailRepository; -import org.apache.james.server.core.MailImpl; -import org.apache.mailet.Mail; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Mail repository that is backed by a JCR content repository. - * - * @Deprecated: See JAMES-2323 - * - * Will be removed in James 3.2.0 upcoming release. - * - * Use a modern, maintained MailRepository instead. For instead FileMailRepository. - */ -@Deprecated -public class JCRMailRepository extends AbstractMailRepository implements MailRepository { - private static final Logger LOGGER = LoggerFactory.getLogger(JCRMailRepository.class); - - private static final String MAIL_PATH = "mailrepository"; - - private Repository repository; - private SimpleCredentials creds; - private String workspace; - - - @Inject - public void setRepository(Repository repository) { - this.repository = repository; - } - - @Override - @PostConstruct - public void init() throws Exception { - // register the nodetype - CndImporter.registerNodeTypes(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("org/apache/james/imap/jcr/james.cnd")), login()); - } - - @Override - public void doConfigure(HierarchicalConfiguration config) throws ConfigurationException { - this.workspace = config.getString("workspace", null); - String username = config.getString("username", null); - String password = config.getString("password", null); - - if (username != null && password != null) { - this.creds = new SimpleCredentials(username, password.toCharArray()); - } - } - - protected String toSafeName(String key) { - return ISO9075.encode(Text.escapeIllegalJcrChars(key)); - } - - private Session login() throws RepositoryException { - return repository.login(creds, workspace); - } - - @Override - public Iterator<MailKey> list() throws MessagingException { - try { - Session session = login(); - try { - Collection<String> keys = new ArrayList<>(); - QueryManager manager = session.getWorkspace().getQueryManager(); - Query query = manager.createQuery("/jcr:root/" + MAIL_PATH + "//element(*,james:mail)", Query.XPATH); - NodeIterator iterator = query.execute().getNodes(); - while (iterator.hasNext()) { - String name = iterator.nextNode().getName(); - keys.add(Text.unescapeIllegalJcrChars(name)); - } - return keys.stream() - .map(MailKey::new) - .iterator(); - } finally { - session.logout(); - } - } catch (RepositoryException e) { - throw new MessagingException("Unable to list messages", e); - } - } - - @Override - public Mail retrieve(MailKey key) throws MessagingException { - try { - Session session = login(); - try { - String name = toSafeName(key.asString()); - QueryManager manager = session.getWorkspace().getQueryManager(); - Query query = manager.createQuery("/jcr:root/" + MAIL_PATH + "//element(" + name + ",james:mail)", Query.XPATH); - NodeIterator iterator = query.execute().getNodes(); - if (iterator.hasNext()) { - return getMail(iterator.nextNode()); - } else { - return null; - } - } finally { - session.logout(); - } - } catch (IOException | RepositoryException e) { - throw new MessagingException("Unable to retrieve message: " + key, e); - } - } - - // -------------------------------------------------------------< private > - - /** - * Reads a mail message from the given mail node. - * - * @param node - * mail node - * @return mail message - * @throws MessagingException - * if a messaging error occurs - * @throws RepositoryException - * if a repository error occurs - * @throws IOException - * if an IO error occurs - */ - private Mail getMail(Node node) throws MessagingException, RepositoryException, IOException { - String name = Text.unescapeIllegalJcrChars(node.getName()); - MailImpl mail = new MailImpl(name, getSender(node), getRecipients(node), getMessage(node)); - mail.setState(getState(node)); - mail.setLastUpdated(getLastUpdated(node)); - mail.setErrorMessage(getError(node)); - mail.setRemoteHost(getRemoteHost(node)); - mail.setRemoteAddr(getRemoteAddr(node)); - getAttributes(node, mail); - return mail; - } - - /** - * Writes the mail message to the given mail node. - * - * @param node - * mail node - * @param mail - * mail message - * @throws MessagingException - * if a messaging error occurs - * @throws RepositoryException - * if a repository error occurs - * @throws IOException - * if an IO error occurs - */ - private void setMail(Node node, Mail mail) throws MessagingException, RepositoryException, IOException { - setState(node, mail.getState()); - setLastUpdated(node, mail.getLastUpdated()); - setError(node, mail.getErrorMessage()); - setRemoteHost(node, mail.getRemoteHost()); - setRemoteAddr(node, mail.getRemoteAddr()); - setSender(node, mail.getMaybeSender()); - setRecipients(node, mail.getRecipients()); - setMessage(node, mail.getMessage()); - setAttributes(node, mail); - } - - /** - * Reads the message state from the <code>james:state</code> property. - * - * @param node - * mail node - * @return message state, or {@link Mail#DEFAULT} if not set - * @throws RepositoryException - * if a repository error occurs - */ - private String getState(Node node) throws RepositoryException { - try { - return node.getProperty("james:state").getString(); - } catch (PathNotFoundException e) { - return Mail.DEFAULT; - } - } - - /** - * Writes the message state to the <code>james:state</code> property. - * - * @param node - * mail node - * @param state - * message state - * @throws RepositoryException - * if a repository error occurs - */ - private void setState(Node node, String state) throws RepositoryException { - node.setProperty("james:state", state); - } - - /** - * Reads the update timestamp from the - * <code>jcr:content/jcr:lastModified</code> property. - * - * @param node - * mail node - * @return update timestamp - * @throws RepositoryException - * if a repository error occurs - */ - private Date getLastUpdated(Node node) throws RepositoryException { - try { - node = node.getNode("jcr:content"); - } catch (PathNotFoundException e) { - node = node.getProperty("jcr:content").getNode(); - } - return node.getProperty("jcr:lastModified").getDate().getTime(); - } - - /** - * Writes the update timestamp to the - * <code>jcr:content/jcr:lastModified</code> property. - * - * @param node - * mail node - * @param updated - * update timestamp, or <code>null</code> if not set - * @throws RepositoryException - * if a repository error occurs - */ - private void setLastUpdated(Node node, Date updated) throws RepositoryException { - try { - node = node.getNode("jcr:content"); - } catch (PathNotFoundException e) { - node = node.getProperty("jcr:content").getNode(); - } - Calendar calendar = Calendar.getInstance(); - if (updated != null) { - calendar.setTime(updated); - } - node.setProperty("jcr:lastModified", calendar); - } - - /** - * Reads the error message from the <code>james:error</code> property. - * - * @param node - * mail node - * @return error message, or <code>null</code> if not set - * @throws RepositoryException - * if a repository error occurs - */ - private String getError(Node node) throws RepositoryException { - try { - return node.getProperty("james:error").getString(); - } catch (PathNotFoundException e) { - return null; - } - } - - /** - * Writes the error message to the <code>james:error</code> property. - * - * @param node - * mail node - * @param error - * error message - * @throws RepositoryException - * if a repository error occurs - */ - private void setError(Node node, String error) throws RepositoryException { - node.setProperty("james:error", error); - } - - /** - * Reads the remote host name from the <code>james:remotehost</code> - * property. - * - * @param node - * mail node - * @return remote host name, or <code>null</code> if not set - * @throws RepositoryException - * if a repository error occurs - */ - private String getRemoteHost(Node node) throws RepositoryException { - try { - return node.getProperty("james:remotehost").getString(); - } catch (PathNotFoundException e) { - return null; - } - } - - /** - * Writes the remote host name to the <code>james:remotehost</code> - * property. - * - * @param node - * mail node - * @param host - * remote host name - * @throws RepositoryException - * if a repository error occurs - */ - private void setRemoteHost(Node node, String host) throws RepositoryException { - node.setProperty("james:remotehost", host); - } - - /** - * Reads the remote address from the <code>james:remoteaddr</code> property. - * - * @param node - * mail node - * @return remote address, or <code>null</code> if not set - * @throws RepositoryException - * if a repository error occurs - */ - private String getRemoteAddr(Node node) throws RepositoryException { - try { - return node.getProperty("james:remoteaddr").getString(); - } catch (PathNotFoundException e) { - return null; - } - } - - /** - * Writes the remote address to the <code>james:remoteaddr</code> property. - * - * @param node - * mail node - * @param addr - * remote address - * @throws RepositoryException - * if a repository error occurs - */ - private void setRemoteAddr(Node node, String addr) throws RepositoryException { - node.setProperty("james:remoteaddr", addr); - } - - /** - * Reads the envelope sender from the <code>james:sender</code> property. - * - * @param node - * mail node - * @return envelope sender, or <code>null</code> if not set - * @throws MessagingException - * if a messaging error occurs - * @throws RepositoryException - * if a repository error occurs - */ - private MailAddress getSender(Node node) throws MessagingException, RepositoryException { - try { - String sender = node.getProperty("james:sender").getString(); - return new MailAddress(sender); - } catch (PathNotFoundException e) { - return null; - } - } - - /** - * Writes the envelope sender to the <code>james:sender</code> property. - * - * @param node - * mail node - * @param sender - * envelope sender - * @throws MessagingException - * if a messaging error occurs - * @throws RepositoryException - * if a repository error occurs - */ - private void setSender(Node node, MaybeSender sender) throws RepositoryException { - node.setProperty("james:sender", sender.asString()); - } - - /** - * Reads the list of recipients from the <code>james:recipients</code> - * property. - * - * @param node - * mail node - * @return list of recipient, or an empty list if not set - * @throws MessagingException - * if a messaging error occurs - * @throws RepositoryException - * if a repository error occurs - */ - @SuppressWarnings("unchecked") - private Collection<MailAddress> getRecipients(Node node) throws MessagingException, RepositoryException { - try { - Value[] values = node.getProperty("james:recipients").getValues(); - Collection<MailAddress> recipients = new ArrayList<>(values.length); - for (Value value : values) { - recipients.add(new MailAddress(value.getString())); - } - return recipients; - } catch (PathNotFoundException e) { - return Collections.EMPTY_LIST; - } - } - - /** - * Writes the list of recipients to the <code>james:recipients</code> - * property. - * - * @param node - * mail node - * @param recipients - * list of recipient - * @throws MessagingException - * if a messaging error occurs - * @throws RepositoryException - * if a repository error occurs - */ - private void setRecipients(Node node, Collection<MailAddress> recipients) throws RepositoryException { - String[] values = new String[recipients.size()]; - Iterator<MailAddress> iterator = recipients.iterator(); - for (int i = 0; iterator.hasNext(); i++) { - values[i] = iterator.next().toString(); - } - node.setProperty("james:recipients", values); - } - - /** - * Reads the message content from the <code>jcr:content/jcr:data</code> - * binary property. - * - * @param node - * mail node - * @return mail message - * @throws MessagingException - * if a messaging error occurs - * @throws RepositoryException - * if a repository error occurs - * @throws IOException - * if an IO error occurs - */ - private MimeMessage getMessage(Node node) throws MessagingException, RepositoryException, IOException { - try { - node = node.getNode("jcr:content"); - } catch (PathNotFoundException e) { - node = node.getProperty("jcr:content").getNode(); - } - - try (InputStream stream = node.getProperty("jcr:data").getStream()) { - Properties properties = System.getProperties(); - return new MimeMessage(javax.mail.Session.getDefaultInstance(properties), stream); - } - } - - /** - * Writes the message content to the <code>jcr:content/jcr:data</code> - * binary property. - * - * @param node - * mail node - * @param message - * mail message - * @throws MessagingException - * if a messaging error occurs - * @throws RepositoryException - * if a repository error occurs - * @throws IOException - * if an IO error occurs - */ - private void setMessage(Node node, final MimeMessage message) throws RepositoryException, IOException { - try { - node = node.getNode("jcr:content"); - } catch (PathNotFoundException e) { - node = node.getProperty("jcr:content").getNode(); - } - - PipedInputStream input = new PipedInputStream(); - PipedOutputStream output = new PipedOutputStream(input); - new Thread(() -> { - try (PipedOutputStream stream = output) { - message.writeTo(stream); - } catch (Exception e) { - LOGGER.info("Exception ignored", e); - } - }).start(); - node.setProperty("jcr:data", input); - } - - /** - * Writes the mail attributes from the <code>jamesattr:*</code> property. - * - * @param node - * mail node - * @param mail - * mail message - * @throws RepositoryException - * if a repository error occurs - * @throws IOException - * if an IO error occurs - */ - private void getAttributes(Node node, Mail mail) throws RepositoryException, IOException { - PropertyIterator iterator = node.getProperties("jamesattr:*"); - while (iterator.hasNext()) { - Property property = iterator.nextProperty(); - String name = Text.unescapeIllegalJcrChars(property.getName().substring("jamesattr:".length())); - if (property.getType() == PropertyType.BINARY) { - try (InputStream input = property.getStream()) { - ObjectInputStream stream = new ObjectInputStream(input); - mail.setAttribute(name, (Serializable) stream.readObject()); - } catch (ClassNotFoundException e) { - throw new IOException(e.getMessage()); - } - } else { - mail.setAttribute(name, property.getString()); - } - } - } - - /** - * Writes the mail attributes to the <code>jamesattr:*</code> property. - * - * @param node - * mail node - * @param mail - * mail message - * @throws RepositoryException - * if a repository error occurs - * @throws IOException - * if an IO error occurs - */ - private void setAttributes(Node node, Mail mail) throws RepositoryException, IOException { - Iterator<String> iterator = mail.getAttributeNames(); - while (iterator.hasNext()) { - String name = iterator.next(); - Object value = mail.getAttribute(name); - name = "jamesattr:" + Text.escapeIllegalJcrChars(name); - if (value instanceof String || value == null) { - node.setProperty(name, (String) value); - } else { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - ObjectOutputStream output = new ObjectOutputStream(buffer); - output.writeObject(value); - output.close(); - node.setProperty(name, new ByteArrayInputStream(buffer.toByteArray())); - } - } - } - - @Override - protected void internalRemove(MailKey key) throws MessagingException { - try { - Session session = login(); - try { - String name = ISO9075.encode(Text.escapeIllegalJcrChars(key.asString())); - QueryManager manager = session.getWorkspace().getQueryManager(); - Query query = manager.createQuery("/jcr:root/" + MAIL_PATH + "//element(" + name + ",james:mail)", Query.XPATH); - NodeIterator nodes = query.execute().getNodes(); - if (nodes.hasNext()) { - while (nodes.hasNext()) { - nodes.nextNode().remove(); - } - session.save(); - LOGGER.info("Mail {} removed from repository", key); - } else { - LOGGER.warn("Mail {} not found", key); - } - } finally { - session.logout(); - } - } catch (RepositoryException e) { - throw new MessagingException("Unable to remove message: " + key, e); - } - } - - @Override - protected void internalStore(Mail mail) throws MessagingException, IOException { - try { - Session session = login(); - try { - String name = Text.escapeIllegalJcrChars(mail.getName()); - final String xpath = "/jcr:root/" + MAIL_PATH + "//element(" + name + ",james:mail)"; - - QueryManager manager = session.getWorkspace().getQueryManager(); - Query query = manager.createQuery(xpath, Query.XPATH); - NodeIterator iterator = query.execute().getNodes(); - - if (iterator.hasNext()) { - while (iterator.hasNext()) { - setMail(iterator.nextNode(), mail); - } - } else { - Node parent = session.getRootNode().getNode(MAIL_PATH); - Node node = parent.addNode(name, "james:mail"); - Node resource = node.addNode("jcr:content", "nt:resource"); - resource.setProperty("jcr:mimeType", "message/rfc822"); - setMail(node, mail); - } - session.save(); - LOGGER.info("Mail {} stored in repository", mail.getName()); - } finally { - session.logout(); - } - } catch (IOException | RepositoryException e) { - throw new MessagingException("Unable to store message: " + mail.getName(), e); - } - } - -} http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/src/main/java/org/apache/james/user/jcr/JCRUsersRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/src/main/java/org/apache/james/user/jcr/JCRUsersRepository.java b/server/data/data-jcr/src/main/java/org/apache/james/user/jcr/JCRUsersRepository.java deleted file mode 100644 index 9278341..0000000 --- a/server/data/data-jcr/src/main/java/org/apache/james/user/jcr/JCRUsersRepository.java +++ /dev/null @@ -1,410 +0,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. * - ****************************************************************/ - -package org.apache.james.user.jcr; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Locale; - -import javax.inject.Inject; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.PathNotFoundException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.HierarchicalConfiguration; -import org.apache.jackrabbit.util.ISO9075; -import org.apache.jackrabbit.util.Text; -import org.apache.james.user.api.UsersRepository; -import org.apache.james.user.api.UsersRepositoryException; -import org.apache.james.user.api.model.User; -import org.apache.james.user.jcr.model.JCRUser; -import org.apache.james.user.lib.AbstractUsersRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * {@link UsersRepository} implementation which stores users to a JCR - * {@link Repository} - * - * @Deprecated: See JAMES-2571 The JCR implementation is not enough maintained and thus will be removed from James in version 3.3.0. Please prefer using - * other MailboxManagers or contribute the JCR mailbox maintenance. - */ -@Deprecated -public class JCRUsersRepository extends AbstractUsersRepository { - private static final Logger LOGGER = LoggerFactory.getLogger(JCRUsersRepository.class); - - // TODO: Add namespacing - private static final String PASSWD_PROPERTY = "passwd"; - - private static final String USERNAME_PROPERTY = "username"; - private static final String USERS_PATH = "users"; - - private Repository repository; - private SimpleCredentials creds; - private String workspace; - - @Inject - public void setRepository(Repository repository) { - this.repository = repository; - } - - @Override - public void doConfigure(HierarchicalConfiguration config) throws ConfigurationException { - this.workspace = config.getString("workspace", null); - String username = config.getString("username", null); - String password = config.getString("password", null); - - if (username != null && password != null) { - this.creds = new SimpleCredentials(username, password.toCharArray()); - } - } - - protected String toSafeName(String key) { - return ISO9075.encode(Text.escapeIllegalJcrChars(key)); - } - - private Session login() throws RepositoryException { - return repository.login(creds, workspace); - } - - /** - * Get the user object with the specified user name. Return null if no such - * user. - * - * @param username - * the name of the user to retrieve - * @return the user being retrieved, null if the user doesn't exist - * - */ - @Override - public User getUserByName(String username) { - User user; - try { - final Session session = login(); - try { - final String name = toSafeName(username); - final String path = USERS_PATH + "/" + name; - final Node rootNode = session.getRootNode(); - - try { - final Node node = rootNode.getNode(path); - user = new JCRUser(node.getProperty(USERNAME_PROPERTY).getString(), node.getProperty(PASSWD_PROPERTY).getString()); - } catch (PathNotFoundException e) { - // user not found - user = null; - } - } finally { - session.logout(); - } - - } catch (RepositoryException e) { - LOGGER.info("Failed to add user: {}", username, e); - user = null; - } - return user; - } - - /** - * Returns the user name of the user matching name on an equalsIgnoreCase - * basis. Returns null if no match. - * - * @param name - * the name to case-correct - * @return the case-correct name of the user, null if the user doesn't exist - */ - public String getRealName(String name) { - return null; - } - - /** - * Update the repository with the specified user object. A user object with - * this username must already exist. - * - * @param user - * the user - * @throws UsersRepositoryException - * If an error occurred - */ - @Override - public void updateUser(User user) throws UsersRepositoryException { - if (user != null && user instanceof JCRUser) { - final JCRUser jcrUser = (JCRUser) user; - final String userName = jcrUser.getUserName(); - try { - final Session session = login(); - try { - final String name = toSafeName(userName); - final String path = USERS_PATH + "/" + name; - final Node rootNode = session.getRootNode(); - - try { - final String hashedSaltedPassword = jcrUser.getHashedSaltedPassword(); - rootNode.getNode(path).setProperty(PASSWD_PROPERTY, hashedSaltedPassword); - session.save(); - } catch (PathNotFoundException e) { - // user not found - LOGGER.debug("User not found"); - throw new UsersRepositoryException("User " + user.getUserName() + " not exist"); - } - } finally { - session.logout(); - } - - } catch (RepositoryException e) { - LOGGER.info("Failed to add user: {}", userName, e); - throw new UsersRepositoryException("Failed to add user: " + userName, e); - - } - } - } - - /** - * Removes a user from the repository - * - * @param username - * the user to remove from the repository - * @throws UsersRepositoryException - */ - @Override - public void removeUser(String username) throws UsersRepositoryException { - try { - final Session session = login(); - try { - final String name = toSafeName(username); - final String path = USERS_PATH + "/" + name; - try { - session.getRootNode().getNode(path).remove(); - session.save(); - } catch (PathNotFoundException e) { - // user not found - throw new UsersRepositoryException("User " + username + " not exists"); - } - } finally { - session.logout(); - } - - } catch (RepositoryException e) { - LOGGER.info("Failed to remove user: {}", username, e); - throw new UsersRepositoryException("Failed to remove user: " + username, e); - } - } - - /** - * Returns whether or not this user is in the repository - * - * @param name - * the name to check in the repository - * @return whether the user is in the repository - * @throws UsersRepositoryException - */ - @Override - public boolean contains(String name) throws UsersRepositoryException { - try { - final Session session = login(); - try { - final Node rootNode = session.getRootNode(); - final String path = USERS_PATH + "/" + toSafeName(name.toLowerCase(Locale.US)); - rootNode.getNode(path); - return true; - } finally { - session.logout(); - } - } catch (PathNotFoundException e) { - LOGGER.debug("User not found: {}", name, e); - } catch (RepositoryException e) { - throw new UsersRepositoryException("Failed to search for user: " + name, e); - - } - - return false; - } - - /** - * Test if user with name 'name' has password 'password'. - * - * @param username - * the name of the user to be tested - * @param password - * the password to be tested - * - * @return true if the test is successful, false if the user doesn't exist - * or if the password is incorrect - * @throws UsersRepositoryException - * - * @since James 1.2.2 - */ - @Override - public boolean test(String username, String password) throws UsersRepositoryException { - try { - final Session session = login(); - try { - final String name = toSafeName(username); - final String path = USERS_PATH + "/" + name; - final Node rootNode = session.getRootNode(); - - try { - final Node node = rootNode.getNode(path); - final String current = node.getProperty(PASSWD_PROPERTY).getString(); - if (current == null || current.equals("")) { - return password == null || password.equals(""); - } - final String hashPassword = JCRUser.hashPassword(username, password); - return current.equals(hashPassword); - } catch (PathNotFoundException e) { - // user not found - LOGGER.debug("User not found"); - return false; - } - } finally { - session.logout(); - } - - } catch (RepositoryException e) { - LOGGER.info("Failed to search user: {}", username, e); - throw new UsersRepositoryException("Failed to search for user: " + username, e); - } - } - - /** - * Returns a count of the users in the repository. - * - * @return the number of users in the repository - * @throws UsersRepositoryException - */ - @Override - public int countUsers() throws UsersRepositoryException { - try { - final Session session = login(); - try { - final Node rootNode = session.getRootNode(); - try { - final Node node = rootNode.getNode(USERS_PATH); - // TODO: Use query - // TODO: Use namespacing to avoid unwanted nodes - NodeIterator it = node.getNodes(); - return (int) it.getSize(); - } catch (PathNotFoundException e) { - return 0; - } - } finally { - session.logout(); - } - } catch (RepositoryException e) { - LOGGER.info("Failed to count user", e); - throw new UsersRepositoryException("Failed to count user", e); - } - } - - /** - * List users in repository. - * - * @return Iterator over a collection of Strings, each being one user in the - * repository. - * @throws UsersRepositoryException - */ - @Override - public Iterator<String> list() throws UsersRepositoryException { - final Collection<String> userNames = new ArrayList<>(); - try { - final Session session = login(); - try { - final Node rootNode = session.getRootNode(); - try { - final Node baseNode = rootNode.getNode(USERS_PATH); - // TODO: Use query - final NodeIterator it = baseNode.getNodes(); - while (it.hasNext()) { - final Node node = it.nextNode(); - try { - final String userName = node.getProperty(USERNAME_PROPERTY).getString(); - userNames.add(userName); - } catch (PathNotFoundException e) { - LOGGER.info("Node missing user name. Ignoring."); - } - } - } catch (PathNotFoundException e) { - LOGGER.info("Path not found. Forgotten to setup the repository?"); - } - } finally { - session.logout(); - } - } catch (RepositoryException e) { - LOGGER.info("Failed to list users", e); - throw new UsersRepositoryException("Failed to list users", e); - } - return userNames.iterator(); - } - - @Override - protected void doAddUser(String username, String password) throws UsersRepositoryException { - String lowerCasedUsername = username.toLowerCase(Locale.US); - if (contains(lowerCasedUsername)) { - throw new UsersRepositoryException(lowerCasedUsername + " already exists."); - } - try { - final Session session = login(); - try { - final String name = toSafeName(lowerCasedUsername); - final String path = USERS_PATH + "/" + name; - final Node rootNode = session.getRootNode(); - try { - rootNode.getNode(path); - LOGGER.info("User already exists"); - throw new UsersRepositoryException("User " + lowerCasedUsername + " already exists"); - } catch (PathNotFoundException e) { - // user does not exist - } - Node parent; - try { - parent = rootNode.getNode(USERS_PATH); - } catch (PathNotFoundException e) { - // TODO: Need to consider whether should insist that parent - // TODO: path exists. - parent = rootNode.addNode(USERS_PATH); - } - - Node node = parent.addNode(name); - node.setProperty(USERNAME_PROPERTY, lowerCasedUsername); - final String hashedPassword; - if (password == null) { - // Support easy password reset - hashedPassword = ""; - } else { - hashedPassword = JCRUser.hashPassword(lowerCasedUsername, password); - } - node.setProperty(PASSWD_PROPERTY, hashedPassword); - session.save(); - } finally { - session.logout(); - } - - } catch (RepositoryException e) { - LOGGER.info("Failed to add user: {}", lowerCasedUsername, e); - throw new UsersRepositoryException("Failed to add user: " + lowerCasedUsername, e); - } - } - -} http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/src/main/java/org/apache/james/user/jcr/model/JCRUser.java ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/src/main/java/org/apache/james/user/jcr/model/JCRUser.java b/server/data/data-jcr/src/main/java/org/apache/james/user/jcr/model/JCRUser.java deleted file mode 100644 index c40fcf5..0000000 --- a/server/data/data-jcr/src/main/java/org/apache/james/user/jcr/model/JCRUser.java +++ /dev/null @@ -1,92 +0,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. * - ****************************************************************/ - -package org.apache.james.user.jcr.model; - -import org.apache.jackrabbit.util.Text; -import org.apache.james.user.api.model.User; - -/** - * User backed by JCR data. Differs from standard James by improved hash. TODO: - * think about improving DefaultUser. - */ -public class JCRUser implements User { - - /** - * Static salt for hashing password. Modifying this value will render all - * passwords unrecognizable. - */ - public static final String SALT = "JCRUsersRepository"; - - /** - * Hashes salted password. - * - * @param username - * not null - * @param password - * not null - * @return not null - */ - public static String hashPassword(String username, String password) { - // Combine dynamic and static salt - return Text.md5(Text.md5(username + password) + SALT); - } - - private final String userName; - private String hashedSaltedPassword; - - public JCRUser(String userName, String hashedSaltedPassword) { - super(); - this.userName = userName; - this.hashedSaltedPassword = hashedSaltedPassword; - } - - @Override - public String getUserName() { - return userName; - } - - /** - * Gets salted, hashed password. - * - * @return the hashedSaltedPassword - */ - public final String getHashedSaltedPassword() { - return hashedSaltedPassword; - } - - @Override - public boolean setPassword(String newPass) { - final boolean result; - if (newPass == null) { - result = false; - } else { - hashedSaltedPassword = hashPassword(userName, newPass); - result = true; - } - return result; - } - - @Override - public boolean verifyPassword(String pass) { - final boolean result; - result = pass != null && hashedSaltedPassword.equals(hashPassword(userName, pass)); - return result; - } -} http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/src/main/resources/org/apache/james/mailbox/jcr/james.cnd ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/src/main/resources/org/apache/james/mailbox/jcr/james.cnd b/server/data/data-jcr/src/main/resources/org/apache/james/mailbox/jcr/james.cnd deleted file mode 100644 index 477f151..0000000 --- a/server/data/data-jcr/src/main/resources/org/apache/james/mailbox/jcr/james.cnd +++ /dev/null @@ -1,28 +0,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. - */ - -<james = 'http://james.apache.org/2007/jcr/'> -<jamesattr = 'http://james.apache.org/2007/jcr/attributes/'> - -[james:mail] > nt:file -- james:state (STRING) -- james:error (STRING) -- james:sender (STRING) -- james:recipients (STRING) multiple -- james:remotehost (STRING) -- james:remoteaddr (STRING) -- * (UNDEFINED) http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/src/reporting-site/site.xml ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/src/reporting-site/site.xml b/server/data/data-jcr/src/reporting-site/site.xml deleted file mode 100644 index d919164..0000000 --- a/server/data/data-jcr/src/reporting-site/site.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - 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 name="${project.name}"> - - <body> - - <menu ref="parent" /> - <menu ref="reports" /> - - </body> - -</project> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/src/test/java/org/apache/james/user/jcr/JcrUserRepositoryTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/src/test/java/org/apache/james/user/jcr/JcrUserRepositoryTest.java b/server/data/data-jcr/src/test/java/org/apache/james/user/jcr/JcrUserRepositoryTest.java deleted file mode 100644 index 142cdd5..0000000 --- a/server/data/data-jcr/src/test/java/org/apache/james/user/jcr/JcrUserRepositoryTest.java +++ /dev/null @@ -1,77 +0,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. * - ****************************************************************/ -package org.apache.james.user.jcr; - -import java.io.File; -import java.io.IOException; - -import org.apache.commons.configuration.DefaultConfigurationBuilder; -import org.apache.commons.io.FileUtils; -import org.apache.jackrabbit.core.RepositoryImpl; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.apache.james.user.lib.AbstractUsersRepository; -import org.apache.james.user.lib.AbstractUsersRepositoryTest; -import org.junit.After; -import org.junit.Before; -import org.xml.sax.InputSource; - -public class JcrUserRepositoryTest extends AbstractUsersRepositoryTest { - - private static final String JACKRABBIT_HOME = "target/jackrabbit"; - private RepositoryImpl repository; - - @Override - protected AbstractUsersRepository getUsersRepository() throws Exception { - JCRUsersRepository repos = new JCRUsersRepository(); - repos.setRepository(repository); - DefaultConfigurationBuilder config = new DefaultConfigurationBuilder(); - config.addProperty("username", "admin"); - config.addProperty("password", "test"); - repos.configure(config); - return repos; - } - - @Override - @Before - public void setUp() throws Exception { - File home = new File(JACKRABBIT_HOME); - if (home.exists()) { - delete(home); - } - RepositoryConfig config = RepositoryConfig.create(new InputSource(this.getClass().getClassLoader() - .getResourceAsStream("test-repository.xml")), JACKRABBIT_HOME); - repository = RepositoryImpl.create(config); - super.setUp(); - } - - private void delete(File file) { - try { - FileUtils.forceDelete(file); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - @After - public void tearDown() throws Exception { - super.tearDown(); - repository.shutdown(); - } -} http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/src/test/resources/log4j.properties b/server/data/data-jcr/src/test/resources/log4j.properties deleted file mode 100644 index 34f5a5f..0000000 --- a/server/data/data-jcr/src/test/resources/log4j.properties +++ /dev/null @@ -1,6 +0,0 @@ -log4j.rootLogger=WARN, A1 -log4j.appender.A1=org.apache.log4j.ConsoleAppender -log4j.appender.A1.layout=org.apache.log4j.PatternLayout - -# Print the date in ISO 8601 format -log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/data/data-jcr/src/test/resources/test-repository.xml ---------------------------------------------------------------------- diff --git a/server/data/data-jcr/src/test/resources/test-repository.xml b/server/data/data-jcr/src/test/resources/test-repository.xml deleted file mode 100644 index 592cca8..0000000 --- a/server/data/data-jcr/src/test/resources/test-repository.xml +++ /dev/null @@ -1,92 +0,0 @@ -<?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. ---> -<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN" - "http://jackrabbit.apache.org/dtd/repository-1.6.dtd"> -<!-- Example Repository Configuration File - Used by - - org.apache.jackrabbit.core.config.RepositoryConfigTest.java - - ---> -<Repository> - <!-- - virtual file system where the repository stores global state - (e.g. registered namespaces, custom node types, etc.) - --> - <FileSystem class='org.apache.jackrabbit.core.fs.mem.MemoryFileSystem'> - </FileSystem> - <!-- - security configuration - --> - <Security appName="Jackrabbit"> - <SecurityManager class="org.apache.jackrabbit.core.security.simple.SimpleSecurityManager" workspaceName="default"> - </SecurityManager> - - <AccessManager class="org.apache.jackrabbit.core.security.simple.SimpleAccessManager"> - </AccessManager> - - <LoginModule class="org.apache.jackrabbit.core.security.simple.SimpleLoginModule"> - <param name="adminId" value="admin"/> - </LoginModule> - </Security> - - <Workspaces rootPath='${rep.home}/workspaces' defaultWorkspace='default'/> - - <Workspace name='${wsp.name}'> - <FileSystem class='org.apache.jackrabbit.core.fs.mem.MemoryFileSystem'> - </FileSystem> - <!-- - persistence manager of the workspace: - class: FQN of class implementing the PersistenceManager interface - --> - <PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager"> - <param name="persistent" value="false"/> - </PersistenceManager> - - <SearchIndex class='org.apache.jackrabbit.core.query.lucene.SearchIndex'> - <param name='path' value='${wsp.home}/index'/> - <param name='textFilterClasses' value='org.apache.jackrabbit.extractor.HTMLTextExtractor,org.apache.jackrabbit.extractor.XMLTextExtractor'/> - <param name='extractorPoolSize' value='2'/> - <param name='supportHighlighting' value='true'/> - </SearchIndex> - - </Workspace> - - <!-- - Configures the versioning - --> - <Versioning rootPath='${rep.home}/version'> - <FileSystem class='org.apache.jackrabbit.core.fs.mem.MemoryFileSystem'> - </FileSystem> - - <PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager"> - <param name="persistent" value="false"/> - </PersistenceManager> - - </Versioning> - <!-- - Search index for content that is shared repository wide - (/jcr:system tree, contains mainly versions) - --> - <SearchIndex class='org.apache.jackrabbit.core.query.lucene.SearchIndex'> - <param name='path' value='${rep.home}/repository/index'/> - <param name='textFilterClasses' value='org.apache.jackrabbit.extractor.HTMLTextExtractor,org.apache.jackrabbit.extractor.XMLTextExtractor'/> - <param name='extractorPoolSize' value='2'/> - <param name='supportHighlighting' value='true'/> - </SearchIndex> - -</Repository> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/karaf/features/src/main/resources/features.xml ---------------------------------------------------------------------- diff --git a/server/karaf/features/src/main/resources/features.xml b/server/karaf/features/src/main/resources/features.xml index 081f486..e9dda48 100644 --- a/server/karaf/features/src/main/resources/features.xml +++ b/server/karaf/features/src/main/resources/features.xml @@ -151,10 +151,6 @@ </bundle> </feature> - <!--<feature name="james-server-data-jcr" version="${project.version}">--> - <!--<bundle>mvn:org.apache.james/james-server-data-jcr/${project.version}</bundle>--> - <!--</feature>--> - <feature name="james-server-data-jdbc" version="${project.version}"> <bundle>mvn:org.apache.james/james-server-data-jdbc/${project.version}</bundle> <feature version="${project.version}">james-server-lifecycle-api</feature> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/server/pom.xml ---------------------------------------------------------------------- diff --git a/server/pom.xml b/server/pom.xml index c90ea73..3d95824 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -58,7 +58,6 @@ <module>data/data-api</module> <module>data/data-cassandra</module> <module>data/data-file</module> - <module>data/data-jcr</module> <module>data/data-jdbc</module> <module>data/data-jmap</module> <module>data/data-jmap-cassandra</module> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/src/site/site.xml ---------------------------------------------------------------------- diff --git a/src/site/site.xml b/src/site/site.xml index 2135b16..4a9ac3c 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -201,7 +201,6 @@ <item name="Mailbox Cassandra" href="/mailbox/mailbox-cassandra.html" /> <item name="Mailbox Maildir" href="/mailbox/mailbox-maildir.html" /> <item name="Mailbox JPA" href="/mailbox/mailbox-jpa.html" /> - <item name="Mailbox JCR" href="/mailbox/mailbox-jcr.html" /> </item> <item name="Wiring" href="/mailbox/mailbox-spring.html" /> <item name="Download releases" href="http://james.apache.org/download.cgi" /> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/src/site/xdoc/mailbox/index.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/mailbox/index.xml b/src/site/xdoc/mailbox/index.xml index fd2ba9f..aa2d284 100644 --- a/src/site/xdoc/mailbox/index.xml +++ b/src/site/xdoc/mailbox/index.xml @@ -49,7 +49,6 @@ <li><a href="mailbox-cassandra.html">Cassandra</a></li> <li><a href="mailbox-maildir.html">Maildir</a></li> <li><a href="mailbox-jpa.html">JPA</a> </li> - <li><a href="mailbox-jcr.html">JCR</a> </li> </ul> </section> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/src/site/xdoc/mailbox/mailbox-api.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/mailbox/mailbox-api.xml b/src/site/xdoc/mailbox/mailbox-api.xml index d40aa6b..71bba1b 100644 --- a/src/site/xdoc/mailbox/mailbox-api.xml +++ b/src/site/xdoc/mailbox/mailbox-api.xml @@ -38,8 +38,7 @@ and in the Mailet container.</p> <p>Each implementation <a href="mailbox-memory.html">Memory</a>, <a href="mailbox-maildir.html">Maildir</a>, - <a href="mailbox-jpa.html">JPA</a>, - <a href="mailbox-jcr.html">JCR (Deprecated)</a>) is responsible + <a href="mailbox-jpa.html">JPA</a>) is responsible to implement the management interfaces. All "common/util" implementations reside in the <a href="mailbox-store.html">Mailbox Store</a> module.</p> </section> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/src/site/xdoc/mailbox/mailbox-jcr.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/mailbox/mailbox-jcr.xml b/src/site/xdoc/mailbox/mailbox-jcr.xml deleted file mode 100644 index 4d6a161..0000000 --- a/src/site/xdoc/mailbox/mailbox-jcr.xml +++ /dev/null @@ -1,54 +0,0 @@ -<?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. ---> -<document> - - <properties> - <title>Mailbox JCR (Deprecated)</title> - </properties> - - <body> - - <section name="Maibox JCR Responsibility"> - <div class="ui-widget"> - <div class="ui-priority-secondary ui-corner-all"> - <p> <span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span> - This implementation has been deprecated in the 3.2.0 release of James. It will be removed in the next (3.3.0) release. - We strongly encourage you to choose another mailbox implemetation (JPA for traditional SQL or Cassandra for NoSQL). - By the way, if you have some development skills and you would like to support this backend, - we will be really pleased to help you maintaining this project. - </p> - </div> - </div> - <p>This implementation stores user mailboxes using JCR (Java Content Repository) technology.</p> - <p>The default JCR provider used is - <a hfre="http://jackrabbit.apache.org/">Apache Jackrabbit</a>. - </p> - <p>It only supports the Basic capability.</p> - </section> -<!-- - <section name="Installation"> - - </section> - <section name="Mailbox JCR Classes"> - </section> ---> - </body> - -</document> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/src/site/xdoc/mailbox/mailbox-spring.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/mailbox/mailbox-spring.xml b/src/site/xdoc/mailbox/mailbox-spring.xml index 1c40755..3e37778 100644 --- a/src/site/xdoc/mailbox/mailbox-spring.xml +++ b/src/site/xdoc/mailbox/mailbox-spring.xml @@ -44,7 +44,6 @@ <ul> <li>spring-mailbox-memory.xml</li> <li>spring-mailbox-maildir.xml</li> - <li>spring-mailbox-jcr.xml</li> <li>spring-mailbox-jpa.xml</li> <li>spring-mailbox-authenticator.xml</li> <li>spring-mailbox-locker.xml</li> http://git-wip-us.apache.org/repos/asf/james-project/blob/876987c8/src/site/xdoc/mailbox/source-code.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/mailbox/source-code.xml b/src/site/xdoc/mailbox/source-code.xml index c09c2a0..2ebae12 100644 --- a/src/site/xdoc/mailbox/source-code.xml +++ b/src/site/xdoc/mailbox/source-code.xml @@ -30,8 +30,7 @@ <a href="mailbox-store.html">Mailbox Store</a>(the base and utility classes) and the different implementations we propose (<a href="mailbox-memory.html">Memory</a>, <a href="mailbox-maildir.html">Maildir</a>, - <a href="mailbox-jpa.html">JPA</a>, - <a href="mailbox-jcr.html">JCR (Deprecated)</a>). + <a href="mailbox-jpa.html">JPA</a>). </p> <p>A module for <a href="mailbox-tool.html">tooling</a> is also available. </p> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
