org.dita.dost.TestUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.dita.dost.TestUtils.java

Source

/*
 * This file is part of the DITA Open Toolkit project.
 * See the accompanying license.txt file for applicable licenses.
 */
package org.dita.dost;

import static org.apache.commons.io.FileUtils.*;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;

import org.custommonkey.xmlunit.XMLUnit;

import org.dita.dost.log.DITAOTLogger;
import org.dita.dost.util.CatalogUtils;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.XMLFilterImpl;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * Test utilities.
 * 
 * @author Jarno Elovirta
 */
public class TestUtils {

    public static final File testStub = new File("src" + File.separator + "test" + File.separator + "resources");

    /**
     * Get test resource directory
     * 
     * @param testClass test class
     * @return resource directory
     * @throws RuntimeException if retrieving the directory failed
     */
    public static File getResourceDir(final Class<?> testClass) throws RuntimeException {
        final URL dir = ClassLoader.getSystemResource(testClass.getSimpleName());
        if (dir == null) {
            throw new RuntimeException("Failed to find resource for " + testClass.getSimpleName());
        }
        try {
            return new File(dir.toURI());
        } catch (URISyntaxException e) {
            throw new RuntimeException(
                    "Failed to find resource for " + testClass.getSimpleName() + ":" + e.getMessage(), e);
        }
    }

    /**
     * Create temporary directory based on test class.
     * 
     * @param testClass test class
     * @return temporary directory
     * @throws IOException if creating directory failed
     */
    public static File createTempDir(final Class<?> testClass) throws IOException {
        final File tempDir = new File(System.getProperty("java.io.tmpdir"), testClass.getName());
        if (!tempDir.exists() && !tempDir.mkdirs()) {
            throw new IOException("Unable to create temporary directory " + tempDir.getAbsolutePath());
        }
        return tempDir;
    }

    /**
     * Read file contents into a string.
     * 
     * @param file file to read
     * @return contents of the file
     * @throws IOException if reading file failed
     */
    public static String readFileToString(final File file) throws IOException {
        return readFileToString(file, false);
    }

