You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/04/09 08:15:32 UTC

[1/5] incubator-freemarker-online-tester git commit: renamed the package name to org/apache/freemarker/onlinetester

Repository: incubator-freemarker-online-tester
Updated Branches:
  refs/heads/master 7b46afe22 -> 808bd5365


http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceTest.java b/src/test/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceTest.java
new file mode 100644
index 0000000..fcaf358
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceTest.java
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.services;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import freemarker.core.Environment;
+import freemarker.core.HTMLOutputFormat;
+import freemarker.core.ParseException;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+
+@RunWith(MockitoJUnitRunner.class)
+public class FreeMarkerServiceTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FreeMarkerServiceTest.class); 
+    
+    private static final int MAX_THREADS = 3;
+    private static final int MAX_QUEUE_LENGTH = 2;
+    private static final int MAX_TEMPLATE_EXECUTION_TIME = 1500;
+
+    private static final int BLOCKING_TEST_TIMEOUT = 5000;
+    
+    private static final String TRUNCATION_TEST_TEMPLATE = "12345";
+    
+    @InjectMocks
+    private FreeMarkerService freeMarkerService;
+    
+    @Before
+    public void initializeSpringBeans() {
+        freeMarkerService.setMaxQueueLength(MAX_QUEUE_LENGTH);
+        freeMarkerService.setMaxThreads(MAX_THREADS);
+        freeMarkerService.postConstruct();
+        freeMarkerService.setMaxTemplateExecutionTime(MAX_TEMPLATE_EXECUTION_TIME);
+    }
+
+    @Test
+    public void testCalculationOfATemplateWithNoDataModel() {
+        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                "test", Collections.<String, Object>emptyMap(), null, null, null);
+        assertThat(serviceResponse.isSuccesful(), is(true));
+        assertThat(serviceResponse.getTemplateOutput(), is("test"));
+    }
+
+    @Test
+    public void testSimpleTemplate() {
+        HashMap<String, Object> dataModel = new HashMap<>();
+        dataModel.put("var1", "val1");
+        String templateSourceCode = "${var1}";
+        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                templateSourceCode, dataModel, null, null, null);
+        assertThat(serviceResponse.getTemplateOutput(), equalTo("val1"));
+    }
+
+    @Test
+    public void testTemplateWithFewArgsAndOperators() {
+        HashMap<String, Object> dataModel = new HashMap<>();
+        dataModel.put("var1", "val1");
+        dataModel.put("var2", "val2");
+        String template = "${var1?capitalize} ${var2?cap_first}";
+        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                template, dataModel, null, null, null);
+        assertThat(serviceResponse.getTemplateOutput(), equalTo("Val1 Val2"));
+    }
+
+    @Test
+    public void testOutputFormatParamterMatters() {
+        String template = "${'&'}";
+        {
+            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                    template, null, null, null, null);
+            assertThat(serviceResponse.getTemplateOutput(), equalTo("&"));
+        }
+        {
+            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                    template, null, HTMLOutputFormat.INSTANCE, null, null);
+            assertThat(serviceResponse.getTemplateOutput(), equalTo("&amp;"));
+        }
+    }
+
+    @Test
+    public void testLocaleParameterMatters() {
+        String template = "${.locale}";
+        {
+            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                    template, null, null, new Locale("en", "US"), null);
+            assertThat(serviceResponse.getTemplateOutput(), equalTo("en_US"));
+        }
+        {
+            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                    template, null, null, new Locale("ru", "RU"), null);
+            assertThat(serviceResponse.getTemplateOutput(), equalTo("ru_RU"));
+        }
+    }
+
+    @Test
+    public void testTimeZoneParameterMatters() {
+        String template = "${" + System.currentTimeMillis() + "?numberToDatetime}";
+        
+        String gmt1Result;
+        {
+            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                    template, null, null, null, TimeZone.getTimeZone("GMT+01"));
+            gmt1Result = serviceResponse.getTemplateOutput();
+        }
+        
+        String gmt2Result;
+        {
+            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                    template, null, null, new Locale("ru", "RU"), null);
+            gmt2Result = serviceResponse.getTemplateOutput();
+        }
+        
+        assertThat(gmt1Result, not(equalTo(gmt2Result)));
+    }
+    
+    @Test
+    public void testTemplateWithSyntaxError() {
+        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                "test ${xx", Collections.<String, Object>emptyMap(), null, null, null);
+        assertThat(serviceResponse.isSuccesful(), is(false));
+        assertThat(serviceResponse.getFailureReason(), instanceOf(ParseException.class));
+    }
+
+    @Test
+    public void testTemplateWithEvaluationError() {
+        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                "test ${x}", Collections.<String, Object>emptyMap(), null, null, null);
+        assertThat(serviceResponse.isSuccesful(), is(false));
+        assertThat(serviceResponse.getFailureReason(), instanceOf(TemplateException.class));
+    }
+
+    @Test
+    public void testResultAlmostTruncation() {
+        freeMarkerService.setMaxOutputLength(5);
+        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                TRUNCATION_TEST_TEMPLATE, Collections.<String, Object>emptyMap(), null, null, null);
+        assertThat(serviceResponse.isSuccesful(), is(true));
+        assertThat(serviceResponse.isTemplateOutputTruncated(), is(false));
+        assertThat(serviceResponse.getTemplateOutput(), equalTo(TRUNCATION_TEST_TEMPLATE));
+    }
+
+    @Test
+    public void testResultTruncation() {
+        freeMarkerService.setMaxOutputLength(4);
+        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
+                TRUNCATION_TEST_TEMPLATE, Collections.<String, Object>emptyMap(), null, null, null);
+        assertThat(serviceResponse.isSuccesful(), is(true));
+        assertThat(serviceResponse.isTemplateOutputTruncated(), is(true));
+        assertThat(serviceResponse.getTemplateOutput(),
+                startsWith(TRUNCATION_TEST_TEMPLATE.substring(0, freeMarkerService.getMaxOutputLength())));
+        assertThat(serviceResponse.getTemplateOutput().charAt(freeMarkerService.getMaxOutputLength()),
+                not(equalTo(TRUNCATION_TEST_TEMPLATE.charAt(freeMarkerService.getMaxOutputLength()))));
+    }
+    
+    @Test
+    public void testTemplateExecutionTimeout() throws InterruptedException, ExecutionException {
+        freeMarkerService.setMaxTemplateExecutionTime(200);
+        
+        // To avoid blocking the CI server forever without giving error:
+        Future<FreeMarkerServiceResponse> future = Executors.newSingleThreadExecutor().submit(
+                new Callable<FreeMarkerServiceResponse>() {
+        
+                    @Override
+                    public FreeMarkerServiceResponse call() throws Exception {
+                        return freeMarkerService.calculateTemplateOutput(
+                                "<#list 1.. as _></#list>", Collections.<String, Object>emptyMap(), null, null, null);
+                    }
+                    
+                });
+        FreeMarkerServiceResponse serviceResponse;
+        try {
+            serviceResponse = future.get(BLOCKING_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+        } catch (TimeoutException e) {
+            throw new AssertionError("The template execution wasn't aborted (within the timeout).");
+        }
+        assertThat(serviceResponse.isSuccesful(), is(false));
+        assertThat(serviceResponse.getFailureReason(), instanceOf(TimeoutException.class));
+    }
+    
+    @Test
+    public void testServiceOverburden() throws InterruptedException {
+        final BlockerDirective blocker = new BlockerDirective();
+        final Map<String, BlockerDirective> blockerDataModel = Collections.singletonMap("blocker", blocker);
+        try {
+            // Fill all available task "slots":
+            for (int i = 0; i < MAX_THREADS + MAX_QUEUE_LENGTH; i++) {
+                new Thread(new Runnable() {
+                    @Override
+                    public void run() {
+                        freeMarkerService.calculateTemplateOutput("<@blocker/>", blockerDataModel, null, null, null);                    
+                    }
+                }).start();
+            }
+            
+            // Wait until all template executions has started:
+            synchronized (blocker) {
+                final long startTime = System.currentTimeMillis();
+                while (blocker.getEntered() < MAX_THREADS) {
+                    // To avoid blocking the CI server forever is something goes wrong:
+                    if (System.currentTimeMillis() - startTime > BLOCKING_TEST_TIMEOUT) {
+                        fail("JUnit test timed out");
+                    }
+                    blocker.wait(1000);
+                }
+            }
+            Thread.sleep(200);
+            // Because the others are waiting in the queue, and weren't started:
+            assertThat(blocker.getEntered(), not(greaterThan(MAX_THREADS)));
+            
+            // Souldn't accept on more tasks:
+            try {
+                freeMarkerService.calculateTemplateOutput("<@blocker/>", blockerDataModel, null, null, null);
+                fail("Expected RejectedExecutionException, but nothing was thrown.");
+            } catch (RejectedExecutionException e) {
+                // Expected
+            }
+        } finally {
+            // Ensure that the started threads will end:
+            blocker.release();
+        }
+    }
+    
+    private static final class BlockerDirective implements TemplateDirectiveModel {
+        
+        private int entered;
+        private boolean released;
+
+        public synchronized void release() {
+            released = true;
+            notifyAll();
+        }
+        
+        @Override
+        public synchronized void execute(Environment env, @SuppressWarnings("rawtypes") Map params,
+                TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
+            entered++;
+            notifyAll();
+            final long startTime = System.currentTimeMillis();
+            while (!released) {
+                // To avoid blocking the CI server forever is something goes wrong:
+                if (System.currentTimeMillis() - startTime > BLOCKING_TEST_TIMEOUT) {
+                    LOG.error("JUnit test timed out");
+                }
+                try {
+                    wait(1000);
+                } catch (InterruptedException e) {
+                    LOG.error("JUnit test was interrupted");
+                }
+            }
+            LOG.debug("Blocker released");
+        }
+
+        public synchronized int getEntered() {
+            return entered;
+        }
+        
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/util/DataModelParserTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/util/DataModelParserTest.java b/src/test/java/org/apache/freemarker/onlinetester/util/DataModelParserTest.java
new file mode 100644
index 0000000..468b2b5
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/util/DataModelParserTest.java
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.util;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.math.BigDecimal;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.GregorianCalendar;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import freemarker.template.utility.DateUtil;
+
+public class DataModelParserTest {
+    
+    @Test
+    public void testEmpty() throws DataModelParsingException {
+        assertTrue(DataModelParser.parse("", DateUtil.UTC).isEmpty());
+        assertTrue(DataModelParser.parse(" \n ", DateUtil.UTC).isEmpty());
+    }
+
+    @Test
+    public void testSingleAssignment() throws DataModelParsingException {
+        assertEquals(ImmutableMap.of("n", "v"), DataModelParser.parse("n=v", DateUtil.UTC));
+        assertEquals(ImmutableMap.of("n", "v"), DataModelParser.parse("\n\n\tn\t= v", DateUtil.UTC));
+        assertEquals(ImmutableMap.of("longerN", "longer v"), DataModelParser.parse("longerN=longer v", DateUtil.UTC));
+        assertEquals(ImmutableMap.of("a:b.c-d$@", "foo bar\nbaaz"), DataModelParser.parse("a:b.c-d$@ = foo bar\nbaaz", DateUtil.UTC));
+    }
+
+    @Test
+    public void testNotBlankButHasNoAssignment() {
+        try {
+            DataModelParser.parse("x", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("must start with an assignment"));
+        }
+    }
+
+    @Test
+    public void testNoLinebreakBeforeEquals() {
+        try {
+            DataModelParser.parse("x\n=y", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("must start with an assignment"));
+        }
+    }
+
+    @Test
+    public void testMultipleAssignments() throws DataModelParsingException {
+        assertEquals(ImmutableMap.of("n1", "v1", "n2", "v2", "n3", "v3"),
+                DataModelParser.parse("n1=v1\nn2=v2\nn3=v3", DateUtil.UTC));
+        assertEquals(ImmutableMap.of("n1", "v1", "n2", "v2", "n3", "v3"),
+                DataModelParser.parse(" n1 = v1 \r\n\r\n\tn2=v2\nn3 = v3\n\n", DateUtil.UTC));
+        assertEquals(ImmutableMap.of("n1", "=\n=v", "n2", "l1\nl2\n\nl3", "n3", "v3"),
+                DataModelParser.parse("n1==\n=v \n n2=l1\nl2\n\nl3\nn3=v3", DateUtil.UTC));
+    }
+
+    @Test
+    public void testStrings() throws DataModelParsingException {
+        assertEquals(
+                ImmutableMap.of(
+                    "a", "C:\\x",
+                    "b", "foo\nbar",
+                    "c", "foo\t\"bar\"",
+                    "d", "foo\t\"bar\"",
+                    "e", "Foo's"
+                ),
+                DataModelParser.parse(
+                        "a=C:\\x\n"
+                        + "b=foo\nbar\n"
+                        + "c=foo\t\"bar\"\n"
+                        + "d=\"foo\\t\\\"bar\\\"\"\n"
+                        + "e=\"Foo's\"",
+                        DateUtil.UTC));
+        try {
+            DataModelParser.parse("a=\"foo", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("quoted"));
+        }
+        try {
+            DataModelParser.parse("a='foo'", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("quoted"));
+        }
+        try {
+            DataModelParser.parse("a=\"\\x\"", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("escape"));
+        }
+    }
+    
+    @Test
+    public void testBasicNumbers() throws DataModelParsingException {
+        assertEquals(
+                ImmutableMap.of(
+                    "a", BigDecimal.valueOf(1),
+                    "b", BigDecimal.valueOf(1.5),
+                    "c", BigDecimal.valueOf(-1.5),
+                    "d", BigDecimal.valueOf(1.5),
+                    "e", BigDecimal.valueOf(-0.125)
+                ),
+                DataModelParser.parse("a=1\nb=1.5\nc=-1.5\nd=+1.5\ne=-12.5e-2", DateUtil.UTC));
+        try {
+            DataModelParser.parse("a=1,5", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("Malformed number"));
+            assertThat(e.getMessage(), not(containsString("ISO")));
+        }
+    }
+    
+    @Test
+    public void testSpecialNumbers() throws DataModelParsingException {
+    assertEquals(
+            ImmutableMap.of(
+                "a", Double.NaN,
+                "b", Double.POSITIVE_INFINITY,
+                "c", Double.NEGATIVE_INFINITY,
+                "d", Double.POSITIVE_INFINITY
+            ),
+            DataModelParser.parse("a=NaN\nb=Infinity\nc=-Infinity\nd=+Infinity", DateUtil.UTC));
+    }
+
+    @Test
+    public void testBooleans() throws DataModelParsingException {
+        assertEquals(ImmutableMap.of("a", true, "b", false), DataModelParser.parse("a=true\nb=false", DateUtil.UTC));
+        try {
+            DataModelParser.parse("a=True", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("true"));
+        }
+    }
+    
+    @Test
+    public void testTemporals() throws DataModelParsingException {
+        final Map<String, Object> dm = DataModelParser.parse("a=2014-02-12T01:02:03Z\nb=2014-02-12\nc=01:02:03Z", DateUtil.UTC);
+        
+        final GregorianCalendar cal = new GregorianCalendar(DateUtil.UTC);
+        cal.clear();
+        
+        cal.set(2014, 1, 12, 1, 2, 3);
+        Timestamp a = new Timestamp(cal.getTimeInMillis());
+        assertThat(dm.get("a"), instanceOf(Timestamp.class));
+        assertEquals(dm.get("a"), a);
+        
+        cal.set(2014, 1, 12, 0, 0, 0);
+        java.sql.Date b = new java.sql.Date(cal.getTimeInMillis());
+        assertThat(dm.get("b"), instanceOf(java.sql.Date.class));
+        assertEquals(dm.get("b"), b);
+        
+        cal.set(1970, 0, 1, 1, 2, 3);
+        Time c = new Time(cal.getTimeInMillis());
+        assertThat(dm.get("c"), instanceOf(Time.class));
+        assertEquals(dm.get("c"), c);
+        
+        try {
+            DataModelParser.parse("a=2012T123", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("ISO 8601 date-time"));
+        }
+        try {
+            DataModelParser.parse("a=2012-0102", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("ISO 8601 date"));
+        }
+        try {
+            DataModelParser.parse("a=25:00", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("ISO 8601 time"));
+        }
+    }
+    
+    @Test
+    public void testMaps() throws DataModelParsingException {
+        final Object map = DataModelParser.parse(
+                "n = {\n"
+                + "\t\"a\": 1,\n"
+                + "\t\"b\": 2\n"
+                + "}",
+                DateUtil.UTC)
+                .get("n");
+        assertEquals(ImmutableMap.of("a", 1, "b", 2), map);
+        assertThat(map, instanceOf(LinkedHashMap.class));
+        try {
+            DataModelParser.parse("n={1:2}", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("JSON"));
+        }
+    }    
+    
+    @Test
+    public void testLists() throws DataModelParsingException {
+        final Object list = DataModelParser.parse("n=[1, 2]", DateUtil.UTC).get("n");
+        assertEquals(ImmutableList.of(1, 2), list);
+        assertThat(list, instanceOf(List.class));
+        try {
+            DataModelParser.parse("n=[", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("JSON"));
+        }
+    }
+
+    @Test
+    public void testXML() throws DataModelParsingException {
+        final Object doc = DataModelParser.parse("n=<e xmlns='foo:/bar' a='123'>text</e>", DateUtil.UTC).get("n");
+        assertThat(doc, instanceOf(Document.class));
+        final Node firstChild = ((Document) doc).getFirstChild();
+        assertEquals("e", firstChild.getNodeName());
+        assertEquals("foo:/bar", firstChild.getNamespaceURI());
+        
+        try {
+            DataModelParser.parse("n=<ns:e />", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("XML"));
+        }
+    }
+    
+    @Test
+    public void testNull() throws DataModelParsingException {
+        assertNull(DataModelParser.parse("n=null", DateUtil.UTC).get("n"));
+        try {
+            DataModelParser.parse("a=NULL", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("null"));
+        }
+    }
+
+    @Test
+    public void testEmptyValue() throws DataModelParsingException {
+        try {
+            DataModelParser.parse("n=", DateUtil.UTC);
+            fail();
+        } catch (DataModelParsingException e) {
+            assertThat(e.getMessage(), containsString("Empty"));
+        }
+        
+        assertEquals("", DataModelParser.parse("n=\"\"", DateUtil.UTC).get("n"));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/util/LengthLimitedWriterTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/util/LengthLimitedWriterTest.java b/src/test/java/org/apache/freemarker/onlinetester/util/LengthLimitedWriterTest.java
new file mode 100644
index 0000000..b072a96
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/util/LengthLimitedWriterTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.util;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import org.junit.Test;
+
+public class LengthLimitedWriterTest {
+
+    private StringWriter wrappedW = new StringWriter();
+    private LengthLimitedWriter w = new LengthLimitedWriter(wrappedW, 5);
+    
+    @Test
+    public void testLimitNotExceeded() throws IOException {
+        w.write("123");
+        w.write("45");
+    }
+
+    @Test
+    public void testLimitExceededWithString() throws IOException {
+        w.write("123");
+        try {
+            w.write("456");
+            fail();
+        } catch (LengthLimitExceededException e) {
+            assertEquals("12345", wrappedW.toString());
+        }
+    }
+
+    @Test
+    public void testLimitExceededWithCharArray() throws IOException {
+        w.write(new char[] { '1', '2', '3' });
+        try {
+            w.write(new char[] { '4', '5', '6' });
+            fail();
+        } catch (LengthLimitExceededException e) {
+            assertEquals("12345", wrappedW.toString());
+        }
+    }
+
+    @Test
+    public void testLimitExceededWithChar() throws IOException {
+        w.write('1');
+        w.write('2');
+        w.write('3');
+        w.write('4');
+        w.write('5');
+        try {
+            w.write('6');
+            fail();
+        } catch (LengthLimitExceededException e) {
+            assertEquals("12345", wrappedW.toString());
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/view/FreeMarkerOnlineViewTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/view/FreeMarkerOnlineViewTest.java b/src/test/java/org/apache/freemarker/onlinetester/view/FreeMarkerOnlineViewTest.java
new file mode 100644
index 0000000..b9572ba
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/view/FreeMarkerOnlineViewTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.view;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.junit.Test;
+
+import org.apache.freemarker.onlinetester.services.AllowedSettingValuesMaps;
+
+import freemarker.core.HTMLOutputFormat;
+
+
+public class FreeMarkerOnlineViewTest {
+
+    private static final String TEMPLATE = "Template";
+    private static final String DATA_MODEL = "DataModel";
+
+    @Test
+    public void testVieEmptyConstrucotr() {
+        FreeMarkerOnlineView view = new FreeMarkerOnlineView();
+        assertEquals(view.getTemplate(), "");
+        assertEquals(view.getDataModel(), "");
+        assertEquals(view.getOutputFormat(), AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT_KEY);
+        assertEquals(view.getLocale(), AllowedSettingValuesMaps.DEFAULT_LOCALE_KEY);
+        assertEquals(view.getTimeZone(), AllowedSettingValuesMaps.DEFAULT_TIME_ZONE_KEY);
+    }
+
+    @Test
+    public void testViewWhenAllOK() {
+        FreeMarkerOnlineView view = new FreeMarkerOnlineView();
+        
+        view.setTemplate(TEMPLATE);
+        view.setDataModel(DATA_MODEL);
+        String outputFormatStr = HTMLOutputFormat.INSTANCE.getName();
+        view.setOutputFormat(outputFormatStr);
+        String localeStr = Locale.GERMAN.toString();
+        view.setLocale(localeStr);
+        String timeZoneStr = TimeZone.getTimeZone("GMT+01").getID();
+        view.setTimeZone(timeZoneStr);
+        
+        assertEquals(view.getTemplate(), TEMPLATE);
+        assertEquals(view.getDataModel(), DATA_MODEL);
+        assertEquals(view.getOutputFormat(), outputFormatStr);
+        assertEquals(view.getLocale(), localeStr);
+        assertEquals(view.getTimeZone(), timeZoneStr);
+    }
+    
+}


[4/5] incubator-freemarker-online-tester git commit: renamed the package name to org/apache/freemarker/onlinetester

Posted by dd...@apache.org.
renamed the package name to org/apache/freemarker/onlinetester


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/commit/2f0c0424
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/tree/2f0c0424
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/diff/2f0c0424

Branch: refs/heads/master
Commit: 2f0c0424bbfee360018b3d5e8d7688b588d4b176
Parents: 7b46afe
Author: Pradeep Murugesan <pr...@outlook.com>
Authored: Sun Apr 9 09:15:49 2017 +0200
Committer: Pradeep Murugesan <pr...@outlook.com>
Committed: Sun Apr 9 09:15:49 2017 +0200

----------------------------------------------------------------------
 README.md                                       |  36 +-
 build.gradle                                    |   4 +-
 intellij.gradle                                 |   2 +-
 .../dropwizard/ApplicationStartup.java          |  42 ---
 .../healthchecks/MyProjectHealthCheck.java      |  37 --
 .../com/kenshoo/freemarker/model/ErrorCode.java |  25 --
 .../kenshoo/freemarker/model/ErrorResponse.java |  30 --
 .../freemarker/model/ExecuteRequest.java        |  78 ----
 .../freemarker/model/ExecuteResourceField.java  |  57 ---
 .../model/ExecuteResourceProblem.java           |  53 ---
 .../freemarker/model/ExecuteResponse.java       |  63 ----
 .../freemarker/model/SelectionOption.java       |  88 -----
 .../FreeMarkerOnlineExecuteResource.java        | 220 -----------
 .../resources/FreeMarkerOnlineResource.java     |  63 ----
 .../services/AllowedSettingValuesMaps.java      | 115 ------
 .../freemarker/services/FreeMarkerService.java  | 364 -------------------
 .../services/FreeMarkerServiceException.java    |  38 --
 .../services/FreeMarkerServiceResponse.java     |  68 ----
 .../freemarker/util/DataModelParser.java        | 268 --------------
 .../util/DataModelParsingException.java         |  39 --
 .../kenshoo/freemarker/util/ExceptionUtils.java |  53 ---
 .../util/LengthLimitExceededException.java      |  35 --
 .../freemarker/util/LengthLimitedWriter.java    |  87 -----
 .../freemarker/view/FreeMarkerOnlineView.java   | 157 --------
 .../dropwizard/ApplicationStartup.java          |  42 +++
 .../healthchecks/MyProjectHealthCheck.java      |  37 ++
 .../onlinetester/model/ErrorCode.java           |  25 ++
 .../onlinetester/model/ErrorResponse.java       |  30 ++
 .../onlinetester/model/ExecuteRequest.java      |  78 ++++
 .../model/ExecuteResourceField.java             |  57 +++
 .../model/ExecuteResourceProblem.java           |  53 +++
 .../onlinetester/model/ExecuteResponse.java     |  63 ++++
 .../onlinetester/model/SelectionOption.java     |  88 +++++
 .../FreeMarkerOnlineExecuteResource.java        | 220 +++++++++++
 .../resources/FreeMarkerOnlineResource.java     |  63 ++++
 .../services/AllowedSettingValuesMaps.java      | 115 ++++++
 .../services/FreeMarkerService.java             | 364 +++++++++++++++++++
 .../services/FreeMarkerServiceException.java    |  38 ++
 .../services/FreeMarkerServiceResponse.java     |  68 ++++
 .../onlinetester/util/DataModelParser.java      | 268 ++++++++++++++
 .../util/DataModelParsingException.java         |  39 ++
 .../onlinetester/util/ExceptionUtils.java       |  53 +++
 .../util/LengthLimitExceededException.java      |  35 ++
 .../onlinetester/util/LengthLimitedWriter.java  |  87 +++++
 .../onlinetester/view/FreeMarkerOnlineView.java | 157 ++++++++
 src/main/resources/spring/bootstrap-context.xml |   2 +-
 .../platform/DropWizardServiceTest.java         |  36 --
 .../platform/YamlPropertiesPersister.java       |  91 -----
 .../FreeMarkerOnlineExecuteResourceTest.java    | 159 --------
 .../resources/FreeMarkerOnlineResourceTest.java |  70 ----
 .../FreeMarkerServiceResponseBuilderTest.java   |  61 ----
 .../services/FreeMarkerServiceTest.java         | 308 ----------------
 .../freemarker/util/DataModelParserTest.java    | 281 --------------
 .../util/LengthLimitedWriterTest.java           |  77 ----
 .../view/FreeMarkerOnlineViewTest.java          |  69 ----
 .../platform/DropWizardServiceTest.java         |  39 ++
 .../platform/YamlPropertiesPersister.java       |  91 +++++
 .../FreeMarkerOnlineExecuteResourceTest.java    | 159 ++++++++
 .../resources/FreeMarkerOnlineResourceTest.java |  70 ++++
 .../FreeMarkerServiceResponseBuilderTest.java   |  61 ++++
 .../services/FreeMarkerServiceTest.java         | 308 ++++++++++++++++
 .../onlinetester/util/DataModelParserTest.java  | 281 ++++++++++++++
 .../util/LengthLimitedWriterTest.java           |  77 ++++
 .../view/FreeMarkerOnlineViewTest.java          |  69 ++++
 64 files changed, 3157 insertions(+), 3154 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 38e5992..546e48e 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,22 @@
 ```
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
+ 
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+   http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ 
 ```
 
 freemarker-online

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 66ee5fd..3e0405f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-group = 'com.kenshoo.freemarker'
+group = 'org.apache.freemarker.onlinetester'
 project.projectName = "freemarker-online"
 def BUILD_NUMBER = project.hasProperty('BUILD_NUMBER') ? "$BUILD_NUMBER" : 'undef'
 project.version = "0.1.$BUILD_NUMBER"
@@ -100,7 +100,7 @@ fatJar {
     exclude "META-INF/*.DSA"
     exclude "META-INF/*.RSA"
     manifest {
-        attributes 'Main-Class': 'com.kenshoo.freemarker.dropwizard.ApplicationStartup'
+        attributes 'Main-Class': 'org.apache.freemarker.onlinetester.dropwizard.ApplicationStartup'
         attributes 'Implementation-Version': "$version"
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/intellij.gradle
----------------------------------------------------------------------
diff --git a/intellij.gradle b/intellij.gradle
index 8cf9da1..0853356 100644
--- a/intellij.gradle
+++ b/intellij.gradle
@@ -39,7 +39,7 @@ idea.workspace.iws.withXml { provider ->
     list.appendNode('item', [index: '0', class: 'java.lang.String', itemvalue: 'MyProjectStartup'])
     def Application = runManager.appendNode('configuration', [default: 'false', name: "${projectName}", type: 'Application', factoryName: 'Application'])
     Application.appendNode('extension', [name: 'coverage', enabled: 'false', merge: 'false', runner: 'idea'])
-    Application.appendNode('option', [name: 'MAIN_CLASS_NAME', value: "com.kenshoo.freemarker.dropwizard.ApplicationStartup"])
+    Application.appendNode('option', [name: 'MAIN_CLASS_NAME', value: "org.apache.freemarker.onlinetester.dropwizard.ApplicationStartup"])
     Application.appendNode('option', [name: 'VM_PARAMETERS', value: ""])
     Application.appendNode('option', [name: 'PROGRAM_PARAMETERS', value: "server  src/main/resources/${projectName}.yml"])
     Application.appendNode('option', [name: 'WORKING_DIRECTORY', value: "$projectDir"])

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/dropwizard/ApplicationStartup.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/dropwizard/ApplicationStartup.java b/src/main/java/com/kenshoo/freemarker/dropwizard/ApplicationStartup.java
deleted file mode 100644
index 9378e33..0000000
--- a/src/main/java/com/kenshoo/freemarker/dropwizard/ApplicationStartup.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.dropwizard;
-
-import com.berico.fallwizard.SpringConfiguration;
-import com.berico.fallwizard.SpringService;
-import com.yammer.dropwizard.assets.AssetsBundle;
-import com.yammer.dropwizard.config.Bootstrap;
-import com.yammer.dropwizard.views.ViewBundle;
-
-public class ApplicationStartup extends SpringService<SpringConfiguration> {
-
-    public static void main(String[] args) throws Exception {
-        new ApplicationStartup().run(args);
-    }
-
-    @Override
-    public void initialize(Bootstrap<SpringConfiguration> bootstrap) {
-        bootstrap.setName("freemarker-online");
-        bootstrap.addBundle(new ViewBundle());
-        bootstrap.addBundle(new AssetsBundle("/assets/css", "/css"));
-        bootstrap.addBundle(new AssetsBundle("/assets/js", "/js"));
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/healthchecks/MyProjectHealthCheck.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/healthchecks/MyProjectHealthCheck.java b/src/main/java/com/kenshoo/freemarker/healthchecks/MyProjectHealthCheck.java
deleted file mode 100644
index 6f353dd..0000000
--- a/src/main/java/com/kenshoo/freemarker/healthchecks/MyProjectHealthCheck.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.healthchecks;
-
-import com.yammer.metrics.core.HealthCheck;
-import org.springframework.stereotype.Component;
-
-@Component
-public class MyProjectHealthCheck extends HealthCheck {
-
-    // note that this is due to the default spring CTR
-    public MyProjectHealthCheck() {
-        super("MyProjectHealthCheck");
-    }
-
-    @Override
-    protected Result check() throws Exception {
-        return Result.healthy(); // we're always healthy!
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/model/ErrorCode.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/model/ErrorCode.java b/src/main/java/com/kenshoo/freemarker/model/ErrorCode.java
deleted file mode 100644
index d26566c..0000000
--- a/src/main/java/com/kenshoo/freemarker/model/ErrorCode.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.model;
-
-public enum ErrorCode {
-    FREEMARKER_SERVICE_TIMEOUT
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/model/ErrorResponse.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/model/ErrorResponse.java b/src/main/java/com/kenshoo/freemarker/model/ErrorResponse.java
deleted file mode 100644
index 5af5314..0000000
--- a/src/main/java/com/kenshoo/freemarker/model/ErrorResponse.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.model;
-
-public class ErrorResponse {
-    private ErrorCode errorCode;
-    private String errorDescription;
-
-    public ErrorResponse(ErrorCode errorCode, String errorDescription) {
-        this.errorCode = errorCode;
-        this.errorDescription = errorDescription;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/model/ExecuteRequest.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/model/ExecuteRequest.java b/src/main/java/com/kenshoo/freemarker/model/ExecuteRequest.java
deleted file mode 100644
index 5797116..0000000
--- a/src/main/java/com/kenshoo/freemarker/model/ExecuteRequest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- package com.kenshoo.freemarker.model;
-
-
-public class ExecuteRequest {
-    private String template;
-    private String dataModel;
-    private String outputFormat;
-    private String locale;
-    private String timeZone;
-
-    public ExecuteRequest() {
-    }
-
-    public ExecuteRequest(String template, String dataModel) {
-        this.template = template;
-        this.dataModel = dataModel;
-    }
-
-    public String getDataModel() {
-        return dataModel;
-    }
-
-    public void setDataModel(String dataModel) {
-        this.dataModel = dataModel;
-    }
-
-    public String getTemplate() {
-
-        return template;
-    }
-
-    public void setTemplate(String template) {
-        this.template = template;
-    }
-
-    public String getOutputFormat() {
-        return outputFormat;
-    }
-
-    public void setOutputFormat(String outputFormat) {
-        this.outputFormat = outputFormat;
-    }
-
-    public String getLocale() {
-        return locale;
-    }
-
-    public void setLocale(String locale) {
-        this.locale = locale;
-    }
-
-    public String getTimeZone() {
-        return timeZone;
-    }
-
-    public void setTimeZone(String timeZone) {
-        this.timeZone = timeZone;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/model/ExecuteResourceField.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/model/ExecuteResourceField.java b/src/main/java/com/kenshoo/freemarker/model/ExecuteResourceField.java
deleted file mode 100644
index 815b1e8..0000000
--- a/src/main/java/com/kenshoo/freemarker/model/ExecuteResourceField.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.model;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonValue;
-
-public enum ExecuteResourceField {
-    DATA_MODEL("dataModel"),
-    TEMPLATE("template"),
-    OUTPUT_FORMAT("outputFormat"),
-    LOCALE("locale"),
-    TIME_ZONE("timeZone");
-    
-    private final String fieldName;
-    
-    private ExecuteResourceField(String filedName) {
-        this.fieldName = filedName;
-    }
-    
-    public String toString() {
-        return getFieldName();
-    }
-    
-    @JsonValue
-    public String getFieldName() {
-        return fieldName;
-    }
-
-    @JsonCreator
-    public static ExecuteResourceField fromEnumString(String val) {
-        for(ExecuteResourceField field : values()) {
-            if(field.getFieldName().equals(val)) {
-                return field;
-            }
-        }
-        throw new IllegalArgumentException("Invalid string value passed: " + val);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/model/ExecuteResourceProblem.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/model/ExecuteResourceProblem.java b/src/main/java/com/kenshoo/freemarker/model/ExecuteResourceProblem.java
deleted file mode 100644
index 3acf216..0000000
--- a/src/main/java/com/kenshoo/freemarker/model/ExecuteResourceProblem.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.model;
-
-public class ExecuteResourceProblem {
-    
-    private ExecuteResourceField field;
-    private String message;
-    
-    // Needed for JSON unmarshalling
-    public ExecuteResourceProblem() {
-        //
-    }
-    
-    public ExecuteResourceProblem(ExecuteResourceField field, String message) {
-        this.field = field;
-        this.message = message;
-    }
-
-    public ExecuteResourceField getField() {
-        return field;
-    }
-
-    public void setField(ExecuteResourceField field) {
-        this.field = field;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/model/ExecuteResponse.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/model/ExecuteResponse.java b/src/main/java/com/kenshoo/freemarker/model/ExecuteResponse.java
deleted file mode 100644
index 8261858..0000000
--- a/src/main/java/com/kenshoo/freemarker/model/ExecuteResponse.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.model;
-
-import java.util.List;
-
-public class ExecuteResponse {
-    private String result;
-    private List<ExecuteResourceProblem> problems;
-    private boolean truncatedResult;
-
-    public ExecuteResponse(String result, List<ExecuteResourceProblem> problems, boolean truncatedResult) {
-        this.result = result;
-        this.problems = problems;
-        this.truncatedResult = truncatedResult;
-    }
-
-    public ExecuteResponse() {
-
-    }
-
-    public List<ExecuteResourceProblem> getProblems() {
-        return problems;
-    }
-
-    public void setProblems(List<ExecuteResourceProblem> problems) {
-        this.problems = problems;
-    }
-
-    public boolean isTruncatedResult() {
-        return truncatedResult;
-    }
-
-    public void setTruncatedResult(boolean truncatedResult) {
-        this.truncatedResult = truncatedResult;
-    }
-
-    public String getResult() {
-        return result;
-    }
-
-    public void setResult(String result) {
-        this.result = result;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/model/SelectionOption.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/model/SelectionOption.java b/src/main/java/com/kenshoo/freemarker/model/SelectionOption.java
deleted file mode 100644
index d68d419..0000000
--- a/src/main/java/com/kenshoo/freemarker/model/SelectionOption.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.model;
-
-public class SelectionOption implements Comparable<SelectionOption> {
-    
-    private final String value;
-    private final String label;
-    
-    public String getValue() {
-        return value;
-    }
-    
-    public String getLabel() {
-        return label;
-    }
-    
-    public SelectionOption(String value, String label) {
-        this.value = value;
-        this.label = label;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((label == null) ? 0 : label.hashCode());
-        result = prime * result + ((value == null) ? 0 : value.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        SelectionOption other = (SelectionOption) obj;
-        if (label == null) {
-            if (other.label != null) {
-                return false;
-            }
-        } else if (!label.equals(other.label)) {
-            return false;
-        }
-        if (value == null) {
-            if (other.value != null) {
-                return false;
-            }
-        } else if (!value.equals(other.value)) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public int compareTo(SelectionOption o) {
-        int r = label.compareTo(o.label);
-        if (r != 0) {
-            return r;
-        }
-        
-        return value.compareTo(o.value);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineExecuteResource.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineExecuteResource.java b/src/main/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineExecuteResource.java
deleted file mode 100644
index d55f8a2..0000000
--- a/src/main/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineExecuteResource.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.resources;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.concurrent.RejectedExecutionException;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import com.kenshoo.freemarker.model.ErrorCode;
-import com.kenshoo.freemarker.model.ErrorResponse;
-import com.kenshoo.freemarker.model.ExecuteRequest;
-import com.kenshoo.freemarker.model.ExecuteResourceField;
-import com.kenshoo.freemarker.model.ExecuteResourceProblem;
-import com.kenshoo.freemarker.model.ExecuteResponse;
-import com.kenshoo.freemarker.services.AllowedSettingValuesMaps;
-import com.kenshoo.freemarker.services.FreeMarkerService;
-import com.kenshoo.freemarker.services.FreeMarkerServiceResponse;
-import com.kenshoo.freemarker.util.DataModelParser;
-import com.kenshoo.freemarker.util.DataModelParsingException;
-import com.kenshoo.freemarker.util.ExceptionUtils;
-
-import freemarker.core.OutputFormat;
-
-@Path("/api/execute")
-@Component
-public class FreeMarkerOnlineExecuteResource {
-    private static final int MAX_TEMPLATE_INPUT_LENGTH = 10000;
-
-    private static final int MAX_DATA_MODEL_INPUT_LENGTH = 10000;
-
-    private static final String MAX_TEMPLATE_INPUT_LENGTH_EXCEEDED_ERROR_MESSAGE
-            = "The template length has exceeded the {0} character limit set for this service.";
-
-    private static final String MAX_DATA_MODEL_INPUT_LENGTH_EXCEEDED_ERROR_MESSAGE
-            = "The data model length has exceeded the {0} character limit set for this service.";
-
-    private static final String UNKNOWN_OUTPUT_FORMAT_ERROR_MESSAGE = "Unknown output format: {0}";
-    private static final String UNKNOWN_LOCALE_ERROR_MESSAGE = "Unknown locale: {0}";
-    private static final String UNKNOWN_TIME_ZONE_ERROR_MESSAGE = "Unknown time zone: {0}";
-
-    private static final String SERVICE_OVERBURDEN_ERROR_MESSAGE
-            = "Sorry, the service is overburden and couldn't handle your request now. Try again later.";
-
-    static final String DATA_MODEL_ERROR_MESSAGE_HEADING = "Failed to parse data model:";
-    static final String DATA_MODEL_ERROR_MESSAGE_FOOTER = "Note: This is NOT a FreeMarker error message. "
-            + "The data model syntax is specific to this online service.";
-
-    @Autowired
-    private FreeMarkerService freeMarkerService;
-
-    @POST
-    @Produces(MediaType.APPLICATION_JSON)
-    @Consumes(MediaType.APPLICATION_JSON)
-    public Response formResult(
-            ExecuteRequest req) {
-        ExecuteResponse resp = new ExecuteResponse();
-        
-        if (StringUtils.isBlank(req.getTemplate()) && StringUtils.isBlank(req.getDataModel())) {
-            return Response.status(400).entity("Empty Template & data").build();
-        }
-
-        List<ExecuteResourceProblem> problems = new ArrayList<ExecuteResourceProblem>();
-        
-        String template = getTemplate(req, problems);
-        Map<String, Object> dataModel = getDataModel(req, problems);
-        OutputFormat outputFormat = getOutputFormat(req, problems);
-        Locale locale = getLocale(req, problems);
-        TimeZone timeZone = getTimeZone(req, problems);
-        
-        if (!problems.isEmpty()) {
-            resp.setProblems(problems);
-            return buildFreeMarkerResponse(resp);
-        }
-        
-        FreeMarkerServiceResponse freeMarkerServiceResponse;
-        try {
-            freeMarkerServiceResponse = freeMarkerService.calculateTemplateOutput(
-                    template, dataModel,
-                    outputFormat, locale, timeZone);
-        } catch (RejectedExecutionException e) {
-            String error = SERVICE_OVERBURDEN_ERROR_MESSAGE;
-            return Response.serverError().entity(new ErrorResponse(ErrorCode.FREEMARKER_SERVICE_TIMEOUT, error)).build();
-        }
-        if (!freeMarkerServiceResponse.isSuccesful()){
-            Throwable failureReason = freeMarkerServiceResponse.getFailureReason();
-            String error = ExceptionUtils.getMessageWithCauses(failureReason);
-            problems.add(new ExecuteResourceProblem(ExecuteResourceField.TEMPLATE, error));
-            resp.setProblems(problems);
-            return buildFreeMarkerResponse(resp);
-        }
-
-        String result = freeMarkerServiceResponse.getTemplateOutput();
-        resp.setResult(result);
-        resp.setTruncatedResult(freeMarkerServiceResponse.isTemplateOutputTruncated());
-        return buildFreeMarkerResponse(resp);
-    }
-
-    private String getTemplate(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
-        String template = req.getTemplate();
-        
-        if (template.length() > MAX_TEMPLATE_INPUT_LENGTH) {
-            String error = formatMessage(MAX_TEMPLATE_INPUT_LENGTH_EXCEEDED_ERROR_MESSAGE, MAX_TEMPLATE_INPUT_LENGTH);
-            problems.add(new ExecuteResourceProblem(ExecuteResourceField.TEMPLATE, error));
-            return null;
-        }
-        
-        return template;
-    }
-
-    private Map<String, Object> getDataModel(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
-        String dataModel = req.getDataModel();
-        
-        if (dataModel.length() > MAX_DATA_MODEL_INPUT_LENGTH) {
-            String error = formatMessage(
-                    MAX_DATA_MODEL_INPUT_LENGTH_EXCEEDED_ERROR_MESSAGE, MAX_DATA_MODEL_INPUT_LENGTH);
-            problems.add(new ExecuteResourceProblem(ExecuteResourceField.DATA_MODEL, error));
-            return null;
-        }
-        
-        try {
-            return DataModelParser.parse(dataModel, freeMarkerService.getFreeMarkerTimeZone());
-        } catch (DataModelParsingException e) {
-            problems.add(new ExecuteResourceProblem(ExecuteResourceField.DATA_MODEL, decorateResultText(e.getMessage())));
-            return null;
-        }
-    }
-
-    private OutputFormat getOutputFormat(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
-        String outputFormatStr = req.getOutputFormat();
-        
-        if (StringUtils.isBlank(outputFormatStr)) {
-            return AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT;
-        }
-    
-        OutputFormat outputFormat = AllowedSettingValuesMaps.OUTPUT_FORMAT_MAP.get(outputFormatStr);
-        if (outputFormat == null) {
-            problems.add(new ExecuteResourceProblem(
-                    ExecuteResourceField.OUTPUT_FORMAT,
-                    formatMessage(UNKNOWN_OUTPUT_FORMAT_ERROR_MESSAGE, outputFormatStr)));
-        }
-        return outputFormat;
-    }
-
-    private Locale getLocale(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
-        String localeStr = req.getLocale();
-        
-        if (StringUtils.isBlank(localeStr)) {
-            return AllowedSettingValuesMaps.DEFAULT_LOCALE;
-        }
-        
-        Locale locale = AllowedSettingValuesMaps.LOCALE_MAP.get(localeStr);
-        if (locale == null) {
-            problems.add(new ExecuteResourceProblem(
-                    ExecuteResourceField.LOCALE,
-                    formatMessage(UNKNOWN_LOCALE_ERROR_MESSAGE, localeStr)));
-        }
-        return locale;
-    }
-
-    private TimeZone getTimeZone(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
-        String timeZoneStr = req.getTimeZone();
-        
-        if (StringUtils.isBlank(timeZoneStr)) {
-            return AllowedSettingValuesMaps.DEFAULT_TIME_ZONE;
-        }
-        
-        TimeZone timeZone = AllowedSettingValuesMaps.TIME_ZONE_MAP.get(timeZoneStr);
-        if (timeZone == null) {
-            problems.add(new ExecuteResourceProblem(
-                    ExecuteResourceField.TIME_ZONE,
-                    formatMessage(UNKNOWN_TIME_ZONE_ERROR_MESSAGE, timeZoneStr)));
-        }
-        return timeZone;
-    }
-
-    private Response buildFreeMarkerResponse(ExecuteResponse executeResponse){
-        return Response.ok().entity(executeResponse).build();
-    }
-    
-    private String decorateResultText(String resultText) {
-        return DATA_MODEL_ERROR_MESSAGE_HEADING + "\n\n" + resultText + "\n\n" + DATA_MODEL_ERROR_MESSAGE_FOOTER;
-    }
-    
-    private String formatMessage(String key, Object... params) {
-        return new MessageFormat(key, Locale.US).format(params);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineResource.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineResource.java b/src/main/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineResource.java
deleted file mode 100644
index e612c8c..0000000
--- a/src/main/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineResource.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.resources;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-import org.springframework.stereotype.Component;
-
-import com.kenshoo.freemarker.view.FreeMarkerOnlineView;
-
-@Path("/")
-@Component
-public class FreeMarkerOnlineResource {
-
-    @GET
-    @Produces(MediaType.TEXT_HTML)
-    public FreeMarkerOnlineView blankForm() {
-        return new FreeMarkerOnlineView();
-    }
-
-    @POST
-    @Produces(MediaType.TEXT_HTML)
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public FreeMarkerOnlineView formResult(
-            @FormParam("template") String template,
-            @FormParam("dataModel") String dataModel,
-            @FormParam("outputFormat") String outputFormat,
-            @FormParam("locale") String locale,
-            @FormParam("timeZone") String timeZone) {
-        FreeMarkerOnlineView view = new FreeMarkerOnlineView();
-        view.setTemplate(template);
-        view.setDataModel(dataModel);
-        view.setOutputFormat(outputFormat);
-        view.setLocale(locale);
-        view.setTimeZone(timeZone);
-        view.setExecute(true);
-        return view;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/services/AllowedSettingValuesMaps.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/services/AllowedSettingValuesMaps.java b/src/main/java/com/kenshoo/freemarker/services/AllowedSettingValuesMaps.java
deleted file mode 100644
index 8b98df0..0000000
--- a/src/main/java/com/kenshoo/freemarker/services/AllowedSettingValuesMaps.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.services;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
-
-import freemarker.core.HTMLOutputFormat;
-import freemarker.core.OutputFormat;
-import freemarker.core.PlainTextOutputFormat;
-import freemarker.core.RTFOutputFormat;
-import freemarker.core.UndefinedOutputFormat;
-import freemarker.core.XHTMLOutputFormat;
-import freemarker.core.XMLOutputFormat;
-
-/**
- * Maps of the setting values the caller can chose from (these are the value shown in a dropdown on the UI).
- */
-public class AllowedSettingValuesMaps {
-
-    public static final OutputFormat DEFAULT_OUTPUT_FORMAT = UndefinedOutputFormat.INSTANCE;
-    public static final String DEFAULT_OUTPUT_FORMAT_KEY = DEFAULT_OUTPUT_FORMAT.getName();
-    public static final Map<String, OutputFormat> OUTPUT_FORMAT_MAP;
-    static {
-        Map<String, OutputFormat> map = new HashMap<String, OutputFormat>();
-        
-        addOutputFormatToMap(map, UndefinedOutputFormat.INSTANCE);
-        addOutputFormatToMap(map, HTMLOutputFormat.INSTANCE);
-        addOutputFormatToMap(map, XMLOutputFormat.INSTANCE);
-        addOutputFormatToMap(map, XHTMLOutputFormat.INSTANCE);
-        addOutputFormatToMap(map, RTFOutputFormat.INSTANCE);
-        addOutputFormatToMap(map, PlainTextOutputFormat.INSTANCE);
-        
-        OUTPUT_FORMAT_MAP = Collections.unmodifiableMap(map);
-    }
-    
-    private static void addOutputFormatToMap(Map<String, OutputFormat> map, OutputFormat outputFormat) {
-        map.put(outputFormat.getName(), outputFormat);
-    }
-
-    public static final Locale DEFAULT_LOCALE = Locale.US;
-    public static final String DEFAULT_LOCALE_KEY = DEFAULT_LOCALE.toString();
-    public static final Map<String, Locale> LOCALE_MAP;
-    static {
-        List<Locale> availableLocales = new ArrayList<Locale>(Arrays.asList(Locale.getAvailableLocales()));
-        
-        for (Iterator<Locale> iterator = availableLocales.iterator(); iterator.hasNext();) {
-            Locale locale = iterator.next();
-            // Don't bloat the list with "variants"
-            if (!StringUtils.isBlank(locale.getVariant())) {
-                iterator.remove();
-            }
-        }
-        
-        if (!availableLocales.contains(DEFAULT_LOCALE)) {
-            availableLocales.add(DEFAULT_LOCALE);
-        }
-        
-        Map<String, Locale> map = new HashMap<String, Locale>();
-        for (Locale locale : availableLocales) {
-            map.put(locale.toString(), locale);
-        }
-        
-        LOCALE_MAP = Collections.unmodifiableMap(map);
-    }
-
-    public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("America/Los_Angeles");
-    
-    public static final String DEFAULT_TIME_ZONE_KEY;
-    
-    public static final Map<String, TimeZone> TIME_ZONE_MAP;
-    static {
-        String[] availableIDs = TimeZone.getAvailableIDs();
-        
-        DEFAULT_TIME_ZONE_KEY = AllowedSettingValuesMaps.DEFAULT_TIME_ZONE.getID();
-        if (!ArrayUtils.contains(availableIDs, DEFAULT_TIME_ZONE_KEY)) {
-            ArrayUtils.add(availableIDs, DEFAULT_TIME_ZONE_KEY);
-        }
-        
-        Map<String, TimeZone> map = new HashMap<String, TimeZone>();
-        for (String timeZoneId : availableIDs) {
-            map.put(timeZoneId, TimeZone.getTimeZone(timeZoneId));
-        }
-        
-        TIME_ZONE_MAP = Collections.unmodifiableMap(map);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/services/FreeMarkerService.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/services/FreeMarkerService.java b/src/main/java/com/kenshoo/freemarker/services/FreeMarkerService.java
deleted file mode 100644
index 84a96ea..0000000
--- a/src/main/java/com/kenshoo/freemarker/services/FreeMarkerService.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.services;
-
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.TimeZone;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import javax.annotation.PostConstruct;
-
-import org.apache.commons.lang3.StringEscapeUtils;
-import org.eclipse.jetty.util.BlockingArrayQueue;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import com.kenshoo.freemarker.util.LengthLimitExceededException;
-import com.kenshoo.freemarker.util.LengthLimitedWriter;
-
-import freemarker.core.FreeMarkerInternalsAccessor;
-import freemarker.core.OutputFormat;
-import freemarker.core.ParseException;
-import freemarker.core.TemplateClassResolver;
-import freemarker.core.TemplateConfiguration;
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateExceptionHandler;
-
-@Service
-public class FreeMarkerService {
-
-    private static final int DEFAULT_MAX_OUTPUT_LENGTH = 100000;
-    private static final int DEFAULT_MAX_THREADS = Math.max(2,
-            (int) Math.round(Runtime.getRuntime().availableProcessors() * 3.0 / 4));
-    /** Not implemented yet, will need 2.3.22, even then a _CoreAPI call. */
-    private static final long DEFAULT_MAX_TEMPLATE_EXECUTION_TIME = 2000;
-    private static final int MIN_DEFAULT_MAX_QUEUE_LENGTH = 2;
-    private static final int MAX_DEFAULT_MAX_QUEUE_LENGTH_MILLISECONDS = 30000;
-    private static final long THREAD_KEEP_ALIVE_TIME = 4 * 1000;
-    private static final long ABORTION_LOOP_TIME_LIMIT = 5000;
-    private static final long ABORTION_LOOP_INTERRUPTION_DISTANCE = 50;
-    
-    private static final String MAX_OUTPUT_LENGTH_EXCEEDED_TERMINATION = "\n----------\n"
-            + "Aborted template processing, as the output length has exceeded the {0} character limit set for "
-            + "this service.";
-    
-    private static final Logger logger = LoggerFactory.getLogger(FreeMarkerService.class);
-
-    private final Configuration freeMarkerConfig;
-    
-    private ExecutorService templateExecutor;
-    
-    private int maxOutputLength = DEFAULT_MAX_OUTPUT_LENGTH;
-    
-    private int maxThreads = DEFAULT_MAX_THREADS;
-    private Integer maxQueueLength;
-    private long maxTemplateExecutionTime = DEFAULT_MAX_TEMPLATE_EXECUTION_TIME;
-
-    public FreeMarkerService() {
-        freeMarkerConfig = new Configuration(Configuration.getVersion());
-        freeMarkerConfig.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
-        freeMarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
-        freeMarkerConfig.setLogTemplateExceptions(false);
-        freeMarkerConfig.setLocale(AllowedSettingValuesMaps.DEFAULT_LOCALE);
-        freeMarkerConfig.setTimeZone(AllowedSettingValuesMaps.DEFAULT_TIME_ZONE);
-        freeMarkerConfig.setOutputFormat(AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT);
-        freeMarkerConfig.setOutputEncoding("UTF-8");
-    }
-    
-    /**
-     * @param templateSourceCode
-     *            The FTL to execute; not {@code null}.
-     * @param dataModel
-     *            The FreeMarker data-model to execute the template with; maybe {@code null}.
-     * @param outputFormat
-     *            The output format to execute the template with; maybe {@code null}.
-     * @param locale
-     *            The locale to execute the template with; maybe {@code null}.
-     * @param timeZone
-     *            The time zone to execute the template with; maybe {@code null}.
-     * 
-     * @return The result of the template parsing and evaluation. The method won't throw exception if that fails due to
-     *         errors in the template provided, instead it indicates this fact in the response object. That's because
-     *         this is a service for trying out the template language, so such errors are part of the normal operation.
-     * 
-     * @throws RejectedExecutionException
-     *             If the service is overburden and thus doing the calculation was rejected.
-     * @throws FreeMarkerServiceException
-     *             If the calculation fails from a reason that's not a mistake in the template and doesn't fit the
-     *             meaning of {@link RejectedExecutionException} either.
-     */
-    public FreeMarkerServiceResponse calculateTemplateOutput(
-            String templateSourceCode, Object dataModel, OutputFormat outputFormat, Locale locale, TimeZone timeZone)
-            throws RejectedExecutionException {
-        Objects.requireNonNull(templateExecutor, "templateExecutor was null - was postConstruct ever called?");
-        
-        final CalculateTemplateOutput task = new CalculateTemplateOutput(
-                templateSourceCode, dataModel, outputFormat, locale, timeZone);
-        Future<FreeMarkerServiceResponse> future = templateExecutor.submit(task);
-        
-        synchronized (task) {
-            while (!task.isTemplateExecutionStarted() && !task.isTaskEnded() && !future.isDone()) {
-                try {
-                    task.wait(50); // Timeout is needed to periodically check future.isDone()
-                } catch (InterruptedException e) {
-                    throw new FreeMarkerServiceException("Template execution task was interrupted.", e);
-                }
-            }
-        }
-        
-        try {
-            return future.get(maxTemplateExecutionTime, TimeUnit.MILLISECONDS);
-        } catch (ExecutionException e) {
-            throw new FreeMarkerServiceException("Template execution task unexpectedly failed", e.getCause());
-        } catch (InterruptedException e) {
-            throw new FreeMarkerServiceException("Template execution task was interrupted.", e);
-        } catch (TimeoutException e) {
-            // Exactly one interruption should be enough, and it should abort template processing pretty much
-            // immediately. But to be on the safe side we will interrupt in a loop, with a timeout.
-            final long abortionLoopStartTime = System.currentTimeMillis();
-            long timeLeft = ABORTION_LOOP_TIME_LIMIT;
-            boolean templateExecutionEnded = false;
-            do {
-                synchronized (task) {
-                    Thread templateExecutorThread = task.getTemplateExecutorThread();
-                    if (templateExecutorThread == null) {
-                        templateExecutionEnded = true;
-                    } else {
-                        FreeMarkerInternalsAccessor.interruptTemplateProcessing(templateExecutorThread);
-                        logger.debug("Trying to interrupt overly long template processing (" + timeLeft + " ms left).");
-                    }
-                }
-                if (!templateExecutionEnded) {
-                    try {
-                        timeLeft = ABORTION_LOOP_TIME_LIMIT - (System.currentTimeMillis() - abortionLoopStartTime);
-                        if (timeLeft > 0) {
-                            Thread.sleep(ABORTION_LOOP_INTERRUPTION_DISTANCE);
-                        }
-                    } catch (InterruptedException eInt) {
-                        logger.error("Template execution abortion loop was interrupted", eInt);
-                        timeLeft = 0;
-                    }
-                }
-            } while (!templateExecutionEnded && timeLeft > 0);
-            
-            if (templateExecutionEnded) {
-                logger.debug("Long template processing has ended.");
-                try {
-                    return future.get();
-                } catch (InterruptedException | ExecutionException e1) {
-                    throw new FreeMarkerServiceException("Failed to get result from template executor task", e);
-                }
-            } else {
-                throw new FreeMarkerServiceException(
-                        "Couldn't stop long running template processing within " + ABORTION_LOOP_TIME_LIMIT
-                        + " ms. It's possibly stuck forever. Such problems can exhaust the executor pool. "
-                        + "Template (quoted): " + StringEscapeUtils.escapeJava(templateSourceCode));
-            }
-        }
-    }
-    
-    public int getMaxOutputLength() {
-        return maxOutputLength;
-    }
-
-    public void setMaxOutputLength(int maxOutputLength) {
-        this.maxOutputLength = maxOutputLength;
-    }
-
-    public int getMaxThreads() {
-        return maxThreads;
-    }
-    
-    public void setMaxThreads(int maxThreads) {
-        this.maxThreads = maxThreads;
-    }
-    
-    public int getMaxQueueLength() {
-        return maxQueueLength;
-    }
-    
-    public void setMaxQueueLength(int maxQueueLength) {
-        this.maxQueueLength = maxQueueLength;
-    }
-
-    public long getMaxTemplateExecutionTime() {
-        return maxTemplateExecutionTime;
-    }
-    
-    public void setMaxTemplateExecutionTime(long maxTemplateExecutionTime) {
-        this.maxTemplateExecutionTime = maxTemplateExecutionTime;
-    }
-
-    /**
-     * Returns the time zone used by the FreeMarker templates.
-     */
-    public TimeZone getFreeMarkerTimeZone() {
-        return freeMarkerConfig.getTimeZone();
-    }
-    
-    private FreeMarkerServiceResponse createFailureResponse(Throwable e) {
-        logger.debug("The template had error(s)", e);
-        return new FreeMarkerServiceResponse.Builder().buildForFailure(e);
-    }
-
-    @PostConstruct
-    public void postConstruct() {
-        int actualMaxQueueLength = maxQueueLength != null
-                ? maxQueueLength
-                : Math.max(
-                        MIN_DEFAULT_MAX_QUEUE_LENGTH,
-                        (int) (MAX_DEFAULT_MAX_QUEUE_LENGTH_MILLISECONDS / maxTemplateExecutionTime));
-        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
-                maxThreads, maxThreads,
-                THREAD_KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS,
-                new BlockingArrayQueue<Runnable>(actualMaxQueueLength));
-        threadPoolExecutor.allowCoreThreadTimeOut(true);
-        templateExecutor = threadPoolExecutor;
-    }
-    
-    private class CalculateTemplateOutput implements Callable<FreeMarkerServiceResponse> {
-        
-        private boolean templateExecutionStarted;
-        private Thread templateExecutorThread;
-        private final String templateSourceCode;
-        private final Object dataModel;
-        private final OutputFormat outputFormat;
-        private final Locale locale;
-        private final TimeZone timeZone;
-        private boolean taskEnded;
-
-        private CalculateTemplateOutput(String templateSourceCode, Object dataModel,
-                OutputFormat outputFormat, Locale locale, TimeZone timeZone) {
-            this.templateSourceCode = templateSourceCode;
-            this.dataModel = dataModel;
-            this.outputFormat = outputFormat;
-            this.locale = locale;
-            this.timeZone = timeZone;
-        }
-        
-        @Override
-        public FreeMarkerServiceResponse call() throws Exception {
-            try {
-                Template template;
-                try {
-                    TemplateConfiguration tCfg = new TemplateConfiguration();
-                    tCfg.setParentConfiguration(freeMarkerConfig);
-                    if (outputFormat != null) {
-                        tCfg.setOutputFormat(outputFormat);
-                    }
-                    if (locale != null) {
-                        tCfg.setLocale(locale);
-                    }
-                    if (timeZone != null) {
-                        tCfg.setTimeZone(timeZone);
-                    }
-                    
-                    template = new Template(null, null,
-                            new StringReader(templateSourceCode), freeMarkerConfig, tCfg, null);
-                    
-                    tCfg.apply(template);
-                } catch (ParseException e) {
-                    // Expected (part of normal operation)
-                    return createFailureResponse(e);
-                } catch (Exception e) {
-                    // Not expected
-                    throw new FreeMarkerServiceException("Unexpected exception during template parsing", e);
-                }
-                
-                FreeMarkerInternalsAccessor.makeTemplateInterruptable(template);
-                
-                boolean resultTruncated;
-                StringWriter writer = new StringWriter();
-                try {
-                    synchronized (this) {
-                        templateExecutorThread = Thread.currentThread(); 
-                        templateExecutionStarted = true;
-                        notifyAll();
-                    }
-                    try {
-                        template.process(dataModel, new LengthLimitedWriter(writer, maxOutputLength));
-                    } finally {
-                        synchronized (this) {
-                            templateExecutorThread = null;
-                            FreeMarkerInternalsAccessor.clearAnyPendingTemplateProcessingInterruption();
-                        }
-                    }
-                    resultTruncated = false;
-                } catch (LengthLimitExceededException e) {
-                    // Not really an error, we just cut the output here.
-                    resultTruncated = true;
-                    writer.write(new MessageFormat(MAX_OUTPUT_LENGTH_EXCEEDED_TERMINATION, AllowedSettingValuesMaps.DEFAULT_LOCALE)
-                            .format(new Object[] { maxOutputLength }));
-                    // Falls through
-                } catch (TemplateException e) {
-                    // Expected (part of normal operation)
-                    return createFailureResponse(e);
-                } catch (Exception e) {
-                    if (FreeMarkerInternalsAccessor.isTemplateProcessingInterruptedException(e)) {
-                        return new FreeMarkerServiceResponse.Builder().buildForFailure(new TimeoutException(
-                                "Template processing was aborted for exceeding the " + getMaxTemplateExecutionTime()
-                                + " ms time limit set for this online service. This is usually because you have "
-                                + "a very long running #list (or other kind of loop) in your template.")); 
-                    }
-                    // Not expected
-                    throw new FreeMarkerServiceException("Unexpected exception during template evaluation", e);
-                }
-                
-                return new FreeMarkerServiceResponse.Builder().buildForSuccess(writer.toString(), resultTruncated);
-            } finally {
-                synchronized (this) {
-                    taskEnded = true;
-                    notifyAll();
-                }
-            }
-        }
-        
-        private synchronized boolean isTemplateExecutionStarted() {
-            return templateExecutionStarted;
-        }
-
-        private synchronized boolean isTaskEnded() {
-            return taskEnded;
-        }
-        
-        /**
-         * @return non-{@code null} after the task execution has actually started, but before it has finished.
-         */
-        private synchronized Thread getTemplateExecutorThread() {
-            return templateExecutorThread;
-        }
-        
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/services/FreeMarkerServiceException.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/services/FreeMarkerServiceException.java b/src/main/java/com/kenshoo/freemarker/services/FreeMarkerServiceException.java
deleted file mode 100644
index ae7970d..0000000
--- a/src/main/java/com/kenshoo/freemarker/services/FreeMarkerServiceException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.services;
-
-/**
- * When {@link FreeMarkerService} fails on an unexpected way (non-user error). 
- */
-public class FreeMarkerServiceException extends RuntimeException {
-
-    private static final long serialVersionUID = 1L;
-
-    public FreeMarkerServiceException(String message) {
-        super(message);
-        // TODO Auto-generated constructor stub
-    }
-
-    public FreeMarkerServiceException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/services/FreeMarkerServiceResponse.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/services/FreeMarkerServiceResponse.java b/src/main/java/com/kenshoo/freemarker/services/FreeMarkerServiceResponse.java
deleted file mode 100644
index 8aa37ec..0000000
--- a/src/main/java/com/kenshoo/freemarker/services/FreeMarkerServiceResponse.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.services;
-
-public class FreeMarkerServiceResponse {
-    
-    private final String templateOutput;
-    private final boolean templateOutputTruncated;
-    private final Throwable failureReason;
-
-    FreeMarkerServiceResponse(String templateOutput, boolean templateOutputTruncated) {
-        this.templateOutput = templateOutput;
-        this.templateOutputTruncated = templateOutputTruncated;
-        this.failureReason = null;
-    }
-
-    FreeMarkerServiceResponse(Throwable failureReason) {
-        this.templateOutput = null;
-        this.templateOutputTruncated = false;
-        this.failureReason = failureReason;
-    }
-    
-    public String getTemplateOutput() {
-        return templateOutput;
-    }
-
-    public boolean isTemplateOutputTruncated() {
-        return templateOutputTruncated;
-    }
-
-    public boolean isSuccesful() {
-        return failureReason == null;
-    }
-
-    public Throwable getFailureReason() {
-        return failureReason;
-    }
-
-    public static class Builder {
-        
-        public FreeMarkerServiceResponse buildForSuccess(String result, boolean resultTruncated){
-            return new FreeMarkerServiceResponse(result, resultTruncated);
-        }
-
-        public FreeMarkerServiceResponse buildForFailure(Throwable failureReason){
-            return new FreeMarkerServiceResponse(failureReason);
-        }
-        
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/util/DataModelParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/util/DataModelParser.java b/src/main/java/com/kenshoo/freemarker/util/DataModelParser.java
deleted file mode 100644
index ada847d..0000000
--- a/src/main/java/com/kenshoo/freemarker/util/DataModelParser.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.util;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.math.BigDecimal;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.parsers.DocumentBuilder;
-
-import org.springframework.util.StringUtils;
-import org.w3c.dom.Document;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import freemarker.ext.dom.NodeModel;
-import freemarker.template.utility.DateUtil;
-import freemarker.template.utility.DateUtil.CalendarFieldsToDateConverter;
-import freemarker.template.utility.DateUtil.DateParseException;
-import freemarker.template.utility.DateUtil.TrivialCalendarFieldsToDateConverter;
-
-/**
- * Parses the text that the user enters into the data model input field.
- */
-public final class DataModelParser {
-
-    private static final String KEYWORD_NEGATIVE_INFINITY = "-Infinity";
-
-    private static final String KEYWORD_POSITIVE_INFINITY = "+Infinity";
-
-    private static final String KEYWORD_INFINITY = "Infinity";
-
-    private static final String KEYWORD_TRUE = "true";
-
-    private static final String KEYWORD_FALSE = "false";
-
-    private static final String KEYWORD_NULL = "null";
-
-    private static final String KEYWORD_NAN = "NaN";
-
-    /** Matches a line starting like "someVariable=". */
-    private static final Pattern ASSIGNMENT_START = Pattern.compile(
-            "^\\s*"
-            + "(\\p{L}[\\p{L}\\p{N}\\.:\\-_$@]*)" // name
-            + "[ \t]*=\\s*",
-            Pattern.MULTILINE);
-
-    /** Matches a value that starts like a number, or probably meant to be number at least. */
-    private static final Pattern NUMBER_LIKE = Pattern.compile("[+-]?[\\.,]?[0-9].*", Pattern.DOTALL);
-    
-    private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
-
-    private DataModelParser() {
-        // Not meant to be instantiated
-    }
-
-    public static Map<String, Object> parse(String src, TimeZone timeZone) throws DataModelParsingException {
-        if (!StringUtils.hasText(src)) {
-            return Collections.emptyMap();
-        }
-
-        Map<String, Object> dataModel = new LinkedHashMap<>();
-
-        String lastName = null;
-        int lastAssignmentStartEnd = 0;
-        final Matcher assignmentStart = ASSIGNMENT_START.matcher(src);
-        findAssignments: while (true) {
-            boolean hasNextAssignment = assignmentStart.find(lastAssignmentStartEnd);
-
-            if (lastName != null) {
-                String value = src.substring(
-                        lastAssignmentStartEnd, hasNextAssignment ? assignmentStart.start() : src.length())
-                        .trim();
-                final Object parsedValue;
-                try {
-                    parsedValue = parseValue(value, timeZone);
-                } catch (DataModelParsingException e) {
-                    throw new DataModelParsingException(
-                            "Failed to parse the value of \"" + lastName + "\":\n" + e.getMessage(), e.getCause());
-                }
-                dataModel.put(lastName, parsedValue);
-            }
-
-            if (lastName == null && (!hasNextAssignment || assignmentStart.start() != 0)) {
-                throw new DataModelParsingException(
-                        "The data model specification must start with an assignment (name=value).");
-            }
-
-            if (!hasNextAssignment) {
-                break findAssignments;
-            }
-
-            lastName = assignmentStart.group(1).trim();
-            lastAssignmentStartEnd = assignmentStart.end();
-        }
-
-        return dataModel;
-    }
-    
-    private static Object parseValue(String value, TimeZone timeZone) throws DataModelParsingException {
-        // Note: Because we fall back to interpret the input as a literal string value when it doesn't look like
-        // anything else (like a number, boolean, etc.), it's important to avoid misunderstandings, and throw exception
-        // in suspicious situations. The user can always quote the string value if we are "too smart". But he will
-        // be confused about the rules of FreeMarker if what he believes to be a non-string is misinterpreted by this
-        // parser as a string. Getting sometimes an error and then quoting the string is better than that.
-        
-        if (value.endsWith(";")) {  // Tolerate this habit of Java and JavaScript programmers
-            value = value.substring(value.length() - 1).trim();
-        }
-        
-        if (NUMBER_LIKE.matcher(value).matches()) {
-            try {
-                return new BigDecimal(value);
-            } catch (NumberFormatException e) {
-                // Maybe it's a ISO 8601 Date/time/datetime
-                CalendarFieldsToDateConverter calToDateConverter = new TrivialCalendarFieldsToDateConverter();
-                
-                DateParseException attemptedTemportalPExc = null;
-                String attemptedTemporalType = null;
-                final int dashIdx = value.indexOf('-');
-                final int colonIdx = value.indexOf(':');
-                if (value.indexOf('T') > 1 || (dashIdx > 1 && colonIdx > dashIdx)) {
-                    try {
-                        return new Timestamp(
-                                DateUtil.parseISO8601DateTime(value, timeZone, calToDateConverter).getTime());
-                    } catch (DateParseException pExc) {
-                        attemptedTemporalType = "date-time";
-                        attemptedTemportalPExc = pExc;
-                    }
-                } else if (dashIdx > 1) {
-                    try {
-                        return new java.sql.Date(
-                                DateUtil.parseISO8601Date(value, timeZone, calToDateConverter).getTime());
-                    } catch (DateParseException pExc) {
-                        attemptedTemporalType = "date";
-                        attemptedTemportalPExc = pExc;
-                    }
-                } else if (colonIdx > 1) { 
-                    try {
-                        return new Time(
-                                DateUtil.parseISO8601Time(value, timeZone, calToDateConverter).getTime());
-                    } catch (DateParseException pExc) {
-                        attemptedTemporalType = "time";
-                        attemptedTemportalPExc = pExc;
-                    }
-                }
-                if (attemptedTemportalPExc == null) {
-                    throw new DataModelParsingException("Malformed number: " + value, e);
-                } else {
-                    throw new DataModelParsingException(
-                            "Malformed ISO 8601 " + attemptedTemporalType + " (or malformed number): " + 
-                            attemptedTemportalPExc.getMessage(), e.getCause());
-                }
-            }
-        } else if (value.startsWith("\"")) {
-            try {
-                return JSON_MAPPER.readValue(value, String.class);
-            } catch (IOException e) {
-                throw new DataModelParsingException(
-                        "Malformed quoted string (using JSON syntax): " + getMessageWithoutLocation(e),
-                        e);
-            }
-        } else if (value.startsWith("\'")) {
-            throw new DataModelParsingException(
-                    "Malformed quoted string (using JSON syntax): Use \" character for quotation, not \' character.");
-        } else if (value.startsWith("[")) {
-            try {
-                return JSON_MAPPER.readValue(value, List.class);
-            } catch (IOException e) {
-                throw new DataModelParsingException(
-                        "Malformed list (using JSON syntax): " + getMessageWithoutLocation(e),
-                        e);
-            }
-        } else if (value.startsWith("{")) {
-            try {
-                return JSON_MAPPER.readValue(value, LinkedHashMap.class);
-            } catch (IOException e) {
-                throw new DataModelParsingException(
-                        "Malformed list (using JSON syntax): " + getMessageWithoutLocation(e),
-                        e);
-            }
-        } else if (value.startsWith("<")) {
-            try {
-                DocumentBuilder builder = NodeModel.getDocumentBuilderFactory().newDocumentBuilder();
-                ErrorHandler errorHandler = NodeModel.getErrorHandler();
-                if (errorHandler != null) builder.setErrorHandler(errorHandler);
-                final Document doc = builder.parse(new InputSource(new StringReader(value)));
-                NodeModel.simplify(doc);
-                return doc;
-            } catch (SAXException e) {
-                final String saxMsg = e.getMessage();
-                throw new DataModelParsingException("Malformed XML: " + (saxMsg != null ? saxMsg : e), e);
-            } catch (Exception e) {
-                throw new DataModelParsingException("XML parsing has failed with internal error: " + e, e);
-            }
-        } else if (value.equalsIgnoreCase(KEYWORD_TRUE)) {
-            checkKeywordCase(value, KEYWORD_TRUE);
-            return Boolean.TRUE;
-        } else if (value.equalsIgnoreCase(KEYWORD_FALSE)) {
-            checkKeywordCase(value, KEYWORD_FALSE);
-            return Boolean.FALSE;
-        } else if (value.equalsIgnoreCase(KEYWORD_NULL)) {
-            checkKeywordCase(value, KEYWORD_NULL);
-            return null;
-        } else if (value.equalsIgnoreCase(KEYWORD_NAN)) {
-            checkKeywordCase(value, KEYWORD_NAN);
-            return Double.NaN;
-        } else if (value.equalsIgnoreCase(KEYWORD_INFINITY)) {
-            checkKeywordCase(value, KEYWORD_INFINITY);
-            return Double.POSITIVE_INFINITY;
-        } else if (value.equalsIgnoreCase(KEYWORD_POSITIVE_INFINITY)) {
-            checkKeywordCase(value, KEYWORD_POSITIVE_INFINITY);
-            return Double.POSITIVE_INFINITY;
-        } else if (value.equalsIgnoreCase(KEYWORD_NEGATIVE_INFINITY)) {
-            checkKeywordCase(value, KEYWORD_NEGATIVE_INFINITY);
-            return Double.NEGATIVE_INFINITY;
-        } else if (value.length() == 0) {
-            throw new DataModelParsingException(
-                    "Empty value. (If you indeed wanted a 0 length string, quote it, like \"\".)");
-        } else {
-            return value;
-        }
-    }
-
-    private static String getMessageWithoutLocation(IOException e) {
-        return e instanceof JsonProcessingException
-                ? ((JsonProcessingException) e).getOriginalMessage()
-                : e.getMessage();
-    }
-
-    private static void checkKeywordCase(String inputKeyword, String correctKeyword) throws DataModelParsingException {
-        if (!correctKeyword.equals(inputKeyword)) {
-            throw new DataModelParsingException("Keywords are case sensitive; the correct form is: "
-                    + correctKeyword);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/util/DataModelParsingException.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/util/DataModelParsingException.java b/src/main/java/com/kenshoo/freemarker/util/DataModelParsingException.java
deleted file mode 100644
index 926e10b..0000000
--- a/src/main/java/com/kenshoo/freemarker/util/DataModelParsingException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.util;
-
-import java.util.TimeZone;
-
-/**
- * Thrown by {@link DataModelParser#parse(String, TimeZone)}.
- */
-public class DataModelParsingException extends Exception {
-
-    private static final long serialVersionUID = 1L;
-
-    public DataModelParsingException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public DataModelParsingException(String message) {
-        super(message);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/util/ExceptionUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/util/ExceptionUtils.java b/src/main/java/com/kenshoo/freemarker/util/ExceptionUtils.java
deleted file mode 100644
index 5c7548b..0000000
--- a/src/main/java/com/kenshoo/freemarker/util/ExceptionUtils.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.util;
-
-import freemarker.core.ParseException;
-import freemarker.template.TemplateException;
-
-public final class ExceptionUtils {
-
-    private ExceptionUtils() {
-        // Not meant to be instantiated
-    }
-
-    /**
-     * The error message (and sometimes also the class), and then the same with the cause exception, and so on. Doesn't
-     * contain the stack trace or other location information.
-     */
-    public static String getMessageWithCauses(final Throwable exc) {
-        StringBuilder sb = new StringBuilder();
-        
-        Throwable curExc = exc;
-        while (curExc != null) {
-            if (curExc != exc) {
-                sb.append("\n\nCaused by:\n");
-            }
-            String msg = curExc.getMessage();
-            if (msg == null || !(curExc instanceof TemplateException || curExc instanceof ParseException)) {
-                sb.append(curExc.getClass().getName()).append(": ");
-            }
-            sb.append(msg);
-            curExc = curExc.getCause();
-        }
-        return sb.toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/util/LengthLimitExceededException.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/util/LengthLimitExceededException.java b/src/main/java/com/kenshoo/freemarker/util/LengthLimitExceededException.java
deleted file mode 100644
index df25144..0000000
--- a/src/main/java/com/kenshoo/freemarker/util/LengthLimitExceededException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.util;
-
-import java.io.IOException;
-
-/**
- * Thrown by {@link LengthLimitedWriter}.
- */
-public class LengthLimitExceededException extends IOException {
-
-    private static final long serialVersionUID = 1L;
-    
-    public LengthLimitExceededException() {
-        super("The outout String length limit of the Writer was exceeded.");
-    }
-
-}


[5/5] incubator-freemarker-online-tester git commit: Renamed the package to org.apache.freemarker.onlinetester

Posted by dd...@apache.org.
Renamed the package to org.apache.freemarker.onlinetester

Merge commit 'refs/pull/6/head' of https://github.com/apache/incubator-freemarker-online-tester


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/commit/808bd536
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/tree/808bd536
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/diff/808bd536

Branch: refs/heads/master
Commit: 808bd536597f47f2a3c85e5e77f1129eda218df6
Parents: 7b46afe 2f0c042
Author: ddekany <dd...@apache.org>
Authored: Sun Apr 9 10:14:19 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Sun Apr 9 10:15:21 2017 +0200

----------------------------------------------------------------------
 README.md                                       |  36 +-
 build.gradle                                    |   4 +-
 intellij.gradle                                 |   2 +-
 .../dropwizard/ApplicationStartup.java          |  42 ---
 .../healthchecks/MyProjectHealthCheck.java      |  37 --
 .../com/kenshoo/freemarker/model/ErrorCode.java |  25 --
 .../kenshoo/freemarker/model/ErrorResponse.java |  30 --
 .../freemarker/model/ExecuteRequest.java        |  78 ----
 .../freemarker/model/ExecuteResourceField.java  |  57 ---
 .../model/ExecuteResourceProblem.java           |  53 ---
 .../freemarker/model/ExecuteResponse.java       |  63 ----
 .../freemarker/model/SelectionOption.java       |  88 -----
 .../FreeMarkerOnlineExecuteResource.java        | 220 -----------
 .../resources/FreeMarkerOnlineResource.java     |  63 ----
 .../services/AllowedSettingValuesMaps.java      | 115 ------
 .../freemarker/services/FreeMarkerService.java  | 364 -------------------
 .../services/FreeMarkerServiceException.java    |  38 --
 .../services/FreeMarkerServiceResponse.java     |  68 ----
 .../freemarker/util/DataModelParser.java        | 268 --------------
 .../util/DataModelParsingException.java         |  39 --
 .../kenshoo/freemarker/util/ExceptionUtils.java |  53 ---
 .../util/LengthLimitExceededException.java      |  35 --
 .../freemarker/util/LengthLimitedWriter.java    |  87 -----
 .../freemarker/view/FreeMarkerOnlineView.java   | 157 --------
 .../dropwizard/ApplicationStartup.java          |  42 +++
 .../healthchecks/MyProjectHealthCheck.java      |  37 ++
 .../onlinetester/model/ErrorCode.java           |  25 ++
 .../onlinetester/model/ErrorResponse.java       |  30 ++
 .../onlinetester/model/ExecuteRequest.java      |  78 ++++
 .../model/ExecuteResourceField.java             |  57 +++
 .../model/ExecuteResourceProblem.java           |  53 +++
 .../onlinetester/model/ExecuteResponse.java     |  63 ++++
 .../onlinetester/model/SelectionOption.java     |  88 +++++
 .../FreeMarkerOnlineExecuteResource.java        | 220 +++++++++++
 .../resources/FreeMarkerOnlineResource.java     |  63 ++++
 .../services/AllowedSettingValuesMaps.java      | 115 ++++++
 .../services/FreeMarkerService.java             | 364 +++++++++++++++++++
 .../services/FreeMarkerServiceException.java    |  38 ++
 .../services/FreeMarkerServiceResponse.java     |  68 ++++
 .../onlinetester/util/DataModelParser.java      | 268 ++++++++++++++
 .../util/DataModelParsingException.java         |  39 ++
 .../onlinetester/util/ExceptionUtils.java       |  53 +++
 .../util/LengthLimitExceededException.java      |  35 ++
 .../onlinetester/util/LengthLimitedWriter.java  |  87 +++++
 .../onlinetester/view/FreeMarkerOnlineView.java | 157 ++++++++
 src/main/resources/spring/bootstrap-context.xml |   2 +-
 .../platform/DropWizardServiceTest.java         |  36 --
 .../platform/YamlPropertiesPersister.java       |  91 -----
 .../FreeMarkerOnlineExecuteResourceTest.java    | 159 --------
 .../resources/FreeMarkerOnlineResourceTest.java |  70 ----
 .../FreeMarkerServiceResponseBuilderTest.java   |  61 ----
 .../services/FreeMarkerServiceTest.java         | 308 ----------------
 .../freemarker/util/DataModelParserTest.java    | 281 --------------
 .../util/LengthLimitedWriterTest.java           |  77 ----
 .../view/FreeMarkerOnlineViewTest.java          |  69 ----
 .../platform/DropWizardServiceTest.java         |  39 ++
 .../platform/YamlPropertiesPersister.java       |  91 +++++
 .../FreeMarkerOnlineExecuteResourceTest.java    | 159 ++++++++
 .../resources/FreeMarkerOnlineResourceTest.java |  70 ++++
 .../FreeMarkerServiceResponseBuilderTest.java   |  61 ++++
 .../services/FreeMarkerServiceTest.java         | 308 ++++++++++++++++
 .../onlinetester/util/DataModelParserTest.java  | 281 ++++++++++++++
 .../util/LengthLimitedWriterTest.java           |  77 ++++
 .../view/FreeMarkerOnlineViewTest.java          |  69 ++++
 64 files changed, 3157 insertions(+), 3154 deletions(-)
----------------------------------------------------------------------



[3/5] incubator-freemarker-online-tester git commit: renamed the package name to org/apache/freemarker/onlinetester

Posted by dd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/util/LengthLimitedWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/util/LengthLimitedWriter.java b/src/main/java/com/kenshoo/freemarker/util/LengthLimitedWriter.java
deleted file mode 100644
index abf3edc..0000000
--- a/src/main/java/com/kenshoo/freemarker/util/LengthLimitedWriter.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.util;
-
-import java.io.FilterWriter;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-
-/**
- * A {@link StringWriter} that limits its buffer size, and throws {@link LengthLimitExceededException} when that's
- * exceeded.
- */
-public class LengthLimitedWriter extends FilterWriter {
-    
-    private int lengthLeft;
-
-    public LengthLimitedWriter(Writer writer, int lengthLimit) {
-        super(writer);
-        this.lengthLeft = lengthLimit;
-    }
-
-    @Override
-    public void write(int c) throws IOException {
-        if (lengthLeft < 1) {
-            throw new LengthLimitExceededException();
-        }
-        
-        super.write(c);
-        
-        lengthLeft--;
-    }
-
-    @Override
-    public void write(char[] cbuf, int off, int len) throws IOException {
-        final boolean lengthExceeded;
-        if (lengthLeft < len) {
-            len = lengthLeft;
-            lengthExceeded = true;
-        } else {
-            lengthExceeded = false;
-        }
-        
-        super.write(cbuf, off, len);
-        lengthLeft -= len;
-        
-        if (lengthExceeded) {
-            throw new LengthLimitExceededException();
-        }
-    }
-
-    @Override
-    public void write(String str, int off, int len) throws IOException {
-        final boolean lengthExceeded;
-        if (lengthLeft < len) {
-            len = lengthLeft;
-            lengthExceeded = true;
-        } else {
-            lengthExceeded = false;
-        }
-        
-        super.write(str, off, len);
-        lengthLeft -= len;
-        
-        if (lengthExceeded) {
-            throw new LengthLimitExceededException();
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/com/kenshoo/freemarker/view/FreeMarkerOnlineView.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/kenshoo/freemarker/view/FreeMarkerOnlineView.java b/src/main/java/com/kenshoo/freemarker/view/FreeMarkerOnlineView.java
deleted file mode 100644
index fb256f1..0000000
--- a/src/main/java/com/kenshoo/freemarker/view/FreeMarkerOnlineView.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.view;
-
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.commons.lang3.StringUtils;
-
-import com.kenshoo.freemarker.model.SelectionOption;
-import com.kenshoo.freemarker.services.AllowedSettingValuesMaps;
-import com.yammer.dropwizard.views.View;
-
-import freemarker.template.Configuration;
-
-public class FreeMarkerOnlineView extends View {
-
-    private static final List<SelectionOption> LOCALE_SELECTION_OPTIONS = toLocaleSelectionOptions(AllowedSettingValuesMaps.LOCALE_MAP);
-    private static final List<SelectionOption> TIME_ZONE_SELECTION_OPTIONS = toSelectionOptions(AllowedSettingValuesMaps.TIME_ZONE_MAP);
-    private static final List<SelectionOption> OUTPUT_FORMAT_SELECTION_OPTIONS = toSelectionOptions(AllowedSettingValuesMaps.OUTPUT_FORMAT_MAP);
-    
-    private String template = "";
-    private String dataModel = "";
-    private String outputFormat = AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT_KEY;
-    private String locale = AllowedSettingValuesMaps.DEFAULT_LOCALE_KEY;
-    private String timeZone = AllowedSettingValuesMaps.DEFAULT_TIME_ZONE_KEY;
-    
-    private boolean execute;
-    
-    private static List<SelectionOption> toSelectionOptions(Map<String, ?> settingValueMap) {
-        ArrayList<SelectionOption> selectionOptions = new ArrayList<SelectionOption>(settingValueMap.size());
-        for (String key : settingValueMap.keySet()) {
-            selectionOptions.add(new SelectionOption(key, truncate(key, 25)));
-        }
-        Collections.sort(selectionOptions);
-        return selectionOptions;
-    }
-    
-    private static List<SelectionOption> toLocaleSelectionOptions(Map<String, Locale> localeMap) {
-        ArrayList<SelectionOption> selectionOptions = new ArrayList<SelectionOption>(localeMap.size());
-        for (Map.Entry<String, Locale> ent : localeMap.entrySet()) {
-            Locale locale = ent.getValue();
-            selectionOptions.add(
-                    new SelectionOption(ent.getKey(),
-                    truncate(locale.getDisplayName(Locale.US), 18) + "; " + locale.toString()));
-        }
-        Collections.sort(selectionOptions);
-        return selectionOptions;
-    }
-    
-    private static String truncate(String s, int maxLength) {
-        if (s == null) {
-            return null;
-        }
-        return s.length() <= maxLength ? s : s.substring(0, Math.max(maxLength - 3, 0)) + "[...]";
-    }    
-
-    /**
-     *
-     * @param template
-     * @param dataModel
-     * @param execute set to true if the execution should be triggered on page load.
-     */
-    public FreeMarkerOnlineView() {
-        super("/view/freemarker-online.ftl", Charset.forName("utf-8"));
-    }
-
-    public String getTemplate() {
-        return template;
-    }
-
-    public void setTemplate(String template) {
-        this.template = withDefault(template, "");
-    }
-
-    public String getDataModel() {
-        return dataModel;
-    }
-
-    public void setDataModel(String dataModel) {
-        this.dataModel = withDefault(dataModel, "");
-    }
-
-    public String getFreeMarkerVersion() {
-        return Configuration.getVersion().toString();
-    }
-    
-    public List<SelectionOption> getOutputFormats() {
-        return OUTPUT_FORMAT_SELECTION_OPTIONS;
-    }
-
-    public List<SelectionOption> getLocales() {
-        return LOCALE_SELECTION_OPTIONS;
-    }
-
-    public List<SelectionOption> getTimeZones() {
-        return TIME_ZONE_SELECTION_OPTIONS;
-    }
-
-    public String getOutputFormat() {
-        return outputFormat;
-    }
-
-    public void setOutputFormat(String outputFormat) {
-        this.outputFormat = withDefault(outputFormat, AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT_KEY);
-    }
-
-    public String getLocale() {
-        return locale;
-    }
-
-    public void setLocale(String locale) {
-        this.locale = withDefault(locale, AllowedSettingValuesMaps.DEFAULT_LOCALE_KEY);
-    }
-
-    public String getTimeZone() {
-        return timeZone;
-    }
-
-    public void setTimeZone(String timeZone) {
-        this.timeZone = withDefault(timeZone, AllowedSettingValuesMaps.DEFAULT_TIME_ZONE_KEY);
-    }
-    
-    public boolean isExecute() {
-        return execute;
-    }
-
-    public void setExecute(boolean executeImmediately) {
-        this.execute = executeImmediately;
-    }
-
-    private static String withDefault(String value, String defaultValue) {
-        return !StringUtils.isBlank(value) ? value : defaultValue;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/dropwizard/ApplicationStartup.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/dropwizard/ApplicationStartup.java b/src/main/java/org/apache/freemarker/onlinetester/dropwizard/ApplicationStartup.java
new file mode 100644
index 0000000..4caf07c
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/dropwizard/ApplicationStartup.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.dropwizard;
+
+import com.berico.fallwizard.SpringConfiguration;
+import com.berico.fallwizard.SpringService;
+import com.yammer.dropwizard.assets.AssetsBundle;
+import com.yammer.dropwizard.config.Bootstrap;
+import com.yammer.dropwizard.views.ViewBundle;
+
+public class ApplicationStartup extends SpringService<SpringConfiguration> {
+
+    public static void main(String[] args) throws Exception {
+        new ApplicationStartup().run(args);
+    }
+
+    @Override
+    public void initialize(Bootstrap<SpringConfiguration> bootstrap) {
+        bootstrap.setName("freemarker-online");
+        bootstrap.addBundle(new ViewBundle());
+        bootstrap.addBundle(new AssetsBundle("/assets/css", "/css"));
+        bootstrap.addBundle(new AssetsBundle("/assets/js", "/js"));
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/healthchecks/MyProjectHealthCheck.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/healthchecks/MyProjectHealthCheck.java b/src/main/java/org/apache/freemarker/onlinetester/healthchecks/MyProjectHealthCheck.java
new file mode 100644
index 0000000..192fa46
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/healthchecks/MyProjectHealthCheck.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.healthchecks;
+
+import com.yammer.metrics.core.HealthCheck;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MyProjectHealthCheck extends HealthCheck {
+
+    // note that this is due to the default spring CTR
+    public MyProjectHealthCheck() {
+        super("MyProjectHealthCheck");
+    }
+
+    @Override
+    protected Result check() throws Exception {
+        return Result.healthy(); // we're always healthy!
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/model/ErrorCode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/model/ErrorCode.java b/src/main/java/org/apache/freemarker/onlinetester/model/ErrorCode.java
new file mode 100644
index 0000000..c983e87
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/model/ErrorCode.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.model;
+
+public enum ErrorCode {
+    FREEMARKER_SERVICE_TIMEOUT
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/model/ErrorResponse.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/model/ErrorResponse.java b/src/main/java/org/apache/freemarker/onlinetester/model/ErrorResponse.java
new file mode 100644
index 0000000..68ddf69
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/model/ErrorResponse.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.model;
+
+public class ErrorResponse {
+    private ErrorCode errorCode;
+    private String errorDescription;
+
+    public ErrorResponse(ErrorCode errorCode, String errorDescription) {
+        this.errorCode = errorCode;
+        this.errorDescription = errorDescription;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteRequest.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteRequest.java b/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteRequest.java
new file mode 100644
index 0000000..a206131
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteRequest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ package org.apache.freemarker.onlinetester.model;
+
+
+public class ExecuteRequest {
+    private String template;
+    private String dataModel;
+    private String outputFormat;
+    private String locale;
+    private String timeZone;
+
+    public ExecuteRequest() {
+    }
+
+    public ExecuteRequest(String template, String dataModel) {
+        this.template = template;
+        this.dataModel = dataModel;
+    }
+
+    public String getDataModel() {
+        return dataModel;
+    }
+
+    public void setDataModel(String dataModel) {
+        this.dataModel = dataModel;
+    }
+
+    public String getTemplate() {
+
+        return template;
+    }
+
+    public void setTemplate(String template) {
+        this.template = template;
+    }
+
+    public String getOutputFormat() {
+        return outputFormat;
+    }
+
+    public void setOutputFormat(String outputFormat) {
+        this.outputFormat = outputFormat;
+    }
+
+    public String getLocale() {
+        return locale;
+    }
+
+    public void setLocale(String locale) {
+        this.locale = locale;
+    }
+
+    public String getTimeZone() {
+        return timeZone;
+    }
+
+    public void setTimeZone(String timeZone) {
+        this.timeZone = timeZone;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResourceField.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResourceField.java b/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResourceField.java
new file mode 100644
index 0000000..71ad454
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResourceField.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public enum ExecuteResourceField {
+    DATA_MODEL("dataModel"),
+    TEMPLATE("template"),
+    OUTPUT_FORMAT("outputFormat"),
+    LOCALE("locale"),
+    TIME_ZONE("timeZone");
+    
+    private final String fieldName;
+    
+    private ExecuteResourceField(String filedName) {
+        this.fieldName = filedName;
+    }
+    
+    public String toString() {
+        return getFieldName();
+    }
+    
+    @JsonValue
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    @JsonCreator
+    public static ExecuteResourceField fromEnumString(String val) {
+        for(ExecuteResourceField field : values()) {
+            if(field.getFieldName().equals(val)) {
+                return field;
+            }
+        }
+        throw new IllegalArgumentException("Invalid string value passed: " + val);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResourceProblem.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResourceProblem.java b/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResourceProblem.java
new file mode 100644
index 0000000..3c69d43
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResourceProblem.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.model;
+
+public class ExecuteResourceProblem {
+    
+    private ExecuteResourceField field;
+    private String message;
+    
+    // Needed for JSON unmarshalling
+    public ExecuteResourceProblem() {
+        //
+    }
+    
+    public ExecuteResourceProblem(ExecuteResourceField field, String message) {
+        this.field = field;
+        this.message = message;
+    }
+
+    public ExecuteResourceField getField() {
+        return field;
+    }
+
+    public void setField(ExecuteResourceField field) {
+        this.field = field;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResponse.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResponse.java b/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResponse.java
new file mode 100644
index 0000000..41c33f1
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/model/ExecuteResponse.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.model;
+
+import java.util.List;
+
+public class ExecuteResponse {
+    private String result;
+    private List<ExecuteResourceProblem> problems;
+    private boolean truncatedResult;
+
+    public ExecuteResponse(String result, List<ExecuteResourceProblem> problems, boolean truncatedResult) {
+        this.result = result;
+        this.problems = problems;
+        this.truncatedResult = truncatedResult;
+    }
+
+    public ExecuteResponse() {
+
+    }
+
+    public List<ExecuteResourceProblem> getProblems() {
+        return problems;
+    }
+
+    public void setProblems(List<ExecuteResourceProblem> problems) {
+        this.problems = problems;
+    }
+
+    public boolean isTruncatedResult() {
+        return truncatedResult;
+    }
+
+    public void setTruncatedResult(boolean truncatedResult) {
+        this.truncatedResult = truncatedResult;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    public void setResult(String result) {
+        this.result = result;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/model/SelectionOption.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/model/SelectionOption.java b/src/main/java/org/apache/freemarker/onlinetester/model/SelectionOption.java
new file mode 100644
index 0000000..d7dfe49
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/model/SelectionOption.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.model;
+
+public class SelectionOption implements Comparable<SelectionOption> {
+    
+    private final String value;
+    private final String label;
+    
+    public String getValue() {
+        return value;
+    }
+    
+    public String getLabel() {
+        return label;
+    }
+    
+    public SelectionOption(String value, String label) {
+        this.value = value;
+        this.label = label;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((label == null) ? 0 : label.hashCode());
+        result = prime * result + ((value == null) ? 0 : value.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        SelectionOption other = (SelectionOption) obj;
+        if (label == null) {
+            if (other.label != null) {
+                return false;
+            }
+        } else if (!label.equals(other.label)) {
+            return false;
+        }
+        if (value == null) {
+            if (other.value != null) {
+                return false;
+            }
+        } else if (!value.equals(other.value)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int compareTo(SelectionOption o) {
+        int r = label.compareTo(o.label);
+        if (r != 0) {
+            return r;
+        }
+        
+        return value.compareTo(o.value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineExecuteResource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineExecuteResource.java b/src/main/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineExecuteResource.java
new file mode 100644
index 0000000..c850720
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineExecuteResource.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.resources;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.concurrent.RejectedExecutionException;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.freemarker.onlinetester.model.ErrorCode;
+import org.apache.freemarker.onlinetester.model.ExecuteResourceProblem;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import org.apache.freemarker.onlinetester.model.ErrorResponse;
+import org.apache.freemarker.onlinetester.model.ExecuteRequest;
+import org.apache.freemarker.onlinetester.model.ExecuteResourceField;
+import org.apache.freemarker.onlinetester.model.ExecuteResponse;
+import org.apache.freemarker.onlinetester.services.AllowedSettingValuesMaps;
+import org.apache.freemarker.onlinetester.services.FreeMarkerService;
+import org.apache.freemarker.onlinetester.services.FreeMarkerServiceResponse;
+import org.apache.freemarker.onlinetester.util.DataModelParser;
+import org.apache.freemarker.onlinetester.util.DataModelParsingException;
+import org.apache.freemarker.onlinetester.util.ExceptionUtils;
+
+import freemarker.core.OutputFormat;
+
+@Path("/api/execute")
+@Component
+public class FreeMarkerOnlineExecuteResource {
+    private static final int MAX_TEMPLATE_INPUT_LENGTH = 10000;
+
+    private static final int MAX_DATA_MODEL_INPUT_LENGTH = 10000;
+
+    private static final String MAX_TEMPLATE_INPUT_LENGTH_EXCEEDED_ERROR_MESSAGE
+            = "The template length has exceeded the {0} character limit set for this service.";
+
+    private static final String MAX_DATA_MODEL_INPUT_LENGTH_EXCEEDED_ERROR_MESSAGE
+            = "The data model length has exceeded the {0} character limit set for this service.";
+
+    private static final String UNKNOWN_OUTPUT_FORMAT_ERROR_MESSAGE = "Unknown output format: {0}";
+    private static final String UNKNOWN_LOCALE_ERROR_MESSAGE = "Unknown locale: {0}";
+    private static final String UNKNOWN_TIME_ZONE_ERROR_MESSAGE = "Unknown time zone: {0}";
+
+    private static final String SERVICE_OVERBURDEN_ERROR_MESSAGE
+            = "Sorry, the service is overburden and couldn't handle your request now. Try again later.";
+
+    static final String DATA_MODEL_ERROR_MESSAGE_HEADING = "Failed to parse data model:";
+    static final String DATA_MODEL_ERROR_MESSAGE_FOOTER = "Note: This is NOT a FreeMarker error message. "
+            + "The data model syntax is specific to this online service.";
+
+    @Autowired
+    private FreeMarkerService freeMarkerService;
+
+    @POST
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response formResult(
+            ExecuteRequest req) {
+        ExecuteResponse resp = new ExecuteResponse();
+        
+        if (StringUtils.isBlank(req.getTemplate()) && StringUtils.isBlank(req.getDataModel())) {
+            return Response.status(400).entity("Empty Template & data").build();
+        }
+
+        List<ExecuteResourceProblem> problems = new ArrayList<ExecuteResourceProblem>();
+        
+        String template = getTemplate(req, problems);
+        Map<String, Object> dataModel = getDataModel(req, problems);
+        OutputFormat outputFormat = getOutputFormat(req, problems);
+        Locale locale = getLocale(req, problems);
+        TimeZone timeZone = getTimeZone(req, problems);
+        
+        if (!problems.isEmpty()) {
+            resp.setProblems(problems);
+            return buildFreeMarkerResponse(resp);
+        }
+        
+        FreeMarkerServiceResponse freeMarkerServiceResponse;
+        try {
+            freeMarkerServiceResponse = freeMarkerService.calculateTemplateOutput(
+                    template, dataModel,
+                    outputFormat, locale, timeZone);
+        } catch (RejectedExecutionException e) {
+            String error = SERVICE_OVERBURDEN_ERROR_MESSAGE;
+            return Response.serverError().entity(new ErrorResponse(ErrorCode.FREEMARKER_SERVICE_TIMEOUT, error)).build();
+        }
+        if (!freeMarkerServiceResponse.isSuccesful()){
+            Throwable failureReason = freeMarkerServiceResponse.getFailureReason();
+            String error = ExceptionUtils.getMessageWithCauses(failureReason);
+            problems.add(new ExecuteResourceProblem(ExecuteResourceField.TEMPLATE, error));
+            resp.setProblems(problems);
+            return buildFreeMarkerResponse(resp);
+        }
+
+        String result = freeMarkerServiceResponse.getTemplateOutput();
+        resp.setResult(result);
+        resp.setTruncatedResult(freeMarkerServiceResponse.isTemplateOutputTruncated());
+        return buildFreeMarkerResponse(resp);
+    }
+
+    private String getTemplate(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
+        String template = req.getTemplate();
+        
+        if (template.length() > MAX_TEMPLATE_INPUT_LENGTH) {
+            String error = formatMessage(MAX_TEMPLATE_INPUT_LENGTH_EXCEEDED_ERROR_MESSAGE, MAX_TEMPLATE_INPUT_LENGTH);
+            problems.add(new ExecuteResourceProblem(ExecuteResourceField.TEMPLATE, error));
+            return null;
+        }
+        
+        return template;
+    }
+
+    private Map<String, Object> getDataModel(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
+        String dataModel = req.getDataModel();
+        
+        if (dataModel.length() > MAX_DATA_MODEL_INPUT_LENGTH) {
+            String error = formatMessage(
+                    MAX_DATA_MODEL_INPUT_LENGTH_EXCEEDED_ERROR_MESSAGE, MAX_DATA_MODEL_INPUT_LENGTH);
+            problems.add(new ExecuteResourceProblem(ExecuteResourceField.DATA_MODEL, error));
+            return null;
+        }
+        
+        try {
+            return DataModelParser.parse(dataModel, freeMarkerService.getFreeMarkerTimeZone());
+        } catch (DataModelParsingException e) {
+            problems.add(new ExecuteResourceProblem(ExecuteResourceField.DATA_MODEL, decorateResultText(e.getMessage())));
+            return null;
+        }
+    }
+
+    private OutputFormat getOutputFormat(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
+        String outputFormatStr = req.getOutputFormat();
+        
+        if (StringUtils.isBlank(outputFormatStr)) {
+            return AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT;
+        }
+    
+        OutputFormat outputFormat = AllowedSettingValuesMaps.OUTPUT_FORMAT_MAP.get(outputFormatStr);
+        if (outputFormat == null) {
+            problems.add(new ExecuteResourceProblem(
+                    ExecuteResourceField.OUTPUT_FORMAT,
+                    formatMessage(UNKNOWN_OUTPUT_FORMAT_ERROR_MESSAGE, outputFormatStr)));
+        }
+        return outputFormat;
+    }
+
+    private Locale getLocale(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
+        String localeStr = req.getLocale();
+        
+        if (StringUtils.isBlank(localeStr)) {
+            return AllowedSettingValuesMaps.DEFAULT_LOCALE;
+        }
+        
+        Locale locale = AllowedSettingValuesMaps.LOCALE_MAP.get(localeStr);
+        if (locale == null) {
+            problems.add(new ExecuteResourceProblem(
+                    ExecuteResourceField.LOCALE,
+                    formatMessage(UNKNOWN_LOCALE_ERROR_MESSAGE, localeStr)));
+        }
+        return locale;
+    }
+
+    private TimeZone getTimeZone(ExecuteRequest req, List<ExecuteResourceProblem> problems) {
+        String timeZoneStr = req.getTimeZone();
+        
+        if (StringUtils.isBlank(timeZoneStr)) {
+            return AllowedSettingValuesMaps.DEFAULT_TIME_ZONE;
+        }
+        
+        TimeZone timeZone = AllowedSettingValuesMaps.TIME_ZONE_MAP.get(timeZoneStr);
+        if (timeZone == null) {
+            problems.add(new ExecuteResourceProblem(
+                    ExecuteResourceField.TIME_ZONE,
+                    formatMessage(UNKNOWN_TIME_ZONE_ERROR_MESSAGE, timeZoneStr)));
+        }
+        return timeZone;
+    }
+
+    private Response buildFreeMarkerResponse(ExecuteResponse executeResponse){
+        return Response.ok().entity(executeResponse).build();
+    }
+    
+    private String decorateResultText(String resultText) {
+        return DATA_MODEL_ERROR_MESSAGE_HEADING + "\n\n" + resultText + "\n\n" + DATA_MODEL_ERROR_MESSAGE_FOOTER;
+    }
+    
+    private String formatMessage(String key, Object... params) {
+        return new MessageFormat(key, Locale.US).format(params);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineResource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineResource.java b/src/main/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineResource.java
new file mode 100644
index 0000000..ebf82a1
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineResource.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.resources;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.springframework.stereotype.Component;
+
+import org.apache.freemarker.onlinetester.view.FreeMarkerOnlineView;
+
+@Path("/")
+@Component
+public class FreeMarkerOnlineResource {
+
+    @GET
+    @Produces(MediaType.TEXT_HTML)
+    public FreeMarkerOnlineView blankForm() {
+        return new FreeMarkerOnlineView();
+    }
+
+    @POST
+    @Produces(MediaType.TEXT_HTML)
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    public FreeMarkerOnlineView formResult(
+            @FormParam("template") String template,
+            @FormParam("dataModel") String dataModel,
+            @FormParam("outputFormat") String outputFormat,
+            @FormParam("locale") String locale,
+            @FormParam("timeZone") String timeZone) {
+        FreeMarkerOnlineView view = new FreeMarkerOnlineView();
+        view.setTemplate(template);
+        view.setDataModel(dataModel);
+        view.setOutputFormat(outputFormat);
+        view.setLocale(locale);
+        view.setTimeZone(timeZone);
+        view.setExecute(true);
+        return view;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/services/AllowedSettingValuesMaps.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/services/AllowedSettingValuesMaps.java b/src/main/java/org/apache/freemarker/onlinetester/services/AllowedSettingValuesMaps.java
new file mode 100644
index 0000000..e3111aa
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/services/AllowedSettingValuesMaps.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.services;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import freemarker.core.HTMLOutputFormat;
+import freemarker.core.OutputFormat;
+import freemarker.core.PlainTextOutputFormat;
+import freemarker.core.RTFOutputFormat;
+import freemarker.core.UndefinedOutputFormat;
+import freemarker.core.XHTMLOutputFormat;
+import freemarker.core.XMLOutputFormat;
+
+/**
+ * Maps of the setting values the caller can chose from (these are the value shown in a dropdown on the UI).
+ */
+public class AllowedSettingValuesMaps {
+
+    public static final OutputFormat DEFAULT_OUTPUT_FORMAT = UndefinedOutputFormat.INSTANCE;
+    public static final String DEFAULT_OUTPUT_FORMAT_KEY = DEFAULT_OUTPUT_FORMAT.getName();
+    public static final Map<String, OutputFormat> OUTPUT_FORMAT_MAP;
+    static {
+        Map<String, OutputFormat> map = new HashMap<String, OutputFormat>();
+        
+        addOutputFormatToMap(map, UndefinedOutputFormat.INSTANCE);
+        addOutputFormatToMap(map, HTMLOutputFormat.INSTANCE);
+        addOutputFormatToMap(map, XMLOutputFormat.INSTANCE);
+        addOutputFormatToMap(map, XHTMLOutputFormat.INSTANCE);
+        addOutputFormatToMap(map, RTFOutputFormat.INSTANCE);
+        addOutputFormatToMap(map, PlainTextOutputFormat.INSTANCE);
+        
+        OUTPUT_FORMAT_MAP = Collections.unmodifiableMap(map);
+    }
+    
+    private static void addOutputFormatToMap(Map<String, OutputFormat> map, OutputFormat outputFormat) {
+        map.put(outputFormat.getName(), outputFormat);
+    }
+
+    public static final Locale DEFAULT_LOCALE = Locale.US;
+    public static final String DEFAULT_LOCALE_KEY = DEFAULT_LOCALE.toString();
+    public static final Map<String, Locale> LOCALE_MAP;
+    static {
+        List<Locale> availableLocales = new ArrayList<Locale>(Arrays.asList(Locale.getAvailableLocales()));
+        
+        for (Iterator<Locale> iterator = availableLocales.iterator(); iterator.hasNext();) {
+            Locale locale = iterator.next();
+            // Don't bloat the list with "variants"
+            if (!StringUtils.isBlank(locale.getVariant())) {
+                iterator.remove();
+            }
+        }
+        
+        if (!availableLocales.contains(DEFAULT_LOCALE)) {
+            availableLocales.add(DEFAULT_LOCALE);
+        }
+        
+        Map<String, Locale> map = new HashMap<String, Locale>();
+        for (Locale locale : availableLocales) {
+            map.put(locale.toString(), locale);
+        }
+        
+        LOCALE_MAP = Collections.unmodifiableMap(map);
+    }
+
+    public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("America/Los_Angeles");
+    
+    public static final String DEFAULT_TIME_ZONE_KEY;
+    
+    public static final Map<String, TimeZone> TIME_ZONE_MAP;
+    static {
+        String[] availableIDs = TimeZone.getAvailableIDs();
+        
+        DEFAULT_TIME_ZONE_KEY = AllowedSettingValuesMaps.DEFAULT_TIME_ZONE.getID();
+        if (!ArrayUtils.contains(availableIDs, DEFAULT_TIME_ZONE_KEY)) {
+            ArrayUtils.add(availableIDs, DEFAULT_TIME_ZONE_KEY);
+        }
+        
+        Map<String, TimeZone> map = new HashMap<String, TimeZone>();
+        for (String timeZoneId : availableIDs) {
+            map.put(timeZoneId, TimeZone.getTimeZone(timeZoneId));
+        }
+        
+        TIME_ZONE_MAP = Collections.unmodifiableMap(map);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerService.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerService.java b/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerService.java
new file mode 100644
index 0000000..4487abe
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerService.java
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.services;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.TimeZone;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.freemarker.onlinetester.util.LengthLimitedWriter;
+import org.eclipse.jetty.util.BlockingArrayQueue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import org.apache.freemarker.onlinetester.util.LengthLimitExceededException;
+
+import freemarker.core.FreeMarkerInternalsAccessor;
+import freemarker.core.OutputFormat;
+import freemarker.core.ParseException;
+import freemarker.core.TemplateClassResolver;
+import freemarker.core.TemplateConfiguration;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateExceptionHandler;
+
+@Service
+public class FreeMarkerService {
+
+    private static final int DEFAULT_MAX_OUTPUT_LENGTH = 100000;
+    private static final int DEFAULT_MAX_THREADS = Math.max(2,
+            (int) Math.round(Runtime.getRuntime().availableProcessors() * 3.0 / 4));
+    /** Not implemented yet, will need 2.3.22, even then a _CoreAPI call. */
+    private static final long DEFAULT_MAX_TEMPLATE_EXECUTION_TIME = 2000;
+    private static final int MIN_DEFAULT_MAX_QUEUE_LENGTH = 2;
+    private static final int MAX_DEFAULT_MAX_QUEUE_LENGTH_MILLISECONDS = 30000;
+    private static final long THREAD_KEEP_ALIVE_TIME = 4 * 1000;
+    private static final long ABORTION_LOOP_TIME_LIMIT = 5000;
+    private static final long ABORTION_LOOP_INTERRUPTION_DISTANCE = 50;
+    
+    private static final String MAX_OUTPUT_LENGTH_EXCEEDED_TERMINATION = "\n----------\n"
+            + "Aborted template processing, as the output length has exceeded the {0} character limit set for "
+            + "this service.";
+    
+    private static final Logger logger = LoggerFactory.getLogger(FreeMarkerService.class);
+
+    private final Configuration freeMarkerConfig;
+    
+    private ExecutorService templateExecutor;
+    
+    private int maxOutputLength = DEFAULT_MAX_OUTPUT_LENGTH;
+    
+    private int maxThreads = DEFAULT_MAX_THREADS;
+    private Integer maxQueueLength;
+    private long maxTemplateExecutionTime = DEFAULT_MAX_TEMPLATE_EXECUTION_TIME;
+
+    public FreeMarkerService() {
+        freeMarkerConfig = new Configuration(Configuration.getVersion());
+        freeMarkerConfig.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
+        freeMarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+        freeMarkerConfig.setLogTemplateExceptions(false);
+        freeMarkerConfig.setLocale(AllowedSettingValuesMaps.DEFAULT_LOCALE);
+        freeMarkerConfig.setTimeZone(AllowedSettingValuesMaps.DEFAULT_TIME_ZONE);
+        freeMarkerConfig.setOutputFormat(AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT);
+        freeMarkerConfig.setOutputEncoding("UTF-8");
+    }
+    
+    /**
+     * @param templateSourceCode
+     *            The FTL to execute; not {@code null}.
+     * @param dataModel
+     *            The FreeMarker data-model to execute the template with; maybe {@code null}.
+     * @param outputFormat
+     *            The output format to execute the template with; maybe {@code null}.
+     * @param locale
+     *            The locale to execute the template with; maybe {@code null}.
+     * @param timeZone
+     *            The time zone to execute the template with; maybe {@code null}.
+     * 
+     * @return The result of the template parsing and evaluation. The method won't throw exception if that fails due to
+     *         errors in the template provided, instead it indicates this fact in the response object. That's because
+     *         this is a service for trying out the template language, so such errors are part of the normal operation.
+     * 
+     * @throws RejectedExecutionException
+     *             If the service is overburden and thus doing the calculation was rejected.
+     * @throws FreeMarkerServiceException
+     *             If the calculation fails from a reason that's not a mistake in the template and doesn't fit the
+     *             meaning of {@link RejectedExecutionException} either.
+     */
+    public FreeMarkerServiceResponse calculateTemplateOutput(
+            String templateSourceCode, Object dataModel, OutputFormat outputFormat, Locale locale, TimeZone timeZone)
+            throws RejectedExecutionException {
+        Objects.requireNonNull(templateExecutor, "templateExecutor was null - was postConstruct ever called?");
+        
+        final CalculateTemplateOutput task = new CalculateTemplateOutput(
+                templateSourceCode, dataModel, outputFormat, locale, timeZone);
+        Future<FreeMarkerServiceResponse> future = templateExecutor.submit(task);
+        
+        synchronized (task) {
+            while (!task.isTemplateExecutionStarted() && !task.isTaskEnded() && !future.isDone()) {
+                try {
+                    task.wait(50); // Timeout is needed to periodically check future.isDone()
+                } catch (InterruptedException e) {
+                    throw new FreeMarkerServiceException("Template execution task was interrupted.", e);
+                }
+            }
+        }
+        
+        try {
+            return future.get(maxTemplateExecutionTime, TimeUnit.MILLISECONDS);
+        } catch (ExecutionException e) {
+            throw new FreeMarkerServiceException("Template execution task unexpectedly failed", e.getCause());
+        } catch (InterruptedException e) {
+            throw new FreeMarkerServiceException("Template execution task was interrupted.", e);
+        } catch (TimeoutException e) {
+            // Exactly one interruption should be enough, and it should abort template processing pretty much
+            // immediately. But to be on the safe side we will interrupt in a loop, with a timeout.
+            final long abortionLoopStartTime = System.currentTimeMillis();
+            long timeLeft = ABORTION_LOOP_TIME_LIMIT;
+            boolean templateExecutionEnded = false;
+            do {
+                synchronized (task) {
+                    Thread templateExecutorThread = task.getTemplateExecutorThread();
+                    if (templateExecutorThread == null) {
+                        templateExecutionEnded = true;
+                    } else {
+                        FreeMarkerInternalsAccessor.interruptTemplateProcessing(templateExecutorThread);
+                        logger.debug("Trying to interrupt overly long template processing (" + timeLeft + " ms left).");
+                    }
+                }
+                if (!templateExecutionEnded) {
+                    try {
+                        timeLeft = ABORTION_LOOP_TIME_LIMIT - (System.currentTimeMillis() - abortionLoopStartTime);
+                        if (timeLeft > 0) {
+                            Thread.sleep(ABORTION_LOOP_INTERRUPTION_DISTANCE);
+                        }
+                    } catch (InterruptedException eInt) {
+                        logger.error("Template execution abortion loop was interrupted", eInt);
+                        timeLeft = 0;
+                    }
+                }
+            } while (!templateExecutionEnded && timeLeft > 0);
+            
+            if (templateExecutionEnded) {
+                logger.debug("Long template processing has ended.");
+                try {
+                    return future.get();
+                } catch (InterruptedException | ExecutionException e1) {
+                    throw new FreeMarkerServiceException("Failed to get result from template executor task", e);
+                }
+            } else {
+                throw new FreeMarkerServiceException(
+                        "Couldn't stop long running template processing within " + ABORTION_LOOP_TIME_LIMIT
+                        + " ms. It's possibly stuck forever. Such problems can exhaust the executor pool. "
+                        + "Template (quoted): " + StringEscapeUtils.escapeJava(templateSourceCode));
+            }
+        }
+    }
+    
+    public int getMaxOutputLength() {
+        return maxOutputLength;
+    }
+
+    public void setMaxOutputLength(int maxOutputLength) {
+        this.maxOutputLength = maxOutputLength;
+    }
+
+    public int getMaxThreads() {
+        return maxThreads;
+    }
+    
+    public void setMaxThreads(int maxThreads) {
+        this.maxThreads = maxThreads;
+    }
+    
+    public int getMaxQueueLength() {
+        return maxQueueLength;
+    }
+    
+    public void setMaxQueueLength(int maxQueueLength) {
+        this.maxQueueLength = maxQueueLength;
+    }
+
+    public long getMaxTemplateExecutionTime() {
+        return maxTemplateExecutionTime;
+    }
+    
+    public void setMaxTemplateExecutionTime(long maxTemplateExecutionTime) {
+        this.maxTemplateExecutionTime = maxTemplateExecutionTime;
+    }
+
+    /**
+     * Returns the time zone used by the FreeMarker templates.
+     */
+    public TimeZone getFreeMarkerTimeZone() {
+        return freeMarkerConfig.getTimeZone();
+    }
+    
+    private FreeMarkerServiceResponse createFailureResponse(Throwable e) {
+        logger.debug("The template had error(s)", e);
+        return new FreeMarkerServiceResponse.Builder().buildForFailure(e);
+    }
+
+    @PostConstruct
+    public void postConstruct() {
+        int actualMaxQueueLength = maxQueueLength != null
+                ? maxQueueLength
+                : Math.max(
+                        MIN_DEFAULT_MAX_QUEUE_LENGTH,
+                        (int) (MAX_DEFAULT_MAX_QUEUE_LENGTH_MILLISECONDS / maxTemplateExecutionTime));
+        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
+                maxThreads, maxThreads,
+                THREAD_KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS,
+                new BlockingArrayQueue<Runnable>(actualMaxQueueLength));
+        threadPoolExecutor.allowCoreThreadTimeOut(true);
+        templateExecutor = threadPoolExecutor;
+    }
+    
+    private class CalculateTemplateOutput implements Callable<FreeMarkerServiceResponse> {
+        
+        private boolean templateExecutionStarted;
+        private Thread templateExecutorThread;
+        private final String templateSourceCode;
+        private final Object dataModel;
+        private final OutputFormat outputFormat;
+        private final Locale locale;
+        private final TimeZone timeZone;
+        private boolean taskEnded;
+
+        private CalculateTemplateOutput(String templateSourceCode, Object dataModel,
+                OutputFormat outputFormat, Locale locale, TimeZone timeZone) {
+            this.templateSourceCode = templateSourceCode;
+            this.dataModel = dataModel;
+            this.outputFormat = outputFormat;
+            this.locale = locale;
+            this.timeZone = timeZone;
+        }
+        
+        @Override
+        public FreeMarkerServiceResponse call() throws Exception {
+            try {
+                Template template;
+                try {
+                    TemplateConfiguration tCfg = new TemplateConfiguration();
+                    tCfg.setParentConfiguration(freeMarkerConfig);
+                    if (outputFormat != null) {
+                        tCfg.setOutputFormat(outputFormat);
+                    }
+                    if (locale != null) {
+                        tCfg.setLocale(locale);
+                    }
+                    if (timeZone != null) {
+                        tCfg.setTimeZone(timeZone);
+                    }
+                    
+                    template = new Template(null, null,
+                            new StringReader(templateSourceCode), freeMarkerConfig, tCfg, null);
+                    
+                    tCfg.apply(template);
+                } catch (ParseException e) {
+                    // Expected (part of normal operation)
+                    return createFailureResponse(e);
+                } catch (Exception e) {
+                    // Not expected
+                    throw new FreeMarkerServiceException("Unexpected exception during template parsing", e);
+                }
+                
+                FreeMarkerInternalsAccessor.makeTemplateInterruptable(template);
+                
+                boolean resultTruncated;
+                StringWriter writer = new StringWriter();
+                try {
+                    synchronized (this) {
+                        templateExecutorThread = Thread.currentThread(); 
+                        templateExecutionStarted = true;
+                        notifyAll();
+                    }
+                    try {
+                        template.process(dataModel, new LengthLimitedWriter(writer, maxOutputLength));
+                    } finally {
+                        synchronized (this) {
+                            templateExecutorThread = null;
+                            FreeMarkerInternalsAccessor.clearAnyPendingTemplateProcessingInterruption();
+                        }
+                    }
+                    resultTruncated = false;
+                } catch (LengthLimitExceededException e) {
+                    // Not really an error, we just cut the output here.
+                    resultTruncated = true;
+                    writer.write(new MessageFormat(MAX_OUTPUT_LENGTH_EXCEEDED_TERMINATION, AllowedSettingValuesMaps.DEFAULT_LOCALE)
+                            .format(new Object[] { maxOutputLength }));
+                    // Falls through
+                } catch (TemplateException e) {
+                    // Expected (part of normal operation)
+                    return createFailureResponse(e);
+                } catch (Exception e) {
+                    if (FreeMarkerInternalsAccessor.isTemplateProcessingInterruptedException(e)) {
+                        return new FreeMarkerServiceResponse.Builder().buildForFailure(new TimeoutException(
+                                "Template processing was aborted for exceeding the " + getMaxTemplateExecutionTime()
+                                + " ms time limit set for this online service. This is usually because you have "
+                                + "a very long running #list (or other kind of loop) in your template.")); 
+                    }
+                    // Not expected
+                    throw new FreeMarkerServiceException("Unexpected exception during template evaluation", e);
+                }
+                
+                return new FreeMarkerServiceResponse.Builder().buildForSuccess(writer.toString(), resultTruncated);
+            } finally {
+                synchronized (this) {
+                    taskEnded = true;
+                    notifyAll();
+                }
+            }
+        }
+        
+        private synchronized boolean isTemplateExecutionStarted() {
+            return templateExecutionStarted;
+        }
+
+        private synchronized boolean isTaskEnded() {
+            return taskEnded;
+        }
+        
+        /**
+         * @return non-{@code null} after the task execution has actually started, but before it has finished.
+         */
+        private synchronized Thread getTemplateExecutorThread() {
+            return templateExecutorThread;
+        }
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceException.java b/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceException.java
new file mode 100644
index 0000000..2ca7ee4
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceException.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.services;
+
+/**
+ * When {@link FreeMarkerService} fails on an unexpected way (non-user error). 
+ */
+public class FreeMarkerServiceException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public FreeMarkerServiceException(String message) {
+        super(message);
+        // TODO Auto-generated constructor stub
+    }
+
+    public FreeMarkerServiceException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceResponse.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceResponse.java b/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceResponse.java
new file mode 100644
index 0000000..3950717
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceResponse.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.services;
+
+public class FreeMarkerServiceResponse {
+    
+    private final String templateOutput;
+    private final boolean templateOutputTruncated;
+    private final Throwable failureReason;
+
+    FreeMarkerServiceResponse(String templateOutput, boolean templateOutputTruncated) {
+        this.templateOutput = templateOutput;
+        this.templateOutputTruncated = templateOutputTruncated;
+        this.failureReason = null;
+    }
+
+    FreeMarkerServiceResponse(Throwable failureReason) {
+        this.templateOutput = null;
+        this.templateOutputTruncated = false;
+        this.failureReason = failureReason;
+    }
+    
+    public String getTemplateOutput() {
+        return templateOutput;
+    }
+
+    public boolean isTemplateOutputTruncated() {
+        return templateOutputTruncated;
+    }
+
+    public boolean isSuccesful() {
+        return failureReason == null;
+    }
+
+    public Throwable getFailureReason() {
+        return failureReason;
+    }
+
+    public static class Builder {
+        
+        public FreeMarkerServiceResponse buildForSuccess(String result, boolean resultTruncated){
+            return new FreeMarkerServiceResponse(result, resultTruncated);
+        }
+
+        public FreeMarkerServiceResponse buildForFailure(Throwable failureReason){
+            return new FreeMarkerServiceResponse(failureReason);
+        }
+        
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/util/DataModelParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/util/DataModelParser.java b/src/main/java/org/apache/freemarker/onlinetester/util/DataModelParser.java
new file mode 100644
index 0000000..b356be6
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/util/DataModelParser.java
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.util;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import freemarker.ext.dom.NodeModel;
+import freemarker.template.utility.DateUtil;
+import freemarker.template.utility.DateUtil.CalendarFieldsToDateConverter;
+import freemarker.template.utility.DateUtil.DateParseException;
+import freemarker.template.utility.DateUtil.TrivialCalendarFieldsToDateConverter;
+
+/**
+ * Parses the text that the user enters into the data model input field.
+ */
+public final class DataModelParser {
+
+    private static final String KEYWORD_NEGATIVE_INFINITY = "-Infinity";
+
+    private static final String KEYWORD_POSITIVE_INFINITY = "+Infinity";
+
+    private static final String KEYWORD_INFINITY = "Infinity";
+
+    private static final String KEYWORD_TRUE = "true";
+
+    private static final String KEYWORD_FALSE = "false";
+
+    private static final String KEYWORD_NULL = "null";
+
+    private static final String KEYWORD_NAN = "NaN";
+
+    /** Matches a line starting like "someVariable=". */
+    private static final Pattern ASSIGNMENT_START = Pattern.compile(
+            "^\\s*"
+            + "(\\p{L}[\\p{L}\\p{N}\\.:\\-_$@]*)" // name
+            + "[ \t]*=\\s*",
+            Pattern.MULTILINE);
+
+    /** Matches a value that starts like a number, or probably meant to be number at least. */
+    private static final Pattern NUMBER_LIKE = Pattern.compile("[+-]?[\\.,]?[0-9].*", Pattern.DOTALL);
+    
+    private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+
+    private DataModelParser() {
+        // Not meant to be instantiated
+    }
+
+    public static Map<String, Object> parse(String src, TimeZone timeZone) throws DataModelParsingException {
+        if (!StringUtils.hasText(src)) {
+            return Collections.emptyMap();
+        }
+
+        Map<String, Object> dataModel = new LinkedHashMap<>();
+
+        String lastName = null;
+        int lastAssignmentStartEnd = 0;
+        final Matcher assignmentStart = ASSIGNMENT_START.matcher(src);
+        findAssignments: while (true) {
+            boolean hasNextAssignment = assignmentStart.find(lastAssignmentStartEnd);
+
+            if (lastName != null) {
+                String value = src.substring(
+                        lastAssignmentStartEnd, hasNextAssignment ? assignmentStart.start() : src.length())
+                        .trim();
+                final Object parsedValue;
+                try {
+                    parsedValue = parseValue(value, timeZone);
+                } catch (DataModelParsingException e) {
+                    throw new DataModelParsingException(
+                            "Failed to parse the value of \"" + lastName + "\":\n" + e.getMessage(), e.getCause());
+                }
+                dataModel.put(lastName, parsedValue);
+            }
+
+            if (lastName == null && (!hasNextAssignment || assignmentStart.start() != 0)) {
+                throw new DataModelParsingException(
+                        "The data model specification must start with an assignment (name=value).");
+            }
+
+            if (!hasNextAssignment) {
+                break findAssignments;
+            }
+
+            lastName = assignmentStart.group(1).trim();
+            lastAssignmentStartEnd = assignmentStart.end();
+        }
+
+        return dataModel;
+    }
+    
+    private static Object parseValue(String value, TimeZone timeZone) throws DataModelParsingException {
+        // Note: Because we fall back to interpret the input as a literal string value when it doesn't look like
+        // anything else (like a number, boolean, etc.), it's important to avoid misunderstandings, and throw exception
+        // in suspicious situations. The user can always quote the string value if we are "too smart". But he will
+        // be confused about the rules of FreeMarker if what he believes to be a non-string is misinterpreted by this
+        // parser as a string. Getting sometimes an error and then quoting the string is better than that.
+        
+        if (value.endsWith(";")) {  // Tolerate this habit of Java and JavaScript programmers
+            value = value.substring(value.length() - 1).trim();
+        }
+        
+        if (NUMBER_LIKE.matcher(value).matches()) {
+            try {
+                return new BigDecimal(value);
+            } catch (NumberFormatException e) {
+                // Maybe it's a ISO 8601 Date/time/datetime
+                CalendarFieldsToDateConverter calToDateConverter = new TrivialCalendarFieldsToDateConverter();
+                
+                DateParseException attemptedTemportalPExc = null;
+                String attemptedTemporalType = null;
+                final int dashIdx = value.indexOf('-');
+                final int colonIdx = value.indexOf(':');
+                if (value.indexOf('T') > 1 || (dashIdx > 1 && colonIdx > dashIdx)) {
+                    try {
+                        return new Timestamp(
+                                DateUtil.parseISO8601DateTime(value, timeZone, calToDateConverter).getTime());
+                    } catch (DateParseException pExc) {
+                        attemptedTemporalType = "date-time";
+                        attemptedTemportalPExc = pExc;
+                    }
+                } else if (dashIdx > 1) {
+                    try {
+                        return new java.sql.Date(
+                                DateUtil.parseISO8601Date(value, timeZone, calToDateConverter).getTime());
+                    } catch (DateParseException pExc) {
+                        attemptedTemporalType = "date";
+                        attemptedTemportalPExc = pExc;
+                    }
+                } else if (colonIdx > 1) { 
+                    try {
+                        return new Time(
+                                DateUtil.parseISO8601Time(value, timeZone, calToDateConverter).getTime());
+                    } catch (DateParseException pExc) {
+                        attemptedTemporalType = "time";
+                        attemptedTemportalPExc = pExc;
+                    }
+                }
+                if (attemptedTemportalPExc == null) {
+                    throw new DataModelParsingException("Malformed number: " + value, e);
+                } else {
+                    throw new DataModelParsingException(
+                            "Malformed ISO 8601 " + attemptedTemporalType + " (or malformed number): " + 
+                            attemptedTemportalPExc.getMessage(), e.getCause());
+                }
+            }
+        } else if (value.startsWith("\"")) {
+            try {
+                return JSON_MAPPER.readValue(value, String.class);
+            } catch (IOException e) {
+                throw new DataModelParsingException(
+                        "Malformed quoted string (using JSON syntax): " + getMessageWithoutLocation(e),
+                        e);
+            }
+        } else if (value.startsWith("\'")) {
+            throw new DataModelParsingException(
+                    "Malformed quoted string (using JSON syntax): Use \" character for quotation, not \' character.");
+        } else if (value.startsWith("[")) {
+            try {
+                return JSON_MAPPER.readValue(value, List.class);
+            } catch (IOException e) {
+                throw new DataModelParsingException(
+                        "Malformed list (using JSON syntax): " + getMessageWithoutLocation(e),
+                        e);
+            }
+        } else if (value.startsWith("{")) {
+            try {
+                return JSON_MAPPER.readValue(value, LinkedHashMap.class);
+            } catch (IOException e) {
+                throw new DataModelParsingException(
+                        "Malformed list (using JSON syntax): " + getMessageWithoutLocation(e),
+                        e);
+            }
+        } else if (value.startsWith("<")) {
+            try {
+                DocumentBuilder builder = NodeModel.getDocumentBuilderFactory().newDocumentBuilder();
+                ErrorHandler errorHandler = NodeModel.getErrorHandler();
+                if (errorHandler != null) builder.setErrorHandler(errorHandler);
+                final Document doc = builder.parse(new InputSource(new StringReader(value)));
+                NodeModel.simplify(doc);
+                return doc;
+            } catch (SAXException e) {
+                final String saxMsg = e.getMessage();
+                throw new DataModelParsingException("Malformed XML: " + (saxMsg != null ? saxMsg : e), e);
+            } catch (Exception e) {
+                throw new DataModelParsingException("XML parsing has failed with internal error: " + e, e);
+            }
+        } else if (value.equalsIgnoreCase(KEYWORD_TRUE)) {
+            checkKeywordCase(value, KEYWORD_TRUE);
+            return Boolean.TRUE;
+        } else if (value.equalsIgnoreCase(KEYWORD_FALSE)) {
+            checkKeywordCase(value, KEYWORD_FALSE);
+            return Boolean.FALSE;
+        } else if (value.equalsIgnoreCase(KEYWORD_NULL)) {
+            checkKeywordCase(value, KEYWORD_NULL);
+            return null;
+        } else if (value.equalsIgnoreCase(KEYWORD_NAN)) {
+            checkKeywordCase(value, KEYWORD_NAN);
+            return Double.NaN;
+        } else if (value.equalsIgnoreCase(KEYWORD_INFINITY)) {
+            checkKeywordCase(value, KEYWORD_INFINITY);
+            return Double.POSITIVE_INFINITY;
+        } else if (value.equalsIgnoreCase(KEYWORD_POSITIVE_INFINITY)) {
+            checkKeywordCase(value, KEYWORD_POSITIVE_INFINITY);
+            return Double.POSITIVE_INFINITY;
+        } else if (value.equalsIgnoreCase(KEYWORD_NEGATIVE_INFINITY)) {
+            checkKeywordCase(value, KEYWORD_NEGATIVE_INFINITY);
+            return Double.NEGATIVE_INFINITY;
+        } else if (value.length() == 0) {
+            throw new DataModelParsingException(
+                    "Empty value. (If you indeed wanted a 0 length string, quote it, like \"\".)");
+        } else {
+            return value;
+        }
+    }
+
+    private static String getMessageWithoutLocation(IOException e) {
+        return e instanceof JsonProcessingException
+                ? ((JsonProcessingException) e).getOriginalMessage()
+                : e.getMessage();
+    }
+
+    private static void checkKeywordCase(String inputKeyword, String correctKeyword) throws DataModelParsingException {
+        if (!correctKeyword.equals(inputKeyword)) {
+            throw new DataModelParsingException("Keywords are case sensitive; the correct form is: "
+                    + correctKeyword);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/util/DataModelParsingException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/util/DataModelParsingException.java b/src/main/java/org/apache/freemarker/onlinetester/util/DataModelParsingException.java
new file mode 100644
index 0000000..8c62127
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/util/DataModelParsingException.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.util;
+
+import java.util.TimeZone;
+
+/**
+ * Thrown by {@link DataModelParser#parse(String, TimeZone)}.
+ */
+public class DataModelParsingException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    public DataModelParsingException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public DataModelParsingException(String message) {
+        super(message);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/util/ExceptionUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/util/ExceptionUtils.java b/src/main/java/org/apache/freemarker/onlinetester/util/ExceptionUtils.java
new file mode 100644
index 0000000..dfbe293
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/util/ExceptionUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.util;
+
+import freemarker.core.ParseException;
+import freemarker.template.TemplateException;
+
+public final class ExceptionUtils {
+
+    private ExceptionUtils() {
+        // Not meant to be instantiated
+    }
+
+    /**
+     * The error message (and sometimes also the class), and then the same with the cause exception, and so on. Doesn't
+     * contain the stack trace or other location information.
+     */
+    public static String getMessageWithCauses(final Throwable exc) {
+        StringBuilder sb = new StringBuilder();
+        
+        Throwable curExc = exc;
+        while (curExc != null) {
+            if (curExc != exc) {
+                sb.append("\n\nCaused by:\n");
+            }
+            String msg = curExc.getMessage();
+            if (msg == null || !(curExc instanceof TemplateException || curExc instanceof ParseException)) {
+                sb.append(curExc.getClass().getName()).append(": ");
+            }
+            sb.append(msg);
+            curExc = curExc.getCause();
+        }
+        return sb.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/util/LengthLimitExceededException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/util/LengthLimitExceededException.java b/src/main/java/org/apache/freemarker/onlinetester/util/LengthLimitExceededException.java
new file mode 100644
index 0000000..f7bb00c
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/util/LengthLimitExceededException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.util;
+
+import java.io.IOException;
+
+/**
+ * Thrown by {@link LengthLimitedWriter}.
+ */
+public class LengthLimitExceededException extends IOException {
+
+    private static final long serialVersionUID = 1L;
+    
+    public LengthLimitExceededException() {
+        super("The outout String length limit of the Writer was exceeded.");
+    }
+
+}



[2/5] incubator-freemarker-online-tester git commit: renamed the package name to org/apache/freemarker/onlinetester

Posted by dd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/util/LengthLimitedWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/util/LengthLimitedWriter.java b/src/main/java/org/apache/freemarker/onlinetester/util/LengthLimitedWriter.java
new file mode 100644
index 0000000..bb2650d
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/util/LengthLimitedWriter.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.util;
+
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
+/**
+ * A {@link StringWriter} that limits its buffer size, and throws {@link LengthLimitExceededException} when that's
+ * exceeded.
+ */
+public class LengthLimitedWriter extends FilterWriter {
+    
+    private int lengthLeft;
+
+    public LengthLimitedWriter(Writer writer, int lengthLimit) {
+        super(writer);
+        this.lengthLeft = lengthLimit;
+    }
+
+    @Override
+    public void write(int c) throws IOException {
+        if (lengthLeft < 1) {
+            throw new LengthLimitExceededException();
+        }
+        
+        super.write(c);
+        
+        lengthLeft--;
+    }
+
+    @Override
+    public void write(char[] cbuf, int off, int len) throws IOException {
+        final boolean lengthExceeded;
+        if (lengthLeft < len) {
+            len = lengthLeft;
+            lengthExceeded = true;
+        } else {
+            lengthExceeded = false;
+        }
+        
+        super.write(cbuf, off, len);
+        lengthLeft -= len;
+        
+        if (lengthExceeded) {
+            throw new LengthLimitExceededException();
+        }
+    }
+
+    @Override
+    public void write(String str, int off, int len) throws IOException {
+        final boolean lengthExceeded;
+        if (lengthLeft < len) {
+            len = lengthLeft;
+            lengthExceeded = true;
+        } else {
+            lengthExceeded = false;
+        }
+        
+        super.write(str, off, len);
+        lengthLeft -= len;
+        
+        if (lengthExceeded) {
+            throw new LengthLimitExceededException();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/java/org/apache/freemarker/onlinetester/view/FreeMarkerOnlineView.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/onlinetester/view/FreeMarkerOnlineView.java b/src/main/java/org/apache/freemarker/onlinetester/view/FreeMarkerOnlineView.java
new file mode 100644
index 0000000..3aecbb5
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/onlinetester/view/FreeMarkerOnlineView.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.view;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+
+import org.apache.freemarker.onlinetester.model.SelectionOption;
+import org.apache.freemarker.onlinetester.services.AllowedSettingValuesMaps;
+import com.yammer.dropwizard.views.View;
+
+import freemarker.template.Configuration;
+
+public class FreeMarkerOnlineView extends View {
+
+    private static final List<SelectionOption> LOCALE_SELECTION_OPTIONS = toLocaleSelectionOptions(AllowedSettingValuesMaps.LOCALE_MAP);
+    private static final List<SelectionOption> TIME_ZONE_SELECTION_OPTIONS = toSelectionOptions(AllowedSettingValuesMaps.TIME_ZONE_MAP);
+    private static final List<SelectionOption> OUTPUT_FORMAT_SELECTION_OPTIONS = toSelectionOptions(AllowedSettingValuesMaps.OUTPUT_FORMAT_MAP);
+    
+    private String template = "";
+    private String dataModel = "";
+    private String outputFormat = AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT_KEY;
+    private String locale = AllowedSettingValuesMaps.DEFAULT_LOCALE_KEY;
+    private String timeZone = AllowedSettingValuesMaps.DEFAULT_TIME_ZONE_KEY;
+    
+    private boolean execute;
+    
+    private static List<SelectionOption> toSelectionOptions(Map<String, ?> settingValueMap) {
+        ArrayList<SelectionOption> selectionOptions = new ArrayList<SelectionOption>(settingValueMap.size());
+        for (String key : settingValueMap.keySet()) {
+            selectionOptions.add(new SelectionOption(key, truncate(key, 25)));
+        }
+        Collections.sort(selectionOptions);
+        return selectionOptions;
+    }
+    
+    private static List<SelectionOption> toLocaleSelectionOptions(Map<String, Locale> localeMap) {
+        ArrayList<SelectionOption> selectionOptions = new ArrayList<SelectionOption>(localeMap.size());
+        for (Map.Entry<String, Locale> ent : localeMap.entrySet()) {
+            Locale locale = ent.getValue();
+            selectionOptions.add(
+                    new SelectionOption(ent.getKey(),
+                    truncate(locale.getDisplayName(Locale.US), 18) + "; " + locale.toString()));
+        }
+        Collections.sort(selectionOptions);
+        return selectionOptions;
+    }
+    
+    private static String truncate(String s, int maxLength) {
+        if (s == null) {
+            return null;
+        }
+        return s.length() <= maxLength ? s : s.substring(0, Math.max(maxLength - 3, 0)) + "[...]";
+    }    
+
+    /**
+     *
+     * @param template
+     * @param dataModel
+     * @param execute set to true if the execution should be triggered on page load.
+     */
+    public FreeMarkerOnlineView() {
+        super("/view/freemarker-online.ftl", Charset.forName("utf-8"));
+    }
+
+    public String getTemplate() {
+        return template;
+    }
+
+    public void setTemplate(String template) {
+        this.template = withDefault(template, "");
+    }
+
+    public String getDataModel() {
+        return dataModel;
+    }
+
+    public void setDataModel(String dataModel) {
+        this.dataModel = withDefault(dataModel, "");
+    }
+
+    public String getFreeMarkerVersion() {
+        return Configuration.getVersion().toString();
+    }
+    
+    public List<SelectionOption> getOutputFormats() {
+        return OUTPUT_FORMAT_SELECTION_OPTIONS;
+    }
+
+    public List<SelectionOption> getLocales() {
+        return LOCALE_SELECTION_OPTIONS;
+    }
+
+    public List<SelectionOption> getTimeZones() {
+        return TIME_ZONE_SELECTION_OPTIONS;
+    }
+
+    public String getOutputFormat() {
+        return outputFormat;
+    }
+
+    public void setOutputFormat(String outputFormat) {
+        this.outputFormat = withDefault(outputFormat, AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT_KEY);
+    }
+
+    public String getLocale() {
+        return locale;
+    }
+
+    public void setLocale(String locale) {
+        this.locale = withDefault(locale, AllowedSettingValuesMaps.DEFAULT_LOCALE_KEY);
+    }
+
+    public String getTimeZone() {
+        return timeZone;
+    }
+
+    public void setTimeZone(String timeZone) {
+        this.timeZone = withDefault(timeZone, AllowedSettingValuesMaps.DEFAULT_TIME_ZONE_KEY);
+    }
+    
+    public boolean isExecute() {
+        return execute;
+    }
+
+    public void setExecute(boolean executeImmediately) {
+        this.execute = executeImmediately;
+    }
+
+    private static String withDefault(String value, String defaultValue) {
+        return !StringUtils.isBlank(value) ? value : defaultValue;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/main/resources/spring/bootstrap-context.xml
----------------------------------------------------------------------
diff --git a/src/main/resources/spring/bootstrap-context.xml b/src/main/resources/spring/bootstrap-context.xml
index db4bf9b..8d8e518 100644
--- a/src/main/resources/spring/bootstrap-context.xml
+++ b/src/main/resources/spring/bootstrap-context.xml
@@ -24,7 +24,7 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">
 
-    <context:component-scan base-package="com.kenshoo"/>
+    <context:component-scan base-package="org.apache.freemarker.onlinetester"/>
 
     <context:annotation-config/>
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/platform/DropWizardServiceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/platform/DropWizardServiceTest.java b/src/test/java/com/kenshoo/freemarker/platform/DropWizardServiceTest.java
deleted file mode 100644
index 312ed0b..0000000
--- a/src/test/java/com/kenshoo/freemarker/platform/DropWizardServiceTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2014 Kenshoo.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.kenshoo.freemarker.platform;
-
-import com.google.common.io.Resources;
-import com.kenshoo.freemarker.dropwizard.ApplicationStartup;
-import com.yammer.dropwizard.testing.junit.DropwizardServiceRule;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-
-public class DropWizardServiceTest {
-    @ClassRule
-    public static TestRule testRule = new DropwizardServiceRule<>(ApplicationStartup.class,
-            Resources.getResource("freemarker-online.yml").getPath());
-
-
-    @Test
-    public void testServerIsUp() throws Exception {
-        ((DropwizardServiceRule) testRule).getService();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/platform/YamlPropertiesPersister.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/platform/YamlPropertiesPersister.java b/src/test/java/com/kenshoo/freemarker/platform/YamlPropertiesPersister.java
deleted file mode 100644
index 1299581..0000000
--- a/src/test/java/com/kenshoo/freemarker/platform/YamlPropertiesPersister.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.platform;
-
-import com.fasterxml.jackson.dataformat.yaml.snakeyaml.Yaml;
-import org.springframework.util.PropertiesPersister;
-import org.springframework.util.StringUtils;
-
-import java.io.*;
-import java.util.Map;
-import java.util.Properties;
-
-public class YamlPropertiesPersister implements PropertiesPersister {
-    @Override
-    public void load(Properties props, InputStream is) throws IOException {
-        load(props, new InputStreamReader(is));
-    }
-
-    /**
-     * We want to traverse map representing Yaml object and each time we find String=String pair we want to
-     * save it as Property. As we are going deeper into map we generate compound key as path-like String
-     *
-     * @see org.springframework.util.PropertiesPersister#load(java.util.Properties, java.io.Reader)
-     */
-    @Override
-    public void load(Properties props, Reader reader) throws IOException {
-        Yaml yaml = new Yaml();
-        @SuppressWarnings("unchecked")
-        Map<String, Object> map = (Map<String, Object>) yaml.load(reader);
-        // now we can populate supplied props
-        assignProperties(props, map, null);
-    }
-
-    @SuppressWarnings("unchecked")
-    public void assignProperties(Properties props, Map<String, Object> map, String path) {
-        for (Map.Entry<String, Object> entry : map.entrySet()) {
-            String key = entry.getKey();
-            if (!StringUtils.isEmpty(path))
-                key = path + "." + key;
-            Object val = entry.getValue();
-            if (val instanceof String) {
-                // see if we need to create a compound key
-                props.put(key, val);
-            } else if (val instanceof Map) {
-                assignProperties(props, (Map<String, Object>) val, key);
-            }
-        }
-    }
-
-    @Override
-    public void store(Properties props, OutputStream os, String header) throws IOException {
-        throw new IllegalStateException("Current implementation is a read-only");
-    }
-
-    @Override
-    public void store(Properties props, Writer writer, String header) throws IOException {
-        throw new IllegalStateException("Current implementation is a read-only");
-    }
-
-    @Override
-    public void loadFromXml(Properties props, InputStream is) throws IOException {
-        throw new IllegalStateException("Use DefaultPropertiesPersister if you want to read/write XML");
-    }
-
-    @Override
-    public void storeToXml(Properties props, OutputStream os, String header) throws IOException {
-        throw new IllegalStateException("Use DefaultPropertiesPersister if you want to load/store to XML");
-    }
-
-    @Override
-    public void storeToXml(Properties props, OutputStream os, String header, String encoding) throws IOException {
-        throw new IllegalStateException("Use DefaultPropertiesPersister if you want to read/write XML");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineExecuteResourceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineExecuteResourceTest.java b/src/test/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineExecuteResourceTest.java
deleted file mode 100644
index e7ca204..0000000
--- a/src/test/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineExecuteResourceTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.resources;
-
-import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-import org.springframework.web.context.ContextLoaderListener;
-import org.springframework.web.context.request.RequestContextListener;
-
-import com.kenshoo.freemarker.model.ExecuteRequest;
-import com.kenshoo.freemarker.model.ExecuteResourceField;
-import com.kenshoo.freemarker.model.ExecuteResourceProblem;
-import com.kenshoo.freemarker.model.ExecuteResponse;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
-import com.sun.jersey.test.framework.AppDescriptor;
-import com.sun.jersey.test.framework.JerseyTest;
-import com.sun.jersey.test.framework.WebAppDescriptor;
-
-public class FreeMarkerOnlineExecuteResourceTest extends JerseyTest {
-    private static final String DATA_MODEL = "user=John";
-    private static final String TEMPLATE_WITH_VARIABLE = "Welcome ${user}";
-    private static final String TEMPLATE_PLAIN = "Welcome John";
-    private static final String MALFORMED_DATA_MODEL = "userJohn";
-    private static final String EXECUTE_API = "api/execute";
-    @Override
-    protected AppDescriptor configure() {
-        return new WebAppDescriptor.Builder("com.kenshoo.freemarker.resources")
-                        .contextPath("/")
-                        .contextListenerClass(ContextLoaderListener.class)
-                        .contextParam("contextConfigLocation", "classpath:spring/bootstrap-context.xml")
-                        .servletClass(SpringServlet.class)
-                        .requestListenerClass(RequestContextListener.class)
-                        .build();
-    }
-
-    @Test
-    public void testSuccessRequest() throws Exception {
-        ExecuteRequest req = new ExecuteRequest(TEMPLATE_WITH_VARIABLE, DATA_MODEL);
-        ClientResponse resp = client().resource(getBaseURI().toString() + EXECUTE_API)
-                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
-        assertEquals(200, resp.getStatus());
-        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
-        assertNull(response.getProblems());
-    }
-
-    @Test
-    public void testMalformedDataModel() throws Exception {
-        ExecuteRequest req = new ExecuteRequest(TEMPLATE_PLAIN, MALFORMED_DATA_MODEL);
-        ClientResponse resp = client().resource(getBaseURI().toString() + EXECUTE_API)
-                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
-        assertEquals(200, resp.getStatus());
-        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
-        assertNotNull(response.getProblems());
-        assertTrue(containsProblem(response, ExecuteResourceField.DATA_MODEL));
-    }
-
-    @Test
-    public void testLongDataModel() throws Exception {
-        ExecuteRequest req = new ExecuteRequest(TEMPLATE_PLAIN, create30KString());
-        ClientResponse resp = client().resource(getBaseURI().toString() + EXECUTE_API)
-                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
-        assertEquals(200, resp.getStatus());
-        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
-        assertNotNull(response.getProblems());
-        assertTrue(containsProblem(response, ExecuteResourceField.DATA_MODEL));
-        String problemMessage = getProblemMessage(response, ExecuteResourceField.DATA_MODEL);
-        assertThat(problemMessage, containsString("data model"));
-        assertThat(problemMessage, containsString("limit"));
-    }
-
-    @Test
-    public void testLongTemplate() throws Exception {
-        ExecuteRequest req = new ExecuteRequest(create30KString(), DATA_MODEL);
-        ClientResponse resp = client().resource(getBaseURI().toString() + EXECUTE_API)
-                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
-        assertEquals(200, resp.getStatus());
-        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
-        assertNotNull(response.getProblems());
-        assertTrue(containsProblem(response, ExecuteResourceField.TEMPLATE));
-        String problemMessage = getProblemMessage(response, ExecuteResourceField.TEMPLATE);
-        assertThat(problemMessage, containsString("template"));
-        assertThat(problemMessage, containsString("limit"));
-    }
-
-    @Test
-    public void testMultipleErrorsDataModel() throws Exception {
-        ExecuteRequest req = new ExecuteRequest(create30KString(), create30KString());
-        req.setOutputFormat("wrongOutputFormat");
-        req.setLocale("wrongLocale");
-        req.setTimeZone("wrongTimeZone");
-        
-        ClientResponse resp = client().resource(getBaseURI() + EXECUTE_API)
-                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
-        
-        assertEquals(200, resp.getStatus());
-        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
-        assertNotNull(response.getProblems());
-        assertThat(getProblemMessage(response, ExecuteResourceField.TEMPLATE), containsString("limit"));
-        assertThat(getProblemMessage(response, ExecuteResourceField.DATA_MODEL), containsString("limit"));
-        assertThat(getProblemMessage(response, ExecuteResourceField.OUTPUT_FORMAT), containsString("wrongOutputFormat"));
-        assertThat(getProblemMessage(response, ExecuteResourceField.LOCALE), containsString("wrongLocale"));
-        assertThat(getProblemMessage(response, ExecuteResourceField.TIME_ZONE), containsString("wrongTimeZone"));
-    }
-    
-    private String create30KString() {
-        final String veryLongString;
-        {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < 30000 / 10; i++) {
-                sb.append("0123456789");
-            }
-            veryLongString = sb.toString();
-        }
-        return veryLongString;
-    }
-
-    private boolean containsProblem(ExecuteResponse response, ExecuteResourceField field) {
-        for (ExecuteResourceProblem problem : response.getProblems()) {
-            if (problem.getField() == field) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private String getProblemMessage(ExecuteResponse response, ExecuteResourceField field) {
-        for (ExecuteResourceProblem problem : response.getProblems()) {
-            if (problem.getField() == field) {
-                return problem.getMessage();
-            }
-        }
-        return null;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineResourceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineResourceTest.java b/src/test/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineResourceTest.java
deleted file mode 100644
index 6b3df76..0000000
--- a/src/test/java/com/kenshoo/freemarker/resources/FreeMarkerOnlineResourceTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.resources;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyMap;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.when;
-
-import java.util.Locale;
-import java.util.TimeZone;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import com.kenshoo.freemarker.services.FreeMarkerService;
-import com.kenshoo.freemarker.view.FreeMarkerOnlineView;
-
-import freemarker.core.OutputFormat;
-
-@RunWith(MockitoJUnitRunner.class)
-public class FreeMarkerOnlineResourceTest {
-
-    @InjectMocks
-    FreeMarkerOnlineResource freeMarkerOnlineResultResource;
-
-    @Mock
-    FreeMarkerService freeMarkerService;
-
-    @Test
-    public void testInitialForm() {
-        when(freeMarkerService.calculateTemplateOutput(
-                anyString(), anyMap(), any(OutputFormat.class), any(Locale.class), any(TimeZone.class)))
-                .thenThrow(new AssertionError());
-        FreeMarkerOnlineView view = freeMarkerOnlineResultResource.blankForm();
-        assertEquals(view.getTemplate(), "");
-        assertEquals(view.getDataModel(), "");
-    }
-    
-    @Test
-    public void testPostedBlankForm() {
-        when(freeMarkerService.calculateTemplateOutput(
-                anyString(), anyMap(), any(OutputFormat.class), any(Locale.class), any(TimeZone.class)))
-                .thenThrow(new AssertionError());
-        FreeMarkerOnlineView view = freeMarkerOnlineResultResource.formResult(null, null, null, null, null);
-        assertEquals(view.getTemplate(), "");
-        assertEquals(view.getDataModel(), "");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/services/FreeMarkerServiceResponseBuilderTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/services/FreeMarkerServiceResponseBuilderTest.java b/src/test/java/com/kenshoo/freemarker/services/FreeMarkerServiceResponseBuilderTest.java
deleted file mode 100644
index caf5ca4..0000000
--- a/src/test/java/com/kenshoo/freemarker/services/FreeMarkerServiceResponseBuilderTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.services;
-
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class FreeMarkerServiceResponseBuilderTest {
-
-    private static final String RESULT = "Result";
-    
-    private final FreeMarkerServiceResponse.Builder builder = new FreeMarkerServiceResponse.Builder();
-
-    @Test
-    public void testSuccessResult() {
-        FreeMarkerServiceResponse result = builder.buildForSuccess(RESULT, false);
-        assertThat(result.getTemplateOutput(), equalTo(RESULT));
-        assertThat(result.isTemplateOutputTruncated(), is(false));
-        assertThat(result.isSuccesful(), is(true));
-        assertThat(result.getFailureReason(), nullValue());
-    }
-        
-    @Test
-    public void testSuccessTruncatedResult() {
-        FreeMarkerServiceResponse result = builder.buildForSuccess(RESULT, true);
-        assertThat(result.getTemplateOutput(), equalTo(RESULT));
-        assertThat(result.isTemplateOutputTruncated(), is(true));
-        assertThat(result.isSuccesful(), is(true));
-        assertThat(result.getFailureReason(), nullValue());
-    }
-
-    @Test
-    public void testErrorResult() {
-        Throwable failureReason = new Exception();
-        FreeMarkerServiceResponse result = builder.buildForFailure(failureReason);
-        assertThat(result.getTemplateOutput(), nullValue());
-        assertThat(result.isTemplateOutputTruncated(), is(false));
-        assertThat(result.isSuccesful(), is(false));
-        assertThat(result.getFailureReason(), sameInstance(failureReason));
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/services/FreeMarkerServiceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/services/FreeMarkerServiceTest.java b/src/test/java/com/kenshoo/freemarker/services/FreeMarkerServiceTest.java
deleted file mode 100644
index 6608d52..0000000
--- a/src/test/java/com/kenshoo/freemarker/services/FreeMarkerServiceTest.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.services;
-
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.hamcrest.Matchers.startsWith;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import freemarker.core.Environment;
-import freemarker.core.HTMLOutputFormat;
-import freemarker.core.ParseException;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-
-@RunWith(MockitoJUnitRunner.class)
-public class FreeMarkerServiceTest {
-
-    private static final Logger LOG = LoggerFactory.getLogger(FreeMarkerServiceTest.class); 
-    
-    private static final int MAX_THREADS = 3;
-    private static final int MAX_QUEUE_LENGTH = 2;
-    private static final int MAX_TEMPLATE_EXECUTION_TIME = 1500;
-
-    private static final int BLOCKING_TEST_TIMEOUT = 5000;
-    
-    private static final String TRUNCATION_TEST_TEMPLATE = "12345";
-    
-    @InjectMocks
-    private FreeMarkerService freeMarkerService;
-    
-    @Before
-    public void initializeSpringBeans() {
-        freeMarkerService.setMaxQueueLength(MAX_QUEUE_LENGTH);
-        freeMarkerService.setMaxThreads(MAX_THREADS);
-        freeMarkerService.postConstruct();
-        freeMarkerService.setMaxTemplateExecutionTime(MAX_TEMPLATE_EXECUTION_TIME);
-    }
-
-    @Test
-    public void testCalculationOfATemplateWithNoDataModel() {
-        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                "test", Collections.<String, Object>emptyMap(), null, null, null);
-        assertThat(serviceResponse.isSuccesful(), is(true));
-        assertThat(serviceResponse.getTemplateOutput(), is("test"));
-    }
-
-    @Test
-    public void testSimpleTemplate() {
-        HashMap<String, Object> dataModel = new HashMap<>();
-        dataModel.put("var1", "val1");
-        String templateSourceCode = "${var1}";
-        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                templateSourceCode, dataModel, null, null, null);
-        assertThat(serviceResponse.getTemplateOutput(), equalTo("val1"));
-    }
-
-    @Test
-    public void testTemplateWithFewArgsAndOperators() {
-        HashMap<String, Object> dataModel = new HashMap<>();
-        dataModel.put("var1", "val1");
-        dataModel.put("var2", "val2");
-        String template = "${var1?capitalize} ${var2?cap_first}";
-        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                template, dataModel, null, null, null);
-        assertThat(serviceResponse.getTemplateOutput(), equalTo("Val1 Val2"));
-    }
-
-    @Test
-    public void testOutputFormatParamterMatters() {
-        String template = "${'&'}";
-        {
-            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                    template, null, null, null, null);
-            assertThat(serviceResponse.getTemplateOutput(), equalTo("&"));
-        }
-        {
-            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                    template, null, HTMLOutputFormat.INSTANCE, null, null);
-            assertThat(serviceResponse.getTemplateOutput(), equalTo("&amp;"));
-        }
-    }
-
-    @Test
-    public void testLocaleParameterMatters() {
-        String template = "${.locale}";
-        {
-            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                    template, null, null, new Locale("en", "US"), null);
-            assertThat(serviceResponse.getTemplateOutput(), equalTo("en_US"));
-        }
-        {
-            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                    template, null, null, new Locale("ru", "RU"), null);
-            assertThat(serviceResponse.getTemplateOutput(), equalTo("ru_RU"));
-        }
-    }
-
-    @Test
-    public void testTimeZoneParameterMatters() {
-        String template = "${" + System.currentTimeMillis() + "?numberToDatetime}";
-        
-        String gmt1Result;
-        {
-            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                    template, null, null, null, TimeZone.getTimeZone("GMT+01"));
-            gmt1Result = serviceResponse.getTemplateOutput();
-        }
-        
-        String gmt2Result;
-        {
-            FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                    template, null, null, new Locale("ru", "RU"), null);
-            gmt2Result = serviceResponse.getTemplateOutput();
-        }
-        
-        assertThat(gmt1Result, not(equalTo(gmt2Result)));
-    }
-    
-    @Test
-    public void testTemplateWithSyntaxError() {
-        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                "test ${xx", Collections.<String, Object>emptyMap(), null, null, null);
-        assertThat(serviceResponse.isSuccesful(), is(false));
-        assertThat(serviceResponse.getFailureReason(), instanceOf(ParseException.class));
-    }
-
-    @Test
-    public void testTemplateWithEvaluationError() {
-        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                "test ${x}", Collections.<String, Object>emptyMap(), null, null, null);
-        assertThat(serviceResponse.isSuccesful(), is(false));
-        assertThat(serviceResponse.getFailureReason(), instanceOf(TemplateException.class));
-    }
-
-    @Test
-    public void testResultAlmostTruncation() {
-        freeMarkerService.setMaxOutputLength(5);
-        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                TRUNCATION_TEST_TEMPLATE, Collections.<String, Object>emptyMap(), null, null, null);
-        assertThat(serviceResponse.isSuccesful(), is(true));
-        assertThat(serviceResponse.isTemplateOutputTruncated(), is(false));
-        assertThat(serviceResponse.getTemplateOutput(), equalTo(TRUNCATION_TEST_TEMPLATE));
-    }
-
-    @Test
-    public void testResultTruncation() {
-        freeMarkerService.setMaxOutputLength(4);
-        FreeMarkerServiceResponse serviceResponse = freeMarkerService.calculateTemplateOutput(
-                TRUNCATION_TEST_TEMPLATE, Collections.<String, Object>emptyMap(), null, null, null);
-        assertThat(serviceResponse.isSuccesful(), is(true));
-        assertThat(serviceResponse.isTemplateOutputTruncated(), is(true));
-        assertThat(serviceResponse.getTemplateOutput(),
-                startsWith(TRUNCATION_TEST_TEMPLATE.substring(0, freeMarkerService.getMaxOutputLength())));
-        assertThat(serviceResponse.getTemplateOutput().charAt(freeMarkerService.getMaxOutputLength()),
-                not(equalTo(TRUNCATION_TEST_TEMPLATE.charAt(freeMarkerService.getMaxOutputLength()))));
-    }
-    
-    @Test
-    public void testTemplateExecutionTimeout() throws InterruptedException, ExecutionException {
-        freeMarkerService.setMaxTemplateExecutionTime(200);
-        
-        // To avoid blocking the CI server forever without giving error:
-        Future<FreeMarkerServiceResponse> future = Executors.newSingleThreadExecutor().submit(
-                new Callable<FreeMarkerServiceResponse>() {
-        
-                    @Override
-                    public FreeMarkerServiceResponse call() throws Exception {
-                        return freeMarkerService.calculateTemplateOutput(
-                                "<#list 1.. as _></#list>", Collections.<String, Object>emptyMap(), null, null, null);
-                    }
-                    
-                });
-        FreeMarkerServiceResponse serviceResponse;
-        try {
-            serviceResponse = future.get(BLOCKING_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
-        } catch (TimeoutException e) {
-            throw new AssertionError("The template execution wasn't aborted (within the timeout).");
-        }
-        assertThat(serviceResponse.isSuccesful(), is(false));
-        assertThat(serviceResponse.getFailureReason(), instanceOf(TimeoutException.class));
-    }
-    
-    @Test
-    public void testServiceOverburden() throws InterruptedException {
-        final BlockerDirective blocker = new BlockerDirective();
-        final Map<String, BlockerDirective> blockerDataModel = Collections.singletonMap("blocker", blocker);
-        try {
-            // Fill all available task "slots":
-            for (int i = 0; i < MAX_THREADS + MAX_QUEUE_LENGTH; i++) {
-                new Thread(new Runnable() {
-                    @Override
-                    public void run() {
-                        freeMarkerService.calculateTemplateOutput("<@blocker/>", blockerDataModel, null, null, null);                    
-                    }
-                }).start();
-            }
-            
-            // Wait until all template executions has started:
-            synchronized (blocker) {
-                final long startTime = System.currentTimeMillis();
-                while (blocker.getEntered() < MAX_THREADS) {
-                    // To avoid blocking the CI server forever is something goes wrong:
-                    if (System.currentTimeMillis() - startTime > BLOCKING_TEST_TIMEOUT) {
-                        fail("JUnit test timed out");
-                    }
-                    blocker.wait(1000);
-                }
-            }
-            Thread.sleep(200);
-            // Because the others are waiting in the queue, and weren't started:
-            assertThat(blocker.getEntered(), not(greaterThan(MAX_THREADS)));
-            
-            // Souldn't accept on more tasks:
-            try {
-                freeMarkerService.calculateTemplateOutput("<@blocker/>", blockerDataModel, null, null, null);
-                fail("Expected RejectedExecutionException, but nothing was thrown.");
-            } catch (RejectedExecutionException e) {
-                // Expected
-            }
-        } finally {
-            // Ensure that the started threads will end:
-            blocker.release();
-        }
-    }
-    
-    private static final class BlockerDirective implements TemplateDirectiveModel {
-        
-        private int entered;
-        private boolean released;
-
-        public synchronized void release() {
-            released = true;
-            notifyAll();
-        }
-        
-        @Override
-        public synchronized void execute(Environment env, @SuppressWarnings("rawtypes") Map params,
-                TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
-            entered++;
-            notifyAll();
-            final long startTime = System.currentTimeMillis();
-            while (!released) {
-                // To avoid blocking the CI server forever is something goes wrong:
-                if (System.currentTimeMillis() - startTime > BLOCKING_TEST_TIMEOUT) {
-                    LOG.error("JUnit test timed out");
-                }
-                try {
-                    wait(1000);
-                } catch (InterruptedException e) {
-                    LOG.error("JUnit test was interrupted");
-                }
-            }
-            LOG.debug("Blocker released");
-        }
-
-        public synchronized int getEntered() {
-            return entered;
-        }
-        
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/util/DataModelParserTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/util/DataModelParserTest.java b/src/test/java/com/kenshoo/freemarker/util/DataModelParserTest.java
deleted file mode 100644
index f651fb8..0000000
--- a/src/test/java/com/kenshoo/freemarker/util/DataModelParserTest.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.util;
-
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import java.math.BigDecimal;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.GregorianCalendar;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Test;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-import freemarker.template.utility.DateUtil;
-
-public class DataModelParserTest {
-    
-    @Test
-    public void testEmpty() throws DataModelParsingException {
-        assertTrue(DataModelParser.parse("", DateUtil.UTC).isEmpty());
-        assertTrue(DataModelParser.parse(" \n ", DateUtil.UTC).isEmpty());
-    }
-
-    @Test
-    public void testSingleAssignment() throws DataModelParsingException {
-        assertEquals(ImmutableMap.of("n", "v"), DataModelParser.parse("n=v", DateUtil.UTC));
-        assertEquals(ImmutableMap.of("n", "v"), DataModelParser.parse("\n\n\tn\t= v", DateUtil.UTC));
-        assertEquals(ImmutableMap.of("longerN", "longer v"), DataModelParser.parse("longerN=longer v", DateUtil.UTC));
-        assertEquals(ImmutableMap.of("a:b.c-d$@", "foo bar\nbaaz"), DataModelParser.parse("a:b.c-d$@ = foo bar\nbaaz", DateUtil.UTC));
-    }
-
-    @Test
-    public void testNotBlankButHasNoAssignment() {
-        try {
-            DataModelParser.parse("x", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("must start with an assignment"));
-        }
-    }
-
-    @Test
-    public void testNoLinebreakBeforeEquals() {
-        try {
-            DataModelParser.parse("x\n=y", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("must start with an assignment"));
-        }
-    }
-
-    @Test
-    public void testMultipleAssignments() throws DataModelParsingException {
-        assertEquals(ImmutableMap.of("n1", "v1", "n2", "v2", "n3", "v3"),
-                DataModelParser.parse("n1=v1\nn2=v2\nn3=v3", DateUtil.UTC));
-        assertEquals(ImmutableMap.of("n1", "v1", "n2", "v2", "n3", "v3"),
-                DataModelParser.parse(" n1 = v1 \r\n\r\n\tn2=v2\nn3 = v3\n\n", DateUtil.UTC));
-        assertEquals(ImmutableMap.of("n1", "=\n=v", "n2", "l1\nl2\n\nl3", "n3", "v3"),
-                DataModelParser.parse("n1==\n=v \n n2=l1\nl2\n\nl3\nn3=v3", DateUtil.UTC));
-    }
-
-    @Test
-    public void testStrings() throws DataModelParsingException {
-        assertEquals(
-                ImmutableMap.of(
-                    "a", "C:\\x",
-                    "b", "foo\nbar",
-                    "c", "foo\t\"bar\"",
-                    "d", "foo\t\"bar\"",
-                    "e", "Foo's"
-                ),
-                DataModelParser.parse(
-                        "a=C:\\x\n"
-                        + "b=foo\nbar\n"
-                        + "c=foo\t\"bar\"\n"
-                        + "d=\"foo\\t\\\"bar\\\"\"\n"
-                        + "e=\"Foo's\"",
-                        DateUtil.UTC));
-        try {
-            DataModelParser.parse("a=\"foo", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("quoted"));
-        }
-        try {
-            DataModelParser.parse("a='foo'", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("quoted"));
-        }
-        try {
-            DataModelParser.parse("a=\"\\x\"", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("escape"));
-        }
-    }
-    
-    @Test
-    public void testBasicNumbers() throws DataModelParsingException {
-        assertEquals(
-                ImmutableMap.of(
-                    "a", BigDecimal.valueOf(1),
-                    "b", BigDecimal.valueOf(1.5),
-                    "c", BigDecimal.valueOf(-1.5),
-                    "d", BigDecimal.valueOf(1.5),
-                    "e", BigDecimal.valueOf(-0.125)
-                ),
-                DataModelParser.parse("a=1\nb=1.5\nc=-1.5\nd=+1.5\ne=-12.5e-2", DateUtil.UTC));
-        try {
-            DataModelParser.parse("a=1,5", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("Malformed number"));
-            assertThat(e.getMessage(), not(containsString("ISO")));
-        }
-    }
-    
-    @Test
-    public void testSpecialNumbers() throws DataModelParsingException {
-    assertEquals(
-            ImmutableMap.of(
-                "a", Double.NaN,
-                "b", Double.POSITIVE_INFINITY,
-                "c", Double.NEGATIVE_INFINITY,
-                "d", Double.POSITIVE_INFINITY
-            ),
-            DataModelParser.parse("a=NaN\nb=Infinity\nc=-Infinity\nd=+Infinity", DateUtil.UTC));
-    }
-
-    @Test
-    public void testBooleans() throws DataModelParsingException {
-        assertEquals(ImmutableMap.of("a", true, "b", false), DataModelParser.parse("a=true\nb=false", DateUtil.UTC));
-        try {
-            DataModelParser.parse("a=True", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("true"));
-        }
-    }
-    
-    @Test
-    public void testTemporals() throws DataModelParsingException {
-        final Map<String, Object> dm = DataModelParser.parse("a=2014-02-12T01:02:03Z\nb=2014-02-12\nc=01:02:03Z", DateUtil.UTC);
-        
-        final GregorianCalendar cal = new GregorianCalendar(DateUtil.UTC);
-        cal.clear();
-        
-        cal.set(2014, 1, 12, 1, 2, 3);
-        Timestamp a = new Timestamp(cal.getTimeInMillis());
-        assertThat(dm.get("a"), instanceOf(Timestamp.class));
-        assertEquals(dm.get("a"), a);
-        
-        cal.set(2014, 1, 12, 0, 0, 0);
-        java.sql.Date b = new java.sql.Date(cal.getTimeInMillis());
-        assertThat(dm.get("b"), instanceOf(java.sql.Date.class));
-        assertEquals(dm.get("b"), b);
-        
-        cal.set(1970, 0, 1, 1, 2, 3);
-        Time c = new Time(cal.getTimeInMillis());
-        assertThat(dm.get("c"), instanceOf(Time.class));
-        assertEquals(dm.get("c"), c);
-        
-        try {
-            DataModelParser.parse("a=2012T123", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("ISO 8601 date-time"));
-        }
-        try {
-            DataModelParser.parse("a=2012-0102", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("ISO 8601 date"));
-        }
-        try {
-            DataModelParser.parse("a=25:00", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("ISO 8601 time"));
-        }
-    }
-    
-    @Test
-    public void testMaps() throws DataModelParsingException {
-        final Object map = DataModelParser.parse(
-                "n = {\n"
-                + "\t\"a\": 1,\n"
-                + "\t\"b\": 2\n"
-                + "}",
-                DateUtil.UTC)
-                .get("n");
-        assertEquals(ImmutableMap.of("a", 1, "b", 2), map);
-        assertThat(map, instanceOf(LinkedHashMap.class));
-        try {
-            DataModelParser.parse("n={1:2}", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("JSON"));
-        }
-    }    
-    
-    @Test
-    public void testLists() throws DataModelParsingException {
-        final Object list = DataModelParser.parse("n=[1, 2]", DateUtil.UTC).get("n");
-        assertEquals(ImmutableList.of(1, 2), list);
-        assertThat(list, instanceOf(List.class));
-        try {
-            DataModelParser.parse("n=[", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("JSON"));
-        }
-    }
-
-    @Test
-    public void testXML() throws DataModelParsingException {
-        final Object doc = DataModelParser.parse("n=<e xmlns='foo:/bar' a='123'>text</e>", DateUtil.UTC).get("n");
-        assertThat(doc, instanceOf(Document.class));
-        final Node firstChild = ((Document) doc).getFirstChild();
-        assertEquals("e", firstChild.getNodeName());
-        assertEquals("foo:/bar", firstChild.getNamespaceURI());
-        
-        try {
-            DataModelParser.parse("n=<ns:e />", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("XML"));
-        }
-    }
-    
-    @Test
-    public void testNull() throws DataModelParsingException {
-        assertNull(DataModelParser.parse("n=null", DateUtil.UTC).get("n"));
-        try {
-            DataModelParser.parse("a=NULL", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("null"));
-        }
-    }
-
-    @Test
-    public void testEmptyValue() throws DataModelParsingException {
-        try {
-            DataModelParser.parse("n=", DateUtil.UTC);
-            fail();
-        } catch (DataModelParsingException e) {
-            assertThat(e.getMessage(), containsString("Empty"));
-        }
-        
-        assertEquals("", DataModelParser.parse("n=\"\"", DateUtil.UTC).get("n"));
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/util/LengthLimitedWriterTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/util/LengthLimitedWriterTest.java b/src/test/java/com/kenshoo/freemarker/util/LengthLimitedWriterTest.java
deleted file mode 100644
index c56d52e..0000000
--- a/src/test/java/com/kenshoo/freemarker/util/LengthLimitedWriterTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.util;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.io.StringWriter;
-
-import org.junit.Test;
-
-public class LengthLimitedWriterTest {
-
-    private StringWriter wrappedW = new StringWriter();
-    private LengthLimitedWriter w = new LengthLimitedWriter(wrappedW, 5);
-    
-    @Test
-    public void testLimitNotExceeded() throws IOException {
-        w.write("123");
-        w.write("45");
-    }
-
-    @Test
-    public void testLimitExceededWithString() throws IOException {
-        w.write("123");
-        try {
-            w.write("456");
-            fail();
-        } catch (LengthLimitExceededException e) {
-            assertEquals("12345", wrappedW.toString());
-        }
-    }
-
-    @Test
-    public void testLimitExceededWithCharArray() throws IOException {
-        w.write(new char[] { '1', '2', '3' });
-        try {
-            w.write(new char[] { '4', '5', '6' });
-            fail();
-        } catch (LengthLimitExceededException e) {
-            assertEquals("12345", wrappedW.toString());
-        }
-    }
-
-    @Test
-    public void testLimitExceededWithChar() throws IOException {
-        w.write('1');
-        w.write('2');
-        w.write('3');
-        w.write('4');
-        w.write('5');
-        try {
-            w.write('6');
-            fail();
-        } catch (LengthLimitExceededException e) {
-            assertEquals("12345", wrappedW.toString());
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/com/kenshoo/freemarker/view/FreeMarkerOnlineViewTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/com/kenshoo/freemarker/view/FreeMarkerOnlineViewTest.java b/src/test/java/com/kenshoo/freemarker/view/FreeMarkerOnlineViewTest.java
deleted file mode 100644
index c67b44c..0000000
--- a/src/test/java/com/kenshoo/freemarker/view/FreeMarkerOnlineViewTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.kenshoo.freemarker.view;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.Locale;
-import java.util.TimeZone;
-
-import org.junit.Test;
-
-import com.kenshoo.freemarker.services.AllowedSettingValuesMaps;
-
-import freemarker.core.HTMLOutputFormat;
-
-
-public class FreeMarkerOnlineViewTest {
-
-    private static final String TEMPLATE = "Template";
-    private static final String DATA_MODEL = "DataModel";
-
-    @Test
-    public void testVieEmptyConstrucotr() {
-        FreeMarkerOnlineView view = new FreeMarkerOnlineView();
-        assertEquals(view.getTemplate(), "");
-        assertEquals(view.getDataModel(), "");
-        assertEquals(view.getOutputFormat(), AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT_KEY);
-        assertEquals(view.getLocale(), AllowedSettingValuesMaps.DEFAULT_LOCALE_KEY);
-        assertEquals(view.getTimeZone(), AllowedSettingValuesMaps.DEFAULT_TIME_ZONE_KEY);
-    }
-
-    @Test
-    public void testViewWhenAllOK() {
-        FreeMarkerOnlineView view = new FreeMarkerOnlineView();
-        
-        view.setTemplate(TEMPLATE);
-        view.setDataModel(DATA_MODEL);
-        String outputFormatStr = HTMLOutputFormat.INSTANCE.getName();
-        view.setOutputFormat(outputFormatStr);
-        String localeStr = Locale.GERMAN.toString();
-        view.setLocale(localeStr);
-        String timeZoneStr = TimeZone.getTimeZone("GMT+01").getID();
-        view.setTimeZone(timeZoneStr);
-        
-        assertEquals(view.getTemplate(), TEMPLATE);
-        assertEquals(view.getDataModel(), DATA_MODEL);
-        assertEquals(view.getOutputFormat(), outputFormatStr);
-        assertEquals(view.getLocale(), localeStr);
-        assertEquals(view.getTimeZone(), timeZoneStr);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/platform/DropWizardServiceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/platform/DropWizardServiceTest.java b/src/test/java/org/apache/freemarker/onlinetester/platform/DropWizardServiceTest.java
new file mode 100644
index 0000000..f23672c
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/platform/DropWizardServiceTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.platform;
+
+import com.google.common.io.Resources;
+import org.apache.freemarker.onlinetester.dropwizard.ApplicationStartup;
+import com.yammer.dropwizard.testing.junit.DropwizardServiceRule;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+public class DropWizardServiceTest {
+    @ClassRule
+    public static TestRule testRule = new DropwizardServiceRule<>(ApplicationStartup.class,
+            Resources.getResource("freemarker-online.yml").getPath());
+
+
+    @Test
+    public void testServerIsUp() throws Exception {
+        ((DropwizardServiceRule) testRule).getService();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/platform/YamlPropertiesPersister.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/platform/YamlPropertiesPersister.java b/src/test/java/org/apache/freemarker/onlinetester/platform/YamlPropertiesPersister.java
new file mode 100644
index 0000000..4257e40
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/platform/YamlPropertiesPersister.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.platform;
+
+import com.fasterxml.jackson.dataformat.yaml.snakeyaml.Yaml;
+import org.springframework.util.PropertiesPersister;
+import org.springframework.util.StringUtils;
+
+import java.io.*;
+import java.util.Map;
+import java.util.Properties;
+
+public class YamlPropertiesPersister implements PropertiesPersister {
+    @Override
+    public void load(Properties props, InputStream is) throws IOException {
+        load(props, new InputStreamReader(is));
+    }
+
+    /**
+     * We want to traverse map representing Yaml object and each time we find String=String pair we want to
+     * save it as Property. As we are going deeper into map we generate compound key as path-like String
+     *
+     * @see org.springframework.util.PropertiesPersister#load(java.util.Properties, java.io.Reader)
+     */
+    @Override
+    public void load(Properties props, Reader reader) throws IOException {
+        Yaml yaml = new Yaml();
+        @SuppressWarnings("unchecked")
+        Map<String, Object> map = (Map<String, Object>) yaml.load(reader);
+        // now we can populate supplied props
+        assignProperties(props, map, null);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void assignProperties(Properties props, Map<String, Object> map, String path) {
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+            String key = entry.getKey();
+            if (!StringUtils.isEmpty(path))
+                key = path + "." + key;
+            Object val = entry.getValue();
+            if (val instanceof String) {
+                // see if we need to create a compound key
+                props.put(key, val);
+            } else if (val instanceof Map) {
+                assignProperties(props, (Map<String, Object>) val, key);
+            }
+        }
+    }
+
+    @Override
+    public void store(Properties props, OutputStream os, String header) throws IOException {
+        throw new IllegalStateException("Current implementation is a read-only");
+    }
+
+    @Override
+    public void store(Properties props, Writer writer, String header) throws IOException {
+        throw new IllegalStateException("Current implementation is a read-only");
+    }
+
+    @Override
+    public void loadFromXml(Properties props, InputStream is) throws IOException {
+        throw new IllegalStateException("Use DefaultPropertiesPersister if you want to read/write XML");
+    }
+
+    @Override
+    public void storeToXml(Properties props, OutputStream os, String header) throws IOException {
+        throw new IllegalStateException("Use DefaultPropertiesPersister if you want to load/store to XML");
+    }
+
+    @Override
+    public void storeToXml(Properties props, OutputStream os, String header, String encoding) throws IOException {
+        throw new IllegalStateException("Use DefaultPropertiesPersister if you want to read/write XML");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineExecuteResourceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineExecuteResourceTest.java b/src/test/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineExecuteResourceTest.java
new file mode 100644
index 0000000..d0f81cb
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineExecuteResourceTest.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.resources;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.freemarker.onlinetester.model.ExecuteRequest;
+import org.apache.freemarker.onlinetester.model.ExecuteResourceField;
+import org.apache.freemarker.onlinetester.model.ExecuteResourceProblem;
+import org.apache.freemarker.onlinetester.model.ExecuteResponse;
+import org.junit.Test;
+import org.springframework.web.context.ContextLoaderListener;
+import org.springframework.web.context.request.RequestContextListener;
+
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
+import com.sun.jersey.test.framework.AppDescriptor;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+public class FreeMarkerOnlineExecuteResourceTest extends JerseyTest {
+    private static final String DATA_MODEL = "user=John";
+    private static final String TEMPLATE_WITH_VARIABLE = "Welcome ${user}";
+    private static final String TEMPLATE_PLAIN = "Welcome John";
+    private static final String MALFORMED_DATA_MODEL = "userJohn";
+    private static final String EXECUTE_API = "api/execute";
+    @Override
+    protected AppDescriptor configure() {
+        return new WebAppDescriptor.Builder("org.apache.freemarker.onlinetester.resources")
+                        .contextPath("/")
+                        .contextListenerClass(ContextLoaderListener.class)
+                        .contextParam("contextConfigLocation", "classpath:spring/bootstrap-context.xml")
+                        .servletClass(SpringServlet.class)
+                        .requestListenerClass(RequestContextListener.class)
+                        .build();
+    }
+
+    @Test
+    public void testSuccessRequest() throws Exception {
+        ExecuteRequest req = new ExecuteRequest(TEMPLATE_WITH_VARIABLE, DATA_MODEL);
+        ClientResponse resp = client().resource(getBaseURI().toString() + EXECUTE_API)
+                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
+        assertEquals(200, resp.getStatus());
+        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
+        assertNull(response.getProblems());
+    }
+
+    @Test
+    public void testMalformedDataModel() throws Exception {
+        ExecuteRequest req = new ExecuteRequest(TEMPLATE_PLAIN, MALFORMED_DATA_MODEL);
+        ClientResponse resp = client().resource(getBaseURI().toString() + EXECUTE_API)
+                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
+        assertEquals(200, resp.getStatus());
+        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
+        assertNotNull(response.getProblems());
+        assertTrue(containsProblem(response, ExecuteResourceField.DATA_MODEL));
+    }
+
+    @Test
+    public void testLongDataModel() throws Exception {
+        ExecuteRequest req = new ExecuteRequest(TEMPLATE_PLAIN, create30KString());
+        ClientResponse resp = client().resource(getBaseURI().toString() + EXECUTE_API)
+                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
+        assertEquals(200, resp.getStatus());
+        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
+        assertNotNull(response.getProblems());
+        assertTrue(containsProblem(response, ExecuteResourceField.DATA_MODEL));
+        String problemMessage = getProblemMessage(response, ExecuteResourceField.DATA_MODEL);
+        assertThat(problemMessage, containsString("data model"));
+        assertThat(problemMessage, containsString("limit"));
+    }
+
+    @Test
+    public void testLongTemplate() throws Exception {
+        ExecuteRequest req = new ExecuteRequest(create30KString(), DATA_MODEL);
+        ClientResponse resp = client().resource(getBaseURI().toString() + EXECUTE_API)
+                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
+        assertEquals(200, resp.getStatus());
+        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
+        assertNotNull(response.getProblems());
+        assertTrue(containsProblem(response, ExecuteResourceField.TEMPLATE));
+        String problemMessage = getProblemMessage(response, ExecuteResourceField.TEMPLATE);
+        assertThat(problemMessage, containsString("template"));
+        assertThat(problemMessage, containsString("limit"));
+    }
+
+    @Test
+    public void testMultipleErrorsDataModel() throws Exception {
+        ExecuteRequest req = new ExecuteRequest(create30KString(), create30KString());
+        req.setOutputFormat("wrongOutputFormat");
+        req.setLocale("wrongLocale");
+        req.setTimeZone("wrongTimeZone");
+        
+        ClientResponse resp = client().resource(getBaseURI() + EXECUTE_API)
+                .header("Content-Type", "application/json").entity(req).post(ClientResponse.class);
+        
+        assertEquals(200, resp.getStatus());
+        ExecuteResponse response = resp.getEntity(ExecuteResponse.class);
+        assertNotNull(response.getProblems());
+        assertThat(getProblemMessage(response, ExecuteResourceField.TEMPLATE), containsString("limit"));
+        assertThat(getProblemMessage(response, ExecuteResourceField.DATA_MODEL), containsString("limit"));
+        assertThat(getProblemMessage(response, ExecuteResourceField.OUTPUT_FORMAT), containsString("wrongOutputFormat"));
+        assertThat(getProblemMessage(response, ExecuteResourceField.LOCALE), containsString("wrongLocale"));
+        assertThat(getProblemMessage(response, ExecuteResourceField.TIME_ZONE), containsString("wrongTimeZone"));
+    }
+    
+    private String create30KString() {
+        final String veryLongString;
+        {
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < 30000 / 10; i++) {
+                sb.append("0123456789");
+            }
+            veryLongString = sb.toString();
+        }
+        return veryLongString;
+    }
+
+    private boolean containsProblem(ExecuteResponse response, ExecuteResourceField field) {
+        for (ExecuteResourceProblem problem : response.getProblems()) {
+            if (problem.getField() == field) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private String getProblemMessage(ExecuteResponse response, ExecuteResourceField field) {
+        for (ExecuteResourceProblem problem : response.getProblems()) {
+            if (problem.getField() == field) {
+                return problem.getMessage();
+            }
+        }
+        return null;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineResourceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineResourceTest.java b/src/test/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineResourceTest.java
new file mode 100644
index 0000000..4f6ef7c
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/resources/FreeMarkerOnlineResourceTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.resources;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyMap;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import org.apache.freemarker.onlinetester.services.FreeMarkerService;
+import org.apache.freemarker.onlinetester.view.FreeMarkerOnlineView;
+
+import freemarker.core.OutputFormat;
+
+@RunWith(MockitoJUnitRunner.class)
+public class FreeMarkerOnlineResourceTest {
+
+    @InjectMocks
+    FreeMarkerOnlineResource freeMarkerOnlineResultResource;
+
+    @Mock
+    FreeMarkerService freeMarkerService;
+
+    @Test
+    public void testInitialForm() {
+        when(freeMarkerService.calculateTemplateOutput(
+                anyString(), anyMap(), any(OutputFormat.class), any(Locale.class), any(TimeZone.class)))
+                .thenThrow(new AssertionError());
+        FreeMarkerOnlineView view = freeMarkerOnlineResultResource.blankForm();
+        assertEquals(view.getTemplate(), "");
+        assertEquals(view.getDataModel(), "");
+    }
+    
+    @Test
+    public void testPostedBlankForm() {
+        when(freeMarkerService.calculateTemplateOutput(
+                anyString(), anyMap(), any(OutputFormat.class), any(Locale.class), any(TimeZone.class)))
+                .thenThrow(new AssertionError());
+        FreeMarkerOnlineView view = freeMarkerOnlineResultResource.formResult(null, null, null, null, null);
+        assertEquals(view.getTemplate(), "");
+        assertEquals(view.getDataModel(), "");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker-online-tester/blob/2f0c0424/src/test/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceResponseBuilderTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceResponseBuilderTest.java b/src/test/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceResponseBuilderTest.java
new file mode 100644
index 0000000..f83a1b4
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/onlinetester/services/FreeMarkerServiceResponseBuilderTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.onlinetester.services;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class FreeMarkerServiceResponseBuilderTest {
+
+    private static final String RESULT = "Result";
+    
+    private final FreeMarkerServiceResponse.Builder builder = new FreeMarkerServiceResponse.Builder();
+
+    @Test
+    public void testSuccessResult() {
+        FreeMarkerServiceResponse result = builder.buildForSuccess(RESULT, false);
+        assertThat(result.getTemplateOutput(), equalTo(RESULT));
+        assertThat(result.isTemplateOutputTruncated(), is(false));
+        assertThat(result.isSuccesful(), is(true));
+        assertThat(result.getFailureReason(), nullValue());
+    }
+        
+    @Test
+    public void testSuccessTruncatedResult() {
+        FreeMarkerServiceResponse result = builder.buildForSuccess(RESULT, true);
+        assertThat(result.getTemplateOutput(), equalTo(RESULT));
+        assertThat(result.isTemplateOutputTruncated(), is(true));
+        assertThat(result.isSuccesful(), is(true));
+        assertThat(result.getFailureReason(), nullValue());
+    }
+
+    @Test
+    public void testErrorResult() {
+        Throwable failureReason = new Exception();
+        FreeMarkerServiceResponse result = builder.buildForFailure(failureReason);
+        assertThat(result.getTemplateOutput(), nullValue());
+        assertThat(result.isTemplateOutputTruncated(), is(false));
+        assertThat(result.isSuccesful(), is(false));
+        assertThat(result.getFailureReason(), sameInstance(failureReason));
+    }
+    
+}