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

Added preference to store path of descriptor.proto (includes changes to
"compiler" preference page.)
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferencePage.java
index 9b18254..4009ecd 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferencePage.java
@@ -37,6 +37,8 @@
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class CompilerPreferencePage extends PreferenceAndPropertyPage {
+  public CompilerPreferencePage() {
+  }
 
   private static final String PREFERENCE_PAGE_ID = CompilerPreferencePage.class.getName();
 
@@ -59,6 +61,9 @@
   @Inject private PluginImageHelper imageHelper;
 
   private final CodeGenerationSettings codeGenerationSettings = new CodeGenerationSettings();
+  private Group grpDescriptorLocation;
+  private Text txtDescriptorFilePath;
+  private Button btnDescriptorPathBrowse;
 
   @Override protected void doCreateContents(Composite parent) {
     btnCompileProtoFiles = new Button(parent, SWT.CHECK);
@@ -77,15 +82,15 @@
 
     grpCompilerLocation = new Group(cmpMain, SWT.NONE);
     grpCompilerLocation.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
-    grpCompilerLocation.setLayout(new GridLayout(4, false));
+    grpCompilerLocation.setLayout(new GridLayout(2, false));
     grpCompilerLocation.setText(protocLocation);
 
     btnUseProtocInSystemPath = new Button(grpCompilerLocation, SWT.RADIO);
-    btnUseProtocInSystemPath.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 4, 1));
+    btnUseProtocInSystemPath.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
     btnUseProtocInSystemPath.setText(protocInSystemPath);
 
     btnUseProtocInCustomPath = new Button(grpCompilerLocation, SWT.RADIO);
-    btnUseProtocInCustomPath.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 4, 1));
+    btnUseProtocInCustomPath.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
     btnUseProtocInCustomPath.setText(protocInCustomPath);
 
     txtProtocFilePath = new Text(grpCompilerLocation, SWT.BORDER);
@@ -94,9 +99,19 @@
 
     btnProtocPathBrowse = new Button(grpCompilerLocation, SWT.NONE);
     btnProtocPathBrowse.setText(browseCustomPath);
-    new Label(grpCompilerLocation, SWT.NONE);
-    new Label(grpCompilerLocation, SWT.NONE);
-
+    
+    grpDescriptorLocation = new Group(cmpMain, SWT.NONE);
+    grpDescriptorLocation.setText(descriptorLocation);
+    grpDescriptorLocation.setLayout(new GridLayout(2, false));
+    grpDescriptorLocation.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+    
+    txtDescriptorFilePath = new Text(grpDescriptorLocation, SWT.BORDER);
+    txtDescriptorFilePath.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+    txtDescriptorFilePath.setEditable(false);
+    
+    btnDescriptorPathBrowse = new Button(grpDescriptorLocation, SWT.NONE);
+    btnDescriptorPathBrowse.setText(browseCustomPath);
+    
     grpCodeGeneration = new Group(cmpMain, SWT.NONE);
     grpCodeGeneration.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
     grpCodeGeneration.setText(codeGeneration);
@@ -155,6 +170,15 @@
         checkState();
       }
     });
