KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > resources > LocationValidator


1 /*******************************************************************************
2  * Copyright (c) 2005, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.resources;
12
13 import java.net.URI JavaDoc;
14 import org.eclipse.core.filesystem.EFS;
15 import org.eclipse.core.filesystem.URIUtil;
16 import org.eclipse.core.internal.utils.FileUtil;
17 import org.eclipse.core.internal.utils.Messages;
18 import org.eclipse.core.resources.*;
19 import org.eclipse.core.runtime.*;
20 import org.eclipse.osgi.util.NLS;
21
22 /**
23  * This class implements the various path, URI, and name validation methods
24  * in the workspace API
25  */

26 public class LocationValidator {
27     private final Workspace workspace;
28
29     public LocationValidator(Workspace workspace) {
30         this.workspace = workspace;
31     }
32
33     /**
34      * Returns a string representation of a URI suitable for displaying to an end user.
35      */

36     private String JavaDoc toString(URI JavaDoc uri) {
37         try {
38             return EFS.getStore(uri).toString();
39         } catch (CoreException e) {
40             //there is no store defined, so the best we can do is the URI toString.
41
return uri.toString();
42         }
43     }
44
45     /**
46      * Check that the location is absolute
47      */

48     private IStatus validateAbsolute(URI JavaDoc location, boolean error) {
49         if (!location.isAbsolute()) {
50             IPath pathPart = new Path(location.getSchemeSpecificPart());
51             String JavaDoc message;
52             if (pathPart.segmentCount() > 0)
53                 message = NLS.bind(Messages.pathvar_undefined, location.toString(), pathPart.segment(0));
54             else
55                 message = Messages.links_noPath;
56             int code = error ? IResourceStatus.VARIABLE_NOT_DEFINED : IResourceStatus.VARIABLE_NOT_DEFINED_WARNING;
57             return new ResourceStatus(code, null, message);
58         }
59         return Status.OK_STATUS;
60     }
61
62     /* (non-Javadoc)
63      * @see IWorkspace#validateLinkLocation(IResource, IPath)
64      */

65     public IStatus validateLinkLocation(IResource resource, IPath unresolvedLocation) {
66         IPath location = workspace.getPathVariableManager().resolvePath(unresolvedLocation);
67         if (location.isEmpty())
68             return new ResourceStatus(IResourceStatus.INVALID_VALUE, resource.getFullPath(), Messages.links_noPath);
69         //check that the location is absolute
70
if (!location.isAbsolute()) {
71             //we know there is at least one segment, because of previous isEmpty check
72
String JavaDoc message = NLS.bind(Messages.pathvar_undefined, location.toOSString(), location.segment(0));
73             return new ResourceStatus(IResourceStatus.VARIABLE_NOT_DEFINED_WARNING, resource.getFullPath(), message);
74         }
75         //if the location doesn't have a device, see if the OS will assign one
76
if (location.getDevice() == null)
77             location = new Path(location.toFile().getAbsolutePath());
78         return validateLinkLocationURI(resource, URIUtil.toURI(location));
79     }
80
81     public IStatus validateLinkLocationURI(IResource resource, URI JavaDoc unresolvedLocation) {
82         String JavaDoc message;
83         //check if resource linking is disabled
84
if (ResourcesPlugin.getPlugin().getPluginPreferences().getBoolean(ResourcesPlugin.PREF_DISABLE_LINKING)) {
85             message = NLS.bind(Messages.links_workspaceVeto, resource.getName());
86             return new ResourceStatus(IResourceStatus.INVALID_VALUE, resource.getFullPath(), message);
87         }
88         //check that the resource is the right type
89
int type = resource.getType();
90         if (type != IResource.FOLDER && type != IResource.FILE) {
91             message = NLS.bind(Messages.links_notFileFolder, resource.getName());
92             return new ResourceStatus(IResourceStatus.INVALID_VALUE, resource.getFullPath(), message);
93         }
94         IContainer parent = resource.getParent();
95         if (!parent.isAccessible()) {
96             message = NLS.bind(Messages.links_parentNotAccessible, resource.getFullPath());
97             return new ResourceStatus(IResourceStatus.INVALID_VALUE, resource.getFullPath(), message);
98         }
99         URI JavaDoc location = workspace.getPathVariableManager().resolveURI(unresolvedLocation);
100         //check nature veto
101
String JavaDoc[] natureIds = ((Project) resource.getProject()).internalGetDescription().getNatureIds();
102
103         IStatus result = workspace.getNatureManager().validateLinkCreation(natureIds);
104         if (!result.isOK())
105             return result;
106         //check team provider veto
107
if (resource.getType() == IResource.FILE)
108             result = workspace.getTeamHook().validateCreateLink((IFile) resource, IResource.NONE, location);
109         else
110             result = workspace.getTeamHook().validateCreateLink((IFolder) resource, IResource.NONE, location);
111         if (!result.isOK())
112             return result;
113         //check the standard path name restrictions
114
result = validateSegments(location);
115         if (!result.isOK())
116             return result;
117         //check if the location is based on an undefined variable
118
result = validateAbsolute(location, false);
119         if (!result.isOK())
120             return result;
121         // test if the given location overlaps the platform metadata location
122
URI JavaDoc testLocation = workspace.getMetaArea().getLocation().toFile().toURI();
123         if (FileUtil.isOverlapping(location, testLocation)) {
124             message = NLS.bind(Messages.links_invalidLocation, toString(location));
125             return new ResourceStatus(IResourceStatus.INVALID_VALUE, resource.getFullPath(), message);
126         }
127         //test if the given path overlaps the location of the given project
128
testLocation = resource.getProject().getLocationURI();
129         if (testLocation != null && FileUtil.isPrefixOf(location, testLocation)) {
130             message = NLS.bind(Messages.links_locationOverlapsProject, toString(location));
131             return new ResourceStatus(IResourceStatus.INVALID_VALUE, resource.getFullPath(), message);
132         }
133         //warnings (all errors must be checked before all warnings)
134

135         // Iterate over each known project and ensure that the location does not
136
// conflict with any project locations or linked resource locations
137
IProject[] projects = workspace.getRoot().getProjects();
138         for (int i = 0; i < projects.length; i++) {
139             IProject project = projects[i];
140             // since we are iterating over the project in the workspace, we
141
// know that they have been created before and must have a description
142
IProjectDescription desc = ((Project) project).internalGetDescription();
143             testLocation = desc.getLocationURI();
144             if (testLocation != null && FileUtil.isOverlapping(location, testLocation)) {
145                 message = NLS.bind(Messages.links_overlappingResource, toString(location));
146                 return new ResourceStatus(IResourceStatus.OVERLAPPING_LOCATION, resource.getFullPath(), message);
147             }
148             //iterate over linked resources and check for overlap
149
if (!project.isOpen())
150                 continue;
151             IResource[] children = null;
152             try {
153                 children = project.members();
154             } catch (CoreException e) {
155                 //ignore projects that cannot be accessed
156
}
157             if (children == null)
158                 continue;
159             for (int j = 0; j < children.length; j++) {
160                 if (children[j].isLinked()) {
161                     testLocation = children[j].getLocationURI();
162                     if (testLocation != null && FileUtil.isOverlapping(location, testLocation)) {
163                         message = NLS.bind(Messages.links_overlappingResource, toString(location));
164                         return new ResourceStatus(IResourceStatus.OVERLAPPING_LOCATION, resource.getFullPath(), message);
165                     }
166                 }
167             }
168         }
169         return Status.OK_STATUS;
170     }
171
172     /* (non-Javadoc)
173      * @see IWorkspace#validateName(String, int)
174      */

175     public IStatus validateName(String JavaDoc segment, int type) {
176         String JavaDoc message;
177
178         /* segment must not be null */
179         if (segment == null) {
180             message = Messages.resources_nameNull;
181             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
182         }
183
184         // cannot be an empty string
185
if (segment.length() == 0) {
186             message = Messages.resources_nameEmpty;
187             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
188         }
189
190         /* test invalid characters */
191         char[] chars = OS.INVALID_RESOURCE_CHARACTERS;
192         for (int i = 0; i < chars.length; i++)
193             if (segment.indexOf(chars[i]) != -1) {
194                 message = NLS.bind(Messages.resources_invalidCharInName, String.valueOf(chars[i]), segment);
195                 return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
196             }
197
198         /* test invalid OS names */
199         if (!OS.isNameValid(segment)) {
200             message = NLS.bind(Messages.resources_invalidName, segment);
201             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
202         }
203         return Status.OK_STATUS;
204     }
205
206     /**
207      * Validates that the given workspace path is valid for the given type. If
208      * <code>lastSegmentOnly</code> is true, it is assumed that all segments except
209      * the last one have previously been validated. This is an optimization for validating
210      * a leaf resource when it is known that the parent exists (and thus its parent path
211      * must already be valid).
212      */

213     public IStatus validatePath(IPath path, int type, boolean lastSegmentOnly) {
214         String JavaDoc message;
215
216         /* path must not be null */
217         if (path == null) {
218             message = Messages.resources_pathNull;
219             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
220         }
221
222         /* path must not have a device separator */
223         if (path.getDevice() != null) {
224             message = NLS.bind(Messages.resources_invalidCharInPath, String.valueOf(IPath.DEVICE_SEPARATOR), path);
225             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
226         }
227
228         /* path must not be the root path */
229         if (path.isRoot()) {
230             message = Messages.resources_invalidRoot;
231             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
232         }
233
234         /* path must be absolute */
235         if (!path.isAbsolute()) {
236             message = NLS.bind(Messages.resources_mustBeAbsolute, path);
237             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
238         }
239
240         /* validate segments */
241         int numberOfSegments = path.segmentCount();
242         if ((type & IResource.PROJECT) != 0) {
243             if (numberOfSegments == ICoreConstants.PROJECT_SEGMENT_LENGTH) {
244                 return validateName(path.segment(0), IResource.PROJECT);
245             } else if (type == IResource.PROJECT) {
246                 message = NLS.bind(Messages.resources_projectPath, path);
247                 return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
248             }
249         }
250         if ((type & (IResource.FILE | IResource.FOLDER)) != 0) {
251             if (numberOfSegments < ICoreConstants.MINIMUM_FILE_SEGMENT_LENGTH) {
252                 message = NLS.bind(Messages.resources_resourcePath, path);
253                 return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
254             }
255             int fileFolderType = type &= ~IResource.PROJECT;
256             int segmentCount = path.segmentCount();
257             if (lastSegmentOnly)
258                 return validateName(path.segment(segmentCount - 1), fileFolderType);
259             IStatus status = validateName(path.segment(0), IResource.PROJECT);
260             if (!status.isOK())
261                 return status;
262             // ignore first segment (the project)
263
for (int i = 1; i < segmentCount; i++) {
264                 status = validateName(path.segment(i), fileFolderType);
265                 if (!status.isOK())
266                     return status;
267             }
268             return Status.OK_STATUS;
269         }
270         message = NLS.bind(Messages.resources_invalidPath, path);
271         return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
272     }
273
274     /* (non-Javadoc)
275      * @see IWorkspace#validatePath(String, int)
276      */

277     public IStatus validatePath(String JavaDoc path, int type) {
278         /* path must not be null */
279         if (path == null) {
280             String JavaDoc message = Messages.resources_pathNull;
281             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
282         }
283         return validatePath(Path.fromOSString(path), type, false);
284     }
285
286     public IStatus validateProjectLocation(IProject context, IPath unresolvedLocation) {
287         // the default default is ok for all projects
288
if (unresolvedLocation == null)
289             return Status.OK_STATUS;
290         IPath location = workspace.getPathVariableManager().resolvePath(unresolvedLocation);
291         //check that the location is absolute
292
if (!location.isAbsolute()) {
293             String JavaDoc message;
294             if (location.segmentCount() > 0)
295                 message = NLS.bind(Messages.pathvar_undefined, location.toString(), location.segment(0));
296             else
297                 message = Messages.links_noPath;
298             return new ResourceStatus(IResourceStatus.VARIABLE_NOT_DEFINED, null, message);
299         }
300         return validateProjectLocationURI(context, URIUtil.toURI(location));
301     }
302
303     /* (non-Javadoc)
304      * @see IWorkspace#validateProjectLocation(IProject, URI)
305      */

306     public IStatus validateProjectLocationURI(IProject context, URI JavaDoc unresolvedLocation) {
307         String JavaDoc message;
308         // the default default is ok for all projects
309
if (unresolvedLocation == null)
310             return Status.OK_STATUS;
311         URI JavaDoc location = workspace.getPathVariableManager().resolveURI(unresolvedLocation);
312         //check the standard path name restrictions
313
IStatus result = validateSegments(location);
314         if (!result.isOK())
315             return result;
316         result = validateAbsolute(location, true);
317         if (!result.isOK())
318             return result;
319         //check that the URI has a legal scheme
320
try {
321             EFS.getFileSystem(location.getScheme());
322         } catch (CoreException e) {
323             return e.getStatus();
324         }
325         //overlaps with default default location can only occur with file URIs
326
if (location.getScheme().equals(EFS.SCHEME_FILE)) {
327             IPath locationPath = URIUtil.toPath(location);
328             // test if the given location overlaps the default default location
329
IPath defaultDefaultLocation = workspace.getRoot().getLocation();
330             if (FileUtil.isPrefixOf(locationPath, defaultDefaultLocation)) {
331                 message = NLS.bind(Messages.resources_overlapWorkspace, toString(location), defaultDefaultLocation.toOSString());
332                 return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
333             }
334             // test if the given location is the default location for any potential project
335
IPath parentPath = locationPath.removeLastSegments(1);
336             if (FileUtil.isPrefixOf(parentPath, defaultDefaultLocation) && FileUtil.isPrefixOf(defaultDefaultLocation, parentPath)) {
337                 message = NLS.bind(Messages.resources_overlapProject, toString(location), locationPath.lastSegment());
338                 return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
339             }
340         }
341
342         // Iterate over each known project and ensure that the location does not
343
// conflict with any of their already defined locations.
344
IProject[] projects = workspace.getRoot().getProjects();
345         for (int j = 0; j < projects.length; j++) {
346             IProject project = projects[j];
347             // since we are iterating over the project in the workspace, we
348
// know that they have been created before and must have a description
349
IProjectDescription desc = ((Project) project).internalGetDescription();
350             URI JavaDoc testLocation = desc.getLocationURI();
351             // if the project uses the default location then continue
352
if (testLocation == null)
353                 continue;
354             if (project.equals(context)) {
355                 //tolerate locations being the same if this is the project being tested
356
if (URIUtil.equals(testLocation, location))
357                     continue;
358                 //a project cannot be moved inside of its current location
359
if (!FileUtil.isPrefixOf(testLocation, location))
360                     continue;
361             } else if (!URIUtil.equals(testLocation, location)) {
362                 // a project cannot have the same location as another existing project
363
continue;
364             }
365             //in all other cases there is illegal overlap
366
message = NLS.bind(Messages.resources_overlapProject, toString(location), project.getName());
367             return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
368         }
369         //if this project exists and has linked resources, the project location cannot overlap
370
//the locations of any linked resources in that project
371
if (context.exists() && context.isOpen()) {
372             IResource[] children = null;
373             try {
374                 children = context.members();
375             } catch (CoreException e) {
376                 //ignore projects that cannot be accessed
377
}
378             if (children != null) {
379                 for (int i = 0; i < children.length; i++) {
380                     if (children[i].isLinked()) {
381                         URI JavaDoc testLocation = children[i].getLocationURI();
382                         if (testLocation != null && FileUtil.isPrefixOf(testLocation, location)) {
383                             message = NLS.bind(Messages.links_locationOverlapsLink, toString(location));
384                             return new ResourceStatus(IResourceStatus.OVERLAPPING_LOCATION, context.getFullPath(), message);
385                         }
386                     }
387                 }
388             }
389         }
390         return Status.OK_STATUS;
391     }
392
393     /**
394      * Validates the standard path name restrictions on the segments of the provided URI.
395      * @param location The URI to validate
396      * @return A status indicating if the segments of the provided URI are valid
397      */

398     private IStatus validateSegments(URI JavaDoc location) {
399         if (EFS.SCHEME_FILE.equals(location.getScheme())) {
400             IPath pathPart = new Path(location.getSchemeSpecificPart());
401             int segmentCount = pathPart.segmentCount();
402             for (int i = 0; i < segmentCount; i++) {
403                 IStatus result = validateName(pathPart.segment(i), IResource.PROJECT);
404                 if (!result.isOK())
405                     return result;
406             }
407         }
408         return Status.OK_STATUS;
409     }
410 }
Popular Tags