1 /* 2 * Copyright 2011-2013 smartics, Kronseder & Reiner GmbH 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package de.smartics.checkstyle.checks.strings; 17 18 import java.nio.ByteBuffer; 19 import java.nio.CharBuffer; 20 import java.nio.charset.CharacterCodingException; 21 import java.nio.charset.Charset; 22 import java.nio.charset.CharsetDecoder; 23 24 import com.puppycrawl.tools.checkstyle.api.Check; 25 import com.puppycrawl.tools.checkstyle.api.DetailAST; 26 import com.puppycrawl.tools.checkstyle.api.TokenTypes; 27 28 /** 29 * Check to detect usage of characters of disallowed encoding in String 30 * and character literals. 31 */ 32 public class StringLiteralEncodingCheck extends Check 33 { 34 // ********************************* Fields ********************************* 35 36 // --- constants ------------------------------------------------------------ 37 38 // --- members -------------------------------------------------------------- 39 40 /** 41 * The allowed encoding within String and character literals. 42 */ 43 private String encoding; 44 45 /** 46 * The decoder dependent on the {@link #encoding}. 47 */ 48 private CharsetDecoder decoder; 49 50 // ****************************** Initializer ******************************* 51 52 // ****************************** Constructors ****************************** 53 54 /** 55 * Default constructor. 56 */ 57 public StringLiteralEncodingCheck() 58 { 59 this.encoding = "US-ASCII"; 60 this.decoder = createDecoder(encoding); 61 } 62 63 // ****************************** Inner Classes ***************************** 64 65 // ********************************* Methods ******************************** 66 67 // --- init ----------------------------------------------------------------- 68 69 private static CharsetDecoder createDecoder(final String encoding) 70 { 71 return Charset.forName(encoding).newDecoder(); 72 } 73 74 // --- get&set -------------------------------------------------------------- 75 76 /** 77 * Sets the allowed encoding within String literals. 78 * 79 * @param encoding the allowed encoding within String literals. 80 */ 81 public void setEncoding(final String encoding) 82 { 83 this.encoding = encoding; 84 this.decoder = createDecoder(encoding); 85 } 86 87 // --- business ------------------------------------------------------------- 88 89 /** 90 * {@inheritDoc} 91 * 92 * @see com.puppycrawl.tools.checkstyle.api.Check#getDefaultTokens() 93 */ 94 @Override 95 public int[] getDefaultTokens() 96 { 97 return new int[] 98 { TokenTypes.STRING_LITERAL, TokenTypes.CHAR_LITERAL }; 99 } 100 101 /** 102 * {@inheritDoc} 103 * 104 * @see com.puppycrawl.tools.checkstyle.api.Check#visitToken(com.puppycrawl.tools.checkstyle.api.DetailAST) 105 */ 106 @Override 107 public void visitToken(final DetailAST ast) 108 { 109 final String literal = ast.getText(); 110 if (!isProperlyEncoded(literal)) 111 { 112 log(ast.getLineNo(), "not_supported_encoding", literal, encoding); 113 } 114 } 115 116 /** 117 * Inspired by <a href= 118 * "http://stackoverflow.com/questions/3585053/in-java-is-it-possible-to-check-if-a-string-is-only-ascii" 119 * >In Java, is it possible to check if a String is only ASCII?</a>. 120 */ 121 private boolean isProperlyEncoded(final String string) 122 { 123 final byte[] stringBytes = string.getBytes(); 124 125 try 126 { 127 final CharBuffer buffer = decoder.decode(ByteBuffer.wrap(stringBytes)); 128 buffer.toString(); 129 } 130 catch (final CharacterCodingException e) 131 { 132 return false; 133 } 134 135 return true; 136 } 137 138 // --- object basics -------------------------------------------------------- 139 140 /** 141 * Returns the string representation of the class for debugging. 142 * 143 * @return the string representation of the class for debugging. 144 */ 145 @Override 146 public String toString() 147 { 148 return "StringLiteralEncodingCheck with encoding '" + encoding + "'."; 149 150 } 151 }