KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > tool > Util


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.tool;
12
13 import java.io.IOException JavaDoc;
14 import java.io.InputStream JavaDoc;
15 import java.nio.ByteBuffer JavaDoc;
16 import java.nio.CharBuffer JavaDoc;
17 import java.nio.charset.Charset JavaDoc;
18 import java.nio.charset.CharsetDecoder JavaDoc;
19 import java.nio.charset.CoderResult JavaDoc;
20 import java.nio.charset.CodingErrorAction JavaDoc;
21 import java.nio.charset.IllegalCharsetNameException JavaDoc;
22 import java.nio.charset.UnsupportedCharsetException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24
25 import javax.tools.FileObject;
26
27 /**
28  * Util class that defines helper methods to read class contents with handling of wrong encoding
29  *
30  */

31 public final class Util {
32     public static String JavaDoc LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
33

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 JavaDoc getSource(char[] unitSource) {
43             //extra from the source the innacurate token
44
//and "highlight" it using some underneath ^^^^^
45
//put some context around too.
46

47             //this code assumes that the font used in the console is fixed size
48

49             //sanity .....
50
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"; //$NON-NLS-1$
57

58             StringBuffer JavaDoc errorBuffer = new StringBuffer JavaDoc();
59             errorBuffer.append('\t');
60
61             char c;
62             final char SPACE = ' ';
63             final char MARK = '^';
64             final char TAB = '\t';
65             //the next code tries to underline the token.....
66
//it assumes (for a good display) that token source does not
67
//contain any \r \n. This is false on statements !
68
//(the code still works but the display is not optimal !)
69

70             // expand to line limits
71
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             // trim left and right spaces/tabs
80
while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
81             //while ((c = unitSource[end]) == ' ' || c == '\t') end--; TODO (philippe) should also trim right, but all tests are to be updated
82

83             // copy source
84
errorBuffer.append(unitSource, begin, end-begin+1);
85             errorBuffer.append(Util.LINE_SEPARATOR).append("\t"); //$NON-NLS-1$
86

87             // compute underline
88
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 JavaDoc<EncodingError> encodingErrors = new ArrayList JavaDoc<EncodingError>();
99         FileObject fileObject;
100         String JavaDoc encoding;
101
102         public EncodingErrorCollector(FileObject fileObject, String JavaDoc 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 JavaDoc string) {
110             // this is where the encoding errors should be reported
111
char[] unitSource = string.toCharArray();
112             for (EncodingError error : this.encodingErrors) {
113                 System.err.println(this.fileObject.getName() + " Unmappable character for encoding " + this.encoding);//$NON-NLS-1$
114
System.err.println(error.getSource(unitSource));
115             }
116         }
117     }
118
119     public static char[] getInputStreamAsCharArray(InputStream JavaDoc stream, int length, String JavaDoc encoding) throws IOException JavaDoc {
120         Charset JavaDoc charset = null;
121         try {
122             charset = Charset.forName(encoding);
123         } catch (IllegalCharsetNameException JavaDoc e) {
124             System.err.println("Illegal charset name : " + encoding); //$NON-NLS-1$
125
return null;
126         } catch(UnsupportedCharsetException JavaDoc e) {
127             System.err.println("Unsupported charset : " + encoding); //$NON-NLS-1$
128
return null;
129         }
130         CharsetDecoder JavaDoc 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 JavaDoc byteBuffer = ByteBuffer.allocate(contents.length);
134         byteBuffer.put(contents);
135         byteBuffer.flip();
136         return charsetDecoder.decode(byteBuffer).array();
137     }
138
139     public static CharSequence JavaDoc getCharContents(FileObject fileObject, boolean ignoreEncodingErrors, byte[] contents, String JavaDoc encoding) throws IOException JavaDoc {
140         if (contents == null) return null;
141         Charset JavaDoc charset = null;
142         try {
143             charset = Charset.forName(encoding);
144         } catch (IllegalCharsetNameException JavaDoc e) {
145             System.err.println("Illegal charset name : " + encoding); //$NON-NLS-1$
146
return null;
147         } catch(UnsupportedCharsetException JavaDoc e) {
148             System.err.println("Unsupported charset : " + encoding); //$NON-NLS-1$
149
return null;
150         }
151         CharsetDecoder JavaDoc charsetDecoder = charset.newDecoder();
152         ByteBuffer JavaDoc 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 JavaDoc out = CharBuffer.allocate(contents.length);
161             CoderResult JavaDoc result = null;
162             String JavaDoc 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                     /* treat the error
169                      * The wrong input character is at out.position
170                      */

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                         // resize
177
CharBuffer JavaDoc 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 JavaDoc 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