Author: gk
Date: Thu Dec 13 14:54:04 2018
New Revision: 1848852
URL: http://svn.apache.org/viewvc?rev=1848852&view=rev
Log:
- update parent in master pom.xml to get the tests run
- migrate Fulcrum components crypto, intake, parser to Junit 5
- fix basedir in crypto
- update formatting in testcontainer, json
Modified:
turbine/fulcrum/trunk/crypto/src/test/org/apache/fulcrum/crypto/CryptoServiceTest.java
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeServiceTest.java
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeTest.java
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeValidatonTest.java
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java
turbine/fulcrum/trunk/json/jackson2/src/test/log4j2.xml
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/DefaultServiceTest.java
turbine/fulcrum/trunk/parser/src/test/org/apache/fulcrum/parser/BaseValueParserTest.java
turbine/fulcrum/trunk/parser/src/test/org/apache/fulcrum/parser/ParameterParserTest.java
turbine/fulcrum/trunk/parser/src/test/org/apache/fulcrum/parser/ParserServiceTest.java
turbine/fulcrum/trunk/pom.xml
turbine/fulcrum/trunk/template/pom.xml
turbine/fulcrum/trunk/template/xdocs/index.xml
turbine/fulcrum/trunk/testcontainer/pom.xml
turbine/fulcrum/trunk/testcontainer/src/java/org/apache/fulcrum/testcontainer/BaseUnit5Test.java
turbine/fulcrum/trunk/testcontainer/src/java/org/apache/fulcrum/testcontainer/ECMContainer.java
turbine/fulcrum/trunk/testcontainer/src/test/log4j2.xml
turbine/fulcrum/trunk/testcontainer/src/test/org/apache/fulcrum/testcontainer/YaafiContainerJunit5Test.java
turbine/fulcrum/trunk/testcontainer/xdocs/index.xml
Modified:
turbine/fulcrum/trunk/crypto/src/test/org/apache/fulcrum/crypto/CryptoServiceTest.java
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/crypto/src/test/org/apache/fulcrum/crypto/CryptoServiceTest.java?rev=1848852&r1=1848851&r2=1848852&view=diff
==============================================================================
---
turbine/fulcrum/trunk/crypto/src/test/org/apache/fulcrum/crypto/CryptoServiceTest.java
(original)
+++
turbine/fulcrum/trunk/crypto/src/test/org/apache/fulcrum/crypto/CryptoServiceTest.java
Thu Dec 13 14:54:04 2018
@@ -20,7 +20,14 @@ package org.apache.fulcrum.crypto;
*/
-import org.apache.fulcrum.testcontainer.BaseUnitTest;
+import org.apache.fulcrum.testcontainer.BaseUnit5Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
/**
* Basic testing of the Container
@@ -29,7 +36,8 @@ import org.apache.fulcrum.testcontainer.
* @author <a href="mailto:[email protected]">Stephen McConnell</a>
* @version $Id$
*/
-public class CryptoServiceTest extends BaseUnitTest
+@DisplayName("Crypto Service Test")
+public class CryptoServiceTest extends BaseUnit5Test
{
private CryptoService sc = null;
private static final String preDefinedInput = "Oeltanks";
@@ -37,21 +45,21 @@ public class CryptoServiceTest extends B
/**
* Constructor for test.
*
- * @param testName name of the test being executed
+ * @param testInfo Junit 5 info object of the test being executed
*/
- public CryptoServiceTest(String testName)
+ public CryptoServiceTest(TestInfo testInfo)
{
- super(testName);
- }
+ }
+ @BeforeEach
public void setUp() throws Exception
{
- super.setUp();
sc = (CryptoService) this.lookup( CryptoService.ROLE );
-
}
+
+ @Test
public void testUnixCrypt() throws Exception
{
String preDefinedSeed = "z5";
@@ -63,7 +71,7 @@ public class CryptoServiceTest extends B
*/
ca.setSeed(preDefinedSeed);
String output = ca.encrypt(preDefinedInput);
- assertEquals("Encryption failed ", preDefinedResult, output);
+ assertEquals( preDefinedResult, output, "Encryption failed ");
/*
* Test random Seed
*
@@ -72,22 +80,21 @@ public class CryptoServiceTest extends B
String result = ca.encrypt(preDefinedInput);
ca.setSeed(result);
output = ca.encrypt(preDefinedInput);
- assertEquals("Encryption failed ", output, result);
-
-
+ assertEquals( output, result, "Encryption failed ");
}
-
+ @Test
public void testClearCrypt() throws Exception
{
String preDefinedResult = "Oeltanks";
CryptoAlgorithm ca = sc.getCryptoAlgorithm("clear");
String output = ca.encrypt(preDefinedInput);
- assertEquals("Encryption failed ", preDefinedResult, output);
+ assertEquals( preDefinedResult, output, "Encryption failed ");
}
-
+ @Test
+ @DisplayName("OldJavaCrypt: Truncated base64 from MD5 (Turbine 2.1) Test")
public void testOldJavaCryptMd5() throws Exception
{
String preDefinedResult = "XSop0mncK19Ii2r2CUe2";
@@ -95,9 +102,10 @@ public class CryptoServiceTest extends B
CryptoAlgorithm ca = sc.getCryptoAlgorithm("oldjava");
ca.setCipher("MD5");
String output = ca.encrypt(preDefinedInput);
- assertEquals("MD5 Encryption failed ", preDefinedResult, output);
+ assertEquals( preDefinedResult, output, "MD5 Encryption failed ");
}
+ @Test
public void testOldJavaCryptSha1() throws Exception
{
String preDefinedResult = "uVDiJHaavRYX8oWt5ctkaa7j";
@@ -105,37 +113,36 @@ public class CryptoServiceTest extends B
CryptoAlgorithm ca = sc.getCryptoAlgorithm("oldjava");
ca.setCipher("SHA1");
String output = ca.encrypt(preDefinedInput);
- assertEquals("SHA1 Encryption failed ", preDefinedResult, output);
+ assertEquals( preDefinedResult, output, "SHA1 Encryption failed ");
}
+ @Test
public void testJavaCryptMd5() throws Exception
{
String preDefinedResult = "XSop0mncK19Ii2r2CUe29w==";
CryptoAlgorithm ca = sc.getCryptoAlgorithm("java");
ca.setCipher("MD5");
String output = ca.encrypt(preDefinedInput);
- assertEquals("MD5 Encryption failed ", preDefinedResult, output);
+ assertEquals( preDefinedResult, output, "MD5 Encryption failed ");
}
-
+ @Test
public void testJavaCryptSha1() throws Exception
{
String preDefinedResult = "uVDiJHaavRYX8oWt5ctkaa7j1cw=";
CryptoAlgorithm ca = sc.getCryptoAlgorithm("java");
ca.setCipher("SHA1");
String output = ca.encrypt(preDefinedInput);
- assertEquals("SHA1 Encryption failed ", preDefinedResult, output);
+ assertEquals( preDefinedResult, output, "SHA1 Encryption failed ");
}
-
- public void testJavaCryptSha256() throws Exception
+ @Test
+ public void testJavaCryptSha256() throws Exception
{
-
String preDefinedResult =
"XBSqev4ilv7P7852G2rL5WgX3FLy8VzfOY+tVq+xjek=";
CryptoAlgorithm ca = sc.getCryptoAlgorithm("java");
ca.setCipher("SHA-256");
String output = ca.encrypt(preDefinedInput);
- assertEquals("SHA256 Encryption failed ", preDefinedResult, output);
-
+ assertEquals( preDefinedResult, output, "SHA256 Encryption failed ");
}
}
Modified:
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeServiceTest.java
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeServiceTest.java?rev=1848852&r1=1848851&r2=1848852&view=diff
==============================================================================
---
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeServiceTest.java
(original)
+++
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeServiceTest.java
Thu Dec 13 14:54:04 2018
@@ -1,5 +1,6 @@
package org.apache.fulcrum.intake;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -19,36 +20,41 @@ package org.apache.fulcrum.intake;
* under the License.
*/
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+
import java.io.File;
import org.apache.fulcrum.intake.model.Group;
-import org.apache.fulcrum.testcontainer.BaseUnit4Test;
-import org.junit.Before;
-import org.junit.Test;
+import org.apache.fulcrum.testcontainer.BaseUnit5Test;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
/**
* @author Eric Pugh
*
*/
-public class IntakeServiceTest extends BaseUnit4Test
+public class IntakeServiceTest extends BaseUnit5Test
{
- private static final File BASEDIR = new File( System.getProperty(
"basedir" ));
+ private static final File BASEDIR = new File(".");// System.getProperty(
"basedir" )
private IntakeService intakeService = null;
/**
- * Defines the testcase for JUnit4.
+ * Defines the testcase for JUnit5.
*
*/
- public IntakeServiceTest() {
+ public IntakeServiceTest(TestInfo testInfo) {
+
}
- @Before
+ @BeforeEach
public void setUp() throws Exception
{
File appData = new File( BASEDIR, "target/appData.ser");
@@ -70,9 +76,7 @@ public class IntakeServiceTest extends B
Group group = intakeService.getGroup("LoginGroup");
File file = new File( BASEDIR, "target/appData.ser");
- assertTrue(
- "Make sure serialized data file exists:" + file,
- file.exists());
+ assertTrue(file.exists(), "Make sure serialized data file exists:" +
file);
assertNotNull(group);
assertEquals("loginGroupKey", group.getGID());
Modified:
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeTest.java
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeTest.java?rev=1848852&r1=1848851&r2=1848852&view=diff
==============================================================================
---
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeTest.java
(original)
+++
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeTest.java
Thu Dec 13 14:54:04 2018
@@ -19,7 +19,6 @@ package org.apache.fulcrum.intake;
* under the License.
*/
-import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Locale;
@@ -38,9 +37,18 @@ import org.apache.fulcrum.intake.validat
import org.apache.fulcrum.parser.DefaultParameterParser;
import org.apache.fulcrum.parser.ParserService;
import org.apache.fulcrum.parser.ValueParser;
-import org.apache.fulcrum.testcontainer.BaseUnit4Test;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.apache.fulcrum.testcontainer.BaseUnit5Test;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
/**
* Test the facade class for the service
*
@@ -48,13 +56,13 @@ import org.junit.Test;
* @author <a href="mailto:[email protected]">Jürgen Hoffmann</a>
* @version $Id$
*/
-public class IntakeTest extends BaseUnit4Test
+public class IntakeTest extends BaseUnit5Test
{
/**
- * Defines the testcase for JUnit4.
+ * Defines the testcase for JUnit5.
*
*/
- public IntakeTest()
+ public IntakeTest(TestInfo testInfo)
{
}
@@ -63,7 +71,7 @@ public class IntakeTest extends BaseUnit
* This looks strange to me. A test should not bother with explicit
initialization.
* That's the task of the container.
*/
- @Ignore
+ @Disabled
public void OFFtestFacadeNotConfigured() throws Exception
{
assertFalse(IntakeServiceFacade.isInitialized());
@@ -108,7 +116,7 @@ public class IntakeTest extends BaseUnit
LoginForm form = new LoginForm();
group.setProperties(form);
- assertEquals("User names should be equal", "Joe", form.getUsername());
+ assertEquals("Joe", form.getUsername(), "User names should be equal");
}
@Test
@@ -126,10 +134,10 @@ public class IntakeTest extends BaseUnit
pp.setString("loginGroupKey_0loginUsernameKey", "Joe");
group.init(pp);
- assertTrue("The field should be set", userNameField.isSet());
- assertTrue("The field should be validated",
userNameField.isValidated());
- assertTrue("The field should be valid", userNameField.isValid());
- assertEquals("The field should have the value Joe", "Joe",
userNameField.getValue());
+ assertTrue(userNameField.isSet(), "The field should be set");
+ assertTrue( userNameField.isValidated(), "The field should be
validated");
+ assertTrue( userNameField.isValid(), "The field should be valid");
+ assertEquals("Joe", userNameField.getValue(), "The field should have
the value Joe");
}
@Test
@@ -141,8 +149,8 @@ public class IntakeTest extends BaseUnit
assertTrue(IntakeServiceFacade.isInitialized());
group = IntakeServiceFacade.getGroup("BooleanTest");
Field<?> booleanField = group.get("EmptyBooleanTestField");
- assertTrue("The Default Validator of an intake Field type boolean
should be BooleanValidator", (booleanField.getValidator() instanceof
BooleanValidator));
- assertFalse("An Empty intake Field type boolean should not be
required", booleanField.isRequired());
+ assertTrue( (booleanField.getValidator() instanceof BooleanValidator),
"The Default Validator of an intake Field type boolean should be
BooleanValidator");
+ assertFalse( booleanField.isRequired(), "An Empty intake Field type
boolean should not be required");
}
@Test
@@ -154,8 +162,8 @@ public class IntakeTest extends BaseUnit
assertTrue(IntakeServiceFacade.isInitialized());
group = IntakeServiceFacade.getGroup("BooleanTest");
Field<?> booleanField = group.get("BooleanTestField");
- assertTrue("The Default Validator of an intake Field type boolean
should be BooleanValidator", (booleanField.getValidator() instanceof
BooleanValidator));
- assertFalse("An intake Field type boolean, which is not required,
should not be required", booleanField.isRequired());
+ assertTrue( booleanField.getValidator() instanceof BooleanValidator,
"The Default Validator of an intake Field type boolean should be
BooleanValidator");
+ assertFalse( booleanField.isRequired(), "An intake Field type boolean,
which is not required, should not be required");
}
@Test
@@ -167,8 +175,8 @@ public class IntakeTest extends BaseUnit
assertTrue(IntakeServiceFacade.isInitialized());
group = IntakeServiceFacade.getGroup("BooleanTest");
Field<?> booleanField = group.get("RequiredBooleanTestField");
- assertTrue("The Default Validator of an intake Field type boolean
should be BooleanValidator", (booleanField.getValidator() instanceof
BooleanValidator));
- assertTrue("An intake Field type boolean, which is required, should be
required", booleanField.isRequired());
+ assertTrue( booleanField.getValidator() instanceof BooleanValidator,
"The Default Validator of an intake Field type boolean should be
BooleanValidator");
+ assertTrue( booleanField.isRequired(), "An intake Field type boolean,
which is required, should be required");
}
@Test
@@ -178,8 +186,8 @@ public class IntakeTest extends BaseUnit
Group group = is.getGroup("NumberTest");
assertNotNull(group);
Field<?> multiValueField = group.get("MultiIntegerTestField");
- assertTrue("The Default Validator of an intake Field type int should
be IntegerValidator", (multiValueField.getValidator() instanceof
IntegerValidator));
- assertTrue("An intake Field type int, which is multiValued, should be
multiValued", multiValueField.isMultiValued());
+ assertTrue( (multiValueField.getValidator() instanceof
IntegerValidator), "The Default Validator of an intake Field type int should be
IntegerValidator");
+ assertTrue( multiValueField.isMultiValued(), "An intake Field type
int, which is multiValued, should be multiValued");
ParserService ps = (ParserService) this.lookup( ParserService.ROLE );
ValueParser pp = ps.getParser(DefaultParameterParser.class);
@@ -189,10 +197,10 @@ public class IntakeTest extends BaseUnit
pp.add("nt_0mitf", values[1]);
group.init(pp);
- assertTrue("The field should be set", multiValueField.isSet());
- assertTrue("The field should be validated",
multiValueField.isValidated());
- assertTrue("The field should be valid", multiValueField.isValid());
- assertTrue("The field should have the value [1, 2]",
Arrays.equals(values, (int[])multiValueField.getValue()));
+ assertTrue( multiValueField.isSet(), "The field should be set");
+ assertTrue( multiValueField.isValidated(), "The field should be
validated");
+ assertTrue( multiValueField.isValid(), "The field should be valid");
+ assertTrue( Arrays.equals(values, (int[])multiValueField.getValue()),
"The field should have the value [1, 2]");
}
@Test
@@ -210,7 +218,7 @@ public class IntakeTest extends BaseUnit
}
catch (ValidationException ve)
{
- assertEquals("Invalid number message is wrong.", "Entry was not a
valid Integer", ve.getMessage());
+ assertEquals("Entry was not a valid Integer", ve.getMessage(),
"Invalid number message is wrong.");
}
Field<?> longField = group.get("EmptyLongTestField");
@@ -221,7 +229,7 @@ public class IntakeTest extends BaseUnit
}
catch (ValidationException ve)
{
- assertEquals("Invalid number message is wrong.", "Entry was not a
valid Long", ve.getMessage());
+ assertEquals("Entry was not a valid Long", ve.getMessage(),
"Invalid number message is wrong.");
}
Field<?> shortField = group.get("EmptyShortTestField");
@@ -232,7 +240,7 @@ public class IntakeTest extends BaseUnit
}
catch (ValidationException ve)
{
- assertEquals("Invalid number message is wrong.", "Entry was not a
valid Short", ve.getMessage());
+ assertEquals("Entry was not a valid Short", ve.getMessage(),
"Invalid number message is wrong.");
}
Field<?> floatField = group.get("EmptyFloatTestField");
@@ -243,7 +251,7 @@ public class IntakeTest extends BaseUnit
}
catch (ValidationException ve)
{
- assertEquals("Invalid number message is wrong.", "Entry was not a
valid Float", ve.getMessage());
+ assertEquals("Entry was not a valid Float", ve.getMessage(),
"Invalid number message is wrong.");
}
Field<?> doubleField = group.get("EmptyDoubleTestField");
@@ -254,7 +262,7 @@ public class IntakeTest extends BaseUnit
}
catch (ValidationException ve)
{
- assertEquals("Invalid number message is wrong.", "Entry was not a
valid Double", ve.getMessage());
+ assertEquals("Entry was not a valid Double", ve.getMessage(),
"Invalid number message is wrong.");
}
Field<?> bigDecimalField = group.get("EmptyBigDecimalTestField");
@@ -265,7 +273,7 @@ public class IntakeTest extends BaseUnit
}
catch (ValidationException ve)
{
- assertEquals("Invalid number message is wrong.", "Entry was not a
valid BigDecimal", ve.getMessage());
+ assertEquals( "Entry was not a valid BigDecimal", ve.getMessage(),
"Invalid number message is wrong.");
}
Field<?> numberField = group.get("NumberTestField");
@@ -276,7 +284,7 @@ public class IntakeTest extends BaseUnit
}
catch (ValidationException ve)
{
- assertEquals("Invalid number message is wrong.", "Not a number",
ve.getMessage());
+ assertEquals("Not a number", ve.getMessage(), "Entry was not a
valid BigDecimal");
}
}
}
Modified:
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeValidatonTest.java
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeValidatonTest.java?rev=1848852&r1=1848851&r2=1848852&view=diff
==============================================================================
---
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeValidatonTest.java
(original)
+++
turbine/fulcrum/trunk/intake/src/test/org/apache/fulcrum/intake/IntakeValidatonTest.java
Thu Dec 13 14:54:04 2018
@@ -19,10 +19,6 @@ package org.apache.fulcrum.intake;
* under the License.
*/
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
import java.util.Locale;
import org.apache.fulcrum.intake.model.Field;
@@ -40,8 +36,20 @@ import org.apache.fulcrum.intake.validat
import org.apache.fulcrum.parser.DefaultParameterParser;
import org.apache.fulcrum.parser.ParserService;
import org.apache.fulcrum.parser.ValueParser;
-import org.apache.fulcrum.testcontainer.BaseUnit4Test;
-import org.junit.Test;
+
+import org.apache.fulcrum.testcontainer.BaseUnit5Test;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* Test the validators
*
@@ -52,13 +60,14 @@ import org.junit.Test;
*
* @author <a href="[email protected]">Thomas Vandahl</a>
*/
-public class IntakeValidatonTest extends BaseUnit4Test
+@DisplayName("Intake Validator Test")
+public class IntakeValidatonTest extends BaseUnit5Test
{
/**
- * Defines the testcase for JUnit4.
+ * Defines the testcase for JUnit5.
*
*/
- public IntakeValidatonTest()
+ public IntakeValidatonTest(TestInfo testInfo)
{
}
Modified:
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java?rev=1848852&r1=1848851&r2=1848852&view=diff
==============================================================================
---
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java
(original)
+++
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java
Thu Dec 13 14:54:04 2018
@@ -24,7 +24,6 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -91,727 +90,755 @@ import com.fasterxml.jackson.databind.se
*/
public class Jackson2MapperService extends AbstractLogEnabled implements
JsonService, Initializable, Configurable {
- private static final String DEFAULT_TYPING = "defaultTyping";
- private static final String CACHE_FILTERS = "cacheFilters";
- private static final String DATE_FORMAT = "dateFormat";
- private static final String ESCAPE_CHARS = "escapeCharsGlobal";
- private static final String ESCAPE_CHAR_CLASS = "escapeCharsClass";
- private static final String USE_JSON_PATH = "useJsonPath";
- ObjectMapper mapper;
- AnnotationIntrospector primary; // support default
- AnnotationIntrospector secondary;
-
- private static final String ANNOTATIONINSPECTOR =
"annotationInspectors";
-
- private Map<String, String> annotationInspectors = null;
- private Map<String, Boolean> features = null;
- private Map<String, String> featureTypes = null;
-
- private String dateFormat;
-
- /**
- * Default dateformat is <code>MM/dd/yyyy</code>, could be overwritten
in
- * {@link #setDateFormat(DateFormat)}.
- */
- public static final String DEFAULTDATEFORMAT = "MM/dd/yyyy";
-
- private boolean cacheFilters = true; // true -> this is by default true
in jackson, if not using
-
// multiple serialization in one thread
- String[] defaultTypeDefs = null;
- private CacheService cacheService;
- private boolean escapeCharsGlobal = false; // to be backward
compatible, but should be true, then escaping to avoid
-
// XSS payload by default
- private boolean useJsonPath = false;
- private String escapeCharsClass = null;
-
- @Override
- public String ser(Object src) throws Exception {
- return ser(src, false);
- }
-
- @Override
- public <T> String ser(Object src, Class<T> type) throws Exception {
- return ser(src, type, false);
- }
-
- public String ser(Object src, FilterProvider filter) throws Exception {
- return ser(src, filter, false);
- }
-
- public String ser(Object src, FilterProvider filter, Boolean
cleanCache) throws Exception {
- String serResult = null;
- if (src == null) {
- getLogger().info("no serializable object.");
- return serResult;
- }
- if (filter == null) {
- getLogger().debug("ser class::" + src.getClass() + "
without filter.");
- return ser(src);
- } else {
- getLogger().debug("add filter for cache filter Class "
+ src.getClass().getName());
-
setCustomIntrospectorWithExternalFilterId(src.getClass(), null); // filter class
- cacheService.getFilters().put(src.getClass().getName(),
filter);
- }
- getLogger().debug("ser class::" + src.getClass() + " with
filter " + filter);
- mapper.setFilterProvider(filter);
- String res = mapper.writer(filter).writeValueAsString(src);
- if (cleanCache) {
- cacheService.cleanSerializerCache(mapper);
- }
- return res;
- }
-
- @Override
- public <T> T deSer(String json, Class<T> type) throws Exception {
- ObjectReader reader = null;
- if (type != null)
- reader = mapper.readerFor(type);
- else
- reader = mapper.reader();
-
- return reader.readValue(json);
- }
-
- public <T> T deSer(Object src, Class<T> type) throws Exception {
- return mapper.convertValue(src, type);
- }
-
- public <T> Collection<T> deSerCollectionWithType(String json, Class<?
extends Collection> collectionClass,
- Class<T> type) throws Exception {
- return mapper.readValue(json,
mapper.getTypeFactory().constructCollectionType(collectionClass, type));
- }
-
- public <T> String serCollectionWithTypeReference(Collection<T> src,
TypeReference collectionType,
- Boolean cleanCache) throws Exception {
- String res =
mapper.writerFor(collectionType).writeValueAsString(src);
- if (cleanCache) {
- cacheService.cleanSerializerCache(mapper);
- }
- return res;
- }
-
- @Override
- public <T> Collection<T> deSerCollection(String json, Object
collectionType, Class<T> elementType)
- throws Exception {
- if (collectionType instanceof TypeReference) {
- return mapper.readValue(json, (TypeReference<T>)
collectionType);
- } else {
- return mapper.readValue(json, mapper.getTypeFactory()
-
.constructCollectionType(((Collection<T>) collectionType).getClass(),
elementType));
- }
- }
-
- public <T> List<T> deSerList(String json, Class<? extends List>
targetList, Class<T> elementType) throws Exception {
- return mapper.readValue(json,
mapper.getTypeFactory().constructParametricType(targetList, elementType));
- }
-
- public <T, U> Map<T, U> deSerMap(String json, Class<? extends Map>
mapClass, Class<T> keyClass, Class<U> valueClass)
- throws Exception {
- return mapper.readValue(json,
mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass));
- }
-
- public <T> Collection<T> deSerCollectionWithTypeReference(String json,
TypeReference<T> collectionType)
- throws Exception {
- return mapper.readValue(json, collectionType);
- }
-
- /**
- * @param name name of the module
- * @param target target class
- * @param mixin provide mixin as class. Deregistering module could be
only done
- * by setting this parameter to null.
- *
- * @see #addAdapter(String, Class, Object)
- */
- @Override
- public JsonService addAdapter(String name, Class target, Class mixin)
throws Exception {
- getLogger().debug(
- "registering unversioned simple mixin module
named " + name + " of type " + mixin + " for: " + target);
- mapper.addMixIn(target, mixin);
- return this;
- }
-
- /**
- * Add a named module or a {@link Module}.
- *
- * @param name Name of the module, optional. Could be null, if module
is a
- * {@link Module}.
- *
- * @param target Target class, optional. Could be null, if module is a
- * {@link Module}.
- *
- * @param module Either an Jackson Module @link {@link Module} or an
custom
- * wrapper @link CustomModuleWrapper.
- *
- * @see JsonService#addAdapter(String, Class, Object)
- */
- @Override
- public JsonService addAdapter(String name, Class target, Object module)
throws Exception {
- if (module instanceof CustomModuleWrapper) {
- CustomModuleWrapper cmw = (CustomModuleWrapper) module;
- Module cm = new CustomModule(name, target,
cmw.getSer(), cmw.getDeSer());
- getLogger().debug("registering custom module " + cm + "
for: " + target);
- mapper.registerModule(cm);
- } else if (module instanceof Module) {
- getLogger().debug("registering module " + module);
- mapper.registerModule((Module) module);
- } else {
- throw new Exception("expecting module type" +
Module.class);
- }
- return this;
- }
-
- /**
- * set a single mixin. convenience method, calls
- * {@link ObjectMapper#registerModule(Module)}
- *
- * @param src he object to be serialized
- * @param name the name for the mixin
- * @param target the target class for the mixin
- * @param mixin the mixin class
- * @return serialized result
- * @throws JsonProcessingException if not properly processed
- */
- @SuppressWarnings("rawtypes")
- public String withMixinModule(Object src, String name, Class target,
Class mixin) throws JsonProcessingException {
- Module mx = new MixinModule(name, target, mixin);
- getLogger().debug("registering module " + mx + ", mixin: " +
mixin);
- return
mapper.registerModule(mx).writer().writeValueAsString(src);
- }
-
- /**
- * This is a convenience method with read, but the old mixins will be
cleared
- * {@link ObjectMapper#setMixIns(Map)}
- *
- * @param src the object to be serialized
- * @param target the target class for the mixin
- * @param mixin the mixin class
- * @return serialized result
- * @throws JsonProcessingException if fail
- */
- @SuppressWarnings("rawtypes")
- public String withSetMixins(Object src, Class target, Class mixin)
throws JsonProcessingException {
- return setMixins(target,
mixin).writer().writeValueAsString(src);
- }
-
- /**
- * @param target The target class
- * @param mixin the mixin class
- * @return an objectmapper
- */
- @SuppressWarnings("rawtypes")
- public ObjectMapper setMixins(Class target, Class mixin) {
- Map<Class<?>, Class<?>> sourceMixins = null;
- if (target != null) {
- sourceMixins = new HashMap<>(1);
- sourceMixins.put(target, mixin);
- }
- getLogger().debug("clean set mixins for target " + target + ",
mixin: " + mixin);
- return mapper.setMixIns(sourceMixins);
- }
-
- @Override
- public String serializeAllExceptFilter(Object src, String...
filterAttr) throws Exception {
- return serializeAllExceptFilter(src, src.getClass(), true,
filterAttr);
- }
-
- @Override
- public synchronized String serializeAllExceptFilter(Object src, Boolean
cache, String... filterAttr)
- throws Exception {
- return serializeAllExceptFilter(src, src.getClass(), cache,
filterAttr);
- }
-
- public synchronized <T> String serializeAllExceptFilter(Object src,
Class<T>[] filterClasses, String... filterAttr)
- throws Exception {
- return serializeAllExceptFilter(src, filterClasses, true,
filterAttr);
- }
-
- @Override
- public synchronized <T> String serializeAllExceptFilter(Object src,
Class<T> filterClass, String... filterAttr)
- throws Exception {
- return serializeAllExceptFilter(src, filterClass, true,
filterAttr);
- }
-
- @Override
- public <T> String serializeAllExceptFilter(Object src, Class<T>
filterClass, Boolean cleanFilter,
- String... filterAttr) throws Exception {
- return serializeAllExceptFilter(src, new Class[] { filterClass
}, cleanFilter, filterAttr);
- }
-
- /**
- *
- * @param src the object to be serailized, may be a list
- * @param filterClasses the same object class or a detail class, which
should be
- * filtered
- * @param <T> class type
- * @param clean cleaning the cache after serialization
- * @param filterAttr attributes to be filtered for filtered class
- * @return the serailized string
- * @throws Exception generic exception
- */
- public synchronized <T> String serializeAllExceptFilter(Object src,
Class<T>[] filterClasses, Boolean clean,
- String... filterAttr) throws Exception {
- PropertyFilter pf = null;
- if (filterAttr != null)
- pf =
SimpleBeanPropertyFilter.serializeAllExcept(filterAttr);
- else if (filterClasses == null) { // no filter
- return ser(src, clean);
- // should be better:
- // return filter(src, new Class<?>[] { src.getClass()
}, filterClasses, pf,
- // clean);
- }
- return filter(src, new Class<?>[] { filterClasses[0] },
filterClasses, pf, clean);
- }
-
- @Override
- public String serializeOnlyFilter(Object src, String... filterAttrs)
throws Exception {
- return serializeOnlyFilter(src, src.getClass(), true,
filterAttrs);
- }
-
- @Override
- public synchronized String serializeOnlyFilter(Object src, Boolean
cache, String... filterAttr) throws Exception {
- return serializeOnlyFilter(src, src.getClass(), cache,
filterAttr);
- }
-
- @Override
- public synchronized <T> String serializeOnlyFilter(Object src, Class<T>
filterClass, String... filterAttr)
- throws Exception {
- return serializeOnlyFilter(src, filterClass, true, filterAttr);
- }
-
- @Override
- public synchronized <T> String serializeOnlyFilter(Object src, Class<T>
filterClass, Boolean refresh,
- String... filterAttr) throws Exception {
- return serializeOnlyFilter(src, new Class[] { filterClass },
refresh, filterAttr);
- }
-
- public synchronized <T> String serializeOnlyFilter(Object src,
Class<T>[] filterClasses, Boolean refresh,
- String... filterAttr) throws Exception {
- PropertyFilter pf = null;
- if (filterAttr != null && filterAttr.length > 0 &&
!"".equals(filterAttr[0])) {
- pf =
SimpleBeanPropertyFilter.filterOutAllExcept(filterAttr);
- getLogger().debug("setting filteroutAllexcept filter
for size of filterAttr: " + filterAttr.length);
- } else {
- getLogger().warn("no filter attributes set!");
- pf =
SimpleBeanPropertyFilter.filterOutAllExcept("dummy");
- }
- if (filterClasses == null)
- throw new Exception("You have to provide some class to
apply the filtering!");
- return filter(src, filterClasses, null, pf, refresh);
- }
-
- @Override
- public String ser(Object src, Boolean cleanCache) throws Exception {
- if
(cacheService.getFilters().containsKey(src.getClass().getName())) {
- getLogger().warn("Found registered filter - using
instead of default view filter for class:"
- + src.getClass().getName());
- SimpleFilterProvider filter = (SimpleFilterProvider)
cacheService.getFilters()
- .get(src.getClass().getName());
- return ser(src, filter, cleanCache);//
mapper.writerWithView(src.getClass()).writeValueAsString(src);
- }
- String res =
mapper.writerWithView(Object.class).writeValueAsString(src);
- if (cleanCache != null && cleanCache) {
- cacheService.cleanSerializerCache(mapper);
- }
- return res;
- }
-
- @Override
- public <T> String ser(Object src, Class<T> type, Boolean cleanCache)
throws Exception {
- getLogger().info("serializing object:" + src + " for type " +
type);
- if (src != null &&
cacheService.getFilters().containsKey(src.getClass().getName())) {
- getLogger().warn("Found registered filter - could not
use custom view and custom filter for class:"
- + src.getClass().getName());
- // throw new
- // Exception("Found registered filter - could not use
custom view and custom
- // filter for class:"+
- // src.getClass().getName());
- SimpleFilterProvider filter = (SimpleFilterProvider)
cacheService.getFilters()
- .get(src.getClass().getName());
- return ser(src, filter);
- }
-
- String res = (type != null) ?
mapper.writerWithView(type).writeValueAsString(src)
- : mapper.writeValueAsString(src);
- if (cleanCache) {
- cacheService.cleanSerializerCache(mapper);
- }
- return res;
- }
-
- /**
- *
- * @param src The source Object to be filtered.
- * @param filterClass This Class array contains at least one
element. If no
- * class is provided it is the class type of the
source
- * object. The filterClass is to become the key
of the
- * filter object cache.
- * @param excludeClasses The classes to be excluded, optionally used
only for
- * methods like
- * {@link #serializeAllExceptFilter(Object,
Class[], String...)}.
- * @param pf Expecting a property filter from e.g @link
- * {@link SimpleBeanPropertyFilter}.
- * @param clean if <code>true</code> does not reuse the filter
object
- * (no cashing).
- * @return The serialized Object as String
- * @throws Exception
- */
- private <T> String filter(Object src, Class<?>[] filterClasses,
Class<T>[] excludeClasses, PropertyFilter pf,
- Boolean clean) throws Exception {
- FilterProvider filter = null;
- if (filterClasses.length > 0) {
- filter = retrieveFilter(pf, filterClasses[0],
excludeClasses);
- }
- getLogger().info("filtering with filter " + filter);
- String serialized = ser(src, filter, clean);
- if (!cacheFilters || clean) {
- if (filterClasses.length > 0) {
- boolean exclude = (excludeClasses != null) ?
true : false;
- cacheService.removeFilter(filterClasses[0],
exclude);
- }
- }
- return serialized;
- }
-
- private <T> SimpleFilterProvider retrieveFilter(PropertyFilter pf,
Class<?> filterClass,
- Class<T>[] excludeClasses) {
- SimpleFilterProvider filter = null;
- if (pf != null) {
- filter = new SimpleFilterProvider();
- filter.setDefaultFilter(pf);
- }
- if
(!cacheService.getFilters().containsKey(filterClass.getName())) {
- getLogger().debug("add filter for cache filter Class "
+ filterClass.getName());
- setCustomIntrospectorWithExternalFilterId(filterClass,
excludeClasses); // filter class
- if (pf != null) {
-
cacheService.getFilters().put(filterClass.getName(), filter);
- }
- } else {
- filter = (SimpleFilterProvider)
cacheService.getFilters().get(filterClass.getName());
- //
setCustomIntrospectorWithExternalFilterId(filterClass); // filter
- // class
- }
- getLogger().debug("set filter:" + filter);
- return filter;
- }
-
- /**
- * @param filterClass
- * <li>Adding filterClass into
- * {@link
SimpleNameIntrospector#setFilteredClass(Class)}
- * enables the filtering process.
- * @param externalFilterIds
- * <li>Adding externalFilterIs to
- * {@link
SimpleNameIntrospector#setExternalFilterExcludeClasses(Class...)}
- * excludes these classes.
- */
- private <T> void setCustomIntrospectorWithExternalFilterId(Class<?>
filterClass,
- Class<T>[] externalFilterClassIds) {
- if (primary instanceof SimpleNameIntrospector) {
- // first one is required that we get to the
PropertyFilter
- ((SimpleNameIntrospector)
primary).setFilteredClasses(filterClass);
- if (externalFilterClassIds != null) {
- ((SimpleNameIntrospector)
primary).setIsExludeType(true);
- for (Class<T> filterClazz :
externalFilterClassIds) {
- getLogger().debug("added class for
filters " + filterClazz);
- }
- ((SimpleNameIntrospector)
primary).setExternalFilterExcludeClasses(externalFilterClassIds);
- }
- }
- }
-
- public Jackson2MapperService registerModule(Module module) {
- mapper.registerModule(module);
- return this;
- }
-
- public <T> void addSimpleModule(SimpleModule module, Class<T> type,
JsonSerializer<T> ser) {
- module.addSerializer(type, ser);
- }
-
- public <T> void addSimpleModule(SimpleModule module, Class<T> type,
JsonDeserializer<T> deSer) {
- module.addDeserializer(type, deSer);
- }
-
- /**
- * Default Dateformat: {@link #DEFAULTDATEFORMAT}
- */
- @Override
- public void setDateFormat(final DateFormat df) {
- mapper.setDateFormat(df);
- }
-
- /**
- * Avalon component lifecycle method
- */
- @Override
- public void configure(Configuration conf) throws ConfigurationException
{
- getLogger().debug("conf.getName()" + conf.getName());
- this.annotationInspectors = new HashMap<>();
-
- final Configuration configuredAnnotationInspectors =
conf.getChild(ANNOTATIONINSPECTOR, false);
-
- if (configuredAnnotationInspectors != null) {
- Configuration[] nameVal =
configuredAnnotationInspectors.getChildren();
- for (int i = 0; i < nameVal.length; i++) {
- String key = nameVal[i].getName();
- getLogger().debug("configured key: " + key);
- if (key.equals("features")) {
- this.features = new HashMap<>();
- this.featureTypes = new HashMap<>();
- Configuration[] localFeatures =
nameVal[i].getChildren();
- for (int j = 0; j <
localFeatures.length; j++) {
- boolean featureValue =
localFeatures[j].getAttributeAsBoolean("value", false);
- String featureType =
localFeatures[j].getAttribute("type");
- String feature =
localFeatures[j].getValue();
-
getLogger().debug("configuredAnnotationInspectors " + feature + ":" +
featureValue);
- this.features.put(feature,
featureValue);
- this.featureTypes.put(feature,
featureType);
- }
- } else {
- String val = nameVal[i].getValue();
-
getLogger().debug("configuredAnnotationInspectors " + key + ":" + val);
- this.annotationInspectors.put(key, val);
- }
- }
- }
- final Configuration configuredDateFormat =
conf.getChild(DATE_FORMAT, true);
- this.dateFormat =
configuredDateFormat.getValue(DEFAULTDATEFORMAT);
-
- final Configuration configuredKeepFilter =
conf.getChild(CACHE_FILTERS, false);
- if (configuredKeepFilter != null) {
- this.cacheFilters =
configuredKeepFilter.getValueAsBoolean();
- }
- final Configuration configuredEscapeChars =
conf.getChild(ESCAPE_CHARS, false);
- if (configuredEscapeChars != null) {
- this.escapeCharsGlobal =
configuredEscapeChars.getValueAsBoolean();
- }
- final Configuration configuredEscapeCharClass =
conf.getChild(ESCAPE_CHAR_CLASS, false);
- if (configuredEscapeCharClass != null) {
- this.escapeCharsClass =
configuredEscapeCharClass.getValue();
- }
-
- final Configuration configuredDefaultType =
conf.getChild(DEFAULT_TYPING, false);
- if (configuredDefaultType != null) {
- defaultTypeDefs = new String[] {
configuredDefaultType.getAttribute("type"),
-
configuredDefaultType.getAttribute("key") };
- }
- final Configuration configuredjsonPath =
conf.getChild(USE_JSON_PATH, false);
- if (configuredjsonPath != null) {
- this.useJsonPath =
configuredjsonPath.getValueAsBoolean();
- }
- }
-
- @Override
- public void initialize() throws Exception {
- mapper = new ObjectMapper(null, null, null);// add configurable
JsonFactory,.. later?
-
- initAnnotationInspectors();
-
- initFeatures();
-
- initDefaultTyping();
-
- getLogger().info("setting date format to:" + dateFormat);
- getLogger().info("cacheFilters is:" + cacheFilters);
- if (!cacheFilters) {
-
mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);
- }
-
- mapper.setDateFormat(new SimpleDateFormat(dateFormat));
-
- if (escapeCharsGlobal) {
-
mapper.getFactory().setCharacterEscapes(characterEscapes);
- }
- if (escapeCharsClass != null) {
- try {
- characterEscapes = (CharacterEscapes)
Class.forName(escapeCharsClass).getConstructor().newInstance();
- } catch (Exception e) {
- throw new Exception(
- "JsonMapperService: Error
instantiating " + escapeCharsClass + " for " + ESCAPE_CHAR_CLASS);
- }
- }
-
- getLogger().debug("initialized mapper:" + mapper);
-
- mapper.getSerializerProvider().setNullValueSerializer(new
JsonSerializer<Object>() {
- @Override
- public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException {
- jgen.writeString("");
-
- }
- });
- cacheService = new CacheService(primary);
- if (cacheService instanceof LogEnabled) {
-
cacheService.enableLogging(getLogger().getChildLogger(cacheService.getClass().getSimpleName()));
- getLogger().info("setting cacheService logger: " +
cacheService.getClass().getSimpleName());
- }
-
- if (useJsonPath) {
- // set it before runtime
- DefaultJsonPathWrapper djpw = null;
- try {
- djpw = new DefaultJsonPathWrapper(this.mapper);
- getLogger().debug("******** initialized new
jsonPath defaults: " + djpw.getJsonPathDefault());
- } catch (Exception e) {
- throw new Exception(
- "JsonMapperService: Error
instantiating " + djpw + " using useJsonPath=" + useJsonPath);
- }
-
- }
- }
-
- private void initDefaultTyping() {
- if (defaultTypeDefs != null && defaultTypeDefs.length == 2) {
- DefaultTyping defaultTyping =
DefaultTyping.valueOf(defaultTypeDefs[0]);
- mapper.enableDefaultTypingAsProperty(defaultTyping,
defaultTypeDefs[1]);
- getLogger().info("default typing is " +
defaultTypeDefs[0] + " with key:" + defaultTypeDefs[1]);
- }
- }
-
- private void initFeatures() throws Exception {
- if (features != null && !features.isEmpty()) {
-
- for (Entry<String, Boolean> entry :
features.entrySet()) {
- String featureKey = entry.getKey();
- Boolean featureValue = entry.getValue();
- String featureType =
featureTypes.get(featureKey);
- Class<?> configFeature = null;
- try {
- getLogger().debug("initializing
featureType: " + featureType);
- configFeature =
Class.forName(featureType);
- } catch (Exception e) {
- throw new Exception("JsonMapperService:
Error instantiating " + featureType + " for " + featureKey,
- e);
- }
- ConfigFeature feature = null;
- if (!StringUtils.isEmpty(featureKey) &&
featureValue != null) {
- try {
- if
(configFeature.equals(SerializationFeature.class)) {
- feature =
SerializationFeature.valueOf(featureKey);
-
mapper.configure((SerializationFeature) feature, featureValue);
- assert
mapper.getSerializationConfig()
-
.isEnabled((SerializationFeature) feature) == featureValue;
-
getLogger().info("initialized serconfig mapper feature: " + feature + " with "
- +
mapper.getSerializationConfig().isEnabled((SerializationFeature) feature));
- } else if
(configFeature.equals(DeserializationFeature.class)) {
- feature =
DeserializationFeature.valueOf(featureKey);
-
mapper.configure((DeserializationFeature) feature, featureValue);
- assert
mapper.getDeserializationConfig()
-
.isEnabled((DeserializationFeature) feature) == featureValue;
-
getLogger().info("initialized deserconfig mapper feature: " + feature + " with "
- +
mapper.getDeserializationConfig().isEnabled((DeserializationFeature) feature));
- } else if
(configFeature.equals(MapperFeature.class)) {
- feature =
MapperFeature.valueOf(featureKey);
-
mapper.configure((MapperFeature) feature, featureValue);
- assert
mapper.getDeserializationConfig().isEnabled((MapperFeature) feature) ==
featureValue;
- assert
mapper.getSerializationConfig().isEnabled((MapperFeature) feature) ==
featureValue;
-
getLogger().info("initialized serconfig mapper feature: " + feature + " with "
- +
mapper.getDeserializationConfig().isEnabled((MapperFeature) feature));
-
getLogger().info("initialized deserconfig mapper feature: " + feature + " with "
- +
mapper.getSerializationConfig().isEnabled((MapperFeature) feature));
- } else if
(configFeature.equals(JsonParser.class)) {
- Feature parserFeature =
JsonParser.Feature.valueOf(featureKey);
-
getLogger().info("initializing parser feature: " + parserFeature + " with " +
featureValue);
-
mapper.configure(parserFeature, featureValue);
- } else if
(configFeature.equals(JsonGenerator.class)) {
-
com.fasterxml.jackson.core.JsonGenerator.Feature genFeature =
JsonGenerator.Feature
-
.valueOf(featureKey);
-
getLogger().info("initializing parser feature: " + genFeature + " with " +
featureValue);
-
mapper.configure(genFeature, featureValue);
- }
- } catch (Exception e) {
- throw new
Exception("JsonMapperService: Error instantiating feature " + featureKey + "
with "
- + featureValue,
e);
- }
- }
- }
- }
- }
-
- private void initAnnotationInspectors() throws Exception {
- for (Entry<String, String> entry :
annotationInspectors.entrySet()) {
- String key = entry.getKey();
- String avClass = entry.getValue();
- if (key.equals("primary") &&
!StringUtils.isEmpty(avClass)) {
- try {
- primary = (AnnotationIntrospector)
Class.forName(avClass).getConstructor().newInstance();
- } catch (Exception e) {
- throw new Exception("JsonMapperService:
Error instantiating " + avClass + " for " + key);
- }
- } else if (key.equals("secondary") && avClass != null) {
- try {
- secondary = (AnnotationIntrospector)
Class.forName(avClass).getConstructor().newInstance();
- } catch (Exception e) {
- throw new Exception("JsonMapperService:
Error instantiating " + avClass + " for " + key);
- }
- }
- }
- if (primary == null) {
- primary = new JacksonAnnotationIntrospector(); //
support default
- getLogger().info("using default introspector:" +
primary.getClass().getName());
- mapper.setAnnotationIntrospector(primary);
- } else if (primary != null && secondary != null) {
- AnnotationIntrospector pair = new
AnnotationIntrospectorPair(primary, secondary);
- mapper.setAnnotationIntrospector(pair);
- } else {
- mapper.setAnnotationIntrospector(primary);
- }
-
- if (primary instanceof LogEnabled) {
- ((LogEnabled)
primary).enableLogging(getLogger().getChildLogger(primary.getClass().getSimpleName()));
- getLogger().info("setting primary introspector logger:
" + primary.getClass().getSimpleName());
- }
- if (secondary instanceof LogEnabled) {
- ((LogEnabled)
secondary).enableLogging(getLogger().getChildLogger(secondary.getClass().getSimpleName()));
- getLogger().info("setting secondary introspector
logger: " + secondary.getClass().getSimpleName());
- }
- }
-
- public ObjectMapper getMapper() {
- return mapper;
- }
-
- public void setMapper(ObjectMapper mapper) {
- this.mapper = mapper;
- }
-
- public boolean isCacheFilters() {
- return cacheFilters;
- }
-
- public void setCacheFilters(boolean cacheFilters) {
- this.cacheFilters = cacheFilters;
- if (!cacheFilters)
-
mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);
- }
-
- static CharacterEscapes characterEscapes = new CharacterEscapes() {
- private static final long serialVersionUID = 1L;
- private final int[] asciiEscapes;
- { // instance init
- int[] esc = standardAsciiEscapesForJSON();
- // this avoids to get evaluated immediately
- esc['<'] = CharacterEscapes.ESCAPE_STANDARD;
- esc['>'] = CharacterEscapes.ESCAPE_STANDARD;
- esc['&'] = CharacterEscapes.ESCAPE_STANDARD;
- esc['\''] = CharacterEscapes.ESCAPE_STANDARD;
- // esc['/'] = '/'; //CharacterEscapes.ESCAPE_CUSTOM;
- asciiEscapes = esc;
- }
-
- @Override
- public int[] getEscapeCodesForAscii() {
- return asciiEscapes;
- }
+ private static final String DEFAULT_TYPING = "defaultTyping";
+ private static final String CACHE_FILTERS = "cacheFilters";
+ private static final String DATE_FORMAT = "dateFormat";
+ private static final String ESCAPE_CHARS = "escapeCharsGlobal";
+ private static final String ESCAPE_CHAR_CLASS = "escapeCharsClass";
+ private static final String USE_JSON_PATH = "useJsonPath";
+ ObjectMapper mapper;
+ AnnotationIntrospector primary; // support default
+ AnnotationIntrospector secondary;
+
+ private static final String ANNOTATIONINSPECTOR = "annotationInspectors";
+
+ private Map<String, String> annotationInspectors = null;
+ private Map<String, Boolean> features = null;
+ private Map<String, String> featureTypes = null;
+
+ private String dateFormat;
+
+ /**
+ * Default dateformat is <code>MM/dd/yyyy</code>, could be overwritten in
+ * {@link #setDateFormat(DateFormat)}.
+ */
+ public static final String DEFAULTDATEFORMAT = "MM/dd/yyyy";
+
+
+ private boolean cacheFilters = true; // true -> this is by default true in
jackson, if not using
+ // multiple serialization in one
thread
+ String[] defaultTypeDefs = null;
+ private CacheService cacheService;
+ private boolean escapeCharsGlobal = false; // to be backward compatible,
but should be true, then escaping to avoid
+ // XSS payload by default
+ private boolean useJsonPath = false;
+ private String escapeCharsClass = null;
+
+ @Override
+ public String ser(Object src) throws Exception {
+ return ser(src, false);
+ }
+
+ @Override
+ public <T> String ser(Object src, Class<T> type) throws Exception {
+ return ser(src, type, false);
+ }
+
+ public String ser(Object src, FilterProvider filter) throws Exception {
+ return ser(src, filter, false);
+ }
+
+ /**
+ *
+ * @param src
+ * @param filter
+ * @param cleanCache cleans the jackson cache
+ * @return
+ * @throws Exception
+ */
+ public String ser(Object src, FilterProvider filter, Boolean cleanCache)
throws Exception {
+ String serResult = null;
+ if (src == null) {
+ getLogger().info("no serializable object.");
+ return serResult;
+ }
+ if (filter == null) {
+ getLogger().debug("ser class::" + src.getClass() + " without
filter.");
+ return ser(src);
+ } else {
+ getLogger().debug("add filter for cache filter Class " +
src.getClass().getName());
+ setCustomIntrospectorWithExternalFilterId(src.getClass(), null);
// filter class
+ if (isCacheFilters()) {
+ cacheService.getFilters().put(src.getClass().getName(),
filter);
+ }
+ }
+ getLogger().debug("ser class::" + src.getClass() + " with filter " +
filter);
+ mapper.setFilterProvider(filter);
+ String res = mapper.writer(filter).writeValueAsString(src);
+ if (cleanCache) {
+ cacheService.cleanSerializerCache(mapper);
+ }
+ return res;
+ }
+
+ @Override
+ public <T> T deSer(String json, Class<T> type) throws Exception {
+ ObjectReader reader = null;
+ if (type != null)
+ reader = mapper.readerFor(type);
+ else
+ reader = mapper.reader();
+
+ return reader.readValue(json);
+ }
+
+ public <T> T deSer(Object src, Class<T> type) throws Exception {
+ return mapper.convertValue(src, type);
+ }
+
+ /**
+ * Add a named module or a {@link Module}.
+ *
+ * @param name Name of the module, optional. Could be null, if module is
a
+ * {@link Module}.
+ *
+ * @param target Target class, optional. Could be null, if module is a
+ * {@link Module}.
+ *
+ * @param module Either an Jackson Module @link {@link Module} or an custom
+ * wrapper @link CustomModuleWrapper.
+ */
+ @Override
+ public JsonService addAdapter(String name, Class target, Object module)
+ throws Exception {
+ if (module instanceof CustomModuleWrapper) {
+ CustomModuleWrapper cmw = (CustomModuleWrapper) module;
+ Module cm = new CustomModule(name, target, cmw.getSer(),
+ cmw.getDeSer());
+ getLogger().debug("registering custom module " + cm + " for: " +
target);
+ mapper.registerModule(cm);
+ } else if (module instanceof Module) {
+ getLogger().debug(
+ "registering module " + module );
+ mapper.registerModule((Module) module);
+ } else {
+ throw new Exception("expecting module type" + Module.class);
+ }
+ return this;
+ }
+
+ public Class<?> showMixinForClass(Class target) {
+ Class<?> mixin = mapper.findMixInClassFor( target );
+ getLogger().debug("find mixin for target " + target + " -> mixin: " +
mixin);
+ return mixin;
+ }
+
+ public <T> List<T> deSerList(String json, Class<? extends List>
targetList, Class<T> elementType) throws Exception {
+ return mapper.readValue(json,
mapper.getTypeFactory().constructParametricType(targetList, elementType));
+ }
+
+ public <T, U> Map<T, U> deSerMap(String json, Class<? extends Map>
mapClass, Class<T> keyClass, Class<U> valueClass)
+ throws Exception {
+ return mapper.readValue(json,
mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass));
+ }
+
+ public <T> Collection<T> deSerCollectionWithTypeReference(String json,
TypeReference<T> collectionType)
+ throws Exception {
+ return mapper.readValue(json, collectionType);
+ }
+
+ public <T> Collection<T> deSerCollectionWithType(String json, Class<?
extends Collection> collectionClass,
+ Class<T> type) throws Exception {
+ return mapper.readValue(json,
mapper.getTypeFactory().constructCollectionType(collectionClass, type));
+ }
+
+ @Override
+ public <T> Collection<T> deSerCollection(String json, Object
collectionType, Class<T> elementType)
+ throws Exception {
+ if (collectionType instanceof TypeReference) {
+ return mapper.readValue(json, (TypeReference<T>) collectionType);
+ } else {
+ return mapper.readValue(json, mapper.getTypeFactory()
+ .constructCollectionType(((Collection<T>)
collectionType).getClass(), elementType));
+ }
+ }
+
+ /**
+ *
+ * @param src
+ * @param collectionType
+ * @param cleanCache cleans jackson serializer cache, after
+ * @return
+ * @throws Exception
+ */
+ public <T> String serCollectionWithTypeReference(Collection<T> src,
TypeReference collectionType,
+ Boolean cleanCache)
throws Exception {
+ String res = mapper.writerFor(collectionType).writeValueAsString(src);
+ if (cleanCache) {
+ cacheService.cleanSerializerCache(mapper);
+ }
+ return res;
+ }
+
+ /**
+ * @param name name of the module
+ * @param target target class
+ * @param mixin provide mixin as class. Deregistering module could be
only done
+ * by setting this parameter to null.
+ *
+ * @see #addAdapter(String, Class, Object)
+ */
+ @Override
+ public JsonService addAdapter(String name, Class target, Class mixin)
throws Exception {
+ getLogger().debug(
+ "registering unversioned simple mixin module named " + name +
" of type " + mixin + " for: " + target);
+ mapper.addMixIn(target, mixin);
+ return this;
+ }
+
+ /**
+ * set a single mixin. convenience method, calls
+ * {@link ObjectMapper#registerModule(Module)}
+ *
+ * @param src he object to be serialized
+ * @param name the name for the mixin
+ * @param target the target class for the mixin
+ * @param mixin the mixin class
+ * @return serialized result
+ * @throws JsonProcessingException if not properly processed
+ */
+ @SuppressWarnings("rawtypes")
+ public String withMixinModule(Object src, String name, Class target, Class
mixin) throws JsonProcessingException {
+ Module mx = new MixinModule(name, target, mixin);
+ getLogger().debug("registering module " + mx + ", mixin: " + mixin);
+ return mapper.registerModule(mx).writer().writeValueAsString(src);
+ }
+
+ /**
+ * This is a convenience method with read, but the old mixins will be
cleared
+ * {@link ObjectMapper#setMixIns(Map)}
+ *
+ * @param src the object to be serialized
+ * @param target the target class for the mixin
+ * @param mixin the mixin class
+ * @return serialized result
+ * @throws JsonProcessingException if fail
+ */
+ @SuppressWarnings("rawtypes")
+ public String withSetMixins(Object src, Class target, Class mixin) throws
JsonProcessingException {
+ return setMixins(target, mixin).writer().writeValueAsString(src);
+ }
+
+ /**
+ * @param target The target class
+ * @param mixin the mixin class
+ * @return an objectmapper
+ */
+ @SuppressWarnings("rawtypes")
+ public ObjectMapper setMixins(Class target, Class mixin) {
+ Map<Class<?>, Class<?>> sourceMixins = null;
+ if (target != null) {
+ sourceMixins = new HashMap<>(1);
+ sourceMixins.put(target, mixin);
+ }
+ getLogger().debug("complete reset mixins for target " + target + ",
mixin: " + mixin);
+ return mapper.setMixIns(sourceMixins);
+ }
+
+ @Override
+ public String serializeAllExceptFilter(Object src, String... filterAttr)
throws Exception {
+ return serializeAllExceptFilter(src, src.getClass(), true, filterAttr);
+ }
+
+ @Override
+ public synchronized String serializeAllExceptFilter(Object src, Boolean
cache, String... filterAttr)
+ throws Exception {
+ return serializeAllExceptFilter(src, src.getClass(), cache,
filterAttr);
+ }
+
+ public synchronized <T> String serializeAllExceptFilter(Object src,
Class<T>[] filterClasses, String... filterAttr)
+ throws Exception {
+ return serializeAllExceptFilter(src, filterClasses, true, filterAttr);
+ }
+
+ @Override
+ public synchronized <T> String serializeAllExceptFilter(Object src,
Class<T> filterClass, String... filterAttr)
+ throws Exception {
+ return serializeAllExceptFilter(src, filterClass, true, filterAttr);
+ }
+
+ @Override
+ public <T> String serializeAllExceptFilter(Object src, Class<T>
filterClass, Boolean cleanFilter,
+ String... filterAttr) throws Exception {
+ return serializeAllExceptFilter(src, new Class[] { filterClass },
cleanFilter, filterAttr);
+ }
+
+ /**
+ *
+ * @param src the object to be serailized, may be a list
+ * @param filterClasses the same object class or a detail class, which
should be
+ * filtered
+ * @param <T> class type
+ * @param clean cleaning the cache after serialization
+ * @param filterAttr attributes to be filtered for filtered class
+ * @return the serailized string
+ * @throws Exception generic exception
+ */
+ public synchronized <T> String serializeAllExceptFilter(Object src,
Class<T>[] filterClasses, Boolean clean,
+ String... filterAttr) throws Exception {
+ PropertyFilter pf = null;
+ if (filterAttr != null)
+ pf = SimpleBeanPropertyFilter.serializeAllExcept(filterAttr);
+ else if (filterClasses == null) { // no filter
+ return ser(src, clean);
+ // should be better:
+ // return filter(src, new Class<?>[] { src.getClass() },
filterClasses, pf,
+ // clean);
+ }
+ return filter(src, new Class<?>[] { filterClasses[0] }, filterClasses,
pf, clean);
+ }
+
+ @Override
+ public String serializeOnlyFilter(Object src, String... filterAttrs)
throws Exception {
+ return serializeOnlyFilter(src, src.getClass(), true, filterAttrs);
+ }
+
+ @Override
+ public synchronized String serializeOnlyFilter(Object src, Boolean cache,
String... filterAttr) throws Exception {
+ return serializeOnlyFilter(src, src.getClass(), cache, filterAttr);
+ }
+
+ @Override
+ public synchronized <T> String serializeOnlyFilter(Object src, Class<T>
filterClass, String... filterAttr)
+ throws Exception {
+ return serializeOnlyFilter(src, filterClass, true, filterAttr);
+ }
+
+ @Override
+ public synchronized <T> String serializeOnlyFilter(Object src, Class<T>
filterClass, Boolean refresh,
+ String... filterAttr) throws Exception {
+ return serializeOnlyFilter(src, new Class[] { filterClass }, refresh,
filterAttr);
+ }
+
+ public synchronized <T> String serializeOnlyFilter(Object src, Class<T>[]
filterClasses, Boolean refresh,
+ String... filterAttr) throws Exception {
+ PropertyFilter pf = null;
+ if (filterAttr != null && filterAttr.length > 0 &&
!"".equals(filterAttr[0])) {
+ pf = SimpleBeanPropertyFilter.filterOutAllExcept(filterAttr);
+ getLogger().debug("setting filteroutAllexcept filter for size of
filterAttr: " + filterAttr.length);
+ } else {
+ getLogger().warn("no filter attributes set!");
+ pf = SimpleBeanPropertyFilter.filterOutAllExcept("dummy");
+ }
+ if (filterClasses == null)
+ throw new Exception("You have to provide some class to apply the
filtering!");
+ return filter(src, filterClasses, null, pf, refresh);
+ }
+
+ @Override
+ public String ser(Object src, Boolean cleanCache) throws Exception {
+ if (isCacheFilters() &&
cacheService.getFilters().containsKey(src.getClass().getName())) {
+ getLogger().warn("Found registered filter - using instead of
default view filter for class:"
+ + src.getClass().getName());
+ SimpleFilterProvider filter = (SimpleFilterProvider)
cacheService.getFilters()
+ .get(src.getClass().getName());
+ return ser(src, filter, cleanCache);//
mapper.writerWithView(src.getClass()).writeValueAsString(src);
+ }
+ String res =
mapper.writerWithView(Object.class).writeValueAsString(src);
+ if (cleanCache != null && cleanCache) {
+ cacheService.cleanSerializerCache(mapper);
+ }
+ return res;
+ }
+
+ @Override
+ public <T> String ser(Object src, Class<T> type, Boolean cleanCache)
throws Exception {
+ getLogger().info("serializing object:" + src + " for type " + type);
+ if (isCacheFilters() && src != null &&
cacheService.getFilters().containsKey(src.getClass().getName())) {
+ getLogger().warn("Found registered filter - could not use custom
view and custom filter for class:"
+ + src.getClass().getName());
+ // throw new
+ // Exception("Found registered filter - could not use custom view
and custom
+ // filter for class:"+
+ // src.getClass().getName());
+ SimpleFilterProvider filter = (SimpleFilterProvider)
cacheService.getFilters()
+ .get(src.getClass().getName());
+ return ser(src, filter);
+ }
+
+ String res = (type != null) ?
mapper.writerWithView(type).writeValueAsString(src)
+ : mapper.writeValueAsString(src);
+ if (cleanCache) {
+ cacheService.cleanSerializerCache(mapper);
+ }
+ return res;
+ }
+
+ /**
+ *
+ * @param src The source Object to be filtered.
+ * @param filterClass This Class array contains at least one element.
If no
+ * class is provided it is the class type of the
source
+ * object. The filterClass is to become the key of
the
+ * filter object cache.
+ * @param excludeClasses The classes to be excluded, optionally used only
for
+ * methods like
+ * {@link #serializeAllExceptFilter(Object, Class[],
String...)}.
+ * @param pf Expecting a property filter from e.g @link
+ * {@link SimpleBeanPropertyFilter}.
+ * @param clean if <code>true</code> does not reuse the filter
object
+ * (no cashing).
+ * @return The serialized Object as String
+ * @throws Exception
+ */
+ private <T> String filter(Object src, Class<?>[] filterClasses, Class<T>[]
excludeClasses, PropertyFilter pf,
+ Boolean clean) throws Exception {
+ FilterProvider filter = null;
+ if (filterClasses.length > 0) {
+ filter = retrieveFilter(pf, filterClasses[0], excludeClasses);
+ }
+ getLogger().info("filtering with filter " + filter);
+ String serialized = ser(src, filter, clean);
+ if (!isCacheFilters() || clean) {
+ if (filterClasses.length > 0) {
+ boolean exclude = (excludeClasses != null) ? true : false;
+ cacheService.removeFilter(filterClasses[0], exclude);
+ }
+ }
+ return serialized;
+ }
+
+ private <T> SimpleFilterProvider retrieveFilter(PropertyFilter pf,
Class<?> filterClass,
+ Class<T>[] excludeClasses) {
+ SimpleFilterProvider filter = null;
+ if (pf != null) {
+ filter = new SimpleFilterProvider();
+ filter.setDefaultFilter(pf);
+ }
+ if (isCacheFilters()) {
+ if (!cacheService.getFilters().containsKey(filterClass.getName()))
{
+ getLogger().debug("add filter for cache filter Class " +
filterClass.getName());
+ setCustomIntrospectorWithExternalFilterId(filterClass,
excludeClasses); // filter class
+ if (pf != null) {
+ cacheService.getFilters().put(filterClass.getName(),
filter);
+ }
+ } else {
+ filter = (SimpleFilterProvider)
cacheService.getFilters().get(filterClass.getName());
+ // setCustomIntrospectorWithExternalFilterId(filterClass); //
filter
+ // class
+ }
+ }
+ getLogger().debug("set filter:" + filter);
+ return filter;
+ }
+
+ /**
+ * @param filterClass
+ * <li>Adding filterClass into
+ * {@link
SimpleNameIntrospector#setFilteredClass(Class)}
+ * enables the filtering process.
+ * @param externalFilterIds
+ * <li>Adding externalFilterIs to
+ * {@link
SimpleNameIntrospector#setExternalFilterExcludeClasses(Class...)}
+ * excludes these classes.
+ */
+ private <T> void setCustomIntrospectorWithExternalFilterId(Class<?>
filterClass,
+ Class<T>[] externalFilterClassIds) {
+ if (primary instanceof SimpleNameIntrospector) {
+ // first one is required that we get to the PropertyFilter
+ ((SimpleNameIntrospector) primary).setFilteredClasses(filterClass);
+ if (externalFilterClassIds != null) {
+ ((SimpleNameIntrospector) primary).setIsExludeType(true);
+ for (Class<T> filterClazz : externalFilterClassIds) {
+ getLogger().debug("added class for filters " +
filterClazz);
+ }
+ ((SimpleNameIntrospector)
primary).setExternalFilterExcludeClasses(externalFilterClassIds);
+ }
+ }
+ }
+
+ public Jackson2MapperService registerModule(Module module) {
+ mapper.registerModule(module);
+ return this;
+ }
+
+ public <T> void addSimpleModule(SimpleModule module, Class<T> type,
JsonSerializer<T> ser) {
+ module.addSerializer(type, ser);
+ }
+
+ public <T> void addSimpleModule(SimpleModule module, Class<T> type,
JsonDeserializer<T> deSer) {
+ module.addDeserializer(type, deSer);
+ }
+
+ /**
+ * Default Dateformat: {@link #DEFAULTDATEFORMAT}
+ */
+ @Override
+ public void setDateFormat(final DateFormat df) {
+ mapper.setDateFormat(df);
+ }
+
+ /**
+ * Avalon component lifecycle method
+ */
+ @Override
+ public void configure(Configuration conf) throws ConfigurationException {
+ getLogger().debug("conf.getName()" + conf.getName());
+ this.annotationInspectors = new HashMap<>();
+
+ final Configuration configuredAnnotationInspectors =
conf.getChild(ANNOTATIONINSPECTOR, false);
+
+ if (configuredAnnotationInspectors != null) {
+ Configuration[] nameVal =
configuredAnnotationInspectors.getChildren();
+ for (int i = 0; i < nameVal.length; i++) {
+ String key = nameVal[i].getName();
+ getLogger().debug("configured key: " + key);
+ if (key.equals("features")) {
+ this.features = new HashMap<>();
+ this.featureTypes = new HashMap<>();
+ Configuration[] localFeatures = nameVal[i].getChildren();
+ for (int j = 0; j < localFeatures.length; j++) {
+ boolean featureValue =
localFeatures[j].getAttributeAsBoolean("value", false);
+ String featureType =
localFeatures[j].getAttribute("type");
+ String feature = localFeatures[j].getValue();
+ getLogger().debug("configuredAnnotationInspectors " +
feature + ":" + featureValue);
+ this.features.put(feature, featureValue);
+ this.featureTypes.put(feature, featureType);
+ }
+ } else {
+ String val = nameVal[i].getValue();
+ getLogger().debug("configuredAnnotationInspectors " + key
+ ":" + val);
+ this.annotationInspectors.put(key, val);
+ }
+ }
+ }
+ final Configuration configuredDateFormat = conf.getChild(DATE_FORMAT,
true);
+ this.dateFormat = configuredDateFormat.getValue(DEFAULTDATEFORMAT);
+
+ final Configuration configuredKeepFilter =
conf.getChild(CACHE_FILTERS, false);
+ if (configuredKeepFilter != null) {
+ setCacheFilters( configuredKeepFilter.getValueAsBoolean());
+ }
+ final Configuration configuredEscapeChars =
conf.getChild(ESCAPE_CHARS, false);
+ if (configuredEscapeChars != null) {
+ this.escapeCharsGlobal = configuredEscapeChars.getValueAsBoolean();
+ }
+ final Configuration configuredEscapeCharClass =
conf.getChild(ESCAPE_CHAR_CLASS, false);
+ if (configuredEscapeCharClass != null) {
+ this.escapeCharsClass = configuredEscapeCharClass.getValue();
+ }
+
+ final Configuration configuredDefaultType =
conf.getChild(DEFAULT_TYPING, false);
+ if (configuredDefaultType != null) {
+ defaultTypeDefs = new String[] {
configuredDefaultType.getAttribute("type"),
+ configuredDefaultType.getAttribute("key") };
+ }
+ final Configuration configuredjsonPath = conf.getChild(USE_JSON_PATH,
false);
+ if (configuredjsonPath != null) {
+ this.useJsonPath = configuredjsonPath.getValueAsBoolean();
+ }
+ }
+
+ @Override
+ public void initialize() throws Exception {
+ mapper = new ObjectMapper(null, null, null);// add configurable
JsonFactory,.. later?
+
+ initAnnotationInspectors();
+
+ initFeatures();
+
+ initDefaultTyping();
+
+ getLogger().info("setting date format to:" + dateFormat);
+ getLogger().info("cacheFilters is:" + isCacheFilters());
+ if (!isCacheFilters()) {
+ mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE,
true);
+ }
+
+ mapper.setDateFormat(new SimpleDateFormat(dateFormat));
+
+ if (escapeCharsGlobal) {
+ mapper.getFactory().setCharacterEscapes(characterEscapes);
+ }
+ if (escapeCharsClass != null) {
+ try {
+ characterEscapes = (CharacterEscapes)
Class.forName(escapeCharsClass).getConstructor().newInstance();
+ } catch (Exception e) {
+ throw new Exception(
+ "JsonMapperService: Error instantiating " +
escapeCharsClass + " for " + ESCAPE_CHAR_CLASS);
+ }
+ }
+
+ getLogger().debug("initialized mapper:" + mapper);
+
+ mapper.getSerializerProvider().setNullValueSerializer(new
JsonSerializer<Object>() {
+ @Override
+ public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException {
+ jgen.writeString("");
+
+ }
+ });
+ cacheService = new CacheService(primary);
+ if (cacheService instanceof LogEnabled) {
+
cacheService.enableLogging(getLogger().getChildLogger(cacheService.getClass().getSimpleName()));
+ getLogger().info("setting cacheService logger: " +
cacheService.getClass().getSimpleName());
+ }
+
+ if (useJsonPath) {
+ // set it before runtime
+ DefaultJsonPathWrapper djpw = null;
+ try {
+ djpw = new DefaultJsonPathWrapper(this.mapper);
+ getLogger().debug("******** initialized new jsonPath defaults:
" + djpw.getJsonPathDefault());
+ } catch (Exception e) {
+ throw new Exception(
+ "JsonMapperService: Error instantiating " + djpw + "
using useJsonPath=" + useJsonPath);
+ }
+
+ }
+ }
+
+ private void initDefaultTyping() {
+ if (defaultTypeDefs != null && defaultTypeDefs.length == 2) {
+ DefaultTyping defaultTyping =
DefaultTyping.valueOf(defaultTypeDefs[0]);
+ mapper.enableDefaultTypingAsProperty(defaultTyping,
defaultTypeDefs[1]);
+ getLogger().info("default typing is " + defaultTypeDefs[0] + "
with key:" + defaultTypeDefs[1]);
+ }
+ }
+
+ private void initFeatures() throws Exception {
+ if (features != null && !features.isEmpty()) {
+
+ for (Entry<String, Boolean> entry : features.entrySet()) {
+ String featureKey = entry.getKey();
+ Boolean featureValue = entry.getValue();
+ String featureType = featureTypes.get(featureKey);
+ Class<?> configFeature = null;
+ try {
+ getLogger().debug("initializing featureType: " +
featureType);
+ configFeature = Class.forName(featureType);
+ } catch (Exception e) {
+ throw new Exception("JsonMapperService: Error
instantiating " + featureType + " for " + featureKey,
+ e);
+ }
+ ConfigFeature feature = null;
+ if (!StringUtils.isEmpty(featureKey) && featureValue != null) {
+ try {
+ if (configFeature.equals(SerializationFeature.class)) {
+ feature = SerializationFeature.valueOf(featureKey);
+ mapper.configure((SerializationFeature) feature,
featureValue);
+ assert mapper.getSerializationConfig()
+ .isEnabled((SerializationFeature) feature)
== featureValue;
+ getLogger().info("initialized serconfig mapper
feature: " + feature + " with "
+ +
mapper.getSerializationConfig().isEnabled((SerializationFeature) feature));
+ } else if
(configFeature.equals(DeserializationFeature.class)) {
+ feature =
DeserializationFeature.valueOf(featureKey);
+ mapper.configure((DeserializationFeature) feature,
featureValue);
+ assert mapper.getDeserializationConfig()
+ .isEnabled((DeserializationFeature)
feature) == featureValue;
+ getLogger().info("initialized deserconfig mapper
feature: " + feature + " with "
+ +
mapper.getDeserializationConfig().isEnabled((DeserializationFeature) feature));
+ } else if (configFeature.equals(MapperFeature.class)) {
+ feature = MapperFeature.valueOf(featureKey);
+ mapper.configure((MapperFeature) feature,
featureValue);
+ assert
mapper.getDeserializationConfig().isEnabled((MapperFeature) feature) ==
featureValue;
+ assert
mapper.getSerializationConfig().isEnabled((MapperFeature) feature) ==
featureValue;
+ getLogger().info("initialized serconfig mapper
feature: " + feature + " with "
+ +
mapper.getDeserializationConfig().isEnabled((MapperFeature) feature));
+ getLogger().info("initialized deserconfig mapper
feature: " + feature + " with "
+ +
mapper.getSerializationConfig().isEnabled((MapperFeature) feature));
+ } else if (configFeature.equals(JsonParser.class)) {
+ Feature parserFeature =
JsonParser.Feature.valueOf(featureKey);
+ getLogger().info("initializing parser feature: " +
parserFeature + " with " + featureValue);
+ mapper.configure(parserFeature, featureValue);
+ } else if (configFeature.equals(JsonGenerator.class)) {
+ com.fasterxml.jackson.core.JsonGenerator.Feature
genFeature = JsonGenerator.Feature
+ .valueOf(featureKey);
+ getLogger().info("initializing parser feature: " +
genFeature + " with " + featureValue);
+ mapper.configure(genFeature, featureValue);
+ }
+ } catch (Exception e) {
+ throw new Exception("JsonMapperService: Error
instantiating feature " + featureKey + " with "
+ + featureValue, e);
+ }
+ }
+ }
+ }
+ }
+
+ private void initAnnotationInspectors() throws Exception {
+ for (Entry<String, String> entry : annotationInspectors.entrySet()) {
+ String key = entry.getKey();
+ String avClass = entry.getValue();
+ if (key.equals("primary") && !StringUtils.isEmpty(avClass)) {
+ try {
+ primary = (AnnotationIntrospector)
Class.forName(avClass).getConstructor().newInstance();
+ } catch (Exception e) {
+ throw new Exception("JsonMapperService: Error
instantiating " + avClass + " for " + key);
+ }
+ } else if (key.equals("secondary") && avClass != null) {
+ try {
+ secondary = (AnnotationIntrospector)
Class.forName(avClass).getConstructor().newInstance();
+ } catch (Exception e) {
+ throw new Exception("JsonMapperService: Error
instantiating " + avClass + " for " + key);
+ }
+ }
+ }
+ if (primary == null) {
+ primary = new JacksonAnnotationIntrospector(); // support default
+ getLogger().info("using default introspector:" +
primary.getClass().getName());
+ mapper.setAnnotationIntrospector(primary);
+ } else if (primary != null && secondary != null) {
+ AnnotationIntrospector pair = new
AnnotationIntrospectorPair(primary, secondary);
+ mapper.setAnnotationIntrospector(pair);
+ } else {
+ mapper.setAnnotationIntrospector(primary);
+ }
+
+ if (primary instanceof LogEnabled) {
+ ((LogEnabled)
primary).enableLogging(getLogger().getChildLogger(primary.getClass().getSimpleName()));
+ getLogger().info("setting primary introspector logger: " +
primary.getClass().getSimpleName());
+ }
+ if (secondary instanceof LogEnabled) {
+ ((LogEnabled)
secondary).enableLogging(getLogger().getChildLogger(secondary.getClass().getSimpleName()));
+ getLogger().info("setting secondary introspector logger: " +
secondary.getClass().getSimpleName());
+ }
+ }
+
+ public ObjectMapper getMapper() {
+ return mapper;
+ }
+
+ public void setMapper(ObjectMapper mapper) {
+ this.mapper = mapper;
+ }
+
+ public boolean isCacheFilters() {
+ return cacheFilters;
+ }
+
+ public void setCacheFilters(boolean cacheFilters) {
+ this.cacheFilters = cacheFilters;
+ if (!cacheFilters)
+ mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE,
true);
+ }
+
+ static CharacterEscapes characterEscapes = new CharacterEscapes() {
+ private static final long serialVersionUID = 1L;
+ private final int[] asciiEscapes;
+ { // instance init
+ int[] esc = standardAsciiEscapesForJSON();
+ // this avoids to get evaluated immediately
+ esc['<'] = CharacterEscapes.ESCAPE_STANDARD;
+ esc['>'] = CharacterEscapes.ESCAPE_STANDARD;
+ esc['&'] = CharacterEscapes.ESCAPE_STANDARD;
+ esc['\''] = CharacterEscapes.ESCAPE_STANDARD;
+ // esc['/'] = '/'; //CharacterEscapes.ESCAPE_CUSTOM;
+ asciiEscapes = esc;
+ }
+
+ @Override
+ public int[] getEscapeCodesForAscii() {
+ return asciiEscapes;
+ }
- @Override
- public SerializableString getEscapeSequence(final int ch) {
+ @Override
+ public SerializableString getEscapeSequence(final int ch) {
// if ( ch == '/') {
// return new SerializedString("\\\\/");
// } else {
- return null;
+ return null;
// }
- }
- };
+ }
+ };
}
Modified: turbine/fulcrum/trunk/json/jackson2/src/test/log4j2.xml
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/test/log4j2.xml?rev=1848852&r1=1848851&r2=1848852&view=diff
==============================================================================
--- turbine/fulcrum/trunk/json/jackson2/src/test/log4j2.xml (original)
+++ turbine/fulcrum/trunk/json/jackson2/src/test/log4j2.xml Thu Dec 13 14:54:04
2018
@@ -25,14 +25,20 @@
<File name="logfile" fileName="target/fulcrum-test.log">
<PatternLayout pattern="%d [%t] %-5p %c - %m%n"/>
</File>
+ <File name="avalon" fileName="target/avalon-test.log">
+ <PatternLayout pattern="%d [%t] %-5p %c - %m%n"/>
+ </File>
</Appenders>
<Loggers>
<Logger name="org.apache.fulcrum" level="debug" additivity="false">
<AppenderRef ref="console"/>
<AppenderRef ref="logfile"/>
</Logger>
+ <Logger name="org.apache.fulcrum.yaafi" level="debug"
additivity="false">
+ <AppenderRef ref="avalon"/>
+ </Logger>
<Logger name="avalon" level="debug" additivity="false">
- <AppenderRef ref="console"/>
+ <AppenderRef ref="avalon"/>
</Logger>
<Logger name="org.apache.logging.log4j" level="info" additivity="false">
<AppenderRef ref="logfile"/>