├── .gitignore ├── mail_demo ├── src │ ├── main │ │ ├── webapp │ │ │ ├── css │ │ │ │ ├── homepage.css │ │ │ │ ├── reset.css │ │ │ │ ├── mail_share.css │ │ │ │ └── jquery-ui-1.8.13.custom.css │ │ │ ├── js │ │ │ │ ├── homepage.js │ │ │ │ ├── namespace.js │ │ │ │ ├── mail_share.js │ │ │ │ └── jquery-ui-1.8.13.custom.min.js │ │ │ ├── WEB-INF │ │ │ │ ├── ftl │ │ │ │ │ ├── layouts │ │ │ │ │ │ ├── footer.ftl │ │ │ │ │ │ ├── header.ftl │ │ │ │ │ │ └── main.ftl │ │ │ │ │ ├── mail │ │ │ │ │ │ ├── share_success.ftl │ │ │ │ │ │ ├── share_dialog.ftl │ │ │ │ │ │ ├── share_failure.ftl │ │ │ │ │ │ ├── share_load.ftl │ │ │ │ │ │ └── share_form.ftl │ │ │ │ │ ├── components │ │ │ │ │ │ └── get_start.ftl │ │ │ │ │ ├── homepage.ftl │ │ │ │ │ └── product │ │ │ │ │ │ ├── show.ftl │ │ │ │ │ │ ├── edit.ftl │ │ │ │ │ │ ├── new.ftl │ │ │ │ │ │ └── index.ftl │ │ │ │ ├── view-context.xml │ │ │ │ ├── mybatis-context.xml │ │ │ │ ├── freemarker-context.xml │ │ │ │ ├── mail-context.xml │ │ │ │ ├── servlet-context.xml │ │ │ │ └── web.xml │ │ │ ├── favicon.ico │ │ │ ├── error_403.html │ │ │ ├── error_404.html │ │ │ └── error_500.html │ │ ├── resources │ │ │ ├── share_mail.ftl │ │ │ ├── mybatis.properties │ │ │ ├── web.config.properties │ │ │ ├── mybatis_config.xml │ │ │ ├── log4j.properties │ │ │ └── sql │ │ │ │ └── database_create.sql │ │ └── java │ │ │ └── org │ │ │ └── fssle │ │ │ └── sample │ │ │ ├── api │ │ │ └── GuavaApi.java │ │ │ ├── mail │ │ │ ├── Mailer.java │ │ │ ├── MailMessageBuilder.java │ │ │ ├── MailForm.java │ │ │ ├── MailShareService.java │ │ │ ├── MailErrors.java │ │ │ ├── Mail.java │ │ │ ├── SimpleMailer.java │ │ │ ├── TemplateMailMessageBuilder.java │ │ │ ├── MailService.java │ │ │ ├── MailValidator.java │ │ │ └── MailShareForm.java │ │ │ ├── controller │ │ │ ├── HomeController.java │ │ │ ├── MailController.java │ │ │ └── ProductController.java │ │ │ ├── presenter │ │ │ ├── ProductsPresenter.java │ │ │ ├── ProductPresenter.java │ │ │ └── MailSharePresenter.java │ │ │ ├── form │ │ │ └── ProductForm.java │ │ │ ├── pojo │ │ │ └── Product.java │ │ │ ├── mapper │ │ │ ├── MyBatisConnectionFactory.java │ │ │ ├── ProductMapper.java │ │ │ └── ProductDAO.java │ │ │ ├── service │ │ │ └── ProductsService.java │ │ │ └── interceptor │ │ │ └── LoggerInterceptor.java │ └── test │ │ └── java │ │ └── org │ │ └── fssle │ │ └── sample │ │ ├── mail │ │ ├── mail-test.ftl │ │ ├── TemplateMailMessageBuilderTest.java │ │ ├── SimpleMailerTest.java │ │ ├── MailValidatorTest.java │ │ └── MailServiceTest.java │ │ ├── controller │ │ ├── HomeControllerTest.java │ │ ├── ProductControllerTest.java │ │ └── MailControllerTest.java │ │ ├── mapper │ │ └── ProductDAOTest.java │ │ └── api │ │ └── GuavaApiTest.java ├── README.md ├── home.iml └── pom.xml ├── template ├── src │ ├── main │ │ ├── webapp │ │ │ └── WEB-INF │ │ │ │ ├── css │ │ │ │ ├── reset.css │ │ │ │ └── homepage.css │ │ │ │ ├── js │ │ │ │ └── homepage.js │ │ │ │ ├── ftl │ │ │ │ ├── layouts │ │ │ │ │ ├── footer.ftl │ │ │ │ │ ├── header.ftl │ │ │ │ │ └── main.ftl │ │ │ │ ├── components │ │ │ │ │ └── get_start.ftl │ │ │ │ └── homepage.ftl │ │ │ │ ├── servlet-context.xml │ │ │ │ ├── freemarker-context.xml │ │ │ │ └── web.xml │ │ ├── resources │ │ │ ├── web.config.properties │ │ │ └── freemarker.properties │ │ └── java │ │ │ └── org │ │ │ └── fssle │ │ │ └── sample │ │ │ └── controller │ │ │ └── HomeController.java │ └── test │ │ └── java │ │ └── org │ │ └── fssle │ │ └── sample │ │ └── controller │ │ └── HomeControllerTest.java ├── README.md ├── home.iml ├── pom.xml └── home.iws └── .gitmodules /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | logs -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/css/homepage.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/css/reset.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/js/homepage.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/css/mail_share.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/css/reset.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/js/homepage.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/src/main/resources/web.config.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/css/homepage.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/layouts/footer.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/layouts/header.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/ftl/layouts/footer.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/ftl/layouts/header.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/mail/mail-test.ftl: -------------------------------------------------------------------------------- 1 | Hello, ${sender} -------------------------------------------------------------------------------- /template/src/main/resources/freemarker.properties: -------------------------------------------------------------------------------- 1 | webRoot=http://localhost:8080/home/ 2 | use.cache=false -------------------------------------------------------------------------------- /mail_demo/src/main/resources/share_mail.ftl: -------------------------------------------------------------------------------- 1 | ${imageUrl} 2 | Message from ${senderName}: 3 | ${message} 4 | 5 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lite/java-libs/master/mail_demo/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/api/GuavaApi.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.api; 2 | 3 | public class GuavaApi { 4 | } 5 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/mail/share_success.ftl: -------------------------------------------------------------------------------- 1 | Your email has been sent to ${to} 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "spring-mvc-showcase"] 2 | path = spring-mvc-showcase 3 | url = git://github.com/SpringSource/spring-mvc-showcase.git 4 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/Mailer.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | public interface Mailer { 4 | void send(Mail mail); 5 | } 6 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/components/get_start.ftl: -------------------------------------------------------------------------------- 1 | <#macro getStart message> 2 | 3 | <#if message??> 4 | 5 |

${message}

6 | 7 | 8 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/ftl/components/get_start.ftl: -------------------------------------------------------------------------------- 1 | <#macro getStart message> 2 | 3 | <#if message??> 4 | 5 |

${message}

