patch to store classpath results between restarts to aid performance (FELIX-2595)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@996072 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/eclipse/ui/internal/classpath/SigilClassPathContainer.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/eclipse/ui/internal/classpath/SigilClassPathContainer.java
index 802e9e8..baf9cea 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/eclipse/ui/internal/classpath/SigilClassPathContainer.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/eclipse/ui/internal/classpath/SigilClassPathContainer.java
@@ -19,15 +19,24 @@
package org.apache.felix.sigil.eclipse.ui.internal.classpath;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
import org.apache.felix.sigil.eclipse.SigilCore;
import org.apache.felix.sigil.eclipse.job.ThreadProgressMonitor;
import org.apache.felix.sigil.eclipse.model.project.ISigilProjectModel;
+import org.apache.felix.sigil.eclipse.ui.SigilUI;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
/**
* @author dave
@@ -36,9 +45,13 @@
public class SigilClassPathContainer implements IClasspathContainer
{
- private IClasspathEntry[] entries;
- private ISigilProjectModel sigil;
+ private static final String CLASSPATH = "classpath";
+ private static final String EMPTY = "empty";
+ private IClasspathEntry[] entries;
+
+ private final ISigilProjectModel sigil;
+
public SigilClassPathContainer(ISigilProjectModel sigil)
{
this.sigil = sigil;
@@ -90,9 +103,15 @@
{
try
{
- IProgressMonitor monitor = ThreadProgressMonitor.getProgressMonitor();
if (sigil.exists()) {
- entries = sigil.findExternalClasspath(monitor).toArray(new IClasspathEntry[0]);
+ entries = getCachedClassPath(sigil);
+
+ if ( entries == null ) {
+ IProgressMonitor monitor = ThreadProgressMonitor.getProgressMonitor();
+ entries = sigil.findExternalClasspath(monitor).toArray(new IClasspathEntry[0]);
+
+ cacheClassPath(sigil, entries);
+ }
}
}
catch (CoreException e)
@@ -107,4 +126,146 @@
}
}
}
+
+ static IClasspathEntry[] getCachedClassPath(ISigilProjectModel project) {
+ File f = getClassPathDir(project);
+ if ( f == null || !f.exists() ) return null;
+
+ File[] entries = f.listFiles();
+ if ( entries == null || entries.length == 0 ) return null;
+
+ ArrayList<IClasspathEntry> list = new ArrayList<IClasspathEntry>(entries.length);
+ for(File entry : entries ) {
+ if ( EMPTY.equals(entry.getName() ) ) {
+ list.clear();
+ break;
+ }
+ else {
+ try
+ {
+ list.add(readClassPath(project.getJavaModel(), entry));
+ }
+ catch (IOException e)
+ {
+ SigilCore.warn("Failed to read classpath entry " + entry, e);
+ }
+ }
+ }
+ return list.toArray(new IClasspathEntry[list.size()]);
+ }
+
+ private static File getClassPathDir(ISigilProjectModel project)
+ {
+ IPath loc = project.getProject().getWorkingLocation(SigilUI.PLUGIN_ID);
+
+ if ( loc == null ) return null;
+
+ loc = loc.append(CLASSPATH);
+
+ return new File(loc.toOSString());
+ }
+
+ static void cacheClassPath(ISigilProjectModel project, IClasspathEntry[] entries)
+ {
+ File f = getClassPathDir(project);
+
+ if ( f == null ) return;
+
+ if ( !f.exists() ) {
+ if (!f.mkdirs()) {
+ SigilCore.warn("Failed to create temp working directory " + f);
+ return;
+ }
+ }
+
+ try
+ {
+ if (entries.length == 0)
+ {
+ File empty = new File(f, EMPTY);
+ empty.createNewFile();
+ }
+ else {
+ int i = 0;
+ for(IClasspathEntry e : entries) {
+ File entry = new File(f, Integer.toString(i++));
+ writeClassPath(project.getJavaModel(), entry, e);
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ SigilCore.warn("Failed to read write classpath entries", e);
+ }
+ }
+
+ /**
+ * @param sigil
+ */
+ static void flushCachedClassPath(ISigilProjectModel project)
+ {
+ File f = getClassPathDir(project);
+
+ if ( f == null || !f.exists() ) return;
+
+ File[] files = f.listFiles();
+ if ( files == null ) return;
+
+ for (File entry : files) {
+ entry.delete();
+ }
+ }
+
+ private static IClasspathEntry readClassPath(IJavaProject javaModel, File entry) throws IOException
+ {
+ FileInputStream in = new FileInputStream(entry);
+
+ try
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ byte[] b = new byte[1024];
+
+ for(;;) {
+ int r = in.read(b);
+ if ( r == -1 ) break;
+ buf.write(b, 0, r);
+ }
+
+ String enc = buf.toString();
+ return javaModel.decodeClasspathEntry(enc);
+ }
+ finally
+ {
+ try
+ {
+ in.close();
+ }
+ catch (IOException e)
+ {
+ SigilCore.warn("Failed to close stream to " + entry, e);
+ }
+ }
+ }
+
+ private static void writeClassPath(IJavaProject javaModel, File file, IClasspathEntry entry) throws IOException
+ {
+ String enc = javaModel.encodeClasspathEntry(entry);
+ FileOutputStream out = new FileOutputStream(file);
+ try {
+ out.write(enc.getBytes());
+ out.flush();
+ }
+ finally {
+ try
+ {
+ out.close();
+ }
+ catch (IOException e)
+ {
+ SigilCore.warn("Failed to close stream to " + entry, e);
+ }
+ }
+ }
+
}
diff --git a/sigil/eclipse/ui/src/org/apache/felix/sigil/eclipse/ui/internal/classpath/SigilClasspathContainerInitializer.java b/sigil/eclipse/ui/src/org/apache/felix/sigil/eclipse/ui/internal/classpath/SigilClasspathContainerInitializer.java
index 311454a..2216efa 100644
--- a/sigil/eclipse/ui/src/org/apache/felix/sigil/eclipse/ui/internal/classpath/SigilClasspathContainerInitializer.java
+++ b/sigil/eclipse/ui/src/org/apache/felix/sigil/eclipse/ui/internal/classpath/SigilClasspathContainerInitializer.java
@@ -46,6 +46,8 @@
throws CoreException
{
ISigilProjectModel sigil = SigilCore.create(project.getProject());
+
+ SigilClassPathContainer.flushCachedClassPath(sigil);
IClasspathContainer sigilContainer = new SigilClassPathContainer(sigil);
@@ -53,15 +55,24 @@
IClasspathContainer[] respectiveContainers = new IClasspathContainer[] { sigilContainer };
+
+ JavaCore.setClasspathContainer(containerPath, affectedProjects,
+ respectiveContainers, getMonitor());
+ }
+
+ /**
+ * @return
+ */
+ private IProgressMonitor getMonitor()
+ {
IProgressMonitor monitor = ThreadProgressMonitor.getProgressMonitor();
if (monitor == null)
{
monitor = Job.getJobManager().createProgressGroup();
}
-
- JavaCore.setClasspathContainer(containerPath, affectedProjects,
- respectiveContainers, monitor);
+
+ return monitor;
}
@Override
@@ -76,10 +87,7 @@
IClasspathContainer[] respectiveContainers = new IClasspathContainer[] { sigilContainer };
- IProgressMonitor monitor = Job.getJobManager().createProgressGroup();
-
JavaCore.setClasspathContainer(containerPath, affectedProjects,
- respectiveContainers, monitor);
+ respectiveContainers, getMonitor());
}
-
}