001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.util;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
018    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
019    import com.liferay.portal.kernel.util.DiffHtml;
020    import com.liferay.portal.kernel.util.LocaleUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    
023    import java.io.Reader;
024    
025    import java.util.Locale;
026    
027    import javax.xml.transform.TransformerFactory;
028    import javax.xml.transform.sax.SAXTransformerFactory;
029    import javax.xml.transform.sax.TransformerHandler;
030    import javax.xml.transform.stream.StreamResult;
031    
032    import org.outerj.daisy.diff.HtmlCleaner;
033    import org.outerj.daisy.diff.XslFilter;
034    import org.outerj.daisy.diff.html.HTMLDiffer;
035    import org.outerj.daisy.diff.html.HtmlSaxDiffOutput;
036    import org.outerj.daisy.diff.html.TextNodeComparator;
037    import org.outerj.daisy.diff.html.dom.DomTreeBuilder;
038    
039    import org.xml.sax.ContentHandler;
040    import org.xml.sax.InputSource;
041    import org.xml.sax.helpers.AttributesImpl;
042    
043    /**
044     * This class can compare two different versions of HTML code. It detects
045     * changes to an entire HTML page such as removal or addition of characters or
046     * images.
047     *
048     * @author Julio Camarero
049     */
050    @DoPrivileged
051    public class DiffHtmlImpl implements DiffHtml {
052    
053            /**
054             * This is a diff method with default values.
055             *
056             * @param  source the source text
057             * @param  target the modified version of the source text
058             * @return a string containing the HTML code of the source text showing the
059             *         differences with the target text
060             * @throws Exception if an exception occurred
061             */
062            @Override
063            public String diff(Reader source, Reader target) throws Exception {
064                    InputSource oldSource = new InputSource(source);
065                    InputSource newSource = new InputSource(target);
066    
067                    UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
068    
069                    SAXTransformerFactory saxTransformerFactory =
070                            (SAXTransformerFactory)TransformerFactory.newInstance();
071    
072                    TransformerHandler tranformHandler =
073                            saxTransformerFactory.newTransformerHandler();
074    
075                    tranformHandler.setResult(new StreamResult(unsyncStringWriter));
076    
077                    XslFilter xslFilter = new XslFilter();
078    
079                    ContentHandler contentHandler = xslFilter.xsl(
080                            tranformHandler,
081                            "com/liferay/portal/util/dependencies/diff_html.xsl");
082    
083                    HtmlCleaner htmlCleaner = new HtmlCleaner();
084    
085                    DomTreeBuilder oldDomTreeBuilder = new DomTreeBuilder();
086    
087                    htmlCleaner.cleanAndParse(oldSource, oldDomTreeBuilder);
088    
089                    Locale locale = LocaleUtil.getDefault();
090    
091                    TextNodeComparator leftTextNodeComparator = new TextNodeComparator(
092                            oldDomTreeBuilder, locale);
093    
094                    DomTreeBuilder newDomTreeBuilder = new DomTreeBuilder();
095    
096                    htmlCleaner.cleanAndParse(newSource, newDomTreeBuilder);
097    
098                    TextNodeComparator rightTextNodeComparator = new TextNodeComparator(
099                            newDomTreeBuilder, locale);
100    
101                    contentHandler.startDocument();
102                    contentHandler.startElement(
103                            StringPool.BLANK, _DIFF_REPORT, _DIFF_REPORT, new AttributesImpl());
104                    contentHandler.startElement(
105                            StringPool.BLANK, _DIFF, _DIFF, new AttributesImpl());
106    
107                    HtmlSaxDiffOutput htmlSaxDiffOutput = new HtmlSaxDiffOutput(
108                            contentHandler, _DIFF);
109    
110                    HTMLDiffer htmlDiffer = new HTMLDiffer(htmlSaxDiffOutput);
111    
112                    htmlDiffer.diff(leftTextNodeComparator, rightTextNodeComparator);
113    
114                    contentHandler.endElement(StringPool.BLANK, _DIFF, _DIFF);
115                    contentHandler.endElement(StringPool.BLANK, _DIFF_REPORT, _DIFF_REPORT);
116                    contentHandler.endDocument();
117    
118                    unsyncStringWriter.flush();
119    
120                    String string = unsyncStringWriter.toString();
121    
122                    if (string.startsWith("<?xml")) {
123                            int index = string.indexOf("?>");
124    
125                            string = string.substring(index + 2);
126                    }
127    
128                    return string;
129            }
130    
131            private static final String _DIFF = "diff";
132    
133            private static final String _DIFF_REPORT = "diffreport";
134    
135    }