在 Eclipse RCP 应用程序中创建新工作区时出错

Error in creating new workspace in Eclipse RCP application

在 Eclipse RCP 应用程序中创建新工作区时出现问题。

启动 RCP 应用程序时,会提示一个对话框询问工作区位置。 给出位置后,会出现错误 “无法启动产品,因为无法创建指定的工作区。 指定的工作区目录无效或只读。 我遵循了来自 eclipse IDEApplication.java 的代码,但我仍然面临同样的问题。

申请代码:

@SuppressWarnings("restriction")
public class MyRcpApplication implements IApplication
{

  private static final String METADATA_PROJECTS_PATH = "/.plugins/org.eclipse.core.resources/.projects";
  private static final String METADATA_ROOT = ".metadata";
  private static final String COMMAND_ARG = "--container";
  private static final String SYSTEM_PROPERTY_EXIT_CODE = "eclipse.exitcode";
  private static final String WORKSPACE_VERSION_KEY = "org.eclipse.core.runtime";
  private static final String VERSION_FILENAME = "version.ini";
  private static final String WORKSPACE_VERSION_VALUE = "1"; //$NON-NLS-1$

  public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$
  private Shell shell;

  /*
   * (non-Javadoc)
   * 
   * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
   */
  @Override
  public Object start(final IApplicationContext context)
  {

    Display display = PlatformUI.createDisplay();
    Shell shell = display.getActiveShell();
    try
    {
      // for backward compatibility we need to clear the workspace before start also
      cleanUpTheWorkSpace();
      boolean instanceLocationCheck = checkInstanceLocation(shell, context.getArguments());
      if (!instanceLocationCheck)
      {
        MessageDialog.openError(shell, IDEWorkbenchMessages.IDEApplication_workspaceInUseTitle,
            "Could not launch the product because the associated workspace is currently in use by another My Application.");
        return IApplication.EXIT_OK;
      }

      int returnCode = PlatformUI.createAndRunWorkbench(display, new MyApplicationWorkbenchAdvisor());
      if (returnCode == PlatformUI.RETURN_RESTART)
      {
        // eclipse.exitcode system property may be set to re-launch
        if (IApplication.EXIT_RELAUNCH.equals(Integer.getInteger(SYSTEM_PROPERTY_EXIT_CODE)))
        {
          return IApplication.EXIT_RELAUNCH;
        }

        return IApplication.EXIT_RESTART;
      }
      // if application return code is exit clean up the workspace
      // cleanUpTheWorkSpace();
      return IApplication.EXIT_OK;
    }
    finally
    {
      if (display != null)
      {
        display.dispose();
      }
      Location instanceLoc = Platform.getInstanceLocation();
      if (instanceLoc != null)
      {
        instanceLoc.release();
      }
    }
  }

  @SuppressWarnings("rawtypes")
  private boolean checkInstanceLocation(final Shell shell, final Map arguments)
  {
    Location instanceLoc = Platform.getInstanceLocation();
    if (instanceLoc == null)
    {
      MessageDialog.openError(shell, "Workspace is Mandatory", "IDEs need a valid workspace.");
      return false;
    }

    // -data "/valid/path", workspace already set
    if (instanceLoc.isSet())
    {

      // make sure the meta data version is compatible (or the user has
      // chosen to overwrite it).
      try
      {
        // Used to check whether are we launching My application from development environment or not
        if (isDevLaunchMode(arguments))
        {
          return true;
        }
        // Used to check instance location is locked or not
        if (instanceLoc.isLocked())
        {
          return false;
        }
        // we failed to create the directory.
        // Two possibilities:
        // 1. directory is already in use
        // 2. directory could not be created
        File workspaceDirectory = new File(instanceLoc.getURL().getFile());
        if (workspaceDirectory.exists())
        {
          if (isDevLaunchMode(arguments))
          {
            return true;
          }
          MessageDialog.openError(
              shell,
              "Workspace Cannot Be Locked",
              "Could not launch the product because the associated workspace at '" + workspaceDirectory.getAbsolutePath()
                  + "' is currently in use by another Eclipse application");

        }
        else
        {
          MessageDialog
              .openError(
                  shell,
                  "Workspace Cannot Be Created",
                  "Could not launch the product because the specified workspace cannot be created.  The specified workspace directory is either invalid or read-only.");
        }
      }
      catch (IOException e)
      {
        MessageDialog.openError(shell, "Internal Error", e.getMessage());
      }
    }
    else
    {
      try
      {
        // -data @noDefault or -data not specified, prompt and set
        ChooseWorkspaceData launchData = new ChooseWorkspaceData(instanceLoc.getDefault());
        boolean force = false;
        while (true)
        {
          URL workspaceUrl = promptForWorkspace(shell, launchData, force);
          if (workspaceUrl == null)
          {
            return false;
          }

          // if there is an error with the first selection, then force the
          // dialog to open to give the user a chance to correct
          force = true;

          try
          {
            // the operation will fail if the url is not a valid
            // instance data area, so other checking is unneeded
            if (instanceLoc.set(workspaceUrl, false))
            {
              launchData.writePersistedData();
              writeWorkspaceVersion(workspaceUrl);
              return true;
            }
          }
          catch (IllegalStateException e)
          {
            MessageDialog
                .openError(
                    shell,
                    IDEWorkbenchMessages
                    .IDEApplication_workspaceCannotBeSetTitle,
                    IDEWorkbenchMessages
                    .IDEApplication_workspaceCannotBeSetMessage);
            return false;
          }

          // by this point it has been determined that the workspace is
          // already in use -- force the user to choose again
          MessageDialog.openError(shell, IDEWorkbenchMessages
              .IDEApplication_workspaceInUseTitle,
              IDEWorkbenchMessages.
              IDEApplication_workspaceInUseMessage);
        }
      }

      catch (IllegalStateException | IOException e)
      {
      }
    }

    return true;
  }

