Wed, 16 Oct 2013 16:33:04 -0400
8026286: Improper locking of annotation queues causes assertion failures.
8026063: Calls to annotate.flush() cause incorrect type annotations to be generated.
Summary: Fix locking in ClassReader.java
Reviewed-by: jfranck
1 /*
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.util;
28 import java.io.IOException;
29 import java.lang.ref.SoftReference;
30 import java.nio.CharBuffer;
31 import javax.tools.JavaFileObject;
33 import com.sun.tools.javac.file.JavacFileManager;
34 import com.sun.tools.javac.tree.EndPosTable;
36 import static com.sun.tools.javac.util.LayoutCharacters.*;
38 /**
39 * A simple abstraction of a source file, as needed for use in a diagnostic message.
40 * Provides access to the line and position in a line for any given character offset.
41 *
42 * <p><b>This is NOT part of any supported API.
43 * If you write code that depends on this, you do so at your own risk.
44 * This code and its internal interfaces are subject to change or
45 * deletion without notice.</b>
46 */
47 public class DiagnosticSource {
49 /* constant DiagnosticSource to be used when sourcefile is missing */
50 public static final DiagnosticSource NO_SOURCE = new DiagnosticSource() {
51 @Override
52 protected boolean findLine(int pos) {
53 return false;
54 }
55 };
57 public DiagnosticSource(JavaFileObject fo, AbstractLog log) {
58 this.fileObject = fo;
59 this.log = log;
60 }
62 private DiagnosticSource() {}
64 /** Return the underlying file object handled by this
65 * DiagnosticSource object.
66 */
67 public JavaFileObject getFile() {
68 return fileObject;
69 }
71 /** Return the one-based line number associated with a given pos
72 * for the current source file. Zero is returned if no line exists
73 * for the given position.
74 */
75 public int getLineNumber(int pos) {
76 try {
77 if (findLine(pos)) {
78 return line;
79 }
80 return 0;
81 } finally {
82 buf = null;
83 }
84 }
86 /** Return the one-based column number associated with a given pos
87 * for the current source file. Zero is returned if no column exists
88 * for the given position.
89 */
90 public int getColumnNumber(int pos, boolean expandTabs) {
91 try {
92 if (findLine(pos)) {
93 int column = 0;
94 for (int bp = lineStart; bp < pos; bp++) {
95 if (bp >= bufLen) {
96 return 0;
97 }
98 if (buf[bp] == '\t' && expandTabs) {
99 column = (column / TabInc * TabInc) + TabInc;
100 } else {
101 column++;
102 }
103 }
104 return column + 1; // positions are one-based
105 }
106 return 0;
107 } finally {
108 buf = null;
109 }
110 }
112 /** Return the content of the line containing a given pos.
113 */
114 public String getLine(int pos) {
115 try {
116 if (!findLine(pos))
117 return null;
119 int lineEnd = lineStart;
120 while (lineEnd < bufLen && buf[lineEnd] != CR && buf[lineEnd] != LF)
121 lineEnd++;
122 if (lineEnd - lineStart == 0)
123 return null;
124 return new String(buf, lineStart, lineEnd - lineStart);
125 } finally {
126 buf = null;
127 }
128 }
130 public EndPosTable getEndPosTable() {
131 return endPosTable;
132 }
134 public void setEndPosTable(EndPosTable t) {
135 if (endPosTable != null && endPosTable != t)
136 throw new IllegalStateException("endPosTable already set");
137 endPosTable = t;
138 }
140 /** Find the line in the buffer that contains the current position
141 * @param pos Character offset into the buffer
142 */
143 protected boolean findLine(int pos) {
144 if (pos == Position.NOPOS)
145 return false;
147 try {
148 // try and recover buffer from soft reference cache
149 if (buf == null && refBuf != null)
150 buf = refBuf.get();
152 if (buf == null) {
153 buf = initBuf(fileObject);
154 lineStart = 0;
155 line = 1;
156 } else if (lineStart > pos) { // messages don't come in order
157 lineStart = 0;
158 line = 1;
159 }
161 int bp = lineStart;
162 while (bp < bufLen && bp < pos) {
163 switch (buf[bp++]) {
164 case CR:
165 if (bp < bufLen && buf[bp] == LF) bp++;
166 line++;
167 lineStart = bp;
168 break;
169 case LF:
170 line++;
171 lineStart = bp;
172 break;
173 }
174 }
175 return bp <= bufLen;
176 } catch (IOException e) {
177 log.directError("source.unavailable");
178 buf = new char[0];
179 return false;
180 }
181 }
183 protected char[] initBuf(JavaFileObject fileObject) throws IOException {
184 char[] buf;
185 CharSequence cs = fileObject.getCharContent(true);
186 if (cs instanceof CharBuffer) {
187 CharBuffer cb = (CharBuffer) cs;
188 buf = JavacFileManager.toArray(cb);
189 bufLen = cb.limit();
190 } else {
191 buf = cs.toString().toCharArray();
192 bufLen = buf.length;
193 }
194 refBuf = new SoftReference<char[]>(buf);
195 return buf;
196 }
198 /** The underlying file object. */
199 protected JavaFileObject fileObject;
201 protected EndPosTable endPosTable;
203 /** A soft reference to the content of the file object. */
204 protected SoftReference<char[]> refBuf;
206 /** A temporary hard reference to the content of the file object. */
207 protected char[] buf;
209 /** The length of the content. */
210 protected int bufLen;
212 /** The start of a line found by findLine. */
213 protected int lineStart;
215 /** The line number of a line found by findLine. */
216 protected int line;
218 /** A log for reporting errors, such as errors accessing the content. */
219 protected AbstractLog log;
220 }