|
From: <caw...@us...> - 2007-01-15 03:00:48
|
Revision: 1765
http://svn.sourceforge.net/rubyeclipse/?rev=1765&view=rev
Author: cawilliams
Date: 2007-01-14 19:00:47 -0800 (Sun, 14 Jan 2007)
Log Message:
-----------
preliminary checkin of some in-progress work on hooking together loadpaths, interpreters and library containers
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/util/Util.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java
trunk/org.rubypeople.rdt.debug.core.tests/src/org/rubypeople/rdt/debug/core/tests/FTC_DebuggerLaunch.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/preferences/EditInterpreterDialog.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/preferences/RubyInterpreterLabelProvider.java
trunk/org.rubypeople.rdt.debug.ui.tests/src/org/rubypeople/rdt/internal/debug/ui/launcher/TC_RubyApplicationShortcut.java
trunk/org.rubypeople.rdt.launching/plugin.xml
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/DebuggerRunner.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RdtLaunchingMessages.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RdtLaunchingPlugin.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyInterpreter.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyRuntime.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/IInterpreter.java
trunk/org.rubypeople.rdt.launching.tests/src/org/rubypeople/rdt/internal/launching/TC_RubyInterpreter.java
trunk/org.rubypeople.rdt.launching.tests/src/org/rubypeople/rdt/internal/launching/TC_RubyRuntime.java
trunk/org.rubypeople.rdt.launching.tests/src/org/rubypeople/rdt/internal/launching/TC_RunnerLaunching.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/CompositeId.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyContainer.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyContainerInitializer.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/VMDefinitionsContainer.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/VMStandin.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/AbstractInterpreter.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/ExecutionArguments.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/IInterpreter2.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/IInterpreterInstallChangedListener.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/IInterpreterInstallType.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/IRubyLaunchConfigurationConstants.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/IVMRunner.java
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/PropertyChangeEvent.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -48,6 +48,7 @@
import org.rubypeople.rdt.internal.core.RubyModel;
import org.rubypeople.rdt.internal.core.RubyModelManager;
import org.rubypeople.rdt.internal.core.RubyProject;
+import org.rubypeople.rdt.internal.core.SetLoadpathOperation;
import org.rubypeople.rdt.internal.core.SymbolIndexResourceChangeListener;
import org.rubypeople.rdt.internal.core.builder.IndexUpdater;
import org.rubypeople.rdt.internal.core.builder.MassIndexUpdaterJob;
@@ -1098,5 +1099,155 @@
}
return null;
}
+
+ public static void setLoadpathContainer(final IPath containerPath, IRubyProject[] affectedProjects, ILoadpathContainer[] respectiveContainers, IProgressMonitor monitor) throws RubyModelException {
+ if (affectedProjects.length != respectiveContainers.length) Assert.isTrue(false, "Projects and containers collections should have the same size"); //$NON-NLS-1$
+
+ if (monitor != null && monitor.isCanceled()) return;
+
+ if (RubyModelManager.CP_RESOLVE_VERBOSE){
+ Util.verbose(
+ "CPContainer SET - setting container\n" + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " projects: {" +//$NON-NLS-1$
+ org.rubypeople.rdt.internal.compiler.util.Util.toString(
+ affectedProjects,
+ new org.rubypeople.rdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) { return ((IRubyProject) o).getElementName(); }
+ }) +
+ "}\n values: {\n" +//$NON-NLS-1$
+ org.rubypeople.rdt.internal.compiler.util.Util.toString(
+ respectiveContainers,
+ new org.rubypeople.rdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) {
+ StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
+ if (o == null) {
+ buffer.append("<null>"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ ILoadpathContainer container = (ILoadpathContainer) o;
+ buffer.append(container.getDescription());
+ buffer.append(" {\n"); //$NON-NLS-1$
+ ILoadpathEntry[] entries = container.getLoadpathEntries();
+ if (entries != null){
+ for (int i = 0; i < entries.length; i++){
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append(entries[i]);
+ buffer.append('\n');
+ }
+ }
+ buffer.append(" }"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ }) +
+ "\n }\n invocation stack trace:"); //$NON-NLS-1$
+ new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
+ }
+
+ RubyModelManager manager = RubyModelManager.getRubyModelManager();
+ if (manager.containerPutIfInitializingWithSameEntries(containerPath, affectedProjects, respectiveContainers))
+ return;
+
+ final int projectLength = affectedProjects.length;
+ final IRubyProject[] modifiedProjects;
+ System.arraycopy(affectedProjects, 0, modifiedProjects = new IRubyProject[projectLength], 0, projectLength);
+ final ILoadpathEntry[][] oldResolvedPaths = new ILoadpathEntry[projectLength][];
+
+ // filter out unmodified project containers
+ int remaining = 0;
+ for (int i = 0; i < projectLength; i++){
+
+ if (monitor != null && monitor.isCanceled()) return;
+
+ RubyProject affectedProject = (RubyProject) affectedProjects[i];
+ ILoadpathContainer newContainer = respectiveContainers[i];
+ if (newContainer == null) newContainer = RubyModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS; // 30920 - prevent infinite loop
+ boolean found = false;
+ if (RubyProject.hasRubyNature(affectedProject.getProject())){
+ ILoadpathEntry[] rawClasspath = affectedProject.getRawLoadpath();
+ for (int j = 0, cpLength = rawClasspath.length; j <cpLength; j++) {
+ ILoadpathEntry entry = rawClasspath[j];
+ if (entry.getEntryKind() == ILoadpathEntry.CPE_CONTAINER && entry.getPath().equals(containerPath)){
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found){
+ modifiedProjects[i] = null; // filter out this project - does not reference the container path, or isnt't yet Java project
+ manager.containerPut(affectedProject, containerPath, newContainer);
+ continue;
+ }
+ ILoadpathContainer oldContainer = manager.containerGet(affectedProject, containerPath);
+ if (oldContainer == RubyModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
+ oldContainer = null;
+ }
+ if (oldContainer != null && oldContainer.equals(respectiveContainers[i])){
+ modifiedProjects[i] = null; // filter out this project - container did not change
+ continue;
+ }
+ remaining++;
+ oldResolvedPaths[i] = affectedProject.getResolvedLoadpath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ manager.containerPut(affectedProject, containerPath, newContainer);
+ }
+
+ if (remaining == 0) return;
+
+ // trigger model refresh
+ try {
+ final boolean canChangeResources = !ResourcesPlugin.getWorkspace().isTreeLocked();
+ RubyCore.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor progressMonitor) throws CoreException {
+ for(int i = 0; i < projectLength; i++){
+
+ if (progressMonitor != null && progressMonitor.isCanceled()) return;
+
+ RubyProject affectedProject = (RubyProject)modifiedProjects[i];
+ if (affectedProject == null) continue; // was filtered out
+
+ if (RubyModelManager.CP_RESOLVE_VERBOSE){
+ Util.verbose(
+ "CPContainer SET - updating affected project due to setting container\n" + //$NON-NLS-1$
+ " project: " + affectedProject.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath); //$NON-NLS-1$
+ }
+
+ // force a refresh of the affected project (will compute deltas)
+ affectedProject.setRawLoadpath(
+ affectedProject.getRawLoadpath(),
+ SetLoadpathOperation.DO_NOT_SET_OUTPUT,
+ progressMonitor,
+ canChangeResources,
+ oldResolvedPaths[i],
+ false, // updating - no need for early validation
+ false); // updating - no need to save
+ }
+ }
+ },
+ null/*no need to lock anything*/,
+ monitor);
+ } catch(CoreException e) {
+ if (RubyModelManager.CP_RESOLVE_VERBOSE){
+ Util.verbose(
+ "CPContainer SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$
+ " container path: " + containerPath, //$NON-NLS-1$
+ System.err);
+ e.printStackTrace();
+ }
+ if (e instanceof RubyModelException) {
+ throw (RubyModelException)e;
+ } else {
+ throw new RubyModelException(e);
+ }
+ } finally {
+ for (int i = 0; i < projectLength; i++) {
+ if (respectiveContainers[i] == null) {
+ manager.containerPut(affectedProjects[i], containerPath, null); // reset init in progress marker
+ }
+ }
+ }
+
+ }
+
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/util/Util.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/util/Util.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/util/Util.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -7,6 +7,10 @@
public class Util {
+ public interface Displayable {
+ public String displayString(Object o);
+ }
+
private static final int DEFAULT_READING_SIZE = 8192;
public final static String UTF_8 = "UTF-8"; //$NON-NLS-1$
public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
@@ -28,6 +32,19 @@
}
/**
+ * Converts an array of Objects into String.
+ */
+ public static String toString(Object[] objects, Displayable renderer) {
+ if (objects == null) return ""; //$NON-NLS-1$
+ StringBuffer buffer = new StringBuffer(10);
+ for (int i = 0; i < objects.length; i++){
+ if (i > 0) buffer.append(", "); //$NON-NLS-1$
+ buffer.append(renderer.displayString(objects[i]));
+ }
+ return buffer.toString();
+ }
+
+ /**
* Returns the given input stream's contents as a byte array. If a length is
* specified (ie. if length != -1), only length bytes are returned.
* Otherwise all bytes in the stream are returned. Note this doesn't close
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -1568,5 +1568,93 @@
}
}
}
+
+ /*
+ * Optimize startup case where a container for 1 project is initialized at a time with the same entries as on shutdown.
+ */
+ public boolean containerPutIfInitializingWithSameEntries(IPath containerPath, IRubyProject[] projects, ILoadpathContainer[] respectiveContainers) {
+ int projectLength = projects.length;
+ if (projectLength != 1)
+ return false;
+ final ILoadpathContainer container = respectiveContainers[0];
+ if (container == null)
+ return false;
+ IRubyProject project = projects[0];
+ if (!containerInitializationInProgress(project).contains(containerPath))
+ return false;
+ ILoadpathContainer previousSessionContainer = getPreviousSessionContainer(containerPath, project);
+ final ILoadpathEntry[] newEntries = container.getLoadpathEntries();
+ if (previousSessionContainer == null)
+ if (newEntries.length == 0) {
+ containerPut(project, containerPath, container);
+ return true;
+ } else {
+ return false;
+ }
+ final ILoadpathEntry[] oldEntries = previousSessionContainer.getLoadpathEntries();
+ if (oldEntries.length != newEntries.length)
+ return false;
+ for (int i = 0, length = newEntries.length; i < length; i++) {
+ if (!newEntries[i].equals(oldEntries[i])) {
+ if (CP_RESOLVE_VERBOSE) {
+ Util.verbose(
+ "CPContainer SET - missbehaving container\n" + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " projects: {" +//$NON-NLS-1$
+ org.rubypeople.rdt.internal.compiler.util.Util.toString(
+ projects,
+ new org.rubypeople.rdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) { return ((IRubyProject) o).getElementName(); }
+ }) +
+ "}\n values on previous session: {\n" +//$NON-NLS-1$
+ org.rubypeople.rdt.internal.compiler.util.Util.toString(
+ respectiveContainers,
+ new org.rubypeople.rdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) {
+ StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
+ if (o == null) {
+ buffer.append("<null>"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ buffer.append(container.getDescription());
+ buffer.append(" {\n"); //$NON-NLS-1$
+ for (int j = 0; j < oldEntries.length; j++){
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append(oldEntries[j]);
+ buffer.append('\n');
+ }
+ buffer.append(" }"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ }) +
+ "}\n new values: {\n" +//$NON-NLS-1$
+ org.rubypeople.rdt.internal.compiler.util.Util.toString(
+ respectiveContainers,
+ new org.rubypeople.rdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) {
+ StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
+ if (o == null) {
+ buffer.append("<null>"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ buffer.append(container.getDescription());
+ buffer.append(" {\n"); //$NON-NLS-1$
+ for (int j = 0; j < newEntries.length; j++){
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append(newEntries[j]);
+ buffer.append('\n');
+ }
+ buffer.append(" }"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ }) +
+ "\n }"); //$NON-NLS-1$
+ }
+ return false;
+ }
+ }
+ containerPut(project, containerPath, container);
+ return true;
+ }
}
Modified: trunk/org.rubypeople.rdt.debug.core.tests/src/org/rubypeople/rdt/debug/core/tests/FTC_DebuggerLaunch.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.core.tests/src/org/rubypeople/rdt/debug/core/tests/FTC_DebuggerLaunch.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.debug.core.tests/src/org/rubypeople/rdt/debug/core/tests/FTC_DebuggerLaunch.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -1,13 +1,13 @@
package org.rubypeople.rdt.debug.core.tests;
import java.io.ByteArrayInputStream;
+import java.io.File;
import junit.framework.TestCase;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
@@ -36,7 +36,7 @@
// to be set accordingly
String rubyInterpreterPath = FTC_ClassicDebuggerCommunicationTest.RUBY_INTERPRETER ;
System.out.println("Using interpreter: " + rubyInterpreterPath) ;
- IInterpreter rubyInterpreter = new RubyInterpreter("RubyInterpreter", new Path(rubyInterpreterPath));
+ IInterpreter rubyInterpreter = new RubyInterpreter("RubyInterpreter", new File(rubyInterpreterPath));
RubyRuntime.getDefault().addInstalledInterpreter(rubyInterpreter) ;
}
Modified: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/preferences/EditInterpreterDialog.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/preferences/EditInterpreterDialog.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/preferences/EditInterpreterDialog.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -2,9 +2,7 @@
import java.io.File;
-import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
@@ -44,8 +42,8 @@
String interpreterName = interpreterToEdit.getName();
interpreterNameText.setText(interpreterName != null ? interpreterName : ""); //$NON-NLS-1$
- IPath installLocation = interpreterToEdit.getInstallLocation();
- interpreterLocationText.setText(installLocation != null ? installLocation.toOSString() : ""); //$NON-NLS-1$
+ File installLocation = interpreterToEdit.getInstallLocation();
+ interpreterLocationText.setText(installLocation != null ? installLocation.getAbsolutePath() : ""); //$NON-NLS-1$
}
protected void createLocationEntryField(Composite composite) {
@@ -145,7 +143,7 @@
interpreterToEdit = new RubyInterpreter(null, null);
interpreterToEdit.setName(interpreterNameText.getText());
- interpreterToEdit.setInstallLocation(new Path(interpreterLocationText.getText()));
+ interpreterToEdit.setInstallLocation(new File(interpreterLocationText.getText()));
super.okPressed();
}
protected Control createDialogArea(Composite parent) {
Modified: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/preferences/RubyInterpreterLabelProvider.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/preferences/RubyInterpreterLabelProvider.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/preferences/RubyInterpreterLabelProvider.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -1,6 +1,7 @@
package org.rubypeople.rdt.internal.debug.ui.preferences;
-import org.eclipse.core.runtime.IPath;
+import java.io.File;
+
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.swt.graphics.Image;
@@ -22,8 +23,8 @@
case 0 :
return interpreter.getName();
case 1 :
- IPath installLocation = interpreter.getInstallLocation();
- return installLocation != null ? installLocation.toOSString() : "In user path";
+ File installLocation = interpreter.getInstallLocation();
+ return installLocation != null ? installLocation.getAbsolutePath() : "In user path";
default :
return "Unknown Column Index";
}
Modified: trunk/org.rubypeople.rdt.debug.ui.tests/src/org/rubypeople/rdt/internal/debug/ui/launcher/TC_RubyApplicationShortcut.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui.tests/src/org/rubypeople/rdt/internal/debug/ui/launcher/TC_RubyApplicationShortcut.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.debug.ui.tests/src/org/rubypeople/rdt/internal/debug/ui/launcher/TC_RubyApplicationShortcut.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -25,7 +25,6 @@
import org.eclipse.ui.part.FileEditorInput;
import org.rubypeople.rdt.internal.debug.ui.RdtDebugUiPlugin;
import org.rubypeople.rdt.internal.debug.ui.RubySourceLocator;
-import org.rubypeople.rdt.internal.debug.ui.launcher.RubyApplicationShortcut;
import org.rubypeople.rdt.internal.launching.RubyInterpreter;
import org.rubypeople.rdt.internal.launching.RubyLaunchConfigurationAttribute;
import org.rubypeople.rdt.internal.launching.RubyRuntime;
@@ -98,7 +97,7 @@
Assert.assertEquals("All configurations deleted.", 0, this.getLaunchConfigurations().length);
ShamApplicationLaunchConfigurationDelegate.resetLaunches();
- IInterpreter interpreterOne = new RubyInterpreter("InterpreterOne", new Path("C:/RubyInstallRootOne"));
+ IInterpreter interpreterOne = new RubyInterpreter("InterpreterOne", new File("C:/RubyInstallRootOne"));
RubyRuntime.getDefault().setInstalledInterpreters(Arrays.asList(new IInterpreter[] { interpreterOne}));
}
Modified: trunk/org.rubypeople.rdt.launching/plugin.xml
===================================================================
--- trunk/org.rubypeople.rdt.launching/plugin.xml 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.launching/plugin.xml 2007-01-15 03:00:47 UTC (rev 1765)
@@ -19,6 +19,7 @@
<import plugin="org.rubypeople.rdt.core"/>
<import plugin="org.rubypeople.rdt.debug.core"/>
<import plugin="org.eclipse.core.runtime"/>
+ <import plugin="org.eclipse.core.variables"/>
</requires>
<extension
@@ -30,5 +31,19 @@
id="org.rubypeople.rdt.launching.LaunchConfigurationTypeRubyApplication">
</launchConfigurationType>
</extension>
+ <extension
+ point="org.rubypeople.rdt.core.loadpathVariableInitializer">
+ <classpathVariableInitializer
+ variable="RUBY_LIB"
+ class="org.rubypeople.jdt.internal.launching.RubyLoadpathVariablesInitializer">
+ </classpathVariableInitializer>
+ </extension>
+ <extension
+ point="org.rubypeople.rdt.core.loadpathContainerInitializer">
+ <classpathContainerInitializer
+ class="org.rubypeople.rdt.internal.launching.RubyContainerInitializer"
+ id="org.rubypeople.rdt.launching.RUBY_CONTAINER">
+ </classpathContainerInitializer>
+ </extension>
</plugin>
Added: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/CompositeId.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/CompositeId.java (rev 0)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/CompositeId.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.launching;
+
+import java.util.ArrayList;
+
+/**
+ * Utility class for id's made of multiple Strings
+ */
+public class CompositeId {
+ private String[] fParts;
+
+ public CompositeId(String[] parts) {
+ fParts= parts;
+ }
+
+ public static CompositeId fromString(String idString) {
+ ArrayList parts= new ArrayList();
+ int commaIndex= idString.indexOf(',');
+ while (commaIndex > 0) {
+ int length= Integer.valueOf(idString.substring(0, commaIndex)).intValue();
+ String part= idString.substring(commaIndex+1, commaIndex+1+length);
+ parts.add(part);
+ idString= idString.substring(commaIndex+1+length);
+ commaIndex= idString.indexOf(',');
+ }
+ String[] result= (String[])parts.toArray(new String[parts.size()]);
+ return new CompositeId(result);
+ }
+
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ for (int i= 0; i < fParts.length; i++) {
+ buf.append(fParts[i].length());
+ buf.append(',');
+ buf.append(fParts[i]);
+ }
+ return buf.toString();
+ }
+
+ public String get(int index) {
+ return fParts[index];
+ }
+
+ public int getPartCount() {
+ return fParts.length;
+ }
+}
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/DebuggerRunner.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/DebuggerRunner.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/DebuggerRunner.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -6,6 +6,7 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IProcess;
@@ -85,9 +86,9 @@
protected IInterpreter convertInterpreter(IInterpreter rubyInterpreter) {
if (isUseRubyDebug()) {
- IPath rdebugLocation = rubyInterpreter.getInstallLocation().removeLastSegments(1);
+ IPath rdebugLocation = new Path(rubyInterpreter.getInstallLocation().getAbsolutePath()).removeLastSegments(1);
rdebugLocation = rdebugLocation.append("rdebug");
- return new RubyInterpreter("rdebug", rdebugLocation);
+ return new RubyInterpreter("rdebug", rdebugLocation.toFile());
} else {
return rubyInterpreter;
}
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RdtLaunchingMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RdtLaunchingMessages.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RdtLaunchingMessages.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -11,6 +11,18 @@
public static String RdtLaunchingPlugin_noInterpreterSelected;
public static String RdtLaunchingPlugin_interpreterNotFound;
public static String RdtLaunchingPlugin_noInterpreterSelectedTitle;
+ public static String RubyRuntime_badFormat;
+ public static String RubyRuntime_VM_type_element_with_unknown_id_1;
+ public static String RubyRuntime_VM_element_specified_with_no_id_attribute_2;
+ public static String RubyRuntime_exceptionOccurred;
+ public static String vmInstall_assert_typeNotNull;
+ public static String vmInstall_assert_idNotNull;
+ public static String AbstractInterpreterInstall_0;
+ public static String AbstractInterpreterInstall_1;
+ public static String AbstractInterpreterInstall_3;
+ public static String AbstractInterpreterInstall_4;
+ public static String LaunchingPlugin_33;
+ public static String LaunchingPlugin_34;
private RdtLaunchingMessages() {}
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RdtLaunchingPlugin.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RdtLaunchingPlugin.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RdtLaunchingPlugin.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -1,14 +1,30 @@
package org.rubypeople.rdt.internal.launching;
+import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.osgi.framework.BundleContext;
import org.rubypeople.rdt.core.RubyCore;
+import org.w3c.dom.Document;
+import org.xml.sax.helpers.DefaultHandler;
public class RdtLaunchingPlugin extends Plugin {
public static final String PLUGIN_ID = "org.rubypeople.rdt.launching"; //$NON-NLS-1$
@@ -22,6 +38,7 @@
return aPath;
}
protected static RdtLaunchingPlugin plugin;
+ private static DocumentBuilder fgXMLParser;
public RdtLaunchingPlugin() {
super();
@@ -54,4 +71,79 @@
super.stop(arg0);
savePluginPreferences() ;
}
+
+ public static String getUniqueIdentifier() {
+ return PLUGIN_ID;
+ }
+
+ /**
+ * Returns a Document that can be used to build a DOM tree
+ * @return the Document
+ * @throws ParserConfigurationException if an exception occurs creating the document builder
+ */
+ public static Document getDocument() throws ParserConfigurationException {
+ DocumentBuilderFactory dfactory= DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder= dfactory.newDocumentBuilder();
+ Document doc= docBuilder.newDocument();
+ return doc;
+ }
+
+ /**
+ * Serializes a XML document into a string - encoded in UTF8 format,
+ * with platform line separators.
+ *
+ * @param doc document to serialize
+ * @return the document as a string
+ */
+ public static String serializeDocument(Document doc) throws IOException, TransformerException {
+ ByteArrayOutputStream s= new ByteArrayOutputStream();
+
+ TransformerFactory factory= TransformerFactory.newInstance();
+ Transformer transformer= factory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+
+ DOMSource source= new DOMSource(doc);
+ StreamResult outputTarget= new StreamResult(s);
+ transformer.transform(source, outputTarget);
+
+ return s.toString("UTF8"); //$NON-NLS-1$
+ }
+
+ public static void log(String message) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null));
+ }
+
+ /**
+ * Returns a shared XML parser.
+ *
+ * @return an XML parser
+ * @throws CoreException if unable to create a parser
+ * @since 3.0
+ */
+ public static DocumentBuilder getParser() throws CoreException {
+ if (fgXMLParser == null) {
+ try {
+ fgXMLParser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ fgXMLParser.setErrorHandler(new DefaultHandler());
+ } catch (ParserConfigurationException e) {
+ abort(RdtLaunchingMessages.LaunchingPlugin_33, e);
+ } catch (FactoryConfigurationError e) {
+ abort(RdtLaunchingMessages.LaunchingPlugin_34, e);
+ }
+ }
+ return fgXMLParser;
+ }
+
+ /**
+ * Throws an exception with the given message and underlying exception.
+ *
+ * @param message error message
+ * @param exception underlying exception or <code>null</code> if none
+ * @throws CoreException
+ */
+ protected static void abort(String message, Throwable exception) throws CoreException {
+ IStatus status = new Status(IStatus.ERROR, RdtLaunchingPlugin.getUniqueIdentifier(), 0, message, exception);
+ throw new CoreException(status);
+ }
}
Added: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyContainer.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyContainer.java (rev 0)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyContainer.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -0,0 +1,85 @@
+package org.rubypeople.rdt.internal.launching;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IPath;
+import org.rubypeople.rdt.core.ILoadpathContainer;
+import org.rubypeople.rdt.core.ILoadpathEntry;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.launching.IInterpreter;
+import org.rubypeople.rdt.launching.IInterpreterInstallChangedListener;
+import org.rubypeople.rdt.launching.PropertyChangeEvent;
+
+public class RubyContainer implements ILoadpathContainer {
+
+ private static Map fgLoadpathEntries;
+ private IInterpreter fInterpreter;
+
+ public RubyContainer(IInterpreter interpreter, IPath containerPath) {
+ fInterpreter = interpreter;
+ }
+
+ public String getDescription() {
+ return "Ruby System Library";
+ }
+
+ public ILoadpathEntry[] getLoadpathEntries() {
+ return getLoadpathEntries(fInterpreter);
+ }
+
+ /**
+ * Returns the loadpath entries associated with the given VM.
+ *
+ * @param vm
+ * @return loadpath entries
+ */
+ private static ILoadpathEntry[] getLoadpathEntries(IInterpreter vm) {
+ if (fgLoadpathEntries == null) {
+ fgLoadpathEntries = new HashMap(10);
+ // add a listener to clear cached value when a VM changes or is removed
+ IInterpreterInstallChangedListener listener = new IInterpreterInstallChangedListener() {
+ public void defaultInterpreterInstallChanged(IInterpreter previous, IInterpreter current) {
+ }
+
+ public void interpreterChanged(PropertyChangeEvent event) {
+ if (event.getSource() != null) {
+ fgLoadpathEntries.remove(event.getSource());
+ }
+ }
+
+ public void interpreterAdded(IInterpreter newVm) {
+ }
+
+ public void interpreterRemoved(IInterpreter removedVm) {
+ fgLoadpathEntries.remove(removedVm);
+ }
+ };
+ RubyRuntime.addInterpreterInstallChangedListener(listener);
+ }
+ ILoadpathEntry[] entries = (ILoadpathEntry[])fgLoadpathEntries.get(vm);
+ if (entries == null) {
+ entries = computeLoadpathEntries(vm);
+ fgLoadpathEntries.put(vm, entries);
+ }
+ return entries;
+ }
+
+ /**
+ * Computes the loadpath entries associated with a VM - one entry per library.
+ *
+ * @param vm
+ * @return loadpath entries
+ */
+ private static ILoadpathEntry[] computeLoadpathEntries(IInterpreter vm) {
+ IPath[] libs = vm.getLibraryLocations();
+ List entries = new ArrayList(libs.length);
+ for (int i = 0; i < libs.length; i++) {
+ entries.add(RubyCore.newLibraryEntry(libs[i], false));
+ }
+ return (ILoadpathEntry[])entries.toArray(new ILoadpathEntry[entries.size()]);
+ }
+
+}
Added: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyContainerInitializer.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyContainerInitializer.java (rev 0)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyContainerInitializer.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -0,0 +1,73 @@
+package org.rubypeople.rdt.internal.launching;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.rubypeople.rdt.core.ILoadpathContainer;
+import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.LoadpathContainerInitializer;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.launching.IInterpreter;
+import org.rubypeople.rdt.launching.IInterpreterInstallType;
+
+public class RubyContainerInitializer extends LoadpathContainerInitializer {
+
+ @Override
+ public void initialize(IPath containerPath, IRubyProject project)
+ throws CoreException {
+ int size = containerPath.segmentCount();
+ if (size > 0) {
+ if (containerPath.segment(0).equals(RubyRuntime.RUBY_CONTAINER)) {
+ IInterpreter vm = resolveInterpreter(containerPath);
+ RubyContainer container = null;
+ if (vm != null) {
+ container = new RubyContainer(vm, containerPath);
+ }
+ RubyCore.setLoadpathContainer(containerPath,
+ new IRubyProject[] { project },
+ new ILoadpathContainer[] { container }, null);
+ }
+ }
+
+ }
+
+ /**
+ * Returns the VM install associated with the container path, or
+ * <code>null</code> if it does not exist.
+ */
+ public static IInterpreter resolveInterpreter(IPath containerPath) {
+ IInterpreter vm = null;
+ if (containerPath.segmentCount() > 1) {
+ // specific Ruby VM
+ String vmTypeId = getInterpreterTypeId(containerPath);
+ String vmName = getInterpreterName(containerPath);
+ IInterpreterInstallType vmType = RubyRuntime
+ .getInterpreterInstallType(vmTypeId);
+ if (vmType != null) {
+ vm = vmType.findInterpreterInstallByName(vmName);
+ }
+ } else {
+ // workspace default Ruby VM
+ vm = RubyRuntime.getDefaultInterpreterInstall();
+ }
+ return vm;
+ }
+
+ /**
+ * Returns the VM type identifier from the given container ID path.
+ *
+ * @return the VM type identifier from the given container ID path
+ */
+ public static String getInterpreterTypeId(IPath path) {
+ return path.segment(1);
+ }
+
+ /**
+ * Returns the VM name from the given container ID path.
+ *
+ * @return the VM name from the given container ID path
+ */
+ public static String getInterpreterName(IPath path) {
+ return path.segment(2);
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyInterpreter.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyInterpreter.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyInterpreter.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -11,20 +11,22 @@
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.rubypeople.rdt.launching.IInterpreter;
+import org.rubypeople.rdt.launching.IInterpreterInstallType;
+import org.rubypeople.rdt.launching.IVMRunner;
public class RubyInterpreter implements IInterpreter {
public static final String END_OF_OPTIONS_DELIMITER = "--";
- protected IPath installLocation;
+ protected File installLocation;
protected String name;
private final CommandExecutor commandExecutor;
- public RubyInterpreter(String aName, IPath validInstallLocation) {
+ public RubyInterpreter(String aName, File validInstallLocation) {
this(aName, validInstallLocation, new StandardCommandExecutor());
}
- public RubyInterpreter(String aName, IPath validInstallLocation, CommandExecutor commandExecutor) {
+ public RubyInterpreter(String aName, File validInstallLocation, CommandExecutor commandExecutor) {
name = aName;
installLocation = validInstallLocation;
this.commandExecutor = commandExecutor;
@@ -33,18 +35,11 @@
/* (non-Javadoc)
* @see org.rubypeople.rdt.internal.launching.IInterpreter#getInstallLocation()
*/
- public IPath getInstallLocation() {
+ public File getInstallLocation() {
return installLocation;
}
/* (non-Javadoc)
- * @see org.rubypeople.rdt.internal.launching.IInterpreter#setInstallLocation(org.eclipse.core.runtime.IPath)
- */
- public void setInstallLocation(IPath validInstallLocation) {
- installLocation = validInstallLocation;
- }
-
- /* (non-Javadoc)
* @see org.rubypeople.rdt.internal.launching.IInterpreter#getName()
*/
public String getName() {
@@ -59,8 +54,8 @@
}
public String getCommand() throws IllegalCommandException {
- if( new File(installLocation.toOSString()).isFile() ){
- return installLocation.toOSString();
+ if( installLocation.isFile() ){
+ return installLocation.getAbsolutePath();
}
String errorMessage = MessageFormat.format(RdtLaunchingMessages.RdtLaunchingPlugin_interpreterNotFound, new Object[] {this.getName()}) ;
throw new IllegalCommandException(errorMessage) ;
@@ -95,4 +90,43 @@
return false;
}
+
+ public String getId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String[] getInterpreterArguments() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public IInterpreterInstallType getInterpreterInstallType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public IVMRunner getInterpreterRunner(String mode) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public IPath[] getLibraryLocations() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setInstallLocation(File validInstallLocation) {
+ this.installLocation = validInstallLocation;
+ }
+
+ public void setInterpreterArguments(String[] vmArgs) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setLibraryLocations(IPath[] paths) {
+ // TODO Auto-generated method stub
+
+ }
}
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyRuntime.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyRuntime.java 2007-01-11 14:55:22 UTC (rev 1764)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyRuntime.java 2007-01-15 03:00:47 UTC (rev 1765)
@@ -1,7 +1,9 @@
package org.rubypeople.rdt.internal.launching;
import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
@@ -10,16 +12,33 @@
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
+import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.variables.VariablesPlugin;
import org.rubypeople.rdt.launching.IInterpreter;
+import org.rubypeople.rdt.launching.IInterpreterInstallChangedListener;
+import org.rubypeople.rdt.launching.IInterpreterInstallType;
+import org.rubypeople.rdt.launching.IRubyLaunchConfigurationConstants;
+import org.rubypeople.rdt.launching.PropertyChangeEvent;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
@@ -32,9 +51,56 @@
private static final String ATTR_PATH = "path";
private static final String ATTR_NAME = "name";
private static final String ATTR_SELECTED = "selected";
+
+ /**
+ * Loadpath container used for a project's Ruby
+ * (value <code>"org.rubypeople.rdt.launching.RUBY_CONTAINER"</code>). A
+ * container is resolved in the context of a specific Ruby project, to one
+ * or more system libraries contained in the Ruby std library. The container can have zero
+ * or two path segments following the container name. When no segments
+ * follow the container name, the workspace default Ruby is used to build a
+ * project. Otherwise the segments identify a specific Ruby used to build a
+ * project:
+ * <ol>
+ * <li>VM Install Type Identifier - identifies the type of Ruby VM used to build the
+ * project. For example, the standard VM.</li>
+ * <li>VM Install Name - a user defined name that identifies that a specific VM
+ * of the above kind. For example, <code>JRuby 1.8.4</code>. This information is
+ * shared in a projects loadpath file, so teams must agree on Ruby VM naming
+ * conventions.</li>
+ * </ol>
+ * @since 0.9.0
+ */
+ public static final String RUBY_CONTAINER = RdtLaunchingPlugin.getUniqueIdentifier() + "RUBY_CONTAINER"; //$NON-NLS-1$
+
+ /**
+ * Preference key for the String of XML that defines all installed VMs.
+ *
+ * @since 0.9.0
+ */
+ public static final String PREF_VM_XML = RdtLaunchingPlugin.getUniqueIdentifier() + ".PREF_VM_XML"; //$NON-NLS-1$
+ /**
+ * Simple identifier constant (value <code>"vmInstalls"</code>) for the
+ * VM installs extension point.
+ *
+ * @since 0.9.0
+ */
+ public static final String EXTENSION_POINT_VM_INSTALLS = "vmInstalls"; //$NON-NLS-1$
+
+ private static IInterpreterInstallType[] fgInterpreterTypes= null;
+
protected static RubyRuntime runtime;
+ private static Object fgVMLock = new Object();
+ private static boolean fgInitializingVMs;
+ private static String fgDefaultVMId;
+ private static String fgDefaultVMConnectorId;
+ /**
+ * Set of IDs of VMs contributed via vmInstalls extension point.
+ */
+ private static Set fgContributedVMs = new HashSet();
+
protected List<IInterpreter> installedInterpreters;
protected IInterpreter selectedInterpreter;
private List<Listener> listeners = new ArrayList<Listener>();
@@ -144,11 +210,11 @@
}
private void autoDetectRubyInterpreter() {
- IPath path = null;
+ File path = null;
if (Platform.getOS().equals(Platform.OS_WIN32)) {
- path = new Path("/ruby/bin/ruby.exe");
+ path = new File("/ruby/bin/ruby.exe");
} else {
- path = new Path("/usr/local/bin/ruby");
+ path = new File("/usr/local/bin/ruby");
}
IInterpreter interpreter = new RubyInterpreter("Default Ruby Interpreter", path);
installedInterpreters.add(interpreter);
@@ -206,7 +272,7 @@
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
if (TAG_INTERPRETER.equals(qName)) {
String interpreterName = atts.getValue(ATTR_NAME);
- IPath installLocation = new Path(atts.getValue(ATTR_PATH));
+ File installLocation = new File(atts.getValue(ATTR_PATH));
IInterpreter interpreter = new RubyInterpreter(interpreterName, installLocation);
installedInterpreters.add(interpreter);
if (atts.getValue(ATTR_SELECTED) != null)
@@ -226,4 +292,368 @@
IPath fileLocation = stateLocation.append("runtimeConfiguration.xml");
return new File(fileLocation.toOSString());
}
+
+ public static void addInterpreterInstallChangedListener(IInterpreterInstallChangedListener listener) {
+ // TODO Implement and add to listeners, and replace the addListener(Listener) stuff
+
+ }
+ /**
+ * Returns the VM install type with the given unique id.
+ * @param id the VM install type unique id
+ * @return The VM install type for the given id, or <code>null</code> if no
+ * VM install type with the given id is registered.
+ */
+ public static IInterpreterInstallType getInterpreterInstallType(String id) {
+ IInterpreterInstallType[] vmTypes= getInterpreterInstallTypes();
+ for (int i= 0; i < vmTypes.length; i++) {
+ if (vmTypes[i].getId().equals(id)) {
+ return vmTypes[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the list of registered VM types. VM types are registered via
+ * <code>"org.rubypeople.rdt.launching.vmTypes"</code> extension point.
+ * Returns an empty list if there are no registered VM types.
+ *
+ * @return the list of registered VM types
+ */
+ public static IInterpreterInstallType[] getInterpreterInstallTypes() {
+ initializeInterpreters();
+ return fgInterpreterTypes;
+ }
+
+ public static IInterpreter getDefaultInterpreterInstall() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * Perform VM type and VM install initialization. Does not hold locks
+ * while performing change notification.
+ *
+ * @since 3.2
+ */
+ private static void initializeInterpreters() {
+ VMDefinitionsContainer vmDefs = null;
+ boolean setPref = false;
+ boolean updateCompliance = false;
+ synchronized (fgVMLock) {
+ if (fgInterpreterTypes == null) {
+ try {
+ fgInitializingVMs = true;
+ // 1. load VM type extensions
+ initializeVMTypeExtensions();
+ try {
+ vmDefs = new VMDefinitionsContainer();
+ // 2. add persisted VMs
+ setPref = addPersistedVMs(vmDefs);
+
+ // 3. load contributed VM installs
+ addVMExtensions(vmDefs);
+ // 4. verify default VM is valid
+ String defId = vmDefs.getDefaultVMInstallCompositeID();
+ boolean validDef = false;
+ if (defId != null) {
+ Iterator iterator = vmDefs.getValidVMList().iterator();
+ while (iterator.hasNext()) {
+ IInterpreter vm = (IInterpreter) iterator.next();
+ if (getCompositeIdFromVM(vm).equals(defId)) {
+ validDef = true;
+ break;
+ }
+ }
+ }
+ if (!validDef) {
+ // use the first as the default
+ setPref = true;
+ List list = vmDefs.getValidVMList();
+ if (!list.isEmpty()) {
+ IInterpreter vm = (IInterpreter) list.get(0);
+ vmDefs.setDefaultVMInstallCompositeID(getCompositeIdFromVM(vm));
+ }
+ }
+ fgDefaultVMId = vmDefs.getDefaultVMInstallCompositeID();
+ fgDefaultVMConnectorId = vmDefs.getDefaultVMInstallConnectorTypeID();
+
+ // Create the underlying VMs for each valid VM
+ List vmList = vmDefs.getValidVMList();
+ Iterator vmListIterator = vmList.iterator();
+ while (vmListIterator.hasNext()) {
+ VMStandin vmStandin = (VMStandin) vmListIterator.next();
+ vmStandin.convertToRealVM();
+ }
+
+
+ } catch (IOException e) {
+ RdtLaunchingPlugin.log(e);
+ }
+ } finally {
+ fgInitializingVMs = false;
+ }
+ }
+ }
+ if (vmDefs != null) {
+ // notify of initial VMs for backwards compatibility
+ IInterpreterInstallType[] installTypes = getInterpreterInstallTypes();
+ for (int i = 0; i < installTypes.length; i++) {
+ IInterpreterInstallType type = installTypes[i];
+ IInterpreter[] installs = type.getInterpreterInstalls();
+ for (int j = 0; j < installs.length; j++) {
+ fireInterpreterAdded(installs[j]);
+ }
+ }
+
+ // save settings if required
+ if (setPref) {
+ try {
+ String xml = vmDefs.getAsXML();
+ RdtLaunchingPlugin.getDefault().getPluginPreferences().setValue(PREF_VM_XML, xml);
+ } catch (ParserConfigurationException e) {
+ RdtLaunchingPlugin.log(e);
+ } catch (IOException e) {
+ RdtLaunchingPlugin.log(e);
+ } catch (TransformerException e) {
+ RdtLaunchingPlugin.log(e);
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Initializes vm type extensions.
+ */
+ private static void initializeVMTypeExtensions() {
+ IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(RdtLaunchingPlugin.PLUGIN_ID, "vmInstallTypes"); //$NON-NLS-1$
+ IConfigurationElement[] configs= extensionPoint.getConfigurationElements();
+ MultiStatus status= new MultiStatus(RdtLaunchingPlugin.getUniqueIdentifier(), IStatus.OK, RdtLaunchingMessages.RubyRuntime_exceptionOccurred, null);
+ fgInterpreterTypes= new IInterpreterInstallType[configs.length];
+
+ for (int i= 0; i < configs.length; i++) {
+ try {
+ IInterpreterInstallType vmType= (IInterpreterInstallType)configs[i].createExecutableExtension("class"); //$NON-NLS-1$
+ fgInterpreterTypes[i]= vmType;
+ } catch (CoreException e) {
+ status.add(e.getStatus());
+ }
+ }
+ if (!status.isOK()) {
+ //only happens on a CoreException
+ RdtLaunchingPlugin.log(status);
+ //cleanup null entries in fgVMTypes
+ List temp= new ArrayList(fgInterpreterTypes.length);
+ for (int i = 0; i < fgInterpreterTypes.length; i++) {
+ if(fgInterpreterTypes[i] != null) {
+ temp.add(fgInterpreterTypes[i]);
+ }
+ fgInterpreterTypes= new IInterpreterInstallType[temp.size()];
+ fgInterpreterTypes= (IInterpreterInstallType[])temp.toArray(fgInterpreterTypes);
+ }
+ }
+ }
+
+ /**
+ * This method loads installed JREs based an existing user preference
+ * or old vm configurations file. The VMs found in the preference
+ * or vm configurations file are added to the given VM definitions container.
+ *
+ * Returns whether the user preferences should be set - i.e. if it was
+ * not already set when initialized.
+ */
+ private static boolean addPersistedVMs(VMDefinitionsContainer vmDefs) throws IOException {
+ // Try retrieving the VM preferences from the preference store
+ String vmXMLString = getPreferences().getString(PREF_VM_XML);
+
+ // If the preference was found, load VMs from it into memory
+ if (vmXMLString.length() > 0) {
+ try {
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(vmXMLString.getBytes());
+ VMDefinitionsContainer.parseXMLIntoContainer(inputStream, vmDefs);
+ return false;
+ } catch (IOException ioe) {
+ RdtLaunchingPlugin.log(ioe);
+ }
+ } else {
+ // Otherwise, look for the old file that previously held the VM definitions
+ IPath stateLocation= RdtLaunchingPlugin.getDefault().getStateLocation();
+ IPath stateFile= stateLocation.append("vmConfiguration.xml"); //$NON-NLS-1$
+ File file = new File(stateFile.toOSString());
+
+ if (file.exists()) {
+ // If file exists, load VM definitions from it into memory and write the definitions to
+ // the preference store WITHOUT triggering any processing of the new value
+ FileInputStream fileInputStream = new FileInputStream(file);
+ VMDefinitionsContainer.parseXMLIntoContainer(fileInputStream, vmDefs);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the preference store for the launching plug-in.
+ *
+ * @return the preference store for the launching plug-in
+ * @since 0.9.0
+ */
+ public static Preferences getPreferences() {
+ return RdtLaunchingPlugin.getDefault().getPluginPreferences();
+ }
+
+ /**
+ * Returns a String that uniquely identifies the specified VM across all VM types.
+ *
+ * @param vm the instance of IVMInstallType to be identified
+ *
+ * @since 2.1
+ */
+ public static String getCompositeIdFromVM(IInterpreter vm) {
+ if (vm == null) {
+ return null;
+ }
+ IInterpreterInstallType vmType= vm.getInterpreterInstallType();
+ String typeID= vmType.getId();
+ CompositeId id= new CompositeId(new String[] { typeID, vm.getId() });
+ return id.toString();
+ }
+
+ /**
+ * Loads contributed VM installs
+ * @since 3.2
+ */
+ private static void addVMExtensions(VMDefinitionsContainer vmDefs) {
+ IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(RdtLaunchingPlugin.PLUGIN_ID, RubyRuntime.EXTENSION_POINT_VM_INSTALLS);
+ IConfigurationElement[] configs= extensionPoint.getConfigurationElements();
+ for (int i = 0; i < configs.length; i++) {
+ IConfigurationElement element = configs[i];
+ try {
+ if ("vmInstall".equals(element.getName())) { //$NON-NLS-1$
+ String vmType = element.getAttribute("vmInstallType"); //$NON-NLS-1$
+ if (vmType == null) {
+ abort(MessageFormat.format("Missing required vmInstallType attribute for vmInstall contributed by {0}", //$NON-NLS-1$
+ new String[]{element.getContributor().getName()}), null);
+ }
+ String id = element.getAttribute("id"); //$NON-NLS-1$
+ if (id == null) {
+ abort(MessageFormat.format("Missing required id attribute for vmInstall contributed by {0}", //$NON-NLS-1$
+ new String[]{element.getContributor().getName()}), null);
+ }
+ IInterpreterInstallType installType = getInterpreterInstallType(vmType);
+ if (installType == null) {
+ abort(MessageFormat.format("vmInstall {0} contributed by {1} references undefined VM install type {2}", //$NON-NLS-1$
+ new String[]{id, element.getContributor().getName(), vmType}), null);
+ }
+ IInterpreter install = installType.findInterpreterInstall(id);
+ if (install == null) {
+ // only load/create if first time we've seen this VM install
+ String name = element.getAttribute("name"); //$NON-NLS-1$
+ if (name == null) {
+ abort(MessageFormat.format("vmInstall {0} contributed by {1} missing required attribute name", //$NON-NLS-1$
+ new String[]{id, element.getContributor().getName()}), null);
+ }
+ String home = element.getAttribute("home"); //$NON-NLS-1$
+ if (home == null) {
+ abort(MessageFormat.format("vmInstall {0} contributed by {1} missing required attribute home", //$NON-NLS-1$
+ new String[]{id, element.getContributor().getName()}), null);
+ }
+ String vmArgs = element.getAttribute("vmArgs"); //$NON-NLS-1$
+ VMStandin standin = new VMStandin(installType, id);
+ standin.setName(name);
+ home = substitute(home);
+ File homeDir = new File(home);
+ if (homeDir.exists()) {
+ try {
+ // adjust for relative path names
+ home = homeDir.getCanonicalPath();
+ homeDir = new File(home);
+ } catch (IOException e) {
+ }
+ }
+ IStatus status = installType.validateInstallLocation(homeDir);
+ if (!status.isOK()) {
+ abort(MessageFormat.format("Illegal install location {0} for vmInstall {1} contributed by {2}: {3}", //$NON-NLS-1$
+ new String[]{home, id, element.getContributor().getName(), status.getMessage()}), null);
+ }
+ standin.setInstallLocation(homeDir);
+ if (vmArgs != null) {
+ standin.setVMArgs(vmArgs);
+ }
+ IConfigurationElement[] libraries = element.getChildren("library"); //$NON-NLS-1$
+ IPath[] locations = null;
+ if (libraries.length > 0) {
+ locations = new IPath[libraries.length];
+ for (int j = 0; j < libraries.length; j++) {
+ IConfigurationElement library = libraries[j];
+ String libPathStr = library.getAttribute("path"); //$NON-NLS-1$
+ if (libPathStr == null) {
+ abort(MessageFormat.format("library for vmInstall {0} contributed by {1} missing required attribute libPath", //$NON-NLS-1$
+ new String[]{id, element.getContributor().getName()}), null);
+ }
+
+ IPath homePath = new Path(home);
+ IPath libPath = homePath.append(substitute(libPathStr));
+ locations[j] = libPath;
+ }
+ }
+ standin.setLibraryLocations(locations);
+ vmDefs.addVM(standin);
+ }
+ fgC...
[truncated message content] |