    /**
     * Read file contents into a string.
     * 
     * @param file file to read
     * @param ignoreHead ignore first row
     * @return contents of the file
     * @throws IOException if reading file failed
     */
    public static String readFileToString(final File file, final boolean ignoreHead) throws IOException {
        final StringBuilder std = new StringBuilder();
        BufferedReader in = null;
        try {
            in = new BufferedReader(new FileReader(file));
            boolean firstLine = true;
            if (ignoreHead) {
                in.readLine();
            }
            String str;
            while ((str = in.readLine()) != null) {
                if (!firstLine) {
                    std.append("\n");
                } else {
                    firstLine = false;
                }
                std.append(str);
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }
        return std.toString();
    }

    /**
     * Read XML file contents into a string.
     * 
     * @param file XML file to read
     * @param normalize normalize whitespace
     * @return contents of the file
     * @throws Exception if parsing the file failed
     */
    public static String readXmlToString(final File file, final boolean normalize, final boolean clean)
            throws Exception {
        final Writer std = new CharArrayWriter();
        InputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(file));
            final Transformer t = TransformerFactory.newInstance().newTransformer();
            XMLReader p = XMLReaderFactory.createXMLReader();
            p.setEntityResolver(CatalogUtils.getCatalogResolver());
            if (normalize) {
                t.setOutputProperty(OutputKeys.INDENT, "yes");
                p = new NormalizingXMLFilterImpl(p);
            }
            if (clean) {
                p = new CleaningXMLFilterImpl(p);
            }
            t.transform(new SAXSource(p, new InputSource(in)), new StreamResult(std));
        } finally {
            if (in != null) {
                in.close();
            }
        }
        return std.toString();
    }

    private static class NormalizingXMLFilterImpl extends XMLFilterImpl {

        NormalizingXMLFilterImpl(final XMLReader parent) {
            super(parent);
        }

        @Override
        public void characters(final char[] ch, final int start, final int length) throws SAXException {
            final char[] res = new String(ch, start, length).replaceAll("\\s+", " ").trim().toCharArray();
            getContentHandler().characters(res, 0, res.length);
        }

        @Override
        public void ignorableWhitespace(final char[] ch, final int start, final int length) throws SAXException {
            //NOOP
        }

    }

    private static class CleaningXMLFilterImpl extends XMLFilterImpl {

        CleaningXMLFilterImpl(final XMLReader parent) {
            super(parent);
        }

        @Override
        public void startElement(final String uri, final String localName, final String qName,
                final Attributes atts) throws SAXException {
            final AttributesImpl attsBuf = new AttributesImpl(atts);
            for (final String a : new String[] { "class", "domains", "xtrf", "xtrc" }) {
                final int i = attsBuf.getIndex(a);
                if (i != -1) {
                    attsBuf.removeAttribute(i);
                }
            }
            getContentHandler().startElement(uri, localName, qName, attsBuf);
        }

        @Override
        public void processingInstruction(final String target, final String data) throws SAXException {
            // Ignore
        }

    }

    /**
     * Deletes a file. If file is a directory, delete it and all sub-directories.
     * 
     * @param file file or directory to delete, must not be null
     * @throws IOException in case deletion is unsuccessful
     */
    public static void forceDelete(final File file) throws IOException {
        if (file.exists()) {
            if (file.isDirectory()) {
                for (final File c : file.listFiles()) {
                    forceDelete(c);
                }
            }
            if (!file.delete()) {
                throw new IOException("Failed to delete " + file.getAbsolutePath());
            }
        }
    }

    /**
     * Copy directories recursively.
     * 
     * @param src source directory
     * @param dst destination directory
     * @throws IOException if copying failed
     */
    public static void copy(final File src, final File dst) throws IOException {
        if (src.isFile()) {
            copyFile(src, dst);
        } else {
            if (!dst.exists() && !dst.mkdirs()) {
                throw new IOException("Failed to create directory " + dst);
            }
            for (final File s : src.listFiles()) {
                copy(s, new File(dst, s.getName()));
            }
        }
    }

    /**
     * Normalize XML file.
     * 
     * @param src source XML file
     * @param dst destination XML file
     * @throws Exception if parsing or serializing failed
     */
    public static void normalize(final File src, final File dst) throws Exception {
        CatalogUtils.setDitaDir(new File("src" + File.separator + "main").getAbsoluteFile());
        final Transformer serializer = TransformerFactory.newInstance().newTransformer();
        final XMLReader parser = XMLReaderFactory.createXMLReader();
        parser.setEntityResolver(CatalogUtils.getCatalogResolver());
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new BufferedInputStream(new FileInputStream(src));
            out = new BufferedOutputStream(new FileOutputStream(dst));
            serializer.transform(new SAXSource(parser, new InputSource(in)), new StreamResult(out));
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

    /**
     * Reset XMLUnit configuration.
     */
    public static void resetXMLUnit() {
        final DocumentBuilderFactory b = DocumentBuilderFactory.newInstance();
        XMLUnit.setControlDocumentBuilderFactory(b);
        XMLUnit.setTestDocumentBuilderFactory(b);
        XMLUnit.setControlEntityResolver(null);
        XMLUnit.setTestEntityResolver(null);
    }

    /**
     * DITA-OT logger that will throw an assertion error for error messages.
     */
    public static class TestLogger implements DITAOTLogger {

        private boolean failOnError;

        public TestLogger() {
            this.failOnError = true;
        }

        public TestLogger(final boolean failOnError) {
            this.failOnError = failOnError;
        }

        public void info(final String msg) {
            //System.out.println(msg);
        }

        public void warn(final String msg) {
            //System.err.println(msg);
        }

        public void error(final String msg) {
            if (failOnError) {
                throw new AssertionError("Error message was thrown: " + msg);
            }
        }

        public void error(final String msg, final Throwable t) {
            if (failOnError) {
                t.printStackTrace();
                throw new AssertionError("Error message was thrown: " + msg);
            }
        }

        public void debug(final String msg) {
            //System.out.println(msg);
        }

    }

    /**
     * DITA-OT logger that will cache messages.
     */
    public static final class CachingLogger implements DITAOTLogger {

        private List<Message> buf = new ArrayList<Message>();

        public void info(final String msg) {
            buf.add(new Message(Message.Level.INFO, msg, null));
        }

        public void warn(final String msg) {
            buf.add(new Message(Message.Level.WARN, msg, null));
        }

        public void error(final String msg) {
            buf.add(new Message(Message.Level.ERROR, msg, null));
        }

        public void error(final String msg, final Throwable t) {
            buf.add(new Message(Message.Level.ERROR, msg, t));
        }

        public void logFatal(final String msg) {
            buf.add(new Message(Message.Level.FATAL, msg, null));
        }

        public void debug(final String msg) {
            buf.add(new Message(Message.Level.DEBUG, msg, null));
        }

        public void logException(final Throwable t) {
            buf.add(new Message(Message.Level.ERROR, t.getMessage(), t));
        }

        public static final class Message {
            public enum Level {
                DEBUG, INFO, WARN, ERROR, FATAL
            }

            public final Level level;
            public final String message;
            public final Throwable exception;

            public Message(final Level level, final String message, final Throwable exception) {
                this.level = level;
                this.message = message;
                this.exception = exception;
            }
        }

        public List<Message> getMessages() {
            return Collections.unmodifiableList(buf);
        }

    }

}