001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2026 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018/////////////////////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.site; 021 022import java.io.PrintWriter; 023import java.io.Writer; 024import java.util.regex.Pattern; 025 026import javax.swing.text.MutableAttributeSet; 027 028import org.apache.maven.doxia.module.xdoc.XdocSink; 029import org.apache.maven.doxia.sink.SinkEventAttributes; 030import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet; 031 032/** 033 * A sink for Checkstyle's xdoc templates. 034 * This module will be removed once 035 * <a href="https://github.com/checkstyle/checkstyle/issues/13426">#13426</a> is resolved. 036 * 037 * @see <a href="https://maven.apache.org/doxia/doxia/doxia-sink-api">Doxia Sink API</a> 038 */ 039public class XdocsTemplateSink extends XdocSink { 040 041 /** Encoding of the writer. */ 042 private final String encoding; 043 044 /** 045 * Create a new instance, initialize the Writer. 046 * 047 * @param writer not null writer to write the result. 048 * @param encoding encoding of the writer. 049 */ 050 public XdocsTemplateSink(Writer writer, String encoding) { 051 super(new CustomPrintWriter(writer)); 052 this.encoding = encoding; 053 } 054 055 /** 056 * Place the XML declaration at the top of the file. 057 */ 058 @Override 059 public void body() { 060 write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>"); 061 writeEOL(); 062 } 063 064 /** 065 * Place a newline at the end of the file, flush the writer, and reset the sink. 066 */ 067 @Override 068 public void body_() { 069 writeEOL(); 070 flush(); 071 init(); 072 } 073 074 /** 075 * Write an external link. We override this method because the default implementation 076 * adds a {@code class="external-link"} attribute to the link which we don't want. 077 * 078 * @param href the link. 079 */ 080 @Override 081 public void link(String href) { 082 final MutableAttributeSet attributes = new SinkEventAttributeSet(); 083 attributes.addAttribute(SinkEventAttributes.HREF, href); 084 writeStartTag(A, attributes); 085 } 086 087 /** 088 * Write a table row tag. We override this method because the default implementation 089 * adds a {@code align="top"} attribute to the row which we don't want. 090 */ 091 @Override 092 public void tableRow() { 093 writeStartTag(TR); 094 } 095 096 /** 097 * Write a table tag. We override this method because the default implementation 098 * adds different attributes which we don't want. We ignore the parameters 099 * because we don't need them, but the default implementation will take them 100 * into account once this class is removed. 101 * 102 * @param justification ignored 103 * @param grid ignored 104 */ 105 @Override 106 public void tableRows(int[] justification, boolean grid) { 107 writeStartTag(TABLE); 108 } 109 110 /** 111 * A Custom writer that only prints Unix-style newline character. 112 */ 113 private static final class CustomPrintWriter extends PrintWriter { 114 115 /** A Regex pattern to represent all kinds of newline character. */ 116 private static final Pattern LINE_BREAK_ESCAPE = Pattern.compile("\\R"); 117 118 /** Unix-Style newline character. */ 119 private static final String NEWLINE = "\n"; 120 121 /** 122 * Creates a new instance of this custom writer. 123 * 124 * @param writer not null writer to write the result 125 */ 126 private CustomPrintWriter(Writer writer) { 127 super(writer); 128 } 129 130 /** 131 * Enforces Unix-style newline character. 132 */ 133 @Override 134 public void println() { 135 write(NEWLINE, 0, NEWLINE.length()); 136 } 137 138 /** 139 * Unifies all newline characters to Unix-Style Newline character. 140 * 141 * @param line text that is to be written in the output file. 142 * @param offset starting offset value for writing data. 143 * @param length total length of string to be written. 144 */ 145 @Override 146 public void write(String line, int offset, int length) { 147 final String lineBreakReplacedLine = 148 LINE_BREAK_ESCAPE.matcher(line).replaceAll(NEWLINE); 149 super.write(lineBreakReplacedLine, 0, lineBreakReplacedLine.length()); 150 } 151 } 152}