Java tutorial
/*- * #%L * XML Format Maven Plugin * %% * Copyright (C) 2011 - 2019 Acegi Technology Pty Limited * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ package au.com.acegi.xmlformat; import static au.com.acegi.xmlformat.IOUtil.hash; import java.io.File; import static java.io.File.createTempFile; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringReader; import java.nio.file.Files; import static java.nio.file.Files.copy; import java.nio.file.Path; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Utility methods private to the package. */ final class FormatUtil { private static final String TMP_FILE_PREFIX = FormatUtil.class.getSimpleName(); private FormatUtil() { } /** * Ingest an input stream, writing formatted XML to the output stream. The * caller is responsible for closing the input and output streams. Any errors * in the input stream will cause an exception and the output stream should * not be relied upon. * * @param in input XML stream * @param out output XML stream * @param fmt format configuration to apply * @throws DocumentException if input XML could not be parsed * @throws IOException if output XML stream could not be written */ static void format(final InputStream in, final OutputStream out, final OutputFormat fmt) throws DocumentException, IOException { final SAXReader reader = new SAXReader(); reader.setEntityResolver(new EntityResolver() { @Override public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException { return new InputSource(new StringReader("")); } }); final Document xmlDoc = reader.read(in); final XMLWriter xmlWriter = new XMLWriter(out, fmt); xmlWriter.write(xmlDoc); xmlWriter.flush(); } /** * Formats the input file, overwriting the input file with the new content if * the formatted content differs. * * @param file to read and then potentially overwrite * @param fmt format configuration to apply * @return true if the file was overwritten * @throws DocumentException if input XML could not be parsed * @throws IOException if output XML stream could not be written */ @SuppressWarnings("checkstyle:returncount") static boolean formatInPlace(final File file, final OutputFormat fmt) throws DocumentException, IOException { if (file.length() == 0) { return false; } final File tmpFile = createTempFile(TMP_FILE_PREFIX, ".xml"); tmpFile.deleteOnExit(); try (InputStream in = Files.newInputStream(file.toPath()); OutputStream out = Files.newOutputStream(tmpFile.toPath())) { format(in, out, fmt); } final long hashFile = hash(file); final long hashTmp = hash(tmpFile); if (hashFile == hashTmp) { return false; } final Path source = tmpFile.toPath(); final Path target = file.toPath(); copy(source, target, REPLACE_EXISTING); return true; } }