net.sf.jasperreports.engine.fonts.SimpleFontExtensionHelper.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jasperreports.engine.fonts.SimpleFontExtensionHelper.java

Source

/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
 * http://www.jaspersoft.com
 *
 * Unless you have purchased a commercial license agreement from Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of JasperReports.
 *
 * JasperReports is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JasperReports is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
 */
package net.sf.jasperreports.engine.fonts;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import net.sf.jasperreports.engine.DefaultJasperReportsContext;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.util.JRXmlUtils;
import net.sf.jasperreports.engine.util.JRXmlWriteHelper;
import net.sf.jasperreports.repo.RepositoryUtil;
import net.sf.jasperreports.util.StringBuilderWriter;

/**
 * @author Teodor Danciu (teodord@users.sourceforge.net)
 */
public final class SimpleFontExtensionHelper implements ErrorHandler {
    private static final Log log = LogFactory.getLog(SimpleFontExtensionHelper.class);
    public static final String EXCEPTION_MESSAGE_KEY_FILE_WRITER_ERROR = "fonts.file.writer.error";
    public static final String EXCEPTION_MESSAGE_KEY_OUTPUT_STREAM_WRITER_ERROR = "fonts.output.stream.writer.error";

    /**
     * Default XML output encoding.
     */
    public static final String DEFAULT_ENCODING = "UTF-8";

    /**
     *
     */
    private static final String NODE_fontFamily = "fontFamily";
    private static final String NODE_normal = "normal";
    private static final String NODE_bold = "bold";
    private static final String NODE_italic = "italic";
    private static final String NODE_boldItalic = "boldItalic";
    private static final String NODE_ttf = "ttf";
    private static final String NODE_pdf = "pdf";
    private static final String NODE_eot = "eot";
    private static final String NODE_svg = "svg";
    private static final String NODE_woff = "woff";
    /**
     * @deprecated Replaced by {@link #NODE_pdf}.
     */
    private static final String NODE_normalPdfFont = "normalPdfFont";
    /**
     * @deprecated Replaced by {@link #NODE_pdf}.
     */
    private static final String NODE_boldPdfFont = "boldPdfFont";
    /**
     * @deprecated Replaced by {@link #NODE_pdf}.
     */
    private static final String NODE_italicPdfFont = "italicPdfFont";
    /**
     * @deprecated Replaced by {@link #NODE_pdf}.
     */
    private static final String NODE_boldItalicPdfFont = "boldItalicPdfFont";
    private static final String NODE_pdfEncoding = "pdfEncoding";
    private static final String NODE_pdfEmbedded = "pdfEmbedded";
    private static final String NODE_exportFonts = "exportFonts";
    private static final String NODE_export = "export";
    private static final String NODE_locales = "locales";
    private static final String NODE_locale = "locale";
    private static final String NODE_includedScript = "includedScript";
    private static final String NODE_excludedScript = "excludedScript";
    private static final String NODE_fontSet = "fontSet";
    private static final String NODE_family = "family";
    private static final String ATTRIBUTE_name = "name";
    private static final String ATTRIBUTE_visible = "visible";
    private static final String ATTRIBUTE_key = "key";
    private static final String ATTRIBUTE_familyName = "familyName";
    private static final String ATTRIBUTE_primary = "primary";

    /**
     * Return a new instance.
     * 
     * @return a new instance
     */
    public static SimpleFontExtensionHelper getInstance() {
        SimpleFontExtensionHelper instance = new SimpleFontExtensionHelper();
        return instance;
    }

    /**
     *
     */
    private DocumentBuilder documentBuilder;

