/*
* This file is part of the Illarion project.
*
* Copyright © 2015 - Illarion e.V.
*
* Illarion is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Illarion 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 General Public License for more details.
*/
package illarion.common.util;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.*;
import java.nio.charset.Charset;
import java.util.regex.Pattern;
public class CopyrightHeader {
@Nonnull
private static final Pattern LINE_BREAK_PATTERN = Pattern.compile("\n\r|\n|\r");
@Nonnull
private static final Pattern TRIM_LINES_PATTERN = Pattern.compile("[ ]*\n[ ]*");
/**
* The width of a line. The width of the text is limited to this length.
*/
private final int lineWidth;
/**
* The intro text for the comment block. This is written before the actual license header.
*/
@Nullable
private final String commentIntro;
/**
* The outro text for the comment block. This is written after the actual license header.
*/
@Nullable
private final String commentOutro;
/**
* The prefix of a comment line. This is written before the actual comment text.
*/
@Nullable
private final String commentLineStart;
/**
* The suffix of a comment line. This is written at the end of the line.
*/
@Nullable
private final String commentLineEnd;
/**
* The original text, as its read from the template file.
*/
@Nullable
private String licenseTextTemplate;
@Nonnull
private static final Charset TEMPLATE_CHARSET = Charset.forName("UTF-8");
public CopyrightHeader(
int lineWidth,
@Nullable String commentIntro,
@Nullable String commentOutro,
@Nullable String commentLineStart,
@Nullable String commentLineEnd) {
this.lineWidth = lineWidth;
this.commentIntro = commentIntro;
this.commentOutro = commentOutro;
this.commentLineStart = commentLineStart;
this.commentLineEnd = commentLineEnd;
}
@Nonnull
private String getLicenseTextTemplate() throws IOException {
if (licenseTextTemplate != null) {
return licenseTextTemplate;
}
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try (InputStream in = cl.getResourceAsStream("agpl_template.txt")) {
if (in != null) {
StringBuilder resultBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, TEMPLATE_CHARSET))) {
String line;
while ((line = reader.readLine()) != null) {
resultBuilder.append(line.trim());
resultBuilder.append(' ');
}
}
resultBuilder.setLength(resultBuilder.length() - 1);
int index;
while ((index = resultBuilder.indexOf("{NL}")) != -1) {
resultBuilder.replace(index, index + 4, "\n");
}
licenseTextTemplate = TRIM_LINES_PATTERN.matcher(resultBuilder.toString()).replaceAll("\n");
}
return (licenseTextTemplate == null) ? "" : licenseTextTemplate;
}
}
public void writeTo(@Nonnull Writer writer) throws IOException {
BufferedWriter bw = new BufferedWriter(writer);
if (commentIntro != null) {
bw.write(commentIntro);
bw.write('\n');
}
int textWidth = lineWidth;
if (commentLineStart != null) {
textWidth -= commentLineStart.length();
}
if (commentLineEnd != null) {
textWidth -= commentLineEnd.length();
}
String[] lines = getLicenseTextTemplate().split("\n");
for (String line : lines) {
String localLine = line;
while (true) {
if (localLine.length() < textWidth) {
writeLine(bw, localLine, textWidth);
break;
} else {
int lastSpaceIndex = localLine.lastIndexOf(' ', textWidth);
writeLine(bw, localLine.substring(0, lastSpaceIndex), textWidth);
localLine = localLine.substring(lastSpaceIndex + 1);
}
}
}
if (commentOutro != null) {
bw.write(commentOutro);
bw.write('\n');
}
bw.flush();
}
private void writeLine(
@Nonnull Writer writer, @Nonnull String line, int padding) throws IOException {
if (commentLineStart != null) {
writer.write(commentLineStart);
}
writer.write(line);
if (commentLineEnd != null) {
for (int i = line.length(); i < padding; i++) {
writer.write(' ');
}
writer.write(commentLineEnd);
}
writer.write('\n');
}
/**
* Check if the license text meets the specifications set in this class instance.
*
* @param text the license text
* @return {@code true} if the text fits the license text
*/
public boolean isLicenseText(@Nonnull CharSequence text) {
String[] textParts = LINE_BREAK_PATTERN.split(text);
if (textParts.length == 0) {
return false;
}
if ((commentIntro != null) && !textParts[0].equals(commentIntro)) {
return false;
}
if ((commentOutro != null) && !textParts[textParts.length - 1].equals(commentOutro)) {
return false;
}
int textStartIndex = (commentIntro == null) ? 0 : 1;
int textEndIndex = (commentOutro == null) ? textParts.length : (textParts.length - 1);
StringBuilder licenseText = new StringBuilder();
for (int i = textStartIndex; i < textEndIndex; i++) {
String line = textParts[i];
int lineStartIndex = 0;
int lineEndIndex = line.length();
if (commentLineStart != null) {
if (!line.startsWith(commentLineStart.trim())) {
return false;
}
lineStartIndex = commentLineStart.length();
}
if (commentLineEnd != null) {
if (!line.endsWith(commentLineEnd.trim())) {
return false;
}
lineEndIndex = line.length() - commentLineEnd.length();
}
if (lineStartIndex < lineEndIndex) {
licenseText.append(line.substring(lineStartIndex, lineEndIndex).trim());
}
licenseText.append(' ');
}
licenseText.setLength(licenseText.length() - 1);
try {
String licenseTemplate = getLicenseTextTemplate().replace('\n', ' ');
return licenseTemplate.equals(licenseText.toString());
} catch (IOException e) {
return false;
}
}
}