diff --git a/build.gradle b/build.gradle index f5bc086c8a..a64e86a4f3 100644 --- a/build.gradle +++ b/build.gradle @@ -115,16 +115,9 @@ 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' - // JSON parser - implementation "com.fasterxml.jackson.core:jackson-core:2.12.3" - implementation "com.fasterxml.jackson.core:jackson-databind:2.12.3" - // PDF Filter implementation 'org.apache.pdfbox:pdfbox:2.0.24' @@ -207,9 +200,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 diff --git a/src/gen/core/project/Masks.java b/src/gen/core/project/Masks.java index b48a97d08c..9d8cafb88f 100644 --- a/src/gen/core/project/Masks.java +++ b/src/gen/core/project/Masks.java @@ -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; @@ -33,6 +37,8 @@ }) public class Masks { + // workaround https://github.com/FasterXML/jackson-modules-base/issues/127 + @JacksonXmlElementWrapper(useWrapping=false) protected List mask; /** diff --git a/src/org/omegat/convert/v20to21/Convert20to21.java b/src/org/omegat/convert/v20to21/Convert20to21.java index 6a67fd7ea1..637ebd5981 100644 --- a/src/org/omegat/convert/v20to21/Convert20to21.java +++ b/src/org/omegat/convert/v20to21/Convert20to21.java @@ -38,7 +38,12 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamWriter; +import com.ctc.wstx.shaded.msv.org_jp_gr_xml.dom.XMLMaker; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; import gen.core.filters.Files; import gen.core.filters.Filter; import gen.core.filters.Filters; @@ -108,10 +113,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); } /** diff --git a/src/org/omegat/core/statistics/StatsResult.java b/src/org/omegat/core/statistics/StatsResult.java index d1192558c4..daef3bf60a 100644 --- a/src/org/omegat/core/statistics/StatsResult.java +++ b/src/org/omegat/core/statistics/StatsResult.java @@ -41,11 +41,16 @@ import javax.xml.bind.JAXB; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.stream.XMLOutputFactory; 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; @@ -248,11 +253,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() { diff --git a/src/org/omegat/filters2/master/FilterMaster.java b/src/org/omegat/filters2/master/FilterMaster.java index aa2f7eab79..0dc8025365 100644 --- a/src/org/omegat/filters2/master/FilterMaster.java +++ b/src/org/omegat/filters2/master/FilterMaster.java @@ -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; @@ -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). */ @@ -108,14 +104,6 @@ public class FilterMaster { /** Classes of all filters. */ static List> filtersClasses = Collections.emptyList(); - static { - try { - CONFIG_CTX = JAXBContext.newInstance(Filters.class); - } catch (Exception ex) { - throw new ExceptionInInitializerError(ex); - } - } - public static void setFilterClasses(List> classes) { filtersClasses = new ArrayList<>(classes); } @@ -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); @@ -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); @@ -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 */ @@ -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) { diff --git a/src/org/omegat/util/ProjectFileStorage.java b/src/org/omegat/util/ProjectFileStorage.java index 08a72754a9..b0d51bafc6 100644 --- a/src/org/omegat/util/ProjectFileStorage.java +++ b/src/org/omegat/util/ProjectFileStorage.java @@ -33,13 +33,25 @@ import java.io.ByteArrayInputStream; import java.io.File; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.nio.file.Files; 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 javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; +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; @@ -71,21 +83,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); } /** @@ -238,9 +243,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) { diff --git a/src/org/omegat/util/TMXReader2.java b/src/org/omegat/util/TMXReader2.java index 2efc8f0bb3..0510605671 100644 --- a/src/org/omegat/util/TMXReader2.java +++ b/src/org/omegat/util/TMXReader2.java @@ -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. @@ -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; } @@ -679,7 +678,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")) { diff --git a/src/org/omegat/util/TMXWriter2.java b/src/org/omegat/util/TMXWriter2.java index 1d4cc7bf97..c7fb42697c 100644 --- a/src/org/omegat/util/TMXWriter2.java +++ b/src/org/omegat/util/TMXWriter2.java @@ -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; @@ -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; @@ -82,10 +82,6 @@ public class TMXWriter2 implements AutoCloseable { */ private final SimpleDateFormat tmxDateFormat; - static { - FACTORY = XMLOutputFactory.newInstance(); - } - /** * * @param file to write TMX entries. @@ -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); diff --git a/test/src/org/omegat/util/TMXWriterTest.java b/test/src/org/omegat/util/TMXWriterTest.java index d05fa218b5..7471eca5bb 100644 --- a/test/src/org/omegat/util/TMXWriterTest.java +++ b/test/src/org/omegat/util/TMXWriterTest.java @@ -28,9 +28,10 @@ import static org.junit.Assert.assertTrue; import java.io.File; -import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; @@ -50,11 +51,12 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + import org.omegat.core.data.ProjectProperties; import org.omegat.core.data.RealProjectTest; import org.omegat.filters.TestFilterBase; -import org.w3c.dom.Document; -import org.w3c.dom.Node; /** * @author Alex Buloichik @@ -158,35 +160,25 @@ public void testLevel2reads() throws Exception { @Test public void testEOLwrite() throws Exception { String eol = TMXWriter2.lineSeparator; - try { - TMXWriter2.lineSeparator = "\r\n"; - - TMXWriter2 wr = new TMXWriter2(outFile, new Language("en-US"), new Language("be-BY"), false, - true, false); - wr.writeEntry("source", "tar\nget", RealProjectTest.createEmptyTMXEntry(), null); - wr.close(); - - StringBuilder text = new StringBuilder(); - try (Reader rd = new InputStreamReader(new FileInputStream(outFile), "UTF-8")) { - char[] buffer = new char[512]; - while (true) { - int len = rd.read(buffer); - if (len < 0) { - break; - } - text.append(buffer, 0, len); + TMXWriter2 wr = new TMXWriter2(outFile, new Language("en-US"), new Language("be-BY"), false, + true, false); + wr.writeEntry("source", "tar\nget", RealProjectTest.createEmptyTMXEntry(), null); + wr.close(); + + StringBuilder text = new StringBuilder(); + try (Reader rd = new InputStreamReader(Files.newInputStream(outFile.toPath()), StandardCharsets.UTF_8)) { + char[] buffer = new char[512]; + while (true) { + int len = rd.read(buffer); + if (len < 0) { + break; } + text.append(buffer, 0, len); } - assertTrue(text.toString().contains("tar\r\nget")); - - final List trs = new ArrayList(); - load(null, trs, true, false); - assertTrue(trs.get(0).contains("tar\nget")); - } finally { - TMXWriter2.lineSeparator = eol; } + assertTrue(text.toString().contains("tar" + eol + "get")); - final List trs = new ArrayList(); + final List trs = new ArrayList<>(); load(null, trs, true, false); assertTrue(trs.get(0).contains("tar\nget")); }