1 /*******************************************************************************
2  * Copyright (c) 2000, 2016 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.corext.refactoring.changes;
15 
16 import org.eclipse.core.runtime.Assert;
17 import org.eclipse.core.runtime.CoreException;
18 import org.eclipse.core.runtime.IPath;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.SubProgressMonitor;
21 
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.resources.IProjectDescription;
24 import org.eclipse.core.resources.IResource;
25 
26 import org.eclipse.ltk.core.refactoring.Change;
27 
28 import org.eclipse.jdt.core.IClasspathEntry;
29 import org.eclipse.jdt.core.IJavaProject;
30 import org.eclipse.jdt.core.JavaCore;
31 import org.eclipse.jdt.core.JavaModelException;
32 
33 import org.eclipse.jdt.internal.corext.refactoring.AbstractJavaElementRenameChange;
34 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
35 import org.eclipse.jdt.internal.corext.util.Messages;
36 
37 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
38 
39 public final class RenameJavaProjectChange extends AbstractJavaElementRenameChange {
40 
41 	private boolean fUpdateReferences;
42 
RenameJavaProjectChange(IJavaProject project, String newName, boolean updateReferences)43 	public RenameJavaProjectChange(IJavaProject project, String newName, boolean updateReferences) {
44 		this(project.getPath(), project.getElementName(), newName, IResource.NULL_STAMP, updateReferences);
45 		Assert.isTrue(!project.isReadOnly(), "should not be read only"); //$NON-NLS-1$
46 	}
47 
RenameJavaProjectChange(IPath resourcePath, String oldName, String newName, long stampToRestore, boolean updateReferences)48 	private RenameJavaProjectChange(IPath resourcePath, String oldName, String newName, long stampToRestore, boolean updateReferences) {
49 		super(resourcePath, oldName, newName, stampToRestore);
50 		fUpdateReferences= updateReferences;
51 
52 		setValidationMethod(VALIDATE_NOT_DIRTY);
53 	}
54 
createModifiedEntry(IClasspathEntry oldEntry)55 	private IClasspathEntry createModifiedEntry(IClasspathEntry oldEntry) {
56 		return JavaCore.newProjectEntry(createNewPath(), oldEntry.getAccessRules(), oldEntry.combineAccessRules(), oldEntry.getExtraAttributes(), oldEntry.isExported());
57 	}
58 
59 	@Override
createNewPath()60 	protected IPath createNewPath() {
61 		return getResourcePath().removeLastSegments(1).append(getNewName());
62 	}
63 
64 	@Override
createUndoChange(long stampToRestore)65 	protected Change createUndoChange(long stampToRestore) throws JavaModelException {
66 		return new RenameJavaProjectChange(createNewPath(), getNewName(), getOldName(), stampToRestore, fUpdateReferences);
67 	}
68 
69 	@Override
doRename(IProgressMonitor pm)70 	protected void doRename(IProgressMonitor pm) throws CoreException {
71 		try {
72 			pm.beginTask(getName(), 2);
73 			if (fUpdateReferences)
74 				modifyClassPaths(new SubProgressMonitor(pm, 1));
75 			IProject project= getProject();
76 			if (project != null) {
77 				IProjectDescription description= project.getDescription();
78 				description.setName(getNewName());
79 				project.move(description, IResource.FORCE | IResource.SHALLOW, new SubProgressMonitor(pm, 1));
80 			}
81 		} finally {
82 			pm.done();
83 		}
84 	}
85 
getJavaProject()86 	private IJavaProject getJavaProject() {
87 		return (IJavaProject) getModifiedElement();
88 	}
89 
90 	@Override
getName()91 	public String getName() {
92 		String[] keys= new String[] { BasicElementLabels.getJavaElementName(getOldName()), BasicElementLabels.getJavaElementName(getNewName())};
93 		return Messages.format(RefactoringCoreMessages.RenameJavaProjectChange_rename, keys);
94 	}
95 
getProject()96 	private IProject getProject() {
97 		IJavaProject jp= getJavaProject();
98 		if (jp == null)
99 			return null;
100 		return jp.getProject();
101 	}
102 
isOurEntry(IClasspathEntry cpe)103 	private boolean isOurEntry(IClasspathEntry cpe) {
104 		if (cpe.getEntryKind() != IClasspathEntry.CPE_PROJECT)
105 			return false;
106 		if (!cpe.getPath().equals(getResourcePath()))
107 			return false;
108 		return true;
109 	}
110 
modifyClassPath(IJavaProject referencingProject, IProgressMonitor pm)111 	private void modifyClassPath(IJavaProject referencingProject, IProgressMonitor pm) throws JavaModelException {
112 		pm.beginTask("", 1); //$NON-NLS-1$
113 		IClasspathEntry[] oldEntries= referencingProject.getRawClasspath();
114 		IClasspathEntry[] newEntries= new IClasspathEntry[oldEntries.length];
115 		for (int i= 0; i < newEntries.length; i++) {
116 			if (isOurEntry(oldEntries[i]))
117 				newEntries[i]= createModifiedEntry(oldEntries[i]);
118 			else
119 				newEntries[i]= oldEntries[i];
120 		}
121 		referencingProject.setRawClasspath(newEntries, pm);
122 		pm.done();
123 	}
124 
modifyClassPaths(IProgressMonitor pm)125 	private void modifyClassPaths(IProgressMonitor pm) throws JavaModelException {
126 		IProject[] referencing= getProject().getReferencingProjects();
127 		pm.beginTask(RefactoringCoreMessages.RenameJavaProjectChange_update, referencing.length);
128 		for (IProject p : referencing) {
129 			IJavaProject jp= JavaCore.create(p);
130 			if (jp != null && jp.exists()) {
131 				modifyClassPath(jp, new SubProgressMonitor(pm, 1));
132 			} else {
133 				pm.worked(1);
134 			}
135 		}
136 		pm.done();
137 	}
138 }
139