6 | 7 | 8 | -------------------------------------------------------------------------------- /mail_demo/src/main/resources/mybatis.properties: -------------------------------------------------------------------------------- 1 | jdbc.driverClassName= com.mysql.jdbc.Driver 2 | jdbc.url=jdbc:mysql://localhost:3306/mail_demo 3 | jdbc.username=root 4 | jdbc.password= -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/mail/share_dialog.ftl: -------------------------------------------------------------------------------- 1 | <#import "share_form.ftl" as shareForm/> 2 | 3 |
4 | <@shareForm.mailForm imageShare /> 5 |
6 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/mail/share_failure.ftl: -------------------------------------------------------------------------------- 1 | <#import "share_form.ftl" as shareForm/> 2 | 3 |
4 | <@shareForm.mailForm imageShare /> 5 |
6 | -------------------------------------------------------------------------------- /mail_demo/src/main/resources/web.config.properties: -------------------------------------------------------------------------------- 1 | webRoot=/home/ 2 | 3 | use.cache=false 4 | 5 | smtp.host=smtp.163.com 6 | smtp.port=25 7 | smtp.username=twtwtest2011@163.com 8 | smtp.password=123456 9 | 10 | 11 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/MailMessageBuilder.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import java.util.Map; 4 | 5 | public interface MailMessageBuilder { 6 | String build(Map model); 7 | } 8 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/MailForm.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import java.util.Map; 4 | 5 | public interface MailForm { 6 | MailErrors validate(); 7 | Mail toMail(String from, String text); 8 | Map getModel(); 9 | } 10 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/MailShareService.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | public class MailShareService extends MailService{ 4 | public MailShareService() { 5 | TemplateMailMessageBuilder mailMessageBuilder = new TemplateMailMessageBuilder(); 6 | mailMessageBuilder.setTemplate("share_mail.ftl"); 7 | setMailMessageBuilder(mailMessageBuilder); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/error_403.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 403 Error Page 6 | 7 | 8 |
9 |

Access Forbidden

10 | 11 |

We are very sorry for this. This error has been logged and we will resolve it ASAP.

12 | 13 |
14 | 15 |
16 |
17 | 18 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/error_404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 Error Page 6 | 7 | 8 |
9 |

Resource Not Found

10 | 11 |

We are very sorry for this. This error has been logged and we will resolve it ASAP.

12 | 13 |
14 | 15 |
16 |
17 | 18 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/error_500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 500 Error Page 6 | 7 | 8 |
9 |

Internal Error Occurs

10 | 11 |

We are very sorry for this. This error has been loged and we will resolve it ASAP.

12 | 13 |
14 | 15 |
16 |
17 | 18 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/js/namespace.js: -------------------------------------------------------------------------------- 1 | var ns = function (nsString, register) { 2 | var namespace = function (namespaceString) { 3 | var names = namespaceString.split('.'); 4 | var root = window; 5 | 6 | for (var i in names) { 7 | if (names.hasOwnProperty(i)) { 8 | root[names[i]] = root[names[i]] || {}; 9 | root = root[names[i]]; 10 | } 11 | } 12 | 13 | return root; 14 | }; 15 | register(namespace(nsString)); 16 | }; -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/homepage.ftl: -------------------------------------------------------------------------------- 1 | <#import "./components/get_start.ftl" as getStart> 2 | 3 | <@layout.mainLayout 4 | styles=["css/homepage.css"] 5 | jscripts=["js/homepage.js"]> 6 | 7 |
8 |
9 | <@getStart.getStart message /> 10 |
11 |
12 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /template/README.md: -------------------------------------------------------------------------------- 1 | # Run 2 | 3 | mvn tomcat:run 4 | 5 | # References: 6 | 7 | ## SpringMVC 8 | 9 | http://maestric.com/doc/java/spring 10 | http://github.com/SpringSource/spring-mvc-showcase 11 | 12 | ## Freemarker 13 | 14 | http://freemarker.sourceforge.net/docs/index.html 15 | 16 | ## Guava 17 | 18 | http://codemunchies.com/2009/10/beautiful-code-with-google-collections-guava-and-static-imports-part-1/ 19 | http://codemunchies.com/2009/10/diving-into-the-google-guava-library-part-2/ 20 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.ui.ModelMap; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | public class HomeController { 9 | 10 | @RequestMapping(value = "/") 11 | public String index(ModelMap modelMap) { 12 | modelMap.put("message", "There is default message."); 13 | return "homepage"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/product/show.ftl: -------------------------------------------------------------------------------- 1 | <#import "../mail/share_load.ftl" as shareLoad> 2 | 3 | <@layout.mainLayout 4 | styles=[] 5 | jscripts=[]> 6 | 7 |
8 | 9 | ${product.id} 10 | ${product.name} 11 | This product url is ${product.url} 12 | 13 | edit 14 | delete 15 | index 16 | 17 | <@shareLoad.shareLink product.id/> 18 | <@shareLoad.shareMedia /> 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/ftl/homepage.ftl: -------------------------------------------------------------------------------- 1 | <#import "./components/get_start.ftl" as getStart> 2 | 3 | <@layout.mainLayout 4 | styles=["css/homepage.css"] 5 | jscripts=["js/homepage.js"]> 6 | 7 |
8 |
9 | <@getStart.getStart message /> 10 |
11 |
12 | 13 |
14 |
    15 | <#list products as product> 16 |
  • ${product}
  • 17 | 18 |
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/presenter/ProductsPresenter.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.presenter; 2 | 3 | import org.fssle.sample.pojo.Product; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collection; 7 | import java.util.List; 8 | 9 | public class ProductsPresenter { 10 | private List products; 11 | 12 | public ProductsPresenter(Collection values) { 13 | products = new ArrayList(values); 14 | } 15 | 16 | public List getProducts() { 17 | return products; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/mail/share_load.ftl: -------------------------------------------------------------------------------- 1 | <#macro shareLink product_id> 2 | 3 | 4 | 5 | <#macro shareMedia> 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/product/edit.ftl: -------------------------------------------------------------------------------- 1 | <#import "../mail/share_load.ftl" as shareLoad> 2 | 3 | <@layout.mainLayout 4 | styles=[] 5 | jscripts=[]> 6 | 7 |
8 | 9 |
10 | Product Id: 11 | Product Name: 12 | 13 |
14 | 15 | index 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/product/new.ftl: -------------------------------------------------------------------------------- 1 | <#import "../mail/share_load.ftl" as shareLoad> 2 | 3 | <@layout.mainLayout 4 | styles=[] 5 | jscripts=[]> 6 | 7 |
8 | 9 |
10 | Product Id: 11 | Product Name: 12 | 13 |
14 | 15 | index 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/MailErrors.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import java.util.Map; 4 | 5 | import static com.google.common.collect.Maps.newHashMap; 6 | 7 | public class MailErrors { 8 | private Map errors = newHashMap(); 9 | 10 | public int getErrorCount() { 11 | return errors.size(); 12 | } 13 | 14 | public void rejectValue(String field, String defaultMessage) { 15 | errors.put(field, defaultMessage); 16 | } 17 | 18 | public String getErrorMessage(String validField) { 19 | return errors.containsKey(validField)?errors.get(validField):""; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/controller/HomeControllerTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.controller; 2 | 3 | import org.junit.Test; 4 | import org.springframework.ui.ModelMap; 5 | 6 | import static org.hamcrest.CoreMatchers.notNullValue; 7 | import static org.junit.Assert.assertThat; 8 | 9 | public class HomeControllerTest { 10 | 11 | private HomeController homeController = new HomeController(); 12 | private ModelMap modelMap; 13 | 14 | @Test 15 | public void should_render_with_default_products() { 16 | modelMap = new ModelMap(); 17 | homeController.index(modelMap); 18 | 19 | assertThat(modelMap.get("message"), notNullValue()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/product/index.ftl: -------------------------------------------------------------------------------- 1 | <@layout.mainLayout 2 | styles=[] 3 | jscripts=[]> 4 | 5 |
6 |
    7 | <#list products.products as product> 8 |
  • ${product.product_name} 9 | show 10 | edit 11 | delete 12 |
  • 13 | 14 |
15 | 16 | new 17 | delete all 18 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /template/src/test/java/org/fssle/sample/controller/HomeControllerTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.controller; 2 | 3 | import org.fssle.sample.controller.HomeController; 4 | import org.junit.Test; 5 | import org.springframework.ui.ModelMap; 6 | 7 | import static org.hamcrest.CoreMatchers.notNullValue; 8 | import static org.junit.Assert.assertThat; 9 | 10 | public class HomeControllerTest { 11 | @Test 12 | public void should_render_with_default() { 13 | 14 | ModelMap modelMap = new ModelMap(); 15 | HomeController homeController = new HomeController(); 16 | homeController.index(modelMap); 17 | 18 | assertThat(modelMap.get("message"), notNullValue()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/form/ProductForm.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.form; 2 | 3 | import org.fssle.sample.pojo.Product; 4 | 5 | public class ProductForm { 6 | private String productId; 7 | private String productName; 8 | 9 | public Product toProduct() { 10 | return new Product(productId, productName); 11 | } 12 | 13 | public String getProductId() { 14 | return productId; 15 | } 16 | 17 | public String getProductName() { 18 | return productName; 19 | } 20 | 21 | public void setProductId(String productId) { 22 | this.productId = productId; 23 | } 24 | 25 | public void setProductName(String productName) { 26 | this.productName = productName; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/view-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/presenter/ProductPresenter.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.presenter; 2 | 3 | import com.google.common.base.Joiner; 4 | import org.fssle.sample.pojo.Product; 5 | 6 | public class ProductPresenter { 7 | private String url; 8 | private Product product; 9 | 10 | public ProductPresenter(Product product) { 11 | this.product = product; 12 | } 13 | 14 | public ProductPresenter() { 15 | this.product = new Product(); 16 | } 17 | 18 | public String getUrl() { 19 | return Joiner.on("-").join("product", product.getProduct_id()); 20 | } 21 | 22 | public String getId(){ 23 | return product.getProduct_id(); 24 | } 25 | 26 | public String getName(){ 27 | return product.getProduct_name(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /mail_demo/src/main/resources/mybatis_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /template/src/main/java/org/fssle/sample/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.ui.ModelMap; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | @Controller 11 | public class HomeController { 12 | 13 | @RequestMapping(value="/") 14 | public String index(ModelMap modelMap) { 15 | List products = new ArrayList(); 16 | products.add("Ruby"); 17 | products.add("Perl"); 18 | products.add("Python"); 19 | modelMap.put("products", products); 20 | modelMap.put("message", "There is something languages."); 21 | 22 | return "homepage.ftl"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mail_demo/README.md: -------------------------------------------------------------------------------- 1 | # Run 2 | 3 | mvn tomcat:run 4 | 5 | # References: 6 | 7 | ## SpringMVC 8 | 9 | http://maestric.com/doc/java/spring 10 | http://github.com/SpringSource/spring-mvc-showcase 11 | 12 | ## Freemarker 13 | 14 | http://freemarker.sourceforge.net/docs/index.html 15 | 16 | ## Guava 17 | 18 | http://codemunchies.com/2009/10/beautiful-code-with-google-collections-guava-and-static-imports-part-1/ 19 | http://codemunchies.com/2009/10/diving-into-the-google-guava-library-part-2/ 20 | 21 | ## mockito 22 | 23 | http://code.google.com/p/mockito/wiki/MavenUsers 24 | 25 | ## log4j 26 | 27 | http://logging.apache.org/log4j/1.2/manual.html 28 | 29 | ## mybatis 30 | 31 | http://code.google.com/p/mybatis 32 | 33 | ## hibernate-validator 34 | 35 | http://docs.jboss.org/hibernate/validator/4.0.1/reference/en/html_single/ 36 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/Mail.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | public class Mail { 4 | private String from; 5 | private String replyTo; 6 | private String to; 7 | private String subject; 8 | private String text; 9 | 10 | public Mail(String from, String replyTo, String to, String subject, String text) { 11 | this.from = from; 12 | this.replyTo = replyTo; 13 | this.to = to; 14 | this.subject = subject; 15 | this.text = text; 16 | } 17 | 18 | public String getFrom() { 19 | return from; 20 | } 21 | 22 | public String getTo() { 23 | return to; 24 | } 25 | 26 | public String getReplyTo() { 27 | return replyTo; 28 | } 29 | 30 | public String getSubject() { 31 | return subject; 32 | } 33 | 34 | public String getText() { 35 | return text; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/ftl/layouts/main.ftl: -------------------------------------------------------------------------------- 1 | <#macro mainLayout 2 | styles = [] 3 | jscripts = []> 4 | 5 | 6 | 7 | 8 | 9 | 10 | <#list styles as css> 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 | <#include "header.ftl"/> 20 |
21 | <#nested/> 22 |
23 | <#include "footer.ftl"/> 24 |
25 | <#list jscripts as script> 26 | 27 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/layouts/main.ftl: -------------------------------------------------------------------------------- 1 | <#macro mainLayout 2 | styles = [] 3 | jscripts = []> 4 | 5 | 6 | 7 | 8 | 9 | 10 | <#list styles as css> 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | <#include "header.ftl"/> 21 |
22 | <#nested/> 23 |
24 | <#include "footer.ftl"/> 25 |
26 | <#list jscripts as script> 27 | 28 | 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/pojo/Product.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.pojo; 2 | 3 | import com.google.common.base.Joiner; 4 | 5 | public class Product { 6 | private String product_id; 7 | private String product_name; 8 | 9 | public Product() { 10 | this("", ""); 11 | } 12 | 13 | public Product(String productId, String productName) { 14 | this.product_id = productId; 15 | this.product_name = productName; 16 | } 17 | 18 | public void setProduct_name(String product_name) { 19 | this.product_name = product_name; 20 | } 21 | 22 | public void setProduct_id(String product_id) { 23 | this.product_id = product_id; 24 | } 25 | 26 | public String getProduct_id() { 27 | return product_id; 28 | } 29 | 30 | public String getProduct_name() { 31 | return product_name; 32 | } 33 | 34 | public String getUrl() { 35 | return Joiner.on("-").join("product", product_id); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /mail_demo/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | ### set log levels ### 2 | log4j.rootLogger = stdout, D, E 3 | 4 | ### stdout ### 5 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender 6 | log4j.appender.stdout.Target = System.out 7 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 8 | log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n 9 | 10 | ### file ### 11 | log4j.appender.D = org.apache.log4j.DailyRollingFileAppender 12 | log4j.appender.D.File = logs/log.log 13 | log4j.appender.D.Append = true 14 | log4j.appender.D.Threshold = DEBUG ## 15 | log4j.appender.D.layout = org.apache.log4j.PatternLayout 16 | log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n 17 | 18 | ### rolling ### 19 | log4j.appender.E = org.apache.log4j.DailyRollingFileAppender 20 | log4j.appender.E.File = logs/error.log 21 | log4j.appender.E.Append = true 22 | log4j.appender.E.Threshold = ERROR ## !!! 23 | log4j.appender.E.layout = org.apache.log4j.PatternLayout 24 | log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n -------------------------------------------------------------------------------- /mail_demo/src/main/resources/sql/database_create.sql: -------------------------------------------------------------------------------- 1 | # DROP database IF EXISTS mail_demo 2 | 3 | # CREATE database mail_demo; 4 | 5 | USE mail_demo; 6 | 7 | DROP TABLE IF EXISTS products; 8 | 9 | CREATE TABLE products ( 10 | product_id INTEGER NOT NULL PRIMARY KEY auto_increment, 11 | product_id VARCHAR(256) NOT NULL UNIQUE, 12 | product_name VARCHAR(256) NOT NULL 13 | ); 14 | 15 | CREATE TABLE test ( 16 | product_id INTEGER NOT NULL PRIMARY KEY auto_increment, 17 | product_id VARCHAR(256) NOT NULL UNIQUE, 18 | product_name VARCHAR(256) NOT NULL, 19 | hash VARCHAR(256) NOT NULL UNIQUE, 20 | created_at DATETIME NOT NULL, 21 | updated_at DATETIME NOT NULL 22 | ); 23 | 24 | INSERT INTO test (product_id, product_name, hash, created_at, updated_at) VALUES ('1', 'Ruby', uuid(), '2011-06-25T15:41:47', '2011-06-25T15:41:48'); 25 | INSERT INTO test (product_id, product_name, hash, created_at, updated_at) VALUES ('2', 'Perl', uuid(), '2011-06-25T15:41:48', '2011-06-25T15:42:48'); 26 | INSERT INTO test (product_id, product_name, hash, created_at, updated_at) VALUES ('3', 'Python', uuid(), '2011-06-25T15:41:49', '2011-06-25T15:43:48'); 27 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mapper/MyBatisConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mapper; 2 | 3 | import org.apache.ibatis.io.Resources; 4 | import org.apache.ibatis.session.SqlSessionFactory; 5 | import org.apache.ibatis.session.SqlSessionFactoryBuilder; 6 | 7 | import java.io.FileNotFoundException; 8 | import java.io.IOException; 9 | import java.io.Reader; 10 | 11 | public class MyBatisConnectionFactory { 12 | 13 | private static SqlSessionFactory sqlSessionFactory; 14 | 15 | static { 16 | try { 17 | String resource = "mybatis_config.xml"; 18 | Reader reader = Resources.getResourceAsReader(resource); 19 | if (sqlSessionFactory == null) { 20 | sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); 21 | sqlSessionFactory.getConfiguration().addMapper(ProductMapper.class); 22 | } 23 | } 24 | catch (FileNotFoundException fileNotFoundException) { 25 | fileNotFoundException.printStackTrace(); 26 | } 27 | catch (IOException iOException) { 28 | } 29 | } 30 | 31 | public static SqlSessionFactory getSqlSessionFactory() { 32 | return sqlSessionFactory; 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/SimpleMailer.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.mail.MailSender; 5 | import org.springframework.mail.SimpleMailMessage; 6 | import org.springframework.scheduling.annotation.Async; 7 | 8 | public class SimpleMailer implements Mailer { 9 | private MailSender mailSender; 10 | 11 | @Autowired 12 | public void setMailSender(MailSender mailSender) { 13 | this.mailSender = mailSender; 14 | } 15 | 16 | @Override 17 | public void send(Mail mail) { 18 | sendMail(mail); 19 | } 20 | 21 | @Async 22 | private void sendMail(Mail mail){ 23 | mailSender.send(toMailMessage(mail)); 24 | } 25 | 26 | private SimpleMailMessage toMailMessage(Mail mail) { 27 | SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); 28 | simpleMailMessage.setFrom(mail.getFrom()); 29 | simpleMailMessage.setTo(mail.getTo()); 30 | simpleMailMessage.setReplyTo(mail.getReplyTo()); 31 | simpleMailMessage.setSubject(mail.getSubject()); 32 | simpleMailMessage.setText(mail.getText()); 33 | return simpleMailMessage; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/mail/TemplateMailMessageBuilderTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import com.google.common.collect.Maps; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.Map; 8 | 9 | import static org.hamcrest.CoreMatchers.is; 10 | import static org.junit.Assert.assertThat; 11 | 12 | public class TemplateMailMessageBuilderTest { 13 | private static final String TEMPLATE = "org/fssle/sample/mail/mail-test.ftl"; 14 | private TemplateMailMessageBuilder builder; 15 | 16 | @Before 17 | public void setUp() throws Exception { 18 | builder = new TemplateMailMessageBuilder(); 19 | builder.setTemplate(TEMPLATE); 20 | } 21 | 22 | @Test 23 | public void should_return_message_with_model() { 24 | Map model = Maps.newHashMap(); 25 | model.put("sender", "Sender"); 26 | 27 | String message = builder.build(model); 28 | 29 | assertThat(message, is("Hello, Sender")); 30 | } 31 | 32 | @Test(expected = RuntimeException.class) 33 | public void should_throw_exception_while_fail_to_create_message() { 34 | Map model = Maps.newHashMap(); 35 | model.put("unknown", "Sender"); 36 | 37 | builder.build(model); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mapper/ProductMapper.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mapper; 2 | 3 | import org.apache.ibatis.annotations.Delete; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | import org.apache.ibatis.annotations.Update; 8 | import org.fssle.sample.pojo.Product; 9 | 10 | import java.util.List; 11 | 12 | public interface ProductMapper { 13 | 14 | @Select("SELECT product_id, product_name FROM products") 15 | List getProducts(); 16 | 17 | @Select("SELECT product_id, product_name FROM products WHERE product_id = #{productId}") 18 | Product getProduct(@Param("productId") String productId); 19 | 20 | @Delete("DELETE FROM products WHERE product_id=#{productId}") 21 | void deleteProduct(@Param("productId") String productId); 22 | 23 | @Insert("INSERT INTO products(product_id, product_name) VALUES( #{product.product_id}, #{product.product_name} )") 24 | void insertProduct(@Param("product")Product product); 25 | 26 | @Update("UPDATE products SET product_id = #{product.product_id}, product_name = #{product.product_name} where product_id = #{productId}") 27 | void updateProduct(@Param("productId") String productId, @Param("product")Product product); 28 | 29 | @Delete("DELETE FROM products") 30 | void deleteProducts(); 31 | } 32 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/TemplateMailMessageBuilder.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import freemarker.template.Configuration; 4 | import freemarker.template.Template; 5 | 6 | import java.io.IOException; 7 | import java.io.StringWriter; 8 | import java.io.Writer; 9 | import java.util.Map; 10 | 11 | public class TemplateMailMessageBuilder implements MailMessageBuilder { 12 | private Template template; 13 | 14 | public void setTemplate(String template) { 15 | try { 16 | this.template = createMailTemplate(template); 17 | } catch (IOException e) { 18 | throw new IllegalArgumentException("fail to create template", e); 19 | } 20 | } 21 | 22 | private Template createMailTemplate(String templateName) throws IOException { 23 | Configuration cfg = new Configuration(); 24 | cfg.setClassForTemplateLoading(this.getClass(), "/"); 25 | return cfg.getTemplate(templateName); 26 | } 27 | 28 | @Override 29 | public String build(Map model) { 30 | try { 31 | Writer writer = new StringWriter(); 32 | template.process(model, writer); 33 | writer.flush(); 34 | return writer.toString(); 35 | } catch (Exception e) { 36 | throw new RuntimeException("failed to build mail message", e); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/service/ProductsService.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.service; 2 | 3 | import org.fssle.sample.mapper.ProductDAO; 4 | import org.fssle.sample.pojo.Product; 5 | import org.fssle.sample.presenter.ProductPresenter; 6 | import org.fssle.sample.presenter.ProductsPresenter; 7 | 8 | public class ProductsService { 9 | private ProductDAO productDAO = new ProductDAO(); 10 | 11 | public ProductsPresenter createProductsPresenter() { 12 | return new ProductsPresenter(productDAO.getProducts()); 13 | } 14 | 15 | public ProductPresenter createProductPresenter() { 16 | return new ProductPresenter(); 17 | } 18 | 19 | public ProductPresenter createProductPresenter(String productId) { 20 | return new ProductPresenter(getProduct(productId)); 21 | } 22 | 23 | public void deleteProduct(String productId) { 24 | productDAO.deleteProduct(productId); 25 | } 26 | 27 | public void insertProduct(Product product) { 28 | productDAO.insertProduct(product); 29 | } 30 | 31 | public void updateProduct(String productId, Product product) { 32 | productDAO.updateProduct(productId, product); 33 | } 34 | 35 | public Product getProduct(String productId) { 36 | return productDAO.getProduct(productId); 37 | } 38 | 39 | public void deleteProducts() { 40 | productDAO.deleteProducts(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/mybatis-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/freemarker-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | rethrow 13 | layouts/main.ftl as layout 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/mail-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | true 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/MailService.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import org.fssle.sample.presenter.MailSharePresenter; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | public class MailService { 7 | private Mailer mailer; 8 | private String senderAddress; 9 | private MailMessageBuilder mailMessageBuilder; 10 | 11 | @Autowired 12 | public void setSenderAddress(String senderAddress) { 13 | this.senderAddress = senderAddress; 14 | } 15 | 16 | @Autowired 17 | public void setMailer(Mailer mailer) { 18 | this.mailer = mailer; 19 | } 20 | 21 | public void setMailMessageBuilder(MailMessageBuilder mailMessageBuilder) { 22 | this.mailMessageBuilder = mailMessageBuilder; 23 | } 24 | 25 | public void send(MailForm form) { 26 | form.validate(); 27 | Mail mail = createMessage(form); 28 | this.mailer.send(mail); 29 | } 30 | 31 | private Mail createMessage(MailForm form) { 32 | String text = mailMessageBuilder.build(form.getModel()); 33 | return form.toMail(senderAddress, text); 34 | } 35 | 36 | public MailSharePresenter createMailPresenter(String imageUrl) { 37 | return new MailSharePresenter(imageUrl); 38 | } 39 | 40 | public MailSharePresenter createMailPresenter(MailShareForm mailShareForm, MailErrors errors) { 41 | return new MailSharePresenter(mailShareForm, errors); 42 | } 43 | 44 | public MailErrors validate(MailShareForm mailShareForm) { 45 | return mailShareForm.validate(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/controller/ProductControllerTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.controller; 2 | 3 | import org.fssle.sample.presenter.ProductPresenter; 4 | import org.fssle.sample.presenter.ProductsPresenter; 5 | import org.fssle.sample.service.ProductsService; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.springframework.ui.ModelMap; 9 | 10 | import static org.hamcrest.CoreMatchers.notNullValue; 11 | import static org.junit.Assert.assertThat; 12 | 13 | public class ProductControllerTest { 14 | private ProductController productController = new ProductController(); 15 | private ModelMap modelMap; 16 | 17 | @Before 18 | public void setUp() throws Exception { 19 | productController.setProductsService(new ProductsService()); 20 | } 21 | 22 | @Test 23 | public void should_return_default_products() { 24 | modelMap = new ModelMap(); 25 | productController.index(modelMap); 26 | ProductsPresenter productsPresenter = (ProductsPresenter) modelMap.get("products"); 27 | 28 | assertThat(productsPresenter, notNullValue()); 29 | assertThat(productsPresenter.getProducts(), notNullValue()); 30 | } 31 | 32 | @Test 33 | public void should_return_with_single_product_by_id() { 34 | modelMap = new ModelMap(); 35 | productController.show("3", modelMap); 36 | ProductPresenter productPresenter = (ProductPresenter) modelMap.get("product"); 37 | 38 | assertThat(productPresenter, notNullValue()); 39 | assertThat(productPresenter.getUrl(), notNullValue()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/servlet-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | classpath:web.config.properties 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/MailValidator.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | public class MailValidator { 7 | private MailErrors errors; 8 | 9 | public MailValidator() { 10 | errors = new MailErrors(); 11 | } 12 | 13 | public MailErrors getErrors() { 14 | return errors; 15 | } 16 | 17 | public void validateEmail(String field, String value, String emptyMessage, String notEmailMessage) { 18 | try { 19 | rejectIfEmptyOrWhitespace(field, value, emptyMessage); 20 | rejectIfNotEmail(field, value, notEmailMessage); 21 | } catch (IllegalArgumentException e) { 22 | } 23 | } 24 | 25 | private void rejectIfEmptyOrWhitespace(String field, String value, String defaultMessage) throws IllegalArgumentException { 26 | if (value.trim().isEmpty()) { 27 | errors.rejectValue(field, defaultMessage); 28 | throw new IllegalArgumentException(defaultMessage); 29 | } 30 | } 31 | 32 | private void rejectIfNotEmail(String field, String value, String defaultMessage) throws IllegalArgumentException { 33 | String expression = "^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}$"; 34 | Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE); 35 | Matcher matcher = pattern.matcher(value); 36 | if (matcher.matches() == false) { 37 | errors.rejectValue(field, defaultMessage); 38 | throw new IllegalArgumentException(defaultMessage); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/presenter/MailSharePresenter.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.presenter; 2 | 3 | import org.fssle.sample.mail.MailErrors; 4 | import org.fssle.sample.mail.MailShareForm; 5 | 6 | public class MailSharePresenter { 7 | private String replyToErrorMessage; 8 | private String replyToError; 9 | private String toErrorMessage; 10 | private String toError; 11 | private MailShareForm emailShareForm; 12 | 13 | public MailSharePresenter(String imageUrl) { 14 | this.emailShareForm = new MailShareForm(imageUrl); 15 | this.replyToErrorMessage = ""; 16 | this.replyToError = ""; 17 | this.toErrorMessage = ""; 18 | this.toError = ""; 19 | } 20 | 21 | public MailSharePresenter(MailShareForm mailShareForm, MailErrors errors) { 22 | this.emailShareForm = mailShareForm; 23 | this.toErrorMessage = errors.getErrorMessage("to"); 24 | this.toError = toErrorMessage.isEmpty()?"":"error";; 25 | this.replyToErrorMessage = errors.getErrorMessage("replyTo"); 26 | this.replyToError = replyToErrorMessage.isEmpty()?"":"error"; 27 | } 28 | 29 | public MailShareForm getEmailShareForm() { 30 | return emailShareForm; 31 | } 32 | 33 | public String getReplyToErrorMessage() { 34 | return replyToErrorMessage; 35 | } 36 | 37 | public String getToErrorMessage() { 38 | return toErrorMessage; 39 | } 40 | 41 | public String getReplyToError() { 42 | return replyToError; 43 | } 44 | 45 | public String getToError() { 46 | return toError; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/mail/SimpleMailerTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import org.junit.Test; 4 | import org.springframework.mail.MailSender; 5 | import org.springframework.mail.javamail.JavaMailSenderImpl; 6 | 7 | import java.util.Properties; 8 | 9 | public class SimpleMailerTest { 10 | 11 | @Test(expected = RuntimeException.class) 12 | public void should_throw_exception_when_failed_to_send_mail() { 13 | SimpleMailer mailer = new SimpleMailer(); 14 | mailer.setMailSender(createMailSender("smtp.163.com", "", "")); 15 | Mail mail = createMail("from@email.com", "to@email.com", "replyTo@email.com", "subject", "text"); 16 | mailer.send(mail); 17 | } 18 | 19 | @Test 20 | public void should_send_mail() { 21 | SimpleMailer mailer = new SimpleMailer(); 22 | mailer.setMailSender(createMailSender("smtp.163.com", "twtwtest2011@163.com", "123456")); 23 | Mail mail = createMail("twtwtest2011@163.com", "to@email.com", "replyTo@email.com", "subject", "text"); 24 | mailer.send(mail); 25 | } 26 | 27 | private MailSender createMailSender(String host, String username, String password) { 28 | JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); 29 | mailSender.setHost(host); 30 | mailSender.setUsername(username); 31 | mailSender.setPassword(password); 32 | Properties prop = new Properties(); 33 | prop.setProperty("mail.smtp.auth", "true"); 34 | mailSender.setJavaMailProperties(prop); 35 | return mailSender; 36 | } 37 | 38 | private Mail createMail(String from, String to, String replyTo, String subject, String text) { 39 | return new Mail(from, replyTo, to, subject, text); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/ftl/mail/share_form.ftl: -------------------------------------------------------------------------------- 1 | <#macro mailForm imageShare> 2 |
3 | <#assign emailShareForm = imageShare.emailShareForm > 4 | 5 | 6 | 7 |
* required fields
8 |
9 | 10 | 11 |
12 |
13 | 14 | 15 |
${imageShare.replyToErrorMessage}
16 |
17 |
18 | 19 | 20 |
${imageShare.toErrorMessage}
21 |
22 |
23 | 24 | 25 |
26 |
27 | 28 | (a link to the page will be included in the message) 29 | 30 |
31 |
32 | 33 |
34 | -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/freemarker-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | classpath:freemarker.properties 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | rethrow 27 | layouts/main.ftl as layout 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/js/mail_share.js: -------------------------------------------------------------------------------- 1 | ns('FSS.sample.dialog', function(ns) { 2 | 3 | ns.getFields = function(fields, dialog) { 4 | var data = {}; 5 | $.each(fields, function(index, elem) { 6 | data[elem] = dialog.find("#" + elem).val(); 7 | }); 8 | return data; 9 | }; 10 | 11 | ns.initialize = function(options) { 12 | invoker = options['invoker']; 13 | title = options['title']; 14 | fields = options['fields']; 15 | url = options['url']; 16 | send = options['send']; 17 | 18 | dialog = $('
'); 19 | $(invoker).click(function() { 20 | $.ajax({url: url, global: false, success: ns.onShow}); 21 | }); 22 | }; 23 | 24 | 25 | ns.onShow = function(data) { 26 | dialog.html(data) 27 | .dialog({ 28 | hide: "explode", 29 | modal: true, 30 | width: 450 31 | }); 32 | 33 | $(".spinner").hide(); 34 | $(send).click(ns.onSend); 35 | }; 36 | 37 | ns.onSend = function() { 38 | $(".spinner").show(); 39 | $.ajax({url: url, global: false, type: "POST", 40 | data: (ns.getFields(fields, $(".share-dialog"))), 41 | success: function(data) { 42 | ns.onShow(data); 43 | }}); 44 | return false; 45 | }; 46 | }); 47 | 48 | ns('FSS.sample.share', function(ns) { 49 | ns.initialize = function() { 50 | FSS.sample.dialog.initialize({ 51 | invoker: '.share-link', 52 | title: 'Share', 53 | fields: ['imageUrl', 'senderName', 'replyTo', "to", "subject", 'message'], 54 | url: $(".share-link").attr("ajaxUrl"), 55 | send: '.send-share' 56 | }); 57 | } 58 | }); 59 | 60 | $(function() { 61 | FSS.sample.share.initialize(); 62 | }); -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/servlet-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | classpath:web.config.properties 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/controller/MailController.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.controller; 2 | 3 | import org.fssle.sample.mail.MailErrors; 4 | import org.fssle.sample.mail.MailService; 5 | import org.fssle.sample.mail.MailShareForm; 6 | import org.fssle.sample.service.ProductsService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.ui.ModelMap; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | 14 | @Controller 15 | public class MailController { 16 | 17 | @Autowired 18 | private ProductsService productsService; 19 | 20 | @Autowired 21 | private MailService mailService; 22 | 23 | public void setProductsService(ProductsService productsService) { 24 | this.productsService = productsService; 25 | } 26 | 27 | public void setMailService(MailService mailService) { 28 | this.mailService = mailService; 29 | } 30 | 31 | @RequestMapping(value = "/mail-share-{id}", method = RequestMethod.GET) 32 | public String show(@PathVariable("id") String productId, 33 | ModelMap modelMap) { 34 | String imageUrl = productsService.getProduct(productId).getUrl(); 35 | modelMap.put("imageShare", mailService.createMailPresenter(imageUrl)); 36 | return "mail/share_dialog"; 37 | } 38 | 39 | @RequestMapping(value = "/mail-share-{id}", method = RequestMethod.POST) 40 | public String post(@PathVariable("id") String productId, 41 | MailShareForm mailShareForm, ModelMap modelMap) { 42 | MailErrors errors = mailService.validate(mailShareForm); 43 | if(errors.getErrorCount()>0){ 44 | modelMap.put("imageShare", mailService.createMailPresenter(mailShareForm, errors)); 45 | return "mail/share_failure"; 46 | } 47 | mailService.send(mailShareForm); 48 | modelMap.put("to", mailShareForm.getTo()); 49 | return "mail/share_success"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/interceptor/LoggerInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.interceptor; 2 | 3 | import org.apache.log4j.Logger; 4 | import org.springframework.web.servlet.ModelAndView; 5 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | public class LoggerInterceptor extends HandlerInterceptorAdapter { 11 | 12 | private static final Logger logger = Logger.getLogger(LoggerInterceptor.class); 13 | 14 | //before the actual handler will be executed 15 | public boolean preHandle(HttpServletRequest request, 16 | HttpServletResponse response, Object handler) 17 | throws Exception { 18 | 19 | logger.info("request.getRequestURL: " + request.getRequestURL()); 20 | logger.info("request.getContextPath: " + request.getContextPath()); 21 | logger.info("request.getPathInfo: " + request.getPathInfo()); 22 | logger.info("request.getQueryString: " + request.getQueryString()); 23 | logger.info("request.getRequestURI: " + request.getRequestURI()); 24 | logger.info("request.getServerName: " + request.getServerName()); 25 | logger.info("request.getServerPort: " + request.getServerPort()); 26 | 27 | long startTime = System.currentTimeMillis(); 28 | request.setAttribute("startTime", startTime); 29 | 30 | return true; 31 | } 32 | 33 | //after the handler is executed 34 | public void postHandle( 35 | HttpServletRequest request, HttpServletResponse response, 36 | Object handler, ModelAndView modelAndView) 37 | throws Exception { 38 | 39 | long startTime = (Long) request.getAttribute("startTime"); 40 | 41 | long endTime = System.currentTimeMillis(); 42 | 43 | long executeTime = endTime - startTime; 44 | 45 | //modified the exisitng modelAndView 46 | modelAndView.addObject("executeTime", executeTime); 47 | 48 | //log it 49 | if (logger.isDebugEnabled()) { 50 | logger.debug("[" + handler + "] executeTime : " + executeTime + "ms"); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /template/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | appServlet 9 | org.springframework.web.servlet.DispatcherServlet 10 | 11 | contextConfigLocation 12 | /WEB-INF/servlet-context.xml 13 | 14 | 1 15 | 16 | 17 | 18 | appServlet 19 | / 20 | 21 | 22 | 23 | 24 | freemarker 25 | freemarker.ext.servlet.FreemarkerServlet 26 | 27 | 28 | TemplatePath 29 | / 30 | 31 | 32 | NoCache 33 | true 34 | 35 | 36 | ContentType 37 | text/html; charset=UTF-8 38 | 39 | 40 | 41 | template_update_delay 42 | 0 43 | 44 | 45 | default_encoding 46 | ISO-8859-1 47 | 48 | 49 | number_format 50 | 0.########## 51 | 52 | 53 | 1 54 | 55 | 56 | 57 | freemarker 58 | *.ftl 59 | 60 | 61 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/mail/MailValidatorTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.CoreMatchers.equalTo; 6 | import static org.hamcrest.CoreMatchers.is; 7 | import static org.hamcrest.CoreMatchers.notNullValue; 8 | import static org.junit.Assert.assertThat; 9 | 10 | public class MailValidatorTest { 11 | 12 | private static final String EMPTY_MESSAGE = "required"; 13 | private static final String NOT_EMAIL_MESSAGE = "invalid"; 14 | 15 | @Test 16 | public void should_return_valid_email_address() { 17 | MailValidator validator = new MailValidator(); 18 | String validField = "validField"; 19 | validator.validateEmail(validField, "valid@email.com", EMPTY_MESSAGE, NOT_EMAIL_MESSAGE); 20 | 21 | MailErrors errors = validator.getErrors(); 22 | assertThat(errors, notNullValue()); 23 | assertThat(errors.getErrorCount(), equalTo(0)); 24 | assertThat(errors.getErrorMessage(validField), is("")); 25 | } 26 | 27 | @Test 28 | public void should_return_invalid_email_address() { 29 | MailValidator validator = new MailValidator(); 30 | String invalidField = "invalidField"; 31 | validator.validateEmail(invalidField, "invalid.email.com", EMPTY_MESSAGE, NOT_EMAIL_MESSAGE); 32 | 33 | MailErrors errors = validator.getErrors(); 34 | assertThat(errors, notNullValue()); 35 | assertThat(errors.getErrorCount(), equalTo(1)); 36 | assertThat(errors.getErrorMessage(invalidField), is(NOT_EMAIL_MESSAGE)); 37 | } 38 | 39 | @Test 40 | public void should_return_invalid_empty_or_whitespace() { 41 | MailValidator validator = new MailValidator(); 42 | String whitespaceField = "whitespaceField"; 43 | String emptyField = "emptyField"; 44 | validator.validateEmail(whitespaceField, " ", EMPTY_MESSAGE, NOT_EMAIL_MESSAGE); 45 | validator.validateEmail(emptyField, "", EMPTY_MESSAGE, NOT_EMAIL_MESSAGE); 46 | 47 | MailErrors errors = validator.getErrors(); 48 | assertThat(errors, notNullValue()); 49 | assertThat(errors.getErrorCount(), equalTo(2)); 50 | assertThat(errors.getErrorMessage(whitespaceField), is(EMPTY_MESSAGE)); 51 | assertThat(errors.getErrorMessage(emptyField), is(EMPTY_MESSAGE)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/mapper/ProductDAOTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mapper; 2 | 3 | import org.fssle.sample.pojo.Product; 4 | import org.junit.After; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | import java.util.List; 9 | 10 | import static org.hamcrest.Matchers.equalTo; 11 | import static org.hamcrest.Matchers.is; 12 | import static org.hamcrest.Matchers.notNullValue; 13 | import static org.junit.Assert.assertNull; 14 | import static org.junit.Assert.assertThat; 15 | 16 | public class ProductDAOTest { 17 | 18 | private ProductDAO productDAO; 19 | 20 | @Before 21 | public void setUp() throws Exception { 22 | productDAO = new ProductDAO(); 23 | defaultProducts(); 24 | } 25 | 26 | @Test 27 | public void should_get_product_by_id() { 28 | assertNull(productDAO.getProduct("none")); 29 | Product product = productDAO.getProduct("3"); 30 | assertThat(product, notNullValue()); 31 | assertThat(product.getProduct_id(), is("3")); 32 | } 33 | 34 | @Test 35 | public void should_update_product_by_id() { 36 | productDAO.updateProduct("2", new Product("4", "product_four")); 37 | assertNull(productDAO.getProduct("2")); 38 | Product product = productDAO.getProduct("4"); 39 | assertThat(product, notNullValue()); 40 | assertThat(product.getProduct_name(), is("product_four")); 41 | } 42 | 43 | @Test 44 | public void should_delete_products() { 45 | productDAO.deleteProducts(); 46 | List products = productDAO.getProducts(); 47 | assertThat(products.size(), equalTo(0)); 48 | } 49 | 50 | @Test 51 | public void should_insert_product() { 52 | productDAO.insertProduct(new Product("4", "product_one")); 53 | productDAO.insertProduct(new Product("5", "product_two")); 54 | Product productOne = productDAO.getProduct("4"); 55 | assertThat(productOne.getProduct_name(), is("product_one")); 56 | Product productTwo = productDAO.getProduct("5"); 57 | assertThat(productTwo.getProduct_name(), is("product_two")); 58 | } 59 | 60 | @Test 61 | public void should_delete_product() { 62 | for (Product product : productDAO.getProducts()) { 63 | productDAO.deleteProduct(product.getProduct_id()); 64 | } 65 | List products = productDAO.getProducts(); 66 | assertThat(products.size(), equalTo(0)); 67 | } 68 | 69 | @After 70 | public void tearDown() throws Exception { 71 | defaultProducts(); 72 | } 73 | 74 | private void defaultProducts() { 75 | productDAO.deleteProducts(); 76 | productDAO.insertProduct(new Product("1", "Ruby")); 77 | productDAO.insertProduct(new Product("2", "Python")); 78 | productDAO.insertProduct(new Product("3", "Perl")); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | sample 9 | org.springframework.web.servlet.DispatcherServlet 10 | 11 | contextConfigLocation 12 | /WEB-INF/servlet-context.xml 13 | 14 | 1 15 | 16 | 17 | 18 | sample 19 | / 20 | 21 | 22 | 23 | default 24 | *.ico 25 | 26 | 27 | default 28 | *.css 29 | 30 | 31 | default 32 | *.gif 33 | 34 | 35 | default 36 | *.jpg 37 | 38 | 39 | default 40 | *.png 41 | 42 | 43 | default 44 | *.js 45 | 46 | 47 | default 48 | *.eot 49 | 50 | 51 | default 52 | *.svg 53 | 54 | 55 | default 56 | *.ttf 57 | 58 | 59 | default 60 | *.woff 61 | 62 | 63 | default 64 | *.html 65 | 66 | 67 | 68 | 500 69 | /error_500.html 70 | 71 | 72 | 403 73 | /error_403.html 74 | 75 | 76 | 404 77 | /error_404.html 78 | 79 | 80 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mail/MailShareForm.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class MailShareForm implements MailForm { 7 | private String senderName; 8 | private String replyTo; 9 | private String to; 10 | private String subject; 11 | private String message; 12 | private String imageUrl; 13 | 14 | public MailShareForm() { 15 | this(""); 16 | } 17 | 18 | public MailShareForm(String imageUrl) { 19 | this("", "", "", "", "", imageUrl); 20 | } 21 | 22 | public MailShareForm(String senderName, String replyTo, String to, String subject, String message, String imageUrl) { 23 | this.senderName = senderName; 24 | this.replyTo = replyTo; 25 | this.to = to; 26 | this.subject = subject; 27 | this.message = message; 28 | this.imageUrl = imageUrl; 29 | } 30 | 31 | @Override 32 | public MailErrors validate() { 33 | MailValidator mailValidator = new MailValidator(); 34 | String emptyMessage = "Please input email address"; 35 | String notEmailMessage = "Invalid email address"; 36 | mailValidator.validateEmail("replyTo", replyTo, emptyMessage, notEmailMessage); 37 | mailValidator.validateEmail("to", to, emptyMessage, notEmailMessage); 38 | return mailValidator.getErrors(); 39 | } 40 | 41 | @Override 42 | public Mail toMail(String from, String text) { 43 | return new Mail(from, replyTo, to, subject, text); 44 | } 45 | 46 | @Override 47 | public Map getModel() { 48 | Map model = new HashMap(); 49 | model.put("imageUrl", imageUrl); 50 | model.put("senderName", senderName); 51 | model.put("message", message); 52 | return model; 53 | } 54 | 55 | public String getSenderName() { 56 | return senderName; 57 | } 58 | 59 | public String getTo() { 60 | return to; 61 | } 62 | 63 | public String getReplyTo() { 64 | return replyTo; 65 | } 66 | 67 | public String getSubject() { 68 | return subject; 69 | } 70 | 71 | public String getMessage() { 72 | return message; 73 | } 74 | 75 | public String getImageUrl() { 76 | return imageUrl; 77 | } 78 | 79 | public void setSenderName(String senderName) { 80 | this.senderName = senderName; 81 | } 82 | 83 | public void setReplyTo(String replyTo) { 84 | this.replyTo = replyTo; 85 | } 86 | 87 | public void setTo(String to) { 88 | this.to = to; 89 | } 90 | 91 | public void setSubject(String subject) { 92 | this.subject = subject; 93 | } 94 | 95 | public void setMessage(String message) { 96 | this.message = message; 97 | } 98 | 99 | public void setImageUrl(String imageUrl) { 100 | this.imageUrl = imageUrl; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/controller/ProductController.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.controller; 2 | 3 | import org.fssle.sample.form.ProductForm; 4 | import org.fssle.sample.service.ProductsService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.ModelMap; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | 12 | @Controller 13 | public class ProductController { 14 | 15 | @Autowired 16 | ProductsService productsService; 17 | 18 | public void setProductsService(ProductsService productsService) { 19 | this.productsService = productsService; 20 | } 21 | 22 | @RequestMapping(value = "/product") 23 | public String index(ModelMap modelMap) { 24 | modelMap.put("products", productsService.createProductsPresenter()); 25 | return "product/index"; 26 | } 27 | 28 | @RequestMapping(value = "/product/{id}") 29 | public String show(@PathVariable("id") String productId, 30 | ModelMap modelMap) { 31 | modelMap.put("product", productsService.createProductPresenter(productId)); 32 | return "product/show"; 33 | } 34 | 35 | @RequestMapping(value = "/product/new") 36 | public String add(ModelMap modelMap) { 37 | modelMap.put("product", productsService.createProductPresenter()); 38 | return "product/new"; 39 | } 40 | 41 | @RequestMapping(value = "/product/new", method = RequestMethod.POST) 42 | public String create(ProductForm productForm, 43 | ModelMap modelMap) { 44 | productsService.insertProduct(productForm.toProduct()); 45 | return "redirect:/product"; 46 | } 47 | 48 | @RequestMapping(value = "/product/{id}/edit") 49 | public String edit(@PathVariable("id") String productId, 50 | ModelMap modelMap) { 51 | modelMap.put("product", productsService.createProductPresenter(productId)); 52 | return "product/edit"; 53 | } 54 | 55 | @RequestMapping(value = "/product/{id}/edit", method = RequestMethod.POST) 56 | public String update(@PathVariable("id") String productId, 57 | ProductForm productForm, 58 | ModelMap modelMap) { 59 | productsService.updateProduct(productId, productForm.toProduct()); 60 | return "redirect:/product"; 61 | } 62 | 63 | @RequestMapping(value = "/product/{id}/delete") 64 | public String destroy(@PathVariable("id") String productId, 65 | ModelMap modelMap) { 66 | productsService.deleteProduct(productId); 67 | return "redirect:/product"; 68 | } 69 | 70 | @RequestMapping(value = "/product/delete") 71 | public String deleteAll(ModelMap modelMap) { 72 | productsService.deleteProducts(); 73 | return "redirect:/product"; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/mail/MailServiceTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mail; 2 | 3 | 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.Map; 8 | 9 | import static org.hamcrest.CoreMatchers.is; 10 | import static org.junit.Assert.assertThat; 11 | import static org.mockito.Mockito.doThrow; 12 | import static org.mockito.Mockito.mock; 13 | 14 | public class MailServiceTest { 15 | private static final String MESSAGE = "fixed message"; 16 | private static final String SENDER_ADDRESS = "test-from@rea-group.com"; 17 | private MailService service; 18 | private StubMailer mailer; 19 | private MailMessageBuilder builder; 20 | 21 | @Before 22 | public void setUp() throws Exception { 23 | service = new MailService(); 24 | mailer = new StubMailer(); 25 | service.setMailer(mailer); 26 | builder = new StubMessageBuilder(MESSAGE); 27 | service.setMailMessageBuilder(builder); 28 | service.setSenderAddress(SENDER_ADDRESS); 29 | } 30 | 31 | @Test(expected = IllegalArgumentException.class) 32 | public void should_throw_exception_while_form_is_invalid() { 33 | MailForm form = createInvalidForm(); 34 | service.send(form); 35 | } 36 | 37 | @Test 38 | public void should_send_mail() { 39 | String sender = "test-sender"; 40 | String to = "test-to@rea-group.com"; 41 | String replyTo = "test-reply@rea-group.com"; 42 | String subject = "feedback"; 43 | 44 | MailForm form = createMailForm(sender, to, replyTo, subject, "", ""); 45 | service.send(form); 46 | 47 | Mail mail = mailer.getMail(); 48 | assertThat(mail.getFrom(), is(SENDER_ADDRESS)); 49 | assertThat(mail.getTo(), is(to)); 50 | assertThat(mail.getReplyTo(), is(replyTo)); 51 | assertThat(mail.getSubject(), is(subject)); 52 | assertThat(mail.getText(), is(MESSAGE)); 53 | } 54 | 55 | private MailShareForm createMailForm(String sender, String to, String replyTo, String subject, String message, String imageUrl) { 56 | return new MailShareForm(sender, replyTo, to, subject, message, imageUrl); 57 | } 58 | 59 | private MailForm createInvalidForm() { 60 | MailShareForm shareForm = mock(MailShareForm.class); 61 | doThrow(new IllegalArgumentException()).when(shareForm).validate(); 62 | return shareForm; 63 | } 64 | 65 | private static class StubMailer implements Mailer { 66 | private Mail mail; 67 | 68 | @Override 69 | public void send(Mail mail) { 70 | this.mail = mail; 71 | } 72 | 73 | public Mail getMail() { 74 | return mail; 75 | } 76 | } 77 | 78 | private static class StubMessageBuilder implements MailMessageBuilder { 79 | private String fixedMessage; 80 | 81 | public StubMessageBuilder(String fixedMessage) { 82 | this.fixedMessage = fixedMessage; 83 | } 84 | 85 | @Override 86 | public String build(Map model) { 87 | return this.fixedMessage; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /mail_demo/src/main/java/org/fssle/sample/mapper/ProductDAO.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.mapper; 2 | 3 | import org.apache.ibatis.session.SqlSession; 4 | import org.apache.ibatis.session.SqlSessionFactory; 5 | import org.fssle.sample.pojo.Product; 6 | 7 | import java.util.List; 8 | 9 | import static com.google.common.collect.Lists.newArrayList; 10 | 11 | public class ProductDAO { 12 | private SqlSessionFactory sqlSessionFactory; 13 | 14 | public ProductDAO() { 15 | sqlSessionFactory = MyBatisConnectionFactory.getSqlSessionFactory(); 16 | } 17 | 18 | public void deleteProducts() { 19 | SqlSession session = sqlSessionFactory.openSession(); 20 | try { 21 | ProductMapper mapper = session.getMapper(ProductMapper.class); 22 | mapper.deleteProducts(); 23 | session.commit(); 24 | } catch (Exception e) { 25 | System.out.println(e.getMessage()); 26 | } finally { 27 | session.close(); 28 | } 29 | } 30 | 31 | public List getProducts() { 32 | SqlSession session = sqlSessionFactory.openSession(); 33 | try { 34 | ProductMapper mapper = session.getMapper(ProductMapper.class); 35 | List list = mapper.getProducts(); 36 | return list; 37 | } catch (Exception e) { 38 | System.out.println(e.getMessage()); 39 | } finally { 40 | session.close(); 41 | } 42 | return newArrayList(); 43 | } 44 | 45 | public Product getProduct(String productId) { 46 | SqlSession session = sqlSessionFactory.openSession(); 47 | try { 48 | ProductMapper mapper = session.getMapper(ProductMapper.class); 49 | Product list = mapper.getProduct(productId); 50 | return list; 51 | } catch (Exception e) { 52 | System.out.println(e.getMessage()); 53 | } finally { 54 | session.close(); 55 | } 56 | return null; 57 | } 58 | 59 | public void updateProduct(String productId, Product product) { 60 | SqlSession session = sqlSessionFactory.openSession(); 61 | try { 62 | ProductMapper mapper = session.getMapper(ProductMapper.class); 63 | mapper.updateProduct(productId, product); 64 | session.commit(); 65 | } catch (Exception e) { 66 | System.out.println(e.getMessage()); 67 | } finally { 68 | session.close(); 69 | } 70 | } 71 | 72 | public void insertProduct(Product product) { 73 | SqlSession session = sqlSessionFactory.openSession(); 74 | try { 75 | ProductMapper mapper = session.getMapper(ProductMapper.class); 76 | mapper.insertProduct(product); 77 | session.commit(); 78 | } catch (Exception e) { 79 | System.out.println(e.getMessage()); 80 | } finally { 81 | session.close(); 82 | } 83 | } 84 | 85 | public void deleteProduct(String productId) { 86 | SqlSession session = sqlSessionFactory.openSession(); 87 | try { 88 | ProductMapper mapper = session.getMapper(ProductMapper.class); 89 | mapper.deleteProduct(productId); 90 | session.commit(); 91 | } catch (Exception e) { 92 | System.out.println(e.getMessage()); 93 | } finally { 94 | session.close(); 95 | } 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/controller/MailControllerTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.controller; 2 | 3 | import org.fssle.sample.mail.MailService; 4 | import org.fssle.sample.mail.MailShareForm; 5 | import org.fssle.sample.presenter.MailSharePresenter; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.springframework.ui.ModelMap; 9 | 10 | import static org.hamcrest.CoreMatchers.is; 11 | import static org.hamcrest.CoreMatchers.notNullValue; 12 | import static org.junit.Assert.assertThat; 13 | 14 | public class MailControllerTest { 15 | 16 | private MailController mailController = new MailController(); 17 | private ModelMap modelMap; 18 | 19 | @Before 20 | public void setUp() { 21 | mailController.setMailService(new MailService()); 22 | } 23 | 24 | @Test 25 | public void should_return_with_empty_image_share() { 26 | modelMap = new ModelMap(); 27 | mailController.show("15", modelMap); 28 | 29 | MailSharePresenter imageShare = (MailSharePresenter) modelMap.get("imageShare"); 30 | assertThat(imageShare, notNullValue()); 31 | assertThat(imageShare.getReplyToErrorMessage(), is("")); 32 | assertThat(imageShare.getToErrorMessage(), is("")); 33 | assertThat(imageShare.getReplyToError(), is("")); 34 | assertThat(imageShare.getToError(), is("")); 35 | } 36 | 37 | @Test 38 | public void should_send_email() { 39 | modelMap = new ModelMap(); 40 | String senderName = "senderName"; 41 | String to = "test-to@email.com"; 42 | String replyTo = "test-replyto@email.com"; 43 | String subject = "share subject"; 44 | String message = "bla bla"; 45 | String imageUrl = ""; 46 | MailShareForm mailShareForm = new MailShareForm(senderName, replyTo, to, subject, message, imageUrl); 47 | 48 | mailController.post("15", mailShareForm, modelMap); 49 | 50 | assertThat((String) modelMap.get("to"), is(to)); 51 | } 52 | 53 | @Test 54 | public void should_validate_failure_when_invalid_data() { 55 | modelMap = new ModelMap(); 56 | String senderName = "senderName"; 57 | String to = "invalid.email.com"; 58 | String replyTo = ""; 59 | String subject = "share subject"; 60 | String message = "bla bla"; 61 | String imageUrl = "http://127.0.0.1/url"; 62 | MailShareForm mailShareForm = new MailShareForm(senderName, replyTo, to, subject, message, imageUrl); 63 | mailController.post("15", mailShareForm, modelMap); 64 | 65 | MailSharePresenter imageShare = (MailSharePresenter) modelMap.get("imageShare"); 66 | assertThat(imageShare, notNullValue()); 67 | assertThat(imageShare.getToErrorMessage(), is("Invalid email address")); 68 | assertThat(imageShare.getReplyToErrorMessage(), is("Please input email address")); 69 | assertThat(imageShare.getToError(), is("error")); 70 | assertThat(imageShare.getReplyToError(), is("error")); 71 | } 72 | 73 | @Test 74 | public void should_return_form_when_validate_failure() { 75 | modelMap = new ModelMap(); 76 | String senderName = "senderName"; 77 | String to = "to.email.com"; 78 | String replyTo = "replyto@email.com"; 79 | String subject = "share subject"; 80 | String message = "bla bla"; 81 | String imageUrl = "http://127.0.0.1/url"; 82 | MailShareForm mailShareForm = new MailShareForm(senderName, replyTo, to, subject, message, imageUrl); 83 | mailController.post("15", mailShareForm, modelMap); 84 | 85 | MailSharePresenter imageShare = (MailSharePresenter) modelMap.get("imageShare"); 86 | assertThat(imageShare, notNullValue()); 87 | MailShareForm emailShareForm = imageShare.getEmailShareForm(); 88 | assertThat(emailShareForm.getSenderName(), is(senderName)); 89 | assertThat(emailShareForm.getTo(), is(to)); 90 | assertThat(emailShareForm.getReplyTo(), is(replyTo)); 91 | assertThat(emailShareForm.getSubject(), is(subject)); 92 | assertThat(emailShareForm.getMessage(), is(message)); 93 | assertThat(emailShareForm.getImageUrl(), is(imageUrl)); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /mail_demo/src/test/java/org/fssle/sample/api/GuavaApiTest.java: -------------------------------------------------------------------------------- 1 | package org.fssle.sample.api; 2 | 3 | import com.google.common.base.CaseFormat; 4 | import com.google.common.base.CharMatcher; 5 | import com.google.common.base.Function; 6 | import com.google.common.base.Joiner; 7 | import com.google.common.base.Preconditions; 8 | import com.google.common.base.Splitter; 9 | import com.google.common.base.Strings; 10 | import com.google.common.collect.Iterables; 11 | import com.google.common.io.Files; 12 | import com.google.common.io.Resources; 13 | import org.junit.Test; 14 | 15 | import java.io.File; 16 | import java.io.IOException; 17 | import java.net.URL; 18 | import java.util.List; 19 | 20 | import static com.google.common.collect.Lists.newArrayList; 21 | import static junit.framework.Assert.assertNull; 22 | import static org.hamcrest.Matchers.containsString; 23 | import static org.hamcrest.Matchers.is; 24 | import static org.junit.Assert.assertThat; 25 | 26 | public class GuavaApiTest { 27 | 28 | @Test 29 | public void should_return_when_string() { 30 | GuavaApi guavaApi = new GuavaApi(); 31 | 32 | assertNull(Strings.emptyToNull("")); 33 | assertThat(Strings.nullToEmpty(null), is("")); 34 | assertThat(Strings.isNullOrEmpty("") && Strings.isNullOrEmpty(null), is(true)); 35 | assertThat(Strings.repeat("java", 3), is("javajavajava")); 36 | } 37 | 38 | @Test 39 | public void should_return_when_charmatcher() { 40 | String source = "a1b2c3"; 41 | CharMatcher matcher = CharMatcher.DIGIT; 42 | assertThat(matcher.matches('8'), is(true)); 43 | assertThat(matcher.retainFrom(source), is("123")); 44 | assertThat(matcher.countIn(source), is(3)); 45 | assertThat(matcher.removeFrom(source), is("abc")); 46 | assertThat(matcher.trimFrom("1a2b3c4"), is("a2b3c")); 47 | } 48 | 49 | @Test 50 | public void should_return_when_joiner() { 51 | assertThat(Joiner.on("-").join("2011", "08", "04"), is("2011-08-04")); 52 | } 53 | 54 | @Test 55 | public void should_return_when_splitter() { 56 | assertThat(getSplitterLength(Splitter.on(',').split("a,b")), is(2)); 57 | assertThat(getSplitterLength(Splitter.on(',').trimResults().split("a , b")), is(2)); 58 | assertThat(getSplitterLength(Splitter.on(',').omitEmptyStrings().split("a,,b")), is(2)); 59 | } 60 | 61 | @Test 62 | public void should_return_when_char_format() { 63 | assertThat(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, "helloGuava"), is("HELLO_GUAVA")); 64 | assertThat(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, "hello-guava"), is("HelloGuava")); 65 | } 66 | 67 | @Test(expected = IllegalArgumentException.class) 68 | public void should_return_when_pre_condition() { 69 | int count = -1; 70 | Preconditions.checkArgument(count > 0, "must be positive: %s", count); 71 | } 72 | 73 | @Test 74 | public void should_return_when_file_io() throws IOException { 75 | File from = new File("README.md"); 76 | File to = new File("target/temp"); 77 | Files.copy(from, to); 78 | File renamed = new File("target/renamed"); 79 | Files.move(to, renamed); 80 | Files.copy(renamed, to); 81 | File target = new File("target"); 82 | Files.deleteDirectoryContents(target); 83 | Files.deleteRecursively(target); 84 | } 85 | 86 | // @Test 87 | public void should_return_when_resource() { 88 | URL url = Resources.getResource("web.config.properties"); 89 | assertThat(url.getPath(), containsString("target")); 90 | assertThat(url.getFile(), containsString("web.config.properties")); 91 | } 92 | 93 | // @Test 94 | public void should_return_when_iterator_transform() { 95 | List strings = newArrayList("abc", "def", ""); 96 | Iterable names = Iterables.transform(strings, new Function() { 97 | public String apply(String from) { 98 | return from.toUpperCase(); 99 | } 100 | }); 101 | assertThat(getSplitterLength(names), is(3)); 102 | } 103 | 104 | private int getSplitterLength(Iterable split) { 105 | return newArrayList(split).size(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /template/home.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /mail_demo/home.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /template/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | org.fssle.sample 6 | home 7 | home 8 | war 9 | 1.0.0-BUILD-SNAPSHOT 10 | 11 | 1.6 12 | 3.1.0.M2 13 | 1.6.10 14 | 1.6.1 15 | 16 | 17 | 18 | 19 | org.springframework 20 | spring-context 21 | ${org.springframework-version} 22 | 23 | 24 | 25 | commons-logging 26 | commons-logging 27 | 28 | 29 | 30 | 31 | org.springframework 32 | spring-webmvc 33 | ${org.springframework-version} 34 | 35 | 36 | 37 | org.aspectj 38 | aspectjrt 39 | ${org.aspectj-version} 40 | 41 | 42 | 43 | 44 | org.slf4j 45 | slf4j-api 46 | ${org.slf4j-version} 47 | 48 | 49 | org.slf4j 50 | jcl-over-slf4j 51 | ${org.slf4j-version} 52 | runtime 53 | 54 | 55 | org.slf4j 56 | slf4j-log4j12 57 | ${org.slf4j-version} 58 | runtime 59 | 60 | 61 | log4j 62 | log4j 63 | 1.2.16 64 | runtime 65 | 66 | 67 | 68 | 69 | javax.inject 70 | javax.inject 71 | 1 72 | 73 | 74 | 75 | 76 | javax.servlet 77 | servlet-api 78 | 2.5 79 | provided 80 | 81 | 82 | javax.servlet.jsp 83 | jsp-api 84 | 2.1 85 | provided 86 | 87 | 88 | javax.servlet.jsp.jstl 89 | jstl-api 90 | 1.2 91 | 92 | 93 | org.glassfish.web 94 | jstl-impl 95 | 1.2 96 | 97 | 98 | 99 | 100 | com.google.guava 101 | guava 102 | r09 103 | 104 | 105 | 106 | 107 | org.codehaus.jackson 108 | jackson-mapper-asl 109 | 1.8.1 110 | 111 | 112 | 113 | 114 | net.java.dev.rome 115 | rome 116 | 1.0.0 117 | 118 | 119 | 120 | 121 | javax.validation 122 | validation-api 123 | 1.0.0.GA 124 | 125 | 126 | org.hibernate 127 | hibernate-validator 128 | 4.1.0.Final 129 | 130 | 131 | 132 | 133 | joda-time 134 | joda-time 135 | 1.6.2 136 | 137 | 138 | 139 | 140 | org.freemarker 141 | freemarker 142 | 2.3.18 143 | 144 | 145 | 146 | 147 | commons-fileupload 148 | commons-fileupload 149 | 1.2.2 150 | 151 | 152 | commons-io 153 | commons-io 154 | 2.0.1 155 | 156 | 157 | 158 | 159 | junit 160 | junit 161 | 4.8.2 162 | test 163 | 164 | 165 | 166 | 167 | 168 | 169 | org.springframework.maven.snapshot 170 | Spring Maven Snapshot Repository 171 | http://maven.springframework.org/snapshot 172 | false 173 | true 174 | 175 | 176 | 177 | org.springframework.maven.milestone 178 | Spring Maven Milestone Repository 179 | http://maven.springframework.org/milestone 180 | false 181 | 182 | 183 | 184 | 185 | 186 | org.apache.maven.plugins 187 | maven-compiler-plugin 188 | 2.3.2 189 | 190 | ${java-version} 191 | ${java-version} 192 | 193 | 194 | 195 | org.apache.maven.plugins 196 | maven-dependency-plugin 197 | 198 | 199 | install 200 | install 201 | 202 | sources 203 | 204 | 205 | 206 | 207 | 208 | org.codehaus.mojo 209 | aspectj-maven-plugin 210 | 211 | 1.2 212 | 213 | 214 | 215 | org.aspectj 216 | aspectjrt 217 | ${org.aspectj-version} 218 | 219 | 220 | org.aspectj 221 | aspectjtools 222 | ${org.aspectj-version} 223 | 224 | 225 | 226 | 227 | 228 | compile 229 | test-compile 230 | 231 | 232 | 233 | 234 | true 235 | ${java-version} 236 | ${java-version} 237 | 238 | 239 | 240 | org.codehaus.mojo 241 | tomcat-maven-plugin 242 | 1.1 243 | 244 | 245 | 246 | 247 | -------------------------------------------------------------------------------- /mail_demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | org.fssle.sample 6 | home 7 | home 8 | war 9 | 1.0.0-BUILD-SNAPSHOT 10 | 11 | 1.6 12 | 3.1.0.M2 13 | 1.6.10 14 | 1.6.1 15 | 16 | 17 | 18 | 19 | org.springframework 20 | spring-context 21 | ${org.springframework-version} 22 | 23 | 24 | 25 | commons-logging 26 | commons-logging 27 | 28 | 29 | 30 | 31 | org.springframework 32 | spring-webmvc 33 | ${org.springframework-version} 34 | 35 | 36 | org.springframework 37 | spring-context-support 38 | ${org.springframework-version} 39 | 40 | 41 | 42 | 43 | org.aspectj 44 | aspectjrt 45 | ${org.aspectj-version} 46 | 47 | 48 | 49 | 50 | org.slf4j 51 | slf4j-api 52 | ${org.slf4j-version} 53 | 54 | 55 | org.slf4j 56 | jcl-over-slf4j 57 | ${org.slf4j-version} 58 | runtime 59 | 60 | 61 | org.slf4j 62 | slf4j-log4j12 63 | ${org.slf4j-version} 64 | runtime 65 | 66 | 67 | log4j 68 | log4j 69 | 1.2.9 70 | 71 | 72 | 73 | 74 | javax.inject 75 | javax.inject 76 | 1 77 | 78 | 79 | 80 | 81 | javax.servlet 82 | servlet-api 83 | 2.5 84 | provided 85 | 86 | 87 | javax.servlet.jsp 88 | jsp-api 89 | 2.1 90 | provided 91 | 92 | 93 | javax.servlet.jsp.jstl 94 | jstl-api 95 | 1.2 96 | 97 | 98 | org.glassfish.web 99 | jstl-impl 100 | 1.2 101 | 102 | 103 | 104 | 105 | javax.mail 106 | mail 107 | 1.4 108 | 109 | 110 | 111 | 112 | com.google.guava 113 | guava 114 | r09 115 | 116 | 117 | 118 | 119 | org.codehaus.jackson 120 | jackson-mapper-asl 121 | 1.8.1 122 | 123 | 124 | 125 | 126 | joda-time 127 | joda-time 128 | 1.6.2 129 | 130 | 131 | 132 | 133 | org.freemarker 134 | freemarker 135 | 2.3.18 136 | 137 | 138 | 139 | 140 | junit 141 | junit 142 | 4.8.2 143 | test 144 | 145 | 146 | 147 | 148 | org.mockito 149 | mockito-all 150 | 1.8.5 151 | 152 | 153 | org.hamcrest 154 | hamcrest-library 155 | 1.1 156 | 157 | 158 | 159 | 160 | org.hibernate 161 | hibernate-validator 162 | 4.1.0.Final 163 | 164 | 165 | 166 | 167 | org.mybatis 168 | mybatis-spring 169 | 1.0.0 170 | 171 | 172 | 173 | 174 | mysql 175 | mysql-connector-java 176 | 5.1.14 177 | 178 | 179 | 180 | 181 | 182 | 183 | org.springframework.maven.snapshot 184 | Spring Maven Snapshot Repository 185 | http://maven.springframework.org/snapshot 186 | 187 | false 188 | 189 | 190 | true 191 | 192 | 193 | 194 | 195 | org.springframework.maven.milestone 196 | Spring Maven Milestone Repository 197 | http://maven.springframework.org/milestone 198 | 199 | false 200 | 201 | 202 | 203 | 204 | 205 | 206 | org.apache.maven.plugins 207 | maven-compiler-plugin 208 | 2.3.2 209 | 210 | ${java-version} 211 | ${java-version} 212 | 213 | 214 | 215 | org.apache.maven.plugins 216 | maven-dependency-plugin 217 | 218 | 219 | install 220 | install 221 | 222 | sources 223 | 224 | 225 | 226 | 227 | 228 | org.codehaus.mojo 229 | aspectj-maven-plugin 230 | 231 | 1.2 232 | 233 | 234 | 235 | org.aspectj 236 | aspectjrt 237 | ${org.aspectj-version} 238 | 239 | 240 | org.aspectj 241 | aspectjtools 242 | ${org.aspectj-version} 243 | 244 | 245 | 246 | 247 | 248 | compile 249 | test-compile 250 | 251 | 252 | 253 | 254 | true 255 | ${java-version} 256 | ${java-version} 257 | 258 | 259 | 260 | org.codehaus.mojo 261 | tomcat-maven-plugin 262 | 1.1 263 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/css/jquery-ui-1.8.13.custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI CSS Framework 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * http://jquery.org/license 7 | * 8 | * http://docs.jquery.com/UI/Theming/API 9 | */ 10 | 11 | /* Layout helpers 12 | ----------------------------------*/ 13 | .ui-helper-hidden { display: none; } 14 | .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } 15 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } 16 | .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } 17 | .ui-helper-clearfix { display: inline-block; } 18 | /* required comment for clearfix to work in Opera \*/ 19 | * html .ui-helper-clearfix { height:1%; } 20 | .ui-helper-clearfix { display:block; } 21 | /* end clearfix */ 22 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } 23 | 24 | 25 | /* Interaction Cues 26 | ----------------------------------*/ 27 | .ui-state-disabled { cursor: default !important; } 28 | 29 | 30 | /* Icons 31 | ----------------------------------*/ 32 | 33 | /* states and images */ 34 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } 35 | 36 | 37 | /* Misc visuals 38 | ----------------------------------*/ 39 | 40 | /* Overlays */ 41 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } 42 | 43 | 44 | /* 45 | * jQuery UI CSS Framework 1.8.13 46 | * 47 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 48 | * Dual licensed under the MIT or GPL Version 2 licenses. 49 | * http://jquery.org/license 50 | * 51 | * http://docs.jquery.com/UI/Theming/API 52 | * 53 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ctl=themeroller 54 | */ 55 | 56 | 57 | /* Component containers 58 | ----------------------------------*/ 59 | .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } 60 | .ui-widget .ui-widget { font-size: 1em; } 61 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } 62 | .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_75_ffffff_1x400.png) 50% 50% repeat-x; color: #222222; } 63 | .ui-widget-content a { color: #222222; } 64 | .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } 65 | .ui-widget-header a { color: #222222; } 66 | 67 | /* Interaction states 68 | ----------------------------------*/ 69 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } 70 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } 71 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } 72 | .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } 73 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } 74 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } 75 | .ui-widget :active { outline: none; } 76 | 77 | /* Interaction Cues 78 | ----------------------------------*/ 79 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } 80 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } 81 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_inset-soft_95_fef1ec_1x100.png) 50% bottom repeat-x; color: #cd0a0a; } 82 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } 83 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } 84 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } 85 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } 86 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } 87 | 88 | /* Icons 89 | ----------------------------------*/ 90 | 91 | /* states and images */ 92 | .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } 93 | .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } 94 | .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } 95 | .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } 96 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } 97 | .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } 98 | .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } 99 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } 100 | 101 | /* positioning */ 102 | .ui-icon-carat-1-n { background-position: 0 0; } 103 | .ui-icon-carat-1-ne { background-position: -16px 0; } 104 | .ui-icon-carat-1-e { background-position: -32px 0; } 105 | .ui-icon-carat-1-se { background-position: -48px 0; } 106 | .ui-icon-carat-1-s { background-position: -64px 0; } 107 | .ui-icon-carat-1-sw { background-position: -80px 0; } 108 | .ui-icon-carat-1-w { background-position: -96px 0; } 109 | .ui-icon-carat-1-nw { background-position: -112px 0; } 110 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 111 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 112 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 113 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 114 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 115 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 116 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 117 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 118 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 119 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 120 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 121 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 122 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 123 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 124 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 125 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 126 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 127 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 128 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 129 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 130 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 131 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 132 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 133 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 134 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 135 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 136 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 137 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 138 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 139 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 140 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 141 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 142 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 143 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 144 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 145 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 146 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 147 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 148 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 149 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 150 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 151 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 152 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 153 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 154 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 155 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 156 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 157 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 158 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 159 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 160 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 161 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 162 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 163 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 164 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 165 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 166 | .ui-icon-arrow-4 { background-position: 0 -80px; } 167 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 168 | .ui-icon-extlink { background-position: -32px -80px; } 169 | .ui-icon-newwin { background-position: -48px -80px; } 170 | .ui-icon-refresh { background-position: -64px -80px; } 171 | .ui-icon-shuffle { background-position: -80px -80px; } 172 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 173 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 174 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 175 | .ui-icon-folder-open { background-position: -16px -96px; } 176 | .ui-icon-document { background-position: -32px -96px; } 177 | .ui-icon-document-b { background-position: -48px -96px; } 178 | .ui-icon-note { background-position: -64px -96px; } 179 | .ui-icon-mail-closed { background-position: -80px -96px; } 180 | .ui-icon-mail-open { background-position: -96px -96px; } 181 | .ui-icon-suitcase { background-position: -112px -96px; } 182 | .ui-icon-comment { background-position: -128px -96px; } 183 | .ui-icon-person { background-position: -144px -96px; } 184 | .ui-icon-print { background-position: -160px -96px; } 185 | .ui-icon-trash { background-position: -176px -96px; } 186 | .ui-icon-locked { background-position: -192px -96px; } 187 | .ui-icon-unlocked { background-position: -208px -96px; } 188 | .ui-icon-bookmark { background-position: -224px -96px; } 189 | .ui-icon-tag { background-position: -240px -96px; } 190 | .ui-icon-home { background-position: 0 -112px; } 191 | .ui-icon-flag { background-position: -16px -112px; } 192 | .ui-icon-calendar { background-position: -32px -112px; } 193 | .ui-icon-cart { background-position: -48px -112px; } 194 | .ui-icon-pencil { background-position: -64px -112px; } 195 | .ui-icon-clock { background-position: -80px -112px; } 196 | .ui-icon-disk { background-position: -96px -112px; } 197 | .ui-icon-calculator { background-position: -112px -112px; } 198 | .ui-icon-zoomin { background-position: -128px -112px; } 199 | .ui-icon-zoomout { background-position: -144px -112px; } 200 | .ui-icon-search { background-position: -160px -112px; } 201 | .ui-icon-wrench { background-position: -176px -112px; } 202 | .ui-icon-gear { background-position: -192px -112px; } 203 | .ui-icon-heart { background-position: -208px -112px; } 204 | .ui-icon-star { background-position: -224px -112px; } 205 | .ui-icon-link { background-position: -240px -112px; } 206 | .ui-icon-cancel { background-position: 0 -128px; } 207 | .ui-icon-plus { background-position: -16px -128px; } 208 | .ui-icon-plusthick { background-position: -32px -128px; } 209 | .ui-icon-minus { background-position: -48px -128px; } 210 | .ui-icon-minusthick { background-position: -64px -128px; } 211 | .ui-icon-close { background-position: -80px -128px; } 212 | .ui-icon-closethick { background-position: -96px -128px; } 213 | .ui-icon-key { background-position: -112px -128px; } 214 | .ui-icon-lightbulb { background-position: -128px -128px; } 215 | .ui-icon-scissors { background-position: -144px -128px; } 216 | .ui-icon-clipboard { background-position: -160px -128px; } 217 | .ui-icon-copy { background-position: -176px -128px; } 218 | .ui-icon-contact { background-position: -192px -128px; } 219 | .ui-icon-image { background-position: -208px -128px; } 220 | .ui-icon-video { background-position: -224px -128px; } 221 | .ui-icon-script { background-position: -240px -128px; } 222 | .ui-icon-alert { background-position: 0 -144px; } 223 | .ui-icon-info { background-position: -16px -144px; } 224 | .ui-icon-notice { background-position: -32px -144px; } 225 | .ui-icon-help { background-position: -48px -144px; } 226 | .ui-icon-check { background-position: -64px -144px; } 227 | .ui-icon-bullet { background-position: -80px -144px; } 228 | .ui-icon-radio-off { background-position: -96px -144px; } 229 | .ui-icon-radio-on { background-position: -112px -144px; } 230 | .ui-icon-pin-w { background-position: -128px -144px; } 231 | .ui-icon-pin-s { background-position: -144px -144px; } 232 | .ui-icon-play { background-position: 0 -160px; } 233 | .ui-icon-pause { background-position: -16px -160px; } 234 | .ui-icon-seek-next { background-position: -32px -160px; } 235 | .ui-icon-seek-prev { background-position: -48px -160px; } 236 | .ui-icon-seek-end { background-position: -64px -160px; } 237 | .ui-icon-seek-start { background-position: -80px -160px; } 238 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 239 | .ui-icon-seek-first { background-position: -80px -160px; } 240 | .ui-icon-stop { background-position: -96px -160px; } 241 | .ui-icon-eject { background-position: -112px -160px; } 242 | .ui-icon-volume-off { background-position: -128px -160px; } 243 | .ui-icon-volume-on { background-position: -144px -160px; } 244 | .ui-icon-power { background-position: 0 -176px; } 245 | .ui-icon-signal-diag { background-position: -16px -176px; } 246 | .ui-icon-signal { background-position: -32px -176px; } 247 | .ui-icon-battery-0 { background-position: -48px -176px; } 248 | .ui-icon-battery-1 { background-position: -64px -176px; } 249 | .ui-icon-battery-2 { background-position: -80px -176px; } 250 | .ui-icon-battery-3 { background-position: -96px -176px; } 251 | .ui-icon-circle-plus { background-position: 0 -192px; } 252 | .ui-icon-circle-minus { background-position: -16px -192px; } 253 | .ui-icon-circle-close { background-position: -32px -192px; } 254 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 255 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 256 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 257 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 258 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 259 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 260 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 261 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 262 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 263 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 264 | .ui-icon-circle-check { background-position: -208px -192px; } 265 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 266 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 267 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 268 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 269 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 270 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 271 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 272 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 273 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 274 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 275 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 276 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 277 | 278 | 279 | /* Misc visuals 280 | ----------------------------------*/ 281 | 282 | /* Corner radius */ 283 | .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } 284 | .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } 285 | .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } 286 | .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } 287 | .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } 288 | .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } 289 | .ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } 290 | .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } 291 | .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } 292 | 293 | /* Overlays */ 294 | .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } 295 | .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* 296 | * jQuery UI Dialog 1.8.13 297 | * 298 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 299 | * Dual licensed under the MIT or GPL Version 2 licenses. 300 | * http://jquery.org/license 301 | * 302 | * http://docs.jquery.com/UI/Dialog#theming 303 | */ 304 | .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } 305 | .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } 306 | .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 307 | .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } 308 | .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } 309 | .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } 310 | .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } 311 | .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } 312 | .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } 313 | .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } 314 | .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } 315 | .ui-draggable .ui-dialog-titlebar { cursor: move; } 316 | -------------------------------------------------------------------------------- /mail_demo/src/main/webapp/js/jquery-ui-1.8.13.custom.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * http://jquery.org/license 7 | * 8 | * http://docs.jquery.com/UI 9 | */ 10 | (function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.13", 11 | keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus(); 12 | b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this, 13 | "overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection", 14 | function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth, 15 | outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a,"tabindex"),d=isNaN(b); 16 | return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e= 17 | 0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+= 47 | a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b), 48 | g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery); 49 | ;/* 50 | * jQuery UI Dialog 1.8.13 51 | * 52 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 53 | * Dual licensed under the MIT or GPL Version 2 licenses. 54 | * http://jquery.org/license 55 | * 56 | * http://docs.jquery.com/UI/Dialog 57 | * 58 | * Depends: 59 | * jquery.ui.core.js 60 | * jquery.ui.widget.js 61 | * jquery.ui.button.js 62 | * jquery.ui.draggable.js 63 | * jquery.ui.mouse.js 64 | * jquery.ui.position.js 65 | * jquery.ui.resizable.js 66 | */ 67 | (function(c,l){var m={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},n={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true},o=c.attrFn||{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true,click:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false, 68 | position:{my:"center",at:"center",collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ 69 | b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), 70 | h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", 71 | e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); 72 | a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d,e;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== 73 | b.uiDialog[0]){e=c(this).css("z-index");isNaN(e)||(d=Math.max(d,e))}});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+= 74 | 1;d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== 75 | f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("
").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("
").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a, 76 | function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;var i=c('').click(function(){h.click.apply(b.element[0],arguments)}).appendTo(g);c.each(h,function(j,k){if(j!=="click")j in o?i[j](k):i.attr(j,k)});c.fn.button&&i.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close", 77 | handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition, 78 | originalSize:f.originalSize,position:f.position,size:f.size}}a=a===l?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize", 79 | f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "): 80 | [a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(c.extend({of:window},a));e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f); 81 | if(g in m)e=true;if(g in n)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"): 82 | e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a= 83 | this.options,b,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();e||this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height- 84 | b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.13",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "), 85 | create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(), 86 | height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){var b=c.inArray(a,this.instances);b!=-1&&this.oldInstances.push(this.instances.splice(b,1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var d=0;c.each(this.instances,function(){d=Math.max(d,this.css("z-index"))});this.maxZ=d},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight); 87 | b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a 2 | 3 | 4 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 51 | 52 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 130 | 131 | 132 | 133 | 136 | 137 | 140 | 141 | 142 | 143 | 146 | 147 | 150 | 151 | 154 | 155 | 158 | 159 | 162 | 163 | 166 | 167 | 168 | 169 | 172 | 173 | 176 | 177 | 180 | 181 | 184 | 185 | 188 | 189 | 192 | 193 | 196 | 197 | 198 | 199 | 202 | 203 | 206 | 207 | 210 | 211 | 214 | 215 | 216 | 217 | 220 | 221 | 224 | 225 | 228 | 229 | 232 | 233 | 236 | 237 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 292 | 293 | 294 | 295 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 318 | 319 | 320 | 321 | 338 | 339 | 340 | 359 | 360 | 361 | 362 | 363 | 371 | 372 | 373 | 374 | 375 | 376 | 382 | 383 | 384 | 385 | 386 | 400 | 401 | 402 | 403 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 425 | 426 | 427 | 514 | 515 | 516 | 517 | 518 | localhost 519 | 5050 520 | 521 | 522 | 523 | 524 | 540 | 541 | 542 | 543 | 1314895016373 544 | 1314895016373 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 588 | 615 | 616 | 617 | 618 | 619 | 622 | 623 | 624 | --------------------------------------------------------------------------------