aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-channel
diff options
context:
space:
mode:
authorDinesh Bolkensteyn <dinesh@dinsoft.net>2011-10-20 20:50:42 +0200
committerDinesh Bolkensteyn <dinesh@dinsoft.net>2011-10-20 20:51:35 +0200
commit0b9c56c76952cc93dea74b386938154158f407dd (patch)
tree2f64114c3f62beb436ba9072cc0e852aa2483974 /sonar-channel
parent58f71c9c265323a5c341e365816521a7119eae07 (diff)
downloadsonarqube-0b9c56c76952cc93dea74b386938154158f407dd.tar.gz
sonarqube-0b9c56c76952cc93dea74b386938154158f407dd.zip
SONAR-2923 and SONAR-2632: Remove sonar-channel buffer restriction and character pushback feature
Diffstat (limited to 'sonar-channel')
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java1
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java111
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java20
-rw-r--r--sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java22
-rw-r--r--sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java18
-rw-r--r--sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java21
6 files changed, 56 insertions, 137 deletions
diff --git a/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java b/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java
index 5422def73a3..032f2d67ef6 100644
--- a/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java
+++ b/sonar-channel/src/main/java/org/sonar/channel/ChannelCodeReaderFilter.java
@@ -73,6 +73,7 @@ public final class ChannelCodeReaderFilter<OUTPUT> extends CodeReaderFilter<OUTP
*/
@Override
public int read(char[] filteredBuffer, int offset, int length) throws IOException {
+ if (internalCodeReader.peek() == -1) return -1;
int initialOffset = offset;
while (offset < filteredBuffer.length) {
if (internalCodeReader.peek() == -1) {
diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java b/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java
index 7274181662e..5a4e1a668e0 100644
--- a/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java
+++ b/sonar-channel/src/main/java/org/sonar/channel/CodeBuffer.java
@@ -23,6 +23,7 @@ import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
+import java.nio.CharBuffer;
import org.apache.commons.io.IOUtils;
@@ -38,13 +39,10 @@ import org.apache.commons.io.IOUtils;
*/
public class CodeBuffer implements CharSequence {
- private final Reader code;
private int lastChar = -1;
private Cursor cursor;
- private int bufferCapacity;
private char[] buffer;
private int bufferPosition = 0;
- private int bufferSize = 0;
private static final char LF = '\n';
private static final char CR = '\r';
private int tabWidth;
@@ -52,22 +50,41 @@ public class CodeBuffer implements CharSequence {
private boolean recordingMode = false;
private StringBuilder recordedCharacters = new StringBuilder();
+ protected CodeBuffer(String code, CodeReaderConfiguration configuration) {
+ this(new StringReader(code), configuration);
+ }
+
protected CodeBuffer(Reader initialCodeReader, CodeReaderConfiguration configuration) {
lastChar = -1;
cursor = new Cursor();
- bufferCapacity = configuration.getBufferCapacity();
tabWidth = configuration.getTabWidth();
- buffer = new char[bufferCapacity];
+
+ /* Setup the filters on the reader */
Reader reader = initialCodeReader;
for (CodeReaderFilter<?> codeReaderFilter : configuration.getCodeReaderFilters()) {
reader = new Filter(reader, codeReaderFilter, configuration);
}
- this.code = reader;
- fillBuffer();
+
+ /* Buffer the whole reader */
+ fillBuffer(reader);
+
+ /* Clean-up */
+ IOUtils.closeQuietly(reader);
}
-
- protected CodeBuffer(String code, CodeReaderConfiguration configuration) {
- this(new StringReader(code), configuration);
+
+ private void fillBuffer(Reader reader) {
+ try {
+ StringBuilder sb = new StringBuilder();
+ char[] buffer = new char[4096];
+ int read;
+ while ((read = reader.read(buffer)) != -1) {
+ sb.append(buffer, 0, read);
+ }
+ this.buffer = new char[sb.length()];
+ sb.getChars(0, sb.length(), this.buffer, 0);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
/**
@@ -76,16 +93,13 @@ public class CodeBuffer implements CharSequence {
* @return the next character or -1 if the end of the stream is reached
*/
public final int pop() {
- if (bufferPosition == bufferSize) {
- fillBuffer();
- }
- if (bufferSize == 0) {
+ if (bufferPosition >= buffer.length) {
return -1;
}
int character = buffer[bufferPosition++];
updateCursorPosition(character);
if (recordingMode) {
- recordedCharacters.append((char) character);
+ recordedCharacters.append((char)character);
}
lastChar = character;
return character;
@@ -103,24 +117,6 @@ public class CodeBuffer implements CharSequence {
}
}
- private int fillBuffer() {
- try {
- int offset = bufferSize - bufferPosition;
- if (offset != 0) {
- System.arraycopy(buffer, bufferPosition, buffer, 0, bufferSize - bufferPosition);
- }
- bufferPosition = 0;
- int numberOfChars = code.read(buffer, offset, bufferCapacity - offset);
- if (numberOfChars == -1) {
- numberOfChars = 0;
- }
- bufferSize = numberOfChars + offset;
- return offset;
- } catch (IOException e) {
- throw new ChannelException(e.getMessage(), e);
- }
- }
-
/**
* Looks at the last consumed character
*
@@ -140,38 +136,6 @@ public class CodeBuffer implements CharSequence {
}
/**
- * Pushes a character sequence onto the top of this CodeBuffer. This characters will be then the first to be read.
- *
- * @param chars
- * the character sequences to push into the CodeBuffer
- */
- public void push(CharSequence chars) {
- int length = chars.length();
- if (bufferPosition >= length) {
- for (int index = 0; index < length; index++) {
- buffer[bufferPosition + index - length] = chars.charAt(index);
- }
- bufferPosition -= length;
- } else {
- char[] extendedBuffer = new char[buffer.length - bufferPosition + length];
- for (int index = 0; index < length; index++) {
- extendedBuffer[index] = chars.charAt(index);
- }
- System.arraycopy(buffer, bufferPosition, extendedBuffer, length, bufferSize - bufferPosition);
- buffer = extendedBuffer;
- bufferSize = bufferSize + length - bufferPosition;
- bufferPosition = 0;
- }
- }
-
- /**
- * Close the stream
- */
- public final void close() {
- IOUtils.closeQuietly(code);
- }
-
- /**
* @return the current line of the cursor
*/
public final int getLinePosition() {
@@ -219,33 +183,26 @@ public class CodeBuffer implements CharSequence {
* Returns the character at the specified index after the cursor without consuming it
*
* @param index
- * the index of the character to be returned
+ * the relative index of the character to be returned
* @return the desired character
* @see java.lang.CharSequence#charAt(int)
*/
public final char charAt(int index) {
- return (char) intAt(index);
+ return (char)intAt(index);
}
protected final int intAt(int index) {
- if (bufferPosition + index > bufferSize - 1) {
- fillBuffer();
- }
- if (bufferPosition + index > bufferSize - 1) {
+ if (bufferPosition + index >= buffer.length) {
return -1;
}
return buffer[bufferPosition + index];
}
/**
- * Warning : this method returns Integer.MAX_VALUE when the buffer is fully used
- * as the length of the stream can't be known before having consumed all characters.
- *
- * Integer.MAX_VALUE is returned to prevent regular expression matchers to stop consuming the stream of characters (see
- * http://jira.codehaus.org/browse/SONAR-2010)
+ * Returns the relative length of the string (i.e. excluding the popped chars)
*/
public final int length() {
- return (bufferSize == bufferCapacity ? Integer.MAX_VALUE : bufferSize - bufferPosition);
+ return buffer.length - bufferPosition;
}
public final CharSequence subSequence(int start, int end) {
diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java
index bd543207ea9..7347074b01d 100644
--- a/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java
+++ b/sonar-channel/src/main/java/org/sonar/channel/CodeReaderConfiguration.java
@@ -28,32 +28,13 @@ import java.util.List;
*/
public class CodeReaderConfiguration {
- public final static int DEFAULT_BUFFER_CAPACITY = 8000;
-
public final static int DEFAULT_TAB_WIDTH = 1;
- private int bufferCapacity = DEFAULT_BUFFER_CAPACITY;
-
private int tabWidth = DEFAULT_TAB_WIDTH;
private List<CodeReaderFilter<?>> codeReaderFilters = new ArrayList<CodeReaderFilter<?>>();
/**
- * @return the bufferCapacity
- */
- public int getBufferCapacity() {
- return bufferCapacity;
- }
-
- /**
- * @param bufferCapacity
- * the bufferCapacity to set
- */
- public void setBufferCapacity(int bufferCapacity) {
- this.bufferCapacity = bufferCapacity;
- }
-
- /**
* @return the tabWidth
*/
public int getTabWidth() {
@@ -96,7 +77,6 @@ public class CodeReaderConfiguration {
public CodeReaderConfiguration cloneWithoutCodeReaderFilters() {
CodeReaderConfiguration clone = new CodeReaderConfiguration();
- clone.setBufferCapacity(bufferCapacity);
clone.setTabWidth(tabWidth);
return clone;
}
diff --git a/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java b/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java
index 471b16bd975..387978fe069 100644
--- a/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java
+++ b/sonar-channel/src/test/java/org/sonar/channel/CodeBufferTest.java
@@ -117,20 +117,6 @@ public class CodeBufferTest {
}
@Test
- public void testPush() {
- CodeReader reader = new CodeReader("12", defaulConfiguration);
- assertEquals('1', (char) reader.pop());
- reader.push("a");
- assertEquals('a', (char) reader.peek());
- reader.push("45");
- assertEquals("45a2", new String(reader.peek(4)));
- for (int i = 0; i < 4; i++) {
- reader.pop();
- }
- assertEquals( -1, reader.pop());
- }
-
- @Test
public void testCharAtIndexOutOfBoundsException() {
CodeBuffer reader = new CodeBuffer("12345", defaulConfiguration);
assertEquals(reader.charAt(5), (char) -1);
@@ -210,14 +196,6 @@ public class CodeBufferTest {
}
@Test
- public void theLengthShouldBeIntegerMaxValueWhenTheBufferCantContainAllCharacters() {
- String myCode = "myCode";
- CodeReaderConfiguration conf = new CodeReaderConfiguration();
- conf.setBufferCapacity(2);
- assertThat(new CodeBuffer(myCode, conf).length(), is(Integer.MAX_VALUE));
- }
-
- @Test
public void testSeveralCodeReaderFilter() throws Exception {
CodeReaderConfiguration configuration = new CodeReaderConfiguration();
configuration.setCodeReaderFilters(new ReplaceNumbersFilter(), new ReplaceCharFilter());
diff --git a/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java b/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java
index a748cfa6f83..b6f1d0b8289 100644
--- a/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java
+++ b/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java
@@ -84,24 +84,6 @@ public class CodeReaderTest {
}
@Test
- public void testPeekToAndReachingTheBufferLimit() {
- CodeReaderConfiguration configuration = new CodeReaderConfiguration();
- configuration.setBufferCapacity(10);
- CodeReader reader = new CodeReader("word1 word2 word2", configuration);
- for (int i = 0; i < 6; i++) {
- reader.pop();
- }
- StringBuilder result = new StringBuilder();
- reader.peekTo(new EndMatcher() {
-
- public boolean match(int endFlag) {
- return ' ' == (char) endFlag;
- }
- }, result);
- assertEquals("word2", result.toString());
- }
-
- @Test
public void testPopToWithRegex() {
CodeReader reader = new CodeReader(new StringReader("123ABC"));
StringBuilder token = new StringBuilder();
diff --git a/sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java b/sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java
index 35d9c936b78..322899266ab 100644
--- a/sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java
+++ b/sonar-channel/src/test/java/org/sonar/channel/RegexChannelTest.java
@@ -33,7 +33,28 @@ public class RegexChannelTest {
dispatcher.consume(new CodeReader("my word"), output);
assertThat(output.toString(), is("<w>my</w> <w>word</w>"));
}
+
+ @Test
+ public void shouldMatchTokenLongerThanBuffer() {
+ ChannelDispatcher<StringBuilder> dispatcher = ChannelDispatcher.builder().addChannel(new MyLiteralChannel()).build();
+ StringBuilder output = new StringBuilder();
+
+ dispatcher.consume(new CodeReader("\"bonjour\""), output);
+ assertThat(output.toString(), is("<literal>\"bonjour\"</literal>"));
+ }
+
+ private static class MyLiteralChannel extends RegexChannel<StringBuilder> {
+
+ public MyLiteralChannel() {
+ super("\"[^\"]*+\"");
+ }
+ @Override
+ protected void consume(CharSequence token, StringBuilder output) {
+ output.append("<literal>" + token + "</literal>");
+ }
+ }
+
private static class MyWordChannel extends RegexChannel<StringBuilder> {
public MyWordChannel() {