View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jexl3;
18  
19  import java.io.BufferedReader;
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.InputStreamReader;
24  import java.io.OutputStream;
25  import java.net.HttpURLConnection;
26  import java.net.InetSocketAddress;
27  import java.net.URL;
28  import java.util.concurrent.Executors;
29  import java.util.concurrent.ThreadPoolExecutor;
30  import java.util.function.Function;
31  
32  import org.junit.Assert;
33  import org.junit.Test;
34  
35  import com.sun.net.httpserver.HttpExchange;
36  import com.sun.net.httpserver.HttpHandler;
37  import com.sun.net.httpserver.HttpServer;
38  
39  /**
40   * Tests for JexlScript
41   * @since 1.1
42   */
43  @SuppressWarnings({"AssertEqualsBetweenInconvertibleTypes"})
44  public class ScriptTest extends JexlTestCase {
45      static final String TEST1 =  "src/test/scripts/test1.jexl";
46      static final String TEST_ADD =  "src/test/scripts/testAdd.jexl";
47      static final String TEST_JSON =  "src/test/scripts/httpPost.jexl";
48  
49      // test class for testScriptUpdatesContext
50      // making this class private static will cause the test to fail.
51      // this is due to unusual code in ClassMap.getAccessibleMethods(Class)
52      // that treats non-public classes in a specific way. Why getAccessibleMethods
53      // does this is not known yet.
54      public static class Tester {
55          private String code;
56          public String getCode () {
57              return code;
58          }
59          public void setCode(final String c) {
60              code = c;
61          }
62      }
63      /**
64       * Create a new test case.
65       */
66      public ScriptTest() {
67          super("ScriptTest");
68      }
69  
70      /**
71       * Test creating a script from spaces.
72       */
73      @Test
74      public void testSpacesScript() {
75          final String code = " ";
76          final JexlScript s = JEXL.createScript(code);
77          Assert.assertNotNull(s);
78      }
79  
80      /**
81       * Test creating a script from a string.
82       */
83      @Test
84      public void testSimpleScript() {
85          final String code = "while (x < 10) x = x + 1;";
86          final JexlScript s = JEXL.createScript(code);
87          final JexlContext jc = new MapContext();
88          jc.set("x",1);
89  
90          final Object o = s.execute(jc);
91          Assert.assertEquals("Result is wrong", 10, o);
92          Assert.assertEquals("getText is wrong", code, s.getSourceText());
93      }
94  
95  
96      @Test
97      public void testScriptJsonFromFileJexl() {
98          HttpServer server = null;
99          try {
100             final String response = "{  \"id\": 101}";
101             server = createJsonServer(h -> response);
102             final File httprFile = new File(TEST_JSON);
103             final JexlScript httprScript = JEXL.createScript(httprFile);
104             final JexlContext jc = new MapContext();
105             Object httpr = httprScript.execute(jc);
106             final JexlScript s = JEXL.createScript("(httpr,url)->httpr.execute(url, null)");
107             //jc.set("httpr", new HttpPostRequest());
108             String url = "http:/"+server.getAddress().toString()+"/test";
109             Object result = s.execute(jc, httpr,url);
110             Assert.assertNotNull(result);
111             Assert.assertEquals(response, result);
112         } catch(IOException xio) {
113             Assert.fail(xio.getMessage());
114         } finally {
115             if (server != null) {
116                 server.stop(0);
117             }
118         }
119     }
120 
121     @Test
122     public void testScriptJsonFromFileJava() {
123         HttpServer server = null;
124         try {
125             final String response = "{  \"id\": 101}";
126             server = createJsonServer(h -> response);
127             String url = "http:/"+server.getAddress().toString()+"/test";
128             final String testScript = "httpr.execute('"+url+"', null)";
129             final JexlScript s = JEXL.createScript(testScript);
130             final JexlContext jc = new MapContext();
131             jc.set("httpr", new HttpPostRequest());
132             Object result = s.execute(jc);
133             Assert.assertNotNull(result);
134             Assert.assertEquals(response, result);
135         } catch(IOException xio) {
136             Assert.fail(xio.getMessage());
137         } finally {
138             if (server != null) {
139                 server.stop(0);
140             }
141         }
142     }
143 
144     /**
145      * An object to call from.
146      */
147     public static class HttpPostRequest {
148         public static String execute(String url, String data) throws IOException {
149             return httpPostRequest(url, data);
150         }
151     }
152 
153     /**
154      *  HTTP post.
155      * @param sURL the url
156      * @param jsonData some json data
157      * @return the result
158      * @throws IOException
159      */
160     private static String httpPostRequest(String sURL, String jsonData) throws IOException {
161         URL url = new java.net.URL(sURL);
162         HttpURLConnection con = (HttpURLConnection) url.openConnection();
163         con.setRequestMethod("POST");
164         con.setRequestProperty("Accept", "application/json");
165         // send data
166         if ( jsonData != null ) {
167             con.setRequestProperty("Content-Type", "application/json");
168             con.setDoOutput(true);
169 
170             OutputStream outputStream = con.getOutputStream();
171             byte[] input = jsonData.getBytes("utf-8");
172             outputStream.write(input, 0, input.length);
173         }
174         // read response
175         int responseCode = con.getResponseCode();
176         InputStream inputStream = null;
177         inputStream =  con.getInputStream();
178         StringBuilder response = new StringBuilder();
179         if (inputStream != null) {
180             try (BufferedReader in = new BufferedReader(new InputStreamReader(inputStream))) {
181                 String inputLine = "";
182                 while ((inputLine = in.readLine()) != null) {
183                     response.append(inputLine);
184                 }
185             }
186         }
187         return response.toString();
188     }
189 
190     /**
191      * Creates a simple local http server.
192      * <p>Only handles POST request on /test</p>
193      * @return the server
194      * @throws IOException
195      */
196     static HttpServer createJsonServer(final Function<HttpExchange, String> responder) throws IOException {
197         HttpServer server  = null;
198         IOException xlatest = null;
199         for(int port = 8001; server == null && port < 8127; ++port) {
200             try {
201                 server = HttpServer.create(new InetSocketAddress("localhost", port), 0);
202             } catch(java.net.BindException xbind) {
203                 xlatest = xbind;
204             }
205         }
206         if (server == null) {
207             throw xlatest;
208         }
209         ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
210         server.createContext("/test", new HttpHandler() {
211             @Override
212             public void handle(HttpExchange httpExchange) throws IOException {
213                 if ("POST".equals(httpExchange.getRequestMethod())) {
214                     try (OutputStream outputStream = httpExchange.getResponseBody()) {
215                         String json = responder.apply(httpExchange);
216                         httpExchange.sendResponseHeaders(200, json.length());
217                         outputStream.write(json.toString().getBytes());
218                         outputStream.flush();
219                     }
220                 } else {
221                     // error
222                     httpExchange.sendResponseHeaders(500, 0);
223                 }
224             }
225         });
226         server.setExecutor(threadPoolExecutor);
227         server.start();
228         return server;
229     }
230 
231     @Test
232     public void testScriptFromFile() {
233         final File testScript = new File(TEST1);
234         final JexlScript s = JEXL.createScript(testScript);
235         final JexlContext jc = new MapContext();
236         jc.set("out", System.out);
237         final Object result = s.execute(jc);
238         Assert.assertNotNull("No result", result);
239         Assert.assertEquals("Wrong result", 7, result);
240     }
241 
242     @Test
243     public void testArgScriptFromFile() {
244         final File testScript = new File(TEST_ADD);
245         final JexlScript s = JEXL.createScript(testScript,"x", "y");
246         final JexlContext jc = new MapContext();
247         jc.set("out", System.out);
248         final Object result = s.execute(jc, 13, 29);
249         Assert.assertNotNull("No result", result);
250         Assert.assertEquals("Wrong result", 42, result);
251     }
252 
253     @Test
254     public void testScriptFromURL() throws Exception {
255         final URL testUrl = new File(TEST1).toURI().toURL();
256         final JexlScript s = JEXL.createScript(testUrl);
257         final JexlContext jc = new MapContext();
258         jc.set("out", System.out);
259         final Object result = s.execute(jc);
260         Assert.assertNotNull("No result", result);
261         Assert.assertEquals("Wrong result", 7, result);
262     }
263 
264     @Test
265     public void testArgScriptFromURL() throws Exception {
266         final URL testUrl = new File(TEST_ADD).toURI().toURL();
267         final JexlScript s = JEXL.createScript(testUrl,"x", "y");
268         final JexlContext jc = new MapContext();
269         jc.set("out", System.out);
270         final Object result = s.execute(jc, 13, 29);
271         Assert.assertNotNull("No result", result);
272         Assert.assertEquals("Wrong result", 42, result);
273     }
274 
275     @Test
276     public void testScriptUpdatesContext() {
277         final String jexlCode = "resultat.setCode('OK')";
278         final JexlExpression e = JEXL.createExpression(jexlCode);
279         final JexlScript s = JEXL.createScript(jexlCode);
280 
281         final Tester resultatJexl = new Tester();
282         final JexlContext jc = new MapContext();
283         jc.set("resultat", resultatJexl);
284 
285         resultatJexl.setCode("");
286         e.evaluate(jc);
287         Assert.assertEquals("OK", resultatJexl.getCode());
288         resultatJexl.setCode("");
289         s.execute(jc);
290         Assert.assertEquals("OK", resultatJexl.getCode());
291     }
292 
293 }