Initial commit

This commit is contained in:
yanzg
2019-05-16 22:46:41 +08:00
commit a8b82c8ef9
197 changed files with 6427 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-aggregator</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,5 @@
#Sun Feb 14 15:24:57 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
org.eclipse.jdt.core.compiler.compliance=1.4
org.eclipse.jdt.core.compiler.source=1.3

View File

@@ -0,0 +1,9 @@
#Sun Feb 14 15:24:57 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-captcha</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,6 @@
#Wed Mar 24 17:07:29 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -0,0 +1,9 @@
#Wed Mar 24 16:30:18 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,55 @@
<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>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-captcha</artifactId>
<name>Account Captcha</name>
<properties>
<kaptcha.version>2.3</kaptcha.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.kaptcha</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>sonatype-forge</id>
<name>Sonatype Forge</name>
<url>http://repository.sonatype.org/content/groups/forge/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@@ -0,0 +1,17 @@
package com.juvenxu.mvnbook.account.captcha;
public class AccountCaptchaException
extends Exception
{
private static final long serialVersionUID = 1339439433313285858L;
public AccountCaptchaException( String message )
{
super( message );
}
public AccountCaptchaException( String message, Throwable throwable )
{
super( message, throwable );
}
}

View File

@@ -0,0 +1,19 @@
package com.juvenxu.mvnbook.account.captcha;
import java.util.List;
public interface AccountCaptchaService
{
String generateCaptchaKey()
throws AccountCaptchaException;
byte[] generateCaptchaImage( String captchaKey )
throws AccountCaptchaException;
boolean validateCaptcha( String captchaKey, String captchaValue )
throws AccountCaptchaException;
List<String> getPreDefinedTexts();
void setPreDefinedTexts( List<String> preDefinedTexts );
}

View File

@@ -0,0 +1,121 @@
package com.juvenxu.mvnbook.account.captcha;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.imageio.ImageIO;
import org.springframework.beans.factory.InitializingBean;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
public class AccountCaptchaServiceImpl
implements AccountCaptchaService, InitializingBean
{
private DefaultKaptcha producer;
private Map<String, String> captchaMap = new HashMap<String, String>();
private List<String> preDefinedTexts;
private int textCount = 0;
public void afterPropertiesSet()
throws Exception
{
producer = new DefaultKaptcha();
producer.setConfig( new Config( new Properties() ) );
}
public String generateCaptchaKey()
{
String key = RandomGenerator.getRandomString();
String value = getCaptchaText();
captchaMap.put( key, value );
return key;
}
public List<String> getPreDefinedTexts()
{
return preDefinedTexts;
}
public void setPreDefinedTexts( List<String> preDefinedTexts )
{
this.preDefinedTexts = preDefinedTexts;
}
private String getCaptchaText()
{
if ( preDefinedTexts != null && !preDefinedTexts.isEmpty() )
{
String text = preDefinedTexts.get( textCount );
textCount = ( textCount + 1 ) % preDefinedTexts.size();
return text;
}
else
{
return producer.createText();
}
}
public byte[] generateCaptchaImage( String captchaKey )
throws AccountCaptchaException
{
String text = captchaMap.get( captchaKey );
if ( text == null )
{
throw new AccountCaptchaException( "Captch key '" + captchaKey + "' not found!" );
}
BufferedImage image = producer.createImage( text );
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
ImageIO.write( image, "jpg", out );
}
catch ( IOException e )
{
throw new AccountCaptchaException( "Failed to write captcha stream!", e );
}
return out.toByteArray();
}
public boolean validateCaptcha( String captchaKey, String captchaValue )
throws AccountCaptchaException
{
String text = captchaMap.get( captchaKey );
if ( text == null )
{
throw new AccountCaptchaException( "Captch key '" + captchaKey + "' not found!" );
}
if ( text.equals( captchaValue ) )
{
captchaMap.remove( captchaKey );
return true;
}
else
{
return false;
}
}
}

View File