    /**
     *
     */
    private SimpleFontExtensionHelper() {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setFeature(JRXmlUtils.FEATURE_DISALLOW_DOCTYPE, true);

            documentBuilder = factory.newDocumentBuilder();
            documentBuilder.setErrorHandler(this);
        } catch (ParserConfigurationException e) {
            throw new JRRuntimeException(e);
        }
    }

    /**
     * @see #loadFontFamilies(JasperReportsContext, String)
     */
    public List<FontFamily> loadFontFamilies(String file) {
        return loadFontFamilies(DefaultJasperReportsContext.getInstance(), file);
    }

    /**
     *
     */
    public List<FontFamily> loadFontFamilies(JasperReportsContext jasperReportsContext, String file) {
        FontExtensionsCollector collector = new FontExtensionsCollector();
        loadFontExtensions(jasperReportsContext, file, collector);
        return collector.getFontFamilies();
    }

    public void loadFontExtensions(JasperReportsContext jasperReportsContext, String file,
            FontExtensionsReceiver receiver) {
        InputStream is = null;

        try {
            is = RepositoryUtil.getInstance(jasperReportsContext).getInputStreamFromLocation(file);
            loadFontExtensions(jasperReportsContext, is, receiver, true);
        } catch (JRException e) {
            throw new JRRuntimeException(e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     *
     */
    public List<FontFamily> loadFontFamilies(JasperReportsContext jasperReportsContext, InputStream is) {
        FontExtensionsCollector collector = new FontExtensionsCollector();
        loadFontExtensions(jasperReportsContext, is, collector);
        return collector.getFontFamilies();
    }

    public void loadFontExtensions(JasperReportsContext jasperReportsContext, InputStream is,
            FontExtensionsReceiver receiver) {
        loadFontExtensions(jasperReportsContext, is, receiver, true);
    }

    public void loadFontExtensions(JasperReportsContext jasperReportsContext, InputStream is,
            FontExtensionsReceiver receiver, boolean loadFonts) {
        try {
            Document document = documentBuilder.parse(new InputSource(new InputStreamReader(is, "UTF-8")));
            parseFontExtensions(jasperReportsContext, document.getDocumentElement(), receiver, loadFonts);
        } catch (SAXException e) {
            throw new JRRuntimeException(e);
        }

        catch (IOException e) {
            throw new JRRuntimeException(e);
        }
    }

    /**
     *
     */
    private void parseFontExtensions(JasperReportsContext jasperReportsContext, Node fontFamiliesNode,
            FontExtensionsReceiver receiver, boolean loadFonts) throws SAXException {
        NodeList nodeList = fontFamiliesNode.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                if (NODE_fontFamily.equals(node.getNodeName())) {
                    try {
                        SimpleFontFamily fontFamily = parseFontFamily(jasperReportsContext, node, loadFonts);
                        receiver.acceptFontFamily(fontFamily);
                    } catch (InvalidFontException e)//only catching the specific InvalidFontException for now
                    {
                        log.error("Error loading font family", e);
                        //discarding the whole family
                    }
                } else if (NODE_fontSet.equals(node.getNodeName())) {
                    SimpleFontSet fontSet = parseFontSet(node);
                    receiver.acceptFontSet(fontSet);
                }
            }
        }
    }

    /**
     *
     */
    @SuppressWarnings("deprecation")
    private SimpleFontFamily parseFontFamily(JasperReportsContext jasperReportsContext, Node fontFamilyNode,
            boolean loadFonts) throws SAXException {
        SimpleFontFamily fontFamily = new SimpleFontFamily(jasperReportsContext);

        NamedNodeMap nodeAttrs = fontFamilyNode.getAttributes();

        if (nodeAttrs.getNamedItem(ATTRIBUTE_name) != null) {
            fontFamily.setName(nodeAttrs.getNamedItem(ATTRIBUTE_name).getNodeValue());
            if (log.isDebugEnabled()) {
                log.debug("Parsing font family " + fontFamily.getName());
            }
        }
        if (nodeAttrs.getNamedItem(ATTRIBUTE_visible) != null) {
            fontFamily.setVisible(Boolean.valueOf(nodeAttrs.getNamedItem(ATTRIBUTE_visible).getNodeValue()));
        }

        NodeList nodeList = fontFamilyNode.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                if (NODE_normal.equals(node.getNodeName())) {
                    fontFamily.setNormalFace(parseFontFace(jasperReportsContext, node, loadFonts));
                } else if (NODE_bold.equals(node.getNodeName())) {
                    fontFamily.setBoldFace(parseFontFace(jasperReportsContext, node, loadFonts));
                } else if (NODE_italic.equals(node.getNodeName())) {
                    fontFamily.setItalicFace(parseFontFace(jasperReportsContext, node, loadFonts));
                } else if (NODE_boldItalic.equals(node.getNodeName())) {
                    fontFamily.setBoldItalicFace(parseFontFace(jasperReportsContext, node, loadFonts));
                } else if (NODE_normalPdfFont.equals(node.getNodeName())) {
                    fontFamily.setNormalPdfFont(node.getTextContent());
                } else if (NODE_boldPdfFont.equals(node.getNodeName())) {
                    fontFamily.setBoldPdfFont(node.getTextContent());
                } else if (NODE_italicPdfFont.equals(node.getNodeName())) {
                    fontFamily.setItalicPdfFont(node.getTextContent());
                } else if (NODE_boldItalicPdfFont.equals(node.getNodeName())) {
                    fontFamily.setBoldItalicPdfFont(node.getTextContent());
                } else if (NODE_pdfEncoding.equals(node.getNodeName())) {
                    fontFamily.setPdfEncoding(node.getTextContent());
                } else if (NODE_pdfEmbedded.equals(node.getNodeName())) {
                    fontFamily.setPdfEmbedded(Boolean.valueOf(node.getTextContent()));
                } else if (NODE_exportFonts.equals(node.getNodeName())) {
                    fontFamily.setExportFonts(parseExportFonts(node));
                } else if (NODE_locales.equals(node.getNodeName())) {
                    fontFamily.setLocales(parseLocales(node));
                }
            }
        }

        return fontFamily;
    }

    /**
     *
     */
    private SimpleFontFace parseFontFace(JasperReportsContext jasperReportsContext, Node fontFaceNode,
            boolean loadFonts) throws SAXException {
        SimpleFontFace fontFace = new SimpleFontFace(jasperReportsContext);

        NodeList nodeList = fontFaceNode.getChildNodes();

        if (nodeList.getLength() == 1 && (fontFaceNode.getFirstChild().getNodeType() == Node.TEXT_NODE
                || fontFaceNode.getFirstChild().getNodeType() == Node.CDATA_SECTION_NODE)) {
            fontFace.setTtf(fontFaceNode.getFirstChild().getTextContent(), loadFonts);
        } else {
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    if (NODE_ttf.equals(node.getNodeName())) {
                        fontFace.setTtf(node.getTextContent(), loadFonts);
                    } else if (NODE_pdf.equals(node.getNodeName())) {
                        fontFace.setPdf(node.getTextContent());
                    } else if (NODE_eot.equals(node.getNodeName())) {
                        fontFace.setEot(node.getTextContent());
                    } else if (NODE_svg.equals(node.getNodeName())) {
                        fontFace.setSvg(node.getTextContent());
                    } else if (NODE_woff.equals(node.getNodeName())) {
                        fontFace.setWoff(node.getTextContent());
                    }
                }
            }
        }

        return fontFace;
    }

    /**
     *
     */
    private Map<String, String> parseExportFonts(Node exportFontsNode) {
        Map<String, String> exportFonts = new HashMap<String, String>();

        NodeList nodeList = exportFontsNode.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE && NODE_export.equals(node.getNodeName())) {
                NamedNodeMap nodeAttrs = node.getAttributes();

                if (nodeAttrs.getNamedItem(ATTRIBUTE_key) != null) {
                    exportFonts.put(nodeAttrs.getNamedItem(ATTRIBUTE_key).getNodeValue(), node.getTextContent());
                }
            }
        }

        return exportFonts;
    }

    private SimpleFontSet parseFontSet(Node fontSetNode) {
        SimpleFontSet fontSet = new SimpleFontSet();

        NamedNodeMap nodeAttrs = fontSetNode.getAttributes();
        if (nodeAttrs.getNamedItem(ATTRIBUTE_name) != null) {
            fontSet.setName(nodeAttrs.getNamedItem(ATTRIBUTE_name).getNodeValue());
        }

        NodeList nodeList = fontSetNode.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                if (NODE_family.equals(node.getNodeName())) {
                    SimpleFontSetFamily family = parsetFontSetFamily(node);
                    fontSet.addFamily(family);
                } else if (NODE_exportFonts.equals(node.getNodeName())) {
                    fontSet.setExportFonts(parseExportFonts(node));
                }
            }
        }

        return fontSet;
    }

    private SimpleFontSetFamily parsetFontSetFamily(Node familyNode) {
        SimpleFontSetFamily family = new SimpleFontSetFamily();

        NamedNodeMap nodeAttrs = familyNode.getAttributes();
        if (nodeAttrs.getNamedItem(ATTRIBUTE_familyName) != null) {
            family.setFamilyName(nodeAttrs.getNamedItem(ATTRIBUTE_familyName).getNodeValue());
        }
        if (nodeAttrs.getNamedItem(ATTRIBUTE_primary) != null) {
            family.setPrimary(Boolean.parseBoolean(nodeAttrs.getNamedItem(ATTRIBUTE_primary).getNodeValue()));
        }

        NodeList nodeList = familyNode.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                if (NODE_includedScript.equals(node.getNodeName())) {
                    family.addIncludedScript(node.getTextContent());
                } else if (NODE_excludedScript.equals(node.getNodeName())) {
                    family.addExcludedScript(node.getTextContent());
                }
            }
        }

        return family;
    }

    /**
     *
     */
    public static String getFontsXml(List<FontFamily> fontFamilies) {
        if (fontFamilies != null) {
            FontExtensionsContainer extensions = new SimpleFontExtensionsContainer(fontFamilies, null);
            StringBuilder sb = new StringBuilder();
            StringBuilderWriter writer = new StringBuilderWriter(sb);
            try {
                writeFontExtensions(writer, extensions);
            } catch (IOException e) {
                //should not happen
                throw new JRRuntimeException(e);
            }
            return sb.toString();
        } else {
            log.error("There are no font families in the list.");
            return null;
        }
    }

    protected static void writeFontExtensions(Writer out, FontExtensionsContainer extensions) throws IOException {
        JRXmlWriteHelper writer = new JRXmlWriteHelper(out);
        writer.writeProlog(DEFAULT_ENCODING);

        writer.startElement("fontFamilies");

        List<? extends FontFamily> fontFamilies = extensions.getFontFamilies();
        if (fontFamilies != null) {
            for (FontFamily fontFamily : fontFamilies) {
                writeFontFamily(writer, fontFamily);
            }
        }

        List<? extends FontSet> fontSets = extensions.getFontSets();
        if (fontSets != null) {
            for (FontSet fontSet : fontSets) {
                writeFontSet(writer, fontSet);
            }
        }

        writer.closeElement();
    }

    /**
     * @throws IOException 
     *
     */
    private static void writeFontFamily(JRXmlWriteHelper writer, FontFamily fontFamily) throws IOException {
        if (fontFamily != null) {
            if (fontFamily.getName() == null) {
                log.error("Font family name is required.");
                return;
            }

            writer.startElement(NODE_fontFamily);
            writer.addAttribute(ATTRIBUTE_name, fontFamily.getName());
            writer.addAttribute(ATTRIBUTE_visible, fontFamily.isVisible(), true);

            writeFontFace(writer, fontFamily.getNormalFace(), NODE_normal);
            writeFontFace(writer, fontFamily.getBoldFace(), NODE_bold);
            writeFontFace(writer, fontFamily.getItalicFace(), NODE_italic);
            writeFontFace(writer, fontFamily.getBoldItalicFace(), NODE_boldItalic);

            if (fontFamily.getPdfEncoding() != null) {
                writer.writeCDATAElement(NODE_pdfEncoding, fontFamily.getPdfEncoding());

            }
            if (fontFamily.isPdfEmbedded() != null) {
                //TODO lucianc we can do without CDATA here
                writer.writeCDATAElement(NODE_pdfEmbedded, Boolean.toString(fontFamily.isPdfEmbedded()));
            }

            if (fontFamily instanceof SimpleFontFamily) {
                SimpleFontFamily simpleFontFamily = (SimpleFontFamily) fontFamily;

                Map<String, String> exportFonts = simpleFontFamily.getExportFonts();
                writeExportFonts(writer, exportFonts);

                Set<String> locales = simpleFontFamily.getLocales();

                if (locales != null) {
                    writer.startElement(NODE_locales);
                    for (String locale : locales) {
                        writer.writeCDATAElement(NODE_locale, locale);
                    }
                    writer.closeElement();
                }
            }
            writer.closeElement();
        } else {
            log.info("Null font family encountered.");
        }
    }

    protected static void writeExportFonts(JRXmlWriteHelper writer, Map<String, String> exportFonts)
            throws IOException {
        if (exportFonts != null) {
            writer.startElement(NODE_exportFonts);
            for (String key : exportFonts.keySet()) {
                writer.writeCDATAElement(NODE_export, exportFonts.get(key), ATTRIBUTE_key, key);
            }
            writer.closeElement();
        }
    }

    /**
     * @throws IOException 
     *
     */
    private static void writeFontFace(JRXmlWriteHelper writer, FontFace fontFace, String faceTypeName)
            throws IOException {
        if (fontFace != null) {
            if (fontFace.getPdf() == null && fontFace.getEot() == null && fontFace.getSvg() == null
                    && fontFace.getWoff() == null) {
                if (fontFace.getTtf() != null) {
                    writer.writeCDATAElement(faceTypeName, fontFace.getTtf());
                }
            } else {
                writer.startElement(faceTypeName);
                if (fontFace.getTtf() != null) {
                    writer.writeCDATAElement("ttf", fontFace.getTtf());
                }
                if (fontFace.getPdf() != null) {
                    writer.writeCDATAElement("pdf", fontFace.getPdf());
                }
                if (fontFace.getEot() != null) {
                    writer.writeCDATAElement("eot", fontFace.getEot());
                }
                if (fontFace.getSvg() != null) {
                    writer.writeCDATAElement("svg", fontFace.getSvg());
                }
                if (fontFace.getWoff() != null) {
                    writer.writeCDATAElement("woff", fontFace.getWoff());
                }
                writer.closeElement();
            }
        }
    }

    private static void writeFontSet(JRXmlWriteHelper writer, FontSet fontSet) throws IOException {
        if (fontSet == null) {
            log.info("Null font set encountered.");
            return;
        }

        if (fontSet.getName() == null) {
            log.error("Font set name is required.");
            return;
        }

        writer.startElement(NODE_fontSet);
        writer.addAttribute(ATTRIBUTE_name, fontSet.getName());

        if (fontSet instanceof SimpleFontSet) {
            Map<String, String> exportFonts = ((SimpleFontSet) fontSet).getExportFonts();
            writeExportFonts(writer, exportFonts);
        }

        List<FontSetFamily> families = fontSet.getFamilies();
        if (families != null) {
            for (FontSetFamily family : families) {
                writeFontSetFamily(writer, family);
            }
        }

        writer.closeElement();
    }

    private static void writeFontSetFamily(JRXmlWriteHelper writer, FontSetFamily family) throws IOException {
        if (family == null) {
            log.info("Null font set family encountered.");
            return;
        }

        if (family.getFamilyName() == null) {
            log.error("Font set name is required.");
            return;
        }

        writer.startElement(NODE_family);
        writer.addAttribute(ATTRIBUTE_familyName, family.getFamilyName());
        writer.addAttribute(ATTRIBUTE_primary, family.isPrimary(), false);

        List<String> includedScripts = family.getIncludedScripts();
        if (includedScripts != null) {
            for (String script : includedScripts) {
                writer.writeCDATAElement(NODE_includedScript, script);
            }
        }

        List<String> excludedScripts = family.getExcludedScripts();
        if (excludedScripts != null) {
            for (String script : excludedScripts) {
                writer.writeCDATAElement(NODE_excludedScript, script);
            }
        }

        writer.closeElement();
    }

    /**
     *
     */
    public static void writeFontsXml(String destFileName, List<FontFamily> fontFamilies) throws JRException {
        FontExtensionsContainer extensions = new SimpleFontExtensionsContainer(fontFamilies, null);
        writeFontExtensionsXml(destFileName, extensions);
    }

    public static void writeFontExtensionsXml(String destFileName, FontExtensionsContainer extensions)
            throws JRException {
        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(destFileName);
            writeFontExtensionsXml(fos, extensions);
        } catch (IOException e) {
            throw new JRException(EXCEPTION_MESSAGE_KEY_FILE_WRITER_ERROR, new Object[] { destFileName }, e);
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     *
     */
    public static void writeFontsXml(OutputStream outputStream, List<FontFamily> fontFamilies) throws JRException {
        FontExtensionsContainer extensions = new SimpleFontExtensionsContainer(fontFamilies, null);
        writeFontExtensionsXml(outputStream, extensions);
    }

    public static void writeFontExtensionsXml(OutputStream outputStream, FontExtensionsContainer extensions)
            throws JRException {
        Writer out = null;
        try {
            out = new OutputStreamWriter(outputStream, DEFAULT_ENCODING);
            writeFontExtensions(out, extensions);
            out.flush();
        } catch (Exception e) {
            throw new JRException(EXCEPTION_MESSAGE_KEY_OUTPUT_STREAM_WRITER_ERROR, null, e);
        }
    }

    /**
     *
     */
    public static void writeFontExtensionsProperties(String fontsXmlLocation, String destFileName)
            throws JRException {
        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(destFileName, false);
            writeFontExtensionsProperties(fontsXmlLocation, fos);
        } catch (IOException e) {
            throw new JRException(EXCEPTION_MESSAGE_KEY_FILE_WRITER_ERROR, new Object[] { destFileName }, e);
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     *
     */
    public static void writeFontExtensionsProperties(String fontFamiliesPropertyValue, OutputStream outputStream)
            throws JRException {
        writeFontExtensionsProperties(
                SimpleFontExtensionsRegistryFactory.PROPERTY_SIMPLE_FONT_FAMILIES_REGISTRY_FACTORY,
                SimpleFontExtensionsRegistryFactory.class.getName(),
                SimpleFontExtensionsRegistryFactory.SIMPLE_FONT_FAMILIES_PROPERTY_PREFIX + "location",
                fontFamiliesPropertyValue, outputStream);
    }

    /**
     *
     */
    public static void writeFontExtensionsProperties(String fontRegistryFactoryPropertyName,
            String fontRegistryFactoryPropertyValue, String fontFamiliesPropertyName,
            String fontFamiliesPropertyValue, OutputStream outputStream) throws JRException {
        Writer out = null;
        try {
            out = new OutputStreamWriter(outputStream, DEFAULT_ENCODING);
            out.write(fontRegistryFactoryPropertyName + "=" + fontRegistryFactoryPropertyValue + "\n");
            out.write(fontFamiliesPropertyName + "=" + fontFamiliesPropertyValue + "\n");
            out.flush();
        } catch (Exception e) {
            throw new JRException(EXCEPTION_MESSAGE_KEY_OUTPUT_STREAM_WRITER_ERROR, null, e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     *
     */
    private Set<String> parseLocales(Node localesNode) throws SAXException {
        Set<String> locales = new HashSet<String>();

        NodeList nodeList = localesNode.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE && NODE_locale.equals(node.getNodeName())) {
                locales.add(node.getTextContent());
            }
        }

        return locales;
    }

    @Override
    public void error(SAXParseException e) {
        if (log.isErrorEnabled()) {
            log.error("Error parsing styled text.", e);
        }
    }

    @Override
    public void fatalError(SAXParseException e) {
        if (log.isFatalEnabled()) {
            log.fatal("Error parsing styled text.", e);
        }
    }

    @Override
    public void warning(SAXParseException e) {
        if (log.isWarnEnabled()) {
            log.warn("Error parsing styled text.", e);
        }
    }

}