/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library 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 2.1 of the License, or (at your option)
* any later version.
*
* This library 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.
*/
package com.liferay.portal.diff;
import com.liferay.portal.kernel.diff.DiffHtml;
import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
import com.liferay.portal.kernel.security.pacl.DoPrivileged;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import java.io.Reader;
import java.util.Locale;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.outerj.daisy.diff.HtmlCleaner;
import org.outerj.daisy.diff.XslFilter;
import org.outerj.daisy.diff.html.HTMLDiffer;
import org.outerj.daisy.diff.html.HtmlSaxDiffOutput;
import org.outerj.daisy.diff.html.TextNodeComparator;
import org.outerj.daisy.diff.html.dom.DomTreeBuilder;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.AttributesImpl;
/**
* This class can compare two different versions of HTML code. It detects
* changes to an entire HTML page such as removal or addition of characters or
* images.
*
* @author Julio Camarero
*/
@DoPrivileged
public class DiffHtmlImpl implements DiffHtml {
/**
* This is a diff method with default values.
*
* @param source the source text
* @param target the modified version of the source text
* @return a string containing the HTML code of the source text showing the
* differences with the target text
* @throws Exception if an exception occurred
*/
@Override
public String diff(Reader source, Reader target) throws Exception {
if (source == null) {
throw new NullPointerException("Source is null");
}
if (target == null) {
throw new NullPointerException("Target is null");
}
InputSource oldSource = new InputSource(source);
InputSource newSource = new InputSource(target);
UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
Thread currentThread = Thread.currentThread();
ClassLoader contextClassLoader = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(
DiffHtmlImpl.class.getClassLoader());
try {
SAXTransformerFactory saxTransformerFactory =
(SAXTransformerFactory)TransformerFactory.newInstance();
TransformerHandler tranformHandler =
saxTransformerFactory.newTransformerHandler();
tranformHandler.setResult(new StreamResult(unsyncStringWriter));
XslFilter xslFilter = new XslFilter();
ContentHandler contentHandler = xslFilter.xsl(
tranformHandler,
"com/liferay/portal/util/dependencies/diff_html.xsl");
HtmlCleaner htmlCleaner = new HtmlCleaner();
DomTreeBuilder oldDomTreeBuilder = new DomTreeBuilder();
htmlCleaner.cleanAndParse(oldSource, oldDomTreeBuilder);
Locale locale = LocaleUtil.getDefault();
TextNodeComparator leftTextNodeComparator = new TextNodeComparator(
oldDomTreeBuilder, locale);
DomTreeBuilder newDomTreeBuilder = new DomTreeBuilder();
htmlCleaner.cleanAndParse(newSource, newDomTreeBuilder);
TextNodeComparator rightTextNodeComparator = new TextNodeComparator(
newDomTreeBuilder, locale);
contentHandler.startDocument();
contentHandler.startElement(
StringPool.BLANK, _DIFF_REPORT, _DIFF_REPORT,
new AttributesImpl());
contentHandler.startElement(
StringPool.BLANK, _DIFF, _DIFF, new AttributesImpl());
HtmlSaxDiffOutput htmlSaxDiffOutput = new HtmlSaxDiffOutput(
contentHandler, _DIFF);
HTMLDiffer htmlDiffer = new HTMLDiffer(htmlSaxDiffOutput);
htmlDiffer.diff(leftTextNodeComparator, rightTextNodeComparator);
contentHandler.endElement(StringPool.BLANK, _DIFF, _DIFF);
contentHandler.endElement(
StringPool.BLANK, _DIFF_REPORT, _DIFF_REPORT);
contentHandler.endDocument();
unsyncStringWriter.flush();
String string = unsyncStringWriter.toString();
if (string.startsWith("<?xml")) {
int index = string.indexOf("?>");
string = string.substring(index + 2);
}
return string;
}
finally {
currentThread.setContextClassLoader(contextClassLoader);
}
}
@Override
public String replaceStyles(String html) {
return StringUtil.replace(
html,
new String[] {
"changeType=\"diff-added-image\"",
"changeType=\"diff-changed-image\"",
"changeType=\"diff-removed-image\"",
"class=\"diff-html-added\"", "class=\"diff-html-changed\"",
"class=\"diff-html-removed\""
},
new String[] {
"style=\"border: 10px solid #CFC;\"",
"style=\"border: 10px solid blue;\"",
"style=\"border: 10px solid #FDC6C6;\"",
"style=\"background-color: #CFC;\"",
"style=\"border-bottom: 2px dotted blue;\"",
"style=\"background-color: #FDC6C6; text-decoration: " +
"line-through;\""
});
}
private static final String _DIFF = "diff";
private static final String _DIFF_REPORT = "diffreport";
}