+    btnDescriptorPathBrowse.addSelectionListener(new SelectionAdapter() {
+      @Override public void widgetSelected(SelectionEvent e) {
+        FileDialog dialog = new FileDialog(getShell(), SWT.OPEN | SWT.SHEET);
+        dialog.setFilterExtensions(new String[] { "*.proto" });
+        String file = dialog.open();
+        if (file != null) txtDescriptorFilePath.setText(file);
+        checkState();
+      }
+    });
     btnRefreshResources.addSelectionListener(new SelectionAdapter() {
       @Override public void widgetSelected(SelectionEvent e) {
         refreshResourcesOptionsEnabled(btnRefreshResources.getSelection());
@@ -168,33 +192,40 @@
   }
 
   private void checkState() {
-    boolean atLeastOneEnabled = false;
+    boolean atLeastOneLanguageEnabled = false;
     for (CodeGenerationSetting option : codeGenerationSettings.allSettings()) {
       if (option.isEnabled()) {
-        atLeastOneEnabled = true;
+        atLeastOneLanguageEnabled = true;
         break;
       }
     }
-    if (!atLeastOneEnabled) {
+    if (!atLeastOneLanguageEnabled) {
       pageIsNowInvalid(errorNoLanguageEnabled);
       return;
     }
-    if (!customPathOptionSelectedAndEnabled()) {
-      pageIsNowValid();
-      return;
+    if (customPathOptionSelectedAndEnabled()) {
+      String protocPath = txtProtocFilePath.getText();
+      if (isEmpty(protocPath)) {
+        pageIsNowInvalid(errorNoSelection);
+        return;
+      }
+      if (!isFileWithName(protocPath, "protoc")) {
+        pageIsNowInvalid(errorInvalidProtoc);
+        return;
+      }
     }
-    String protocPath = txtProtocFilePath.getText();
-    if (isEmpty(protocPath)) {
-      pageIsNowInvalid(errorNoSelection);
-      return;
-    }
-    File file = new File(protocPath);
-    if (!file.isFile() || !"protoc".equals(file.getName())) { //$NON-NLS-1$
-      pageIsNowInvalid(errorInvalidProtoc);
+    String descriptorPath = txtDescriptorFilePath.getText();
+    if (!isEmpty(descriptorPath) && !isFileWithName(descriptorPath, "descriptor.proto")) {
+      pageIsNowInvalid(errorInvalidDescriptor);
       return;
     }
     pageIsNowValid();
   }
+  
+  private boolean isFileWithName(String filePath, String expectedFileName) {
+    File file = new File(filePath);
+    return file.isFile() && expectedFileName.equals(file.getName());
+  }
 
   @Override protected BooleanPreference enableProjectSettingsPreference(IPreferenceStore store) {
     return enableProjectSettings(store);
@@ -207,6 +238,7 @@
         bindSelectionOf(btnUseProtocInSystemPath).to(preferences.useProtocInSystemPath()),
         bindSelectionOf(btnUseProtocInCustomPath).to(preferences.useProtocInCustomPath()),
         bindTextOf(txtProtocFilePath).to(preferences.protocPath()),
+        bindTextOf(txtDescriptorFilePath).to(preferences.descriptorPath()),
         bindSelectionOf(btnRefreshResources).to(preferences.refreshResources()),
         bindSelectionOf(btnRefreshProject).to(preferences.refreshProject()),
         bindSelectionOf(btnRefreshOutputDirectory).to(preferences.refreshOutputDirectory()),
@@ -245,6 +277,7 @@
   private void enableCompilerOptions(boolean isEnabled) {
     tabFolder.setEnabled(isEnabled);
     enableCompilerPathOptions(isEnabled);
+    enableDescriptorPathOptions(isEnabled);
     enableOutputOptions(isEnabled);
     enableRefreshOptions(isEnabled);
   }
@@ -255,11 +288,17 @@
     btnUseProtocInCustomPath.setEnabled(isEnabled);
     enableCompilerCustomPathOptions(customPathOptionSelectedAndEnabled());
   }
-
+  
   private void enableCompilerCustomPathOptions(boolean isEnabled) {
     txtProtocFilePath.setEnabled(isEnabled);
     btnProtocPathBrowse.setEnabled(isEnabled);
   }
+  
+  private void enableDescriptorPathOptions(boolean isEnabled) {
+    grpDescriptorLocation.setEnabled(isEnabled);
+    txtDescriptorFilePath.setEnabled(isEnabled);
+    btnDescriptorPathBrowse.setEnabled(isEnabled);
+  }
 
   private boolean customPathOptionSelectedAndEnabled() {
     return isEnabledAndSelected(btnUseProtocInCustomPath);
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferences.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferences.java
index 78f8aba..4f86403 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferences.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferences.java
@@ -21,6 +21,7 @@
 
   private final boolean compileProtoFiles;
   private final String protocPath;
+  private final String descriptorPath;
   private final CodeGenerationSettings codeGenerationSettings;
   private final boolean refreshResources;
   private final PostCompilationRefreshTarget refreshTarget;
@@ -29,6 +30,7 @@
     compileProtoFiles = preferences.compileProtoFiles().value();
     boolean useProtocInSystemPath = preferences.useProtocInSystemPath().value();
     protocPath = (useProtocInSystemPath) ? "protoc" : preferences.protocPath().value();
+    descriptorPath = preferences.descriptorPath().value();
     codeGenerationSettings = new CodeGenerationSettings();
     codeGenerationSettings.java().enabled(preferences.javaCodeGenerationEnabled().value());
     codeGenerationSettings.java().outputDirectory(preferences.javaOutputDirectory().value());
@@ -48,6 +50,10 @@
   public String protocPath() {
     return protocPath;
   }
+  
+  public String descriptorPath() {
+    return descriptorPath;
+  }
 
   public CodeGenerationSettings codeGenerationSettings() {
     return codeGenerationSettings;
@@ -60,6 +66,4 @@
   public PostCompilationRefreshTarget refreshTarget() {
     return refreshTarget;
   }
-
-
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/Messages.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/Messages.java
index f8d5299..0126998 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/Messages.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/Messages.java
@@ -18,11 +18,13 @@
   public static String browseCustomPath;
   public static String codeGeneration;
   public static String compileOnSave;
+  public static String descriptorLocation;
   public static String editSelected;
   public static String editCodeGenerationOptionTitle;
   public static String enabled;
   public static String errorEnterDirectoryName;
   public static String errorInvalidProtoc;
+  public static String errorInvalidDescriptor;
   public static String errorNoLanguageEnabled;
   public static String errorNoOutputFolderName;
   public static String errorNoSelection;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/Messages.properties
index c4a7c60..c2b1083 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/Messages.properties
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/Messages.properties
@@ -1,11 +1,13 @@
 browseCustomPath=&Browse...
 codeGeneration=Code generation
 compileOnSave=Compile .proto files on &save
+descriptorLocation=\"descriptor.proto\" location
 editSelected=Edit selected...
 editCodeGenerationOptionTitle=Preferences for 
 enabled=Enabled
 errorEnterDirectoryName=Enter the name of the output directory
 errorInvalidProtoc=The selected file is not protoc
+errorInvalidDescriptor=The selected file is not descriptor.proto
 errorNoLanguageEnabled=Enable at least one language
 errorNoSelection=Select the path of protoc
 errorNoOutputFolderName=Enter the name of the output folder
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/RawPreferences.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/RawPreferences.java
index 6336819..356accb 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/RawPreferences.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/RawPreferences.java
@@ -21,6 +21,7 @@
   private final BooleanPreference useProtocInSystemPath;
   private final BooleanPreference useProtocInCustomPath;
   private final StringPreference protocPath;
+  private final StringPreference descriptorPath;
   private final BooleanPreference javaCodeGenerationEnabled;
   private final BooleanPreference cppCodeGenerationEnabled;
   private final BooleanPreference pythonCodeGenerationEnabled;
@@ -36,6 +37,7 @@
     useProtocInSystemPath = new BooleanPreference("compiler.useProtocInSystemPath", store);
     useProtocInCustomPath = new BooleanPreference("compiler.useProtocInCustomPath", store);
     protocPath = new StringPreference("compiler.protocFilePath", store);
+    descriptorPath = new StringPreference("compiler.descriptorFilePath", store);
     javaCodeGenerationEnabled = new BooleanPreference("compiler.javaCodeGenerationEnabled", store);
     cppCodeGenerationEnabled = new BooleanPreference("compiler.cppCodeGenerationEnabled", store);
     pythonCodeGenerationEnabled = new BooleanPreference("compiler.pythonCodeGenerationEnabled", store);
@@ -62,6 +64,10 @@
   StringPreference protocPath() {
     return protocPath;
   }
+  
+  StringPreference descriptorPath() {
+    return descriptorPath;
+  }
 
   BooleanPreference javaCodeGenerationEnabled() {
     return javaCodeGenerationEnabled;