Author: norman Date: Wed Feb 10 13:52:52 2010 New Revision: 908503 URL: http://svn.apache.org/viewvc?rev=908503&view=rev Log: JPAUsersRepository is now usable in james
Modified: james/server/trunk/jpa-store/pom.xml james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUser.java james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUsersRepository.java james/server/trunk/jpa-store/src/test/java/org/apache/james/server/jpa/JpaUsersRepositoryTest.java james/server/trunk/pom.xml james/server/trunk/spring-deployment/pom.xml james/server/trunk/spring-deployment/src/main/config/james/META-INF/persistence.xml james/server/trunk/spring-deployment/src/main/config/james/users-store.xml james/server/trunk/user-library/src/test/java/org/apache/james/userrepository/MockUsersRepositoryTest.java Modified: james/server/trunk/jpa-store/pom.xml URL: http://svn.apache.org/viewvc/james/server/trunk/jpa-store/pom.xml?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/jpa-store/pom.xml (original) +++ james/server/trunk/jpa-store/pom.xml Wed Feb 10 13:52:52 2010 @@ -31,6 +31,42 @@ <name>Apache JAMES Server JPA Backend</name> <version>3.0-M1</version> + <build> + <plugins> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>openjpa-maven-plugin</artifactId> + <version>1.0</version> + <configuration> + <includes>org/apache/james/server/jpa/JPAUser.class</includes> + <addDefaultConstructor>true</addDefaultConstructor> + <enforcePropertyRestrictions>true</enforcePropertyRestrictions> + <toolProperties> + <property> + <name>log</name> + <value>TOOL=TRACE</value> + </property> + <property> + <name>metaDataFactory</name> + <value>jpa(Types=org.apache.james.server.jpa.JPAUser)</value> + </property> + </toolProperties> + </configuration> + + <executions> + <execution> + <id>enhancer</id> + <phase>process-classes</phase> + <goals> + <goal>enhance</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <dependencies> <dependency> <groupId>org.apache.james</groupId> @@ -46,7 +82,20 @@ <artifactId>persistence-api</artifactId> <scope>compile</scope> </dependency> - <dependency> + + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + </dependency> + <dependency> + <groupId>commons-configuration</groupId> + <artifactId>commons-configuration</artifactId> + </dependency> + <dependency> + <groupId>org.apache.james</groupId> + <artifactId>james-server-core-api</artifactId> + </dependency> + <dependency> <groupId>org.apache.james</groupId> <artifactId>james-server-user-library</artifactId> <scope>test</scope> @@ -58,22 +107,16 @@ </dependency> <dependency> <groupId>org.apache.james</groupId> - <artifactId>james-server-core-api</artifactId> - <type>jar</type> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.james</groupId> <artifactId>james-server-user-library</artifactId> <type>test-jar</type> <scope>test</scope> </dependency> <dependency> - <groupId>org.apache.openjpa</groupId> - <artifactId>openjpa</artifactId> - <version>1.2.1</version> - <scope>test</scope> - </dependency> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa</artifactId> + <version>1.2.1</version> + <scope>test</scope> + </dependency> </dependencies> </project> Modified: james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUser.java URL: http://svn.apache.org/viewvc/james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUser.java?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUser.java (original) +++ james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUser.java Wed Feb 10 13:52:52 2010 @@ -26,11 +26,13 @@ import javax.persistence.NamedQuery; import javax.persistence.Version; +import org.apache.commons.codec.digest.DigestUtils; import org.apache.james.api.user.User; @Entity(name = "JamesUser") @NamedQueries( { @NamedQuery(name = "findUserByName", query = "SELECT user FROM JamesUser user WHERE user.name=:name"), + @NamedQuery(name = "deleteUserByName", query = "DELETE FROM JamesUser user WHERE user.name=:name"), @NamedQuery(name = "containsUser", query = "SELECT COUNT(user) FROM JamesUser user WHERE user.name=:name") , @NamedQuery(name = "countUsers", query = "SELECT COUNT(user) FROM JamesUser user"), @NamedQuery(name = "listUserNames", query = "SELECT user.name FROM JamesUser user") @@ -39,13 +41,7 @@ public class JPAUser implements User { /** - * Static salt for hashing password. Modifying this value will render all - * passwords unrecognizable. - */ - public static final String SALT = "JPAUsersRepository"; - - /** - * Hashes salted password. + * Hash password. * * @param username * not null @@ -53,12 +49,20 @@ * not null * @return not null */ - public static String hashPassword(String username, String password) { - // Combine dynamic and static salt - final String hashedSaltedPassword = password;// = - // Text.md5(Text.md5(username - // + password) + SALT); - return hashedSaltedPassword; + private static String hashPassword(String username, String password, String alg) { + String newPass; + if ( alg == null || alg.equals("MD5")) { + newPass = DigestUtils.md5Hex(password); + } else if (alg.equals("NONE")) { + newPass = "password"; + } else if (alg.equals("SHA-256")) { + newPass = DigestUtils.sha256Hex(password); + } else if (alg.equals("SHA-512")) { + newPass = DigestUtils.sha512Hex(password); + } else { + newPass = DigestUtils.shaHex(password); + } + return newPass; } /** Prevents concurrent modification */ @@ -72,40 +76,47 @@ /** Hashed password */ @Basic private String password; + + @Basic + private String alg; protected JPAUser() { } - public JPAUser(final String userName, String password) { + public JPAUser(final String userName, String password, String alg) { super(); this.name = userName; - this.password = hashPassword(userName, password); + this.alg = alg; + this.password = hashPassword(userName, password, alg); } + /* + * (non-Javadoc) + * @see org.apache.james.api.user.User#getUserName() + */ public String getUserName() { return name; } - /** - * Gets salted, hashed password. - * - * @return the hashedSaltedPassword + /* + * (non-Javadoc) + * @see org.apache.james.api.user.User#setPassword(java.lang.String) */ - public final String getHashedSaltedPassword() { - return password; - } - public boolean setPassword(String newPass) { final boolean result; if (newPass == null) { result = false; } else { - password = hashPassword(name, newPass); + password = hashPassword(name, newPass, alg); result = true; } return result; } + /* + * (non-Javadoc) + * @see org.apache.james.api.user.User#verifyPassword(java.lang.String) + */ public boolean verifyPassword(String pass) { final boolean result; if (pass == null) { @@ -113,7 +124,7 @@ } else if (password == null) { result = false; } else { - result = password.equals(hashPassword(name, pass)); + result = password.equals(hashPassword(name, pass, alg)); } return result; } Modified: james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUsersRepository.java URL: http://svn.apache.org/viewvc/james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUsersRepository.java?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUsersRepository.java (original) +++ james/server/trunk/jpa-store/src/main/java/org/apache/james/server/jpa/JPAUsersRepository.java Wed Feb 10 13:52:52 2010 @@ -20,57 +20,36 @@ package org.apache.james.server.jpa; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; -import javax.persistence.PersistenceContext; import javax.persistence.PersistenceException; +import javax.persistence.PersistenceUnit; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.james.api.user.User; import org.apache.james.api.user.UsersRepository; +import org.apache.james.lifecycle.Configurable; +import org.apache.james.lifecycle.LogEnabled; + /** - * Proof-of-concept repository using JPA. TODO: Support managed contexts. TODO: - * Use factory and support pooled contexts + * JPA based UserRepository + * */ -public class JPAUsersRepository implements UsersRepository { - - private static final Log LOGGER = LogFactory.getLog(JPAUsersRepository.class); +public class JPAUsersRepository implements UsersRepository, Configurable, LogEnabled { - private Log logger = LOGGER; + private EntityManagerFactory entityManagerFactory; - private EntityManager entityManager; + private String algo; - /** - * Gets current logger. - * - * @return the logger - */ - public final Log getLogger() { - return logger; - } + private Log logger; - /** - * Setter injection for logging. - * - * @param logger - * the logger to set - */ - public final void setLogger(Log logger) { - this.logger = logger; - } - - /** - * Gets entity manager. - * - * @return the entityManager - */ - public final EntityManager getEntityManager() { - return entityManager; - } /** * Sets entity manager. @@ -78,9 +57,9 @@ * @param entityManager * the entityManager to set */ - @PersistenceContext - public final void setEntityManager(EntityManager entityManager) { - this.entityManager = entityManager; + @PersistenceUnit + public final void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) { + this.entityManagerFactory = entityManagerFactory; } /** @@ -128,10 +107,11 @@ * @since James 2.3.0 */ public boolean addUser(String username, String password) { + EntityManager entityManager = entityManagerFactory.createEntityManager(); final EntityTransaction transaction = entityManager.getTransaction(); try { transaction.begin(); - JPAUser user = new JPAUser(username, password); + JPAUser user = new JPAUser(username, password, algo); entityManager.persist(user); transaction.commit(); return true; @@ -140,6 +120,8 @@ if (transaction.isActive()) { transaction.rollback(); } + } finally { + entityManager.close(); } return false; } @@ -155,16 +137,16 @@ * @since James 1.2.2 */ public User getUserByName(String name) { - return getJPAUserByName(name); - } + EntityManager entityManager = entityManagerFactory.createEntityManager(); - private JPAUser getJPAUserByName(String name) { try { return (JPAUser) entityManager.createNamedQuery("findUserByName").setParameter("name", name).getSingleResult(); } catch (PersistenceException e) { logger.debug("Failed to find user", e); return null; - } + } finally { + entityManager.close(); + } } /** @@ -193,6 +175,10 @@ * @return the case-correct name of the user, null if the user doesn't exist */ public String getRealName(String name) { + User u = getUserByName(name); + if (u != null) { + u.getUserName(); + } return null; } @@ -203,6 +189,8 @@ * @return true if successful. */ public boolean updateUser(User user) { + EntityManager entityManager = entityManagerFactory.createEntityManager(); + final EntityTransaction transaction = entityManager.getTransaction(); try { if (contains(user.getUserName())) { @@ -219,6 +207,8 @@ transaction.rollback(); } return false; + }finally { + entityManager.close(); } return true; } @@ -230,17 +220,20 @@ * the user to remove from the repository */ public void removeUser(String name) { + EntityManager entityManager = entityManagerFactory.createEntityManager(); + final EntityTransaction transaction = entityManager.getTransaction(); try { transaction.begin(); - JPAUser user = getJPAUserByName(name); - entityManager.remove(user); + entityManager.createNamedQuery("deleteUserByName").setParameter("name", name).executeUpdate(); transaction.commit(); } catch (PersistenceException e) { - logger.debug("Failed to save user", e); + logger.debug("Failed to remove user", e); if (transaction.isActive()) { transaction.rollback(); } + } finally { + entityManager.close(); } } @@ -252,11 +245,15 @@ * @return whether the user is in the repository */ public boolean contains(String name) { + EntityManager entityManager = entityManagerFactory.createEntityManager(); + try { return ((Long) entityManager.createNamedQuery("containsUser").setParameter("name", name).getSingleResult()).longValue() > 0; } catch (PersistenceException e) { logger.debug("Failed to find user", e); return false; + } finally { + entityManager.close(); } } @@ -290,7 +287,7 @@ * @since James 1.2.2 */ public boolean test(String name, String password) { - final JPAUser user = getJPAUserByName(name); + final User user = getUserByName(name); final boolean result; if (user == null) { result = false; @@ -306,11 +303,15 @@ * @return the number of users in the repository */ public int countUsers() { + EntityManager entityManager = entityManagerFactory.createEntityManager(); + try { return ((Long) entityManager.createNamedQuery("countUsers").getSingleResult()).intValue(); } catch (PersistenceException e) { logger.debug("Failed to find user", e); return 0; + } finally { + entityManager.close(); } } @@ -322,13 +323,33 @@ */ @SuppressWarnings("unchecked") public Iterator<String> list() { + EntityManager entityManager = entityManagerFactory.createEntityManager(); + try { - return entityManager.createNamedQuery("listUserNames").getResultList().iterator(); + return Collections.unmodifiableList(entityManager.createNamedQuery("listUserNames").getResultList()).iterator(); } catch (PersistenceException e) { logger.debug("Failed to find user", e); return new ArrayList<String>().iterator(); + } finally { + entityManager.close(); } } + /* + * (non-Javadoc) + * @see org.apache.james.lifecycle.Configurable#configure(org.apache.commons.configuration.HierarchicalConfiguration) + */ + public void configure(HierarchicalConfiguration config) throws ConfigurationException { + algo = config.getString("algorithm","MD5"); + } + + /* + * (non-Javadoc) + * @see org.apache.james.lifecycle.LogEnabled#setLog(org.apache.commons.logging.Log) + */ + public void setLog(Log log) { + this.logger = log; + } + } Modified: james/server/trunk/jpa-store/src/test/java/org/apache/james/server/jpa/JpaUsersRepositoryTest.java URL: http://svn.apache.org/viewvc/james/server/trunk/jpa-store/src/test/java/org/apache/james/server/jpa/JpaUsersRepositoryTest.java?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/jpa-store/src/test/java/org/apache/james/server/jpa/JpaUsersRepositoryTest.java (original) +++ james/server/trunk/jpa-store/src/test/java/org/apache/james/server/jpa/JpaUsersRepositoryTest.java Wed Feb 10 13:52:52 2010 @@ -23,6 +23,7 @@ import javax.persistence.PersistenceException; +import org.apache.commons.logging.impl.SimpleLog; import org.apache.james.api.user.UsersRepository; import org.apache.james.userrepository.MockUsersRepositoryTest; import org.apache.openjpa.persistence.OpenJPAEntityManager; @@ -34,7 +35,6 @@ private HashMap<String, String> properties; private OpenJPAEntityManagerFactory factory; - private OpenJPAEntityManager manager; @Override protected void setUp() throws Exception { @@ -53,35 +53,34 @@ protected void tearDown() throws Exception { deleteAll(); super.tearDown(); - if (manager != null) - { - manager.close(); - } - if (factory != null) - { - factory.close(); - } + } private void deleteAll() { + OpenJPAEntityManager manager = factory.createEntityManager(); + final OpenJPAEntityTransaction transaction = manager.getTransaction(); try { - OpenJPAEntityManager manager = factory.createEntityManager(); - final OpenJPAEntityTransaction transaction = manager.getTransaction(); transaction.begin(); manager.createQuery("DELETE FROM JamesUser user").executeUpdate(); transaction.commit(); } catch (PersistenceException e) { e.printStackTrace(); + if (transaction.isActive()) { + transaction.rollback(); + } + } finally { + manager.close(); } } + @Override protected UsersRepository getUsersRepository() throws Exception { factory = OpenJPAPersistence.getEntityManagerFactory(properties); - manager = factory.createEntityManager(); JPAUsersRepository repos = new JPAUsersRepository(); - repos.setEntityManager(manager); + repos.setLog(new SimpleLog("JPA")); + repos.setEntityManagerFactory(factory); return repos; } } Modified: james/server/trunk/pom.xml URL: http://svn.apache.org/viewvc/james/server/trunk/pom.xml?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/pom.xml (original) +++ james/server/trunk/pom.xml Wed Feb 10 13:52:52 2010 @@ -458,7 +458,11 @@ <artifactId>james-server-remotemanager</artifactId> <version>3.0-M1</version> </dependency> - + <dependency> + <groupId>org.apache.james</groupId> + <artifactId>james-server-jpa-store</artifactId> + <version>3.0-M1</version> + </dependency> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> Modified: james/server/trunk/spring-deployment/pom.xml URL: http://svn.apache.org/viewvc/james/server/trunk/spring-deployment/pom.xml?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/spring-deployment/pom.xml (original) +++ james/server/trunk/spring-deployment/pom.xml Wed Feb 10 13:52:52 2010 @@ -343,7 +343,11 @@ <artifactId>apache-james-imap-processor</artifactId> <scope>runtime</scope> </dependency> - + <dependency> + <groupId>org.apache.james</groupId> + <artifactId>james-server-jpa-store</artifactId> + <scope>runtime</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> Modified: james/server/trunk/spring-deployment/src/main/config/james/META-INF/persistence.xml URL: http://svn.apache.org/viewvc/james/server/trunk/spring-deployment/src/main/config/james/META-INF/persistence.xml?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/spring-deployment/src/main/config/james/META-INF/persistence.xml (original) +++ james/server/trunk/spring-deployment/src/main/config/james/META-INF/persistence.xml Wed Feb 10 13:52:52 2010 @@ -2,15 +2,20 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"> <persistence-unit name="James" transaction-type="RESOURCE_LOCAL"> - <class>org.apache.james.imap.jpa.mail.model.JPAHeader</class> - <class>org.apache.james.imap.jpa.mail.model.JPAMailbox</class> - <class>org.apache.james.imap.jpa.mail.model.JPAMailboxMembership</class> - <class>org.apache.james.imap.jpa.mail.model.JPAMessage</class> - <class>org.apache.james.imap.jpa.mail.model.JPAProperty</class> - <class>org.apache.james.imap.jpa.user.model.JPASubscription</class> - <properties> - <!-- create tables on startup --> - <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> - </properties> + <!-- IMAP stuff--> + <class>org.apache.james.imap.jpa.mail.model.JPAHeader</class> + <class>org.apache.james.imap.jpa.mail.model.JPAMailbox</class> + <class>org.apache.james.imap.jpa.mail.model.JPAMailboxMembership</class> + <class>org.apache.james.imap.jpa.mail.model.JPAMessage</class> + <class>org.apache.james.imap.jpa.mail.model.JPAProperty</class> + <class>org.apache.james.imap.jpa.user.model.JPASubscription</class> + + <!-- UsersRepository --> + <class>org.apache.james.server.jpa.JPAUser</class> + + <properties> + <!-- create tables on startup --> + <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> + </properties> </persistence-unit> </persistence> Modified: james/server/trunk/spring-deployment/src/main/config/james/users-store.xml URL: http://svn.apache.org/viewvc/james/server/trunk/spring-deployment/src/main/config/james/users-store.xml?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/spring-deployment/src/main/config/james/users-store.xml (original) +++ james/server/trunk/spring-deployment/src/main/config/james/users-store.xml Wed Feb 10 13:52:52 2010 @@ -52,16 +52,22 @@ <!-- Note: The <data-source> element must refer to a connection configured --> <!-- in the <database-connections> configuration section. --> <!-- The LocalUsers repository, for storing James' User info. --> + <!-- <repository name="LocalUsers" class="org.apache.james.userrepository.JamesUsersJdbcRepository" destinationURL="db://maildb/users"> <sqlFile>file://conf/sqlResources.xml</sqlFile> - <!-- Set whether user names are case sensitive or case insensitive --> <ignoreCase>true</ignoreCase> - <!-- Set whether to enable local aliases --> <enableAliases>true</enableAliases> - <!-- Set whether to enable forwarding --> <enableForwarding>true</enableForwarding> </repository> - + --> + + <!-- JPA based backend. Support password algorithm are: + MD5, SHA-256, SHA-512, NONE + --> + <repository name="LocalUsers" class="org.apache.james.server.jpa.JPAUsersRepository"> + <algorithm>MD5</algorithm> + </repository> + <!-- This is an example configuration including configuration for a list server. --> <!-- CHECKME: before uncommenting this, edit the configuration file's contents --> <!-- --> Modified: james/server/trunk/user-library/src/test/java/org/apache/james/userrepository/MockUsersRepositoryTest.java URL: http://svn.apache.org/viewvc/james/server/trunk/user-library/src/test/java/org/apache/james/userrepository/MockUsersRepositoryTest.java?rev=908503&r1=908502&r2=908503&view=diff ============================================================================== --- james/server/trunk/user-library/src/test/java/org/apache/james/userrepository/MockUsersRepositoryTest.java (original) +++ james/server/trunk/user-library/src/test/java/org/apache/james/userrepository/MockUsersRepositoryTest.java Wed Feb 10 13:52:52 2010 @@ -155,7 +155,7 @@ // UsersFileRepository accept this call for every argument // fail("removing an unknown user didn't fail!"); } catch (Exception e) { - + e.printStackTrace(); } assertTrue("user not added", usersRepository.addUser("username","password")); assertEquals("didn't accept the correct password", usersRepository.test("username", "password"),getPasswordsEnabled()); @@ -172,6 +172,7 @@ try { usersRepository.removeUser("username"); } catch (Exception e) { + e.printStackTrace(); fail("removing the user failed!"); } assertFalse("user not existing", usersRepository.contains("username")); --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org