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.rename;
15 
16 import java.net.URI;
17 
18 import org.eclipse.core.filesystem.EFS;
19 import org.eclipse.core.filesystem.IFileStore;
20 
21 import org.eclipse.core.runtime.Assert;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IPath;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 
26 import org.eclipse.core.resources.IFile;
27 import org.eclipse.core.resources.IResource;
28 import org.eclipse.core.resources.ResourcesPlugin;
29 
30 import org.eclipse.ltk.core.refactoring.Change;
31 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
32 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
33 import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
34 import org.eclipse.ltk.core.refactoring.participants.RenameArguments;
35 
36 import org.eclipse.jdt.core.IJavaElement;
37 import org.eclipse.jdt.core.IJavaProject;
38 import org.eclipse.jdt.core.JavaCore;
39 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
40 import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
41 
42 import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
43 import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
44 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
45 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
46 import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
47 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
48 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
49 import org.eclipse.jdt.internal.corext.refactoring.changes.RenameJavaProjectChange;
50 import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
51 import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
52 import org.eclipse.jdt.internal.corext.util.Messages;
53 import org.eclipse.jdt.internal.corext.util.Resources;
54 
55 import org.eclipse.jdt.ui.refactoring.IRefactoringProcessorIds;
56 import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper;
57 
58 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
59 
60 public final class RenameJavaProjectProcessor extends JavaRenameProcessor implements IReferenceUpdating {
61 
62 	private IJavaProject fProject;
63 	private boolean fUpdateReferences;
64 
65 	/**
66 	 * Creates a new rename java project processor.
67 	 * @param project the java project, or <code>null</code> if invoked by scripting
68 	 */
RenameJavaProjectProcessor(IJavaProject project)69 	public RenameJavaProjectProcessor(IJavaProject project) {
70 		fProject= project;
71 		if (fProject != null)
72 			setNewElementName(fProject.getElementName());
73 		fUpdateReferences= true;
74 	}
75 
RenameJavaProjectProcessor(JavaRefactoringArguments arguments, RefactoringStatus status)76 	public RenameJavaProjectProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) {
77 		this(null);
78 		RefactoringStatus initializeStatus= initialize(arguments);
79 		status.merge(initializeStatus);
80 	}
81 
82 	@Override
getIdentifier()83 	public String getIdentifier() {
84 		return IRefactoringProcessorIds.RENAME_JAVA_PROJECT_PROCESSOR;
85 	}
86 
87 	@Override
isApplicable()88 	public boolean isApplicable() throws CoreException {
89 		return RefactoringAvailabilityTester.isRenameAvailable(fProject);
90 	}
91 
92 	@Override
getProcessorName()93 	public String getProcessorName() {
94 		return RefactoringCoreMessages.RenameJavaProjectRefactoring_rename;
95 	}
96 
97 	@Override
getAffectedProjectNatures()98 	protected String[] getAffectedProjectNatures() throws CoreException {
99 		return JavaProcessors.computeAffectedNatures(fProject);
100 	}
101 
102 	@Override
getElements()103 	public Object[] getElements() {
104 		return new Object[] {fProject};
105 	}
106 
107 	@Override
getNewElement()108 	public Object getNewElement() {
109 		IPath newPath= fProject.getPath().removeLastSegments(1).append(getNewElementName());
110 		return JavaCore.create(ResourcesPlugin.getWorkspace().getRoot().findMember(newPath));
111 	}
112 
113 	@Override
computeRenameModifications()114 	protected RenameModifications computeRenameModifications() throws CoreException {
115 		RenameModifications result= new RenameModifications();
116 		result.rename(fProject, new RenameArguments(getNewElementName(), getUpdateReferences()));
117 		return result;
118 	}
119 
120 	@Override
getChangedFiles()121 	protected IFile[] getChangedFiles() throws CoreException {
122 		IFile projectFile= fProject.getProject().getFile(".project"); //$NON-NLS-1$
123 		if (projectFile != null && projectFile.exists()) {
124 			return new IFile[] {projectFile};
125 		}
126 		return new IFile[0];
127 	}
128 
129 	@Override
getSaveMode()130 	public int getSaveMode() {
131 		return RefactoringSaveHelper.SAVE_ALL;
132 	}
133 
134 	//---- IReferenceUpdating --------------------------------------
135 
136 	@Override
setUpdateReferences(boolean update)137 	public void setUpdateReferences(boolean update) {
138 		fUpdateReferences= update;
139 	}
140 
141 	@Override
getUpdateReferences()142 	public boolean getUpdateReferences() {
143 		return fUpdateReferences;
144 	}
145 
146 	//---- IRenameProcessor ----------------------------------------------
147 
148 	@Override
getCurrentElementName()149 	public String getCurrentElementName() {
150 		return fProject.getElementName();
151 	}
152 
153 	@Override
checkInitialConditions(IProgressMonitor pm)154 	public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
155 		return new RefactoringStatus();
156 	}
157 
158 	@Override
checkNewElementName(String newName)159 	public RefactoringStatus checkNewElementName(String newName) throws CoreException {
160 		Assert.isNotNull(newName, "new name"); //$NON-NLS-1$
161 		RefactoringStatus result= RefactoringStatus.create(ResourcesPlugin.getWorkspace().validateName(newName, IResource.PROJECT));
162 		if (result.hasFatalError())
163 			return result;
164 
165 		if (projectNameAlreadyExists(newName))
166 			return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.RenameJavaProjectRefactoring_already_exists);
167 		if (projectFolderAlreadyExists(newName))
168 			return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.RenameJavaProjectProcessor_folder_already_exists);
169 
170 		return new RefactoringStatus();
171 	}
172 
173 	@Override
doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context)174 	protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException {
175 		pm.beginTask("", 1); //$NON-NLS-1$
176 		try{
177 			if (isReadOnly()){
178 				String message= Messages.format(RefactoringCoreMessages.RenameJavaProjectRefactoring_read_only,
179 						BasicElementLabels.getJavaElementName(fProject.getElementName()));
180 				return RefactoringStatus.createErrorStatus(message);
181 			}
182 			return new RefactoringStatus();
183 		} finally{
184 			pm.done();
185 		}
186 	}
187 
isReadOnly()188 	private boolean isReadOnly() {
189 		return Resources.isReadOnly(fProject.getResource());
190 	}
191 
projectNameAlreadyExists(String newName)192 	private boolean projectNameAlreadyExists(String newName){
193 		return ResourcesPlugin.getWorkspace().getRoot().getProject(newName).exists();
194 	}
195 
projectFolderAlreadyExists(String newName)196 	private boolean projectFolderAlreadyExists(String newName) throws CoreException {
197 		boolean isNotInWorkpace= fProject.getProject().getDescription().getLocationURI() != null;
198 		if (isNotInWorkpace)
199 			return false; // projects outside of the workspace are not renamed
200 
201 		URI locationURI= fProject.getProject().getLocationURI();
202 		IFileStore projectStore= EFS.getStore(locationURI);
203 
204 		if (!projectStore.getFileSystem().isCaseSensitive() && newName.equalsIgnoreCase(fProject.getElementName()))
205 			return false; // allow to change case
206 
207 		IFileStore newProjectStore= projectStore.getParent().getChild(newName);
208 
209 		return newProjectStore.fetchInfo().exists();
210 	}
211 
212 	@Override
createChange(IProgressMonitor monitor)213 	public Change createChange(IProgressMonitor monitor) throws CoreException {
214 		try {
215 			monitor.beginTask("", 1); //$NON-NLS-1$
216 			final String description= Messages.format(RefactoringCoreMessages.RenameJavaProjectProcessor_descriptor_description_short, BasicElementLabels.getJavaElementName(fProject.getElementName()));
217 			final String header= Messages.format(RefactoringCoreMessages.RenameJavaProjectChange_descriptor_description, new String[] { BasicElementLabels.getJavaElementName(fProject.getElementName()), BasicElementLabels.getJavaElementName(getNewElementName())});
218 			final String comment= new JDTRefactoringDescriptorComment(null, this, header).asString();
219 			final int flags= RefactoringDescriptor.STRUCTURAL_CHANGE | RefactoringDescriptor.MULTI_CHANGE | RefactoringDescriptor.BREAKING_CHANGE;
220 			final RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_JAVA_PROJECT);
221 			descriptor.setProject(null);
222 			descriptor.setDescription(description);
223 			descriptor.setComment(comment);
224 			descriptor.setFlags(flags);
225 			descriptor.setJavaElement(fProject);
226 			descriptor.setNewName(getNewElementName());
227 			descriptor.setUpdateReferences(fUpdateReferences);
228 			return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameJavaProjectRefactoring_rename, new Change[] { new RenameJavaProjectChange(fProject, getNewElementName(), fUpdateReferences)});
229 		} finally {
230 			monitor.done();
231 		}
232 	}
233 
initialize(JavaRefactoringArguments extended)234 	private RefactoringStatus initialize(JavaRefactoringArguments extended) {
235 		final String handle= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
236 		if (handle != null) {
237 			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
238 			if (element == null || !element.exists() || element.getElementType() != IJavaElement.JAVA_PROJECT)
239 				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.RENAME_JAVA_PROJECT);
240 			else
241 				fProject= (IJavaProject) element;
242 		} else
243 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
244 		final String name= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
245 		if (name != null && !"".equals(name)) //$NON-NLS-1$
246 			setNewElementName(name);
247 		else
248 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
249 		final String references= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES);
250 		if (references != null) {
251 			fUpdateReferences= Boolean.parseBoolean(references);
252 		} else
253 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES));
254 		return new RefactoringStatus();
255 	}
256 }
257