Skip to content

Commit

Permalink
Use Jackson XML dataformat for JAXB data parser
Browse files Browse the repository at this point in the history
- Update TMXWriterTest to check with system line separator
  It is because XML parser can automatically change /r/n into
  XML entity 
/n when System.lineSeparator() is /n
- Update TMXReader2 to detect both "lang" and "xml:lang"
  some implementation return "lang" from "xml:lang" but
  other can return "xml:lang" as is.
- as a workaround for  FasterXML/jackson-modules-base#127
  Add  @JacksonXmlElementWrapper(useWrapping=false) for mask
  element for the parser of omegat.project file.

Signed-off-by: Hiroshi Miura <miurahr@linux.com>
  • Loading branch information
miurahr committed Oct 15, 2022
1 parent 3fd8b79 commit d625c5c
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 99 deletions.
6 changes: 2 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,6 @@ dependencies {
// macOS integration
implementation 'org.madlonkay:desktopsupport:0.6.0'

api 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'com.sun.xml.bind:jaxb-impl:2.3.4'

// Data: inline data URL handler
implementation 'tokyo.northside:url-protocol-handler:0.1.4'

Expand Down Expand Up @@ -204,9 +201,10 @@ dependencies {
// Moses MT connector
implementation 'org.apache.xmlrpc:xmlrpc-client:3.1.3'

// JSON parser
// XML/JSON parser
implementation "com.fasterxml.jackson.core:jackson-core:2.12.3"
implementation "com.fasterxml.jackson.core:jackson-databind:2.12.3"
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.12.3"
}

// Test dependencies
Expand Down
6 changes: 6 additions & 0 deletions src/gen/core/project/Masks.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@

package gen.core.project;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlType;


Expand Down Expand Up @@ -33,6 +37,8 @@
})
public class Masks {

// workaround https://github.com/FasterXML/jackson-modules-base/issues/127
@JacksonXmlElementWrapper(useWrapping=false)
protected List<String> mask;

/**
Expand Down
17 changes: 6 additions & 11 deletions src/org/omegat/convert/v20to21/Convert20to21.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
import java.io.Serializable;
import java.nio.charset.StandardCharsets;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;

import gen.core.filters.Files;
import gen.core.filters.Filter;
Expand All @@ -60,19 +60,15 @@ private Convert20to21() {
* old config file
* @param toFile
* new config file
* @throws Exception
*/
public static void convertFiltersConfig(final File fromFile, final File toFile) throws Exception {
if (!fromFile.exists()) {
return;
}
String c = read(fromFile);
org.omegat.convert.v20to21.data.Filters filters;
XMLDecoder xmldec = new XMLDecoder(new ByteArrayInputStream(c.getBytes("UTF-8")));
try {
try (XMLDecoder xmldec = new XMLDecoder(new ByteArrayInputStream(c.getBytes(StandardCharsets.UTF_8)))) {
filters = (org.omegat.convert.v20to21.data.Filters) xmldec.readObject();
} finally {
xmldec.close();
}

Filters res = new Filters();
Expand Down Expand Up @@ -108,10 +104,9 @@ public static void convertFiltersConfig(final File fromFile, final File toFile)
convertTextFilter(res);
convertHTMLFilter2(res);

JAXBContext ctx = JAXBContext.newInstance(Filters.class);
Marshaller m = ctx.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(res, toFile);
XmlMapper mapper = new XmlMapper();
mapper.registerModule(new JaxbAnnotationModule());
mapper.writeValue(toFile, res);
}

/**
Expand Down
14 changes: 9 additions & 5 deletions src/org/omegat/core/statistics/StatsResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,17 @@
import java.util.Set;
import java.util.TimeZone;

import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SequenceWriter;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import org.omegat.util.OStrings;
import org.omegat.util.StaticUtils;
import org.omegat.util.gui.TextUtil;
Expand Down Expand Up @@ -248,11 +251,12 @@ public String getJsonData() throws IOException {
* @return XML expression of stats data as String.
*/
@JsonIgnore
public String getXmlData() {
public String getXmlData() throws JsonProcessingException {
setDate();
StringWriter result = new StringWriter();
JAXB.marshal(this, result);
return result.toString();
XmlMapper mapper = new XmlMapper();
mapper.registerModule(new JaxbAnnotationModule());
mapper.enable(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME);
return mapper.writeValueAsString(this);
}

private void setDate() {
Expand Down
34 changes: 11 additions & 23 deletions src/org/omegat/filters2/master/FilterMaster.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,8 @@
import java.util.TreeMap;
import java.util.regex.Pattern;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import org.apache.commons.io.FileUtils;
import org.omegat.filters2.AbstractFilter;
import org.omegat.filters2.FilterContext;
Expand Down Expand Up @@ -88,8 +86,6 @@ public class FilterMaster {
/** name of the filter configuration file */
public static final String FILE_FILTERS = "filters.xml";

private static final JAXBContext CONFIG_CTX;

/**
* There was no version of file filters support (1.4.5 Beta 1 -- 1.6.0 RC12).
*/
Expand All @@ -108,14 +104,6 @@ public class FilterMaster {
/** Classes of all filters. */
static List<Class<?>> filtersClasses = Collections.emptyList();

static {
try {
CONFIG_CTX = JAXBContext.newInstance(Filters.class);
} catch (Exception ex) {
throw new ExceptionInInitializerError(ex);
}
}

public static void setFilterClasses(List<Class<?>> classes) {
filtersClasses = new ArrayList<>(classes);
}
Expand Down Expand Up @@ -437,8 +425,8 @@ public static Filters loadConfig(File configFile) throws IOException {
}
Filters result;
try {
Unmarshaller unm = CONFIG_CTX.createUnmarshaller();
result = (Filters) unm.unmarshal(configFile);
XmlMapper mapper = new XmlMapper();
result = mapper.readValue(configFile, Filters.class);
} catch (Exception e) {
Log.logErrorRB("FILTERMASTER_ERROR_LOADING_FILTERS_CONFIG");
Log.log(e);
Expand All @@ -459,13 +447,13 @@ public static Filters loadConfig(File configFile) throws IOException {
*/
public static void saveConfig(Filters config, File configFile) throws IOException {
if (config == null) {
configFile.delete();
boolean ignored = configFile.delete();
return;
}
try {
Marshaller m = CONFIG_CTX.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(config, configFile);
XmlMapper mapper = new XmlMapper();
mapper.registerModule(new JaxbAnnotationModule());
mapper.writeValue(configFile, config);
} catch (Exception e) {
Log.logErrorRB("FILTERMASTER_ERROR_SAVING_FILTERS_CONFIG");
Log.log(e);
Expand Down Expand Up @@ -713,7 +701,7 @@ public static Filters cloneConfig(Filters orig) {
/**
* Clone one filter's config for editing.
*
* @param f
* @param filter
* one filter's config
* @return new config instance
*/
Expand All @@ -736,8 +724,8 @@ public static Filter cloneFilter(Filter filter) {
/**
* Clone one filter's instance config for editing.
*
* @param f
* new filter's instance config
* @param files
* new filter's instance config file
* @return new config instance
*/
private static Files cloneFiles(Files files) {
Expand Down
26 changes: 9 additions & 17 deletions src/org/omegat/util/ProjectFileStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,16 @@

package org.omegat.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import org.omegat.core.data.ProjectProperties;
import org.omegat.filters2.TranslationException;
import org.omegat.filters2.master.PluginUtils;
Expand Down Expand Up @@ -71,21 +70,14 @@ private ProjectFileStorage() {
*/
public static final String DEFAULT_FOLDER_MARKER = "__DEFAULT__";

private static final JAXBContext CONTEXT;
static {
try {
CONTEXT = JAXBContext.newInstance(Omegat.class);
} catch (Exception ex) {
throw new ExceptionInInitializerError(ex);
}
}

public static Omegat parseProjectFile(File file) throws Exception {
return parseProjectFile(FileUtils.readFileToByteArray(file));
}

public static Omegat parseProjectFile(byte[] projectFile) throws Exception {
return (Omegat) CONTEXT.createUnmarshaller().unmarshal(new ByteArrayInputStream(projectFile));
XmlMapper mapper = new XmlMapper();
mapper.registerModule(new JaxbAnnotationModule());
return mapper.readValue(projectFile, Omegat.class);
}

/**
Expand Down Expand Up @@ -238,9 +230,9 @@ public static void writeProjectFile(ProjectProperties props) throws Exception {
om.getProject().getRepositories().getRepository().addAll(props.getRepositories());
}

Marshaller m = CONTEXT.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(om, outFile);
XmlMapper mapper = new XmlMapper();
mapper.registerModule(new JaxbAnnotationModule());
mapper.writeValue(outFile, om);
}

private static String normalizeLoadedPath(String path, String defaultValue) {
Expand Down
5 changes: 2 additions & 3 deletions src/org/omegat/util/TMXReader2.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
import org.apache.commons.io.input.XmlStreamReader;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
* Helper for read TMX files, using StAX.
Expand Down Expand Up @@ -276,7 +275,7 @@ protected void parseTuv(StartElement element) throws Exception {
// find 'lang' or 'xml:lang' attribute
for (Iterator<?> it = element.getAttributes(); it.hasNext();) {
Attribute a = (Attribute) it.next();
if ("lang".equals(a.getName().getLocalPart())) {
if ("lang".equals(a.getName().getLocalPart()) || "xml:lang".equals(a.getName().getLocalPart())) {
tuv.lang = a.getValue();
break;
}
Expand Down Expand Up @@ -681,7 +680,7 @@ public static class ParsedTuv {
}

public static final EntityResolver TMX_DTD_RESOLVER = new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
public InputSource resolveEntity(String publicId, String systemId) {
if (systemId.endsWith("tmx11.dtd")) {
return new InputSource(TMXReader2.class.getResourceAsStream("/schemas/tmx11.dtd"));
} else if (systemId.endsWith("tmx14.dtd")) {
Expand Down
13 changes: 5 additions & 8 deletions src/org/omegat/util/TMXWriter2.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
Expand Down Expand Up @@ -66,7 +66,7 @@ public class TMXWriter2 implements AutoCloseable {

public static final String PROP_ID = "id";

private static final XMLOutputFactory FACTORY;
private final XMLOutputFactory factory;

private final OutputStream out;
private final XMLStreamWriter xml;
Expand All @@ -82,10 +82,6 @@ public class TMXWriter2 implements AutoCloseable {
*/
private final SimpleDateFormat tmxDateFormat;

static {
FACTORY = XMLOutputFactory.newInstance();
}

/**
*
* @param file to write TMX entries.
Expand All @@ -100,9 +96,10 @@ public TMXWriter2(final File file, final Language sourceLanguage, final Language
boolean sentenceSegmentingEnabled, boolean levelTwo, boolean forceValidTMX) throws Exception {
this.levelTwo = levelTwo;
this.forceValidTMX = forceValidTMX;
factory = XMLOutputFactory.newInstance();

out = new BufferedOutputStream(new FileOutputStream(file));
xml = FACTORY.createXMLStreamWriter(out, StandardCharsets.UTF_8.name());
out = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
xml = factory.createXMLStreamWriter(out, StandardCharsets.UTF_8.name());

xml.writeStartDocument(StandardCharsets.UTF_8.name(), "1.0");
xml.writeCharacters(lineSeparator);
Expand Down

0 comments on commit d625c5c

Please sign in to comment.