Skip to content

Commit ee46a01

Browse files
author
jossonsmith
committed
Refactor SimpleRPCHttpServlet so it can be overrided.
Respect charset in HttpRequest.
1 parent a3f0a37 commit ee46a01

File tree

2 files changed

+97
-41
lines changed

2 files changed

+97
-41
lines changed

sources/net.sf.j2s.ajax/ajaxcore/net/sf/j2s/ajax/HttpRequest.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.IOException;
2020
import java.io.InputStream;
2121
import java.io.OutputStream;
22+
import java.io.UnsupportedEncodingException;
2223
import java.net.HttpURLConnection;
2324
import java.net.URL;
2425
import java.util.HashMap;
@@ -424,7 +425,22 @@ private void request() {
424425
if (checkAbort()) return; // stop receiving anything
425426
is.close();
426427
activeIS = null;
427-
responseText = baos.toString();
428+
responseText = null;
429+
String charset = null;
430+
String type = connection.getHeaderField("Content-Type");
431+
if (type != null) {
432+
int idx = type.toLowerCase().indexOf("charset=");
433+
if (idx != -1) {
434+
charset = type.substring(idx + 8);
435+
try {
436+
responseText = baos.toString(charset);
437+
} catch (UnsupportedEncodingException e) {
438+
}
439+
}
440+
}
441+
if (responseText == null) {
442+
responseText = baos.toString();
443+
}
428444
readyState = 4;
429445
if (onreadystatechange != null) {
430446
onreadystatechange.onLoaded();

sources/net.sf.j2s.ajax/ajaxrpc/net/sf/j2s/ajax/SimpleRPCHttpServlet.java

Lines changed: 80 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,51 @@
3535
*/
3636
public class SimpleRPCHttpServlet extends HttpServlet {
3737

38-
private static final long serialVersionUID = -3852449040495978018L;
38+
private static final long serialVersionUID = -3852449040495666018L;
3939

4040
protected Set runnables = new HashSet();
4141

42-
protected SimpleRPCRunnable getRunnableByURL(String request) {
42+
/**
43+
* Get SimpleRPCRunnable instance correspond to the given request.
44+
*
45+
* @param request String that is from POST data or GET query
46+
* @return SimpleRPCRunnable instance. If request is bad request,
47+
* null will be returned.
48+
*
49+
* TODO: request (May be large string) may be duplicated when being
50+
* passed in as parameter
51+
*/
52+
protected SimpleRPCRunnable getRunnableByRequest(String request) {
4353
if (request == null) return null;
4454
int length = request.length();
4555
if (length <= 7 || !request.startsWith("WLL")) return null;
4656
int index = request.indexOf('#');
4757
if (index == -1) return null;
4858
String clazzName = request.substring(6, index);
59+
4960
if (runnables.contains(clazzName)) {
50-
if (request != null) {
51-
Object obj = getNewInstanceByClassName(clazzName);
52-
if (obj != null && obj instanceof SimpleRPCRunnable) {
53-
return (SimpleRPCRunnable) obj;
54-
}
55-
}
61+
return createRunnableInstance(clazzName);
5662
}
5763
return null;
5864
}
5965

60-
public Object getNewInstanceByClassName(String className) {
66+
/**
67+
* Create SimpleRPCRunnable instance by given class name. May be inherited to
68+
* do more jobs before starting to deserialize request and running the main job.
69+
*
70+
* @param clazzName full class name of inherited SimpleRPCRunnable class
71+
* @return instance of given class name, null may be returned.
72+
*/
73+
protected SimpleRPCRunnable createRunnableInstance(String clazzName) {
6174
try {
62-
Class runnableClass = Class.forName(className);
75+
Class runnableClass = Class.forName(clazzName);
6376
if (runnableClass != null) {
77+
// SimpleRPCRunnale should always has default constructor
6478
Constructor constructor = runnableClass.getConstructor(new Class[0]);
65-
return constructor.newInstance(new Object[0]);
79+
Object obj = constructor.newInstance(new Object[0]);
80+
if (obj != null && obj instanceof SimpleRPCRunnable) {
81+
return (SimpleRPCRunnable) obj;
82+
}
6683
}
6784
} catch (SecurityException e) {
6885
e.printStackTrace();
@@ -81,7 +98,45 @@ public Object getNewInstanceByClassName(String className) {
8198
}
8299
return null;
83100
}
84-
private String readAll(InputStream res) {
101+
102+
/*
103+
* Example of web.xml:
104+
<servlet>
105+
<servlet-name>simplerpc</servlet-name>
106+
<servlet-class>net.sf.j2s.ajax.SimpleRPCHttpServlet</servlet-class>
107+
<init-param>
108+
<param-name>simple.rpc.runnables</param-name>
109+
<param-value>
110+
org.java2script.notepad.AutoSaveRunnable;
111+
org.java2script.notepad.LoadDraftRunnable;
112+
org.java2script.notepad.LoadNoteRunnable;
113+
org.java2script.notepad.SaveNoteRunnable;
114+
</param-value>
115+
</init-param>
116+
</servlet>
117+
<servlet-mapping>
118+
<servlet-name>simplerpc</servlet-name>
119+
<url-pattern>/simplerpc</url-pattern>
120+
</servlet-mapping>
121+
*/
122+
public void init() throws ServletException {
123+
String runnableStr = getInitParameter("simple.rpc.runnables");
124+
if (runnableStr != null) {
125+
String[] splits = runnableStr.trim().split("\\s*[,;:]\\s*");
126+
for (int i = 0; i < splits.length; i++) {
127+
String trim = splits[i].trim();
128+
if (trim.length() != 0) {
129+
runnables.add(trim);
130+
}
131+
}
132+
}
133+
super.init();
134+
}
135+
136+
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
137+
throws ServletException, IOException {
138+
String request = null;
139+
InputStream res = req.getInputStream();
85140
try {
86141
ByteArrayOutputStream baos = new ByteArrayOutputStream();
87142
byte[] buf = new byte[1024];
@@ -90,40 +145,24 @@ private String readAll(InputStream res) {
90145
baos.write(buf, 0, read);
91146
if (baos.size() > 0x1000000) { // 16 * 1024 * 1024 // 16M!
92147
/*
93-
* Some malicious request may try to allocate huge size of memory!
94-
* Limit the data size of HTTP request!
148+
* Some malicious request may try to allocate huge size of memory!
149+
* DoS attack? Limit the data size of HTTP request!
95150
*/
96151
res.close();
97-
throw new RuntimeException("Data size reaches the limit of Java2Script Simple RPC!");
152+
resp.sendError(HttpServletResponse.SC_FORBIDDEN,
153+
"Data size reaches the limit of Java2Script Simple RPC!");
154+
return;
98155
}
99156
}
100157
res.close();
101-
return baos.toString();
158+
request = baos.toString();
102159
} catch (IOException e) {
103160
e.printStackTrace();
161+
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
162+
return;
104163
}
105-
return null;
106-
}
107-
108-
/* (non-Javadoc)
109-
* @see javax.servlet.GenericServlet#init()
110-
*/
111-
public void init() throws ServletException {
112-
String runnableStr = getInitParameter("simple.rpc.runnables");
113-
if (runnableStr != null) {
114-
String[] splits = runnableStr.trim().split("\\s*[,;:]\\s*");
115-
for (int i = 0; i < splits.length; i++) {
116-
String trim = splits[i].trim();
117-
if (trim.length() != 0) {
118-
runnables.add(trim);
119-
}
120-
}
121-
}
122-
}
123-
124-
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
125-
String request = readAll(req.getInputStream());
126-
SimpleRPCRunnable runnable = getRunnableByURL(request);
164+
165+
SimpleRPCRunnable runnable = getRunnableByRequest(request);
127166
if (runnable == null) {
128167
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
129168
return;
@@ -136,9 +175,10 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S
136175
writer.write(runnable.serialize());
137176
}
138177

139-
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
178+
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
179+
throws ServletException, IOException {
140180
String request = req.getQueryString();
141-
SimpleRPCRunnable runnable = getRunnableByURL(request);
181+
SimpleRPCRunnable runnable = getRunnableByRequest(request);
142182
if (runnable == null) {
143183
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
144184
return;

0 commit comments

Comments
 (0)