blob: 4e881c940c439ecd6fd342fb7e66e468e2a6238f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 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.eclipse.wst.jsdt.debug.internal.rhino.ui.refactoring;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.wst.jsdt.debug.internal.rhino.ui.ILaunchConstants;
import org.eclipse.wst.jsdt.debug.internal.rhino.ui.RhinoUIPlugin;
import org.eclipse.wst.jsdt.debug.internal.rhino.ui.launching.IncludeEntry;
/**
* Utilities to help with refactoring
*
* @since 1.0
*/
public class Refactoring {
public static ILaunchConfiguration[] NO_CONFIGS = new ILaunchConfiguration[0];
public static IncludeEntry[] NO_ENTRIES = new IncludeEntry[0];
/**
* Creates one or more {@link Change}s required after an {@link IProject} rename
*
* @param project the renamed {@link IProject}
* @param newname the new name
* @return a new {@link Change}
*/
public static Change createChangesForProjectRename(IProject project, String newname) {
ILaunchConfiguration[] configs = getConfigurationsScopedTo(project.getFullPath().makeAbsolute().toString());
if(configs.length < 1) {
return null;
}
ArrayList changes = new ArrayList(configs.length);
for (int i = 0; i < configs.length; i++) {
changes.add(new ProjectChange(configs[i], project.getName(), newname));
}
return createChangeFromList(changes, Messages.multi_updates);
}
/**
* Create one or more {@link Change}s after a script {@link IFile} rename
*
* @param script the renamed {@link IFile}
* @param newname the new name
* @return a new {@link Change}
*/
public static Change createChangesForScriptRename(IFile script, String newname) {
String scriptname = script.getFullPath().makeAbsolute().toString();
ILaunchConfiguration[] configs = getConfigurationsScopedTo(scriptname);
if(configs.length < 1) {
return null;
}
ArrayList changes = new ArrayList(configs.length);
for (int i = 0; i < configs.length; i++) {
changes.add(new ScriptChange(configs[i], scriptname, newname));
}
return createChangeFromList(changes, Messages.multi_updates);
}
/**
* Create one or more {@link Change}s after an {@link IFolder} rename
*
* @param folder the renamed {@link IFolder}
* @param newname the new name
* @return a new {@link Change}
*/
public static Change createChangesForFolderRename(IFolder folder, String newname) {
String foldername = folder.getFullPath().makeAbsolute().toString();
ILaunchConfiguration[] configs = getConfigurationsScopedTo(foldername);
if(configs.length < 1) {
return null;
}
ArrayList changes = new ArrayList(configs.length);
for (int i = 0; i < configs.length; i++) {
changes.add(new FolderChange(configs[i], foldername, newname));
}
return createChangeFromList(changes, Messages.multi_updates);
}
/**
* Collects the {@link IResource}s associated with the given Rhino launch configuration
*
* @param configuration
* @return the array of associated {@link IResource}s or an empty array, never <code>null</code>
* @throws CoreException
*/
public static IResource[] getResources(ILaunchConfiguration configuration) {
ArrayList resources = new ArrayList(2);
try {
IFile script = getScript(configuration);
if(script != null) {
resources.add(script);
}
}
catch(CoreException ce) {
RhinoUIPlugin.log(ce);
}
return (IResource[]) resources.toArray(new IResource[resources.size()]);
}
/**
* Fetches the script attribute as an {@link IFile} or returns <code>null</code> if it could not be found
*
* @param configuration
* @return the {@link IFile} backing the script attribute or <code>null</code> if not found
* @throws CoreException
*/
public static IFile getScript(ILaunchConfiguration configuration) throws CoreException {
String name = configuration.getAttribute(ILaunchConstants.ATTR_SCRIPT, ILaunchConstants.EMPTY_STRING);
if(!ILaunchConstants.EMPTY_STRING.equals(name)) {
IPath spath = new Path(name);
IResource script = ResourcesPlugin.getWorkspace().getRoot().findMember(spath);
if(script != null && script.getType() == IResource.FILE) {
return (IFile) script;
}
}
return null;
}
/**
* Delegate method to map {@link IResource}s in the given working copy. This method does not save the
* working and if no resources can be computed any existing resource mapping will be removed
*
* @param configuration
* @throws CoreException
*/
public static void mapResources(ILaunchConfigurationWorkingCopy configuration) {
IResource[] resources = getResources(configuration);
if(resources.length < 1) {
configuration.setMappedResources(null);
}
else {
configuration.setMappedResources(resources);
}
}
/**
* Take a list of Changes, and return a unique Change, a CompositeChange, or null.
*/
public static Change createChangeFromList(List changes, String changeLabel) {
int count = changes.size();
if (count == 0) {
return null;
}
else if (count == 1) {
return (Change) changes.get(0);
}
else {
return new CompositeChange(changeLabel, (Change[])changes.toArray(new Change[changes.size()]));
}
}
/**
* Returns the complete known listing of Rhino launch configurations
*
* @return the complete listing of Rhino launch configurations or an empty array, never <code>null</code>
*/
public static ILaunchConfiguration[] getRhinoConfigurations() {
ILaunchManager lm = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type = lm.getLaunchConfigurationType(ILaunchConstants.LAUNCH_CONFIG_TYPE);
if(type != null) {
try {
return lm.getLaunchConfigurations(type);
} catch (CoreException e) {
//ignore just return an empty array
}
}
return NO_CONFIGS;
}
/**
* Returns the complete listing of Rhino {@link ILaunchConfiguration}s that reference the given path in some way.
* The supported reference kinds are (1) via the script attribute, and (2) via the include path where it could be an exact
* match for a workspace script or a partial match for a local file system script
*
* @param elementpath the absolute path of the element to find configuration for
* @return the complete listing of Rhino configurations that reference the given path or an empty array, never <code>null</code>
*/
public static ILaunchConfiguration[] getConfigurationsScopedTo(String elementpath) {
if(elementpath == null) {
return NO_CONFIGS;
}
ILaunchConfiguration[] configs = getRhinoConfigurations();
ArrayList scoped = new ArrayList(4);
List includes = null;
String script = null;
for (int i = 0; i < configs.length; i++) {
try {
script = configs[i].getAttribute(ILaunchConstants.ATTR_SCRIPT, ILaunchConstants.EMPTY_STRING);
if(elementpath.equals(script) || script.indexOf(elementpath) > -1) {
scoped.add(configs[i]);
}
else {
includes = configs[i].getAttribute(ILaunchConstants.ATTR_INCLUDE_PATH, (List)null);
if(includes != null && hasIncludeEntryFor(includes, elementpath)) {
scoped.add(configs[i]);
}
}
}
catch(CoreException ce) {
//ignore, just don't report the configuration
}
}
return (ILaunchConfiguration[]) scoped.toArray(new ILaunchConfiguration[scoped.size()]);
}
/**
* Returns <code>true</code> if the given set of include path entries contains an entry that matches
* the given script path.
*
* @param includes
* @param elementpath
* @return <code>true</code> if a matching include path entry is found
*/
public static boolean hasIncludeEntryFor(List includes, String elementpath) {
if(includes == null || elementpath == null) {
return false;
}
String entry = null;
String path = null;
for (int i = 0; i < includes.size(); i++) {
entry = (String) includes.get(i);
path = entry.substring(1);
if(elementpath.equals(path) || path.indexOf(elementpath) > -1) {
return true;
}
}
return false;
}
/**
* Returns the {@link IncludeEntry}'s for the given absolute script path or an empty array.
* <br><br>
* This method avoids creating {@link IncludeEntry} objects unless potential matches are found.
*
* @param includes the current list of includes to search
* @param elementpath the absolute path of the element to check for
* @return the {@link IncludeEntry}'s of the given script in the include path listing or an empty array, never <code>null</code>
*/
public static final IncludeEntry[] findIncludeEntries(List includes, String elementpath) {
if(includes == null || elementpath == null) {
return NO_ENTRIES;
}
String entry = null;
String path = null;
ArrayList list = new ArrayList();
for (int i = 0; i < includes.size(); i++) {
entry = (String) includes.get(i);
path = entry.substring(1);
if(elementpath.equals(path) || path.indexOf(elementpath) > -1) {
try {
list.add(new IncludeEntry(Integer.parseInt(entry.substring(0, 1)), path));
}
catch(NumberFormatException nfe) {
//ignore but keep looking
}
}
}
return (IncludeEntry[]) list.toArray(new IncludeEntry[list.size()]);
}
/**
* Returns the complete include path from the given {@link ILaunchConfiguration} as a list of {@link IncludeEntry}s
* in the order they are defined in the configuration.
*
* @param configuration
* @return the ordered listing of {@link IncludeEntry}s or an empty array, never <code>null</code>
*/
public static final IncludeEntry[] getIncludeEntries(ILaunchConfiguration configuration) {
try {
List includes = configuration.getAttribute(ILaunchConstants.ATTR_INCLUDE_PATH, (List)null);
if(includes != null) {
ArrayList entries = new ArrayList(includes.size());
String entry = null;
for (int i = 0; i < includes.size(); i++) {
entry = (String) includes.get(i);
try {
entries.add(new IncludeEntry(Integer.parseInt(entry.substring(0, 1)), entry.substring(1)));
}
catch(NumberFormatException nfe) {
//ignore, keep going
}
}
return (IncludeEntry[]) entries.toArray(new IncludeEntry[entries.size()]);
}
}
catch(CoreException ce) {
//do nothing return none
}
return NO_ENTRIES;
}
}