1 11 package org.eclipse.jdt.internal.compiler.apt.util; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.nio.ByteBuffer ; 16 import java.nio.CharBuffer ; 17 import java.nio.charset.Charset ; 18 import java.nio.charset.CharsetDecoder ; 19 import java.nio.charset.CoderResult ; 20 import java.nio.charset.CodingErrorAction ; 21 import java.nio.charset.IllegalCharsetNameException ; 22 import java.nio.charset.UnsupportedCharsetException ; 23 import java.util.ArrayList ; 24 25 import javax.tools.FileObject; 26 27 31 public final class Util { 32 public static String LINE_SEPARATOR = System.getProperty("line.separator"); 34 public static class EncodingError { 35 int position; 36 int length; 37 public EncodingError(int position, int length) { 38 this.position = position; 39 this.length = length; 40 } 41 42 public String getSource(char[] unitSource) { 43 47 49 int startPosition = this.position; 51 int endPosition = this.position + this.length - 1; 52 53 if ((startPosition > endPosition) 54 || ((startPosition < 0) && (endPosition < 0)) 55 || unitSource.length == 0) 56 return "No source available"; 58 StringBuffer errorBuffer = new StringBuffer (); 59 errorBuffer.append('\t'); 60 61 char c; 62 final char SPACE = ' '; 63 final char MARK = '^'; 64 final char TAB = '\t'; 65 70 int length = unitSource.length, begin, end; 72 for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) { 73 if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break; 74 } 75 for (end = endPosition >= length ? length - 1 : endPosition ; end+1 < length; end++) { 76 if ((c = unitSource[end + 1]) == '\r' || c == '\n') break; 77 } 78 79 while ((c = unitSource[begin]) == ' ' || c == '\t') begin++; 81 83 errorBuffer.append(unitSource, begin, end-begin+1); 85 errorBuffer.append(Util.LINE_SEPARATOR).append("\t"); 87 for (int i = begin; i <startPosition; i++) { 89 errorBuffer.append((unitSource[i] == TAB) ? TAB : SPACE); 90 } 91 for (int i = startPosition; i <= (endPosition >= length ? length - 1 : endPosition); i++) { 92 errorBuffer.append(MARK); 93 } 94 return errorBuffer.toString(); 95 } 96 } 97 public static class EncodingErrorCollector { 98 ArrayList <EncodingError> encodingErrors = new ArrayList <EncodingError>(); 99 FileObject fileObject; 100 String encoding; 101 102 public EncodingErrorCollector(FileObject fileObject, String encoding) { 103 this.fileObject = fileObject; 104 this.encoding = encoding; 105 } 106 public void collect(int position, int length) { 107 this.encodingErrors.add(new EncodingError(position, length)); 108 } 109 public void reportAllEncodingErrors(String string) { 110 char[] unitSource = string.toCharArray(); 112 for (EncodingError error : this.encodingErrors) { 113 System.err.println(this.fileObject.getName() + " Unmappable character for encoding " + this.encoding); System.err.println(error.getSource(unitSource)); 115 } 116 } 117 } 118 119 public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding) throws IOException { 120 Charset charset = null; 121 try { 122 charset = Charset.forName(encoding); 123 } catch (IllegalCharsetNameException e) { 124 System.err.println("Illegal charset name : " + encoding); return null; 126 } catch(UnsupportedCharsetException e) { 127 System.err.println("Unsupported charset : " + encoding); return null; 129 } 130 CharsetDecoder charsetDecoder = charset.newDecoder(); 131 charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE); 132 byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, length); 133 ByteBuffer byteBuffer = ByteBuffer.allocate(contents.length); 134 byteBuffer.put(contents); 135 byteBuffer.flip(); 136 return charsetDecoder.decode(byteBuffer).array(); 137 } 138 139 public static CharSequence getCharContents(FileObject fileObject, boolean ignoreEncodingErrors, byte[] contents, String encoding) throws IOException { 140 if (contents == null) return null; 141 Charset charset = null; 142 try { 143 charset = Charset.forName(encoding); 144 } catch (IllegalCharsetNameException e) { 145 System.err.println("Illegal charset name : " + encoding); return null; 147 } catch(UnsupportedCharsetException e) { 148 System.err.println("Unsupported charset : " + encoding); return null; 150 } 151 CharsetDecoder charsetDecoder = charset.newDecoder(); 152 ByteBuffer byteBuffer = ByteBuffer.allocate(contents.length); 153 byteBuffer.put(contents); 154 byteBuffer.flip(); 155 if (ignoreEncodingErrors) { 156 charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE); 157 return charsetDecoder.decode(byteBuffer); 158 } else { 159 charsetDecoder.onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(CodingErrorAction.REPORT); 160 CharBuffer out = CharBuffer.allocate(contents.length); 161 CoderResult result = null; 162 String replacement = charsetDecoder.replacement(); 163 int replacementLength = replacement.length(); 164 EncodingErrorCollector collector = null; 165 while (true) { 166 result = charsetDecoder.decode(byteBuffer, out, true); 167 if (result.isMalformed() || result.isUnmappable()) { 168 171 if (collector == null) { 172 collector = new EncodingErrorCollector(fileObject, encoding); 173 } 174 reportEncodingError(collector, out.position(), result.length()); 175 if ((out.position() + replacementLength) >= out.capacity()) { 176 CharBuffer temp = CharBuffer.allocate(out.capacity() * 2); 178 out.flip(); 179 temp.put(out); 180 out = temp; 181 } 182 out.append(replacement); 183 byteBuffer.position(byteBuffer.position() + result.length()); 184 continue; 185 } 186 if (result.isOverflow()) { 187 CharBuffer temp = CharBuffer.allocate(out.capacity() * 2); 188 out.flip(); 189 temp.put(out); 190 out = temp; 191 } else { 192 break; 193 } 194 } 195 out.flip(); 196 if (collector != null) { 197 collector.reportAllEncodingErrors(out.toString()); 198 } 199 return out; 200 } 201 } 202 203 private static void reportEncodingError(EncodingErrorCollector collector, int position, int length) { 204 collector.collect(position, -length); 205 } 206 } 207 208 | Popular Tags |