Fixed: [Issue 206] Updating resource descriptions takes forever

https://code.google.com/p/protobuf-dt/issues/detail?id=206
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java
index e9b73d3..9a97ad2 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java
@@ -8,6 +8,14 @@
  */
 package com.google.eclipse.protobuf;
 
+import com.google.eclipse.protobuf.conversion.ProtobufTerminalConverters;
+import com.google.eclipse.protobuf.linking.ProtobufResource;
+import com.google.eclipse.protobuf.naming.*;
+import com.google.eclipse.protobuf.resource.*;
+import com.google.eclipse.protobuf.scoping.*;
+import com.google.eclipse.protobuf.validation.*;
+import com.google.inject.Binder;
+
 import org.eclipse.core.runtime.IExtensionRegistry;
 import org.eclipse.xtext.conversion.IValueConverterService;
 import org.eclipse.xtext.naming.*;
@@ -16,14 +24,6 @@
 import org.eclipse.xtext.scoping.impl.ImportUriResolver;
 import org.eclipse.xtext.validation.IResourceValidator;
 
-import com.google.eclipse.protobuf.conversion.ProtobufTerminalConverters;
-import com.google.eclipse.protobuf.linking.ProtobufResource;
-import com.google.eclipse.protobuf.naming.*;
-import com.google.eclipse.protobuf.resource.GlobalResourceServiceProvider;
-import com.google.eclipse.protobuf.scoping.*;
-import com.google.eclipse.protobuf.validation.*;
-import com.google.inject.Binder;
-
 /**
  * Use this class to register components to be used at runtime / without the Equinox extension registry.
  */
@@ -60,6 +60,10 @@
     return ProtobufResource.class;
   }
 
+  @Override public Class<? extends XtextResourceSet> bindXtextResourceSet() {
+    return FastXtextResourceSet.class;
+  }
+
   public void configureExtensionRegistry(Binder binder) {
     binder.bind(IExtensionRegistry.class).toProvider(ExtensionRegistryProvider.class);
   }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/FastXtextResourceSet.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/FastXtextResourceSet.java
new file mode 100644
index 0000000..43729dd
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/FastXtextResourceSet.java
@@ -0,0 +1,61 @@
+package com.google.eclipse.protobuf.resource;
+
+import static org.eclipse.xtext.resource.ClasspathUriUtil.isClasspathUri;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.URIConverter;
+import org.eclipse.emf.ecore.resource.impl.ExtensibleURIConverterImpl;
+import org.eclipse.xtext.resource.*;
+
+import java.io.*;
+import java.util.Map;
+
+public class FastXtextResourceSet extends SynchronizedXtextResourceSet {
+  @Override public URIConverter getURIConverter() {
+    if (uriConverter == null) {
+      uriConverter = new ExtensibleURIConverterImpl() {
+        @Override public URI normalize(URI uri) {
+          if (isClasspathUri(uri)) {
+            URI result = resolveClasspathURI(uri);
+            if (isClasspathUri(result)) {
+              throw new ClasspathUriResolutionException(result);
+            }
+            result = super.normalize(result);
+            return result;
+          }
+          return super.normalize(uri);
+        }
+
+        @Override public InputStream createInputStream(URI uri) throws IOException {
+          InputStream in = doCreateInputStream(uri);
+          return in != null ? in : super.createInputStream(uri);
+        }
+
+        @Override public InputStream createInputStream(URI uri, Map<?, ?> options) throws IOException {
+          InputStream in = doCreateInputStream(uri);
+          return in != null ? in : super.createInputStream(uri, options);
+        }
+
+        private InputStream doCreateInputStream(URI uri) throws IOException {
+          if (isClasspathUri(uri)) {
+            return getClass().getResourceAsStream(uri.path());
+          }
+          if ("proto".equals(uri.fileExtension())) {
+            if (uri.isPlatformResource()) {
+              return getClass().getResourceAsStream(uri.path());
+            }
+            if (uri.isFile()) {
+              return new FileInputStream(uri.path());
+            }
+          }
+          return null;
+        }
+      };
+    }
+    return uriConverter;
+  }
+
+  private URI resolveClasspathURI(URI uri) {
+    return getClasspathUriResolver().resolve(getClasspathURIContext(), uri);
+  }
+}