Fixed: [Issue 94] Importing "google/protobuf/descriptor.proto" does not
work.

Now we pass the path to descriptor.proto to protoc. Code cleanup.
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder_findRootOf_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder_findRootOf_Test.java
new file mode 100644
index 0000000..3e8fab7
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder_findRootOf_Test.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * 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
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.ui.builder;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.rules.ExpectedException.none;
+
+import org.junit.*;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Tests for <code>{@link ProtoDescriptorPathFinder#findRootOf(String)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProtoDescriptorPathFinder_findRootOf_Test {
+
+  private static ProtoDescriptorPathFinder finder;
+
+  @BeforeClass public static void setUpOnce() {
+    finder = new ProtoDescriptorPathFinder();
+  }
+
+  @Rule public ExpectedException thrown = none();
+
+  @Test public void should_return_null_if_path_is_null() {
+    assertThat(finder.findRootOf(null), nullValue());
+  }
+
+  @Test public void should_throw_error_if_path_does_not_contain_descriptor_FQN() {
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage("Path '/usr/local/include' does not contain '/google/protobuf/descriptor.proto'");
+    finder.findRootOf("/usr/local/include");
+  }
+
+  @Test public void should_find_import_root_of_descriptor() {
+    String filePath = "/usr/local/include/google/protobuf/descriptor.proto";
+    assertThat(finder.findRootOf(filePath), equalTo("/usr/local/include"));
+  }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder.java
new file mode 100644
index 0000000..9fa8783
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * 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
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.ui.builder;
+
+import static com.google.eclipse.protobuf.scoping.ProtoDescriptor.DESCRIPTOR_IMPORT_URI;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class ProtoDescriptorPathFinder {
+
+  private static final String DESCRIPTOR_FQN = "/" + DESCRIPTOR_IMPORT_URI;
+
+  public String findRootOf(String descriptorFilePath) {
+    if (descriptorFilePath == null) return null;
+    int indexOfDescriptorFqn = descriptorFilePath.indexOf(DESCRIPTOR_FQN);
+    if (indexOfDescriptorFqn == -1) {
+      String format = "Path '%s' does not contain '%s'";
+      throw new IllegalArgumentException(String.format(format, descriptorFilePath, DESCRIPTOR_FQN));
+    }
+    return descriptorFilePath.substring(0, indexOfDescriptorFqn);
+  }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtobufBuildParticipant.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtobufBuildParticipant.java
index 3dffc5e..e70f5d0 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtobufBuildParticipant.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtobufBuildParticipant.java
@@ -19,7 +19,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.eclipse.core.filesystem.*;
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
 import org.eclipse.emf.common.util.URI;
@@ -42,6 +41,7 @@
   @Inject private ProtocCommandFactory commandFactory;
   @Inject private CompilerPreferencesFactory compilerPreferencesFactory;
   @Inject private PathsPreferencesFactory pathsPreferencesFactory;
+  @Inject private ProtoDescriptorPathFinder protoDescriptorPathFinder;
 
   public void build(IBuildContext context, IProgressMonitor monitor) throws CoreException {
     IProject project = context.getBuiltProject();
@@ -50,25 +50,28 @@
     List<Delta> deltas = context.getDeltas();
     if (deltas.isEmpty()) return;
     OutputDirectories outputDirectories = findOrCreateOutputDirectories(project, preferences.codeGenerationSettings());
+    String descriptorPath = descriptorPath(preferences);
     List<String> importRoots = importRoots(project);
     for (Delta d : deltas) {
-      IResourceDescription newResource = d.getNew();
-      String path = filePathIfIsProtoFile(newResource);
-      if (path == null) continue;
-      IFile source = project.getWorkspace().getRoot().getFile(new Path(path));
+      IFile source = protoFile(d.getNew(), project);
+      if (source == null) continue;
       if (importRoots.isEmpty()) importRoots = singleImportRoot(source);
-      generateSingleProto(source, preferences.protocPath(), importRoots, outputDirectories);
+      generateSingleProto(source, preferences.protocPath(), importRoots, descriptorPath, outputDirectories);
     }
     if (preferences.shouldRefreshResources()) refresh(project, outputDirectories, preferences.refreshTarget(), monitor);
   }
 
+  private String descriptorPath(CompilerPreferences preferences) {
+    return protoDescriptorPathFinder.findRootOf(preferences.descriptorPath());
+  }
+
   private List<String> importRoots(IProject project) {
     List<String> paths = new ArrayList<String>();
     PathsPreferences preferences = pathsPreferencesFactory.preferences(project);
     if (MULTIPLE_DIRECTORIES.equals(preferences.pathResolutionType())) {
       List<DirectoryPath> directoryPaths = preferences.importRoots();
       for (DirectoryPath path : directoryPaths) {
-        String location = locationOfDirectory(path, project);
+        String location = path.location(project);
         if (location != null) paths.add(location);
       }
       return unmodifiableList(paths);
@@ -76,22 +79,9 @@
     return emptyList();
   }
 
-  private String locationOfDirectory(DirectoryPath path, IProject project) {
-    if (path.isWorkspacePath()) return locationOfWorkspaceDirectory(path, project);
-    return locationOfFileSystemDirectory(path);
-  }
-
-  private String locationOfWorkspaceDirectory(DirectoryPath path, IProject project) {
-    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-    IFolder folder = root.getFolder(new Path(path.value()));
-    return folder.getLocation().toOSString();
-  }
-
-  private String locationOfFileSystemDirectory(DirectoryPath path) {
-    IFileSystem fileSystem = EFS.getLocalFileSystem();
-    IFileInfo fileInfo = fileSystem.getStore(new Path(path.value())).fetchInfo();
-    if (!fileInfo.isDirectory()) return null;
-    return path.value();
+  private static IFile protoFile(IResourceDescription r, IProject project) {
+    String path = filePathIfIsProtoFile(r);
+    return (path == null) ? null : project.getWorkspace().getRoot().getFile(new Path(path));
   }
 
   private static String filePathIfIsProtoFile(IResourceDescription r) {
@@ -116,9 +106,9 @@
     return singletonList(current.toString());
   }
 
-  private void generateSingleProto(IFile source, String protocPath, List<String> importRoots,
+  private void generateSingleProto(IFile source, String protocPath, List<String> importRoots, String descriptorPath,
       OutputDirectories outputDirectories) throws CoreException {
-    String command = commandFactory.protocCommand(source, protocPath, importRoots, outputDirectories);
+    String command = commandFactory.protocCommand(source, protocPath, importRoots, descriptorPath, outputDirectories);
     System.out.println(command);
     try {
       Process process = Runtime.getRuntime().exec(command);
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
index ec2694d..32ab772 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
@@ -10,12 +10,14 @@
 
 import static com.google.eclipse.protobuf.util.CommonWords.space;
 
-import com.google.eclipse.protobuf.ui.preferences.pages.compiler.SupportedLanguage;
-
-import org.eclipse.core.resources.*;
-
 import java.util.*;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.xtext.util.Strings;
+
+import com.google.eclipse.protobuf.ui.preferences.pages.compiler.SupportedLanguage;
+
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -28,13 +30,16 @@
       LANG_OUT_FLAG.put(lang, "--" + lang.code() + "_out=");
   }
 
-  String protocCommand(IFile protoFile, String protocPath, List<String> importRoots,
+  String protocCommand(IFile protoFile, String protocPath, List<String> importRoots, String descriptorPath,
       OutputDirectories outputDirectories) {
     StringBuilder command = new StringBuilder();
     command.append(protocPath).append(space());
     for (String importRoot : importRoots) {
       command.append("-I=").append(importRoot).append(space());
     }
+    if (!Strings.isEmpty(descriptorPath)) {
+      command.append("--proto_path=").append(descriptorPath).append(space());
+    }
     for (SupportedLanguage language : SupportedLanguage.values()) {
       IFolder outputDirectory = outputDirectories.outputDirectoryFor(language);
       if (outputDirectory == null) continue;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/paths/DirectoryPath.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/paths/DirectoryPath.java
index 51a5886..1aeb5bb 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/paths/DirectoryPath.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/paths/DirectoryPath.java
@@ -10,17 +10,22 @@
 
 import static com.google.eclipse.protobuf.ui.preferences.pages.paths.ProjectVariable.useProjectName;
 
-import org.eclipse.core.resources.IProject;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
-import java.util.regex.*;
+import org.eclipse.core.filesystem.*;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.Path;
 
 /**
+ * Represents the path of a directory.
+ *
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class DirectoryPath {
 
   private static final Pattern WORKSPACE_PATH_PATTERN = Pattern.compile("\\$\\{workspace_loc:(.*)\\}");
-  
+
   private final String value;
   private final boolean isWorkspacePath;
 
@@ -37,23 +42,54 @@
     }
     return new DirectoryPath(path, false);
   }
-  
+
   DirectoryPath(String path, boolean isWorkspacePath) {
     this.value = path;
     this.isWorkspacePath = isWorkspacePath;
   }
-  
+
   /** {@inheritDoc} */
   @Override public String toString() {
     if (!isWorkspacePath) return value;
     return "${workspace_loc:" + value + "}";
   }
 
+  /**
+   * Returns the textual value of this path.
+   * @return the textual value of this path.
+   */
   public String value() {
     return value;
   }
 
+  /**
+   * Indicates whether this path belongs to a workspace resource.
+   * @return {@code true} if this path belongs to a workspace resource, {@code false} otherwise.
+   */
   public boolean isWorkspacePath() {
     return isWorkspacePath;
   }
+
+  /**
+   * Returns the absolute path in the local file system, or {@code null} if no path can be determined.
+   * @param project used if this path belongs to a workspace resource.
+   * @return the absolute path in the local file system, or {@code null} if no path can be determined.
+   */
+  public String location(IProject project) {
+    if (isWorkspacePath()) return locationOfWorkspaceDirectory(project);
+    return locationOfFileSystemDirectory();
+  }
+
+  private String locationOfWorkspaceDirectory(IProject project) {
+    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+    IFolder folder = root.getFolder(new Path(value()));
+    return folder.getLocation().toOSString();
+  }
+
+  private String locationOfFileSystemDirectory() {
+    IFileSystem fileSystem = EFS.getLocalFileSystem();
+    IFileInfo fileInfo = fileSystem.getStore(new Path(value())).fetchInfo();
+    if (!fileInfo.isDirectory()) return null;
+    return value();
+  }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
index f83be37..b27a2cf 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
@@ -38,6 +38,11 @@
  */
 public class ProtoDescriptor {
 
+  /**
+   * The URI to use when importing descriptor.proto.
+   */
+  public static String DESCRIPTOR_IMPORT_URI = "google/protobuf/descriptor.proto";
+
   private static final Map<String, OptionType> OPTION_DEFINITION_BY_NAME = new HashMap<String, OptionType>();
 
   static {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Imports.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Imports.java
index ac9b01b..ea34fd0 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Imports.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Imports.java
@@ -8,6 +8,8 @@
  */
 package com.google.eclipse.protobuf.util;
 
+import static com.google.eclipse.protobuf.scoping.ProtoDescriptor.DESCRIPTOR_IMPORT_URI;
+
 import com.google.eclipse.protobuf.protobuf.Import;
 import com.google.inject.Singleton;
 
@@ -38,6 +40,6 @@
    * @return {@code true} if the given import URI is equal to the path of descriptor.proto, {@code false} otherwise.
    */
   public boolean isUnresolvedDescriptorUri(String uri) {
-    return "google/protobuf/descriptor.proto".equals(uri);
+    return DESCRIPTOR_IMPORT_URI.equals(uri);
   }
 }