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.util; 15 16 import java.io.File; 17 import java.net.URI; 18 import java.util.ArrayList; 19 import java.util.HashMap; 20 import java.util.List; 21 import java.util.Map; 22 23 import org.eclipse.core.filesystem.EFS; 24 25 import org.eclipse.core.runtime.CoreException; 26 import org.eclipse.core.runtime.IPath; 27 import org.eclipse.core.runtime.IStatus; 28 import org.eclipse.core.runtime.MultiStatus; 29 import org.eclipse.core.runtime.Status; 30 31 import org.eclipse.core.resources.IFile; 32 import org.eclipse.core.resources.IResource; 33 import org.eclipse.core.resources.IResourceStatus; 34 import org.eclipse.core.resources.ResourceAttributes; 35 import org.eclipse.core.resources.ResourcesPlugin; 36 37 import org.eclipse.jdt.core.manipulation.JavaManipulation; 38 39 import org.eclipse.jdt.internal.core.manipulation.JavaManipulationPlugin; 40 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels; 41 import org.eclipse.jdt.internal.corext.CorextMessages; 42 43 import org.eclipse.jdt.internal.ui.IJavaStatusConstants; 44 import org.eclipse.jdt.internal.ui.JavaUIStatus; 45 46 public class Resources { 47 Resources()48 private Resources() { 49 } 50 51 /** 52 * Checks if the given resource is in sync with the underlying file system. 53 * 54 * @param resource the resource to be checked 55 * @return IStatus status describing the check's result. If <code>status. 56 * isOK()</code> returns <code>true</code> then the resource is in sync 57 */ checkInSync(IResource resource)58 public static IStatus checkInSync(IResource resource) { 59 return checkInSync(new IResource[] {resource}); 60 } 61 62 /** 63 * Checks if the given resources are in sync with the underlying file 64 * system. 65 * 66 * @param resources the resources to be checked 67 * @return IStatus status describing the check's result. If <code>status. 68 * isOK() </code> returns <code>true</code> then the resources are in sync 69 */ checkInSync(IResource[] resources)70 public static IStatus checkInSync(IResource[] resources) { 71 IStatus result= null; 72 for (IResource resource : resources) { 73 if (!resource.isSynchronized(IResource.DEPTH_INFINITE)) { 74 result= addOutOfSync(result, resource); 75 } 76 } 77 if (result != null) 78 return result; 79 return Status.OK_STATUS; 80 } 81 82 /** 83 * Makes the given resource committable. Committable means that it is 84 * writeable and that its content hasn't changed by calling 85 * <code>validateEdit</code> for the given resource on <tt>IWorkspace</tt>. 86 * 87 * @param resource the resource to be checked 88 * @param context the context passed to <code>validateEdit</code> 89 * @return status describing the method's result. If <code>status.isOK()</code> returns <code>true</code> then the resources are committable. 90 * 91 * @see org.eclipse.core.resources.IWorkspace#validateEdit(org.eclipse.core.resources.IFile[], java.lang.Object) 92 */ makeCommittable(IResource resource, Object context)93 public static IStatus makeCommittable(IResource resource, Object context) { 94 return makeCommittable(new IResource[] { resource }, context); 95 } 96 97 /** 98 * Makes the given resources committable. Committable means that all 99 * resources are writeable and that the content of the resources hasn't 100 * changed by calling <code>validateEdit</code> for a given file on 101 * <tt>IWorkspace</tt>. 102 * 103 * @param resources the resources to be checked 104 * @param context the context passed to <code>validateEdit</code> 105 * @return IStatus status describing the method's result. If <code>status. 106 * isOK()</code> returns <code>true</code> then the add resources are 107 * committable 108 * 109 * @see org.eclipse.core.resources.IWorkspace#validateEdit(org.eclipse.core.resources.IFile[], java.lang.Object) 110 */ makeCommittable(IResource[] resources, Object context)111 public static IStatus makeCommittable(IResource[] resources, Object context) { 112 List<IResource> readOnlyFiles= new ArrayList<>(); 113 for (IResource resource : resources) { 114 if (resource.getType() == IResource.FILE && isReadOnly(resource)) 115 readOnlyFiles.add(resource); 116 } 117 if (readOnlyFiles.isEmpty()) 118 return Status.OK_STATUS; 119 120 Map<IFile, Long> oldTimeStamps= createModificationStampMap(readOnlyFiles); 121 IStatus status= ResourcesPlugin.getWorkspace().validateEdit( 122 readOnlyFiles.toArray(new IFile[readOnlyFiles.size()]), context); 123 if (!status.isOK()) 124 return status; 125 126 IStatus modified= null; 127 Map<IFile, Long> newTimeStamps= createModificationStampMap(readOnlyFiles); 128 for (IFile file : oldTimeStamps.keySet()) { 129 if (!oldTimeStamps.get(file).equals(newTimeStamps.get(file))) 130 modified= addModified(modified, file); 131 } 132 if (modified != null) 133 return modified; 134 return Status.OK_STATUS; 135 } 136 createModificationStampMap(List<IResource> files)137 private static Map<IFile, Long> createModificationStampMap(List<IResource> files){ 138 Map<IFile, Long> map= new HashMap<>(); 139 for (IResource iResource : files) { 140 IFile file= (IFile)iResource; 141 map.put(file, Long.valueOf(file.getModificationStamp())); 142 } 143 return map; 144 } 145 addModified(IStatus status, IFile file)146 private static IStatus addModified(IStatus status, IFile file) { 147 IStatus entry= JavaUIStatus.createError( 148 IJavaStatusConstants.VALIDATE_EDIT_CHANGED_CONTENT, 149 Messages.format(CorextMessages.Resources_fileModified, BasicElementLabels.getPathLabel(file.getFullPath(), false)), 150 null); 151 if (status == null) { 152 return entry; 153 } else if (status.isMultiStatus()) { 154 ((MultiStatus)status).add(entry); 155 return status; 156 } else { 157 MultiStatus result= new MultiStatus(JavaManipulation.getPreferenceNodeId(), 158 IJavaStatusConstants.VALIDATE_EDIT_CHANGED_CONTENT, 159 CorextMessages.Resources_modifiedResources, null); 160 result.add(status); 161 result.add(entry); 162 return result; 163 } 164 } 165 addOutOfSync(IStatus status, IResource resource)166 private static IStatus addOutOfSync(IStatus status, IResource resource) { 167 IStatus entry= new Status( 168 IStatus.ERROR, 169 ResourcesPlugin.PI_RESOURCES, 170 IResourceStatus.OUT_OF_SYNC_LOCAL, 171 Messages.format(CorextMessages.Resources_outOfSync, BasicElementLabels.getPathLabel(resource.getFullPath(), false)), 172 null); 173 if (status == null) { 174 return entry; 175 } else if (status.isMultiStatus()) { 176 ((MultiStatus)status).add(entry); 177 return status; 178 } else { 179 MultiStatus result= new MultiStatus( 180 ResourcesPlugin.PI_RESOURCES, 181 IResourceStatus.OUT_OF_SYNC_LOCAL, 182 CorextMessages.Resources_outOfSyncResources, null); 183 result.add(status); 184 result.add(entry); 185 return result; 186 } 187 } 188 189 /** 190 * This method is used to generate a list of local locations to 191 * be used in DnD for file transfers. 192 * 193 * @param resources the array of resources to get the local 194 * locations for 195 * @return the local locations 196 */ getLocationOSStrings(IResource[] resources)197 public static String[] getLocationOSStrings(IResource[] resources) { 198 List<String> result= new ArrayList<>(resources.length); 199 for (IResource resource : resources) { 200 IPath location= resource.getLocation(); 201 if (location != null) 202 result.add(location.toOSString()); 203 } 204 return result.toArray(new String[result.size()]); 205 } 206 207 /** 208 * Returns the location of the given resource. For local 209 * resources this is the OS path in the local file system. For 210 * remote resource this is the URI. 211 * 212 * @param resource the resource 213 * @return the location string or <code>null</code> if the 214 * location URI of the resource is <code>null</code> 215 */ getLocationString(IResource resource)216 public static String getLocationString(IResource resource) { 217 URI uri= resource.getLocationURI(); 218 if (uri == null) 219 return null; 220 return EFS.SCHEME_FILE.equalsIgnoreCase(uri.getScheme()) 221 ? new File(uri).getAbsolutePath() 222 : uri.toString(); 223 } 224 isReadOnly(IResource resource)225 public static boolean isReadOnly(IResource resource) { 226 ResourceAttributes resourceAttributes = resource.getResourceAttributes(); 227 if (resourceAttributes == null) // not supported on this platform for this resource 228 return false; 229 return resourceAttributes.isReadOnly(); 230 } 231 setReadOnly(IResource resource, boolean readOnly)232 static void setReadOnly(IResource resource, boolean readOnly) { 233 ResourceAttributes resourceAttributes = resource.getResourceAttributes(); 234 if (resourceAttributes == null) // not supported on this platform for this resource 235 return; 236 237 resourceAttributes.setReadOnly(readOnly); 238 try { 239 resource.setResourceAttributes(resourceAttributes); 240 } catch (CoreException e) { 241 JavaManipulationPlugin.log(e); 242 } 243 } 244 } 245