Author: norman
Date: Fri Oct 13 07:11:36 2006
New Revision: 463685
URL: http://svn.apache.org/viewvc?view=rev&rev=463685
Log:
First steps for VUT Service. See JAMES-582
Added:
james/server/trunk/src/java/org/apache/james/services/VirtualUserTable.java
(with props)
james/server/trunk/src/java/org/apache/james/services/VirtualUserTableManagement.java
(with props)
james/server/trunk/src/java/org/apache/james/vut/
james/server/trunk/src/java/org/apache/james/vut/AbstractVirtualUserTable.java
(with props)
james/server/trunk/src/java/org/apache/james/vut/ErrorMappingException.java
(with props)
james/server/trunk/src/java/org/apache/james/vut/InvalidMappingException.java
(with props)
james/server/trunk/src/java/org/apache/james/vut/JDBCVirtualUserTable.java
(with props)
james/server/trunk/src/test/org/apache/james/vut/
james/server/trunk/src/test/org/apache/james/vut/AbstractVirtualUserTableTest.java
(with props)
james/server/trunk/src/test/org/apache/james/vut/JDBCVirtualUserTableTest.java
(with props)
Modified:
james/server/trunk/src/conf/sqlResources.xml
james/server/trunk/src/java/org/apache/james/util/VirtualUserTableUtil.java
Modified: james/server/trunk/src/conf/sqlResources.xml
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/conf/sqlResources.xml?view=diff&rev=463685&r1=463684&r2=463685
==============================================================================
--- james/server/trunk/src/conf/sqlResources.xml (original)
+++ james/server/trunk/src/conf/sqlResources.xml Fri Oct 13 07:11:36 2006
@@ -984,7 +984,100 @@
PRIMARY KEY (ipaddress,sender,recip)
)
</sql>
+</sqlDefs>
+<!-- SQL statements for the JdbcVirtualUserTable -->
+<sqlDefs name="org.apache.james.vut.JDBCVirtualUserTable">
+
+ <!-- Statements used to check whether a particular message exists in this
repository. -->
+ <sql name="selectMappings">select VirtualUserTable.target_address from
VirtualUserTable, VirtualUserTable as VUTDomains
+where ((VirtualUserTable."user") like ? or (VirtualUserTable."user") like '\%')
+and (VirtualUserTable.domain like ?
+or (VirtualUserTable.domain like '\%' and VUTDomains.domain like ?)) </sql>
+ <sql name="deleteMapping">delete from VirtualUserTable where
VirtualUserTable."user" = ? and VirtualUserTable.domain = ? and
VirtualUserTable.target_address = ?</sql>
+ <sql name="updateMapping">update VirtualUserTable set
VirtualUserTable.target_address = ? where VirtualUserTable."user" = ? and
VirtualUserTable.domain = ? </sql>
+ <sql name="addMapping">insert into VirtualUserTable values(?,?,?) </sql>
+ <!-- Statements used to create the table associated with this class. -->
+ <sql name="createTable" db="mysql">
+ CREATE TABLE VirtualUserTable (
+ user varchar(64) NOT NULL default '',
+ domain varchar(255) NOT NULL default '',
+ target_address varchar(255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="hypersonic">
+ CREATE CACHED TABLE VirtualUserTable (
+ user varchar(64) NOT NULL default '',
+ domain varchar(255) NOT NULL default '',
+ target_address varchar(255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="hsqldb">
+ CREATE CACHED TABLE VirtualUserTable (
+ user varchar(64) NOT NULL default '',
+ domain varchar(255) NOT NULL default '',
+ target_address varchar(255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="mssql">
+ CREATE TABLE [VirtualUserTable] (
+ [user] [varchar] (64) NOT NULL default '',
+ [domain] [varchar] (255) NOT NULL default '',
+ [target_address] [varchar] (255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="oracle">
+ CREATE TABLE VirtualUserTable (
+ user varchar2(64) NOT NULL default '',
+ domain varchar2(255) NOT NULL default '',
+ target_address varchar2(255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="postgresql">
+ CREATE TABLE VirtualUserTable (
+ user varchar(64) NOT NULL default '',
+ domain varchar(255) NOT NULL default '',
+ target_address varchar(255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="sapdb">
+ CREATE TABLE VirtualUserTable (
+ user varchar(64) NOT NULL default '',
+ domain varchar(255) NOT NULL default '',
+ target_address varchar(255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="db2">
+ CREATE TABLE VirtualUserTable (
+ user varchar(64) NOT NULL default '',
+ domain varchar(255) NOT NULL default '',
+ target_address varchar(255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="ingres">
+ CREATE TABLE VirtualUserTable (
+ user varchar(64) NOT NULL default '',
+ domain varchar(255) NOT NULL default '',
+ target_address varchar(255) NOT NULL default '',
+ PRIMARY KEY (user,domain)
+ )
+ </sql>
+ <sql name="createTable" db="derby">
+ CREATE TABLE VirtualUserTable (
+ "user" varchar (64) NOT NULL default '',
+ domain varchar (255) NOT NULL default '',
+ target_address varchar (255) NOT NULL default '',
+ PRIMARY KEY ("user",domain)
+ )
+ </sql>
</sqlDefs>
</sqlResources>
Added:
james/server/trunk/src/java/org/apache/james/services/VirtualUserTable.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/services/VirtualUserTable.java?view=auto&rev=463685
==============================================================================
--- james/server/trunk/src/java/org/apache/james/services/VirtualUserTable.java
(added)
+++ james/server/trunk/src/java/org/apache/james/services/VirtualUserTable.java
Fri Oct 13 07:11:36 2006
@@ -0,0 +1,41 @@
+/****************************************************************
+ * 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.services;
+
+import java.util.Collection;
+
+import org.apache.james.vut.ErrorMappingException;
+
+public interface VirtualUserTable {
+
+ public static final String ROLE =
"org.apache.james.services.VirtualUserTable";
+
+ /**
+ * Return the mapped MailAddress for the given address. Return null if no
+ * matched mapping was found
+ *
+ * @param mailaddress the MailAddress
+ * @return the mapped mailAddress
+ * @throws ErrorMappingException
+ */
+ public Collection getMappings(String user, String domain) throws
ErrorMappingException;
+}
Propchange:
james/server/trunk/src/java/org/apache/james/services/VirtualUserTable.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
james/server/trunk/src/java/org/apache/james/services/VirtualUserTableManagement.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/services/VirtualUserTableManagement.java?view=auto&rev=463685
==============================================================================
---
james/server/trunk/src/java/org/apache/james/services/VirtualUserTableManagement.java
(added)
+++
james/server/trunk/src/java/org/apache/james/services/VirtualUserTableManagement.java
Fri Oct 13 07:11:36 2006
@@ -0,0 +1,36 @@
+/****************************************************************
+ * 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.services;
+
+import org.apache.james.vut.InvalidMappingException;
+
+public interface VirtualUserTableManagement extends VirtualUserTable{
+
+ public static final String ROLE =
"org.apache.james.services.VirtualUserTableManagement";
+
+ public boolean addRegexMapping(String user, String domain, String regex)
throws InvalidMappingException;
+ public boolean removeRegexMapping(String user,String domain, String regex);
+ public boolean addAddressMapping(String user, String domain, String
address) throws InvalidMappingException;
+ public boolean removeAddressMapping(String user,String domain, String
address);
+ public boolean addErrorMapping(String user, String domain, String error)
throws InvalidMappingException;
+ public boolean removeErrorMapping(String user,String domain, String error);
+}
Propchange:
james/server/trunk/src/java/org/apache/james/services/VirtualUserTableManagement.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
james/server/trunk/src/java/org/apache/james/util/VirtualUserTableUtil.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/util/VirtualUserTableUtil.java?view=diff&rev=463685&r1=463684&r2=463685
==============================================================================
--- james/server/trunk/src/java/org/apache/james/util/VirtualUserTableUtil.java
(original)
+++ james/server/trunk/src/java/org/apache/james/util/VirtualUserTableUtil.java
Fri Oct 13 07:11:36 2006
@@ -21,6 +21,8 @@
package org.apache.james.util;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
@@ -56,6 +58,7 @@
String result = null;
+ //TODO: Throw exception on invalid syntax ?
int msgPos = targetString.indexOf(':', "regex:".length() + 1);
// log("regex: targetString = " + targetString);
@@ -143,4 +146,22 @@
}
return mappings;
}
+
+
+ /**
+ * Return a Collection which holds the extracted mappings of the given
String
+ *
+ * @param rawMapping
+ * @return
+ */
+ public static Collection getMappings(String rawMapping) {
+ ArrayList map = new ArrayList();
+ StringTokenizer tokenizer = new StringTokenizer(rawMapping,
+ VirtualUserTableUtil.getSeparator(rawMapping));
+
+ while (tokenizer.hasMoreTokens()) {
+ map.add(tokenizer.nextToken().trim());
+ }
+ return map;
+ }
}
Added:
james/server/trunk/src/java/org/apache/james/vut/AbstractVirtualUserTable.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/vut/AbstractVirtualUserTable.java?view=auto&rev=463685
==============================================================================
---
james/server/trunk/src/java/org/apache/james/vut/AbstractVirtualUserTable.java
(added)
+++
james/server/trunk/src/java/org/apache/james/vut/AbstractVirtualUserTable.java
Fri Oct 13 07:11:36 2006
@@ -0,0 +1,294 @@
+/****************************************************************
+ * 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.vut;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.mail.internet.ParseException;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.james.services.VirtualUserTable;
+import org.apache.james.services.VirtualUserTableManagement;
+import org.apache.james.util.VirtualUserTableUtil;
+import org.apache.mailet.MailAddress;
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.Perl5Compiler;
+
+public abstract class AbstractVirtualUserTable extends AbstractLogEnabled
+ implements VirtualUserTable, VirtualUserTableManagement {
+
+ /**
+ * @see
org.apache.james.services.VirtualUserTable#getMapping(org.apache.mailet.MailAddress)
+ */
+ public Collection getMappings(String user,String domain) throws
ErrorMappingException {
+ Collection mappings = new ArrayList();
+
+ String targetString = mapAddress(user, domain);
+
+
+ // Only non-null mappings are translated
+ if (targetString != null) {
+ if (targetString.startsWith("error:")) {
+ throw new
ErrorMappingException(targetString.substring("error:".length()));
+
+ } else {
+ Iterator map=
VirtualUserTableUtil.getMappings(targetString).iterator();
+
+ while (map.hasNext()) {
+ String target;
+ String targetAddress = map.next().toString();
+
+ if (targetAddress.startsWith("regex:")) {
+ try {
+ targetAddress = VirtualUserTableUtil.regexMap(new
MailAddress(user,domain), targetAddress);
+ } catch (MalformedPatternException e) {
+ getLogger().error("Exception during regexMap
processing: ", e);
+ } catch (ParseException e) {
+ // should never happen
+ }
+
+ if (targetAddress == null) continue;
+ }
+
+ if (targetAddress.indexOf('@') < 0) {
+ target = targetAddress + "@localhost";
+ } else {
+ target = targetAddress;
+ }
+
+ // add mapping
+ mappings.add(target);
+
+ StringBuffer buf = new StringBuffer().append("Valid
virtual user mapping ")
+
.append(user).append("@").append(domain)
+ .append(" to
").append(targetAddress);
+ getLogger().debug(buf.toString());
+
+ }
+ }
+ }
+ return mappings;
+ }
+
+ /**
+ * @see
org.apache.james.services.VirtualUserTableManagement#addRegexMapping(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ public boolean addRegexMapping(String user, String domain, String regex)
throws InvalidMappingException {
+ // TODO: More logging
+
+ if (validUserString(user) == false) {
+ throw new InvalidMappingException("Invalid user: " + user);
+ }
+ if(validDomainString(domain) == false) {
+ throw new InvalidMappingException("Invalid domain: " + domain);
+ }
+
+ try {
+ new Perl5Compiler().compile(regex);
+ } catch (MalformedPatternException e) {
+ throw new InvalidMappingException("Invalid regex: " + regex);
+ }
+ return addMappingInternal(user,domain,"regex:" + regex);
+ }
+
+
+ /**
+ * @see
org.apache.james.services.VirtualUserTableManagement#removeRegexMapping(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ public boolean removeRegexMapping(String user, String domain, String
regex) {
+ // TODO: More logging
+
+ return removeMappingInternal(user,domain,"regex:" + regex);
+ }
+
+ /**
+ * @see
org.apache.james.services.VirtualUserTableManagement#addAddressMapping(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ public boolean addAddressMapping(String user, String domain, String
address) throws InvalidMappingException {
+ // TODO: More logging
+
+ if (validUserString(user) == false) {
+ throw new InvalidMappingException("Invalid user: " + user);
+ }
+ if(validDomainString(domain) == false) {
+ throw new InvalidMappingException("Invalid domain: " + domain);
+ }
+
+ if (address.indexOf('@') < 0) {
+ address = address + "@localhost";
+ }
+ try {
+ new MailAddress(address);
+ } catch (ParseException e) {
+ throw new InvalidMappingException("Invalid emailAddress: " +
address);
+ }
+ return addMappingInternal(user,domain, address);
+ }
+
+ /**
+ * @see
org.apache.james.services.VirtualUserTableManagement#removeAddressMapping(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ public boolean removeAddressMapping(String user, String domain, String
address) {
+ // TODO: More logging
+
+ if (address.indexOf('@') < 0) {
+ address = address + "@localhost";
+ }
+ return removeMappingInternal(user,domain,address);
+ }
+
+ /**
+ * @throws InvalidMappingException
+ * @see
org.apache.james.services.VirtualUserTableManagement#addErrorMapping(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ public boolean addErrorMapping(String user, String domain, String error)
throws InvalidMappingException {
+ // TODO: More logging
+
+ if (validUserString(user) == false) {
+ throw new InvalidMappingException("Invalid user: " + user);
+ }
+ if(validDomainString(domain) == false) {
+ throw new InvalidMappingException("Invalid domain: " + domain);
+ }
+
+ return addMappingInternal(user,domain, "error:" + error);
+ }
+
+ /**
+ * @see
org.apache.james.services.VirtualUserTableManagement#removeErrorMapping(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ public boolean removeErrorMapping(String user, String domain, String
error) {
+ // TODO: More logging
+
+ return removeMappingInternal(user,domain,"error:" + error);
+ }
+
+
+ /**
+ * Convert a raw mapping String to a Collection
+ *
+ * @param rawMapping the mapping Strin
+ * @return map a collection which holds all mappings
+ */
+ protected ArrayList mappingToColletion(String rawMapping) {
+ ArrayList map = new ArrayList();
+ StringTokenizer tokenizer = new StringTokenizer(rawMapping,
+ VirtualUserTableUtil.getSeparator(rawMapping));
+
+ while (tokenizer.hasMoreTokens()) {
+ map.add(tokenizer.nextToken().trim());
+ }
+ return map;
+ }
+
+
+ /**
+ * Convert a Collection which holds mappings to a raw mapping String
+ *
+ * @param map the Collection
+ * @return mapping the mapping String
+ */
+ protected String CollectionToMapping(Collection map) {
+ StringBuffer mapping = new StringBuffer();
+
+ Iterator mappings = map.iterator();
+
+ while (mappings.hasNext()) {
+ mapping.append(mappings.next());
+
+ if (mappings.hasNext()) {
+ mapping.append(";");
+ }
+ }
+
+ return mapping.toString();
+
+ }
+
+ /**
+ * Return true if the userString is valid
+ * TODO: More checkin ?
+ *
+ * @param user the userString
+ * @return true of false
+ */
+ private boolean validUserString(String user) {
+ if(user.endsWith("@%") || user.indexOf("@") < 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return true if the domainString is valid
+ * TODO: More checkin ?
+ *
+ * @param domain the domainString
+ * @return true of false
+ */
+ private boolean validDomainString(String domain) {
+ if (domain.startsWith("%@") || domain.indexOf("@") < 0) {
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Override to map virtual recipients to real recipients, both local and
non-local.
+ * Each key in the provided map corresponds to a potential virtual
recipient, stored as
+ * a <code>MailAddress</code> object.
+ *
+ * Translate virtual recipients to real recipients by mapping a string
containing the
+ * address of the real recipient as a value to a key. Leave the value
<code>null<code>
+ * if no mapping should be performed. Multiple recipients may be specified
by delineating
+ * the mapped string with commas, semi-colons or colons.
+ *
+ * @param recipient the mapping of virtual to real recipients, as
+ * <code>MailAddress</code>es to <code>String</code>s.
+ */
+ protected abstract String mapAddress(String user, String domain);
+
+ /**
+ * Add new mapping
+ *
+ * @param user the user
+ * @param domain the domain
+ * @param mapping the mapping
+ * @return true if successfully
+ */
+ public abstract boolean addMappingInternal(String user, String domain,
String mapping);
+
+ /**
+ * Remove mapping
+ *
+ * @param user the user
+ * @param domain the domain
+ * @param mapping the mapping
+ * @return true if successfully
+ */
+ public abstract boolean removeMappingInternal(String user, String domain,
String mapping);
+
+}
Propchange:
james/server/trunk/src/java/org/apache/james/vut/AbstractVirtualUserTable.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
james/server/trunk/src/java/org/apache/james/vut/ErrorMappingException.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/vut/ErrorMappingException.java?view=auto&rev=463685
==============================================================================
--- james/server/trunk/src/java/org/apache/james/vut/ErrorMappingException.java
(added)
+++ james/server/trunk/src/java/org/apache/james/vut/ErrorMappingException.java
Fri Oct 13 07:11:36 2006
@@ -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.vut;
+
+public class ErrorMappingException extends Exception {
+
+ public ErrorMappingException(String string) {
+ super(string);
+ }
+
+}
Propchange:
james/server/trunk/src/java/org/apache/james/vut/ErrorMappingException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
james/server/trunk/src/java/org/apache/james/vut/InvalidMappingException.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/vut/InvalidMappingException.java?view=auto&rev=463685
==============================================================================
---
james/server/trunk/src/java/org/apache/james/vut/InvalidMappingException.java
(added)
+++
james/server/trunk/src/java/org/apache/james/vut/InvalidMappingException.java
Fri Oct 13 07:11:36 2006
@@ -0,0 +1,30 @@
+/****************************************************************
+ * 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.vut;
+
+public class InvalidMappingException extends Exception {
+
+ public InvalidMappingException(String string) {
+ super(string);
+ }
+
+}
Propchange:
james/server/trunk/src/java/org/apache/james/vut/InvalidMappingException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
james/server/trunk/src/java/org/apache/james/vut/JDBCVirtualUserTable.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/vut/JDBCVirtualUserTable.java?view=auto&rev=463685
==============================================================================
--- james/server/trunk/src/java/org/apache/james/vut/JDBCVirtualUserTable.java
(added)
+++ james/server/trunk/src/java/org/apache/james/vut/JDBCVirtualUserTable.java
Fri Oct 13 07:11:36 2006
@@ -0,0 +1,413 @@
+/****************************************************************
+ * 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.vut;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.cornerstone.services.datasources.DataSourceSelector;
+import org.apache.avalon.excalibur.datasource.DataSourceComponent;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.james.services.FileSystem;
+import org.apache.james.util.JDBCUtil;
+import org.apache.james.util.SqlResources;
+
+public class JDBCVirtualUserTable extends AbstractVirtualUserTable implements
Configurable,Serviceable, Initializable{
+
+ private DataSourceSelector datasources = null;
+ private DataSourceComponent dataSourceComponent = null;
+ private String tableName = null;
+ private String dataSourceName = null;
+
+ /**
+ * Contains all of the sql strings for this component.
+ */
+ protected SqlResources sqlQueries;
+
+ /**
+ * The name of the SQL configuration file to be used to configure this
repository.
+ */
+ private String sqlFileName;
+
+ private FileSystem fileSystem;
+
+ protected String datasourceName;
+
+
+ /**
+ * @see
org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+ */
+ public void service(ServiceManager arg0) throws ServiceException {
+ datasources =
(DataSourceSelector)arg0.lookup(DataSourceSelector.ROLE);
+ setFileSystem((FileSystem) arg0.lookup(FileSystem.ROLE));
+ }
+
+ /**
+ * @see
org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+ */
+ public void configure(Configuration arg0) throws ConfigurationException {
+ String destination = arg0.getAttribute("destinationURL");
+ // normalize the destination, to simplify processing.
+ if ( ! destination.endsWith("/") ) {
+ destination += "/";
+ }
+ // Parse the DestinationURL for the name of the datasource,
+ // the table to use, and the (optional) repository Key.
+ // Split on "/", starting after "db://"
+ List urlParams = new ArrayList();
+ int start = 5;
+
+ int end = destination.indexOf('/', start);
+ while ( end > -1 ) {
+ urlParams.add(destination.substring(start, end));
+ start = end + 1;
+ end = destination.indexOf('/', start);
+ }
+
+ // Build SqlParameters and get datasource name from URL parameters
+ if (urlParams.size() == 0) {
+ StringBuffer exceptionBuffer =
+ new StringBuffer(256)
+ .append("Malformed destinationURL - Must be of the
format '")
+
.append("db://<data-source>[/<table>[/<repositoryName>]]'. Was passed ")
+ .append(arg0.getAttribute("destinationURL"));
+ throw new ConfigurationException(exceptionBuffer.toString());
+ }
+ if (urlParams.size() >= 1) {
+ dataSourceName = (String)urlParams.get(0);
+ }
+ if (urlParams.size() >= 2) {
+ tableName = (String)urlParams.get(1);
+ }
+
+
+ if (getLogger().isDebugEnabled()) {
+ StringBuffer logBuffer =
+ new StringBuffer(128)
+ .append("Parsed URL: table = '")
+ .append(tableName)
+ .append("'");
+ getLogger().debug(logBuffer.toString());
+ }
+
+ sqlFileName = arg0.getChild("sqlFile").getValue();
+ if (!sqlFileName.startsWith("file://")) {
+ throw new ConfigurationException
+ ("Malformed sqlFile - Must be of the format
'file://<filename>'.");
+ }
+ }
+
+ /**
+ * @see org.apache.avalon.framework.activity.Initializable#initialize()
+ */
+ public void initialize() throws Exception {
+
+ setDataSourceComponent((DataSourceComponent)
datasources.select(dataSourceName));
+
+ StringBuffer logBuffer = null;
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.getClass().getName() + ".initialize()");
+ }
+
+ // Test the connection to the database, by getting the
DatabaseMetaData.
+ Connection conn = dataSourceComponent.getConnection();
+ PreparedStatement createStatement = null;
+
+ try {
+ // Initialise the sql strings.
+
+ File sqlFile = null;
+ try {
+ sqlFile = fileSystem.getFile(sqlFileName);
+ sqlFileName = null;
+ } catch (Exception e) {
+ getLogger().fatalError(e.getMessage(), e);
+ throw e;
+ }
+
+ if (getLogger().isDebugEnabled()) {
+ logBuffer =
+ new StringBuffer(128)
+ .append("Reading SQL resources from file: ")
+ .append(sqlFile.getAbsolutePath())
+ .append(", section ")
+ .append(this.getClass().getName())
+ .append(".");
+ getLogger().debug(logBuffer.toString());
+ }
+
+ // Build the statement parameters
+ Map sqlParameters = new HashMap();
+ if (tableName != null) {
+ sqlParameters.put("table", tableName);
+ }
+
+ sqlQueries = new SqlResources();
+ sqlQueries.init(sqlFile, this.getClass().getName(),
+ conn, sqlParameters);
+
+ // Check if the required table exists. If not, create it.
+ DatabaseMetaData dbMetaData = conn.getMetaData();
+ // Need to ask in the case that identifiers are stored, ask the
DatabaseMetaInfo.
+ // Try UPPER, lower, and MixedCase, to see if the table is there.
+
+ if (!(theJDBCUtil.tableExists(dbMetaData, tableName))) {
+
+ // Users table doesn't exist - create it.
+ createStatement =
+
conn.prepareStatement(sqlQueries.getSqlString("createTable", true));
+ createStatement.execute();
+
+ if (getLogger().isInfoEnabled()) {
+ logBuffer =
+ new StringBuffer(64)
+ .append("JdbcVirtalUserTable: Created table '")
+ .append(tableName)
+ .append("'.");
+ getLogger().info(logBuffer.toString());
+ }
+ }
+
+
+ } finally {
+ theJDBCUtil.closeJDBCStatement(createStatement);
+ theJDBCUtil.closeJDBCConnection(conn);
+ }
+ }
+
+ /**
+ * The JDBCUtil helper class
+ */
+ private final JDBCUtil theJDBCUtil = new JDBCUtil() {
+ protected void delegatedLog(String logString) {
+ getLogger().debug("JDBCVirtualUserTable: " + logString);
+ }
+ };
+
+
+ public void setDataSourceComponent(DataSourceComponent
dataSourceComponent) {
+ this.dataSourceComponent = dataSourceComponent;
+ }
+
+
+ public void setFileSystem(FileSystem fileSystem) {
+ this.fileSystem = fileSystem;
+ }
+
+ /**
+ * @see
org.apache.james.vut.AbstractVirtualUserTable#mapAddress(java.lang.String,
java.lang.String)
+ */
+ public String mapAddress(String user, String domain) {
+ Connection conn = null;
+ PreparedStatement mappingStmt = null;
+ try {
+ conn = dataSourceComponent.getConnection();
+ mappingStmt =
conn.prepareStatement(sqlQueries.getSqlString("selectMappings", true));
+
+ ResultSet mappingRS = null;
+ try {
+ mappingStmt.setString(1, user);
+ mappingStmt.setString(2, domain);
+ mappingStmt.setString(3, domain);
+ mappingRS = mappingStmt.executeQuery();
+ if (mappingRS.next()) {
+ return mappingRS.getString(1);
+ }
+ } finally {
+ theJDBCUtil.closeJDBCResultSet(mappingRS);
+ }
+
+ } catch (SQLException sqle) {
+ System.out.println("SSQL:"+
sqlQueries.getSqlString("selectMappings", true));
+ getLogger().error("Error accessing database", sqle);
+ } finally {
+ theJDBCUtil.closeJDBCStatement(mappingStmt);
+ theJDBCUtil.closeJDBCConnection(conn);
+ }
+ return null;
+ }
+
+ /**
+ * @see
org.apache.james.vut.AbstractVirtualUserTable#removeRegexMappingInternal(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ public boolean removeMappingInternal(String user, String domain, String
regex) {
+ String mapping = mapAddress(user,domain);
+ if (mapping != null) {
+ ArrayList map = mappingToColletion(mapping);
+ map.remove(regex);
+
+ if (map.size() == 0) {
+ return removeMapping(user,domain,regex);
+ } else {
+ return updateMapping(user,domain,CollectionToMapping(map));
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * @see
org.apache.james.vut.AbstractVirtualUserTable#addRegexMappingInternal(java.lang.String,
java.lang.String, java.lang.String)
+ */
+ public boolean addMappingInternal(String user, String domain, String
regex) {
+ String mapping = mapAddress(user,domain);
+ if (mapping != null) {
+ ArrayList map = mappingToColletion(mapping);
+ map.add(regex);
+
+ return updateMapping(user,domain,CollectionToMapping(map));
+ }
+ return addMapping(user,domain,regex);
+ }
+
+ /**
+ * Update the mapping for the given user and domain
+ *
+ * @param user the user
+ * @param domain the domain
+ * @param mapping the mapping
+ * @return true if update was successfully
+ */
+ private boolean updateMapping(String user, String domain, String mapping) {
+ Connection conn = null;
+ PreparedStatement mappingStmt = null;
+
+ try {
+ conn = dataSourceComponent.getConnection();
+ mappingStmt = conn.prepareStatement(sqlQueries.getSqlString(
+ "updateMapping", true));
+
+ ResultSet mappingRS = null;
+ try {
+ mappingStmt.setString(1, mapping);
+ mappingStmt.setString(2, user);
+ mappingStmt.setString(3, domain);
+ if (mappingStmt.executeUpdate()> 0) {
+ return true;
+ }
+ } finally {
+ theJDBCUtil.closeJDBCResultSet(mappingRS);
+ }
+
+ } catch (SQLException sqle) {
+ getLogger().error("Error accessing database", sqle);
+ } finally {
+ theJDBCUtil.closeJDBCStatement(mappingStmt);
+ theJDBCUtil.closeJDBCConnection(conn);
+ }
+ return false;
+ }
+
+
+ /**
+ * Remove a mapping for the given user and domain
+ *
+ * @param user the user
+ * @param domain the domain
+ * @param mapping the mapping
+ * @return true if succesfully
+ */
+ private boolean removeMapping(String user, String domain, String mapping) {
+ Connection conn = null;
+ PreparedStatement mappingStmt = null;
+
+ try {
+ conn = dataSourceComponent.getConnection();
+ mappingStmt = conn.prepareStatement(sqlQueries.getSqlString(
+ "deleteMapping", true));
+
+ ResultSet mappingRS = null;
+ try {
+ mappingStmt.setString(1, user);
+ mappingStmt.setString(2, domain);
+ mappingStmt.setString(3, mapping);
+ if(mappingStmt.executeUpdate() > 0) {
+ return true;
+ }
+ } finally {
+ theJDBCUtil.closeJDBCResultSet(mappingRS);
+ }
+
+ } catch (SQLException sqle) {
+ getLogger().error("Error accessing database", sqle);
+ } finally {
+ theJDBCUtil.closeJDBCStatement(mappingStmt);
+ theJDBCUtil.closeJDBCConnection(conn);
+ }
+ return false;
+ }
+
+ /**
+ * Add mapping for given user and domain
+ *
+ * @param user the user
+ * @param domain the domain
+ * @param mapping the mapping
+ * @return true if successfully
+ */
+ private boolean addMapping(String user, String domain, String mapping) {
+ Connection conn = null;
+ PreparedStatement mappingStmt = null;
+
+ try {
+ conn = dataSourceComponent.getConnection();
+ mappingStmt = conn.prepareStatement(sqlQueries.getSqlString(
+ "addMapping", true));
+
+ ResultSet mappingRS = null;
+ try {
+ mappingStmt.setString(1, user);
+ mappingStmt.setString(2, domain);
+ mappingStmt.setString(3, mapping);
+ if(mappingStmt.executeUpdate() >0) {
+ return true;
+ }
+ } finally {
+ theJDBCUtil.closeJDBCResultSet(mappingRS);
+ }
+
+ } catch (SQLException sqle) {
+ getLogger().error("Error accessing database", sqle);
+ } finally {
+ theJDBCUtil.closeJDBCStatement(mappingStmt);
+ theJDBCUtil.closeJDBCConnection(conn);
+ }
+ return false;
+ }
+
+}
+
Propchange:
james/server/trunk/src/java/org/apache/james/vut/JDBCVirtualUserTable.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
james/server/trunk/src/test/org/apache/james/vut/AbstractVirtualUserTableTest.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/test/org/apache/james/vut/AbstractVirtualUserTableTest.java?view=auto&rev=463685
==============================================================================
---
james/server/trunk/src/test/org/apache/james/vut/AbstractVirtualUserTableTest.java
(added)
+++
james/server/trunk/src/test/org/apache/james/vut/AbstractVirtualUserTableTest.java
Fri Oct 13 07:11:36 2006
@@ -0,0 +1,142 @@
+/****************************************************************
+ * 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.vut;
+
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.james.services.VirtualUserTableManagement;
+
+import junit.framework.TestCase;
+
+public abstract class AbstractVirtualUserTableTest extends TestCase {
+
+ protected VirtualUserTableManagement virtualUserTable;
+ protected void setUp() throws Exception {
+ try {
+ virtualUserTable = getVirtalUserTable();
+ } catch (Exception e) {
+ tearDown();
+ throw new Exception(e);
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ ContainerUtil.dispose(virtualUserTable);
+ }
+
+ protected abstract VirtualUserTableManagement getVirtalUserTable() throws
ServiceException, ConfigurationException, Exception;
+
+ public void testStoreAndRetrieveRegexMapping() throws
ErrorMappingException {
+
+ String user = "test";
+ String domain = "localhost";
+ String regex = "(.*):[EMAIL PROTECTED]";
+ String regex2 = "(.+):[EMAIL PROTECTED]";
+ String invalidRegex = ".*):";
+ boolean catched = false;
+ try {
+
+ assertTrue("No mapping",virtualUserTable.getMappings(user,
domain).isEmpty());
+
+ assertTrue("Added virtual mapping",
virtualUserTable.addRegexMapping(user, domain, regex));
+ assertTrue("Added virtual mapping",
virtualUserTable.addRegexMapping(user, domain, regex2));
+
+ assertTrue("Two mappings",virtualUserTable.getMappings(user,
domain).size() == 2);
+
+ assertTrue("remove virtual mapping",
virtualUserTable.removeRegexMapping(user, domain, regex));
+
+ try {
+ assertTrue("Added virtual mapping",
virtualUserTable.addRegexMapping(user, domain, invalidRegex));
+ } catch (InvalidMappingException e) {
+ catched = true;
+ }
+ assertTrue("Invalid Mapping throw exception" , catched);
+
+ assertTrue("remove virtual mapping",
virtualUserTable.removeRegexMapping(user, domain, regex2));
+ } catch (InvalidMappingException e) {
+ fail("Storing failed");
+ }
+
+ }
+
+ public void testStoreAndRetrieveAddressMapping() throws
ErrorMappingException {
+
+ String user = "test";
+ String domain = "localhost";
+ String address = "[EMAIL PROTECTED]";
+ String address2 = "[EMAIL PROTECTED]";
+ String invalidAddress= "[EMAIL PROTECTED]:";
+ boolean catched = false;
+ try {
+
+ assertTrue("No mapping",virtualUserTable.getMappings(user,
domain).isEmpty());
+
+ assertTrue("Added virtual mapping",
virtualUserTable.addAddressMapping(user, domain, address));
+ assertTrue("Added virtual mapping",
virtualUserTable.addAddressMapping(user, domain, address2));
+
+ assertTrue("Two mappings",virtualUserTable.getMappings(user,
domain).size() == 2);
+
+ assertTrue("remove virtual mapping",
virtualUserTable.removeAddressMapping(user, domain, address));
+
+ try {
+ assertTrue("Added virtual mapping",
virtualUserTable.addAddressMapping(user, domain, invalidAddress));
+ } catch (InvalidMappingException e) {
+ catched = true;
+ }
+ assertTrue("Invalid Mapping throw exception" , catched);
+
+ assertTrue("remove virtual mapping",
virtualUserTable.removeAddressMapping(user, domain, address2));
+ } catch (InvalidMappingException e) {
+ fail("Storing failed");
+ }
+
+ }
+
+ public void testStoreAndRetrieveErrorMapping() throws
ErrorMappingException {
+
+ String user = "test";
+ String domain = "localhost";
+ String error = "Bounce!";
+ boolean catched = false;
+ try {
+
+ assertTrue("No mapping",virtualUserTable.getMappings(user,
domain).isEmpty());
+
+ assertTrue("Added virtual mapping",
virtualUserTable.addErrorMapping(user, domain, error));
+
+ try {
+ virtualUserTable.getMappings(user, domain);
+ } catch (ErrorMappingException e) {
+ catched = true;
+ }
+ assertTrue("Error Mapping throw exception" , catched);
+
+ assertTrue("remove virtual mapping",
virtualUserTable.removeErrorMapping(user, domain, error));
+ } catch (InvalidMappingException e) {
+ fail("Storing failed");
+ }
+
+ }
+
+}
Propchange:
james/server/trunk/src/test/org/apache/james/vut/AbstractVirtualUserTableTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
james/server/trunk/src/test/org/apache/james/vut/JDBCVirtualUserTableTest.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/src/test/org/apache/james/vut/JDBCVirtualUserTableTest.java?view=auto&rev=463685
==============================================================================
---
james/server/trunk/src/test/org/apache/james/vut/JDBCVirtualUserTableTest.java
(added)
+++
james/server/trunk/src/test/org/apache/james/vut/JDBCVirtualUserTableTest.java
Fri Oct 13 07:11:36 2006
@@ -0,0 +1,37 @@
+package org.apache.james.vut;
+
+import org.apache.avalon.cornerstone.services.datasources.DataSourceSelector;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.configuration.DefaultConfiguration;
+import org.apache.avalon.framework.service.DefaultServiceManager;
+import org.apache.avalon.framework.service.ServiceException;
+
+import org.apache.james.services.FileSystem;
+
+import org.apache.james.services.VirtualUserTableManagement;
+import org.apache.james.test.mock.avalon.MockLogger;
+
+import org.apache.james.test.mock.james.MockFileSystem;
+import org.apache.james.test.mock.util.AttrValConfiguration;
+import org.apache.james.test.util.Util;
+
+public class JDBCVirtualUserTableTest extends AbstractVirtualUserTableTest {
+
+ protected VirtualUserTableManagement getVirtalUserTable() throws
ServiceException, ConfigurationException, Exception {
+ DefaultServiceManager serviceManager = new DefaultServiceManager();
+ serviceManager.put(FileSystem.ROLE, new MockFileSystem());
+ serviceManager.put(DataSourceSelector.ROLE,
Util.getDataSourceSelector());
+ JDBCVirtualUserTable mr = new JDBCVirtualUserTable();
+
+
+ mr.enableLogging(new MockLogger());
+ DefaultConfiguration defaultConfiguration = new
DefaultConfiguration("ReposConf");
+
defaultConfiguration.setAttribute("destinationURL","db://maildb/virtualusertable");
+ defaultConfiguration.addChild(new
AttrValConfiguration("sqlFile","file://conf/sqlResources.xml"));
+ //defaultConfiguration.setAttribute("type","MAIL");
+ mr.service(serviceManager);
+ mr.configure(defaultConfiguration);
+ mr.initialize();
+ return mr;
+ }
+}
Propchange:
james/server/trunk/src/test/org/apache/james/vut/JDBCVirtualUserTableTest.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]