Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDani Megert2004-05-27 16:22:12 +0000
committerDani Megert2004-05-27 16:22:12 +0000
commit2ca3ecb8120694376df04f44c00e6524c82db36a (patch)
tree302a762176239e19296c0ce89a5166b744ba33e7 /org.eclipse.core.filebuffers
parent88d9fb009126ae6d99da972f05d9a34b4d1c798e (diff)
downloadeclipse.platform.text-2ca3ecb8120694376df04f44c00e6524c82db36a.tar.gz
eclipse.platform.text-2ca3ecb8120694376df04f44c00e6524c82db36a.tar.xz
eclipse.platform.text-2ca3ecb8120694376df04f44c00e6524c82db36a.zip
Fixed bug 60636 and 63626
Diffstat (limited to 'org.eclipse.core.filebuffers')
-rw-r--r--org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/AbstractFileBuffer.java30
-rw-r--r--org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties7
-rw-r--r--org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/JavaTextFileBuffer.java109
-rw-r--r--org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java145
4 files changed, 269 insertions, 22 deletions
diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/AbstractFileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/AbstractFileBuffer.java
index 6be8c2a9e..874a0edde 100644
--- a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/AbstractFileBuffer.java
+++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/AbstractFileBuffer.java
@@ -13,6 +13,7 @@ package org.eclipse.core.internal.filebuffers;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.filebuffers.IFileBuffer;
@@ -33,4 +34,33 @@ public abstract class AbstractFileBuffer implements IFileBuffer {
public abstract void requestSynchronizationContext();
public abstract void releaseSynchronizationContext();
+
+
+ /**
+ * Helper method which computes the encoding out of the given description.
+ * <p>
+ * XXX:
+ * This method should be provided by Platform Core
+ * see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=64342
+ * </p>
+ *
+ * @param description the content description
+ * @return the encoding
+ * @see org.eclipse.core.resources.IFile#getCharset()
+ */
+ static String getCharset(IContentDescription description) {
+ if (description == null)
+ return null;
+ byte[] bom= (byte[]) description.getProperty(IContentDescription.BYTE_ORDER_MARK);
+ if (bom != null)
+ if (bom == IContentDescription.BOM_UTF_8)
+ return "UTF-8"; //$NON-NLS-1$
+ else if (bom == IContentDescription.BOM_UTF_16BE || bom == IContentDescription.BOM_UTF_16LE)
+ // UTF-16 will properly detect the BOM
+ return "UTF-16"; //$NON-NLS-1$
+ else {
+ // unknown BOM... ignore it
+ }
+ return (String)description.getProperty(IContentDescription.CHARSET);
+ }
}
diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties
index 53e28a636..fec7a6f3b 100644
--- a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties
+++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties
@@ -14,9 +14,16 @@ ExtensionsRegistry.error.contentTypeDoesNotExist= The content type with id "{0}"
FileBuffer.error.fileDoesNotExist= The file does not exist.
FileBuffer.error.outOfSync= The file is not synchronized with the the local file system.
+FileBuffer.error.wrongByteOrderMark= Wrong byte order mark for UTF-8 encoding
+
FileBuffer.status.ok= OK
FileBuffer.status.error= Error
FileBufferManager.error.canNotCreateFilebuffer= Cannot create file buffer.
ContainerGenerator.task.creatingContainer= Creating container...
+
+ResourceTextFileBuffer.error.unsupported_encoding.message_arg= Character encoding \"{0}\" is not supported by this platform.
+ResourceTextFileBuffer.error.closeReader= Could not close reader.
+
+JavaTextFileBuffer.error.closeStream= Could not close stream.
diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/JavaTextFileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/JavaTextFileBuffer.java
index 2618cd53e..378e946ac 100644
--- a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/JavaTextFileBuffer.java
+++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/JavaTextFileBuffer.java
@@ -20,12 +20,17 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.filebuffers.ITextFileBuffer;
@@ -83,7 +88,19 @@ public class JavaTextFileBuffer extends JavaFileBuffer implements ITextFileBuffe
protected String fEncoding;
/** Internal document listener */
protected IDocumentListener fDocumentListener= new DocumentListener();
-
+ /**
+ * The encoding which has explicitly been set on the file.
+ */
+ private String fExplicitEncoding;
+ /**
+ * BOM if encoding is UTF-8.
+ * <p>
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ * </p>
+ */
+ private byte[] fUTF8BOM;
public JavaTextFileBuffer(TextFileBufferManager manager) {
@@ -236,6 +253,28 @@ public class JavaTextFileBuffer extends JavaFileBuffer implements ITextFileBuffe
protected void initializeFileBufferContent(IProgressMonitor monitor) throws CoreException {
try {
fDocument= fManager.createEmptyDocument(getLocation());
+
+ InputStream stream= getFileContents(monitor);
+ try {
+ QualifiedName[] options= new QualifiedName[] { IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK };
+ IContentDescription description= Platform.getContentTypeManager().getDescriptionFor(stream, fFile.getName(), options);
+ if (description != null) {
+ fEncoding= getCharset(description);
+
+ fUTF8BOM= (byte[]) description.getProperty(IContentDescription.BYTE_ORDER_MARK);
+ if (fUTF8BOM != null && fUTF8BOM != IContentDescription.BOM_UTF_8)
+ throw new CoreException(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, FileBuffersMessages.getString("FileBuffer.error.wrongByteOrderMark"), null)); //$NON-NLS-1$
+ }
+ } catch (IOException e) {
+ fEncoding= null;
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException ex) {
+ FileBuffersPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, FileBuffersMessages.getString("JavaTextFileBuffer.error.closeStream"), ex)); //$NON-NLS-1$
+ }
+ }
+
setDocumentContent(fDocument, getFileContents(monitor), fEncoding);
} catch (CoreException x) {
fDocument= fManager.createEmptyDocument(getLocation());
@@ -247,13 +286,24 @@ public class JavaTextFileBuffer extends JavaFileBuffer implements ITextFileBuffe
* @see org.eclipse.core.internal.filebuffers.FileBuffer#commitFileBufferContent(org.eclipse.core.runtime.IProgressMonitor, boolean)
*/
protected void commitFileBufferContent(IProgressMonitor monitor, boolean overwrite) throws CoreException {
+ String encoding= computeEncoding();
try {
- String encoding= getEncoding();
- if (encoding == null)
- encoding= fManager.getDefaultEncoding();
-
- InputStream stream= new ByteArrayInputStream(fDocument.get().getBytes(encoding));
+ byte[] bytes= fDocument.get().getBytes(encoding);
+
+ /*
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ */
+ if (fUTF8BOM != null) {
+ byte[] bytesWithBOM= new byte[bytes.length + 3];
+ System.arraycopy(fUTF8BOM, 0, bytesWithBOM, 0, 3);
+ System.arraycopy(bytes, 0, bytesWithBOM, 3, bytes.length);
+ bytes= bytesWithBOM;
+ }
+
+ InputStream stream= new ByteArrayInputStream(bytes);
if (fFile.exists()) {
@@ -283,13 +333,42 @@ public class JavaTextFileBuffer extends JavaFileBuffer implements ITextFileBuffe
}
- } catch (IOException x) {
- String message= (x.getMessage() != null ? x.getMessage() : ""); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException x) {
+ String message= FileBuffersMessages.getFormattedString("ResourceTextFileBuffer.error.unsupported_encoding.message_arg", encoding); //$NON-NLS-1$
IStatus s= new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, message, x);
throw new CoreException(s);
}
}
+ private String computeEncoding() {
+ // User-defined encoding has first priority
+ if (fExplicitEncoding != null)
+ return fExplicitEncoding;
+
+ // Probe content
+ Reader reader= new BufferedReader(new StringReader(fDocument.get()));
+ try {
+ QualifiedName[] options= new QualifiedName[] { IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK };
+ IContentDescription description= Platform.getContentTypeManager().getDescriptionFor(reader, fFile.getName(), options);
+ String encoding= getCharset(description);
+ if (encoding != null)
+ return encoding;
+ else if (fUTF8BOM != null)
+ return "UTF-8"; //$NON-NLS-1$
+ } catch (IOException ex) {
+ // try next strategy
+ } finally {
+ try {
+ reader.close();
+ } catch (IOException ex) {
+ FileBuffersPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, FileBuffersMessages.getString("ResourceTextFileBuffer.error.closeReader"), ex)); //$NON-NLS-1$
+ }
+ }
+
+ // Use global default
+ return fManager.getDefaultEncoding();
+ }
+
/**
* Intitializes the given document with the given stream using the given encoding.
*
@@ -304,7 +383,19 @@ public class JavaTextFileBuffer extends JavaFileBuffer implements ITextFileBuffe
if (encoding == null)
encoding= fManager.getDefaultEncoding();
-
+
+ /*
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ * </p>
+ */
+ if (fUTF8BOM != null) {
+ contentStream.read();
+ contentStream.read();
+ contentStream.read();
+ }
+
in= new BufferedReader(new InputStreamReader(contentStream, encoding), BUFFER_SIZE);
StringBuffer buffer= new StringBuffer(BUFFER_SIZE);
char[] readBuffer= new char[READER_CHUNK_SIZE];
diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java
index 0a8b83605..e71f9df3f 100644
--- a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java
+++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java
@@ -16,17 +16,22 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
-import org.eclipse.core.filebuffers.IPersistableAnnotationModel;
-import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.content.IContentDescription;
+
+import org.eclipse.core.filebuffers.IPersistableAnnotationModel;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
@@ -34,7 +39,7 @@ import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.source.IAnnotationModel;
/**
- *
+ * @since 3.0
*/
public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextFileBuffer {
@@ -88,6 +93,19 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
protected IDocumentListener fDocumentListener= new DocumentListener();
/** The element's annotation model */
protected IAnnotationModel fAnnotationModel;
+ /**
+ * The encoding which has explicitly been set on the file.
+ */
+ private String fExplicitEncoding;
+ /**
+ * BOM if encoding is UTF-8.
+ * <p>
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ * </p>
+ */
+ private byte[] fUTF8BOM;
public ResourceTextFileBuffer(TextFileBufferManager manager) {
@@ -120,8 +138,12 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
*/
public void setEncoding(String encoding) {
fEncoding= encoding;
+ fExplicitEncoding= encoding;
try {
fFile.setCharset(encoding);
+ if (encoding == null)
+ fEncoding= fFile.getCharset();
+ readUTF8BOM();
} catch (CoreException x) {
handleCoreException(x);
}
@@ -209,6 +231,7 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
protected void initializeFileBufferContent(IProgressMonitor monitor) throws CoreException {
try {
fEncoding= null;
+ fExplicitEncoding= null;
try {
fEncoding= fFile.getPersistentProperty(ENCODING_KEY);
} catch (CoreException x) {
@@ -217,6 +240,7 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
if (fEncoding != null) {
// if we found an old encoding property, we try to migrate it to the new core.resources encoding support
try {
+ fExplicitEncoding= fEncoding;
fFile.setCharset(fEncoding);
// if successful delete old property
fFile.setPersistentProperty(ENCODING_KEY, null);
@@ -225,9 +249,15 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
handleCoreException(ex);
}
} else {
- fEncoding= fFile.getCharset();
+ fExplicitEncoding= fFile.getCharset(false);
+ if (fExplicitEncoding != null)
+ fEncoding= fExplicitEncoding;
+ else
+ fEncoding= fFile.getCharset();
}
+ readUTF8BOM();
+
fDocument= fManager.createEmptyDocument(fFile.getLocation());
setDocumentContent(fDocument, fFile.getContents(), fEncoding);
@@ -239,6 +269,28 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
}
}
+ /**
+ * Reads the file's UTF-8 BOM if any and stores it.
+ * <p>
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ * </p>
+ * @throws CoreException if
+ * - reading of file's content description fails
+ * - byte order mark is not valid for UTF-8
+ */
+ protected void readUTF8BOM() throws CoreException {
+ if ("UTF-8".equals(fEncoding)) { //$NON-NLS-1$
+ IContentDescription description= fFile.getContentDescription();
+ if (description != null) {
+ fUTF8BOM= (byte[]) description.getProperty(IContentDescription.BYTE_ORDER_MARK);
+ if (fUTF8BOM != null && fUTF8BOM != IContentDescription.BOM_UTF_8)
+ throw new CoreException(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, FileBuffersMessages.getString("FileBuffer.error.wrongByteOrderMark"), null)); //$NON-NLS-1$
+ }
+ }
+ }
+
/*
* @see org.eclipse.core.internal.filebuffers.ResourceFileBuffer#connected()
*/
@@ -261,14 +313,24 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
* @see org.eclipse.core.internal.filebuffers.FileBuffer#commitFileBufferContent(org.eclipse.core.runtime.IProgressMonitor, boolean)
*/
protected void commitFileBufferContent(IProgressMonitor monitor, boolean overwrite) throws CoreException {
+ String encoding= computeEncoding();
try {
- String encoding= getEncoding();
- if (encoding == null)
- encoding= fManager.getDefaultEncoding();
-
- InputStream stream= new ByteArrayInputStream(fDocument.get().getBytes(encoding));
-
+ byte[] bytes= fDocument.get().getBytes(encoding);
+
+ /*
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ */
+ if (fUTF8BOM != null) {
+ byte[] bytesWithBOM= new byte[bytes.length + 3];
+ System.arraycopy(fUTF8BOM, 0, bytesWithBOM, 0, 3);
+ System.arraycopy(bytes, 0, bytesWithBOM, 3, bytes.length);
+ bytes= bytesWithBOM;
+ }
+
+ InputStream stream= new ByteArrayInputStream(bytes);
if (fFile.exists()) {
if (!overwrite)
@@ -299,13 +361,59 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
}
}
- } catch (IOException x) {
- String message= (x.getMessage() != null ? x.getMessage() : ""); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException x) {
+ String message= FileBuffersMessages.getFormattedString("ResourceTextFileBuffer.error.unsupported_encoding.message_arg", encoding); //$NON-NLS-1$
IStatus s= new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, message, x);
throw new CoreException(s);
}
}
+ private String computeEncoding() {
+ // User-defined encoding has first priority
+ if (fExplicitEncoding != null)
+ return fExplicitEncoding;
+ try {
+ /*
+ * FIXME
+ * Check whether explicit encoding has been set via properties dialog.
+ * This is needed because no notification is sent when this property
+ * changes, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=64077
+ */
+ fExplicitEncoding= fFile.getCharset(false);
+ if (fExplicitEncoding != null)
+ return fExplicitEncoding;
+ } catch (CoreException e) {
+ }
+
+ // Probe content
+ Reader reader= new BufferedReader(new StringReader(fDocument.get()));
+ try {
+ QualifiedName[] options= new QualifiedName[] { IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK };
+ IContentDescription description= Platform.getContentTypeManager().getDescriptionFor(reader, fFile.getName(), options);
+ String encoding= getCharset(description);
+ if (encoding != null)
+ return encoding;
+ else if (fUTF8BOM != null)
+ return "UTF-8"; //$NON-NLS-1$
+ } catch (IOException ex) {
+ // try next strategy
+ } finally {
+ try {
+ reader.close();
+ } catch (IOException ex) {
+ FileBuffersPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, FileBuffersMessages.getString("ResourceTextFileBuffer.error.closeReader"), ex)); //$NON-NLS-1$
+ }
+ }
+
+ // Use parent chain
+ try {
+ return fFile.getParent().getDefaultCharset();
+ } catch (CoreException ex) {
+ // Use global default
+ return fManager.getDefaultEncoding();
+ }
+ }
+
/**
* Updates the element info to a change of the file content and sends out appropriate notifications.
*/
@@ -372,7 +480,18 @@ public class ResourceTextFileBuffer extends ResourceFileBuffer implements ITextF
if (encoding == null)
encoding= fManager.getDefaultEncoding();
-
+
+ /*
+ * XXX:
+ * This is a workaround for a corresponding bug in Java readers and writer,
+ * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+ */
+ if (fUTF8BOM != null) {
+ contentStream.read();
+ contentStream.read();
+ contentStream.read();
+ }
+
in= new BufferedReader(new InputStreamReader(contentStream, encoding), BUFFER_SIZE);
StringBuffer buffer= new StringBuffer(BUFFER_SIZE);
char[] readBuffer= new char[READER_CHUNK_SIZE];

Back to the top