This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.models.jacksonexporter-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-jacksonexporter.git
commit 642f9c1c52543963d8db943d5b0f44a8dc9ef84f Author: Justin Edelson <[email protected]> AuthorDate: Fri Oct 28 15:02:13 2016 +0000 SLING-6183 - add Sling Model Exporter feature git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/models/jackson-exporter@1767030 13f79535-47bb-0310-9956-ffa450edef68 --- README.txt | 24 ++++ pom.xml | 128 +++++++++++++++++++ .../jacksonexporter/impl/JacksonExporter.java | 139 +++++++++++++++++++++ 3 files changed, 291 insertions(+) diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..19ee9e2 --- /dev/null +++ b/README.txt @@ -0,0 +1,24 @@ +Apache Sling Models Jackson Exporter + +Getting Started +=============== + +This component uses a Maven 2 (http://maven.apache.org/) build +environment. It requires a Java 5 JDK (or higher) and Maven (http://maven.apache.org/) +2.0.7 or later. We recommend to use the latest Maven version. + +If you have Maven 2 installed, you can compile and +package the jar using the following command: + + mvn package + +See the Maven 2 documentation for other build features. + +The latest source code for this component is available in the +Subversion (http://subversion.tigris.org/) source repository of +the Apache Software Foundation. If you have Subversion installed, +you can checkout the latest source using the following command: + + svn checkout http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/models/jackson-exporter + +See the Subversion documentation for other source control features. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0c0743c --- /dev/null +++ b/pom.xml @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- 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. --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.sling</groupId> + <artifactId>sling</artifactId> + <version>25</version> + <relativePath /> + </parent> + + <artifactId>org.apache.sling.models.jacksonexporter</artifactId> + <version>0.0.99-SNAPSHOT</version> + <packaging>bundle</packaging> + <name>Apache Sling Models Model Exporter - Jackson</name> + <description>Apache Sling Models Client Model Exporter - Jackson</description> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/models/jackson-exporter</connection> + <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/models/jackson-exporter</developerConnection> + <url>http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/jackson-exporter</url> + </scm> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-scr-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Embed-Dependency>*;scope=compile</Embed-Dependency> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.models.api</artifactId> + <version>1.3.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.scr.annotations</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.9.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.code.findbugs</groupId> + <artifactId>jsr305</artifactId> + <version>3.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <version>2.6</version> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <scope>provided</scope> + </dependency> + <!-- *************************************************************** --> + <!-- JACKSON --> + <!-- *************************************************************** --> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.3.2</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>2.3.2</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>2.3.2</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/models/jacksonexporter/impl/JacksonExporter.java b/src/main/java/org/apache/sling/models/jacksonexporter/impl/JacksonExporter.java new file mode 100644 index 0000000..71492e1 --- /dev/null +++ b/src/main/java/org/apache/sling/models/jacksonexporter/impl/JacksonExporter.java @@ -0,0 +1,139 @@ +/* + * 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.sling.models.jacksonexporter.impl; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; + +import com.fasterxml.jackson.databind.MapperFeature; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.models.export.spi.ModelExporter; +import org.apache.sling.models.factory.ExportException; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.SerializableString; +import com.fasterxml.jackson.core.io.CharacterEscapes; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component +@Service +public class JacksonExporter implements ModelExporter { + + private static final Logger log = LoggerFactory.getLogger(JacksonExporter.class); + + private static final String SERIALIZATION_FEATURE_PREFIX = SerializationFeature.class.getSimpleName() + "."; + + private static final int SERIALIZATION_FEATURE_PREFIX_LENGTH = SERIALIZATION_FEATURE_PREFIX.length(); + + private static final String MAPPER_FEATURE_PREFIX = MapperFeature.class.getSimpleName() + "."; + + private static final int MAPPER_FEATURE_PREFIX_LENGTH = MAPPER_FEATURE_PREFIX.length(); + + @Override + public boolean isSupported(Class<?> clazz) { + return clazz.equals(String.class) || clazz.equals(Map.class); + } + + @Override + public <T> T export(Object model, Class<T> clazz, Map<String, String> options) + throws ExportException { + ObjectMapper mapper = new ObjectMapper(); + for (Map.Entry<String, String> optionEntry : options.entrySet()) { + String key = optionEntry.getKey(); + if (key.startsWith(SERIALIZATION_FEATURE_PREFIX)) { + String enumName = key.substring(SERIALIZATION_FEATURE_PREFIX_LENGTH); + try { + SerializationFeature feature = SerializationFeature.valueOf(enumName); + mapper.configure(feature, Boolean.valueOf(optionEntry.getValue())); + } catch (IllegalArgumentException e) { + log.warn("Bad SerializationFeature option"); + } + } else if (key.startsWith(MAPPER_FEATURE_PREFIX)) { + String enumName = key.substring(MAPPER_FEATURE_PREFIX_LENGTH); + try { + MapperFeature feature = MapperFeature.valueOf(enumName); + mapper.configure(feature, Boolean.valueOf(optionEntry.getValue())); + } catch (IllegalArgumentException e) { + log.warn("Bad SerializationFeature option"); + } + } + } + + if (clazz.equals(Map.class)) { + return (T) mapper.convertValue(model, Map.class); + } else if (clazz.equals(String.class)) { + final JsonFactory f = new JsonFactory(); + f.setCharacterEscapes(new EscapeCloseScriptBlocks()); + StringWriter writer = new StringWriter(); + JsonGenerator jgen; + final boolean printTidy; + if (options.containsKey("tidy")) { + printTidy = Boolean.valueOf(options.get("tidy")); + } else { + printTidy = false; + } + try { + jgen = f.createGenerator(writer); + if (printTidy) { + mapper.writerWithDefaultPrettyPrinter().writeValue(jgen, model); + } else { + mapper.writeValue(jgen, model); + } + } catch (final IOException e) { + throw new ExportException(e); + } + return (T) writer.toString(); + } else { + return null; + } + } + + @Override + public String getName() { + return "jackson"; + } + + private static class EscapeCloseScriptBlocks extends CharacterEscapes { + private final int[] escapes; + + public EscapeCloseScriptBlocks() { + int[] baseEscapes = standardAsciiEscapesForJSON(); + baseEscapes['<'] = CharacterEscapes.ESCAPE_STANDARD; + baseEscapes['>'] = CharacterEscapes.ESCAPE_STANDARD; + escapes = baseEscapes; + } + + @Override + public int[] getEscapeCodesForAscii() { + return escapes; + } + + @Override + public SerializableString getEscapeSequence(final int arg0) { + return null; + } + } +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
