3535 */
3636public 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