@@ -0,0 +1,22 @@
package com.juvenxu.mvnbook.account.captcha;
import java.util.Random;
public class RandomGenerator
{
private static String range = "0123456789abcdefghijklmnopqrstuvwxyz";
public static synchronized String getRandomString()
{
Random random = new Random();
StringBuffer result = new StringBuffer();
for ( int i = 0; i < 8; i++ )
{
result.append( range.charAt( random.nextInt( range.length() ) ) );
}
return result.toString();
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="accountCaptchaService"
class="com.juvenxu.mvnbook.account.captcha.AccountCaptchaServiceImpl">
</bean>
</beans>

View File

@@ -0,0 +1,85 @@
package com.juvenxu.mvnbook.account.captcha;
import static org.junit.Assert.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AccountCaptchaServiceTest
{
private AccountCaptchaService service;
@Before
public void prepare()
throws Exception
{
ApplicationContext ctx = new ClassPathXmlApplicationContext( "account-captcha.xml" );
service = (AccountCaptchaService) ctx.getBean( "accountCaptchaService" );
}
@Test
public void testGenerateCaptcha()
throws Exception
{
String captchaKey = service.generateCaptchaKey();
assertNotNull( captchaKey );
byte[] captchaImage = service.generateCaptchaImage( captchaKey );
assertTrue( captchaImage.length > 0 );
File image = new File( "target/" + captchaKey + ".jpg" );
OutputStream output = null;
try
{
output = new FileOutputStream( image );
output.write( captchaImage );
}
finally
{
if ( output != null )
{
output.close();
}
}
assertTrue( image.exists() && image.length() > 0 );
}
@Test
public void testValidateCaptchaCorrect()
throws Exception
{
List<String> preDefinedTexts = new ArrayList<String>();
preDefinedTexts.add( "12345" );
preDefinedTexts.add( "abcde" );
service.setPreDefinedTexts( preDefinedTexts );
String captchaKey = service.generateCaptchaKey();
service.generateCaptchaImage( captchaKey );
assertTrue( service.validateCaptcha( captchaKey, "12345" ) );
captchaKey = service.generateCaptchaKey();
service.generateCaptchaImage( captchaKey );
assertTrue( service.validateCaptcha( captchaKey, "abcde" ) );
}
@Test
public void testValidateCaptchaIncorrect()
throws Exception
{
List<String> preDefinedTexts = new ArrayList<String>();
preDefinedTexts.add( "12345" );
service.setPreDefinedTexts( preDefinedTexts );
String captchaKey = service.generateCaptchaKey();
service.generateCaptchaImage( captchaKey );
assertFalse( service.validateCaptcha( captchaKey, "67890" ) );
}
}

View File

@@ -0,0 +1,27 @@
package com.juvenxu.mvnbook.account.captcha;
import static org.junit.Assert.assertFalse;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
public class RandomGeneratorTest
{
@Test
public void testGetRandomString()
throws Exception
{
Set<String> randoms = new HashSet<String>( 100 );
for ( int i = 0; i < 100; i++ )
{
String random = RandomGenerator.getRandomString();
assertFalse( randoms.contains( random ) );
randoms.add( random );
}
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-email</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,6 @@
#Wed Mar 24 16:29:49 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -0,0 +1,9 @@
#Mon Feb 15 22:20:48 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,56 @@
<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>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-email</artifactId>
<name>Account Email</name>
<properties>
<javax.mail.version>1.4.1</javax.mail.version>
<greenmail.version>1.3.1b</greenmail.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${javax.mail.version}</version>
</dependency>
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<version>${greenmail.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
</build>
</project>

View File

@@ -0,0 +1,17 @@
package com.juvenxu.mvnbook.account.email;
public class AccountEmailException
extends Exception
{
private static final long serialVersionUID = -4817386460334501672L;
public AccountEmailException( String message )
{
super( message );
}
public AccountEmailException( String message, Throwable throwable )
{
super( message, throwable );
}
}

View File

@@ -0,0 +1,7 @@
package com.juvenxu.mvnbook.account.email;
public interface AccountEmailService
{
void sendMail( String to, String subject, String htmlText )
throws AccountEmailException;
}

View File

@@ -0,0 +1,56 @@
package com.juvenxu.mvnbook.account.email;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
public class AccountEmailServiceImpl
implements AccountEmailService
{
private JavaMailSender javaMailSender;
private String systemEmail;
public void sendMail( String to, String subject, String htmlText )
throws AccountEmailException
{
try
{
MimeMessage msg = javaMailSender.createMimeMessage();
MimeMessageHelper msgHelper = new MimeMessageHelper( msg );
msgHelper.setFrom( systemEmail );
msgHelper.setTo( to );
msgHelper.setSubject( subject );
msgHelper.setText( htmlText, true );
javaMailSender.send( msg );
}
catch ( MessagingException e )
{
throw new AccountEmailException( "Faild to send mail.", e );
}
}
public JavaMailSender getJavaMailSender()
{
return javaMailSender;
}
public void setJavaMailSender( JavaMailSender javaMailSender )
{
this.javaMailSender = javaMailSender;
}
public String getSystemEmail()
{
return systemEmail;
}
public void setSystemEmail( String systemEmail )
{
this.systemEmail = systemEmail;
}
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:service.properties" />
</bean>
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="protocol" value="${email.protocol}" />
<property name="host" value="${email.host}" />
<property name="port" value="${email.port}" />
<property name="username" value="${email.username}" />
<property name="password" value="${email.password}" />
<property name="javaMailProperties">
<props>
<prop key="mail.${email.protocol}.auth">${email.auth}</prop>
</props>
</property>
</bean>
<bean id="accountEmailService"
class="com.juvenxu.mvnbook.account.email.AccountEmailServiceImpl">
<property name="javaMailSender" ref="javaMailSender" />
<property name="systemEmail" value="${email.systemEmail}" />
</bean>
</beans>

View File

@@ -0,0 +1,55 @@
package com.juvenxu.mvnbook.account.email;
import static junit.framework.Assert.assertEquals;
import javax.mail.Message;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetup;
public class AccountEmailServiceTest
{
private GreenMail greenMail;
@Before
public void startMailServer()
throws Exception
{
greenMail = new GreenMail( ServerSetup.SMTP );
greenMail.setUser( "test@juvenxu.com", "123456" );
greenMail.start();
}
@Test
public void testSendMail()
throws Exception
{
ApplicationContext ctx = new ClassPathXmlApplicationContext( "account-email.xml" );
AccountEmailService accountEmailService = (AccountEmailService) ctx.getBean( "accountEmailService" );
String subject = "Test Subject";
String htmlText = "<h3>Test</h3>";
accountEmailService.sendMail( "test2@juvenxu.com", subject, htmlText );
greenMail.waitForIncomingEmail( 2000, 1 );
Message[] msgs = greenMail.getReceivedMessages();
assertEquals( 1, msgs.length );
assertEquals( subject, msgs[0].getSubject() );
assertEquals( htmlText, GreenMailUtil.getBody( msgs[0] ).trim() );
}
@After
public void stopMailServer()
throws Exception
{
greenMail.stop();
}
}

View File

@@ -0,0 +1,15 @@
#email.protocol=smtps
#email.host=smtp.gmail.com
#email.port=465
#email.username=your-id@gmail.com
#email.password=your-password
#email.auth=true
#email.systemEmail=your-id@gmail.com
email.protocol=smtp
email.host=localhost
email.port=25
email.username=test@juvenxu.com
email.password=123456
email.auth=true
email.systemEmail=test1@juvenxu.com

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-persist</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,6 @@
#Wed Mar 24 16:29:49 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -0,0 +1,9 @@
#Mon Feb 15 22:20:48 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,50 @@
<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>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-persist</artifactId>
<name>Account Persist</name>
<properties>
<dom4j.version>1.6.1</dom4j.version>
</properties>
<dependencies>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>${dom4j.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
</build>
</project>

View File

@@ -0,0 +1,64 @@
package com.juvenxu.mvnbook.account.persist;
public class Account
{
private String id;
private String name;
private String email;
private String password;
private boolean activated;
public String getId()
{
return id;
}
public void setId( String id )
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public String getEmail()
{
return email;
}
public void setEmail( String email )
{
this.email = email;
}
public String getPassword()
{
return password;
}
public void setPassword( String password )
{
this.password = password;
}
public boolean isActivated()
{
return activated;
}
public void setActivated( boolean activated )
{
this.activated = activated;
}
}

View File

@@ -0,0 +1,17 @@
package com.juvenxu.mvnbook.account.persist;
public class AccountPersistException
extends Exception
{
private static final long serialVersionUID = -8334988626147289624L;
public AccountPersistException( String message )
{
super( message );
}
public AccountPersistException( String message, Throwable throwable )
{
super( message, throwable );
}
}

View File

@@ -0,0 +1,16 @@
package com.juvenxu.mvnbook.account.persist;
public interface AccountPersistService
{
Account createAccount( Account account )
throws AccountPersistException;
Account readAccount( String id )
throws AccountPersistException;
Account updateAccount( Account account )
throws AccountPersistException;
void deleteAccount( String id )
throws AccountPersistException;
}

View File

@@ -0,0 +1,197 @@
package com.juvenxu.mvnbook.account.persist;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class AccountPersistServiceImpl
implements AccountPersistService
{
private static final String ELEMENT_ROOT = "account-persist";
private static final String ELEMENT_ACCOUNTS = "accounts";
private static final String ELEMENT_ACCOUNT = "account";
private static final String ELEMENT_ACCOUNT_ID = "id";
private static final String ELEMENT_ACCOUNT_NAME = "name";
private static final String ELEMENT_ACCOUNT_EMAIL = "email";
private static final String ELEMENT_ACCOUNT_PASSWORD = "password";
private static final String ELEMENT_ACCOUNT_ACTIVATED = "activated";
private String file;
private SAXReader reader = new SAXReader();
public String getFile()
{
return file;
}
public void setFile( String file )
{
this.file = file;
}
public Account createAccount( Account account )
throws AccountPersistException
{
Document doc = readDocument();
Element accountsEle = doc.getRootElement().element(ELEMENT_ACCOUNTS);
accountsEle.add( buildAccountElement( account ) );
writeDocument( doc );
return account;
}
@SuppressWarnings("unchecked")
public void deleteAccount( String id )
throws AccountPersistException
{
Document doc = readDocument();
Element accountsEle = doc.getRootElement().element( ELEMENT_ACCOUNTS );
for ( Element accountEle : (List<Element>) accountsEle.elements() )
{
if ( accountEle.elementText( ELEMENT_ACCOUNT_ID ).equals( id ) )
{
accountEle.detach();
writeDocument( doc );
return;
}
}
}
@SuppressWarnings("unchecked")
public Account readAccount( String id )
throws AccountPersistException
{
Document doc = readDocument();
Element accountsEle = doc.getRootElement().element( ELEMENT_ACCOUNTS );
for ( Element accountEle : (List<Element>) accountsEle.elements() )
{
if ( accountEle.elementText( ELEMENT_ACCOUNT_ID ).equals( id ) )
{
return buildAccount( accountEle );
}
}
return null;
}
public Account updateAccount( Account account )
throws AccountPersistException
{
if ( readAccount( account.getId() ) != null )
{
deleteAccount( account.getId() );
return createAccount ( account );
}
return null;
}
private Account buildAccount( Element element )
{
Account account = new Account();
account.setId( element.elementText( ELEMENT_ACCOUNT_ID ) );
account.setName( element.elementText( ELEMENT_ACCOUNT_NAME ) );
account.setEmail( element.elementText( ELEMENT_ACCOUNT_EMAIL ) );
account.setPassword( element.elementText( ELEMENT_ACCOUNT_PASSWORD ) );
account.setActivated( ( "true".equals( element.elementText( ELEMENT_ACCOUNT_ACTIVATED ) ) ? true : false ) );
return account;
}
private Element buildAccountElement( Account account )
{
Element element = DocumentFactory.getInstance().createElement( ELEMENT_ACCOUNT );
element.addElement( ELEMENT_ACCOUNT_ID ).setText( account.getId() );
element.addElement( ELEMENT_ACCOUNT_NAME ).setText( account.getName() );
element.addElement( ELEMENT_ACCOUNT_EMAIL ).setText( account.getEmail() );
element.addElement( ELEMENT_ACCOUNT_PASSWORD ).setText( account.getPassword() );
element.addElement( ELEMENT_ACCOUNT_ACTIVATED ).setText( account.isActivated() ? "true" : "false" );
return element;
}
private Document readDocument()
throws AccountPersistException
{
File dataFile = new File( file );
if( !dataFile.exists() )
{
dataFile.getParentFile().mkdirs();
Document doc = DocumentFactory.getInstance().createDocument();
Element rootEle = doc.addElement( ELEMENT_ROOT );
rootEle.addElement( ELEMENT_ACCOUNTS );
writeDocument( doc );
}
try
{
return reader.read( new File( file ) );
}
catch ( DocumentException e )
{
throw new AccountPersistException( "Unable to read persist data xml", e );
}
}
private void writeDocument( Document doc )
throws AccountPersistException
{
Writer out = null;
try
{
out = new OutputStreamWriter( new FileOutputStream( file ), "utf-8" );
XMLWriter writer = new XMLWriter( out, OutputFormat.createPrettyPrint() );
writer.write( doc );
}
catch ( IOException e )
{
throw new AccountPersistException( "Unable to write persist data xml", e );
}
finally
{
try
{
if ( out != null)
{
out.close();
}
}
catch ( IOException e )
{
throw new AccountPersistException( "Unable to close persist data xml writer", e );
}
}
}
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:account-service.properties" />
</bean>
<bean id="accountPersistService"
class="com.juvenxu.mvnbook.account.persist.AccountPersistServiceImpl">
<property name="file" value="${persist.file}" />
</bean>
</beans>

View File

@@ -0,0 +1,102 @@
package com.juvenxu.mvnbook.account.persist;
import static org.junit.Assert.*;
import java.io.File;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AccountPersistServiceTest
{
private AccountPersistService service;
@Before
public void prepare()
throws Exception
{
File persistDataFile = new File ( "target/test-classes/persist-data.xml" );
if ( persistDataFile.exists() )
{
persistDataFile.delete();
}
ApplicationContext ctx = new ClassPathXmlApplicationContext( "account-persist.xml" );
service = (AccountPersistService) ctx.getBean( "accountPersistService" );
Account account = new Account();
account.setId("juven");
account.setName("Juven Xu");
account.setEmail("juven@changeme.com");
account.setPassword("this_should_be_encrypted");
account.setActivated(true);
service.createAccount(account);
}
@Test
public void testReadAccount()
throws Exception
{
Account account = service.readAccount( "juven" );
assertNotNull( account );
assertEquals( "juven", account.getId() );
assertEquals( "Juven Xu", account.getName() );
assertEquals( "juven@changeme.com", account.getEmail() );
assertEquals( "this_should_be_encrypted", account.getPassword() );
assertTrue( account.isActivated() );
}
@Test
public void testDeleteAccount()
throws Exception
{
assertNotNull( service.readAccount( "juven" ) );
service.deleteAccount( "juven" );
assertNull( service.readAccount( "juven" ) );
}
@Test
public void testCreateAccount()
throws Exception
{
assertNull( service.readAccount( "mike" ) );
Account account = new Account();
account.setId("mike");
account.setName("Mike");
account.setEmail("mike@changeme.com");
account.setPassword("this_should_be_encrypted");
account.setActivated(true);
service.createAccount(account);
assertNotNull( service.readAccount( "mike" ));
}
@Test
public void testUpdateAccount()
throws Exception
{
Account account = service.readAccount( "juven" );
account.setName("Juven Xu 1");
account.setEmail("juven1@changeme.com");
account.setPassword("this_still_should_be_encrypted");
account.setActivated(false);
service.updateAccount( account );
account = service.readAccount( "juven" );
assertEquals( "Juven Xu 1", account.getName() );
assertEquals( "juven1@changeme.com", account.getEmail() );
assertEquals( "this_still_should_be_encrypted", account.getPassword() );
assertFalse( account.isActivated() );
}
}

View File

@@ -0,0 +1 @@
persist.file=${project.build.testOutputDirectory}/persist-data.xml

View File

@@ -0,0 +1,69 @@
<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>
<groupId>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Account Parent</name>
<modules>
<module>account-email</module>
<module>account-persist</module>
<module>account-captcha</module>
</modules>
<properties>
<springframework.version>2.5.6</springframework.version>
<junit.version>4.7</junit.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-aggregator</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,5 @@
#Sun Feb 14 15:24:57 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
org.eclipse.jdt.core.compiler.compliance=1.4
org.eclipse.jdt.core.compiler.source=1.3

View File

@@ -0,0 +1,9 @@
#Sun Feb 14 15:24:57 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-captcha</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,6 @@
#Thu Jul 01 16:54:16 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -0,0 +1,9 @@
#Wed Mar 24 16:30:18 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,55 @@
<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>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-captcha</artifactId>
<name>Account Captcha</name>
<properties>
<kaptcha.version>2.3</kaptcha.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.kaptcha</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>sonatype-forge</id>
<name>Sonatype Forge</name>
<url>http://repository.sonatype.org/content/groups/forge/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@@ -0,0 +1,17 @@
package com.juvenxu.mvnbook.account.captcha;
public class AccountCaptchaException
extends Exception
{
private static final long serialVersionUID = 1339439433313285858L;
public AccountCaptchaException( String message )
{
super( message );
}
public AccountCaptchaException( String message, Throwable throwable )
{
super( message, throwable );
}
}

View File

@@ -0,0 +1,19 @@
package com.juvenxu.mvnbook.account.captcha;
import java.util.List;
public interface AccountCaptchaService
{
String generateCaptchaKey()
throws AccountCaptchaException;
byte[] generateCaptchaImage( String captchaKey )
throws AccountCaptchaException;
boolean validateCaptcha( String captchaKey, String captchaValue )
throws AccountCaptchaException;
List<String> getPreDefinedTexts();
void setPreDefinedTexts( List<String> preDefinedTexts );
}

View File

@@ -0,0 +1,121 @@
package com.juvenxu.mvnbook.account.captcha;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.imageio.ImageIO;
import org.springframework.beans.factory.InitializingBean;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
public class AccountCaptchaServiceImpl
implements AccountCaptchaService, InitializingBean
{
private DefaultKaptcha producer;
private Map<String, String> captchaMap = new HashMap<String, String>();
private List<String> preDefinedTexts;
private int textCount = 0;
public void afterPropertiesSet()
throws Exception
{
producer = new DefaultKaptcha();
producer.setConfig( new Config( new Properties() ) );
}
public String generateCaptchaKey()
{
String key = RandomGenerator.getRandomString();
String value = getCaptchaText();
captchaMap.put( key, value );
return key;
}
public List<String> getPreDefinedTexts()
{
return preDefinedTexts;
}
public void setPreDefinedTexts( List<String> preDefinedTexts )
{
this.preDefinedTexts = preDefinedTexts;
}
private String getCaptchaText()
{
if ( preDefinedTexts != null && !preDefinedTexts.isEmpty() )
{
String text = preDefinedTexts.get( textCount );
textCount = ( textCount + 1 ) % preDefinedTexts.size();
return text;
}
else
{
return producer.createText();
}
}
public byte[] generateCaptchaImage( String captchaKey )
throws AccountCaptchaException
{
String text = captchaMap.get( captchaKey );
if ( text == null )
{
throw new AccountCaptchaException( "Captch key '" + captchaKey + "' not found!" );
}
BufferedImage image = producer.createImage( text );
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
ImageIO.write( image, "jpg", out );
}
catch ( IOException e )
{
throw new AccountCaptchaException( "Failed to write captcha stream!", e );
}
return out.toByteArray();
}
public boolean validateCaptcha( String captchaKey, String captchaValue )
throws AccountCaptchaException
{
String text = captchaMap.get( captchaKey );
if ( text == null )
{
throw new AccountCaptchaException( "Captch key '" + captchaKey + "' not found!" );
}
if ( text.equals( captchaValue ) )
{
captchaMap.remove( captchaKey );
return true;
}
else
{
return false;
}
}
}

View File

@@ -0,0 +1,22 @@
package com.juvenxu.mvnbook.account.captcha;
import java.util.Random;
public class RandomGenerator
{
private static String range = "0123456789abcdefghijklmnopqrstuvwxyz";
public static synchronized String getRandomString()
{
Random random = new Random();
StringBuffer result = new StringBuffer();
for ( int i = 0; i < 8; i++ )
{
result.append( range.charAt( random.nextInt( range.length() ) ) );
}
return result.toString();
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="accountCaptchaService"
class="com.juvenxu.mvnbook.account.captcha.AccountCaptchaServiceImpl">
</bean>
</beans>

View File

@@ -0,0 +1,85 @@
package com.juvenxu.mvnbook.account.captcha;
import static org.junit.Assert.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AccountCaptchaServiceTest
{
private AccountCaptchaService service;
@Before
public void prepare()
throws Exception
{
ApplicationContext ctx = new ClassPathXmlApplicationContext( "account-captcha.xml" );
service = (AccountCaptchaService) ctx.getBean( "accountCaptchaService" );
}
@Test
public void testGenerateCaptcha()
throws Exception
{
String captchaKey = service.generateCaptchaKey();
assertNotNull( captchaKey );
byte[] captchaImage = service.generateCaptchaImage( captchaKey );
assertTrue( captchaImage.length > 0 );
File image = new File( "target/" + captchaKey + ".jpg" );
OutputStream output = null;
try
{
output = new FileOutputStream( image );
output.write( captchaImage );
}
finally
{
if ( output != null )
{
output.close();
}
}
assertTrue( image.exists() && image.length() > 0 );
}
@Test
public void testValidateCaptchaCorrect()
throws Exception
{
List<String> preDefinedTexts = new ArrayList<String>();
preDefinedTexts.add( "12345" );
preDefinedTexts.add( "abcde" );
service.setPreDefinedTexts( preDefinedTexts );
String captchaKey = service.generateCaptchaKey();
service.generateCaptchaImage( captchaKey );
assertTrue( service.validateCaptcha( captchaKey, "12345" ) );
captchaKey = service.generateCaptchaKey();
service.generateCaptchaImage( captchaKey );
assertTrue( service.validateCaptcha( captchaKey, "abcde" ) );
}
@Test
public void testValidateCaptchaIncorrect()
throws Exception
{
List<String> preDefinedTexts = new ArrayList<String>();
preDefinedTexts.add( "12345" );
service.setPreDefinedTexts( preDefinedTexts );
String captchaKey = service.generateCaptchaKey();
service.generateCaptchaImage( captchaKey );
assertFalse( service.validateCaptcha( captchaKey, "67890" ) );
}
}

View File

@@ -0,0 +1,27 @@
package com.juvenxu.mvnbook.account.captcha;
import static org.junit.Assert.assertFalse;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
public class RandomGeneratorTest
{
@Test
public void testGetRandomString()
throws Exception
{
Set<String> randoms = new HashSet<String>( 100 );
for ( int i = 0; i < 100; i++ )
{
String random = RandomGenerator.getRandomString();
assertFalse( randoms.contains( random ) );
randoms.add( random );
}
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-email</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,6 @@
#Fri Sep 03 14:42:20 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -0,0 +1,9 @@
#Mon Feb 15 22:20:48 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,56 @@
<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>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-email</artifactId>
<name>Account Email</name>
<properties>
<javax.mail.version>1.4.1</javax.mail.version>
<greenmail.version>1.3.1b</greenmail.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${javax.mail.version}</version>
</dependency>
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<version>${greenmail.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
</build>
</project>

View File

@@ -0,0 +1,17 @@
package com.juvenxu.mvnbook.account.email;
public class AccountEmailException
extends Exception
{
private static final long serialVersionUID = -4817386460334501672L;
public AccountEmailException( String message )
{
super( message );
}
public AccountEmailException( String message, Throwable throwable )
{
super( message, throwable );
}
}

View File

@@ -0,0 +1,7 @@
package com.juvenxu.mvnbook.account.email;
public interface AccountEmailService
{
void sendMail( String to, String subject, String htmlText )
throws AccountEmailException;
}

View File

@@ -0,0 +1,56 @@
package com.juvenxu.mvnbook.account.email;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
public class AccountEmailServiceImpl
implements AccountEmailService
{
private JavaMailSender javaMailSender;
private String systemEmail;
public void sendMail( String to, String subject, String htmlText )
throws AccountEmailException
{
try
{
MimeMessage msg = javaMailSender.createMimeMessage();
MimeMessageHelper msgHelper = new MimeMessageHelper( msg );
msgHelper.setFrom( systemEmail );
msgHelper.setTo( to );
msgHelper.setSubject( subject );
msgHelper.setText( htmlText, true );
javaMailSender.send( msg );
}
catch ( MessagingException e )
{
throw new AccountEmailException( "Faild to send mail.", e );
}
}
public JavaMailSender getJavaMailSender()
{
return javaMailSender;
}
public void setJavaMailSender( JavaMailSender javaMailSender )
{
this.javaMailSender = javaMailSender;
}
public String getSystemEmail()
{
return systemEmail;
}
public void setSystemEmail( String systemEmail )
{
this.systemEmail = systemEmail;
}
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:account-service.properties" />
</bean>
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="protocol" value="${email.protocol}" />
<property name="host" value="${email.host}" />
<property name="port" value="${email.port}" />
<property name="username" value="${email.username}" />
<property name="password" value="${email.password}" />
<property name="javaMailProperties">
<props>
<prop key="mail.${email.protocol}.auth">${email.auth}</prop>
</props>
</property>
</bean>
<bean id="accountEmailService"
class="com.juvenxu.mvnbook.account.email.AccountEmailServiceImpl">
<property name="javaMailSender" ref="javaMailSender" />
<property name="systemEmail" value="${email.systemEmail}" />
</bean>
</beans>

View File

@@ -0,0 +1,56 @@
package com.juvenxu.mvnbook.account.email;
import static junit.framework.Assert.assertEquals;
import javax.mail.Message;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetup;
public class AccountEmailServiceTest
{
private GreenMail greenMail;
@Before
public void startMailServer()
throws Exception
{
greenMail = new GreenMail( ServerSetup.SMTP );
greenMail.setUser( "test@juvenxu.com", "123456" );
greenMail.start();
}
@Test
public void testSendMail()
throws Exception
{
ApplicationContext ctx = new ClassPathXmlApplicationContext( "account-email.xml" );
AccountEmailService accountEmailService = (AccountEmailService) ctx.getBean( "accountEmailService" );
String subject = "Test Subject";
String htmlText = "<h3>Test</h3>";
accountEmailService.sendMail( "test2@juvenxu.com", subject, htmlText );
greenMail.waitForIncomingEmail( 2000, 1 );
Message[] msgs = greenMail.getReceivedMessages();
assertEquals( 1, msgs.length );
assertEquals( "admin@juvenxu.com", msgs[0].getFrom()[0].toString() );
assertEquals( subject, msgs[0].getSubject() );
assertEquals( htmlText, GreenMailUtil.getBody( msgs[0] ).trim() );
}
@After
public void stopMailServer()
throws Exception
{
greenMail.stop();
}
}

View File

@@ -0,0 +1,14 @@
#email.protocol=smtps
#email.host=smtp.gmail.com
#email.port=465
#email.username=juvenshun@gmail.com
#email.password=googleh8z5v0
#email.auth=true
email.protocol=smtp
email.host=localhost
email.port=25
email.username=test@juvenxu.com
email.password=123456
email.auth=true
email.systemEmail=admin@juvenxu.com

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-persist</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,6 @@
#Thu Jul 01 16:54:16 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -0,0 +1,9 @@
#Mon Feb 15 22:20:48 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,50 @@
<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>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-persist</artifactId>
<name>Account Persist</name>
<properties>
<dom4j.version>1.6.1</dom4j.version>
</properties>
<dependencies>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>${dom4j.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
</build>
</project>

View File

@@ -0,0 +1,64 @@
package com.juvenxu.mvnbook.account.persist;
public class Account
{
private String id;
private String name;
private String email;
private String password;
private boolean activated;
public String getId()
{
return id;
}
public void setId( String id )
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public String getEmail()
{
return email;
}
public void setEmail( String email )
{
this.email = email;
}
public String getPassword()
{
return password;
}
public void setPassword( String password )
{
this.password = password;
}
public boolean isActivated()
{
return activated;
}
public void setActivated( boolean activated )
{
this.activated = activated;
}
}

View File

@@ -0,0 +1,17 @@
package com.juvenxu.mvnbook.account.persist;
public class AccountPersistException
extends Exception
{
private static final long serialVersionUID = -8334988626147289624L;
public AccountPersistException( String message )
{
super( message );
}
public AccountPersistException( String message, Throwable throwable )
{
super( message, throwable );
}
}

View File

@@ -0,0 +1,16 @@
package com.juvenxu.mvnbook.account.persist;
public interface AccountPersistService
{
Account createAccount( Account account )
throws AccountPersistException;
Account readAccount( String id )
throws AccountPersistException;
Account updateAccount( Account account )
throws AccountPersistException;
void deleteAccount( String id )
throws AccountPersistException;
}

View File

@@ -0,0 +1,197 @@
package com.juvenxu.mvnbook.account.persist;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class AccountPersistServiceImpl
implements AccountPersistService
{
private static final String ELEMENT_ROOT = "account-persist";
private static final String ELEMENT_ACCOUNTS = "accounts";
private static final String ELEMENT_ACCOUNT = "account";
private static final String ELEMENT_ACCOUNT_ID = "id";
private static final String ELEMENT_ACCOUNT_NAME = "name";
private static final String ELEMENT_ACCOUNT_EMAIL = "email";
private static final String ELEMENT_ACCOUNT_PASSWORD = "password";
private static final String ELEMENT_ACCOUNT_ACTIVATED = "activated";
private String file;
private SAXReader reader = new SAXReader();
public String getFile()
{
return file;
}
public void setFile( String file )
{
this.file = file;
}
public Account createAccount( Account account )
throws AccountPersistException
{
Document doc = readDocument();
Element accountsEle = doc.getRootElement().element(ELEMENT_ACCOUNTS);
accountsEle.add( buildAccountElement( account ) );
writeDocument( doc );
return account;
}
@SuppressWarnings("unchecked")
public void deleteAccount( String id )
throws AccountPersistException
{
Document doc = readDocument();
Element accountsEle = doc.getRootElement().element( ELEMENT_ACCOUNTS );
for ( Element accountEle : (List<Element>) accountsEle.elements() )
{
if ( accountEle.elementText( ELEMENT_ACCOUNT_ID ).equals( id ) )
{
accountEle.detach();
writeDocument( doc );
return;
}
}
}
@SuppressWarnings("unchecked")
public Account readAccount( String id )
throws AccountPersistException
{
Document doc = readDocument();
Element accountsEle = doc.getRootElement().element( ELEMENT_ACCOUNTS );
for ( Element accountEle : (List<Element>) accountsEle.elements() )
{
if ( accountEle.elementText( ELEMENT_ACCOUNT_ID ).equals( id ) )
{
return buildAccount( accountEle );
}
}
return null;
}
public Account updateAccount( Account account )
throws AccountPersistException
{
if ( readAccount( account.getId() ) != null )
{
deleteAccount( account.getId() );
return createAccount ( account );
}
return null;
}
private Account buildAccount( Element element )
{
Account account = new Account();
account.setId( element.elementText( ELEMENT_ACCOUNT_ID ) );
account.setName( element.elementText( ELEMENT_ACCOUNT_NAME ) );
account.setEmail( element.elementText( ELEMENT_ACCOUNT_EMAIL ) );
account.setPassword( element.elementText( ELEMENT_ACCOUNT_PASSWORD ) );
account.setActivated( ( "true".equals( element.elementText( ELEMENT_ACCOUNT_ACTIVATED ) ) ? true : false ) );
return account;
}
private Element buildAccountElement( Account account )
{
Element element = DocumentFactory.getInstance().createElement( ELEMENT_ACCOUNT );
element.addElement( ELEMENT_ACCOUNT_ID ).setText( account.getId() );
element.addElement( ELEMENT_ACCOUNT_NAME ).setText( account.getName() );
element.addElement( ELEMENT_ACCOUNT_EMAIL ).setText( account.getEmail() );
element.addElement( ELEMENT_ACCOUNT_PASSWORD ).setText( account.getPassword() );
element.addElement( ELEMENT_ACCOUNT_ACTIVATED ).setText( account.isActivated() ? "true" : "false" );
return element;
}
private Document readDocument()
throws AccountPersistException
{
File dataFile = new File( file );
if( !dataFile.exists() )
{
dataFile.getParentFile().mkdirs();
Document doc = DocumentFactory.getInstance().createDocument();
Element rootEle = doc.addElement( ELEMENT_ROOT );
rootEle.addElement( ELEMENT_ACCOUNTS );
writeDocument( doc );
}
try
{
return reader.read( new File( file ) );
}
catch ( DocumentException e )
{
throw new AccountPersistException( "Unable to read persist data xml", e );
}
}
private void writeDocument( Document doc )
throws AccountPersistException
{
Writer out = null;
try
{
out = new OutputStreamWriter( new FileOutputStream( file ), "utf-8" );
XMLWriter writer = new XMLWriter( out, OutputFormat.createPrettyPrint() );
writer.write( doc );
}
catch ( IOException e )
{
throw new AccountPersistException( "Unable to write persist data xml", e );
}
finally
{
try
{
if ( out != null)
{
out.close();
}
}
catch ( IOException e )
{
throw new AccountPersistException( "Unable to close persist data xml writer", e );
}
}
}
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:account-service.properties" />
</bean>
<bean id="accountPersistService"
class="com.juvenxu.mvnbook.account.persist.AccountPersistServiceImpl">
<property name="file" value="${persist.file}" />
</bean>
</beans>

View File

@@ -0,0 +1,102 @@
package com.juvenxu.mvnbook.account.persist;
import static org.junit.Assert.*;
import java.io.File;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AccountPersistServiceTest
{
private AccountPersistService service;
@Before
public void prepare()
throws Exception
{
File persistDataFile = new File ( "target/test-classes/persist-data.xml" );
if ( persistDataFile.exists() )
{
persistDataFile.delete();
}
ApplicationContext ctx = new ClassPathXmlApplicationContext( "account-persist.xml" );
service = (AccountPersistService) ctx.getBean( "accountPersistService" );
Account account = new Account();
account.setId("juven");
account.setName("Juven Xu");
account.setEmail("juven@changeme.com");
account.setPassword("this_should_be_encrypted");
account.setActivated(true);
service.createAccount(account);
}
@Test
public void testReadAccount()
throws Exception
{
Account account = service.readAccount( "juven" );
assertNotNull( account );
assertEquals( "juven", account.getId() );
assertEquals( "Juven Xu", account.getName() );
assertEquals( "juven@changeme.com", account.getEmail() );
assertEquals( "this_should_be_encrypted", account.getPassword() );
assertTrue( account.isActivated() );
}
@Test
public void testDeleteAccount()
throws Exception
{
assertNotNull( service.readAccount( "juven" ) );
service.deleteAccount( "juven" );
assertNull( service.readAccount( "juven" ) );
}
@Test
public void testCreateAccount()
throws Exception
{
assertNull( service.readAccount( "mike" ) );
Account account = new Account();
account.setId("mike");
account.setName("Mike");
account.setEmail("mike@changeme.com");
account.setPassword("this_should_be_encrypted");
account.setActivated(true);
service.createAccount(account);
assertNotNull( service.readAccount( "mike" ));
}
@Test
public void testUpdateAccount()
throws Exception
{
Account account = service.readAccount( "juven" );
account.setName("Juven Xu 1");
account.setEmail("juven1@changeme.com");
account.setPassword("this_still_should_be_encrypted");
account.setActivated(false);
service.updateAccount( account );
account = service.readAccount( "juven" );
assertEquals( "Juven Xu 1", account.getName() );
assertEquals( "juven1@changeme.com", account.getEmail() );
assertEquals( "this_still_should_be_encrypted", account.getPassword() );
assertFalse( account.isActivated() );
}
}

View File

@@ -0,0 +1 @@
persist.file=${project.build.testOutputDirectory}/persist-data.xml

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-service</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,6 @@
#Thu Jul 01 16:54:17 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -0,0 +1,9 @@
#Sun May 09 19:38:56 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,53 @@
<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>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-service</artifactId>
<name>Account Service</name>
<properties>
<greenmail.version>1.3.1b</greenmail.version>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>account-email</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>account-persist</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>account-captcha</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<version>${greenmail.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
</build>
</project>

View File

@@ -0,0 +1,19 @@
package com.juvenxu.mvnbook.account.service;
public interface AccountService
{
String generateCaptchaKey()
throws AccountServiceException;
byte[] generateCaptchaImage( String captchaKey )
throws AccountServiceException;
void signUp( SignUpRequest signUpRequest )
throws AccountServiceException;
void activate( String activationNumber )
throws AccountServiceException;
void login( String id, String password )
throws AccountServiceException;
}

View File

@@ -0,0 +1,17 @@
package com.juvenxu.mvnbook.account.service;
public class AccountServiceException
extends Exception
{
private static final long serialVersionUID = 949282286716874926L;
public AccountServiceException( String message )
{
super( message );
}
public AccountServiceException( String message, Throwable throwable )
{
super( message, throwable );
}
}

View File

@@ -0,0 +1,182 @@
package com.juvenxu.mvnbook.account.service;
import java.util.HashMap;
import java.util.Map;
import com.juvenxu.mvnbook.account.captcha.AccountCaptchaException;
import com.juvenxu.mvnbook.account.captcha.AccountCaptchaService;
import com.juvenxu.mvnbook.account.captcha.RandomGenerator;
import com.juvenxu.mvnbook.account.email.AccountEmailException;
import com.juvenxu.mvnbook.account.email.AccountEmailService;
import com.juvenxu.mvnbook.account.persist.Account;
import com.juvenxu.mvnbook.account.persist.AccountPersistException;
import com.juvenxu.mvnbook.account.persist.AccountPersistService;
public class AccountServiceImpl
implements AccountService
{
private Map<String, String> activationMap = new HashMap<String, String>();
private AccountPersistService accountPersistService;
private AccountEmailService accountEmailService;
private AccountCaptchaService accountCaptchaService;
public AccountPersistService getAccountPersistService()
{
return accountPersistService;
}
public void setAccountPersistService( AccountPersistService accountPersistService )
{
this.accountPersistService = accountPersistService;
}
public AccountEmailService getAccountEmailService()
{
return accountEmailService;
}
public void setAccountEmailService( AccountEmailService accountEmailService )
{
this.accountEmailService = accountEmailService;
}
public AccountCaptchaService getAccountCaptchaService()
{
return accountCaptchaService;
}
public void setAccountCaptchaService( AccountCaptchaService accountCaptchaService )
{
this.accountCaptchaService = accountCaptchaService;
}
public byte[] generateCaptchaImage( String captchaKey )
throws AccountServiceException
{
try
{
return accountCaptchaService.generateCaptchaImage( captchaKey );
}
catch ( AccountCaptchaException e )
{
throw new AccountServiceException( "Unable to generate Captcha Image.", e );
}
}
public String generateCaptchaKey()
throws AccountServiceException
{
try
{
return accountCaptchaService.generateCaptchaKey();
}
catch ( AccountCaptchaException e )
{
throw new AccountServiceException( "Unable to generate Captcha key.", e );
}
}
public void signUp( SignUpRequest signUpRequest )
throws AccountServiceException
{
try
{
if ( !signUpRequest.getPassword().equals( signUpRequest.getConfirmPassword() ) )
{
throw new AccountServiceException( "2 passwords do not match." );
}
if ( !accountCaptchaService
.validateCaptcha( signUpRequest.getCaptchaKey(), signUpRequest.getCaptchaValue() ) )
{
throw new AccountServiceException( "Incorrect Captcha." );
}
Account account = new Account();
account.setId( signUpRequest.getId() );
account.setEmail( signUpRequest.getEmail() );
account.setName( signUpRequest.getName() );
account.setPassword( signUpRequest.getPassword() );
account.setActivated( false );
accountPersistService.createAccount( account );
String activationId = RandomGenerator.getRandomString();
activationMap.put( activationId, account.getId() );
String link = signUpRequest.getActivateServiceUrl().endsWith( "/" ) ? signUpRequest.getActivateServiceUrl()
+ activationId : signUpRequest.getActivateServiceUrl() + "?key=" + activationId;
accountEmailService.sendMail( account.getEmail(), "Please Activate Your Account", link );
}
catch ( AccountCaptchaException e )
{
throw new AccountServiceException( "Unable to validate captcha.", e );
}
catch ( AccountPersistException e )
{
throw new AccountServiceException( "Unable to create account.", e );
}
catch ( AccountEmailException e )
{
throw new AccountServiceException( "Unable to send actiavtion mail.", e );
}
}
public void activate( String activationId )
throws AccountServiceException
{
String accountId = activationMap.get( activationId );
if ( accountId == null )
{
throw new AccountServiceException( "Invalid account activation ID." );
}
try
{
Account account = accountPersistService.readAccount( accountId );
account.setActivated( true );
accountPersistService.updateAccount( account );
}
catch ( AccountPersistException e )
{
throw new AccountServiceException( "Unable to activate account." );
}
}
public void login( String id, String password )
throws AccountServiceException
{
try
{
Account account = accountPersistService.readAccount( id );
if ( account == null )
{
throw new AccountServiceException( "Account does not exist." );
}
if ( !account.isActivated() )
{
throw new AccountServiceException( "Account is disabled." );
}
if ( !account.getPassword().equals( password ) )
{
throw new AccountServiceException( "Incorrect password." );
}
}
catch ( AccountPersistException e )
{
throw new AccountServiceException( "Unable to log in.", e );
}
}
}

View File

@@ -0,0 +1,100 @@
package com.juvenxu.mvnbook.account.service;
public class SignUpRequest
{
private String id;
private String email;
private String name;
private String password;
private String confirmPassword;
private String captchaKey;
private String captchaValue;
private String activateServiceUrl;
public String getId()
{
return id;
}
public void setId( String id )
{
this.id = id;
}
public String getEmail()
{
return email;
}
public void setEmail( String email )
{
this.email = email;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public String getPassword()
{
return password;
}
public void setPassword( String password )
{
this.password = password;
}
public String getConfirmPassword()
{
return confirmPassword;
}
public void setConfirmPassword( String confirmPassword )
{
this.confirmPassword = confirmPassword;
}
public String getCaptchaKey()
{
return captchaKey;
}
public void setCaptchaKey( String captchaKey )
{
this.captchaKey = captchaKey;
}
public String getCaptchaValue()
{
return captchaValue;
}
public void setCaptchaValue( String captchaValue )
{
this.captchaValue = captchaValue;
}
public String getActivateServiceUrl()
{
return activateServiceUrl;
}
public void setActivateServiceUrl( String activateServiceUrl )
{
this.activateServiceUrl = activateServiceUrl;
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="accountService" class="com.juvenxu.mvnbook.account.service.AccountServiceImpl">
<property name="accountPersistService" ref="accountPersistService" />
<property name="accountEmailService" ref="accountEmailService" />
<property name="accountCaptchaService" ref="accountCaptchaService" />
</bean>
</beans>

View File

@@ -0,0 +1,123 @@
package com.juvenxu.mvnbook.account.service;
import static junit.framework.Assert.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.mail.Message;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetup;
import com.juvenxu.mvnbook.account.captcha.AccountCaptchaService;
public class AccountServiceTest
{
private GreenMail greenMail;
private AccountService accountService;
@Before
public void prepare()
throws Exception
{
String[] springConfigFiles = {
"account-email.xml",
"account-persist.xml",
"account-captcha.xml",
"account-service.xml" };
ApplicationContext ctx = new ClassPathXmlApplicationContext( springConfigFiles );
AccountCaptchaService accountCaptchaService = (AccountCaptchaService) ctx.getBean( "accountCaptchaService" );
List<String> preDefinedTexts = new ArrayList<String>();
preDefinedTexts.add( "12345" );
preDefinedTexts.add( "abcde" );
accountCaptchaService.setPreDefinedTexts( preDefinedTexts );
accountService = (AccountService) ctx.getBean( "accountService" );
greenMail = new GreenMail( ServerSetup.SMTP );
greenMail.setUser( "test@juvenxu.com", "123456" );
greenMail.start();
File persistDataFile = new File( "target/test-classes/persist-data.xml" );
if ( persistDataFile.exists() )
{
persistDataFile.delete();
}
}
@Test
public void testAccountService()
throws Exception
{
// 1. Get captcha
String captchaKey = accountService.generateCaptchaKey();
accountService.generateCaptchaImage( captchaKey );
String captchaValue = "12345";
// 2. Submit sign up Request
SignUpRequest signUpRequest = new SignUpRequest();
signUpRequest.setCaptchaKey( captchaKey );
signUpRequest.setCaptchaValue( captchaValue );
signUpRequest.setId( "juven" );
signUpRequest.setEmail( "test@juvenxu.com" );
signUpRequest.setName( "Juven Xu" );
signUpRequest.setPassword( "admin123" );
signUpRequest.setConfirmPassword( "admin123" );
signUpRequest.setActivateServiceUrl( "http://localhost:8080/account/activate" );
accountService.signUp( signUpRequest );
// 3. Read activation link
greenMail.waitForIncomingEmail( 2000, 1 );
Message[] msgs = greenMail.getReceivedMessages();
assertEquals( 1, msgs.length );
assertEquals( "Please Activate Your Account", msgs[0].getSubject() );
String activationLink = GreenMailUtil.getBody( msgs[0] ).trim();
// 3a. Try login but not activated
try
{
accountService.login( "juven", "admin123" );
fail( "Disabled account shouldn't be able to log in." );
}
catch ( AccountServiceException e )
{
}
// 4. Activate account
String activationCode = activationLink.substring( activationLink.lastIndexOf( "=" ) + 1 );
accountService.activate( activationCode );
// 5. Login with correct id and password
accountService.login( "juven", "admin123" );
// 5a. Login with incorrect password
try
{
accountService.login( "juven", "admin456" );
fail( "Password is incorrect, shouldn't be able to login." );
}
catch ( AccountServiceException e )
{
}
}
@After
public void stopMailServer()
throws Exception
{
greenMail.stop();
}
}

View File

@@ -0,0 +1,9 @@
email.protocol=smtp
email.host=localhost
email.port=25
email.username=test@juvenxu.com
email.password=123456
email.auth=true
email.systemEmail=admin@juvenxu.com
persist.file=${project.build.testOutputDirectory}/persist-data.xml

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>account-web</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,6 @@
#Thu Jul 01 16:54:17 CST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -0,0 +1,9 @@
#Sun May 09 19:55:57 CST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -0,0 +1,63 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>account-web</artifactId>
<packaging>war</packaging>
<name>Account Web</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>account-service</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.1.0.RC1</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webAppConfig>
<contextPath>/account</contextPath>
</webAppConfig>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,57 @@
package com.juvenxu.mvnbook.account.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.juvenxu.mvnbook.account.service.AccountService;
import com.juvenxu.mvnbook.account.service.AccountServiceException;
public class ActivateServlet
extends HttpServlet
{
private static final long serialVersionUID = 3668445055149826106L;
private ApplicationContext context;
@Override
public void init()
throws ServletException
{
super.init();
context = WebApplicationContextUtils.getWebApplicationContext( getServletContext() );
}
@Override
protected void doGet( HttpServletRequest req, HttpServletResponse resp )
throws ServletException,
IOException
{
String key = req.getParameter( "key" );
if ( key == null || key.length() == 0 )
{
resp.sendError( 400, "No activation key provided." );
return;
}
AccountService service = (AccountService) context.getBean( "accountService" );
try
{
service.activate( key );
resp.getWriter().write( "Account is activated, now you can login." );
}
catch ( AccountServiceException e )
{
resp.sendError( 400, "Unable to activate account" );
return;
}
}
}

View File

@@ -0,0 +1,59 @@
package com.juvenxu.mvnbook.account.web;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.juvenxu.mvnbook.account.service.AccountService;
import com.juvenxu.mvnbook.account.service.AccountServiceException;
public class CaptchaImageServlet
extends HttpServlet
{
private ApplicationContext context;
private static final long serialVersionUID = 5274323889605521606L;
@Override
public void init()
throws ServletException
{
super.init();
context = WebApplicationContextUtils.getWebApplicationContext( getServletContext() );
}
public void doGet( HttpServletRequest request, HttpServletResponse response )
throws ServletException,
IOException
{
String key = request.getParameter( "key" );
if ( key == null || key.length() == 0 )
{
response.sendError( 400, "No Captcha Key Found" );
}
else
{
AccountService service = (AccountService) context.getBean( "accountService" );
try
{
response.setContentType( "image/jpeg" );
OutputStream out = response.getOutputStream();
out.write( service.generateCaptchaImage( key ) );
out.close();
}
catch ( AccountServiceException e )
{
response.sendError( 400, e.getMessage() );
}
}
}
}

View File

@@ -0,0 +1,57 @@
package com.juvenxu.mvnbook.account.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.juvenxu.mvnbook.account.service.AccountService;
import com.juvenxu.mvnbook.account.service.AccountServiceException;
public class LoginServlet
extends HttpServlet
{
private static final long serialVersionUID = 929160785365121624L;
private ApplicationContext context;
@Override
public void init()
throws ServletException
{
super.init();
context = WebApplicationContextUtils.getWebApplicationContext( getServletContext() );
}
@Override
protected void doPost( HttpServletRequest req, HttpServletResponse resp )
throws ServletException,
IOException
{
String id = req.getParameter( "id" );
String password = req.getParameter( "password" );
if ( id == null || id.length() == 0 || password == null || password.length() == 0 )
{
resp.sendError( 400, "incomplete parameter" );
return;
}
AccountService service = (AccountService) context.getBean( "accountService" );
try
{
service.login( id, password );
resp.getWriter().print( "Login Successful!" );
}
catch ( AccountServiceException e )
{
resp.sendError( 400, e.getMessage() );
}
}
}

View File

@@ -0,0 +1,79 @@
package com.juvenxu.mvnbook.account.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.juvenxu.mvnbook.account.service.AccountService;
import com.juvenxu.mvnbook.account.service.AccountServiceException;
import com.juvenxu.mvnbook.account.service.SignUpRequest;
public class SignUpServlet
extends HttpServlet
{
private static final long serialVersionUID = 4784742296013868199L;
private ApplicationContext context;
@Override
public void init()
throws ServletException
{
super.init();
context = WebApplicationContextUtils.getWebApplicationContext( getServletContext() );
}
@Override
protected void doPost( HttpServletRequest req, HttpServletResponse resp )
throws ServletException,
IOException
{
String id = req.getParameter( "id" );
String email = req.getParameter( "email" );
String name = req.getParameter( "name" );
String password = req.getParameter( "password" );
String confirmPassword = req.getParameter( "confirm_password" );
String captchaKey = req.getParameter( "captcha_key" );
String captchaValue = req.getParameter( "captcha_value" );
if ( id == null || id.length() == 0 || email == null || email.length() == 0 || name == null
|| name.length() == 0 || password == null || password.length() == 0 || confirmPassword == null
|| confirmPassword.length() == 0 || captchaKey == null || captchaKey.length() == 0 || captchaValue == null
|| captchaValue.length() == 0 )
{
resp.sendError( 400, "Parameter Incomplete." );
return;
}
AccountService service = (AccountService) context.getBean( "accountService" );
SignUpRequest request = new SignUpRequest();
request.setId( id );
request.setEmail( email );
request.setName( name );
request.setPassword( password );
request.setConfirmPassword( confirmPassword );
request.setCaptchaKey( captchaKey );
request.setCaptchaValue( captchaValue );
request.setActivateServiceUrl( getServletContext().getRealPath( "/" ) + "activate" );
try
{
service.signUp( request );
resp.getWriter().print( "Account is created, please check your mail box for activation link." );
}
catch ( AccountServiceException e )
{
resp.sendError( 400, e.getMessage() );
return;
}
}
}

Some files were not shown because too many files have changed in this diff Show More