Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorspingel2011-02-01 02:38:24 +0000
committerspingel2011-02-01 02:38:24 +0000
commit43a767b8d046d41cecf0b9fa30a8f408560d5e2c (patch)
tree760cd53fd1b57365c5a4062421104cd1df6f4fb1 /org.eclipse.mylyn.tasks.core
parent89b6e7c3c2320fd77d41944915a49092737d2c85 (diff)
downloadorg.eclipse.mylyn.tasks-43a767b8d046d41cecf0b9fa30a8f408560d5e2c.tar.gz
org.eclipse.mylyn.tasks-43a767b8d046d41cecf0b9fa30a8f408560d5e2c.tar.xz
org.eclipse.mylyn.tasks-43a767b8d046d41cecf0b9fa30a8f408560d5e2c.zip
RESOLVED - bug 268456: reading of task data fails with fatal error
https://bugs.eclipse.org/bugs/show_bug.cgi?id=268456
Diffstat (limited to 'org.eclipse.mylyn.tasks.core')
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataExternalizer.java107
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataStore.java38
2 files changed, 126 insertions, 19 deletions
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataExternalizer.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataExternalizer.java
index 4336296cd..dceb6f2d0 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataExternalizer.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataExternalizer.java
@@ -11,6 +11,8 @@
package org.eclipse.mylyn.internal.tasks.core.data;
+import java.io.EOFException;
+import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -41,6 +43,88 @@ import org.xml.sax.helpers.XMLReaderFactory;
*/
public class TaskDataExternalizer {
+ /**
+ * Replaces the first 38 bytes of a an input stream with an XML 1.1 header.
+ */
+ public static class Xml11InputStream extends FilterInputStream {
+
+ /**
+ * XML 1.1 header.
+ */
+ byte[] header;
+
+ /**
+ * Current position in {@link #header}.
+ */
+ int pointer;
+
+ public Xml11InputStream(InputStream in) throws IOException {
+ super(in);
+ header = new String("<?xml version=\"1.1\" encoding=\"UTF-8\"?>").getBytes("US-ASCII"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ public synchronized void reset() throws IOException {
+ throw new IOException();
+ }
+
+ @Override
+ public synchronized void mark(int readlimit) {
+ }
+
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ // fill b with bytes from header until the header has been read
+ if (pointer < header.length) {
+ int read = 0;
+ for (; pointer < header.length && read < len; read++, pointer++) {
+ b[off + read] = header[pointer];
+ readByte();
+ }
+ return read;
+ } else {
+ return super.read(b, off, len);
+ }
+ }
+
+ /**
+ * Advances the underlying stream by a single byte.
+ */
+ private void readByte() throws IOException, EOFException {
+ if (in.read() == -1) {
+ throw new EOFException();
+ }
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (pointer < header.length) {
+ readByte();
+ return header[pointer++];
+ } else {
+ return super.read();
+ }
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ if (pointer < header.length) {
+ // skip at most the number of bytes remaining in the header
+ long skip = Math.min(header.length - pointer, n);
+ pointer += skip;
+ return skip;
+ } else {
+ return super.skip(n);
+ }
+ }
+
+ }
+
private final IRepositoryManager taskRepositoryManager;
public TaskDataExternalizer(IRepositoryManager taskRepositoryManager) {
@@ -90,21 +174,16 @@ public class TaskDataExternalizer {
}
}
- public TaskDataState readState(InputStream in) throws IOException {
- try {
- XMLReader parser = XMLReaderFactory.createXMLReader();
- TaskDataStateReader handler = new TaskDataStateReader(taskRepositoryManager);
- parser.setContentHandler(handler);
- parser.parse(new InputSource(in));
- TaskDataState taskDataState = handler.getTaskDataState();
- if (taskDataState != null) {
- migrate(taskDataState);
- }
- return taskDataState;
- } catch (SAXException e) {
- //e.printStackTrace();
- throw new IOException("Error parsing task data: " + e.getMessage()); //$NON-NLS-1$
+ public TaskDataState readState(InputStream in) throws IOException, SAXException {
+ XMLReader parser = XMLReaderFactory.createXMLReader();
+ TaskDataStateReader handler = new TaskDataStateReader(taskRepositoryManager);
+ parser.setContentHandler(handler);
+ parser.parse(new InputSource(in));
+ TaskDataState taskDataState = handler.getTaskDataState();
+ if (taskDataState != null) {
+ migrate(taskDataState);
}
+ return taskDataState;
}
public void writeState(OutputStream out, ITaskDataWorkingCopy state) throws IOException {
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataStore.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataStore.java
index 9dd1e692b..b08ef73d9 100644
--- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataStore.java
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/data/TaskDataStore.java
@@ -26,8 +26,10 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
+import org.eclipse.mylyn.internal.tasks.core.data.TaskDataExternalizer.Xml11InputStream;
import org.eclipse.mylyn.tasks.core.IRepositoryManager;
import org.eclipse.mylyn.tasks.core.data.TaskData;
+import org.xml.sax.SAXException;
/**
* @author Steffen Pingel
@@ -106,15 +108,41 @@ public class TaskDataStore {
writeState(file, state);
}
+ private TaskDataState readStateInternal(File file, boolean xml11) throws IOException, SAXException {
+ ZipInputStream in = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
+ try {
+ in.getNextEntry();
+ // bug 268456: When TaskData that contains C0 control characters is written to disk using XML 1.0 reading it back
+ // in fails with a SAXException. The XML 1.1 standard allows C0 entities but fails if C1 entities. If C0 control
+ // characters are detected while parsing file as XML 1.0 a second attempt is made using XML 1.1. If the file contains
+ // C0 and C1 control characters reading will fail regardless.
+ if (xml11) {
+ return externalizer.readState(new Xml11InputStream(in));
+ } else {
+ return externalizer.readState(in);
+ }
+ } finally {
+ in.close();
+ }
+ }
+
private TaskDataState readState(File file) throws CoreException {
try {
if (file.exists()) {
- ZipInputStream in = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
try {
- in.getNextEntry();
- return externalizer.readState(in);
- } finally {
- in.close();
+ try {
+ return readStateInternal(file, false);
+ } catch (SAXException e) {
+ // bug 268456: if reading fails, try again using a different XML version
+ if (e.getMessage() != null && e.getMessage().contains("invalid XML character")) { //$NON-NLS-1$
+ return readStateInternal(file, true);
+ } else {
+ throw e;
+ }
+ }
+
+ } catch (SAXException e) {
+ throw new IOException("Error parsing task data: " + e.getMessage()); //$NON-NLS-1$
}
}
return null;

Back to the top