001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020:
021: package com.ecyrd.jspwiki.diff;
022:
023: import java.io.BufferedReader;
024: import java.io.File;
025: import java.io.IOException;
026: import java.io.StringReader;
027: import java.util.Properties;
028:
029: import org.apache.log4j.Logger;
030:
031: import com.ecyrd.jspwiki.*;
032:
033: /**
034: * This DiffProvider allows external command line tools to be used to generate
035: * the diff.
036: */
037: public class ExternalDiffProvider implements DiffProvider {
038: private static final Logger log = Logger
039: .getLogger(ExternalDiffProvider.class);
040:
041: /**
042: * Determines the command to be used for 'diff'. This program must be able
043: * to output diffs in the unified format. For example 'diff -u %s1 %s2'.
044: */
045: public static final String PROP_DIFFCOMMAND = "jspwiki.diffCommand";
046:
047: private String m_diffCommand = null;
048: private String m_encoding;
049:
050: private static final char DIFF_ADDED_SYMBOL = '+';
051: private static final char DIFF_REMOVED_SYMBOL = '-';
052:
053: private static final String CSS_DIFF_ADDED = "<tr><td bgcolor=\"#99FF99\" class=\"diffadd\">";
054: private static final String CSS_DIFF_REMOVED = "<tr><td bgcolor=\"#FF9933\" class=\"diffrem\">";
055: private static final String CSS_DIFF_UNCHANGED = "<tr><td class=\"diff\">";
056: private static final String CSS_DIFF_CLOSE = "</td></tr>";
057:
058: //FIXME This could/should be a property for this provider, there is not guarentee that
059: //the external program generates a format suitible for the colorization code of the
060: //TraditionalDiffProvider, currently set to true for legacy compatibility.
061: //I don't think this 'feature' ever worked right, did it?...
062: private boolean m_traditionalColorization = true;
063:
064: /**
065: * Creates a new ExternalDiffProvider.
066: */
067: public ExternalDiffProvider() {
068: }
069:
070: /**
071: * @see com.ecyrd.jspwiki.WikiProvider#getProviderInfo()
072: * {@inheritDoc}
073: */
074: public String getProviderInfo() {
075: return "ExternalDiffProvider";
076: }
077:
078: /**
079: * {@inheritDoc}
080: * @see com.ecyrd.jspwiki.WikiProvider#initialize(com.ecyrd.jspwiki.WikiEngine, java.util.Properties)
081: */
082: public void initialize(WikiEngine engine, Properties properties)
083: throws NoRequiredPropertyException, IOException {
084: m_diffCommand = properties.getProperty(PROP_DIFFCOMMAND);
085:
086: if ((null == m_diffCommand)
087: || (m_diffCommand.trim().equals(""))) {
088: throw new NoRequiredPropertyException(
089: "ExternalDiffProvider missing required property",
090: PROP_DIFFCOMMAND);
091: }
092:
093: m_encoding = engine.getContentEncoding();
094: }
095:
096: /**
097: * Makes the diff by calling "diff" program.
098: * {@inheritDoc}
099: */
100: public String makeDiffHtml(WikiContext ctx, String p1, String p2) {
101: File f1 = null;
102: File f2 = null;
103: String diff = null;
104:
105: try {
106: f1 = FileUtil.newTmpFile(p1, m_encoding);
107: f2 = FileUtil.newTmpFile(p2, m_encoding);
108:
109: String cmd = TextUtil.replaceString(m_diffCommand, "%s1",
110: f1.getPath());
111: cmd = TextUtil.replaceString(cmd, "%s2", f2.getPath());
112:
113: String output = FileUtil.runSimpleCommand(cmd, f1
114: .getParent());
115:
116: // FIXME: Should this rely on the system default encoding?
117: String rawWikiDiff = new String(output
118: .getBytes("ISO-8859-1"), m_encoding);
119:
120: String htmlWikiDiff = TextUtil.replaceEntities(rawWikiDiff);
121:
122: if (m_traditionalColorization) //FIXME, see comment near declaration...
123: diff = colorizeDiff(diff);
124: else
125: diff = htmlWikiDiff;
126:
127: } catch (IOException e) {
128: log.error("Failed to do file diff", e);
129: } catch (InterruptedException e) {
130: log.error("Interrupted", e);
131: } finally {
132: if (f1 != null)
133: f1.delete();
134: if (f2 != null)
135: f2.delete();
136: }
137:
138: return diff;
139: }
140:
141: /**
142: * Goes through output provided by a diff command and inserts HTML tags to
143: * make the result more legible. Currently colors lines starting with a +
144: * green, those starting with - reddish (hm, got to think of color blindness
145: * here...).
146: */
147: static String colorizeDiff(String diffText) throws IOException {
148: if (diffText == null)
149: return "Invalid diff - probably something wrong with server setup.";
150:
151: String line = null;
152: String start = null;
153: String stop = null;
154:
155: BufferedReader in = new BufferedReader(new StringReader(
156: diffText));
157: StringBuffer out = new StringBuffer();
158:
159: out
160: .append("<table class=\"diff\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n");
161: while ((line = in.readLine()) != null) {
162: stop = CSS_DIFF_CLOSE;
163:
164: if (line.length() > 0) {
165: switch (line.charAt(0)) {
166: case DIFF_ADDED_SYMBOL:
167: start = CSS_DIFF_ADDED;
168: break;
169: case DIFF_REMOVED_SYMBOL:
170: start = CSS_DIFF_REMOVED;
171: break;
172: default:
173: start = CSS_DIFF_UNCHANGED;
174: }
175: } else {
176: start = CSS_DIFF_UNCHANGED;
177: }
178:
179: out.append(start);
180: out.append(line.trim());
181: out.append(stop + "\n");
182: }
183:
184: out.append("</table>\n");
185: return out.toString();
186: }
187: }
|