/*
|
* Copyright 2013 gitblit.com.
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
package com.gitblit.utils;
|
|
import java.io.IOException;
|
import java.text.MessageFormat;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Map.Entry;
|
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
import org.eclipse.jgit.lib.Repository;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import com.gitblit.IStoredSettings;
|
import com.gitblit.Keys;
|
import com.gitblit.models.RepositoryModel;
|
import com.syntevo.bugtraq.BugtraqConfig;
|
import com.syntevo.bugtraq.BugtraqFormatter;
|
import com.syntevo.bugtraq.BugtraqFormatter.OutputHandler;
|
|
public class BugtraqProcessor {
|
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
|
private final IStoredSettings settings;
|
|
public BugtraqProcessor(IStoredSettings settings) {
|
this.settings = settings;
|
}
|
|
/**
|
* Returns an html version of the commit message with any global or
|
* repository-specific regular expression substitution applied.
|
*
|
* This method uses the preferred renderer to transform the commit message.
|
*
|
* @param repository
|
* @param model
|
* @param text
|
* @return html version of the commit message
|
*/
|
public String processCommitMessage(Repository repository, RepositoryModel model, String text) {
|
switch (model.commitMessageRenderer) {
|
case MARKDOWN:
|
try {
|
String prepared = processTextRegex(repository, model.name, text);
|
return MarkdownUtils.transformMarkdown(prepared);
|
} catch (Exception e) {
|
logger.error("Failed to render commit message as markdown", e);
|
}
|
break;
|
default:
|
// noop
|
break;
|
}
|
|
return processPlainCommitMessage(repository, model.name, text);
|
}
|
|
/**
|
* Returns an html version of the commit message with any global or
|
* repository-specific regular expression substitution applied.
|
*
|
* This method assumes the commit message is plain text.
|
*
|
* @param repository
|
* @param repositoryName
|
* @param text
|
* @return html version of the commit message
|
*/
|
public String processPlainCommitMessage(Repository repository, String repositoryName, String text) {
|
String html = StringUtils.escapeForHtml(text, false);
|
html = processTextRegex(repository, repositoryName, html);
|
return StringUtils.breakLinesForHtml(html);
|
|
}
|
|
/**
|
* Returns an processed version of the text with any global or
|
* repository-specific regular expression substitution applied.
|
*
|
* @param repository
|
* @param repositoryName
|
* @param text
|
* @return processed version of the text
|
*/
|
public String processText(Repository repository, String repositoryName, String text) {
|
String html = processTextRegex(repository, repositoryName, text);
|
return html;
|
}
|
|
/**
|
* Apply globally or per-repository specified regex substitutions to the
|
* text.
|
*
|
* @param repository
|
* @param repositoryName
|
* @param text
|
* @return the processed text
|
*/
|
protected String processTextRegex(Repository repository, String repositoryName, String text) {
|
Map<String, String> map = new HashMap<String, String>();
|
// global regex keys
|
if (settings.getBoolean(Keys.regex.global, false)) {
|
for (String key : settings.getAllKeys(Keys.regex.global)) {
|
if (!key.equals(Keys.regex.global)) {
|
String subKey = key.substring(key.lastIndexOf('.') + 1);
|
map.put(subKey, settings.getString(key, ""));
|
}
|
}
|
}
|
|
// repository-specific regex keys
|
List<String> keys = settings.getAllKeys(Keys.regex._ROOT + "."
|
+ repositoryName.toLowerCase());
|
for (String key : keys) {
|
String subKey = key.substring(key.lastIndexOf('.') + 1);
|
map.put(subKey, settings.getString(key, ""));
|
}
|
|
for (Entry<String, String> entry : map.entrySet()) {
|
String definition = entry.getValue().trim();
|
String[] chunks = definition.split("!!!");
|
if (chunks.length == 2) {
|
text = text.replaceAll(chunks[0], chunks[1]);
|
} else {
|
logger.warn(entry.getKey()
|
+ " improperly formatted. Use !!! to separate match from replacement: "
|
+ definition);
|
}
|
}
|
|
try {
|
// parse bugtraq repo config
|
BugtraqConfig config = BugtraqConfig.read(repository);
|
if (config != null) {
|
BugtraqFormatter formatter = new BugtraqFormatter(config);
|
StringBuilder sb = new StringBuilder();
|
formatter.formatLogMessage(text, new BugtraqOutputHandler(sb));
|
text = sb.toString();
|
}
|
} catch (IOException e) {
|
logger.error(MessageFormat.format("Bugtraq config for {0} is invalid!", repositoryName), e);
|
} catch (ConfigInvalidException e) {
|
logger.error(MessageFormat.format("Bugtraq config for {0} is invalid!", repositoryName), e);
|
}
|
|
return text;
|
}
|
|
private class BugtraqOutputHandler implements OutputHandler {
|
|
final StringBuilder sb;
|
|
BugtraqOutputHandler(StringBuilder sb) {
|
this.sb = sb;
|
}
|
|
@Override
|
public void appendText(String text) {
|
sb.append(text);
|
}
|
|
@Override
|
public void appendLink(String name, String target) {
|
sb.append(MessageFormat.format("<a class=\"bugtraq\" href=\"{1}\" target=\"_blank\">{0}</a>", name, target));
|
}
|
}
|
}
|