View Javadoc

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 }