[nobug] get file contents once instead of twice
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FileContentCache.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FileContentCache.java
index 2802c74..6a29258 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FileContentCache.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FileContentCache.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2009 IBM Corporation and others.
+ * Copyright (c) 2007, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,15 +11,21 @@
*******************************************************************************/
package org.eclipse.jst.jsp.core.internal.util;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
-import java.util.HashMap;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.core.filebuffers.FileBuffers;
@@ -30,21 +36,20 @@
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.jface.text.IDocument;
import org.eclipse.jst.jsp.core.internal.Logger;
-import org.eclipse.wst.sse.core.internal.util.Debug;
public class FileContentCache {
private static class CacheEntry {
String contents;
long modificationStamp = IResource.NULL_STAMP;
- IPath path;
+ IPath contentPath;
CacheEntry(IPath path) {
- this.path = path;
+ this.contentPath = path;
modificationStamp = getModificationStamp(path);
contents = readContents(path);
}
@@ -60,48 +65,24 @@
if (modificationStamp == IResource.NULL_STAMP) {
return true;
}
- long newStamp = getModificationStamp(path);
+ long newStamp = getModificationStamp(contentPath);
return newStamp > modificationStamp;
}
- private String detectCharset(IFile file) {
- if (file.getType() == IResource.FILE && file.isAccessible()) {
- IContentDescription d = null;
- try {
- // optimized description lookup, might not succeed
- d = file.getContentDescription();
- if (d != null)
- return d.getCharset();
- }
- catch (CoreException e) {
- // should not be possible given the accessible and file
- // type
- // check above
- }
- InputStream contents = null;
- try {
- contents = file.getContents();
- IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(contents, file.getName(), new QualifiedName[]{IContentDescription.CHARSET});
- if (description != null) {
- return description.getCharset();
- }
- }
- catch (IOException e) {
- // will try to cleanup in finally
- }
- catch (CoreException e) {
- // out of sync
- }
- finally {
- if (contents != null) {
- try {
- contents.close();
- }
- catch (Exception e) {
- // not sure how to recover at this point
- }
- }
- }
+
+ /**
+ * @param name
+ * @param contents2
+ * @return
+ */
+ private String detectCharset(String name, byte[] contents) throws IOException {
+ IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(new ByteArrayInputStream(contents), name, new QualifiedName[]{IContentDescription.CHARSET});
+ if (description != null) {
+ String charset = description.getCharset();
+ if (charset == null && description.getContentType() != null)
+ charset = description.getContentType().getDefaultCharset();
+ if (charset != null)
+ return charset;
}
return ResourcesPlugin.getEncoding();
}
@@ -117,35 +98,51 @@
return IResource.NULL_STAMP;
}
+ /**
+ * Read once and store the contents to determine the encoding and reuse as input
+ */
private String readContents(IPath filePath) {
if (DEBUG)
- System.out.println("readContents:" + filePath);
- StringBuffer s = new StringBuffer();
+ System.out.println(getClass().getName() + " readContents: " + filePath); //$NON-NLS-1$
+
InputStream is = null;
try {
IFile f = getFile(filePath);
if (f != null && f.isAccessible()) {
- String charset = detectCharset(f);
- if (charset == null) {
- charset = ResourcesPlugin.getEncoding();
- }
is = f.getContents();
- Reader reader = new InputStreamReader(is, charset);
- char[] readBuffer = new char[8092];
- int n = reader.read(readBuffer);
- while (n > 0) {
- s.append(readBuffer, 0, n);
- n = reader.read(readBuffer);
- }
+ }
+ else {
+ is = new FileInputStream(filePath.toFile());
+ }
+
+ ByteArrayOutputStream store = new ByteArrayOutputStream();
+ byte[] readBuffer = new byte[8092];
+ int n = is.read(readBuffer);
+ while (n > 0) {
+ store.write(readBuffer, 0, n);
+ n = is.read(readBuffer);
+ }
+
+ byte[] bytes = store.toByteArray();
+ String charset = detectCharset(filePath.lastSegment(), bytes);
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ try {
+ CharBuffer charBuffer = Charset.forName(charset).decode(buffer);
+ return charBuffer.toString();
+ }
+ catch (IllegalCharsetNameException e) {
+ return new String(bytes, charset);
+ }
+ catch (UnsupportedCharsetException e) {
+ return new String(bytes, charset);
}
}
catch (CoreException e) {
+ Logger.logException(e);
// out of sync
}
catch (Exception e) {
- if (Debug.debugStructuredDocument) {
- Logger.logException(e);
- }
+// Logger.logException(e);
}
finally {
try {
@@ -157,28 +154,7 @@
// nothing to do
}
}
- if (is == null) {
- try {
- FileBuffers.getTextFileBufferManager().connect(filePath, LocationKind.LOCATION, new NullProgressMonitor());
- ITextFileBuffer buffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(filePath, LocationKind.LOCATION);
- if (buffer != null) {
- s.append(buffer.getDocument().get());
- }
- }
- catch (CoreException e) {
- // nothing to do
- Logger.logException(e);
- }
- finally {
- try {
- FileBuffers.getTextFileBufferManager().disconnect(filePath, LocationKind.LOCATION, new NullProgressMonitor());
- }
- catch (CoreException e) {
- Logger.logException(e);
- }
- }
- }
- return s.toString();
+ return null;
}
}
@@ -191,11 +167,18 @@
return instance;
}
- private HashMap fContentMap;
+ static class LimitedHashMap extends LinkedHashMap {
+ private static final long serialVersionUID = 1L;
+
+ protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
+ return size() > 25; //completely arbitrary number
+ }
+ }
+ private LinkedHashMap fContentMap;
private FileContentCache() {
super();
- fContentMap = new HashMap();
+ fContentMap = new LimitedHashMap();
}
private void cleanup() {
@@ -212,7 +195,28 @@
public String getContents(IPath filePath) {
if (DEBUG)
- System.out.println("getContents:" + filePath);
+ System.out.println(getClass().getName() + "#getContents: " + filePath); //$NON-NLS-1$
+
+ /*
+ * Use an open file buffer if one exists for contents in dirty
+ * editors. LocationKind.IFILE will only apply to workspace paths, but
+ * they're far more likely to be open in an editor and modified than
+ * files outside the workspace (LocationKind.LOCATION). We'll use
+ * LocationKind.NORMALIZE and let the framework sort things out,
+ * unless it proves to be a performance problem.
+ *
+ * Do not cause a file buffer to be opened by calling connect()
+ */
+ ITextFileBuffer existingBuffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(
+ filePath, LocationKind.NORMALIZE);
+ if (existingBuffer != null) {
+ IDocument document = existingBuffer.getDocument();
+ if (document != null) {
+ return document.get();
+ }
+ }
+
+ //check the cache
CacheEntry entry = null;
Object o = fContentMap.get(filePath);
if (o instanceof Reference) {
@@ -220,7 +224,7 @@
}
if (entry == null || entry.isStale()) {
if (DEBUG && entry != null && entry.isStale())
- System.out.println("stale contents:" + filePath);
+ System.out.println(getClass().getName() + " stale contents: " + filePath); //$NON-NLS-1$
entry = new CacheEntry(filePath);
synchronized (fContentMap) {
fContentMap.put(filePath, new SoftReference(entry));
@@ -229,6 +233,4 @@
cleanup();
return entry.contents;
}
-
-
}