├── .gitignore ├── LICENSE ├── README.md ├── example ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ └── works │ │ └── cirno │ │ └── mocha │ │ └── example │ │ ├── ExampleConfigurator.java │ │ ├── ParameterController.java │ │ ├── User.java │ │ ├── UserService.java │ │ ├── UserServiceImpl.java │ │ └── guice │ │ ├── ExampleModule.java │ │ └── GuicedListener.java │ ├── resources │ ├── log4j.properties │ └── works │ │ └── cirno │ │ └── mocha │ │ └── example │ │ └── spring │ │ └── applicationContext.xml │ └── webapp │ ├── WEB-INF │ ├── jsp │ │ ├── head.jsp │ │ ├── parameter-rest.jsp │ │ ├── parameter-show.jsp │ │ └── parameter.jsp │ └── web.xml │ └── default.css ├── mvc-core ├── .gitignore ├── pom.xml └── src │ ├── main │ └── java │ │ └── works │ │ └── cirno │ │ └── mocha │ │ ├── BasicMVCFactory.java │ │ ├── ClassComparator.java │ │ ├── CloseableResource.java │ │ ├── ConfigBuilder.java │ │ ├── ConfigBuilderImpl.java │ │ ├── Dispatcher.java │ │ ├── DispatcherFilter.java │ │ ├── DispatcherServlet.java │ │ ├── ExceptionHandler.java │ │ ├── InvokeContext.java │ │ ├── InvokeTarget.java │ │ ├── MVCConfig.java │ │ ├── MVCConfigurator.java │ │ ├── MVCInternalException.java │ │ ├── MultiPartItem.java │ │ ├── MultiPartItemCommon.java │ │ ├── ObjectFactory.java │ │ ├── ServletResultRendererConfig.java │ │ ├── ServletResultRendererConfigImpl.java │ │ ├── StartupPerformanceListener.java │ │ ├── TypeOrInstance.java │ │ ├── parameter │ │ ├── name │ │ │ ├── ASMParameterAnalyzer.java │ │ │ ├── AnnotationParameterAnalyzer.java │ │ │ ├── NamedParam.java │ │ │ ├── Parameter.java │ │ │ └── ParameterAnalyzer.java │ │ └── value │ │ │ ├── AbstractStringArrayConverter.java │ │ │ ├── AbstractValueSource.java │ │ │ ├── BeanParameterSource.java │ │ │ ├── CombianParameterSource.java │ │ │ ├── ConvertStrategy.java │ │ │ ├── DefaultParameterSource.java │ │ │ ├── FilePartArrayParameterSource.java │ │ │ ├── FilePartParameterSource.java │ │ │ ├── MapValueSource.java │ │ │ ├── MatcherValueSource.java │ │ │ ├── MatrixParameterSource.java │ │ │ ├── MultiPartStringArraySource.java │ │ │ ├── MultiPartStringSource.java │ │ │ ├── ParameterSource.java │ │ │ ├── RawParameterSource.java │ │ │ ├── RequestArrayValueSource.java │ │ │ ├── RequestValueSource.java │ │ │ ├── StringEnumConverter.java │ │ │ ├── StringPEConverter.java │ │ │ ├── TypedParameterSource.java │ │ │ ├── ValueConverter.java │ │ │ └── ValueSource.java │ │ ├── resolver │ │ ├── InvokeTargetCriteria.java │ │ ├── InvokeTargetResolver.java │ │ ├── PrefixDictInvokeTargetResolver.java │ │ ├── PrefixedInvokeTargetCriteria.java │ │ ├── RegexInvokeTargetResolver.java │ │ └── prd │ │ │ ├── LongTreePrefixDict.java │ │ │ ├── PrefixDict.java │ │ │ └── TreePrefixDict.java │ │ └── result │ │ ├── CodeResultRenderer.java │ │ ├── InputStreamResultRenderer.java │ │ ├── Renderer.java │ │ ├── ResultType.java │ │ ├── ServletResultRenderer.java │ │ └── View.java │ └── test │ ├── java │ └── works │ │ └── cirno │ │ └── mocha │ │ ├── ComparableClassWrapperTest.java │ │ ├── InvokeTargetResolverTest.java │ │ ├── MockInvokeTarget.java │ │ ├── parameter │ │ └── name │ │ │ ├── ASMParameterAnalyzerTest.java │ │ │ ├── ASMTestController.java │ │ │ ├── AnnotationParameterAnalyzerTest.java │ │ │ └── TestController.java │ │ └── resolver │ │ └── prd │ │ └── TreePrefixDictTest.java │ └── resources │ ├── log4j.properties │ ├── uris.list │ └── uritest.properties ├── mvc-inject-guice ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── works │ └── cirno │ └── mocha │ ├── GuiceMVCFactory.java │ ├── GuicedDispatcherFilter.java │ └── GuicedDispatcherServlet.java ├── mvc-inject-spring ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── works │ └── cirno │ └── mocha │ ├── SpringDispatcherFilter.java │ └── SpringMVCFactory.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .idea/ 3 | .settings/ 4 | .project 5 | .classpath 6 | *.iml 7 | pom.xml.tag 8 | pom.xml.releaseBackup 9 | pom.xml.versionsBackup 10 | pom.xml.next 11 | release.properties 12 | dependency-reduced-pom.xml 13 | buildNumber.properties 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Mocha MVC, just another lightweight WebMVC framework 2 | 3 | Inspired by Google [Guice](https://github.com/google/guice), this is a small web MVC framework focused on lightweight and performance. 4 | 5 | It works well with [Spring](https://spring.io) and Guice, also it can work with other DIs or even without any DIs. 6 | 7 | # Feature 8 | 9 | * Use DSL to configure url mappings, get rid of XML ( You can also Google Guice to get rid of XML totally ;) ) 10 | 11 | * Automatic parameter resolve without any configuration 12 | 13 | * Fast and lightweight 14 | 15 | 16 | # Quick start 17 | 18 | There are only 4 steps start a new project with Mocha MVC, no DIs are required. 19 | 20 | 1) Create a maven ( packaging war of course ) project, add following code in pom.xml 21 | 22 | ``` xml 23 | 24 | 25 | cw-releases 26 | Cirnoworks Releases 27 | http://repo1.cirnoworks.com/releases/ 28 | 29 | true 30 | 31 | 32 | false 33 | 34 | default 35 | 36 | 37 | cw-snapshots 38 | Cirnoworks Snapshots 39 | http://repo1.cirnoworks.com/snapshots/ 40 | 41 | false 42 | 43 | 44 | true 45 | 46 | default 47 | 48 | 49 | 50 | 51 | javax.servlet 52 | javax.servlet-api 53 | 3.0.1 54 | provided 55 | 56 | 57 | 58 | org.slf4j 59 | slf4j-simple 60 | 1.7.12 61 | 62 | 63 | works.cirno.mocha 64 | mvc-core 65 | 0.1-SNAPSHOT 66 | 67 | 68 | ``` 69 | 70 | 2) Create Controller class 71 | 72 | ``` java 73 | package example; 74 | 75 | import works.cirno.mocha.*; 76 | 77 | public class HelloController { 78 | void hello(PrintWriter writer, String name){ 79 | writer.print("Hello " + name); 80 | } 81 | } 82 | ``` 83 | 84 | 3) Create Configurator class 85 | 86 | ``` java 87 | package example; 88 | 89 | import works.cirno.mocha.*; 90 | 91 | public class HelloConfigurator extends MVCConfigurator { 92 | public void configure(){ 93 | serve("/hello/${name}").with(HelloController.class, "hello"); 94 | } 95 | } 96 | ``` 97 | 98 | 4) Add Mocha's dispatcher filter into web.xml 99 | ``` xml 100 | 101 | dispatcher 102 | works.cirno.mocha.DispatcherFilter 103 | 104 | configurator 105 | example.HelloController 106 | 107 | 108 | ``` 109 | 110 | Run it! Access /hello/YourName under your contextPath from browser, the result will be "Hello YourName" 111 | 112 | # More 113 | 114 | Sorry for lack of document now, please read the example project for integration with Spring/Guice and more usage. 115 | 116 | There will a detailed document in the wiki, so please stay tuned! 117 | 118 | # License 119 | 120 | The MIT License (MIT) 121 | 122 | Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 123 | 124 | Permission is hereby granted, free of charge, to any person obtaining a copy 125 | of this software and associated documentation files (the "Software"), to deal 126 | in the Software without restriction, including without limitation the rights 127 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 128 | copies of the Software, and to permit persons to whom the Software is 129 | furnished to do so, subject to the following conditions: 130 | 131 | The above copyright notice and this permission notice shall be included in all 132 | copies or substantial portions of the Software. 133 | 134 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 135 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 136 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 137 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 138 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 139 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 140 | SOFTWARE. 141 | 142 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /example/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | works.cirno.mocha 6 | mvc 7 | 0.1-SNAPSHOT 8 | 9 | example 10 | Mocha MVC example with Spring ans Guice 11 | war 12 | 13 | 14 | true 15 | 16 | 17 | 18 | 19 | javax.servlet 20 | javax.servlet-api 21 | 3.0.1 22 | provided 23 | 24 | 25 | 26 | javax.servlet 27 | jstl 28 | 1.2 29 | 30 | 31 | 32 | 35 | org.jboss.spec.javax.servlet 36 | jboss-servlet-api_3.0_spec 37 | 1.0.2.Final 38 | provided 39 | 40 | 41 | 42 | org.ow2.asm 43 | asm-tree 44 | 4.0 45 | 46 | 47 | 48 | works.cirno.mocha 49 | mvc-inject-spring 50 | ${project.version} 51 | 52 | 53 | 54 | works.cirno.mocha 55 | mvc-inject-guice 56 | ${project.version} 57 | 58 | 59 | 60 | org.springframework 61 | spring-web 62 | 3.0.0.RELEASE 63 | 64 | 65 | 66 | org.slf4j 67 | slf4j-log4j12 68 | 1.7.12 69 | 70 | 71 | 72 | com.fasterxml.jackson.core 73 | jackson-core 74 | 2.6.3 75 | 76 | 77 | 78 | commons-io 79 | commons-io 80 | 2.4 81 | 82 | 83 | 84 | commons-codec 85 | commons-codec 86 | 1.10 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /example/src/main/java/works/cirno/mocha/example/ExampleConfigurator.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.example; 2 | 3 | import works.cirno.mocha.MVCConfigurator; 4 | 5 | /** 6 | * 7 | */ 8 | public class ExampleConfigurator extends MVCConfigurator { 9 | 10 | @Override 11 | public void configure() { 12 | 13 | // Extract common parameters 14 | all(new Runnable() { 15 | 16 | @Override 17 | public void run() { 18 | serve("/parameter").withMethod("index").forward("success").to("/WEB-INF/jsp/parameter.jsp"); 19 | serve("/parameter/show") 20 | .withMethod("show") 21 | .forward("success").to("/WEB-INF/jsp/parameter-show.jsp"); 22 | } 23 | }).with(ParameterController.class); 24 | 25 | // Restful styled APIs with simple expression 26 | serve("/parameter/+${userId}").with(ParameterController.class, "user") 27 | .forward("success").to("/WEB-INF/jsp/parameter-rest.jsp"); 28 | 29 | serve("/parameter/+${userId}", "POST").with(ParameterController.class, "userPost"); 30 | 31 | serve("/parameter/+${userId}.json") 32 | .with(ParameterController.class, "userJson"); 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /example/src/main/java/works/cirno/mocha/example/ParameterController.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.example; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | 6 | import javax.inject.Inject; 7 | import javax.inject.Named; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | import com.fasterxml.jackson.core.JsonFactory; 12 | import com.fasterxml.jackson.core.JsonGenerator; 13 | 14 | import works.cirno.mocha.result.View; 15 | 16 | public class ParameterController { 17 | @Inject 18 | @Named("userService") 19 | private UserService userService; 20 | 21 | private JsonFactory jsonFactory = new JsonFactory(); 22 | 23 | public String index() { 24 | // Direct return a view name to redirect / forward to configured view. 25 | return "success"; 26 | } 27 | 28 | public View show(User user) { 29 | 30 | // Return view with attributes, attributes will put to 31 | // HttpServletRequest 32 | return new View("success") 33 | .attribute("user", user); 34 | } 35 | 36 | public View user(String userId) { 37 | User user = userService.getUser(userId); 38 | return new View("success") 39 | .attribute("userId", userId) 40 | .attribute("user", user); 41 | } 42 | 43 | public void userPost(final String userId, User user, HttpServletRequest req, HttpServletResponse resp) 44 | throws IOException { 45 | userService.saveUser(userId, user); 46 | resp.sendRedirect(req.getContextPath() + "/parameter/+" + userId + ".json"); 47 | 48 | } 49 | 50 | public Object userJson(String userId, PrintWriter out) throws IOException { 51 | User user = userService.getUser(userId); 52 | if (user != null) { 53 | try (JsonGenerator gen = jsonFactory.createGenerator(out)) { 54 | gen.writeStartObject(); 55 | { 56 | gen.writeStringField("title", user.getTitle()); 57 | gen.writeStringField("firstName", user.getFirstName()); 58 | gen.writeStringField("lastName", user.getLastName()); 59 | gen.writeStringField("tel", user.getTel()); 60 | gen.writeObjectField("income", user.getIncome()); 61 | } 62 | gen.writeEndObject(); 63 | } 64 | return null; 65 | } else { 66 | return 404; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /example/src/main/java/works/cirno/mocha/example/User.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.example; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.net.URLEncoder; 6 | 7 | import org.apache.commons.codec.binary.Base64; 8 | import org.apache.commons.io.IOUtils; 9 | 10 | public class User { 11 | private String username; 12 | private String title; 13 | private String firstName; 14 | private String lastName; 15 | private String tel; 16 | private String photoUrl; 17 | private Float income; 18 | 19 | public String getUsername() { 20 | return username; 21 | } 22 | 23 | public void setUsername(String username) { 24 | this.username = username; 25 | } 26 | 27 | public String getTitle() { 28 | return title; 29 | } 30 | 31 | public void setTitle(String title) { 32 | this.title = title; 33 | } 34 | 35 | public String getFirstName() { 36 | return firstName; 37 | } 38 | 39 | public void setFirstName(String firstName) { 40 | this.firstName = firstName; 41 | } 42 | 43 | public String getLastName() { 44 | return lastName; 45 | } 46 | 47 | public void setLastName(String lastName) { 48 | this.lastName = lastName; 49 | } 50 | 51 | public String getTel() { 52 | return tel; 53 | } 54 | 55 | public void setTel(String tel) { 56 | this.tel = tel; 57 | } 58 | 59 | public String getPhotoUrl() { 60 | return photoUrl; 61 | } 62 | 63 | public Float getIncome() { 64 | return income; 65 | } 66 | 67 | public void setIncome(Float income) { 68 | this.income = income; 69 | } 70 | 71 | public void setPhoto(InputStream photo) throws IOException { 72 | if (photo != null) { 73 | byte[] content = IOUtils.toByteArray(photo); 74 | photoUrl = "data:;base64," + URLEncoder.encode(Base64.encodeBase64String(content), "utf-8"); 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /example/src/main/java/works/cirno/mocha/example/UserService.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.example; 2 | 3 | public interface UserService { 4 | 5 | void saveUser(String userId, User user); 6 | 7 | User getUser(String userId); 8 | } 9 | -------------------------------------------------------------------------------- /example/src/main/java/works/cirno/mocha/example/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.example; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | public class UserServiceImpl implements UserService { 6 | 7 | private final ConcurrentHashMap userStorage = new ConcurrentHashMap<>(); 8 | 9 | 10 | @Override 11 | public void saveUser(String userId, User user) { 12 | userStorage.put(userId, user); 13 | } 14 | 15 | @Override 16 | public User getUser(String userId) { 17 | return userStorage.get(userId); 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /example/src/main/java/works/cirno/mocha/example/guice/ExampleModule.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.example.guice; 2 | 3 | import com.google.inject.AbstractModule; 4 | import com.google.inject.Singleton; 5 | import com.google.inject.name.Names; 6 | 7 | import works.cirno.mocha.example.UserService; 8 | import works.cirno.mocha.example.UserServiceImpl; 9 | 10 | public class ExampleModule extends AbstractModule { 11 | 12 | @Override 13 | protected void configure() { 14 | 15 | bind(UserService.class).annotatedWith(Names.named("userService")).to(UserServiceImpl.class).in(Singleton.class); 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /example/src/main/java/works/cirno/mocha/example/guice/GuicedListener.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.example.guice; 2 | 3 | import com.google.inject.Guice; 4 | import com.google.inject.Injector; 5 | import com.google.inject.servlet.GuiceServletContextListener; 6 | 7 | public class GuicedListener extends GuiceServletContextListener { 8 | 9 | @Override 10 | protected Injector getInjector() { 11 | return Guice.createInjector(new ExampleModule()); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /example/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Root logger option 2 | log4j.rootLogger=DEBUG, stdout 3 | 4 | # Direct log messages to 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{HH:mm:ss.SSS} %-4p %c - %m%n 9 | 10 | log4j.logger.org.springframework=INFO 11 | log4j.logger.works.cirno.mocha=INFO 12 | log4j.logger.perf=DEBUG 13 | log4j.logger.works.cirno.mocha.example=DEBUG 14 | -------------------------------------------------------------------------------- /example/src/main/resources/works/cirno/mocha/example/spring/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/src/main/webapp/WEB-INF/jsp/head.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 5 | -------------------------------------------------------------------------------- /example/src/main/webapp/WEB-INF/jsp/parameter-rest.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%@include file="head.jsp"%> 5 | forms 6 | 13 | 14 | 15 |
16 |
17 |
18 | Hello ${userId}!
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 | -------------------------------------------------------------------------------- /example/src/main/webapp/WEB-INF/jsp/parameter-show.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%@include file="head.jsp"%> 5 | forms 6 | 13 | 14 | 15 |

User1:

16 | 39 | 40 | -------------------------------------------------------------------------------- /example/src/main/webapp/WEB-INF/jsp/parameter.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%@include file="head.jsp"%> 5 | forms 6 | 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 | -------------------------------------------------------------------------------- /example/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | COOKIE 8 | 9 | 10 | works.cirno.mocha.StartupPerformanceListener 11 | 12 | 13 | 31 | 32 | 33 | 34 | 35 | works.cirno.mocha.example.guice.GuicedListener 36 | 37 | 38 | dispatcher 39 | works.cirno.mocha.GuicedDispatcherFilter 40 | 41 | configurator 42 | works.cirno.mocha.example.ExampleConfigurator 43 | 44 | 45 | 46 | 47 | 48 | 49 | dispatcher 50 | /* 51 | 52 | -------------------------------------------------------------------------------- /example/src/main/webapp/default.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0} 2 | 3 | body { 4 | padding: 8px 12px; 5 | } 6 | 7 | .form-group { 8 | margin: 8px 0; 9 | } 10 | 11 | label { 12 | display: block; 13 | font-weight: bold; 14 | } 15 | 16 | input { 17 | width: 100%; 18 | height: 2em; 19 | line-height: 2em; 20 | border: solid 1px #999; 21 | border-radius: 3px; 22 | text-rendering: optimizeLegibility; 23 | } 24 | 25 | .btn { 26 | line-height: 2em; 27 | height: 2em; 28 | padding: 0 2em; 29 | display: block; 30 | border-radius: 3px; 31 | border: solid 1px transparent; 32 | } 33 | 34 | .btn.btn-primary{ 35 | color: white; 36 | background-color: dodgerblue; 37 | } -------------------------------------------------------------------------------- /mvc-core/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /mvc-core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | works.cirno.mocha 6 | mvc 7 | 0.1-SNAPSHOT 8 | 9 | mvc-core 10 | Mocha MVC Core 11 | 12 | 13 | 14 | javax.servlet 15 | servlet-api 16 | 2.5 17 | provided 18 | 19 | 20 | 21 | org.slf4j 22 | slf4j-api 23 | 1.7.12 24 | 25 | 26 | 27 | org.ow2.asm 28 | asm-tree 29 | 4.2 30 | 31 | 32 | 33 | javax.inject 34 | javax.inject 35 | 1 36 | 37 | 38 | 39 | commons-fileupload 40 | commons-fileupload 41 | 1.3.1 42 | 43 | 44 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/BasicMVCFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.util.concurrent.ConcurrentHashMap; 27 | 28 | /** 29 | * BasicObjectFactory will treat all beans as singleton, 30 | */ 31 | public class BasicMVCFactory implements ObjectFactory { 32 | 33 | private final ConcurrentHashMap, Object> instances = new ConcurrentHashMap<>(); 34 | 35 | @Override 36 | public T getInstance(TypeOrInstance param) { 37 | switch (param.getInjectBy()) { 38 | case TYPE: 39 | return getInstance(param.getType()); 40 | case INSTANCE: 41 | return param.getInstance(); 42 | default: 43 | throw new UnsupportedOperationException("Can't inject by " + param.getInjectBy()); 44 | } 45 | 46 | } 47 | 48 | private T getInstance(Class clazz) { 49 | @SuppressWarnings("unchecked") 50 | T result = (T) instances.get(clazz); 51 | if (result == null) { 52 | try { 53 | result = clazz.newInstance(); 54 | } catch (InstantiationException | IllegalAccessException e) { 55 | throw new RuntimeException(e); 56 | } 57 | instances.put(clazz, result); 58 | } 59 | return result; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/ClassComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.util.Comparator; 27 | 28 | /** 29 | *

Compares class by hierarchy,

30 | * 31 | *

Ensures following rules:
32 | * Given A and B are classes
33 | *

    34 | *
  1. compare(A, B) = 0 when A is same as B
  2. 35 | *
  3. compare(A, B) < 0 when A is subclass of B
  4. 36 | *
  5. If compare(A, B) <= 0 and compare(B, C) <= 0, then compare(A, C) <= 0
  6. 37 | *
38 | */ 39 | public class ClassComparator implements Comparator> { 40 | 41 | @Override 42 | public int compare(Class o1, Class o2) { 43 | if (o2.equals(o1)) { 44 | return 0; 45 | } else if (o2.isAssignableFrom(o1)) { 46 | return -1; 47 | } else if (o1.isAssignableFrom(o2)) { 48 | return 1; 49 | } else { 50 | Class commonParent = null; 51 | Class lastEx = null; 52 | Class lastOther = null; 53 | for (Class clz = o1; clz != null; clz = clz.getSuperclass()) { 54 | if (clz.isAssignableFrom(o2)) { 55 | commonParent = clz; 56 | break; 57 | } 58 | lastEx = clz; 59 | } 60 | if (commonParent == null || lastEx == null) { 61 | throw new IllegalStateException( 62 | "Can't find common parent for class " + o1.getName() + " and " + o2.getName()); 63 | } 64 | for (Class clz = o2; clz != null; clz = clz.getSuperclass()) { 65 | if (commonParent.equals(clz)) { 66 | break; 67 | } 68 | lastOther = clz; 69 | } 70 | if (lastOther == null) { 71 | throw new IllegalStateException( 72 | "Can't find common parent for class " + o1.getName() + " and " + o2.getName()); 73 | } 74 | return lastEx.getName().compareTo(lastOther.getName()); 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/CloseableResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.io.Closeable; 27 | import java.io.IOException; 28 | 29 | final class CloseableResource implements Closeable { 30 | 31 | private final T content; 32 | private final String name; 33 | 34 | public CloseableResource(T content, String name) { 35 | super(); 36 | this.content = content; 37 | this.name = name; 38 | } 39 | 40 | public T getContent() { 41 | return content; 42 | } 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | @Override 49 | public void close() throws IOException { 50 | content.close(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/ConfigBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.io.File; 27 | 28 | import works.cirno.mocha.result.Renderer; 29 | 30 | /** 31 | * 32 | */ 33 | public interface ConfigBuilder { 34 | /** 35 | * Handle request with specified controller and method 36 | */ 37 | ConfigBuilder with(String controllerName, String methodName); 38 | 39 | /** 40 | * Handle request with specified controller and method 41 | */ 42 | ConfigBuilder with(Class controller, String methodName); 43 | 44 | /** 45 | * Handle request with specified controller and method 46 | */ 47 | ConfigBuilder with(String controllerName); 48 | 49 | /** 50 | * Handle request with specified controller and method 51 | */ 52 | ConfigBuilder with(Class controller); 53 | 54 | /** 55 | * Handle request with specified controller and method 56 | */ 57 | ConfigBuilder withMethod(String methodName); 58 | 59 | /** 60 | * Handle 61 | * 62 | * @param exception 63 | * @param result 64 | * @return 65 | */ 66 | ConfigBuilder exception(Class exception, Renderer result); 67 | 68 | ConfigBuilder exception(Class exception, Class result); 69 | 70 | ConfigBuilder exception(Class exception, String resultName); 71 | 72 | /** 73 | * Forward a view result to a specific path (likely forward to JSP)
74 | * Following by a to(path) method, you will specify path to forward to there 75 | * 76 | * @param resultName 77 | * "name" in a View object 78 | * @return 79 | */ 80 | ServletResultRendererConfig forward(String resultName); 81 | 82 | /** 83 | * Redirect a view result to a specific path (forward to JSP)
84 | * Following by a to(path) method, you will specify path to redirect to 85 | * there 86 | * 87 | * @param resultName 88 | * "name" in a View object 89 | * @return 90 | */ 91 | ServletResultRendererConfig redirect(String resultName); 92 | 93 | /** 94 | * Add a custom works.cirno.mocha.result.ResultRenderer to handle result 95 | * 96 | * @param renderer 97 | * @return 98 | */ 99 | ConfigBuilder prependResultRenderer(Renderer renderer); 100 | 101 | ConfigBuilder prependResultRenderer(Class renderer); 102 | 103 | ConfigBuilder prependResultRenderer(String rendererName); 104 | 105 | /** 106 | * Add a custom works.cirno.mocha.result.ResultRenderer to handle result 107 | * 108 | * @param renderer 109 | * @return 110 | */ 111 | ConfigBuilder appendResultRenderer(Renderer renderer); 112 | 113 | ConfigBuilder appendResultRenderer(Class renderer); 114 | 115 | ConfigBuilder appendResultRenderer(String rendererName); 116 | 117 | /** 118 | * Don't parse http body posted, you can fetch the body from a InputStream 119 | * parameter in controller method 120 | * 121 | * @return 122 | */ 123 | ConfigBuilder raw(); 124 | 125 | /** 126 | * Set directory which will store temporary uploaded data 127 | * 128 | * @param tempDirectory 129 | * @return 130 | */ 131 | ConfigBuilder uploadTemp(File tempDirectory); 132 | 133 | } 134 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/ConfigBuilderImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.io.File; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | import works.cirno.mocha.result.Renderer; 32 | 33 | /** 34 | * 35 | */ 36 | class ConfigBuilderImpl implements ConfigBuilder { 37 | 38 | private String path; 39 | private String method; 40 | private boolean pathRegex; 41 | 42 | private MVCConfig config; 43 | 44 | ConfigBuilderImpl(String path, boolean pathRegex, MVCConfig parent) { 45 | this(path, pathRegex, null, parent); 46 | } 47 | 48 | ConfigBuilderImpl(String path, boolean pathRegex, String method, MVCConfig parent) { 49 | this.path = path; 50 | this.method = method; 51 | this.config = new MVCConfig(parent); 52 | } 53 | 54 | String getPath() { 55 | return path; 56 | } 57 | 58 | boolean isPathRegex() { 59 | return pathRegex; 60 | } 61 | 62 | String getMethod() { 63 | return method; 64 | } 65 | 66 | TypeOrInstance getController() { 67 | return config.getController(); 68 | } 69 | 70 | String getMethodName() { 71 | return config.getMethodName(); 72 | } 73 | 74 | Map, TypeOrInstance> getExceptionHandlers() { 75 | return config.getHandlers(); 76 | } 77 | 78 | List> getResultRenderers() { 79 | return config.getResultRenderers(); 80 | } 81 | 82 | HashMap getPendingServletResultRendererConfig() { 83 | return config.getPendingServletResultRendererConfig(); 84 | } 85 | 86 | boolean isRaw() { 87 | return config.isRaw(); 88 | } 89 | 90 | File getUploadTemp() { 91 | return config.getUploadTemp(); 92 | } 93 | 94 | public ConfigBuilder with(Class controller, String methodName) { 95 | return config.with(controller, methodName); 96 | } 97 | 98 | public ConfigBuilder with(String controllerName, String methodName) { 99 | return config.with(controllerName, methodName); 100 | } 101 | 102 | public ConfigBuilder with(String controllerName) { 103 | return config.with(controllerName); 104 | } 105 | 106 | public ConfigBuilder with(Class controller) { 107 | return config.with(controller); 108 | } 109 | 110 | public ConfigBuilder withMethod(String methodName) { 111 | return config.withMethod(methodName); 112 | } 113 | 114 | public ConfigBuilder exception(Class exception, Renderer result) { 115 | return config.exception(exception, result); 116 | } 117 | 118 | public ConfigBuilder exception(Class exception, 119 | Class resultType) { 120 | return config.exception(exception, resultType); 121 | } 122 | 123 | public ConfigBuilder exception(Class exception, String resultName) { 124 | return config.exception(exception, resultName); 125 | } 126 | 127 | public ServletResultRendererConfig forward(String resultName) { 128 | return config.forward(resultName); 129 | } 130 | 131 | public ServletResultRendererConfig redirect(String resultName) { 132 | return config.redirect(resultName); 133 | } 134 | 135 | public ConfigBuilder prependResultRenderer(Renderer renderer) { 136 | return config.prependResultRenderer(renderer); 137 | } 138 | 139 | public ConfigBuilder prependResultRenderer(Class renderer) { 140 | return config.prependResultRenderer(renderer); 141 | } 142 | 143 | public ConfigBuilder prependResultRenderer(String rendererName) { 144 | return config.prependResultRenderer(rendererName); 145 | } 146 | 147 | public ConfigBuilder appendResultRenderer(Renderer renderer) { 148 | return config.appendResultRenderer(renderer); 149 | } 150 | 151 | public ConfigBuilder appendResultRenderer(Class renderer) { 152 | return config.appendResultRenderer(renderer); 153 | } 154 | 155 | public ConfigBuilder appendResultRenderer(String rendererName) { 156 | return config.appendResultRenderer(rendererName); 157 | } 158 | 159 | public ConfigBuilder raw() { 160 | return config.raw(); 161 | } 162 | 163 | public ConfigBuilder uploadTemp(File tempDirectory) { 164 | return config.uploadTemp(tempDirectory); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/DispatcherFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.io.IOException; 27 | import java.util.Enumeration; 28 | import java.util.HashMap; 29 | 30 | import javax.servlet.Filter; 31 | import javax.servlet.FilterChain; 32 | import javax.servlet.FilterConfig; 33 | import javax.servlet.ServletException; 34 | import javax.servlet.ServletRequest; 35 | import javax.servlet.ServletResponse; 36 | import javax.servlet.http.HttpServletRequest; 37 | import javax.servlet.http.HttpServletResponse; 38 | 39 | import org.slf4j.Logger; 40 | import org.slf4j.LoggerFactory; 41 | 42 | /** 43 | * 44 | */ 45 | public class DispatcherFilter extends Dispatcher implements Filter { 46 | 47 | private static final Logger log = LoggerFactory.getLogger(DispatcherFilter.class); 48 | 49 | @Override 50 | public void init(FilterConfig config) throws ServletException { 51 | long begin = System.currentTimeMillis(); 52 | log.info("Initializing dispatcher servlet {}", config.getFilterName()); 53 | try { 54 | HashMap initParameters = new HashMap<>(); 55 | @SuppressWarnings("unchecked") 56 | Enumeration keys = config.getInitParameterNames(); 57 | while (keys.hasMoreElements()) { 58 | String key = keys.nextElement(); 59 | String value = config.getInitParameter(key); 60 | initParameters.put(key, value); 61 | } 62 | 63 | init(config.getFilterName(), config.getServletContext(), initParameters); 64 | log.info("Dispatcher filter {} initialized in {}ms", config.getFilterName(), 65 | System.currentTimeMillis() - begin); 66 | } catch (ServletException e) { 67 | log.error("Initialization failed", e); 68 | throw e; 69 | } 70 | } 71 | 72 | @Override 73 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 74 | throws IOException, ServletException { 75 | HttpServletRequest req = (HttpServletRequest) request; 76 | HttpServletResponse resp = (HttpServletResponse) response; 77 | if (!invoke(req, resp)) { 78 | chain.doFilter(request, response); 79 | } 80 | } 81 | 82 | @Override 83 | public void destroy() { 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/DispatcherServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.io.IOException; 27 | import java.util.Enumeration; 28 | import java.util.HashMap; 29 | 30 | import javax.servlet.Servlet; 31 | import javax.servlet.ServletConfig; 32 | import javax.servlet.ServletException; 33 | import javax.servlet.ServletRequest; 34 | import javax.servlet.ServletResponse; 35 | import javax.servlet.http.HttpServletRequest; 36 | import javax.servlet.http.HttpServletResponse; 37 | 38 | import org.slf4j.Logger; 39 | import org.slf4j.LoggerFactory; 40 | 41 | /** 42 | * 43 | */ 44 | public class DispatcherServlet extends Dispatcher implements Servlet { 45 | 46 | private static final Logger log = LoggerFactory.getLogger(DispatcherFilter.class); 47 | private ServletConfig config; 48 | 49 | @Override 50 | public void init(ServletConfig config) throws ServletException { 51 | long begin = System.currentTimeMillis(); 52 | log.info("Initializing dispatcher servlet {}", config.getServletName()); 53 | this.config = config; 54 | try { 55 | HashMap initParameters = new HashMap<>(); 56 | Enumeration keys = config.getInitParameterNames(); 57 | while (keys.hasMoreElements()) { 58 | String key = keys.nextElement(); 59 | String value = config.getInitParameter(key); 60 | initParameters.put(key, value); 61 | } 62 | 63 | init(config.getServletName(), config.getServletContext(), initParameters); 64 | log.info("Dispatcher servlet {} initialized in {}ms", config.getServletName(), 65 | System.currentTimeMillis() - begin); 66 | } catch (ServletException e) { 67 | log.error("Initialization failed", e); 68 | throw e; 69 | } 70 | } 71 | 72 | @Override 73 | public ServletConfig getServletConfig() { 74 | return this.config; 75 | } 76 | 77 | @Override 78 | public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { 79 | HttpServletRequest req = (HttpServletRequest) request; 80 | HttpServletResponse resp = (HttpServletResponse) response; 81 | if (!this.invoke(req, resp)) { 82 | resp.sendError(404, "Request path not found"); 83 | } 84 | } 85 | 86 | @Override 87 | public String getServletInfo() { 88 | return "Dispatcher servlet"; 89 | } 90 | 91 | @Override 92 | public void destroy() { 93 | 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/ExceptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import javax.servlet.http.HttpServletRequest; 27 | import javax.servlet.http.HttpServletResponse; 28 | 29 | /** 30 | * 31 | */ 32 | public interface ExceptionHandler { 33 | void handle(InvokeContext ctx, HttpServletRequest req, HttpServletResponse resp, T exception); 34 | } 35 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/InvokeContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.io.Closeable; 27 | import java.io.IOException; 28 | import java.util.ArrayList; 29 | import java.util.HashMap; 30 | import java.util.Set; 31 | import java.util.regex.Matcher; 32 | 33 | import javax.servlet.http.HttpServletRequest; 34 | import javax.servlet.http.HttpServletResponse; 35 | 36 | import org.slf4j.Logger; 37 | import org.slf4j.LoggerFactory; 38 | 39 | /** 40 | * 41 | */ 42 | public class InvokeContext implements Closeable { 43 | private static final Logger log = LoggerFactory.getLogger(InvokeContext.class); 44 | private InvokeTarget target; 45 | private Matcher uriMatcher; 46 | private Set groupNames; 47 | private HashMap attributes; 48 | private HttpServletRequest req; 49 | private HttpServletResponse resp; 50 | private boolean multipart; 51 | private HashMap> parts; 52 | private String characterEncoding = "UTF-8"; // TODO make it configurable 53 | private ArrayList> closeables; 54 | 55 | public InvokeContext(InvokeTarget target, Matcher uriMatcher, Set groupNames) { 56 | this.target = target; 57 | this.uriMatcher = uriMatcher; 58 | this.groupNames = groupNames; 59 | } 60 | 61 | public InvokeTarget getTarget() { 62 | return target; 63 | } 64 | 65 | public Matcher getUriMatcher() { 66 | return uriMatcher; 67 | } 68 | 69 | public boolean isGroupName(String str) { 70 | return groupNames.contains(str); 71 | } 72 | 73 | public Object getAttribute(String key) { 74 | return attributes == null ? null : attributes.get(key); 75 | } 76 | 77 | public Object setAttribute(String key, Object value) { 78 | if (attributes == null) { 79 | attributes = new HashMap<>(); 80 | } 81 | return attributes.put(key, value); 82 | } 83 | 84 | public void addPart(MultiPartItem part) { 85 | if (parts == null) { 86 | parts = new HashMap<>(); 87 | } 88 | String name = part.getFieldName(); 89 | ArrayList list = parts.get(name); 90 | if (list == null) { 91 | list = new ArrayList<>(1); 92 | parts.put(name, list); 93 | } 94 | list.add(part); 95 | } 96 | 97 | public MultiPartItem getPart(String name) { 98 | if (parts == null) { 99 | return null; 100 | } 101 | ArrayList list = parts.get(name); 102 | return (list == null || list.size() == 0) ? null : list.get(0); 103 | } 104 | 105 | public MultiPartItem[] getParts(String name) { 106 | if (parts == null) { 107 | return null; 108 | } 109 | ArrayList list = parts.get(name); 110 | return list == null ? null : list.toArray(new MultiPartItem[list.size()]); 111 | } 112 | 113 | public HttpServletRequest getRequest() { 114 | return req; 115 | } 116 | 117 | void setRequest(HttpServletRequest req) { 118 | this.req = req; 119 | } 120 | 121 | public HttpServletResponse getResponse() { 122 | return resp; 123 | } 124 | 125 | void setResponse(HttpServletResponse resp) { 126 | this.resp = resp; 127 | } 128 | 129 | public String getCharacterEncoding() { 130 | return characterEncoding; 131 | } 132 | 133 | void setCharacterEncoding(String characterEncoding) { 134 | this.characterEncoding = characterEncoding; 135 | } 136 | 137 | public void registerCloseable(Closeable closeable, String name) { 138 | if (closeables == null) { 139 | closeables = new ArrayList<>(); 140 | } 141 | closeables.add(new CloseableResource(closeable, name)); 142 | } 143 | 144 | public boolean isMultipart() { 145 | return multipart; 146 | } 147 | 148 | void setMultipart(boolean multipart) { 149 | this.multipart = multipart; 150 | } 151 | 152 | @Override 153 | public void close() throws IOException { 154 | if (closeables != null) { 155 | for (int i = closeables.size() - 1; i >= 0; i--) { 156 | CloseableResource closeable = closeables.get(i); 157 | log.debug("Closing " + closeable.getName()); 158 | try { 159 | closeable.close(); 160 | } catch (Exception e) { 161 | log.warn("Can't close resource: " + closeable.getName() + " (" 162 | + closeable.getContent().getClass().getName() + ")", e); 163 | } 164 | } 165 | } 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/MVCInternalException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | public class MVCInternalException extends RuntimeException { 27 | 28 | /** 29 | * 30 | */ 31 | private static final long serialVersionUID = -4736592789363537011L; 32 | 33 | public MVCInternalException() { 34 | super(); 35 | } 36 | 37 | public MVCInternalException(String message, Throwable cause, boolean enableSuppression, 38 | boolean writableStackTrace) { 39 | super(message, cause, enableSuppression, writableStackTrace); 40 | } 41 | 42 | public MVCInternalException(String message, Throwable cause) { 43 | super(message, cause); 44 | } 45 | 46 | public MVCInternalException(String message) { 47 | super(message); 48 | } 49 | 50 | public MVCInternalException(Throwable cause) { 51 | super(cause); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/MultiPartItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.io.Closeable; 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.io.UnsupportedEncodingException; 31 | import java.nio.charset.Charset; 32 | import java.util.Iterator; 33 | 34 | public interface MultiPartItem extends Closeable { 35 | String getHeader(String name); 36 | 37 | Iterator getHeaders(String name); 38 | 39 | Iterator getHeaderNames(); 40 | 41 | InputStream getInputStream() throws IOException; 42 | 43 | String getContentType(); 44 | 45 | String getName(); 46 | 47 | String getString(Charset charset); 48 | 49 | String getString(String charset) throws UnsupportedEncodingException; 50 | 51 | String getString(); 52 | 53 | long getSize(); 54 | 55 | void write(File file) throws IOException; 56 | 57 | String getFieldName(); 58 | 59 | boolean isFormField(); 60 | } 61 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/MultiPartItemCommon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.io.File; 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | import java.io.UnsupportedEncodingException; 30 | import java.nio.charset.Charset; 31 | import java.util.Iterator; 32 | 33 | import org.apache.commons.fileupload.FileItem; 34 | 35 | class MultiPartItemCommon implements MultiPartItem { 36 | 37 | private FileItem item; 38 | 39 | public MultiPartItemCommon(FileItem item) { 40 | this.item = item; 41 | } 42 | 43 | public String getHeader(String name) { 44 | return item.getHeaders().getHeader(name); 45 | } 46 | 47 | public Iterator getHeaders(String name) { 48 | return item.getHeaders().getHeaders(name); 49 | } 50 | 51 | public Iterator getHeaderNames() { 52 | return item.getHeaders().getHeaderNames(); 53 | } 54 | 55 | public InputStream getInputStream() throws IOException { 56 | return item.getInputStream(); 57 | } 58 | 59 | public String getContentType() { 60 | return item.getContentType(); 61 | } 62 | 63 | public String getName() { 64 | return item.getName(); 65 | } 66 | 67 | public long getSize() { 68 | return item.getSize(); 69 | } 70 | 71 | public void write(File file) throws IOException { 72 | try { 73 | item.write(file); 74 | } catch (IOException | Error e) { 75 | throw e; 76 | } catch (Exception e) { 77 | throw new IOException("Can't write part to file " + file, e); 78 | } 79 | } 80 | 81 | public String getFieldName() { 82 | return item.getFieldName(); 83 | } 84 | 85 | public boolean isFormField() { 86 | return item.isFormField(); 87 | } 88 | 89 | public String getString(Charset charset) { 90 | try { 91 | return item.getString(charset.name()); 92 | } catch (UnsupportedEncodingException e) { 93 | throw new RuntimeException(e); 94 | } 95 | } 96 | 97 | public String getString(String charset) throws UnsupportedEncodingException { 98 | return item.getString(charset); 99 | } 100 | 101 | public String getString() { 102 | return item.getString(); 103 | } 104 | 105 | @Override 106 | public void close() throws IOException { 107 | item.delete(); 108 | } 109 | 110 | @Override 111 | public String toString() { 112 | return "MultiPartItem(CommonUpload): " + item; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/ObjectFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | /** 27 | * 28 | */ 29 | public interface ObjectFactory { 30 | T getInstance(TypeOrInstance param); 31 | } 32 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/ServletResultRendererConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | public interface ServletResultRendererConfig { 27 | /** 28 | * Forward or redirect to following path 29 | * @param path The path to forward or redirect to 30 | * @return 31 | */ 32 | ConfigBuilder to(String path); 33 | } 34 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/ServletResultRendererConfigImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import works.cirno.mocha.result.ResultType; 27 | 28 | public class ServletResultRendererConfigImpl implements ServletResultRendererConfig { 29 | 30 | private ConfigBuilder configBuilder; 31 | private ResultType resultType; 32 | private String path; 33 | 34 | public ServletResultRendererConfigImpl(ConfigBuilder configBuilder, ResultType resultType) { 35 | super(); 36 | this.configBuilder = configBuilder; 37 | this.resultType = resultType; 38 | } 39 | 40 | @Override 41 | public ConfigBuilder to(String path) { 42 | this.path = path; 43 | return configBuilder; 44 | } 45 | 46 | public ResultType getResultType() { 47 | return resultType; 48 | } 49 | 50 | public String getPath() { 51 | return path; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/StartupPerformanceListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import javax.servlet.ServletContext; 27 | import javax.servlet.ServletContextEvent; 28 | import javax.servlet.ServletContextListener; 29 | 30 | import org.slf4j.Logger; 31 | import org.slf4j.LoggerFactory; 32 | 33 | public class StartupPerformanceListener implements ServletContextListener { 34 | 35 | private static final Logger log = LoggerFactory.getLogger(StartupPerformanceListener.class); 36 | 37 | public final static String KEY_PERF_START = "PERF.START.TS"; 38 | 39 | @Override 40 | public void contextInitialized(ServletContextEvent sce) { 41 | log.info("Put startup timestamp to servlet context: {}", KEY_PERF_START); 42 | ServletContext sc = sce.getServletContext(); 43 | sc.setAttribute(KEY_PERF_START, System.currentTimeMillis()); 44 | } 45 | 46 | @Override 47 | public void contextDestroyed(ServletContextEvent sce) { 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/TypeOrInstance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | public class TypeOrInstance { 27 | 28 | public static enum InjectBy { 29 | NAME_TYPE, TYPE, INSTANCE 30 | } 31 | 32 | private InjectBy injectBy; 33 | private Class type; 34 | private T instance; 35 | private String name; 36 | 37 | public TypeOrInstance(String name, Class type) { 38 | this.injectBy = InjectBy.NAME_TYPE; 39 | this.name = name; 40 | this.type = type; 41 | } 42 | 43 | public TypeOrInstance(T instance) { 44 | this.injectBy = InjectBy.INSTANCE; 45 | this.instance = instance; 46 | } 47 | 48 | public TypeOrInstance(Class type) { 49 | this.injectBy = InjectBy.TYPE; 50 | this.type = type; 51 | } 52 | 53 | public InjectBy getInjectBy() { 54 | return injectBy; 55 | } 56 | 57 | public Class getType() { 58 | return type; 59 | } 60 | 61 | public T getInstance() { 62 | return instance; 63 | } 64 | 65 | public String getName() { 66 | return name; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/name/AnnotationParameterAnalyzer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.name; 25 | 26 | import java.lang.annotation.Annotation; 27 | import java.lang.reflect.Method; 28 | 29 | import works.cirno.mocha.InvokeTarget; 30 | 31 | /** 32 | * 33 | */ 34 | public class AnnotationParameterAnalyzer implements ParameterAnalyzer { 35 | 36 | @Override 37 | public Parameter[] getParameters(InvokeTarget target) { 38 | return getParameters(target, null); 39 | } 40 | 41 | @Override 42 | public Parameter[] getParameters(InvokeTarget target, Parameter[] parameters) { 43 | Method method = target.getMethod(); 44 | 45 | Class[] parameterTypes = method.getParameterTypes(); 46 | Annotation[][] parameterAnnotations = method.getParameterAnnotations(); 47 | int length = parameterAnnotations.length; 48 | if (parameters == null) { 49 | parameters = new Parameter[length]; 50 | } else if (parameters.length != length) { 51 | throw new IllegalArgumentException("Input parameters' length is different than parameters of target"); 52 | } 53 | for (int i = 0; i < length; i++) { 54 | if (parameters[i] == null || parameters[i].getName() == null) { 55 | Class type = parameterTypes[i]; 56 | for (Annotation annotation : parameterAnnotations[i]) { 57 | if (annotation instanceof NamedParam) { 58 | NamedParam np = ((NamedParam) annotation); 59 | String name = np.value(); 60 | parameters[i] = new Parameter(name, type); 61 | break; 62 | } 63 | } 64 | if (parameters[i] == null) { 65 | parameters[i] = new Parameter(null, type); 66 | } 67 | } 68 | } 69 | return parameters; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/name/NamedParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.name; 25 | 26 | import java.lang.annotation.ElementType; 27 | import java.lang.annotation.Retention; 28 | import java.lang.annotation.RetentionPolicy; 29 | import java.lang.annotation.Target; 30 | 31 | /** 32 | * 33 | */ 34 | @Target(ElementType.PARAMETER) 35 | @Retention(RetentionPolicy.RUNTIME) 36 | public @interface NamedParam { 37 | 38 | public String value(); 39 | } 40 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/name/Parameter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.name; 25 | 26 | import java.util.Arrays; 27 | import java.util.Collection; 28 | 29 | import works.cirno.mocha.parameter.value.DefaultParameterSource; 30 | import works.cirno.mocha.parameter.value.ParameterSource; 31 | 32 | public class Parameter { 33 | 34 | private Collection DEFAULT_PARAMETER_SOURCES = Arrays 35 | . asList(DefaultParameterSource.INSTANCE); 36 | 37 | private final String name; 38 | private final Class type; 39 | 40 | private Collection parameterSources = DEFAULT_PARAMETER_SOURCES; 41 | 42 | public Parameter(String name, Class type) { 43 | this.name = name; 44 | this.type = type; 45 | } 46 | 47 | public String getName() { 48 | return name; 49 | } 50 | 51 | public Class getType() { 52 | return type; 53 | } 54 | 55 | public Collection getParameterSources() { 56 | return parameterSources; 57 | } 58 | 59 | public void setParameterSources(Collection parameterSources) { 60 | this.parameterSources = parameterSources; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return "Parameter[" + name + "](" + type.getName() + ")"; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/name/ParameterAnalyzer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.name; 25 | 26 | import works.cirno.mocha.InvokeTarget; 27 | 28 | /** 29 | * 30 | */ 31 | public interface ParameterAnalyzer { 32 | Parameter[] getParameters(InvokeTarget target); 33 | 34 | Parameter[] getParameters(InvokeTarget target, Parameter[] parameters); 35 | } 36 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/AbstractStringArrayConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.lang.reflect.Array; 27 | 28 | import works.cirno.mocha.InvokeContext; 29 | 30 | public abstract class AbstractStringArrayConverter implements ValueConverter { 31 | 32 | public static Class getArrayType(Class componentType) throws ClassNotFoundException { 33 | String name; 34 | if (componentType.isArray()) { 35 | // just add a leading "[" 36 | name = "[" + componentType.getName(); 37 | } else if (componentType.isPrimitive()) { 38 | if (componentType == boolean.class) { 39 | name = "[Z"; 40 | } else if (componentType == byte.class) { 41 | name = "[B"; 42 | } else if (componentType == char.class) { 43 | name = "[C"; 44 | } else if (componentType == double.class) { 45 | name = "[D"; 46 | } else if (componentType == float.class) { 47 | name = "[F"; 48 | } else if (componentType == int.class) { 49 | name = "[I"; 50 | } else if (componentType == long.class) { 51 | name = "[J"; 52 | } else if (componentType == short.class) { 53 | name = "[S"; 54 | } else { 55 | throw new UnsupportedOperationException("Unsupported component type: " + componentType.getName()); 56 | } 57 | } else { 58 | name = "[L" + componentType.getName() + ";"; 59 | } 60 | return Class.forName(name); 61 | } 62 | 63 | @Override 64 | public Object convert(Class type, InvokeContext ctx, Object from) { 65 | if (type.isArray()) { 66 | if (from == null || Array.getLength(from) == 0) { 67 | Object one = convertOne(type.getComponentType(), ctx, null); 68 | if (one == NOT_CONVERTABLE) { 69 | return NOT_CONVERTABLE; 70 | } else if (one == null) { 71 | return Array.newInstance(type.getComponentType(), 0); 72 | } else { 73 | Object ret = Array.newInstance(type.getComponentType(), 1); 74 | Array.set(ret, 0, one); 75 | return ret; 76 | } 77 | } else { 78 | Class componentType = type.getComponentType(); 79 | Object one = convertOne(componentType, ctx, Array.get(from, 0)); 80 | if (one == NOT_CONVERTABLE) { 81 | return NOT_CONVERTABLE; 82 | } else { 83 | int len = Array.getLength(from); 84 | Object ret = Array.newInstance(componentType, len); 85 | Array.set(ret, 0, one); 86 | for (int i = 1; i < len; i++) { 87 | one = convertOne(componentType, ctx, Array.get(from, i)); 88 | if (one == NOT_CONVERTABLE) { 89 | return NOT_CONVERTABLE; 90 | } 91 | Array.set(ret, 0, one); 92 | } 93 | return ret; 94 | } 95 | } 96 | } else { 97 | return convertOne(type, ctx, from); 98 | } 99 | } 100 | 101 | protected abstract Object convertOne(Class type, InvokeContext ctx, Object from); 102 | } 103 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/AbstractValueSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | public abstract class AbstractValueSource implements ValueSource { 27 | 28 | private ConvertStrategy strategy = ConvertStrategy.NULL_WHEN_UNCONVERTABLE; 29 | 30 | ValueSource withConvertStrategy(ConvertStrategy strategy) { 31 | this.strategy = strategy; 32 | return this; 33 | } 34 | 35 | @Override 36 | public ConvertStrategy getConvertStrategy() { 37 | return strategy; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/BeanParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.beans.BeanInfo; 27 | import java.beans.IntrospectionException; 28 | import java.beans.Introspector; 29 | import java.beans.PropertyDescriptor; 30 | import java.lang.reflect.Constructor; 31 | import java.lang.reflect.InvocationTargetException; 32 | import java.lang.reflect.Method; 33 | import java.lang.reflect.Modifier; 34 | import java.util.concurrent.ConcurrentHashMap; 35 | 36 | import works.cirno.mocha.InvokeContext; 37 | import works.cirno.mocha.parameter.name.Parameter; 38 | 39 | public class BeanParameterSource implements ParameterSource { 40 | 41 | private ConcurrentHashMap, Boolean> notBean = new ConcurrentHashMap, Boolean>(); 42 | 43 | private ParameterSource propertySource; 44 | 45 | ParameterSource getPropertySource() { 46 | return propertySource; 47 | } 48 | 49 | void setPropertySource(ParameterSource propertySource) { 50 | this.propertySource = propertySource; 51 | } 52 | 53 | @Override 54 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 55 | Class type = parameter.getType(); 56 | String paramName = parameter.getName(); 57 | if (notBean.contains(type)) { 58 | return NOT_HERE; 59 | } else { 60 | try { 61 | BeanInfo info; 62 | Constructor constructor; 63 | try { 64 | if ((type.getModifiers() & (Modifier.ABSTRACT)) != 0) { 65 | notBean.put(type, true); 66 | return NOT_HERE; 67 | } 68 | info = Introspector.getBeanInfo(type); 69 | constructor = type.getConstructor(); 70 | if ((constructor.getModifiers() & (Modifier.PUBLIC)) == 0) { 71 | notBean.put(type, true); 72 | return NOT_HERE; 73 | } 74 | } catch (NoSuchMethodException | IntrospectionException e) { 75 | notBean.put(type, true); 76 | return NOT_HERE; 77 | } 78 | Object result = constructor.newInstance(); 79 | PropertyDescriptor[] propertyDescriptors = info 80 | .getPropertyDescriptors(); 81 | StringBuilder nameBuilder = new StringBuilder(64); 82 | boolean propertyGot = false; 83 | 84 | for (PropertyDescriptor pd : propertyDescriptors) { 85 | Class propertyType = pd.getPropertyType(); 86 | Method writeMethod = pd.getWriteMethod(); 87 | if (propertyType != null && writeMethod != null) { 88 | String propertyName = pd.getName(); 89 | nameBuilder.setLength(0); 90 | nameBuilder.append(paramName).append('.') 91 | .append(propertyName); 92 | 93 | Parameter propertyParameter = new Parameter(nameBuilder.toString(), propertyType); 94 | Object value = propertySource.getParameterValue(ctx, propertyParameter); 95 | if (value != NOT_HERE) { 96 | propertyGot = true; 97 | if (writeMethod != null) { 98 | try{ 99 | writeMethod.invoke(result, value); 100 | }catch(IllegalArgumentException e){ 101 | throw new IllegalArgumentException( 102 | "Expected type: " + writeMethod.getParameterTypes()[0].getName() 103 | + " actual type: " + value.getClass().getName(), 104 | e); 105 | } 106 | } 107 | } 108 | } 109 | } 110 | return propertyGot ? result : NOT_HERE; 111 | } catch (InstantiationException | IllegalAccessException | IllegalArgumentException 112 | | InvocationTargetException ex) { 113 | throw new RuntimeException("Can't setup bean parameter " + paramName + "(" + type + ")", ex); 114 | } 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/CombianParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.util.Collection; 27 | 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | import works.cirno.mocha.InvokeContext; 32 | import works.cirno.mocha.parameter.name.Parameter; 33 | 34 | public class CombianParameterSource implements ParameterSource { 35 | 36 | private static final Logger log = LoggerFactory.getLogger(CombianParameterSource.class); 37 | private static final Logger perfLog = LoggerFactory.getLogger("perf." + CombianParameterSource.class.getName()); 38 | 39 | private Collection sources; 40 | 41 | public CombianParameterSource() { 42 | 43 | } 44 | 45 | public CombianParameterSource(Collection sources) { 46 | this.sources = sources; 47 | } 48 | 49 | public Collection getSources() { 50 | return sources; 51 | } 52 | 53 | public void setSources(Collection sources) { 54 | this.sources = sources; 55 | } 56 | 57 | @Override 58 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 59 | long paramBeginTime = 0; 60 | for (ParameterSource source : sources) { 61 | if (perfLog.isDebugEnabled()) { 62 | paramBeginTime = System.nanoTime(); 63 | } 64 | Object value = source.getParameterValue(ctx, parameter); 65 | if (perfLog.isDebugEnabled()) { 66 | perfLog.debug("Resolve parameter[{}] by {} in {}ms", parameter.getType().getName(), 67 | source.getClass().getName(), (System.nanoTime() - paramBeginTime) / 1000000f); 68 | } 69 | log.debug("Getting parameter {}, result {}", parameter, value); 70 | if (value != NOT_HERE) { 71 | return value; 72 | } 73 | } 74 | return NOT_HERE; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/ConvertStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | public enum ConvertStrategy { 27 | EXCEPTION_WHEN_UNCONVERTABLE, SKIP_WHEN_UNCONVERTABLE, NOT_FOUND_WHEN_UNCONVERTABLE, NULL_WHEN_UNCONVERTABLE 28 | } 29 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/DefaultParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.util.ArrayList; 27 | 28 | public class DefaultParameterSource extends CombianParameterSource { 29 | 30 | public static final DefaultParameterSource INSTANCE = new DefaultParameterSource(); 31 | 32 | public DefaultParameterSource() { 33 | 34 | ArrayList sources = new ArrayList<>(); 35 | 36 | sources.add(new TypedParameterSource()); 37 | sources.add(new RawParameterSource()); 38 | sources.add(new FilePartArrayParameterSource()); 39 | sources.add(new FilePartParameterSource()); 40 | 41 | MatrixParameterSource matrix = new MatrixParameterSource(); 42 | ArrayList vs = new ArrayList<>(); 43 | vs.add(new MatcherValueSource().withConvertStrategy(ConvertStrategy.NULL_WHEN_UNCONVERTABLE)); 44 | vs.add(new MultiPartStringArraySource().withConvertStrategy(ConvertStrategy.SKIP_WHEN_UNCONVERTABLE)); 45 | vs.add(new MultiPartStringSource().withConvertStrategy(ConvertStrategy.NULL_WHEN_UNCONVERTABLE)); 46 | vs.add(new RequestValueSource().withConvertStrategy(ConvertStrategy.SKIP_WHEN_UNCONVERTABLE)); 47 | vs.add(new RequestArrayValueSource().withConvertStrategy(ConvertStrategy.NULL_WHEN_UNCONVERTABLE)); 48 | matrix.setSources(vs); 49 | ArrayList vc = new ArrayList<>(); 50 | vc.add(new StringPEConverter()); 51 | vc.add(new StringEnumConverter()); 52 | matrix.setConverters(vc); 53 | sources.add(matrix); 54 | 55 | BeanParameterSource beanParameterSource = new BeanParameterSource(); 56 | beanParameterSource.setPropertySource(this); 57 | sources.add(beanParameterSource); 58 | 59 | this.setSources(sources); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/FilePartArrayParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.InputStreamReader; 29 | import java.io.Reader; 30 | import java.io.UnsupportedEncodingException; 31 | 32 | import works.cirno.mocha.InvokeContext; 33 | import works.cirno.mocha.MultiPartItem; 34 | import works.cirno.mocha.parameter.name.Parameter; 35 | 36 | public class FilePartArrayParameterSource implements ParameterSource { 37 | 38 | @Override 39 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 40 | if (!ctx.isMultipart()) { 41 | return NOT_HERE; 42 | } 43 | 44 | String name = parameter.getName(); 45 | Class type = parameter.getType(); 46 | if (!type.isArray()) { 47 | return NOT_HERE; 48 | } 49 | MultiPartItem[] parts = ctx.getParts(name); 50 | 51 | if (parts == null || parts.length == 0) { 52 | return NOT_HERE; 53 | } 54 | if (type == MultiPartItem.class) { 55 | return parts; 56 | } else if (type == Reader.class || type == InputStream.class) { 57 | int len = 0; 58 | for (MultiPartItem part : parts) { 59 | if (!part.isFormField()) { 60 | len++; 61 | } 62 | } 63 | 64 | if (len == 0) { 65 | return NOT_HERE; 66 | } 67 | if (type == Reader[].class) { 68 | String encoding = ctx.getCharacterEncoding(); 69 | Reader[] result = new Reader[len]; 70 | int i = 0; 71 | for (MultiPartItem part : parts) { 72 | if (!part.isFormField()) { 73 | try { 74 | ctx.registerCloseable( 75 | result[i++] = new InputStreamReader(part.getInputStream(), encoding), 76 | part.toString()); 77 | } catch (UnsupportedEncodingException e) { 78 | throw new RuntimeException("Encoding " + encoding + " not supported", e); 79 | } catch (IOException e) { 80 | throw new RuntimeException("Can't get inputstream from part", e); 81 | } 82 | } 83 | } 84 | return result; 85 | } else if (type == InputStream[].class) { 86 | String encoding = ctx.getCharacterEncoding(); 87 | InputStream[] result = new InputStream[len]; 88 | int i = 0; 89 | for (MultiPartItem part : parts) { 90 | if (!part.isFormField()) { 91 | try { 92 | ctx.registerCloseable( 93 | result[i++] = part.getInputStream(), 94 | part.toString()); 95 | } catch (IOException e) { 96 | throw new RuntimeException("Can't get inputstream from part", e); 97 | } 98 | } 99 | } 100 | return result; 101 | } else if (type == MultiPartItem[].class) { 102 | MultiPartItem[] result = new MultiPartItem[len]; 103 | int i = 0; 104 | for (MultiPartItem part : parts) { 105 | if (!part.isFormField()) { 106 | result[i++] = part; 107 | } 108 | } 109 | return result; 110 | } 111 | } 112 | return NOT_HERE; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/FilePartParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.InputStreamReader; 29 | import java.io.Reader; 30 | import java.io.UnsupportedEncodingException; 31 | 32 | import works.cirno.mocha.InvokeContext; 33 | import works.cirno.mocha.MultiPartItem; 34 | import works.cirno.mocha.parameter.name.Parameter; 35 | 36 | public class FilePartParameterSource implements ParameterSource { 37 | 38 | @Override 39 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 40 | if (!ctx.isMultipart()) { 41 | return NOT_HERE; 42 | } 43 | String name = parameter.getName(); 44 | Class type = parameter.getType(); 45 | if(type.isArray()){ 46 | return NOT_HERE; 47 | } 48 | MultiPartItem part = ctx.getPart(name); 49 | 50 | if (part == null) { 51 | return NOT_HERE; 52 | } else if (part.isFormField()) { 53 | return NOT_HERE; 54 | } else if (type == Reader.class) { 55 | String encoding = ctx.getCharacterEncoding(); 56 | try { 57 | Reader result = new InputStreamReader(part.getInputStream(), encoding); 58 | ctx.registerCloseable(result, part.toString()); 59 | return result; 60 | } catch (UnsupportedEncodingException e) { 61 | throw new RuntimeException("Encoding " + encoding + " not supported", e); 62 | } catch (IOException e) { 63 | throw new RuntimeException("Can't get inputstream from part", e); 64 | } 65 | } else if (type == InputStream.class) { 66 | try { 67 | InputStream result = part.getInputStream(); 68 | ctx.registerCloseable(result, part.toString()); 69 | return result; 70 | } catch (IOException e) { 71 | throw new RuntimeException("Can't get inputstream from part", e); 72 | } 73 | } else if (type == MultiPartItem.class) { 74 | return part; 75 | } else { 76 | return NOT_HERE; 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/MapValueSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.util.Map; 27 | 28 | import works.cirno.mocha.InvokeContext; 29 | 30 | public class MapValueSource extends AbstractValueSource { 31 | 32 | private final Map map; 33 | 34 | public MapValueSource(Map map) { 35 | super(); 36 | this.map = map; 37 | } 38 | 39 | @Override 40 | public Object getParameter(InvokeContext ctx, String key) { 41 | return map.containsKey(key) ? map.get(key) : NOT_FOUND; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/MatcherValueSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | 28 | public class MatcherValueSource extends AbstractValueSource { 29 | 30 | @Override 31 | public Object getParameter(InvokeContext ctx, String key) { 32 | if(ctx.isGroupName(key)){ 33 | return ctx.getUriMatcher().group(key); 34 | } 35 | return NOT_FOUND; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/MatrixParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.util.List; 27 | 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | import works.cirno.mocha.InvokeContext; 32 | import works.cirno.mocha.parameter.name.Parameter; 33 | 34 | public class MatrixParameterSource implements ParameterSource { 35 | 36 | private static final Logger log = LoggerFactory.getLogger(MatrixParameterSource.class); 37 | private static final Logger perfLog = LoggerFactory.getLogger("perf." + MatrixParameterSource.class.getName()); 38 | 39 | private List sources; 40 | private List converters; 41 | 42 | public List getSources() { 43 | return sources; 44 | } 45 | 46 | public void setSources(List sources) { 47 | this.sources = sources; 48 | } 49 | 50 | public List getConverters() { 51 | return converters; 52 | } 53 | 54 | public void setConverters(List converters) { 55 | this.converters = converters; 56 | } 57 | 58 | @Override 59 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 60 | long beginTime = 0; 61 | boolean usePerfLog = perfLog.isDebugEnabled(); 62 | Class type = parameter.getType(); 63 | String name = parameter.getName(); 64 | for (ValueSource source : sources) { 65 | if (usePerfLog) { 66 | beginTime = System.nanoTime(); 67 | } 68 | Object sourceValue = source.getParameter(ctx, name); 69 | if (usePerfLog) { 70 | perfLog.debug("Get parameter-value named[{}] from source {} in {}ms", parameter.getName(), 71 | source.getClass().getName(), (System.nanoTime() - beginTime) / 1000000f); 72 | } 73 | log.debug("Get parameter[{}]({}) from {}: {}", name, type.getName(), source.getClass().getName(), 74 | sourceValue); 75 | if (sourceValue != ValueSource.NOT_FOUND) { 76 | 77 | Object value = ValueConverter.NOT_CONVERTABLE; 78 | for (ValueConverter converter : converters) { 79 | if (usePerfLog) { 80 | beginTime = System.nanoTime(); 81 | } 82 | value = converter.convert(type, ctx, sourceValue); 83 | if (usePerfLog) { 84 | perfLog.debug("Convert parameter-value named[{}] by converter {} in {}ms", parameter.getName(), 85 | converter.getClass().getName(), (System.nanoTime() - beginTime) / 1000000f); 86 | } 87 | if (value != ValueConverter.NOT_CONVERTABLE) { 88 | return value; 89 | } 90 | } 91 | switch (source.getConvertStrategy()) { 92 | case EXCEPTION_WHEN_UNCONVERTABLE: 93 | throw new RuntimeException( 94 | String.format("Can't find converter to convert parameter[%s] from %s to %s", name, 95 | sourceValue == null ? "null" : sourceValue.getClass().getName(), type.getName())); 96 | case NOT_FOUND_WHEN_UNCONVERTABLE: 97 | return NOT_HERE; 98 | case SKIP_WHEN_UNCONVERTABLE: 99 | break; 100 | case NULL_WHEN_UNCONVERTABLE: 101 | default: 102 | log.warn("Can't find converter to convert parameter[{}] from {} to {}", name, 103 | sourceValue == null ? "null" : sourceValue.getClass().getName(), type.getName()); 104 | return null; 105 | } 106 | } 107 | } 108 | log.debug("Can't find value for parameter[{}]", name); 109 | return NOT_HERE; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/MultiPartStringArraySource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.nio.charset.Charset; 27 | 28 | import works.cirno.mocha.InvokeContext; 29 | import works.cirno.mocha.MultiPartItem; 30 | 31 | public class MultiPartStringArraySource extends AbstractValueSource { 32 | 33 | @Override 34 | public Object getParameter(InvokeContext ctx, String key) { 35 | MultiPartItem[] parts = ctx.getParts(key); 36 | if (parts == null) { 37 | return NOT_FOUND; 38 | } 39 | int len = 0; 40 | for (MultiPartItem part : parts) { 41 | if (part.isFormField()) { 42 | len++; 43 | } 44 | } 45 | if (len == 0) { 46 | return NOT_FOUND; 47 | } 48 | String encoding = ctx.getCharacterEncoding(); 49 | Charset cs = Charset.forName(encoding); 50 | String[] result = new String[len]; 51 | int i = 0; 52 | for (MultiPartItem part : parts) { 53 | if (part.isFormField()) { 54 | result[i] = part.getString(cs); 55 | i++; 56 | } 57 | } 58 | return result; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/MultiPartStringSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.nio.charset.Charset; 27 | 28 | import works.cirno.mocha.InvokeContext; 29 | import works.cirno.mocha.MultiPartItem; 30 | 31 | public class MultiPartStringSource extends AbstractValueSource { 32 | 33 | @Override 34 | public Object getParameter(InvokeContext ctx, String key) { 35 | MultiPartItem part = ctx.getPart(key); 36 | if (part != null && part.isFormField()) { 37 | String encoding = ctx.getCharacterEncoding(); 38 | return part.getString(Charset.forName(encoding)); 39 | } else { 40 | return NOT_FOUND; 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/ParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | import works.cirno.mocha.parameter.name.Parameter; 28 | 29 | public interface ParameterSource { 30 | static final Object NOT_HERE = new Object(){ 31 | public String toString() { 32 | return "NOT_HERE"; 33 | }; 34 | }; 35 | 36 | Object getParameterValue(InvokeContext ctx, Parameter parameter); 37 | } 38 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/RawParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.Reader; 29 | 30 | import works.cirno.mocha.InvokeContext; 31 | import works.cirno.mocha.parameter.name.Parameter; 32 | 33 | public class RawParameterSource implements ParameterSource { 34 | 35 | @Override 36 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 37 | if (ctx.getTarget().isRaw()) { 38 | Class type = parameter.getType(); 39 | try { 40 | if (type == InputStream.class) { 41 | return ctx.getRequest().getInputStream(); 42 | } else if (type == Reader.class) { 43 | return ctx.getRequest().getReader(); 44 | } 45 | } catch (IOException e) { 46 | throw new RuntimeException(e); 47 | } 48 | } 49 | return NOT_HERE; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/RequestArrayValueSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | 28 | public class RequestArrayValueSource extends AbstractValueSource { 29 | 30 | @Override 31 | public Object getParameter(InvokeContext ctx, String key) { 32 | String[] ret = ctx.getRequest().getParameterValues(key); 33 | if (ret == null) { 34 | return NOT_FOUND; 35 | } else { 36 | return ret; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/RequestValueSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | 28 | public class RequestValueSource extends AbstractValueSource { 29 | 30 | @Override 31 | public Object getParameter(InvokeContext ctx, String key) { 32 | String ret = ctx.getRequest().getParameter(key); 33 | if (ret == null) { 34 | return NOT_FOUND; 35 | } else { 36 | return ret; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/StringEnumConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | 28 | public class StringEnumConverter extends AbstractStringArrayConverter { 29 | 30 | @Override 31 | @SuppressWarnings("unchecked") 32 | protected Object convertOne(Class type, InvokeContext ctx, Object from) { 33 | if (!type.isEnum()) { 34 | return NOT_CONVERTABLE; 35 | } 36 | if (from != null && from.getClass() != String.class) { 37 | return NOT_CONVERTABLE; 38 | } 39 | return Enum.valueOf(type.asSubclass(Enum.class), (String) from); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/StringPEConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.beans.PropertyEditor; 27 | import java.beans.PropertyEditorManager; 28 | 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | import works.cirno.mocha.InvokeContext; 33 | 34 | public class StringPEConverter extends AbstractStringArrayConverter { 35 | 36 | private static final Logger log = LoggerFactory.getLogger(StringPEConverter.class); 37 | 38 | @Override 39 | public Object convertOne(Class type, InvokeContext ctx, Object from) { 40 | if (from != null && !(from instanceof String)) { 41 | return NOT_CONVERTABLE; 42 | } 43 | PropertyEditor pe = PropertyEditorManager.findEditor(type); 44 | if (pe == null) { 45 | return NOT_CONVERTABLE; 46 | } 47 | if (from == null) { 48 | return null; 49 | } else { 50 | try { 51 | pe.setAsText((String) from); 52 | return pe.getValue(); 53 | } catch (Exception e) { 54 | log.warn("Can't convert parameter to {}", type.getName(), e); 55 | return NOT_CONVERTABLE; 56 | } 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/TypedParameterSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import java.io.IOException; 27 | import java.io.OutputStream; 28 | import java.io.PrintWriter; 29 | import java.io.Writer; 30 | import java.util.concurrent.ConcurrentHashMap; 31 | 32 | import javax.servlet.ServletOutputStream; 33 | import javax.servlet.ServletRequest; 34 | import javax.servlet.ServletResponse; 35 | import javax.servlet.http.HttpServletRequest; 36 | import javax.servlet.http.HttpServletResponse; 37 | 38 | import works.cirno.mocha.InvokeContext; 39 | import works.cirno.mocha.parameter.name.Parameter; 40 | 41 | public class TypedParameterSource implements ParameterSource { 42 | 43 | private final ParameterSource NULL_FETCHER = new ParameterSource() { 44 | 45 | @Override 46 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 47 | return NOT_HERE; 48 | } 49 | }; 50 | private final ConcurrentHashMap, ParameterSource> fetchers = new ConcurrentHashMap<>(); 51 | 52 | @Override 53 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 54 | Class type = parameter.getType(); 55 | ParameterSource fetcher = fetchers.get(type); 56 | if (fetcher == null) { 57 | if (type.isAssignableFrom(HttpServletRequest.class) && ServletRequest.class.isAssignableFrom(type)) { 58 | fetcher = new ParameterSource() { 59 | 60 | @Override 61 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 62 | return ctx.getRequest(); 63 | } 64 | }; 65 | } else if (type.isAssignableFrom(HttpServletResponse.class) 66 | && ServletResponse.class.isAssignableFrom(type)) { 67 | fetcher = new ParameterSource() { 68 | 69 | @Override 70 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 71 | return ctx.getResponse(); 72 | } 73 | }; 74 | } else if (type.isAssignableFrom(ServletOutputStream.class) && OutputStream.class.isAssignableFrom(type)) { 75 | fetcher = new ParameterSource() { 76 | 77 | @Override 78 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 79 | try { 80 | return ctx.getResponse().getOutputStream(); 81 | } catch (IOException e) { 82 | throw new RuntimeException(e); 83 | } 84 | } 85 | }; 86 | } else if (type.isAssignableFrom(PrintWriter.class) && Writer.class.isAssignableFrom(type)) { 87 | fetcher = new ParameterSource() { 88 | 89 | @Override 90 | public Object getParameterValue(InvokeContext ctx, Parameter parameter) { 91 | try { 92 | return ctx.getResponse().getWriter(); 93 | } catch (IOException e) { 94 | throw new RuntimeException(e); 95 | } 96 | } 97 | }; 98 | } else { 99 | fetcher = NULL_FETCHER; 100 | } 101 | fetchers.putIfAbsent(type, fetcher); 102 | } 103 | return fetcher.getParameterValue(ctx, parameter); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/ValueConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | 28 | public interface ValueConverter { 29 | static final Object NOT_CONVERTABLE = new Object() { 30 | public String toString() { 31 | return "##NOT_CONVERTABLE"; 32 | }; 33 | }; 34 | 35 | Object convert(Class type, InvokeContext ctx, Object from); 36 | } 37 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/parameter/value/ValueSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.parameter.value; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | 28 | public interface ValueSource { 29 | static final Object NOT_FOUND = new Object() { 30 | public String toString() { 31 | return "##NOT_FOUND"; 32 | }; 33 | }; 34 | 35 | Object getParameter(InvokeContext ctx, String key); 36 | 37 | ConvertStrategy getConvertStrategy(); 38 | } 39 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/resolver/InvokeTargetCriteria.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.resolver; 25 | 26 | import java.util.Collections; 27 | import java.util.HashSet; 28 | import java.util.Set; 29 | import java.util.regex.Matcher; 30 | import java.util.regex.Pattern; 31 | 32 | import works.cirno.mocha.InvokeTarget; 33 | 34 | /** 35 | * 36 | */ 37 | public class InvokeTargetCriteria { 38 | protected static final Pattern GROUP_NAME = Pattern.compile("\\(\\?<(.*?)>"); 39 | 40 | private final String uri; 41 | private final Pattern pattern; 42 | private final Set groupNames; 43 | private final String method; 44 | private final InvokeTarget target; 45 | 46 | public InvokeTargetCriteria(String uri, Pattern pattern, String method, InvokeTarget target) { 47 | this.uri = uri; 48 | this.pattern = pattern; 49 | this.method = method; 50 | this.target = target; 51 | 52 | Matcher matcher = GROUP_NAME.matcher(uri); 53 | if (matcher.find()) { 54 | HashSet groupNames = new HashSet<>(3); 55 | do { 56 | groupNames.add(matcher.group(1)); 57 | } while (matcher.find()); 58 | this.groupNames = Collections.unmodifiableSet(groupNames); 59 | } else { 60 | groupNames = Collections. emptySet(); 61 | } 62 | } 63 | 64 | public String getUri() { 65 | return uri; 66 | } 67 | 68 | public Pattern getPattern() { 69 | return pattern; 70 | } 71 | 72 | public String getMethod() { 73 | return method; 74 | } 75 | 76 | public InvokeTarget getTarget() { 77 | return target; 78 | } 79 | 80 | public Set getGroupNames() { 81 | return groupNames; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/resolver/InvokeTargetResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.resolver; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | import works.cirno.mocha.InvokeTarget; 28 | 29 | /** 30 | * 31 | */ 32 | public interface InvokeTargetResolver { 33 | public static final InvokeTarget[] NO_TARGET = new InvokeTarget[0]; 34 | 35 | InvokeTargetCriteria addServe(String uri, String method, InvokeTarget target); 36 | 37 | InvokeContext resolve(String uri, String method); 38 | } 39 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/resolver/PrefixDictInvokeTargetResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.resolver; 25 | 26 | import java.util.ArrayList; 27 | import java.util.Collections; 28 | import java.util.HashMap; 29 | import java.util.List; 30 | import java.util.regex.Matcher; 31 | import java.util.regex.Pattern; 32 | 33 | import works.cirno.mocha.InvokeContext; 34 | import works.cirno.mocha.InvokeTarget; 35 | import works.cirno.mocha.resolver.prd.LongTreePrefixDict; 36 | import works.cirno.mocha.resolver.prd.PrefixDict; 37 | 38 | /** 39 | * 40 | */ 41 | public class PrefixDictInvokeTargetResolver implements InvokeTargetResolver { 42 | private static final Pattern REGEX_META = Pattern.compile("[(\\[.\\\\?*+|]"); 43 | 44 | private HashMap> fullMatchUris = new HashMap<>(); 45 | private PrefixDict dict; 46 | 47 | public PrefixDictInvokeTargetResolver() { 48 | this.dict = new LongTreePrefixDict<>(); 49 | } 50 | 51 | public PrefixDictInvokeTargetResolver(PrefixDict dict) { 52 | this.dict = dict; 53 | } 54 | 55 | private String getPrefix(String uri) { 56 | int trimStart = 0; 57 | int trimEnd = 0; 58 | if (uri.startsWith("^")) { 59 | trimStart = 1; 60 | } 61 | if (uri.endsWith("$")) { 62 | trimEnd = 1; 63 | } 64 | if (trimStart + trimEnd > 0) { 65 | uri = uri.substring(trimStart, uri.length() - trimEnd); 66 | } 67 | int idx = -1; 68 | Matcher matcher = REGEX_META.matcher(uri); 69 | if (matcher.find()) { 70 | switch (matcher.group().charAt(0)) { 71 | case '?': 72 | case '*': 73 | case '+': 74 | case '|': 75 | idx = 0; 76 | break; 77 | default: 78 | idx = matcher.start(); 79 | break; 80 | } 81 | } 82 | switch (idx) { 83 | case -1: 84 | return null; 85 | case 0: 86 | return ""; 87 | default: 88 | return uri.substring(0, idx); 89 | } 90 | } 91 | 92 | @Override 93 | public InvokeTargetCriteria addServe(String uri, String method, InvokeTarget target) { 94 | String prefix = getPrefix(uri); 95 | if (prefix == null) { 96 | ArrayList params = fullMatchUris.get(uri); 97 | if (params == null) { 98 | params = new ArrayList<>(); 99 | fullMatchUris.put(uri, params); 100 | } 101 | InvokeTargetCriteria criteria = new InvokeTargetCriteria(uri, null, method, target); 102 | params.add(criteria); 103 | return criteria; 104 | } else { 105 | PrefixedInvokeTargetCriteria criteria = new PrefixedInvokeTargetCriteria(uri, 106 | Pattern.compile(uri.substring(prefix.length())), method, target, prefix); 107 | dict.add(prefix, criteria); 108 | return criteria; 109 | } 110 | } 111 | 112 | @Override 113 | public InvokeContext resolve(String uri, String method) { 114 | List fullMatches = fullMatchUris.get(uri); 115 | if (fullMatches != null) { 116 | for (InvokeTargetCriteria criteria : fullMatches) { 117 | if (criteria.getMethod() == null || criteria.getMethod().equals(method)) { 118 | return new InvokeContext(criteria.getTarget(), null, Collections. emptySet()); 119 | } 120 | } 121 | } 122 | 123 | List prefixMatches = dict.select(uri); 124 | for (int i = prefixMatches.size() - 1; i >= 0; i--) { 125 | PrefixedInvokeTargetCriteria criteria = prefixMatches.get(i); 126 | Matcher matcher = criteria.getPattern().matcher(uri.substring(criteria.getPrefix().length())); 127 | if ((criteria.getMethod() == null || criteria.getMethod().equals(method)) && matcher.matches()) { 128 | return new InvokeContext(criteria.getTarget(), matcher, criteria.getGroupNames()); 129 | } 130 | } 131 | return null; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/resolver/PrefixedInvokeTargetCriteria.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.resolver; 25 | 26 | import java.util.regex.Pattern; 27 | 28 | import works.cirno.mocha.InvokeTarget; 29 | 30 | /** 31 | * 32 | */ 33 | public class PrefixedInvokeTargetCriteria extends InvokeTargetCriteria { 34 | private final String prefix; 35 | 36 | public PrefixedInvokeTargetCriteria(String uri, Pattern pattern, String method, InvokeTarget target, String prefix) { 37 | super(uri, pattern, method, target); 38 | this.prefix = prefix; 39 | } 40 | 41 | public String getPrefix() { 42 | return prefix; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/resolver/RegexInvokeTargetResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.resolver; 25 | 26 | import java.util.ArrayList; 27 | import java.util.Collections; 28 | import java.util.regex.Matcher; 29 | import java.util.regex.Pattern; 30 | 31 | import works.cirno.mocha.InvokeContext; 32 | import works.cirno.mocha.InvokeTarget; 33 | 34 | /** 35 | * 36 | */ 37 | public class RegexInvokeTargetResolver implements InvokeTargetResolver { 38 | private ArrayList targets = new ArrayList<>(); 39 | 40 | @Override 41 | public InvokeTargetCriteria addServe(String uri, String method, InvokeTarget target) { 42 | InvokeTargetCriteria criteria = new InvokeTargetCriteria(uri, Pattern.compile(uri), method, target); 43 | targets.add(criteria); 44 | return criteria; 45 | } 46 | 47 | @Override 48 | public InvokeContext resolve(String uri, String method) { 49 | for (InvokeTargetCriteria criteria : targets) { 50 | Pattern pattern = criteria.getPattern(); 51 | Matcher matcher = pattern.matcher(uri); 52 | if (matcher.matches() && (criteria.getMethod() == null || criteria.getMethod().equals(method))) { 53 | return new InvokeContext(criteria.getTarget(), matcher, Collections. emptySet()); 54 | } 55 | } 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/resolver/prd/LongTreePrefixDict.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.resolver.prd; 25 | 26 | /** 27 | * 28 | */ 29 | public class LongTreePrefixDict extends TreePrefixDict implements PrefixDict { 30 | 31 | @Override 32 | protected TreePrefixDict createNode() { 33 | return new LongTreePrefixDict(); 34 | } 35 | 36 | @Override 37 | protected int getNewSize(String prefix) { 38 | if (this.size == 0) { 39 | return prefix.length(); 40 | } 41 | 42 | return Math.min(prefix.length(), size); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/resolver/prd/PrefixDict.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.resolver.prd; 25 | 26 | import java.util.List; 27 | 28 | /** 29 | * 30 | */ 31 | public interface PrefixDict { 32 | void add(String prefix, T value); 33 | 34 | List select(String string); 35 | 36 | List select(String string, List values); 37 | } 38 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/resolver/prd/TreePrefixDict.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.resolver.prd; 25 | 26 | import java.util.*; 27 | 28 | /** 29 | * 30 | */ 31 | public class TreePrefixDict implements PrefixDict { 32 | 33 | protected HashMap> nodes = new HashMap<>(); 34 | protected int size = 0; 35 | protected final ArrayList values = new ArrayList<>(4); 36 | 37 | protected TreePrefixDict createNode() { 38 | return new TreePrefixDict(); 39 | } 40 | 41 | private void changeSize(int newSize) { 42 | assert newSize > 0; 43 | assert newSize < size; 44 | int diffSize = size - newSize; 45 | HashMap> newNodes = new HashMap<>(); 46 | for (Map.Entry> entry : nodes.entrySet()) { 47 | String key = entry.getKey(); 48 | String newKey1 = key.substring(0, newSize); 49 | String newKey2 = key.substring(newSize); 50 | TreePrefixDict node = newNodes.get(newKey1); 51 | if (node == null) { 52 | node = createNode(); 53 | newNodes.put(newKey1, node); 54 | } 55 | node.size = diffSize; 56 | node.nodes.put(newKey2, entry.getValue()); 57 | } 58 | this.nodes = newNodes; 59 | this.size = newSize; 60 | } 61 | 62 | protected int getNewSize(String prefix) { 63 | if (this.size == 0) { 64 | return prefix.length(); 65 | } else { 66 | Set others = nodes.keySet(); 67 | int cps = Math.min(prefix.length(), size); 68 | all: 69 | for (String other : others) { 70 | for (int i = 0; i < cps; i++) { 71 | if (prefix.charAt(i) != other.charAt(i)) { 72 | cps = i; 73 | if (cps == 0) { 74 | break all; 75 | } else { 76 | break; 77 | } 78 | } 79 | } 80 | } 81 | return Math.min(cps + 1, Math.min(prefix.length(), size)); 82 | } 83 | } 84 | 85 | public void add(String prefix, T value) { 86 | if (prefix.length() == 0) { 87 | values.add(value); 88 | } else if (this.size == 0) { 89 | this.size = prefix.length(); 90 | TreePrefixDict node = createNode(); 91 | nodes.put(prefix, node); 92 | node.add("", value); 93 | } else { 94 | int newSize = getNewSize(prefix); 95 | if (newSize < size) { 96 | changeSize(newSize); 97 | } 98 | String key1 = prefix.substring(0, this.size); 99 | String key2 = prefix.substring(this.size); 100 | TreePrefixDict node = nodes.get(key1); 101 | if (node == null) { 102 | node = createNode(); 103 | nodes.put(key1, node); 104 | } 105 | node.add(key2, value); 106 | } 107 | } 108 | 109 | public List select(String string) { 110 | return select(string, null); 111 | } 112 | 113 | public List select(String string, List values) { 114 | if (values == null) { 115 | values = new ArrayList<>(); 116 | } 117 | values.addAll(this.values); 118 | int len = string.length(); 119 | if (len >= size) { 120 | String prefix = string.substring(0, size); 121 | TreePrefixDict node = nodes.get(prefix); 122 | if (node != null) { 123 | string = string.substring(size); 124 | node.select(string, values); 125 | } 126 | } 127 | return values; 128 | } 129 | 130 | public void printNodes(int indent) { 131 | for (int i = 0; i < indent; i++) { 132 | System.out.print("\t"); 133 | } 134 | System.out.println("\"\": " + values); 135 | for (Map.Entry> entry : nodes.entrySet()) { 136 | for (int i = 0; i < indent; i++) { 137 | System.out.print("\t"); 138 | } 139 | System.out.println("\"" + entry.getKey() + "\":"); 140 | entry.getValue().printNodes(indent + 1); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/result/CodeResultRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.result; 25 | 26 | import java.io.IOException; 27 | 28 | import javax.servlet.http.HttpServletResponse; 29 | 30 | import org.slf4j.Logger; 31 | import org.slf4j.LoggerFactory; 32 | 33 | import works.cirno.mocha.InvokeContext; 34 | 35 | /** 36 | * 37 | */ 38 | public class CodeResultRenderer implements Renderer { 39 | private static Logger log = LoggerFactory.getLogger(CodeResultRenderer.class); 40 | 41 | private static final CodeResultRenderer instance = new CodeResultRenderer(); 42 | 43 | public static CodeResultRenderer instance() { 44 | return instance; 45 | } 46 | 47 | @Override 48 | public boolean renderResult(InvokeContext ctx, Object resultObj) { 49 | HttpServletResponse resp = ctx.getResponse(); 50 | if (resultObj instanceof Number) { 51 | try { 52 | resp.sendError(((Number) resultObj).intValue()); 53 | } catch (IOException e) { 54 | log.warn("Can't send error to client", e); 55 | } 56 | return true; 57 | } 58 | return false; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/result/InputStreamResultRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.result; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.OutputStream; 29 | 30 | import javax.servlet.http.HttpServletResponse; 31 | 32 | import works.cirno.mocha.InvokeContext; 33 | 34 | public class InputStreamResultRenderer implements Renderer { 35 | 36 | @Override 37 | public boolean renderResult(InvokeContext ctx, Object resultObj) { 38 | HttpServletResponse resp = ctx.getResponse(); 39 | if (resultObj instanceof InputStream) { 40 | try (InputStream is = (InputStream) resultObj; OutputStream os = resp.getOutputStream()) { 41 | byte[] buf = new byte[4096]; 42 | int read; 43 | while ((read = is.read(buf)) >= 0) { 44 | os.write(buf, 0, read); 45 | } 46 | } catch (IOException e) { 47 | ctx.getTarget().log().error("Can't write stream to client", e); 48 | } 49 | return true; 50 | } 51 | return false; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/result/Renderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.result; 25 | 26 | import works.cirno.mocha.InvokeContext; 27 | 28 | public interface Renderer { 29 | boolean renderResult(InvokeContext ctx, Object resultObj); 30 | } 31 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/result/ResultType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.result; 25 | 26 | public enum ResultType { 27 | forward, redirect 28 | } 29 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/result/ServletResultRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.result; 25 | 26 | import java.io.IOException; 27 | import java.util.AbstractMap.SimpleEntry; 28 | import java.util.Collections; 29 | import java.util.HashMap; 30 | import java.util.Map; 31 | import java.util.Map.Entry; 32 | 33 | import javax.servlet.ServletException; 34 | import javax.servlet.http.HttpServletRequest; 35 | import javax.servlet.http.HttpServletResponse; 36 | 37 | import works.cirno.mocha.InvokeContext; 38 | 39 | public class ServletResultRenderer implements Renderer { 40 | 41 | private HashMap> results = new HashMap<>(); 42 | 43 | public void addResult(String name, ResultType type, String path) { 44 | if (name == null) { 45 | throw new NullPointerException("name"); 46 | } 47 | results.put(name, new SimpleEntry(type, path)); 48 | } 49 | 50 | public boolean renderResult(InvokeContext ctx, Object resultObj) { 51 | HttpServletRequest req = ctx.getRequest(); 52 | HttpServletResponse resp = ctx.getResponse(); 53 | try { 54 | String name; 55 | Iterable> attributes; 56 | if (resultObj instanceof String) { 57 | name = (String) resultObj; 58 | attributes = Collections.emptyList(); 59 | } else if (resultObj instanceof View) { 60 | View view = (View) resultObj; 61 | name = view.getName(); 62 | attributes = view.getAttributes(); 63 | } else { 64 | return false; 65 | } 66 | Entry result = results.get(name); 67 | if (result != null) { 68 | ResultType type = result.getKey(); 69 | String path = result.getValue(); 70 | switch (type) { 71 | case forward: 72 | for (Map.Entry attribute : attributes) { 73 | req.setAttribute(attribute.getKey(), attribute.getValue()); 74 | } 75 | req.getRequestDispatcher(path).forward(req, resp); 76 | return true; 77 | case redirect: 78 | resp.sendRedirect(path); 79 | return true; 80 | } 81 | } 82 | return false; 83 | } catch (ServletException | IOException e) { 84 | ctx.getTarget().handleException(ctx, e); 85 | return true; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /mvc-core/src/main/java/works/cirno/mocha/result/View.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha.result; 25 | 26 | import java.util.HashMap; 27 | import java.util.Map.Entry; 28 | 29 | public class View { 30 | private String name; 31 | private HashMap attributes = new HashMap<>(); 32 | 33 | public View(String name) { 34 | this.name = name; 35 | } 36 | 37 | public View attribute(String key, Object value) { 38 | attributes.put(key, value); 39 | return this; 40 | } 41 | 42 | public Object getAttribute(String key) { 43 | return attributes.get(key); 44 | } 45 | 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | public Iterable> getAttributes() { 51 | return attributes.entrySet(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /mvc-core/src/test/java/works/cirno/mocha/InvokeTargetResolverTest.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import works.cirno.mocha.InvokeContext; 7 | import works.cirno.mocha.resolver.InvokeTargetResolver; 8 | import works.cirno.mocha.resolver.PrefixDictInvokeTargetResolver; 9 | import works.cirno.mocha.resolver.RegexInvokeTargetResolver; 10 | 11 | import java.io.BufferedReader; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.io.InputStreamReader; 15 | import java.nio.charset.Charset; 16 | import java.util.Collection; 17 | import java.util.Properties; 18 | import java.util.concurrent.ThreadLocalRandom; 19 | 20 | /** 21 | * 22 | */ 23 | public class InvokeTargetResolverTest { 24 | 25 | private long doBenchmark(InvokeTargetResolver resolver, Collection keys) { 26 | long ret = 0; 27 | long begin = System.nanoTime(); 28 | for (String key : keys) { 29 | int hash = resolver.resolve(key, "GET").hashCode(); 30 | ret += hash; 31 | } 32 | long dur = System.nanoTime() - begin; 33 | if (ThreadLocalRandom.current().nextInt(100000) == 1) { 34 | System.out.println("Please ignore: " + ret); 35 | } 36 | return dur; 37 | } 38 | 39 | public void doTest(InvokeTargetResolver resolver) { 40 | 41 | try (BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/uris.list"), Charset.forName("utf-8")))) { 42 | String line; 43 | while ((line = br.readLine()) != null) { 44 | line = line.trim(); 45 | if (line.length() > 0) { 46 | resolver.addServe(line, "GET", new MockInvokeTarget(line)); 47 | } 48 | } 49 | } catch (IOException e) { 50 | throw new RuntimeException(e); 51 | } 52 | 53 | Properties p = new Properties(); 54 | try (InputStream testIs = getClass().getResourceAsStream("/uritest.properties")) { 55 | p.load(testIs); 56 | } catch (IOException e) { 57 | throw new RuntimeException(e); 58 | } 59 | 60 | for (String key : p.stringPropertyNames()) { 61 | InvokeContext ctx = resolver.resolve(key, "GET"); 62 | MockInvokeTarget target = (MockInvokeTarget) ctx.getTarget(); 63 | String[] expected = p.getProperty(key).split(","); 64 | Assert.assertEquals(target.getTestData(), expected[0]); 65 | if (expected.length == 1) { 66 | // Assert.assertNull(ctx.getUriMatcher()); 67 | } else { 68 | for (int i = 1, max = expected.length; i < max; i++) { 69 | int idx = expected[i].indexOf('='); 70 | if (idx < 0) { 71 | throw new IllegalArgumentException("Illegal test descriptor line: " + key + "=" + p.getProperty(key)); 72 | } 73 | String ek = expected[i].substring(0, idx); 74 | String ev = expected[i].substring(idx + 1); 75 | Assert.assertEquals(ev, ctx.getUriMatcher().group(ek)); 76 | } 77 | } 78 | } 79 | 80 | long total = 0; 81 | for (int i = 0; i < 50; i++) { 82 | long dur = doBenchmark(resolver, p.stringPropertyNames()); 83 | if (i > 39) { 84 | total += dur; 85 | } 86 | } 87 | System.out.println(resolver.getClass().getName() + ": " + (p.stringPropertyNames().size() * 20) + " / " + p.stringPropertyNames().size() + " uris resolved in " + (total / 1000000.0) + "ms"); 88 | } 89 | 90 | @Test 91 | public void testRegexInvokeTargetResolver() { 92 | doTest(new RegexInvokeTargetResolver()); 93 | } 94 | 95 | @Test 96 | public void testPrefixedInvokeTargetResolver() { 97 | doTest(new PrefixDictInvokeTargetResolver()); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /mvc-core/src/test/java/works/cirno/mocha/MockInvokeTarget.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha; 2 | 3 | import works.cirno.mocha.InvokeTarget; 4 | import works.cirno.mocha.parameter.name.ASMTestController; 5 | 6 | /** 7 | * 8 | */ 9 | public class MockInvokeTarget extends InvokeTarget { 10 | 11 | private String testData; 12 | 13 | public MockInvokeTarget(String testData) { 14 | super(null, new ASMTestController(), "method1"); 15 | this.testData = testData; 16 | } 17 | 18 | public String getTestData() { 19 | return testData; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mvc-core/src/test/java/works/cirno/mocha/parameter/name/ASMParameterAnalyzerTest.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.parameter.name; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import works.cirno.mocha.InvokeTarget; 7 | import works.cirno.mocha.parameter.name.ASMParameterAnalyzer; 8 | import works.cirno.mocha.parameter.name.Parameter; 9 | 10 | /** 11 | * 12 | */ 13 | public class ASMParameterAnalyzerTest { 14 | 15 | private ThreadLocal analyzer = new ThreadLocal() { 16 | @Override 17 | protected ASMParameterAnalyzer initialValue() { 18 | return new ASMParameterAnalyzer(); 19 | } 20 | }; 21 | 22 | @Test 23 | public void testNamedArguments1() throws Exception { 24 | ASMParameterAnalyzer analyzer = this.analyzer.get(); 25 | Class controllerClass = ASMTestController.class; 26 | Object controller = controllerClass.newInstance(); 27 | 28 | InvokeTarget target = new InvokeTarget(null, controller, "method1"); 29 | Parameter[] parameters = analyzer.getParameters(target); 30 | Assert.assertEquals(0, parameters.length); 31 | } 32 | 33 | @Test 34 | public void testNamedArguments2() throws Exception { 35 | ASMParameterAnalyzer analyzer = this.analyzer.get(); 36 | Class controllerClass = ASMTestController.class; 37 | Object controller = controllerClass.newInstance(); 38 | 39 | InvokeTarget target = new InvokeTarget(null, controller, "method2"); 40 | Parameter[] parameters = analyzer.getParameters(target); 41 | 42 | Assert.assertEquals(3, parameters.length); 43 | Assert.assertEquals("name", parameters[0].getName()); 44 | Assert.assertEquals("id", parameters[1].getName()); 45 | Assert.assertEquals("uuid", parameters[2].getName()); 46 | } 47 | 48 | @Test 49 | public void testNamedArguments3() throws Exception { 50 | ASMParameterAnalyzer analyzer = this.analyzer.get(); 51 | Class controllerClass = ASMTestController.class; 52 | Object controller = controllerClass.newInstance(); 53 | 54 | InvokeTarget target = new InvokeTarget(null, controller, "method3"); 55 | Parameter[] parameters = analyzer.getParameters(target); 56 | 57 | Assert.assertEquals(3, parameters.length); 58 | Assert.assertEquals("name", parameters[0].getName()); 59 | Assert.assertEquals("id", parameters[1].getName()); 60 | Assert.assertEquals("uuid", parameters[2].getName()); 61 | } 62 | 63 | @Test 64 | public void testNamedArguments4() throws Exception { 65 | ASMParameterAnalyzer analyzer = this.analyzer.get(); 66 | Class controllerClass = ASMTestController.class; 67 | Object controller = controllerClass.newInstance(); 68 | 69 | InvokeTarget target = new InvokeTarget(null, controller, "method4"); 70 | Parameter[] parameters = analyzer.getParameters(target); 71 | 72 | Assert.assertEquals(3, parameters.length); 73 | Assert.assertEquals("name", parameters[0].getName()); 74 | Assert.assertEquals("id", parameters[1].getName()); 75 | Assert.assertEquals("uuid", parameters[2].getName()); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /mvc-core/src/test/java/works/cirno/mocha/parameter/name/ASMTestController.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.parameter.name; 2 | 3 | /** 4 | * 5 | */ 6 | public class ASMTestController { 7 | public void methodD() { 8 | 9 | } 10 | 11 | public void methodD(String arg) { 12 | 13 | } 14 | 15 | public void method1() { 16 | 17 | } 18 | 19 | public String method2(String name, Integer id, String uuid) { 20 | return name + id; 21 | } 22 | 23 | public String method3(String name, Integer id, String uuid) { 24 | { 25 | Integer j = name.hashCode() + id + uuid.hashCode(); 26 | id = j; 27 | } 28 | 29 | Integer i = 15; 30 | return i + "a"; 31 | } 32 | 33 | public String method4(String name, Integer id, String uuid) { 34 | return 1 + uuid; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /mvc-core/src/test/java/works/cirno/mocha/parameter/name/AnnotationParameterAnalyzerTest.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.parameter.name; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import works.cirno.mocha.InvokeTarget; 7 | 8 | /** 9 | * 10 | */ 11 | public class AnnotationParameterAnalyzerTest { 12 | 13 | private ThreadLocal analyzer = new ThreadLocal() { 14 | @Override 15 | protected AnnotationParameterAnalyzer initialValue() { 16 | return new AnnotationParameterAnalyzer(); 17 | } 18 | }; 19 | 20 | @Test 21 | public void testNamedArguments1() throws Exception { 22 | AnnotationParameterAnalyzer analyzer = this.analyzer.get(); 23 | Class controllerClass = TestController.class; 24 | Object controller = controllerClass.newInstance(); 25 | 26 | InvokeTarget target = new InvokeTarget(null, controller, "method1"); 27 | Parameter[] parameters = analyzer.getParameters(target); 28 | Assert.assertEquals(0, parameters.length); 29 | } 30 | 31 | @Test 32 | public void testNamedArguments2() throws Exception { 33 | AnnotationParameterAnalyzer analyzer = this.analyzer.get(); 34 | Class controllerClass = TestController.class; 35 | Object controller = controllerClass.newInstance(); 36 | 37 | InvokeTarget target = new InvokeTarget(null, controller, "method2"); 38 | Parameter[] parameters = analyzer.getParameters(target); 39 | 40 | Assert.assertEquals(3, parameters.length); 41 | Assert.assertEquals("name", parameters[0].getName()); 42 | Assert.assertEquals("id", parameters[1].getName()); 43 | Assert.assertEquals("uuid", parameters[2].getName()); 44 | } 45 | 46 | @Test 47 | public void testNamedArguments3() throws Exception { 48 | AnnotationParameterAnalyzer analyzer = this.analyzer.get(); 49 | Class controllerClass = TestController.class; 50 | Object controller = controllerClass.newInstance(); 51 | 52 | InvokeTarget target = new InvokeTarget(null, controller, "method3"); 53 | Parameter[] parameters = analyzer.getParameters(target); 54 | 55 | Assert.assertEquals(3, parameters.length); 56 | Assert.assertEquals("name", parameters[0].getName()); 57 | Assert.assertEquals("id", parameters[1].getName()); 58 | Assert.assertEquals("uuid", parameters[2].getName()); 59 | } 60 | 61 | @Test 62 | public void testNamedArguments4() throws Exception { 63 | AnnotationParameterAnalyzer analyzer = this.analyzer.get(); 64 | Class controllerClass = TestController.class; 65 | Object controller = controllerClass.newInstance(); 66 | 67 | InvokeTarget target = new InvokeTarget(null, controller, "method4"); 68 | Parameter[] parameters = analyzer.getParameters(target); 69 | 70 | Assert.assertEquals(3, parameters.length); 71 | Assert.assertEquals("name", parameters[0].getName()); 72 | Assert.assertEquals("id", parameters[1].getName()); 73 | Assert.assertEquals("uuid", parameters[2].getName()); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /mvc-core/src/test/java/works/cirno/mocha/parameter/name/TestController.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.parameter.name; 2 | 3 | import works.cirno.mocha.parameter.name.NamedParam; 4 | 5 | /** 6 | * 7 | */ 8 | public class TestController { 9 | public void methodD() { 10 | 11 | } 12 | 13 | public void methodD(@NamedParam("arg") String arg) { 14 | 15 | } 16 | 17 | public void method1() { 18 | 19 | } 20 | 21 | public String method2(@NamedParam("name") String name, @NamedParam("id") Integer id, @NamedParam("uuid") String uuid) { 22 | return name + id; 23 | } 24 | 25 | public String method3(@NamedParam("name") String name, @NamedParam("id") Integer id, @NamedParam("uuid") String uuid) { 26 | { 27 | Integer j = name.hashCode() + id + uuid.hashCode(); 28 | id = j; 29 | } 30 | 31 | Integer i = 15; 32 | return i + "a"; 33 | } 34 | 35 | public String method4(@NamedParam("name") String name, @NamedParam("id") Integer id, @NamedParam("uuid") String uuid) { 36 | return 1 + uuid; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /mvc-core/src/test/java/works/cirno/mocha/resolver/prd/TreePrefixDictTest.java: -------------------------------------------------------------------------------- 1 | package works.cirno.mocha.resolver.prd; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import works.cirno.mocha.resolver.prd.LongTreePrefixDict; 7 | import works.cirno.mocha.resolver.prd.TreePrefixDict; 8 | 9 | /** 10 | * 11 | */ 12 | 13 | public class TreePrefixDictTest { 14 | 15 | private void add(TreePrefixDict prd, String prefix) { 16 | prd.add(prefix, prefix); 17 | } 18 | 19 | private void testDict(TreePrefixDict prd) { 20 | System.out.println("Testing " + prd.getClass().getName()); 21 | add(prd, "/json/user/manage"); 22 | add(prd, "/json/user/manage/"); 23 | add(prd, "/json/user/manage/add"); 24 | add(prd, "/json/user/manage/add/1"); 25 | add(prd, "/json/user/manage/add/2"); 26 | add(prd, "/json/user/manage/add/3"); 27 | add(prd, "/json/user/manage/delete"); 28 | add(prd, "/json/user/manage/modify"); 29 | add(prd, "/json/user"); 30 | add(prd, "/json/unit"); 31 | add(prd, "/json/unit/manage"); 32 | add(prd, "/"); 33 | add(prd, "/login"); 34 | add(prd, "/login.do"); 35 | add(prd, "aaaaaab"); 36 | add(prd, "aaaaaac"); 37 | add(prd, "aaaaaad"); 38 | add(prd, "abaaaab"); 39 | add(prd, "abaaaac"); 40 | add(prd, "abaaaad"); 41 | prd.printNodes(0); 42 | add(prd, "aaaa"); 43 | add(prd, "aa"); 44 | prd.printNodes(0); 45 | 46 | java.util.List var = prd.select("/login"); 47 | Assert.assertArrayEquals(var.toArray(new String[var.size()]), new String[]{"/", "/login"}); 48 | var = prd.select("/login.do"); 49 | Assert.assertArrayEquals(var.toArray(new String[var.size()]), new String[]{"/", "/login", "/login.do"}); 50 | 51 | var = prd.select("/json/user/manage/add"); 52 | Assert.assertArrayEquals(var.toArray(new String[var.size()]), new String[]{"/", "/json/user", "/json/user/manage", "/json/user/manage/", "/json/user/manage/add"}); 53 | var = prd.select("/json/user/manage/45"); 54 | Assert.assertArrayEquals(var.toArray(new String[var.size()]), new String[]{"/", "/json/user", "/json/user/manage", "/json/user/manage/"}); 55 | var = prd.select("/json/user/manage/add/45"); 56 | Assert.assertArrayEquals(var.toArray(new String[var.size()]), new String[]{"/", "/json/user", "/json/user/manage", "/json/user/manage/", "/json/user/manage/add"}); 57 | var = prd.select("/json/user/manage/delete/45"); 58 | Assert.assertArrayEquals(var.toArray(new String[var.size()]), new String[]{"/", "/json/user", "/json/user/manage", "/json/user/manage/", "/json/user/manage/delete"}); 59 | var = prd.select("aaaaaac"); 60 | Assert.assertArrayEquals(var.toArray(new String[var.size()]), new String[]{"aa", "aaaa", "aaaaaac"}); 61 | var = prd.select("abaaaac"); 62 | Assert.assertArrayEquals(var.toArray(new String[var.size()]), new String[]{"abaaaac"}); 63 | } 64 | 65 | @Test 66 | public void testPrefixReverseDict() { 67 | TreePrefixDict prd = new TreePrefixDict<>(); 68 | testDict(prd); 69 | } 70 | 71 | @Test 72 | public void testLongPrefixDict() { 73 | LongTreePrefixDict prd = new LongTreePrefixDict<>(); 74 | testDict(prd); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /mvc-core/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Root logger option 2 | log4j.rootLogger=DEBUG, stdout 3 | 4 | # Direct log messages to 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{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 9 | -------------------------------------------------------------------------------- /mvc-core/src/test/resources/uris.list: -------------------------------------------------------------------------------- 1 | /api/contactlist 2 | /api/contactdetail 3 | /api/contactsInfo 4 | /api/projectlist 5 | /api/foundchatlist 6 | /api/chatlist 7 | /api/chatattr 8 | /api/chatgrouplist 9 | /api/chatNameIcon 10 | /api/symposiumSign 11 | /api/updateTopicRemind 12 | /api/pns 13 | /api/timesync 14 | /api/check4updates 15 | /api/userhead 16 | /api/topichead 17 | /api/roomhead 18 | /api/grouplist 19 | /api/feedback 20 | /api/topichistory 21 | /copyright 22 | /api/pushMessage 23 | /api/push/notify 24 | /tapi/clearCache/(?.*?) 25 | /api/web/login 26 | /api/web/messages 27 | /api/web/messagesBy 28 | /api/web/messagesp2p/(?.*?) 29 | /api/web/userhead/i/(?.*?) 30 | /api/web/userhead/t/(?.*?) 31 | /api/web/topichead/(?.*?)/(?.*?) 32 | /mail/attachment/(?.*?) 33 | /tapi/topic/create 34 | /tapi/topic/update 35 | /tapi/topic/history 36 | /tapi/topic/group/create 37 | /tapi/topic/group/update 38 | /account 39 | /api/easterEgg 40 | /api/web/getJFToken 41 | /api/web/ssoLogout 42 | /api/web/validateJFToken 43 | /api/web/getRefreshToken 44 | /api/web/log 45 | /img/upload 46 | /img64/upload 47 | /img/download 48 | /img/grapeupload 49 | /img/i/(?.*?)/get 50 | /img/i/(?.*?)/upload 51 | /img/t/(?.*?)/get 52 | /img/t/(?.*?)/upload 53 | /app/upload 54 | /app/beta/upload 55 | / 56 | /app 57 | /app/beta 58 | /app/fix 59 | /ios/(?.*?) 60 | /android 61 | /iosBeta/(?.*?) 62 | /androidBeta 63 | /api/fileUpload 64 | /api/fileDownload 65 | /iosDownload 66 | /androidDownload 67 | /admin/init/group 68 | /admin/init/groupTopic 69 | /api/fav/mock/store 70 | /api/fav/list/(?.*?)/(?.*?) 71 | /api/fav/get/(?.*?)/(?.*?) 72 | /api/fav/remove 73 | /api/fav/quota/(?.*?) 74 | /api/fav/store 75 | /api/fav/template 76 | /api/fav/template/list 77 | /api/fav/template/show 78 | /api/fav/template/save 79 | /api/fav/template/edit/(?.*?) 80 | /api/fav/template/update 81 | /api/fav/template/delete/(?.*?) 82 | /api/fav/template/reload 83 | /bbs/rooms 84 | /bbs/forward 85 | /bbs/roomhead 86 | /kf/choose 87 | /kf/close 88 | /api/kf/choose 89 | /api/config/user/set 90 | /api/config/user/list 91 | /api/config/global/list 92 | /config/global 93 | /config/global/update 94 | /config/cmd/send 95 | /tapi/topic/history/count 96 | /tapi/topic/chatinfo -------------------------------------------------------------------------------- /mvc-core/src/test/resources/uritest.properties: -------------------------------------------------------------------------------- 1 | /api/contactlist=/api/contactlist 2 | /api/contactdetail=/api/contactdetail 3 | /api/contactsInfo=/api/contactsInfo 4 | /api/projectlist=/api/projectlist 5 | /api/foundchatlist=/api/foundchatlist 6 | /api/chatlist=/api/chatlist 7 | /api/chatattr=/api/chatattr 8 | /api/chatgrouplist=/api/chatgrouplist 9 | /api/chatNameIcon=/api/chatNameIcon 10 | /api/symposiumSign=/api/symposiumSign 11 | /api/updateTopicRemind=/api/updateTopicRemind 12 | /api/pns=/api/pns 13 | /api/timesync=/api/timesync 14 | /api/check4updates=/api/check4updates 15 | /api/userhead=/api/userhead 16 | /api/topichead=/api/topichead 17 | /api/roomhead=/api/roomhead 18 | /api/grouplist=/api/grouplist 19 | /api/feedback=/api/feedback 20 | /api/topichistory=/api/topichistory 21 | /copyright=/copyright 22 | /api/pushMessage=/api/pushMessage 23 | /api/push/notify=/api/push/notify 24 | /tapi/clearCache/1=/tapi/clearCache/(?.*?),type=1 25 | /api/web/login=/api/web/login 26 | /api/web/messages=/api/web/messages 27 | /api/web/messagesBy=/api/web/messagesBy 28 | /api/web/messagesp2p/abbabab=/api/web/messagesp2p/(?.*?),sender=abbabab 29 | /api/web/userhead/i/abbabab=/api/web/userhead/i/(?.*?),personId=abbabab 30 | /api/web/userhead/t/abbabab=/api/web/userhead/t/(?.*?),personId=abbabab 31 | /api/web/topichead/abbabab/abc=/api/web/topichead/(?.*?)/(?.*?),roomType=abbabab,roomJid=abc 32 | /mail/attachment/kkkkpptt=/mail/attachment/(?.*?),key=kkkkpptt 33 | /tapi/topic/create=/tapi/topic/create 34 | /tapi/topic/update=/tapi/topic/update 35 | /tapi/topic/history=/tapi/topic/history 36 | /tapi/topic/group/create=/tapi/topic/group/create 37 | /tapi/topic/group/update=/tapi/topic/group/update 38 | /account=/account 39 | /api/easterEgg=/api/easterEgg 40 | /api/web/getJFToken=/api/web/getJFToken 41 | /api/web/ssoLogout=/api/web/ssoLogout 42 | /api/web/validateJFToken=/api/web/validateJFToken 43 | /api/web/getRefreshToken=/api/web/getRefreshToken 44 | /api/web/log=/api/web/log 45 | /img/upload=/img/upload 46 | /img64/upload=/img64/upload 47 | /img/download=/img/download 48 | /img/grapeupload=/img/grapeupload 49 | /img/i/1.png/get=/img/i/(?.*?)/get,filename=1.png 50 | /img/i/1.png/upload=/img/i/(?.*?)/upload,filename=1.png 51 | /img/t/1.png/get=/img/t/(?.*?)/get,filename=1.png 52 | /img/t/1.png/upload=/img/t/(?.*?)/upload,filename=1.png 53 | /app/upload=/app/upload 54 | /app/beta/upload=/app/beta/upload 55 | /=/ 56 | /app=/app 57 | /app/beta=/app/beta 58 | /app/fix=/app/fix 59 | /ios/sku.plist=/ios/(?.*?),filename=sku.plist 60 | /android=/android 61 | /iosBeta/skub.plist=/iosBeta/(?.*?),filename=skub.plist 62 | /androidBeta=/androidBeta 63 | /api/fileUpload=/api/fileUpload 64 | /api/fileDownload=/api/fileDownload 65 | /iosDownload=/iosDownload 66 | /androidDownload=/androidDownload 67 | /admin/init/group=/admin/init/group 68 | /admin/init/groupTopic=/admin/init/groupTopic 69 | /api/fav/mock/store=/api/fav/mock/store 70 | /api/fav/list/1234/aaa=/api/fav/list/(?.*?)/(?.*?),timestamp=1234,jid=aaa 71 | /api/fav/get/15/67=/api/fav/get/(?.*?)/(?.*?),id=15,jid=67 72 | /api/fav/remove=/api/fav/remove 73 | /api/fav/quota/abcd=/api/fav/quota/(?.*?),jid=abcd 74 | /api/fav/store=/api/fav/store 75 | /api/fav/template=/api/fav/template 76 | /api/fav/template/list=/api/fav/template/list 77 | /api/fav/template/show=/api/fav/template/show 78 | /api/fav/template/save=/api/fav/template/save 79 | /api/fav/template/edit/123=/api/fav/template/edit/(?.*?),id=123 80 | /api/fav/template/update=/api/fav/template/update 81 | /api/fav/template/delete/566788=/api/fav/template/delete/(?.*?),ids=566788 82 | /api/fav/template/reload=/api/fav/template/reload 83 | /bbs/rooms=/bbs/rooms 84 | /bbs/forward=/bbs/forward 85 | /bbs/roomhead=/bbs/roomhead 86 | /kf/choose=/kf/choose 87 | /kf/close=/kf/close 88 | /api/kf/choose=/api/kf/choose 89 | /api/config/user/set=/api/config/user/set 90 | /api/config/user/list=/api/config/user/list 91 | /api/config/global/list=/api/config/global/list 92 | /config/global=/config/global 93 | /config/global/update=/config/global/update 94 | /config/cmd/send=/config/cmd/send 95 | /tapi/topic/history/count=/tapi/topic/history/count 96 | /tapi/topic/chatinfo=/tapi/topic/chatinfo -------------------------------------------------------------------------------- /mvc-inject-guice/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /mvc-inject-guice/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | works.cirno.mocha 6 | mvc 7 | 0.1-SNAPSHOT 8 | 9 | mvc-inject-guice 10 | Mocha MVC injector-bridge for guice 11 | 12 | 13 | 14 | works.cirno.mocha 15 | mvc-core 16 | ${project.version} 17 | 18 | 19 | 20 | javax.servlet 21 | javax.servlet-api 22 | 3.0.1 23 | provided 24 | 25 | 26 | 27 | javax.inject 28 | javax.inject 29 | 1 30 | 31 | 32 | com.google.inject 33 | guice 34 | 3.0 35 | 36 | 37 | com.google.inject.extensions 38 | guice-servlet 39 | 3.0 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /mvc-inject-guice/src/main/java/works/cirno/mocha/GuiceMVCFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import javax.inject.Inject; 27 | import javax.inject.Singleton; 28 | 29 | import com.google.inject.Injector; 30 | import com.google.inject.Key; 31 | import com.google.inject.name.Names; 32 | 33 | @Singleton 34 | public class GuiceMVCFactory implements ObjectFactory { 35 | 36 | @Inject 37 | private Injector injector; 38 | 39 | void setInjector(Injector injector) { 40 | this.injector = injector; 41 | } 42 | 43 | @Override 44 | public T getInstance(TypeOrInstance param) { 45 | switch (param.getInjectBy()) { 46 | case INSTANCE: 47 | return param.getInstance(); 48 | case NAME_TYPE: 49 | return injector.getInstance(Key.get(param.getType(), Names.named(param.getName()))); 50 | case TYPE: 51 | return injector.getInstance(param.getType()); 52 | } 53 | throw new UnsupportedOperationException("Unknown injection type " + param.getInjectBy()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /mvc-inject-guice/src/main/java/works/cirno/mocha/GuicedDispatcherFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import javax.inject.Inject; 27 | 28 | import com.google.inject.Injector; 29 | 30 | import works.cirno.mocha.DispatcherFilter; 31 | import works.cirno.mocha.ObjectFactory; 32 | 33 | public class GuicedDispatcherFilter extends DispatcherFilter { 34 | 35 | @Inject 36 | private Injector injector; 37 | 38 | @Override 39 | protected ObjectFactory getMVCFactory() { 40 | if (injector == null) { 41 | // not configured in guice servlet, will try fetch injector from 42 | // servlet context 43 | final String INJECTOR_NAME = Injector.class.getName(); 44 | injector = (Injector) servletContext.getAttribute(INJECTOR_NAME); 45 | } 46 | 47 | if (injector == null) { 48 | throw new IllegalStateException("Can't find guice injector."); 49 | } 50 | GuiceMVCFactory factory = new GuiceMVCFactory(); 51 | factory.setInjector(injector); 52 | return factory; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /mvc-inject-guice/src/main/java/works/cirno/mocha/GuicedDispatcherServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import javax.inject.Inject; 27 | 28 | import com.google.inject.Injector; 29 | 30 | import works.cirno.mocha.DispatcherServlet; 31 | import works.cirno.mocha.ObjectFactory; 32 | 33 | public class GuicedDispatcherServlet extends DispatcherServlet { 34 | 35 | @Inject 36 | private Injector injector; 37 | 38 | @Override 39 | protected ObjectFactory getMVCFactory() { 40 | if (injector == null) { 41 | // not configured in guice servlet, will try fetch injector from 42 | // servlet context 43 | final String INJECTOR_NAME = Injector.class.getName(); 44 | injector = (Injector) servletContext.getAttribute(INJECTOR_NAME); 45 | } 46 | 47 | if (injector == null) { 48 | throw new IllegalStateException("Can't find guice injector."); 49 | } 50 | GuiceMVCFactory factory = new GuiceMVCFactory(); 51 | factory.setInjector(injector); 52 | return factory; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /mvc-inject-spring/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /mvc-inject-spring/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | works.cirno.mocha 6 | mvc 7 | 0.1-SNAPSHOT 8 | 9 | mvc-inject-spring 10 | Mocha MVC injector-bridge for spring 11 | 12 | 13 | 14 | works.cirno.mocha 15 | mvc-core 16 | ${project.version} 17 | 18 | 19 | 20 | javax.servlet 21 | javax.servlet-api 22 | 3.0.1 23 | provided 24 | 25 | 26 | 27 | javax.inject 28 | javax.inject 29 | 1 30 | 31 | 32 | org.springframework 33 | spring-context-support 34 | 3.0.0.RELEASE 35 | 36 | 37 | org.springframework 38 | spring-web 39 | 3.0.0.RELEASE 40 | true 41 | 42 | 43 | -------------------------------------------------------------------------------- /mvc-inject-spring/src/main/java/works/cirno/mocha/SpringDispatcherFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import org.springframework.context.ApplicationContext; 27 | import org.springframework.web.context.support.WebApplicationContextUtils; 28 | 29 | import works.cirno.mocha.DispatcherFilter; 30 | import works.cirno.mocha.ObjectFactory; 31 | 32 | public class SpringDispatcherFilter extends DispatcherFilter { 33 | 34 | @Override 35 | protected ObjectFactory getMVCFactory() { 36 | ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); 37 | return SpringMVCFactory.fromCustomApplicationContext(ctx); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /mvc-inject-spring/src/main/java/works/cirno/mocha/SpringMVCFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Cloudee Huang ( https://github.com/cloudeecn / cloudeecn@gmail.com ) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package works.cirno.mocha; 25 | 26 | import java.util.concurrent.ConcurrentHashMap; 27 | 28 | import javax.inject.Named; 29 | import javax.inject.Singleton; 30 | 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | import org.springframework.beans.BeansException; 34 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 35 | import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor; 36 | import org.springframework.context.ApplicationContext; 37 | import org.springframework.context.ApplicationContextAware; 38 | import org.springframework.web.context.support.SpringBeanAutowiringSupport; 39 | 40 | @Named 41 | @Singleton 42 | public class SpringMVCFactory implements ObjectFactory, ApplicationContextAware { 43 | private static final Logger log = LoggerFactory.getLogger(SpringMVCFactory.class); 44 | private ApplicationContext applicationContext; 45 | 46 | private ConcurrentHashMap, Object> unmanagedBeans = new ConcurrentHashMap<>(4); 47 | 48 | AutowiredAnnotationBeanPostProcessor processer; 49 | 50 | @Override 51 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 52 | this.applicationContext = applicationContext; 53 | processer = new AutowiredAnnotationBeanPostProcessor(); 54 | processer.setBeanFactory(applicationContext.getAutowireCapableBeanFactory()); 55 | } 56 | 57 | public static ObjectFactory fromCustomApplicationContext(ApplicationContext ac) { 58 | ObjectFactory factory; 59 | try { 60 | factory = ac.getBean(SpringMVCFactory.class); 61 | log.info("SpringObjectFactory got from application context"); 62 | } catch (NoSuchBeanDefinitionException e) { 63 | factory = ac.getAutowireCapableBeanFactory().createBean(SpringMVCFactory.class); 64 | log.info("SpringObjectFactory created"); 65 | } 66 | return factory; 67 | } 68 | 69 | @Override 70 | public T getInstance(TypeOrInstance param) { 71 | switch (param.getInjectBy()) { 72 | case INSTANCE: 73 | return param.getInstance(); 74 | case NAME_TYPE: 75 | return applicationContext.getBean(param.getName(), param.getType()); 76 | case TYPE: 77 | try { 78 | return applicationContext.getBean(param.getType()); 79 | } catch (NoSuchBeanDefinitionException e) { 80 | Class type = param.getType(); 81 | 82 | @SuppressWarnings("unchecked") 83 | T result = (T) unmanagedBeans.get(type); 84 | if (result == null) { 85 | log.warn("Can't find bean for type {} will manage bean as singleton", type); 86 | try { 87 | result = type.newInstance(); 88 | } catch (InstantiationException | IllegalAccessException e1) { 89 | log.error("Can't instantiate {}.", type.getName(), e1); 90 | throw new NoSuchBeanDefinitionException(type); 91 | } 92 | processer.processInjection(result); 93 | unmanagedBeans.put(type, result); 94 | } 95 | return result; 96 | } 97 | } 98 | throw new UnsupportedOperationException("Unknown injection type " + param.getInjectBy()); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | works.cirno.mocha 5 | mvc 6 | pom 7 | 0.1-SNAPSHOT 8 | Mocha MVC 9 | https://github.com/cloudee/mocha-mvc/ 10 | 11 | scm:git:git@github.com:cloudeecn/mocha-mvc.git 12 | https://github.com/cloudeecn/mocha-mvc/ 13 | HEAD 14 | 15 | 16 | UTF-8 17 | 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 3.3 25 | 26 | 1.7 27 | 1.7 28 | 29 | 30 | 31 | 32 | 33 | 34 | mvc-core 35 | mvc-inject-spring 36 | mvc-inject-guice 37 | example 38 | 39 | 40 | 41 | junit 42 | junit 43 | 4.12 44 | test 45 | 46 | 47 | org.slf4j 48 | slf4j-log4j12 49 | 1.7.12 50 | test 51 | 52 | 53 | 54 | --------------------------------------------------------------------------------