|
From: <caw...@us...> - 2007-01-18 16:30:23
|
Revision: 1801
http://svn.sourceforge.net/rubyeclipse/?rev=1801&view=rev
Author: cawilliams
Date: 2007-01-18 08:30:20 -0800 (Thu, 18 Jan 2007)
Log Message:
-----------
fixing the loadpathVariableInitializer stuff
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/schema/loadpathVariableInitializer.exsd
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.launching/src/org/rubypeople/rdt/launching/RubyRuntime.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyLoadpathVariablesInitializer.java
Modified: trunk/org.rubypeople.rdt.core/schema/loadpathVariableInitializer.exsd
===================================================================
--- trunk/org.rubypeople.rdt.core/schema/loadpathVariableInitializer.exsd 2007-01-18 16:05:57 UTC (rev 1800)
+++ trunk/org.rubypeople.rdt.core/schema/loadpathVariableInitializer.exsd 2007-01-18 16:30:20 UTC (rev 1801)
@@ -3,7 +3,7 @@
<schema targetNamespace="org.rubypeople.rdt.core">
<annotation>
<appInfo>
- <meta.schema plugin="org.rubypeople.rdt.core" id="loadpathVariableInitializer" name="loadpathVariableInitializer"/>
+ <meta.schema plugin="org.rubypeople.rdt.core" id="loadpathVariableInitializer" name="Loadpath Variable Initializers"/>
</appInfo>
<documentation>
This extension point allows clients to contribute custom loadpath variable initializers,
@@ -13,7 +13,8 @@
<element name="extension">
<complexType>
- <sequence minOccurs="0" maxOccurs="unbounded">
+ <sequence>
+ <element ref="loadpathVariableInitializer" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
@@ -58,7 +59,7 @@
This class must implement a public subclass of &lt;code&gt;org.rubypeople.rdt.core.LoadpathVariableInitializer&lt;/code&gt; with a public 0-argument constructor.
</documentation>
<appInfo>
- <meta.attribute kind="ruby" basedOn="org.rubypeople.rdt.core.LoadpathVariableInitializer"/>
+ <meta.attribute kind="java" basedOn="org.rubypeople.rdt.core.LoadpathVariableInitializer"/>
</appInfo>
</annotation>
</attribute>
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-18 16:05:57 UTC (rev 1800)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/RubyCore.java 2007-01-18 16:30:20 UTC (rev 1801)
@@ -1250,4 +1250,66 @@
}
+ /**
+ * Sets the value of the given classpath variable.
+ * The path must not be null.
+ * <p>
+ * This functionality cannot be used while the resource tree is locked.
+ * <p>
+ * Classpath variable values are persisted locally to the workspace, and
+ * are preserved from session to session.
+ * <p>
+ * Updating a variable with the same value has no effect.
+ *
+ * @param variableName the name of the classpath variable
+ * @param path the path
+ * @param monitor a monitor to report progress
+ * @throws RubyModelException
+ * @see #getLoadpathVariable(String)
+ */
+ public static void setLoadpathVariable(
+ String variableName,
+ IPath path,
+ IProgressMonitor monitor)
+ throws RubyModelException {
+
+ if (path == null) Assert.isTrue(false, "Variable path cannot be null"); //$NON-NLS-1$
+ setLoadpathVariables(new String[]{variableName}, new IPath[]{ path }, monitor);
+ }
+
+ /**
+ * Sets the values of all the given classpath variables at once.
+ * Null paths can be used to request corresponding variable removal.
+ * <p>
+ * A combined Java element delta will be notified to describe the corresponding
+ * classpath changes resulting from the variables update. This operation is batched,
+ * and automatically eliminates unnecessary updates (new variable is same as old one).
+ * This operation acquires a lock on the workspace's root.
+ * <p>
+ * This functionality cannot be used while the workspace is locked, since
+ * it may create/remove some resource markers.
+ * <p>
+ * Classpath variable values are persisted locally to the workspace, and
+ * are preserved from session to session.
+ * <p>
+ * Updating a variable with the same value has no effect.
+ *
+ * @param variableNames an array of names for the updated classpath variables
+ * @param paths an array of path updates for the modified classpath variables (null
+ * meaning that the corresponding value will be removed
+ * @param monitor a monitor to report progress
+ * @throws RubyModelException
+ * @see #getLoadpathVariable(String)
+ * @since 0.9.0
+ */
+ public static void setLoadpathVariables(
+ String[] variableNames,
+ IPath[] paths,
+ IProgressMonitor monitor)
+ throws RubyModelException {
+
+ if (variableNames.length != paths.length) Assert.isTrue(false, "Variable names and paths collections should have the same size"); //$NON-NLS-1$
+ RubyModelManager.getRubyModelManager().updateVariableValues(variableNames, paths, true/*update preferences*/, monitor);
+ }
+
}
\ 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-18 16:05:57 UTC (rev 1800)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/compiler/util/Util.java 2007-01-18 16:30:20 UTC (rev 1801)
@@ -102,4 +102,17 @@
return contents;
}
+ /**
+ * Converts an array of Objects into String.
+ */
+ public static String toString(Object[] objects) {
+ return toString(objects,
+ new Displayable(){
+ public String displayString(Object o) {
+ if (o == null) return "null"; //$NON-NLS-1$
+ return o.toString();
+ }
+ });
+ }
+
}
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-18 16:05:57 UTC (rev 1800)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyModelManager.java 2007-01-18 16:30:20 UTC (rev 1801)
@@ -44,11 +44,13 @@
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.osgi.service.prefs.BackingStoreException;
import org.rubypeople.rdt.core.ILoadpathContainer;
import org.rubypeople.rdt.core.ILoadpathEntry;
import org.rubypeople.rdt.core.IParent;
import org.rubypeople.rdt.core.IProblemRequestor;
import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyModel;
import org.rubypeople.rdt.core.IRubyProject;
import org.rubypeople.rdt.core.IRubyScript;
import org.rubypeople.rdt.core.ISourceFolder;
@@ -176,6 +178,9 @@
public static final IRubyScript[] NO_WORKING_COPY = new IRubyScript[0];
public static final boolean VERBOSE = false;
+
+ public final static String CP_VARIABLE_PREFERENCES_PREFIX = RubyCore.PLUGIN_ID+".loadpathVariable."; //$NON-NLS-1$
+
/**
* Special value used for recognizing ongoing initialization and breaking initialization cycles
*/
@@ -1657,4 +1662,197 @@
return true;
}
+ /*
+ * Internal updating of a variable values (null path meaning removal), allowing to change multiple variable values at once.
+ */
+ public void updateVariableValues(
+ String[] variableNames,
+ IPath[] variablePaths,
+ boolean updatePreferences,
+ IProgressMonitor monitor) throws RubyModelException {
+
+ if (monitor != null && monitor.isCanceled()) return;
+
+ if (CP_RESOLVE_VERBOSE){
+ Util.verbose(
+ "CPVariable SET - setting variables\n" + //$NON-NLS-1$
+ " variables: " + org.rubypeople.rdt.internal.compiler.util.Util.toString(variableNames) + '\n' +//$NON-NLS-1$
+ " values: " + org.rubypeople.rdt.internal.compiler.util.Util.toString(variablePaths)); //$NON-NLS-1$
+ }
+
+ if (variablePutIfInitializingWithSameValue(variableNames, variablePaths))
+ return;
+
+ int varLength = variableNames.length;
+
+ // gather classpath information for updating
+ final HashMap affectedProjectClasspaths = new HashMap(5);
+ IRubyModel model = getRubyModel();
+
+ // filter out unmodified variables
+ int discardCount = 0;
+ for (int i = 0; i < varLength; i++){
+ String variableName = variableNames[i];
+ IPath oldPath = this.variableGet(variableName); // if reentering will provide previous session value
+ if (oldPath == VARIABLE_INITIALIZATION_IN_PROGRESS){
+// IPath previousPath = (IPath)this.previousSessionVariables.get(variableName);
+// if (previousPath != null){
+// if (CP_RESOLVE_VERBOSE){
+// Util.verbose(
+// "CPVariable INIT - reentering access to variable during its initialization, will see previous value\n" +
+// " variable: "+ variableName + '\n' +
+// " previous value: " + previousPath);
+// }
+// this.variablePut(variableName, previousPath); // replace value so reentering calls are seeing old value
+// }
+ oldPath = null; //33695 - cannot filter out restored variable, must update affected project to reset cached CP
+ }
+ if (oldPath != null && oldPath.equals(variablePaths[i])){
+ variableNames[i] = null;
+ discardCount++;
+ }
+ }
+ if (discardCount > 0){
+ if (discardCount == varLength) return;
+ int changedLength = varLength - discardCount;
+ String[] changedVariableNames = new String[changedLength];
+ IPath[] changedVariablePaths = new IPath[changedLength];
+ for (int i = 0, index = 0; i < varLength; i++){
+ if (variableNames[i] != null){
+ changedVariableNames[index] = variableNames[i];
+ changedVariablePaths[index] = variablePaths[i];
+ index++;
+ }
+ }
+ variableNames = changedVariableNames;
+ variablePaths = changedVariablePaths;
+ varLength = changedLength;
+ }
+
+ if (monitor != null && monitor.isCanceled()) return;
+
+ if (model != null) {
+ IRubyProject[] projects = model.getRubyProjects();
+ nextProject : for (int i = 0, projectLength = projects.length; i < projectLength; i++){
+ RubyProject project = (RubyProject) projects[i];
+
+ // check to see if any of the modified variables is present on the loadpath
+ ILoadpathEntry[] classpath = project.getRawLoadpath();
+ for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
+
+ ILoadpathEntry entry = classpath[j];
+ for (int k = 0; k < varLength; k++){
+
+ String variableName = variableNames[k];
+ if (entry.getEntryKind() == ILoadpathEntry.CPE_VARIABLE){
+
+ if (variableName.equals(entry.getPath().segment(0))){
+ affectedProjectClasspaths.put(project, project.getResolvedLoadpath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/));
+ continue nextProject;
+ }
+ }
+ }
+ }
+ }
+ }
+ // update variables
+ for (int i = 0; i < varLength; i++){
+ variablePut(variableNames[i], variablePaths[i]);
+ if (updatePreferences)
+ variablePreferencesPut(variableNames[i], variablePaths[i]);
+ }
+ final String[] dbgVariableNames = variableNames;
+
+ // update affected project loadpaths
+ if (!affectedProjectClasspaths.isEmpty()) {
+ try {
+ final boolean canChangeResources = !ResourcesPlugin.getWorkspace().isTreeLocked();
+ RubyCore.run(
+ new IWorkspaceRunnable() {
+ public void run(IProgressMonitor progressMonitor) throws CoreException {
+ // propagate loadpath change
+ Iterator projectsToUpdate = affectedProjectClasspaths.keySet().iterator();
+ while (projectsToUpdate.hasNext()) {
+
+ if (progressMonitor != null && progressMonitor.isCanceled()) return;
+
+ RubyProject affectedProject = (RubyProject) projectsToUpdate.next();
+
+ if (CP_RESOLVE_VERBOSE){
+ Util.verbose(
+ "CPVariable SET - updating affected project due to setting variables\n" + //$NON-NLS-1$
+ " project: " + affectedProject.getElementName() + '\n' + //$NON-NLS-1$
+ " variables: " + org.rubypeople.rdt.internal.compiler.util.Util.toString(dbgVariableNames)); //$NON-NLS-1$
+ }
+
+ affectedProject
+ .setRawLoadpath(
+ affectedProject.getRawLoadpath(),
+ SetLoadpathOperation.DO_NOT_SET_OUTPUT,
+ null, // don't call beginTask on the monitor (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=3717)
+ canChangeResources,
+ (ILoadpathEntry[]) affectedProjectClasspaths.get(affectedProject),
+ false, // updating - no need for early validation
+ false); // updating - no need to save
+ }
+ }
+ },
+ null/*no need to lock anything*/,
+ monitor);
+ } catch (CoreException e) {
+ if (CP_RESOLVE_VERBOSE){
+ Util.verbose(
+ "CPVariable SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$
+ " variables: " + org.rubypeople.rdt.internal.compiler.util.Util.toString(dbgVariableNames), //$NON-NLS-1$
+ System.err);
+ e.printStackTrace();
+ }
+ if (e instanceof RubyModelException) {
+ throw (RubyModelException)e;
+ } else {
+ throw new RubyModelException(e);
+ }
+ }
+ }
+ }
+
+ private void variablePreferencesPut(String variableName, IPath variablePath) {
+ String variableKey = CP_VARIABLE_PREFERENCES_PREFIX+variableName;
+ if (variablePath == null) {
+ this.variablesWithInitializer.remove(variableName);
+ getInstancePreferences().remove(variableKey);
+ } else {
+ getInstancePreferences().put(variableKey, variablePath.toString());
+ }
+ try {
+ getInstancePreferences().flush();
+ } catch (BackingStoreException e) {
+ // ignore exception
+ }
+ }
+
+ /**
+ * Get workpsace eclipse preference for JavaCore plugin.
+ */
+ public IEclipsePreferences getInstancePreferences() {
+ return preferencesLookup[PREF_INSTANCE];
+ }
+
+ /*
+ * Optimize startup case where 1 variable is initialized at a time with the same value as on shutdown.
+ */
+ public boolean variablePutIfInitializingWithSameValue(String[] variableNames, IPath[] variablePaths) {
+ if (variableNames.length != 1)
+ return false;
+ String variableName = variableNames[0];
+ IPath oldPath = getPreviousSessionVariable(variableName);
+ if (oldPath == null)
+ return false;
+ IPath newPath = variablePaths[0];
+ if (!oldPath.equals(newPath))
+ return false;
+ variablePut(variableName, newPath);
+ return true;
+ }
+
}
Added: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyLoadpathVariablesInitializer.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyLoadpathVariablesInitializer.java (rev 0)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/internal/launching/RubyLoadpathVariablesInitializer.java 2007-01-18 16:30:20 UTC (rev 1801)
@@ -0,0 +1,95 @@
+package org.rubypeople.rdt.internal.launching;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceDescription;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.rubypeople.rdt.core.LoadpathVariableInitializer;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.launching.IVMInstall;
+import org.rubypeople.rdt.launching.RubyRuntime;
+
+public class RubyLoadpathVariablesInitializer extends LoadpathVariableInitializer {
+
+ private IProgressMonitor fMonitor;
+
+ @Override
+ public void initialize(String variable) {
+ IVMInstall vmInstall= RubyRuntime.getDefaultInterpreterInstall();
+ if (vmInstall != null) {
+ IPath newPath= null;
+ IPath[] locations= RubyRuntime.getLibraryLocations(vmInstall);
+ // FIXME What should we be looking for?!
+ // look for rt.jar or classes.zip (both may exist, so do exhaustive search)
+ IPath rtjar = null;
+ IPath classeszip = null;
+ for (int i = 0; i < locations.length; i++) {
+ IPath location = locations[i];
+ String name = location.lastSegment();
+ if (name.equalsIgnoreCase("rt.jar")) { //$NON-NLS-1$
+ rtjar = location;
+ } else if (name.equalsIgnoreCase("classes.zip")) { //$NON-NLS-1$
+ classeszip = location;
+ }
+ }
+ // rt.jar if present, then classes.zip, else the first library
+ IPath systemLib = rtjar;
+ if (systemLib == null) {
+ systemLib = classeszip;
+ }
+ if (systemLib == null && locations.length > 0) {
+ systemLib = locations[0];
+ }
+ if (systemLib != null) {
+ if (variable.equals(RubyRuntime.RUBYLIB_VARIABLE)) {
+ newPath= systemLib;
+ }
+ if (newPath == null) {
+ return;
+ }
+ IWorkspace workspace= ResourcesPlugin.getWorkspace();
+ IWorkspaceDescription wsDescription= workspace.getDescription();
+ boolean wasAutobuild= wsDescription.isAutoBuilding();
+ try {
+ setAutobuild(workspace, false);
+ setRubyVMVariable(newPath, variable);
+ } catch (CoreException ce) {
+ LaunchingPlugin.log(ce);
+ return;
+ } finally {
+ try {
+ setAutobuild(workspace, wasAutobuild);
+ } catch (CoreException ce) {
+ LaunchingPlugin.log(ce);
+ }
+ }
+ }
+ }
+
+ }
+
+ private void setRubyVMVariable(IPath newPath, String var) throws CoreException {
+ RubyCore.setLoadpathVariable(var, newPath, getMonitor());
+ }
+
+ private boolean setAutobuild(IWorkspace ws, boolean newState) throws CoreException {
+ IWorkspaceDescription wsDescription= ws.getDescription();
+ boolean oldState= wsDescription.isAutoBuilding();
+ if (oldState != newState) {
+ wsDescription.setAutoBuilding(newState);
+ ws.setDescription(wsDescription);
+ }
+ return oldState;
+ }
+
+ protected IProgressMonitor getMonitor() {
+ if (fMonitor == null) {
+ return new NullProgressMonitor();
+ }
+ return fMonitor;
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/RubyRuntime.java
===================================================================
--- trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/RubyRuntime.java 2007-01-18 16:05:57 UTC (rev 1800)
+++ trunk/org.rubypeople.rdt.launching/src/org/rubypeople/rdt/launching/RubyRuntime.java 2007-01-18 16:30:20 UTC (rev 1801)
@@ -35,9 +35,9 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.VariablesPlugin;
import org.rubypeople.rdt.internal.launching.CompositeId;
-import org.rubypeople.rdt.internal.launching.ListenerList;
import org.rubypeople.rdt.internal.launching.LaunchingMessages;
import org.rubypeople.rdt.internal.launching.LaunchingPlugin;
+import org.rubypeople.rdt.internal.launching.ListenerList;
import org.rubypeople.rdt.internal.launching.RubyInterpreter;
import org.rubypeople.rdt.internal.launching.VMDefinitionsContainer;
import org.rubypeople.rdt.internal.launching.VMStandin;
@@ -89,6 +89,13 @@
* @since 0.9.0
*/
public static final String EXTENSION_POINT_VM_INSTALLS = "vmInstalls"; //$NON-NLS-1$
+
+ /**
+ * Classpath variable name used for the default RubyVM's library
+ * (value <code>"RUBY_LIB"</code>).
+ */
+ public static final String RUBYLIB_VARIABLE= "RUBY_LIB"; //$NON-NLS-1$
+
private static IVMInstallType[] fgInterpreterTypes= null;
@@ -636,4 +643,25 @@
// TODO Actually notify IInterpreterInstallChangedListeners
}
+
+ /**
+ * Evaluates library locations for a IVMInstall. If no library locations are set on the install, a default
+ * location is evaluated and checked if it exists.
+ * @return library locations with paths that exist or are empty
+ * @since 0.9.0
+ */
+ public static IPath[] getLibraryLocations(IVMInstall vm) {
+ IPath[] locations= vm.getLibraryLocations();
+ if (locations != null) return locations;
+
+ IPath[] dflts= vm.getVMInstallType().getDefaultLibraryLocations(vm.getInstallLocation());
+ IPath[] libraryPaths = new IPath[dflts.length];
+ for (int i = 0; i < dflts.length; i++) {
+ libraryPaths[i]= dflts[i];
+ if (!libraryPaths[i].toFile().isFile()) {
+ libraryPaths[i]= Path.EMPTY;
+ }
+ }
+ return libraryPaths;
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|