001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package org.terracotta.dso;
005:
006: import org.apache.commons.io.IOUtils;
007: import org.eclipse.core.resources.IFile;
008: import org.eclipse.core.runtime.CoreException;
009:
010: import java.io.BufferedReader;
011: import java.io.IOException;
012: import java.io.InputStreamReader;
013: import java.io.Reader;
014: import java.util.ArrayList;
015: import java.util.ConcurrentModificationException;
016:
017: /**
018: * Keeps information about a text file's line lengths. Used by TcPlugin
019: * to help create SAXMarkers when there are errors on the config document.
020: * This object is serialized to the plugin's private working area, along
021: * with the config document and config object, after successfully parsing
022: * the document into the object.
023: *
024: * Eclipse documents provide this sort of information but we can't rely
025: * on the config document being loaded into an editor.
026: *
027: * @see TcPlugin.loadConfiguration
028: * @see TcPlugin.handleXmlErrors
029: */
030:
031: public class LineLengths implements java.io.Serializable {
032: private int[] m_lines;
033:
034: public LineLengths() {
035: super ();
036: }
037:
038: public LineLengths(IFile file)
039: throws ConcurrentModificationException, IOException,
040: CoreException {
041: this ();
042: setFile(file);
043: }
044:
045: public LineLengths(Reader reader)
046: throws ConcurrentModificationException, IOException {
047: this ();
048: setReader(reader);
049: }
050:
051: public void setFile(IFile file)
052: throws ConcurrentModificationException, IOException,
053: CoreException {
054: initLines(new InputStreamReader(file.getContents()));
055: }
056:
057: public void setReader(Reader reader)
058: throws ConcurrentModificationException, IOException {
059: initLines(reader);
060: }
061:
062: private void initLines(Reader reader)
063: throws ConcurrentModificationException, IOException {
064: ArrayList<String> list = new ArrayList<String>();
065:
066: try {
067: BufferedReader br = new BufferedReader(reader);
068: String s;
069:
070: while ((s = readLine(br)) != null) {
071: list.add(s);
072: }
073: } catch (IOException e) {
074: IOUtils.closeQuietly(reader);
075: throw e;
076: } catch (ConcurrentModificationException e) {
077: IOUtils.closeQuietly(reader);
078: throw e;
079: } finally {
080: IOUtils.closeQuietly(reader);
081: }
082:
083: int size = list.size();
084: m_lines = new int[size];
085: for (int i = 0; i < size; i++) {
086: m_lines[i] = list.get(i).length();
087: }
088: }
089:
090: /**
091: * Reads a complete line of characters from the reader, preserving the
092: * various forms of line-separator that exist.
093: */
094: private String readLine(BufferedReader br) throws IOException {
095: StringBuffer sb = new StringBuffer();
096: boolean haveCR = false;
097: boolean done = false;
098: int i;
099: char c;
100:
101: while ((i = br.read()) != -1) {
102: c = (char) i;
103:
104: if (haveCR) {
105: switch (c) {
106: case '\n':
107: sb.append(c);
108: done = true;
109: break;
110: default:
111: br.reset();
112: done = true;
113: break;
114: }
115: } else {
116: sb.append(c);
117: switch (c) {
118: case '\n':
119: done = true;
120: break;
121: case '\r':
122: br.mark(1);
123: haveCR = true;
124: }
125: }
126:
127: if (done) {
128: break;
129: }
130: }
131:
132: return sb.length() > 0 ? sb.toString() : null;
133: }
134:
135: public int lineSize(int line) {
136: if (line < 0 || line > m_lines.length) {
137: return 0;
138: }
139: return m_lines[line];
140: }
141:
142: public int offset(int line) {
143: int result = 0;
144:
145: if (line == 0)
146: return 0;
147:
148: for (int i = 0; i < line; i++) {
149: result += m_lines[i];
150: }
151:
152: return result;
153: }
154:
155: public int offset(int line, int col) {
156: if (line < 0 || line > m_lines.length) {
157: return 0;
158: }
159: int result = offset(line);
160: if (col > 0) {
161: result += col;
162: }
163: return result;
164: }
165: }
|