1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.springframework.extensions.webscripts;
20
21 import java.io.BufferedReader;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.PrintStream;
27 import java.io.PrintWriter;
28 import java.io.StringWriter;
29 import java.io.UnsupportedEncodingException;
30 import java.net.MalformedURLException;
31 import java.net.URL;
32 import java.util.HashMap;
33 import java.util.Map;
34
35 import org.junit.Ignore;
36 import org.springframework.beans.BeansException;
37 import org.springframework.beans.factory.InitializingBean;
38 import org.springframework.context.ApplicationContext;
39 import org.springframework.context.ApplicationContextAware;
40 import org.springframework.context.MessageSource;
41 import org.springframework.context.support.ClassPathXmlApplicationContext;
42 import org.springframework.core.io.ClassPathResource;
43 import org.springframework.extensions.config.Config;
44 import org.springframework.extensions.config.ConfigService;
45 import org.springframework.extensions.config.ServerConfigElement;
46 import org.springframework.extensions.config.ServerProperties;
47 import org.springframework.extensions.surf.util.URLDecoder;
48 import org.springframework.extensions.webscripts.servlet.ServletAuthenticatorFactory;
49 import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
50 import org.springframework.mock.web.MockHttpServletRequest;
51 import org.springframework.mock.web.MockHttpServletResponse;
52
53
54
55
56
57
58 @Ignore public class TestWebScriptServer implements ApplicationContextAware, InitializingBean
59 {
60
61 protected ApplicationContext applicationContext;
62
63
64 protected ConfigService configService;
65 protected RuntimeContainer container;
66 protected ServletAuthenticatorFactory authenticatorFactory;
67
68
69 protected ServerProperties serverProperties;
70
71
72 protected BufferedReader fIn;
73
74
75 protected String lastCommand = null;
76
77
78 protected String username = null;
79
80
81 protected Map<String, String> headers = new HashMap<String, String>();
82
83
84 protected MessageSource m_messages;
85
86
87
88
89
90 public void setConfigService(ConfigService configService)
91 {
92 this.configService = configService;
93 }
94
95
96
97
98
99
100 public void setContainer(RuntimeContainer container)
101 {
102 this.container = container;
103 }
104
105
106
107
108 public void setServletAuthenticatorFactory(ServletAuthenticatorFactory authenticatorFactory)
109 {
110 this.authenticatorFactory = authenticatorFactory;
111 }
112
113
114
115
116
117
118
119 public void setMessages(MessageSource messages)
120 throws IOException
121 {
122 this.m_messages = messages;
123 }
124
125
126
127
128
129
130
131 public void setApplicationContext(ApplicationContext applicationContext)
132 throws BeansException
133 {
134 this.applicationContext = applicationContext;
135 }
136
137
138
139
140
141 public void afterPropertiesSet() throws Exception
142 {
143 username = getDefaultUserName();
144 }
145
146
147
148
149 protected String getDefaultUserName()
150 {
151 return "admin";
152 }
153
154
155
156
157
158
159
160 public ServerProperties getServerProperties()
161 {
162 if (serverProperties == null)
163 {
164 Config config = configService.getConfig("Server");
165 serverProperties = (ServerConfigElement)config.getConfigElement(ServerConfigElement.CONFIG_ELEMENT_ID);
166 }
167 return serverProperties;
168 }
169
170
171
172
173
174
175 public ApplicationContext getApplicationContext()
176 {
177 return this.applicationContext;
178 }
179
180
181
182
183
184 public static void main(String[] args)
185 {
186 try
187 {
188 TestWebScriptServer testServer = getTestServer();
189 testServer.rep();
190 }
191 catch(Throwable e)
192 {
193 StringWriter strWriter = new StringWriter();
194 PrintWriter printWriter = new PrintWriter(strWriter);
195 e.printStackTrace(printWriter);
196 System.out.println(strWriter.toString());
197 }
198 finally
199 {
200 System.exit(0);
201 }
202 }
203
204
205
206
207
208
209
210 public static TestWebScriptServer getTestServer()
211 {
212 String[] CONFIG_LOCATIONS = new String[]
213 {
214 "classpath:org/springframework/extensions/webscripts/spring-webscripts-application-context.xml",
215 "classpath:org/springframework/extensions/webscripts/spring-webscripts-application-context-test.xml"
216 };
217 ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
218 TestWebScriptServer testServer = (TestWebScriptServer)context.getBean("webscripts.test");
219
220 return testServer;
221 }
222
223
224
225
226
227
228
229
230 public Response submitRequest(Request req)
231 throws IOException
232 {
233 return submitRequest(req.getMethod(), req.getUri(), req.getHeaders(), req.getBody(), req.getEncoding(), req.getType());
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 public Response submitRequest(String method, String uri, Map<String, String> headers, byte[] body, String encoding, String contentType)
250 throws IOException
251 {
252 MockHttpServletRequest req = createMockServletRequest(method, uri);
253
254
255 if (headers != null)
256 {
257 for (Map.Entry<String, String> header: headers.entrySet())
258 {
259 req.addHeader(header.getKey(), header.getValue());
260 }
261 }
262
263
264 if (body != null)
265 {
266 req.setContent(body);
267 }
268
269 if (encoding != null)
270 {
271 req.setCharacterEncoding(encoding);
272 }
273
274
275 if (contentType != null && contentType.length() != 0)
276 {
277 req.setContentType(contentType);
278 req.addHeader("Content-Type", contentType);
279 }
280
281 MockHttpServletResponse res = new MockHttpServletResponse();
282 AbstractRuntime runtime = new WebScriptServletRuntime(container, authenticatorFactory, req, res, getServerProperties());
283 runtime.executeScript();
284 return new MockHttpServletResponseResponse(res);
285 }
286
287
288
289
290
291
292
293
294
295
296 private MockHttpServletRequest createMockServletRequest(String method, String uri)
297 throws UnsupportedEncodingException, MalformedURLException
298 {
299
300 URL url = new URL(new URL("http://localhost"), uri);
301 String path = url.getPath();
302
303 if (!(path.startsWith("/alfresco/service") || path.startsWith("/a/s")))
304 {
305 path = "/alfresco/service" + path;
306 }
307
308 MockHttpServletRequest req = new MockHttpServletRequest(method, uri);
309 req.setContextPath("/alfresco");
310 req.setServletPath("/service");
311
312 if (uri != null)
313 {
314 String queryString = url.getQuery();
315 if (queryString != null && queryString.length() > 0)
316 {
317 String[] args = queryString.split("&");
318 for (String arg : args)
319 {
320 String[] parts = arg.split("=");
321 req.addParameter(parts[0], (parts.length == 2) ? URLDecoder.decode(parts[1]) : null);
322 }
323 req.setQueryString(URLDecoder.decode(queryString));
324 }
325 String requestURI = path;
326 req.setRequestURI(URLDecoder.decode(requestURI));
327 }
328
329 return req;
330 }
331
332
333
334
335 public void rep()
336 {
337
338 fIn = new BufferedReader(new InputStreamReader(System.in));
339 while (true)
340 {
341 System.out.print("ok> ");
342 try
343 {
344
345 final String line = fIn.readLine();
346 if (line == null || line.equals("exit") || line.equals("quit"))
347 {
348 return;
349 }
350
351
352 long startTime = System.nanoTime();
353 System.out.print(interpretCommand(line));
354 System.out.println("" + (System.nanoTime() - startTime)/1000000f + "ms");
355 }
356 catch (Exception e)
357 {
358 e.printStackTrace(System.err);
359 System.out.println("");
360 }
361 }
362 }
363
364
365
366
367
368
369
370 protected String interpretCommand(final String line)
371 throws IOException
372 {
373 return executeCommand(line);
374 }
375
376
377
378
379
380
381
382
383
384 protected String executeCommand(String line)
385 throws IOException
386 {
387 String[] command = line.split(" ");
388 if (command.length == 0)
389 {
390 command = new String[1];
391 command[0] = line;
392 }
393
394 ByteArrayOutputStream bout = new ByteArrayOutputStream();
395 PrintStream out = new PrintStream(bout);
396
397
398 if (command[0].equals("r"))
399 {
400 if (lastCommand == null)
401 {
402 return "No command entered yet.";
403 }
404
405 if (command.length > 1 && command[1].equals("show"))
406 {
407 return lastCommand + "\n\n";
408 }
409 else
410 {
411 return "repeating command " + lastCommand + "\n\n" + interpretCommand(lastCommand);
412 }
413 }
414
415
416 lastCommand = line;
417
418
419 if (command[0].equals("help"))
420 {
421 String helpFile = m_messages.getMessage("testserver.help", null, null);
422 ClassPathResource helpResource = new ClassPathResource(helpFile);
423 byte[] helpBytes = new byte[500];
424 InputStream helpStream = helpResource.getInputStream();
425 try
426 {
427 int read = helpStream.read(helpBytes);
428 while (read != -1)
429 {
430 bout.write(helpBytes, 0, read);
431 read = helpStream.read(helpBytes);
432 }
433 }
434 finally
435 {
436 helpStream.close();
437 }
438 }
439
440 else if (command[0].equals("user"))
441 {
442 if (command.length == 2)
443 {
444 username = command[1];
445 }
446 out.println("using user " + username);
447 }
448
449 else if (command[0].equals("get") ||
450 command[0].equals("delete"))
451 {
452 String uri = (command.length > 1) ? command[1] : null;
453 Response res = submitRequest(command[0], uri, headers, null, null, null);
454 bout.write(("Response status: " + res.getStatus()).getBytes());
455 out.println();
456 bout.write(res.getContentAsByteArray());
457 out.println();
458 }
459
460 else if (command[0].equals("post"))
461 {
462 String uri = (command.length > 1) ? command[1] : null;
463 String contentType = (command.length > 2) ? command[2] : null;
464 String body = "";
465 for (int i = 3; i < command.length; i++)
466 {
467 body += command[i] + " ";
468 }
469 Response res = submitRequest(command[0], uri, headers, body.getBytes(), null, contentType);
470 bout.write(("Response status: " + res.getStatus()).getBytes());
471 out.println();
472 bout.write(res.getContentAsByteArray());
473 out.println();
474 }
475
476 else if (command[0].equals("put"))
477 {
478 String uri = (command.length > 1) ? command[1] : null;
479 String contentType = (command.length > 2) ? command[2] : null;
480 String body = "";
481 for (int i = 3; i < command.length; i++)
482 {
483 body += command[i] + " ";
484 }
485 Response res = submitRequest(command[0], uri, headers, body.getBytes(), null, contentType);
486 bout.write(("Response status: " + res.getStatus()).getBytes());
487 out.println();
488 bout.write(res.getContentAsByteArray());
489 out.println();
490 }
491
492 else if (command[0].equals("tunnel"))
493 {
494 if (command.length < 4)
495 {
496 return "Syntax Error.\n";
497 }
498
499 if (command[1].equals("param"))
500 {
501 String uri = command[3];
502 if (uri.indexOf('?') == -1)
503 {
504 uri += "?alf:method=" + command[2];
505 }
506 else
507 {
508 uri += "&alf:method=" + command[2];
509 }
510 Response res = submitRequest("post", uri, headers, null, null, null);
511 bout.write(res.getContentAsByteArray());
512 out.println();
513 }
514
515 else if (command[1].equals("header"))
516 {
517 Map<String, String> tunnelheaders = new HashMap<String, String>();
518 tunnelheaders.putAll(headers);
519 tunnelheaders.put("X-HTTP-Method-Override", command[2]);
520 Response res = submitRequest("post", command[3], tunnelheaders, null, null, null);
521 bout.write(res.getContentAsByteArray());
522 out.println();
523 }
524
525 else
526 {
527 return "Syntax Error.\n";
528 }
529 }
530
531 else if (command[0].equals("header"))
532 {
533 if (command.length == 1)
534 {
535 for (Map.Entry<String, String> entry : headers.entrySet())
536 {
537 out.println(entry.getKey() + " = " + entry.getValue());
538 }
539 }
540 else if (command.length == 2)
541 {
542 String[] param = command[1].split("=");
543 if (param.length == 0)
544 {
545 return "Syntax Error.\n";
546 }
547 if (param.length == 1)
548 {
549 headers.remove(param[0]);
550 out.println("deleted header " + param[0]);
551 }
552 else if (param.length == 2)
553 {
554 headers.put(param[0], param[1]);
555 out.println("set header " + param[0] + " = " + headers.get(param[0]));
556 }
557 else
558 {
559 return "Syntax Error.\n";
560 }
561 }
562 else
563 {
564 return "Syntax Error.\n";
565 }
566 }
567
568 else if (command[0].equals("reset"))
569 {
570 container.reset();
571 out.println("Runtime context '" + container.getName() + "' reset.");
572 }
573
574 else
575 {
576 return "Syntax Error.\n";
577 }
578
579 out.flush();
580 String retVal = new String(bout.toByteArray());
581 out.close();
582 return retVal;
583 }
584
585
586
587
588
589 public static class Request
590 {
591 private String method;
592 private String uri;
593 private Map<String, String> args;
594 private Map<String, String> headers;
595 private byte[] body;
596 private String encoding = "UTF-8";
597 private String contentType;
598
599 public Request(Request req)
600 {
601 this.method = req.method;
602 this.uri= req.uri;
603 this.args = req.args;
604 this.headers = req.headers;
605 this.body = req.body;
606 this.encoding = req.encoding;
607 this.contentType = req.contentType;
608 }
609
610 public Request(String method, String uri)
611 {
612 this.method = method;
613 this.uri = uri;
614 }
615
616 public String getMethod()
617 {
618 return method;
619 }
620
621 public String getUri()
622 {
623 return uri;
624 }
625
626 public String getFullUri()
627 {
628
629 String fullUri = uri == null ? "" : uri;
630 if (args != null && args.size() > 0)
631 {
632 char prefix = (uri.indexOf('?') == -1) ? '?' : '&';
633 for (Map.Entry<String, String> arg : args.entrySet())
634 {
635 fullUri += prefix + arg.getKey() + "=" + (arg.getValue() == null ? "" : arg.getValue());
636 prefix = '&';
637 }
638 }
639
640 return fullUri;
641 }
642
643 public Request setArgs(Map<String, String> args)
644 {
645 this.args = args;
646 return this;
647 }
648
649 public Map<String, String> getArgs()
650 {
651 return args;
652 }
653
654 public Request setHeaders(Map<String, String> headers)
655 {
656 this.headers = headers;
657 return this;
658 }
659
660 public Map<String, String> getHeaders()
661 {
662 return headers;
663 }
664
665 public Request setBody(byte[] body)
666 {
667 this.body = body;
668 return this;
669 }
670
671 public byte[] getBody()
672 {
673 return body;
674 }
675
676 public Request setEncoding(String encoding)
677 {
678 this.encoding = encoding;
679 return this;
680 }
681
682 public String getEncoding()
683 {
684 return encoding;
685 }
686
687 public Request setType(String contentType)
688 {
689 this.contentType = contentType;
690 return this;
691 }
692
693 public String getType()
694 {
695 return contentType;
696 }
697 }
698
699
700
701
702 public static class GetRequest extends Request
703 {
704 public GetRequest(String uri)
705 {
706 super("get", uri);
707 }
708 }
709
710
711
712
713 public static class PostRequest extends Request
714 {
715 public PostRequest(String uri, String post, String contentType)
716 throws UnsupportedEncodingException
717 {
718 super("post", uri);
719 setBody(getEncoding() == null ? post.getBytes() : post.getBytes(getEncoding()));
720 setType(contentType);
721 }
722
723 public PostRequest(String uri, byte[] post, String contentType)
724 {
725 super("post", uri);
726 setBody(post);
727 setType(contentType);
728 }
729 }
730
731
732
733
734 public static class PutRequest extends Request
735 {
736 public PutRequest(String uri, String put, String contentType)
737 throws UnsupportedEncodingException
738 {
739 super("put", uri);
740 setBody(getEncoding() == null ? put.getBytes() : put.getBytes(getEncoding()));
741 setType(contentType);
742 }
743
744 public PutRequest(String uri, byte[] put, String contentType)
745 {
746 super("put", uri);
747 setBody(put);
748 setType(contentType);
749 }
750 }
751
752
753
754
755 public static class DeleteRequest extends Request
756 {
757 public DeleteRequest(String uri)
758 {
759 super("delete", uri);
760 }
761 }
762
763
764
765
766 public static class PatchRequest extends Request
767 {
768 public PatchRequest(String uri, String put, String contentType)
769 throws UnsupportedEncodingException
770 {
771 super("patch", uri);
772 setBody(getEncoding() == null ? put.getBytes() : put.getBytes(getEncoding()));
773 setType(contentType);
774 }
775
776 public PatchRequest(String uri, byte[] put, String contentType)
777 {
778 super("patch", uri);
779 setBody(put);
780 setType(contentType);
781 }
782 }
783
784
785
786
787 public interface Response
788 {
789 public byte[] getContentAsByteArray();
790
791 public String getContentAsString()
792 throws UnsupportedEncodingException;
793
794 public String getHeader(String name);
795
796 public String getContentType();
797
798 public int getContentLength();
799
800 public int getStatus();
801 }
802
803
804
805
806 public static class MockHttpServletResponseResponse
807 implements Response
808 {
809 private MockHttpServletResponse res;
810
811 public MockHttpServletResponseResponse(MockHttpServletResponse res)
812 {
813 this.res = res;
814 }
815
816 public byte[] getContentAsByteArray()
817 {
818 return res.getContentAsByteArray();
819 }
820
821 public String getContentAsString()
822 throws UnsupportedEncodingException
823 {
824 return res.getContentAsString();
825 }
826
827 public String getHeader(String name)
828 {
829 return (String)res.getHeader(name);
830 }
831
832 public String getContentType()
833 {
834 return res.getContentType();
835 }
836
837 public int getContentLength()
838 {
839 return res.getContentLength();
840 }
841
842 public int getStatus()
843 {
844 return res.getStatus();
845 }
846 }
847
848 }