/******************************************************************************* * Copyright (c) 2000, 2012 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.jdt.internal.debug.core.refactoring; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.CompositeChange; /** * * provides methods to create refactoring changes */ public class JDTDebugRefactoringUtil { /** * Take a list of Changes, and return a unique Change, a CompositeChange, or null. */ public static Change createChangeFromList(List<Change> changes, String changeLabel) { int nbChanges= changes.size(); if (nbChanges == 0) { return null; } else if (nbChanges == 1) { return changes.get(0); } else { return new CompositeChange(changeLabel, changes.toArray(new Change[changes.size()])); } } /** * Returns the new container name for the given project and launch configuration * @param javaProject the java to get the new container name for * @param launchConfiguration the associated launch configuration * @return the new container name * @since 3.2 */ protected static String computeNewContainerName(ILaunchConfiguration launchConfiguration) { IFile file = launchConfiguration.getFile(); if (file != null) { return file.getParent().getProjectRelativePath().toString(); } return null; } /** * Returns a change for the given launch configuration if the launch configuration needs to * be updated for this IType change. It specifically looks to see if the main type of the launch configuration * is an inner type of the given IType. * @param config the launch configuration * @param type the type to check for * @param newfqname the new fully qualified name * @param pname the new project name * @return the <code>Change</code> for this outer type * @throws CoreException * @since 3.2 */ protected static Change createChangesForOuterTypeChange(ILaunchConfiguration config, IType type, String newfqname, String pname) throws CoreException { IType[] innerTypes = type.getTypes(); if(innerTypes.length == 0) { return null; } Change change = null; String mtname = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, (String)null); for (int i= 0; i < innerTypes.length; i++) { String newTypeName = newfqname + '$' + innerTypes[i].getElementName(); // if it matches, check the type if (innerTypes[i].getFullyQualifiedName().equals(mtname)) { return new LaunchConfigurationProjectMainTypeChange(config, newTypeName, pname); } // if it's not the type, check the inner types change = createChangesForOuterTypeChange(config, innerTypes[i], newTypeName, pname); } return change; } /** * Provides a public mechanism for creating the <code>Change</code> for moving a package * @param packageFragment the fragment to move * @param destination the destination to move it to * @return the <code>Change</code> for moving the package * @throws CoreException * @since 3.2 */ public static Change createChangesForPackageMove(IPackageFragment pfragment, IPackageFragmentRoot destination) throws CoreException { List<Change> changes = new ArrayList<>(); ILaunchConfiguration[] configs = getJavaTypeLaunchConfigurations(pfragment.getJavaProject().getElementName()); String mtname = null; for (int i= 0; i < configs.length; i++) { mtname = configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, (String)null); if(mtname != null) { if(mtname.lastIndexOf(pfragment.getElementName()) > -1) { changes.add(new LaunchConfigurationProjectMainTypeChange(configs[i], null, destination.getJavaProject().getElementName())); } } } return JDTDebugRefactoringUtil.createChangeFromList(changes, RefactoringMessages.LaunchConfigurationProjectMainTypeChange_7); } /** * Provides a public mechanism for creating the <code>Change</code> for renaming a package * @param packageFragment the fragment to rename * @param newName the new name for the fragment * @return the Change for the renaming * @throws CoreException * @since 3.2 */ public static Change createChangesForPackageRename(IPackageFragment pfragment, String newname) throws CoreException { List<Change> changes = new ArrayList<>(); ILaunchConfiguration[] configs = getJavaTypeLaunchConfigurations(pfragment.getJavaProject().getElementName()); String mtname; for (int i= 0; i < configs.length; i++) { mtname = configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, (String)null); if(mtname != null) { String pkname = ""; //$NON-NLS-1$ int index = mtname.lastIndexOf('.'); if(index > 0) { pkname = mtname.substring(0, index); } if (pfragment.getElementName().equals(pkname)) { String ntname = newname + '.' + mtname.substring(index + 1); changes.add(new LaunchConfigurationProjectMainTypeChange(configs[i], ntname, null)); } } else { changes.add(new LaunchConfigurationProjectMainTypeChange(configs[i], null, null)); } } return JDTDebugRefactoringUtil.createChangeFromList(changes, RefactoringMessages.LaunchConfigurationProjectMainTypeChange_7); } /** * Provides a public mechanism for creating the <code>Change</code> for renaming a project * @param javaProject the project to rename * @param newProjectName the new name for the project * @return the Change for the project rename * @throws CoreException * @since 3.2 */ public static Change createChangesForProjectRename(IJavaProject project, String newname) throws CoreException { List<Change> changes = new ArrayList<>(); ILaunchConfiguration[] configs = getJavaTypeLaunchConfigurations(project.getElementName()); LaunchConfigurationProjectMainTypeChange change = null; for (int i= 0; i < configs.length; i++) { change = new LaunchConfigurationProjectMainTypeChange(configs[i], null, newname); String newcname = computeNewContainerName(configs[i]); if (newcname != null) { change.setNewContainerName(newcname); } changes.add(change); } return JDTDebugRefactoringUtil.createChangeFromList(changes, RefactoringMessages.LaunchConfigurationProjectMainTypeChange_7); } /** * Creates a <code>Change</code> for a type change * @param type the type that is changing * @param newfqname the new fully qualified name * @param pname the project name * @return the <code>Change</code> for changing the specified type * @throws CoreException * @since 3.2 */ protected static Change createChangesForTypeChange(IType type, String newfqname, String pname) throws CoreException { List<Change> changes = new ArrayList<>(); String typename = type.getFullyQualifiedName(); ILaunchConfiguration[] configs = getJavaTypeLaunchConfigurations(type.getJavaProject().getElementName()); String mtname; for (int i= 0; i < configs.length; i++) { mtname = configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, (String)null); if (typename.equals(mtname)) { changes.add(new LaunchConfigurationProjectMainTypeChange(configs[i], newfqname, pname)); } else { Change change = createChangesForOuterTypeChange(configs[i], type, newfqname, pname); if (change != null) { changes.add(change); } } } return JDTDebugRefactoringUtil.createChangeFromList(changes, RefactoringMessages.LaunchConfigurationProjectMainTypeChange_7); } /** * Provides a public mechanism for creating the <code>Change</code> for moving a type * @param type the type being moved * @param destination the destination to move the type to * @return the <code>Change</code> for the type move * @throws CoreException * @since 3.2 */ public static Change createChangesForTypeMove(IType type, IJavaElement destination) throws CoreException { IJavaProject pdestination = destination.getJavaProject(); String newpname = null; if (!type.getJavaProject().equals(pdestination)) { newpname = pdestination.getElementName(); } String newfqname = type.getElementName(); if (destination instanceof IType) { newfqname = ((IType)destination).getFullyQualifiedName() + '$' + type.getElementName(); } else if (destination instanceof IPackageFragment) { if (!((IPackageFragment) destination).isDefaultPackage()) { newfqname = destination.getElementName() + '.' + type.getElementName(); } } return createChangesForTypeChange(type, newfqname, newpname); } /** * Provides a public mechanism for creating the <code>Change</code> for renaming a type * @param type the type to rename * @param newname the new name for the type * @return the <code>Change</code> for the type rename * @throws CoreException * @since 3.2 */ public static Change createChangesForTypeRename(IType type, String newname) throws CoreException { IType dtype = type.getDeclaringType(); String newfqname = newname; if (dtype == null) { IPackageFragment packageFragment = type.getPackageFragment(); if (!packageFragment.isDefaultPackage()) { newfqname = packageFragment.getElementName() + '.' + newname; } } else { newfqname = dtype.getFullyQualifiedName() + '$' + newname; } return createChangesForTypeChange(type, newfqname, null); } /** * Returns a listing of configurations that have a specific project name attribute in them * @param pname the project attribute to compare against * @return the list of java type launch configurations that have the specified project attribute * @since 3.2 */ protected static ILaunchConfiguration[] getJavaTypeLaunchConfigurations(String pname) { try { ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(); ArrayList<ILaunchConfiguration> list = new ArrayList<>(); String attrib; for(int i = 0; i < configs.length; i++) { attrib = configs[i].getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null); if(attrib != null) { if(attrib.equals(pname)) { list.add(configs[i]); } } } return list.toArray(new ILaunchConfiguration[list.size()]); } catch(CoreException e) {JDIDebugPlugin.log(e);} return new ILaunchConfiguration[0]; } }