  private static void writeWorkspaceVersion(final URL defaultValue)
  {
    Location instanceLoc = Platform.getInstanceLocation();
    if (instanceLoc.isReadOnly())
    {
      // MessageDialog.openError(shell,"Read-Only Dialog", "Location was read-only");
      System.out.println("Instance Got Locked......");
    }
    if ((instanceLoc == null) || instanceLoc.isReadOnly())
    {
      return;
    }

    File versionFile = getVersionFile(instanceLoc.getURL(), true);
    if (versionFile == null)
    {
      return;
    }

    OutputStream output = null;
    try
    {
      String versionLine = WORKSPACE_VERSION_KEY + '=' + WORKSPACE_VERSION_VALUE;

      output = new FileOutputStream(versionFile);
      output.write(versionLine.getBytes("UTF-8")); //$NON-NLS-1$
    }
    catch (IOException e)
    {
      IDEWorkbenchPlugin.log("Could not write version file", //$NON-NLS-1$
          StatusUtil.newStatus(IStatus.ERROR, e.getMessage(), e));
    }
    finally
    {
      try
      {
        if (output != null)
        {
          output.close();
        }
      }
      catch (IOException e)
      {
        // do nothing
      }
    }
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.eclipse.equinox.app.IApplication#stop()
   */
  @Override
  public void stop()
  {
    if (!PlatformUI.isWorkbenchRunning())
    {
      return;
    }
    final IWorkbench workbench = PlatformUI.getWorkbench();
    final Display display = workbench.getDisplay();
    display.syncExec(new Runnable()
    {
      @Override
      public void run()
      {
        if (!display.isDisposed())
        {
          workbench.close();
        }
      }
    });
  }

  private URL promptForWorkspace(final Shell shell, final ChooseWorkspaceData launchData, boolean force)
  {
    URL url = null;
    do
    {
      new ChooseWorkspaceDialog(shell, launchData, false, force).prompt(force);
      String instancePath = launchData.getSelection();
      if (instancePath == null)
      {
        return null;
      }

      // the dialog is not forced on the first iteration, but is on every
      // subsequent one -- if there was an error then the user needs to be
      // allowed to
      force = true;

      // create the workspace if it does not already exist
      File workspace = new File(instancePath);
      if (!workspace.exists())
      {
        workspace.mkdir();
      }

      try
      {
        // Don't use File.toURL() since it adds a leading slash that Platform does not
        // handle properly. See bug 54081 for more details.
        String path = workspace.getAbsolutePath().replace(File.separatorChar, '/');
        url = new URL("file", null, path); //$NON-NLS-1$
      }
      catch (MalformedURLException e)
      {
        MessageDialog
            .openError(
                shell,
                IDEWorkbenchMessages
                .IDEApplication_workspaceInvalidTitle,
                IDEWorkbenchMessages
                .IDEApplication_workspaceInvalidMessage);
        continue;
      }
    }
    while (!checkValidWorkspace(shell, url));

    return url;
  }

  private boolean checkValidWorkspace(final Shell shell, final URL url)
  {
    String version = readWorkspaceVersion(url);

    // if the version could not be read, then there is not any existing
    // workspace data to trample, e.g., perhaps its a new directory that
    // is just starting to be used as a workspace
    if (version == null)
    {
      return true;
    }

    final int ide_version = Integer.parseInt(WORKSPACE_VERSION_VALUE);
    int workspace_version = Integer.parseInt(version);

    // equality test is required since any version difference (newer
    // or older) may result in data being trampled
    if (workspace_version == ide_version)
    {
      return true;
    }

    // At this point workspace has been detected to be from a version
    // other than the current ide version -- find out if the user wants
    // to use it anyhow.
    String title = "My App Titile"; //$NON-NLS-1$
    String message = "My App Message";

    MessageBox mbox = new MessageBox(shell, SWT.OK | SWT.CANCEL
        | SWT.ICON_WARNING | SWT.APPLICATION_MODAL);
    mbox.setText(title);
    mbox.setMessage(message);
    return mbox.open() == SWT.OK;
  }

  private static String readWorkspaceVersion(final URL workspace)
  {
    File versionFile = getVersionFile(workspace, false);
    if ((versionFile == null) || !versionFile.exists())
    {
      return null;
    }

    try
    {
      // Although the version file is not spec'ed to be a Java properties
      // file, it happens to follow the same format currently, so using
      // Properties to read it is convenient.
      Properties props = new Properties();
      FileInputStream is = new FileInputStream(versionFile);
      try
      {
        props.load(is);
      }
      finally
      {
        is.close();
      }

      return props.getProperty(WORKSPACE_VERSION_KEY);
    }
    catch (IOException e)
    {
      IDEWorkbenchPlugin.log("Could not read version file", new Status( //$NON-NLS-1$
          IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH,
          IStatus.ERROR,
          e.getMessage() == null ? "" : e.getMessage(), //$NON-NLS-1$, 
          e));
      return null;
    }
  }

  private static File getVersionFile(final URL workspaceUrl, final boolean create)
  {
    if (workspaceUrl == null)
    {
      return null;
    }

    try
    {
      // make sure the directory exists
      File metaDir = new File(workspaceUrl.getPath(), METADATA_FOLDER);
      if (!metaDir.exists() && (!create || !metaDir.mkdir()))
      {
        return null;
      }

      // make sure the file exists
      File versionFile = new File(metaDir, VERSION_FILENAME);
      if (!versionFile.exists()
          && (!create || !versionFile.createNewFile()))
      {
        return null;
      }

      return versionFile;
    }
    catch (IOException e)
    {
      // cannot log because instance area has not been set
      return null;
    }
  }

  @SuppressWarnings("rawtypes")
  private static boolean isDevLaunchMode(final Map args)
  {
    // see org.eclipse.pde.internal.core.PluginPathFinder.isDevLaunchMode()
    if (Boolean.getBoolean("eclipse.pde.launch"))
    {
      return true;
    }
    return args.containsKey("-pdelaunch"); //$NON-NLS-1$
  }

  /**
   * Deletes all the available projects in the workspace
   */
  private void cleanUpTheWorkSpace()
  {
    // this will be the
    String[] commands = Platform.getCommandLineArgs();
    if (commands != null)
    {
      List<String> args = Arrays.asList(commands);
      if (args.contains(COMMAND_ARG))
      {
        // if project is in the root delete it.. it will delete associated metadata
        IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
        if (projects != null)
        {
          for (IProject project : projects)
          {
            try
            {
              project.delete(true, new NullProgressMonitor());
            }
            catch (CoreException e)
            {
              // msgHandler.post(MsgSeverity.ERROR, "Unable to clear the workspace");
            }
          }
        }
        // if project is not in the root but if its in the workspace delete the metadata too
        File[] workSpaceFiles = Platform.getLocation().toFile().listFiles();
        for (File file : workSpaceFiles)
        {
          if (METADATA_ROOT.equals(file.getName()))
          {
            File projectMeta = new File(file.getPath() + METADATA_PROJECTS_PATH);
            if ((projectMeta != null) && projectMeta.exists())
            {
              File[] children = projectMeta.listFiles();
              for (File child : children)
              {
                FileUtils.deleteQuietly(child);
              }
            }
          }

          /*
           * else { FileUtils.deleteQuietly(file); }
           */
        }
      }
    }
  }
}

您的代码只是调用

if (instanceLoc.isLocked())
 {
  return false;
 }

检查工作区是否被锁定,但没有采取任何措施使工作区锁定,因此这总是会导致错误代码。

IDEApplication 这样做:

if (instanceLoc.lock()) {
  writeWorkspaceVersion();
  return null;
}

你需要做类似的事情。

以管理员身份尝试 运行 Eclipse。