1 /*******************************************************************************
2  * Copyright (c) 2000, 2015 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  *     Sebastian Davids <sdavids@gmx.de> - 19346, 42056
14  *     Remy Chi Jian Suen - bug 204879
15  *     Serge Beauchamp (Freescale Semiconductor) - [229633] Group and Project Path Variable Support
16  *     Helena Halperin (IBM) - bug #299212
17  *******************************************************************************/
18 package org.eclipse.ui.internal.ide.dialogs;
19 
20 import java.net.URI;
21 import java.util.Set;
22 
23 import org.eclipse.core.filesystem.IFileInfo;
24 import org.eclipse.core.filesystem.URIUtil;
25 import org.eclipse.core.resources.IPathVariableManager;
26 import org.eclipse.core.resources.IResource;
27 import org.eclipse.core.resources.ResourcesPlugin;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IPath;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.core.runtime.Path;
32 import org.eclipse.jface.dialogs.Dialog;
33 import org.eclipse.jface.dialogs.IDialogConstants;
34 import org.eclipse.jface.dialogs.IMessageProvider;
35 import org.eclipse.jface.dialogs.TitleAreaDialog;
36 import org.eclipse.osgi.util.TextProcessor;
37 import org.eclipse.swt.SWT;
38 import org.eclipse.swt.events.SelectionAdapter;
39 import org.eclipse.swt.events.SelectionEvent;
40 import org.eclipse.swt.layout.GridData;
41 import org.eclipse.swt.layout.GridLayout;
42 import org.eclipse.swt.widgets.Button;
43 import org.eclipse.swt.widgets.Composite;
44 import org.eclipse.swt.widgets.Control;
45 import org.eclipse.swt.widgets.DirectoryDialog;
46 import org.eclipse.swt.widgets.FileDialog;
47 import org.eclipse.swt.widgets.Label;
48 import org.eclipse.swt.widgets.Shell;
49 import org.eclipse.swt.widgets.Text;
50 import org.eclipse.ui.ide.dialogs.PathVariableSelectionDialog;
51 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
52 
53 /**
54  * Dialog that prompts the user for defining a variable's name and value. It
55  * supports creating a new variable or editing an existing one. The difference
56  * between the two uses is just a matter of which messages to present to the
57  * user and whether the "Ok" button starts enabled or not.
58  */
59 public class PathVariableDialog extends TitleAreaDialog {
60 
61 	// UI widgets
62 	private Button okButton;
63 
64 	private Label variableNameLabel;
65 
66 	private Label variableValueLabel;
67 
68 	private Label variableResolvedValueLabel;
69 
70 	private Text variableNameField;
71 
72 	private Text variableValueField;
73 
74 	private Label variableResolvedValueField;
75 
76 	private Button fileButton;
77 
78 	private Button folderButton;
79 
80 	private Button variableButton;
81 	/**
82 	 * This dialog type: <code>NEW_VARIABLE</code> or
83 	 * <code>EXISTING_VARIABLE</code>.
84 	 */
85 	private int type;
86 
87 	/**
88 	 * The type of variable that can be edited in this dialog.
89 	 * <code>IResource.FILE</code> or <code>IResource.FOLDER</code>
90 	 */
91 	private int variableType;
92 
93 	/**
94 	 * The name of the variable being edited.
95 	 */
96 	private String variableName;
97 
98 	/**
99 	 * The value of the variable being edited.
100 	 */
101 	private String variableValue;
102 
103 	/**
104 	 * The original name of the variable being edited. It is used when testing
105 	 * if the current variable's name is already in use.
106 	 */
107 	private String originalName;
108 
109 	/**
110 	 * Used to select the proper message depending on the current mode
111 	 * (new/existing variable).
112 	 */
113 	private int operationMode = 0;
114 
115 	/**
116 	 * Reference to the path variable manager. It is used for validating
117 	 * variable names.
118 	 */
119 	private IPathVariableManager pathVariableManager;
120 
121 	/**
122 	 * Set of variable names currently in use. Used when warning the user that
123 	 * the currently selected name is already in use by another variable.
124 	 */
125 	private Set namesInUse;
126 
127 	/**
128 	 * The current validation status. Its value can be one of the following:<ul>
129 	 * <li><code>IMessageProvider.NONE</code> (default);</li>
130 	 * <li><code>IMessageProvider.WARNING</code>;</li>
131 	 * <li><code>IMessageProvider.ERROR</code>;</li>
132 	 * </ul>
133 	 * Used when validating the user input.
134 	 */
135 	private int validationStatus;
136 
137 	/**
138 	 * The current validation message generated by the last
139 	 * call to a <code>validate</code> method.
140 	 */
141 	private String validationMessage;
142 
143 	/**
144 	 * Whether a variable name has been entered.
145 	 */
146 	private boolean nameEntered = false;
147 
148 	/**
149 	 * Whether a variable location has been entered.
150 	 */
151 	private boolean locationEntered = false;
152 
153 	/**
154 	 * The standard message to be shown when there are no problems being
155 	 * reported.
156 	 */
157 	final private String standardMessage;
158 
159 	/**
160 	 * Constant for defining this dialog as intended to create a new variable
161 	 * (value = 1).
162 	 */
163 	public static final int NEW_VARIABLE = 1;
164 
165 	/**
166 	 * Constant for defining this dialog as intended to edit an existing
167 	 * variable (value = 2).
168 	 */
169 	public static final int EXISTING_VARIABLE = 2;
170 
171 	/**
172 	 * Constant for defining this dialog as intended to edit an existing link
173 	 * location (value = 3).
174 	 */
175 	public static final int EDIT_LINK_LOCATION = 3;
176 
177 	private IResource currentResource = null;
178 
179 	/**
180 	 * Constructs a dialog for editing a new/existing path variable.
181 	 *
182 	 * @param parentShell the parent shell
183 	 * @param type the dialog type: <code>NEW_VARIABLE</code> or
184 	 * 	<code>EXISTING_VARIABLE</code>
185 	 * @param variableType the type of variable that can be edited in
186 	 * 	this dialog. <code>IResource.FILE</code> or <code>IResource.FOLDER</code>
187 	 * @param pathVariableManager a reference to the path variable manager
188 	 * @param namesInUse a set of variable names currently in use
189 	 */
PathVariableDialog(Shell parentShell, int type, int variableType, IPathVariableManager pathVariableManager, Set namesInUse)190 	public PathVariableDialog(Shell parentShell, int type, int variableType,
191 			IPathVariableManager pathVariableManager, Set namesInUse) {
192 		super(parentShell);
193 		this.type = type;
194 		this.operationMode = type;
195 		this.variableName = ""; //$NON-NLS-1$
196 		this.variableValue = ""; //$NON-NLS-1$
197 		this.variableType = variableType;
198 		this.pathVariableManager = pathVariableManager;
199 		this.namesInUse = namesInUse;
200 
201 		switch (operationMode) {
202 		case NEW_VARIABLE:
203 			this.standardMessage = IDEWorkbenchMessages.PathVariableDialog_message_newVariable;
204 			break;
205 		case EXISTING_VARIABLE:
206 			this.standardMessage = IDEWorkbenchMessages.PathVariableDialog_message_existingVariable;
207 			break;
208 		default:
209 			this.standardMessage = IDEWorkbenchMessages.PathVariableDialog_message_editLocation;
210 			break;
211 		}
212 	}
213 
214 	/**
215 	 * Configures this dialog's shell, setting the shell's text.
216 	 *
217 	 * @see org.eclipse.jface.window.Window#configureShell(Shell)
218 	 */
219 	@Override
configureShell(Shell shell)220 	protected void configureShell(Shell shell) {
221 		super.configureShell(shell);
222 		switch (operationMode) {
223 		case NEW_VARIABLE:
224 			shell.setText(IDEWorkbenchMessages.PathVariableDialog_shellTitle_newVariable);
225 			break;
226 		case EXISTING_VARIABLE:
227 			shell.setText(IDEWorkbenchMessages.PathVariableDialog_shellTitle_existingVariable);
228 			break;
229 		default:
230 			shell.setText(IDEWorkbenchMessages.PathVariableDialog_shellTitle_editLocation);
231 			break;
232 		}
233 	}
234 
235 	/**
236 	 * Creates and returns the contents of this dialog (except for the button bar).
237 	 *
238 	 * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea
239 	 */
240 	@Override
createDialogArea(Composite parent)241 	protected Control createDialogArea(Composite parent) {
242 		// top level composite
243 		Composite parentComposite = (Composite) super.createDialogArea(parent);
244 
245 		initializeDialogUnits(parentComposite);
246 
247 		// creates dialog area composite
248 		Composite contents = createComposite(parentComposite);
249 
250 		// creates and lay outs dialog area widgets
251 		createWidgets(contents);
252 
253 		// validate possibly already incorrect variable definitions
254 		if (type == EXISTING_VARIABLE) {
255 			nameEntered = locationEntered = true;
256 			validateVariableValue();
257 		}
258 
259 		Dialog.applyDialogFont(parentComposite);
260 
261 		return contents;
262 	}
263 
264 	/**
265 	 * Creates and configures this dialog's main composite.
266 	 *
267 	 * @param parentComposite parent's composite
268 	 * @return this dialog's main composite
269 	 */
createComposite(Composite parentComposite)270 	private Composite createComposite(Composite parentComposite) {
271 		// creates a composite with standard margins and spacing
272 		Composite contents = new Composite(parentComposite, SWT.NONE);
273 
274 		contents.setLayout(new GridLayout(3, false));
275 		contents.setLayoutData(new GridData(GridData.FILL_BOTH));
276 
277 		switch (operationMode) {
278 		case NEW_VARIABLE:
279 			setTitle(IDEWorkbenchMessages.PathVariableDialog_dialogTitle_newVariable);
280 			break;
281 		case EXISTING_VARIABLE:
282 			setTitle(IDEWorkbenchMessages.PathVariableDialog_dialogTitle_existingVariable);
283 			break;
284 		default:
285 			setTitle(IDEWorkbenchMessages.PathVariableDialog_dialogTitle_editLinkLocation);
286 			break;
287 		}
288 		setMessage(standardMessage);
289 		return contents;
290 	}
291 
292 	/**
293 	 * Creates widgets for this dialog.
294 	 *
295 	 * @param contents the parent composite where to create widgets
296 	 */
createWidgets(Composite contents)297 	private void createWidgets(Composite contents) {
298 		String nameLabelText = IDEWorkbenchMessages.PathVariableDialog_variableName;
299 		String valueLabelText = IDEWorkbenchMessages.PathVariableDialog_variableValue;
300 		String resolvedValueLabelText = IDEWorkbenchMessages.PathVariableDialog_variableResolvedValue;
301 
302 		if (operationMode != EDIT_LINK_LOCATION) {
303 			// variable name label
304 			variableNameLabel = new Label(contents, SWT.LEAD);
305 			variableNameLabel.setText(nameLabelText);
306 			variableNameLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
307 
308 			// variable name field.  Attachments done after all widgets created.
309 			variableNameField = new Text(contents, SWT.SINGLE | SWT.BORDER);
310 			variableNameField.setText(variableName);
311 			variableNameField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
312 					false, 2, 1));
313 			variableNameField.addModifyListener(event -> variableNameModified());
314 		}
315 
316 		// variable value label
317 		variableValueLabel = new Label(contents, SWT.LEAD);
318 		variableValueLabel.setText(valueLabelText);
319 		variableValueLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
320 
321 		// variable value field.  Attachments done after all widgets created.
322 		variableValueField = new Text(contents, SWT.SINGLE | SWT.BORDER);
323 		variableValueField.setText(variableValue);
324 		variableValueField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
325 				false));
326 		variableValueField.addModifyListener(event -> variableValueModified());
327 
328 		Composite buttonsComposite = new Composite(contents, SWT.NONE);
329 		buttonsComposite.setLayoutData(new GridData(SWT.END, SWT.CENTER, false,
330 				false, 1, 1));
331 		GridLayout layout = new GridLayout(0, true);
332 		layout.marginWidth = 0;
333 		layout.marginHeight = 0;
334 		buttonsComposite.setLayout(layout);
335 
336 		if ((variableType & IResource.FILE) != 0) {
337 			layout.numColumns++;
338 			// select file path button
339 			fileButton = new Button(buttonsComposite, SWT.PUSH);
340 			fileButton.setText(IDEWorkbenchMessages.PathVariableDialog_file);
341 			fileButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
342 					false));
343 
344 			fileButton.addSelectionListener(new SelectionAdapter() {
345 				@Override
346 				public void widgetSelected(SelectionEvent e) {
347 					selectFile();
348 				}
349 			});
350 			setButtonLayoutData(fileButton);
351 		}
352 
353 		if ((variableType & IResource.FOLDER) != 0) {
354 			layout.numColumns++;
355 			// select folder path button
356 			folderButton = new Button(buttonsComposite, SWT.PUSH);
357 			folderButton.setText(IDEWorkbenchMessages.PathVariableDialog_folder);
358 			folderButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
359 					false));
360 
361 			folderButton.addSelectionListener(new SelectionAdapter() {
362 				@Override
363 				public void widgetSelected(SelectionEvent e) {
364 					selectFolder();
365 				}
366 			});
367 			setButtonLayoutData(folderButton);
368 		}
369 
370 		// the workspace path variable manager does not support variables.
371 		if (currentResource != null) {
372 			layout.numColumns++;
373 			variableButton = new Button(buttonsComposite, SWT.PUSH);
374 			variableButton.setText(IDEWorkbenchMessages.PathVariableDialog_variable);
375 
376 			variableButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
377 				false));
378 
379 			variableButton.addSelectionListener(new SelectionAdapter() {
380 				@Override
381 				public void widgetSelected(SelectionEvent e) {
382 					selectVariable();
383 				}
384 			});
385 			setButtonLayoutData(variableButton);
386 
387 			// variable value label
388 			variableResolvedValueLabel = new Label(contents, SWT.LEAD);
389 			variableResolvedValueLabel.setText(resolvedValueLabelText);
390 
391 			// variable value field.  Attachments done after all widgets created.
392 			variableResolvedValueField = new Label(contents, SWT.LEAD | SWT.SINGLE | SWT.READ_ONLY);
393 			variableResolvedValueField.setText(TextProcessor.process(getVariableResolvedValue()));
394 			variableResolvedValueField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
395 					false, 2, 1));
396 		}
397 	}
398 
getPathVariableManager()399 	private IPathVariableManager getPathVariableManager() {
400 		if (currentResource != null)
401 			return currentResource.getPathVariableManager();
402 		return ResourcesPlugin.getWorkspace().getPathVariableManager();
403 	}
404 
getVariableResolvedValue()405 	private String getVariableResolvedValue() {
406 		if (currentResource != null) {
407 			IPathVariableManager pathVariableManager2 = currentResource.getPathVariableManager();
408 			String[] variables = pathVariableManager2.getPathVariableNames();
409 			String internalFormat = pathVariableManager2.convertFromUserEditableFormat(variableValue, operationMode == EDIT_LINK_LOCATION);
410 			URI uri = URIUtil.toURI(Path.fromOSString(internalFormat));
411 			URI resolvedURI = pathVariableManager2.resolveURI(uri);
412 			String resolveValue = URIUtil.toPath(resolvedURI).toOSString();
413 			// Delete intermediate variables that might have been created as
414 			// as a side effect of converting arbitrary relative paths to an internal string.
415 			for (String newVariable : pathVariableManager2.getPathVariableNames()) {
416 				boolean found = false;
417 				for (String variable : variables) {
418 					if (variable.equals(newVariable)) {
419 						found = true;
420 						break;
421 					}
422 				}
423 				if (!found) {
424 					try {
425 						pathVariableManager2.setURIValue(newVariable, null);
426 					} catch (CoreException e) {
427 						// do nothing
428 					}
429 				}
430 			}
431 			return resolveValue;
432 		}
433 		return variableValue;
434 	}
435 
436 	/**
437 	 * Fires validations (variable name first) and updates enabled state for the
438 	 * "Ok" button accordingly.
439 	 */
variableNameModified()440 	private void variableNameModified() {
441 		// updates and validates the variable name
442 		variableName = variableNameField.getText();
443 		validationStatus = IMessageProvider.NONE;
444 		okButton.setEnabled(validateVariableName() && validateVariableValue() && variableValue.length() != 0);
445 		nameEntered = true;
446 	}
447 
448 	/**
449 	 * Fires validations (variable value first) and updates enabled state for the
450 	 * "Ok" button accordingly.
451 	 */
variableValueModified()452 	private void variableValueModified() {
453 		// updates and validates the variable value
454 		variableValue = variableValueField.getText().trim();
455 		validationStatus = IMessageProvider.NONE;
456 		okButton.setEnabled(validateVariableValue() && validateVariableName());
457 		locationEntered = true;
458 		if (variableResolvedValueField != null)
459 			variableResolvedValueField.setText(TextProcessor.process(getVariableResolvedValue()));
460 	}
461 
462 	/**
463 	 * Opens a dialog where the user can select a folder path.
464 	 */
selectFolder()465 	private void selectFolder() {
466 		DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.SHEET);
467 		dialog.setText(IDEWorkbenchMessages.PathVariableDialog_selectFolderTitle);
468 		dialog.setMessage(IDEWorkbenchMessages.PathVariableDialog_selectFolderMessage);
469 		String filterPath = getVariableResolvedValue();
470 		dialog.setFilterPath(filterPath);
471 		String res = dialog.open();
472 		if (res != null) {
473 			variableValue = new Path(res).makeAbsolute().toOSString();
474 			variableValueField.setText(variableValue);
475 		}
476 	}
477 
478 	/**
479 	 * Opens a dialog where the user can select a file path.
480 	 */
selectFile()481 	private void selectFile() {
482 		FileDialog dialog = new FileDialog(getShell(), SWT.SHEET);
483 		dialog.setText(IDEWorkbenchMessages.PathVariableDialog_selectFileTitle);
484 		String filterPath = getVariableResolvedValue();
485 		dialog.setFilterPath(filterPath);
486 		String res = dialog.open();
487 		if (res != null) {
488 			variableValue = new Path(res).makeAbsolute().toOSString();
489 			variableValueField.setText(variableValue);
490 		}
491 	}
492 
selectVariable()493 	private void selectVariable() {
494 		PathVariableSelectionDialog dialog = new PathVariableSelectionDialog(
495 				getShell(), IResource.FILE | IResource.FOLDER);
496 		dialog.setResource(currentResource);
497 		if (dialog.open() == IDialogConstants.OK_ID) {
498 			String[] variableNames = (String[]) dialog.getResult();
499 			if (variableNames != null && variableNames.length == 1) {
500 				String newValue = variableNames[0];
501 				IPath path = Path.fromOSString(newValue);
502 				if (operationMode != EDIT_LINK_LOCATION && currentResource != null && !path.isAbsolute() && path.segmentCount() > 0) {
503 					path = buildVariableMacro(path);
504 					newValue = path.toOSString();
505 				}
506 				variableValue = newValue;
507 				variableValueField.setText(newValue);
508 			}
509 		}
510 	}
511 
buildVariableMacro(IPath relativeSrcValue)512 	private IPath buildVariableMacro(IPath relativeSrcValue) {
513 		String variable = relativeSrcValue.segment(0);
514 		variable = "${" + variable + "}";  //$NON-NLS-1$//$NON-NLS-2$
515 		return Path.fromOSString(variable).append(relativeSrcValue.removeFirstSegments(1));
516 	}
517 
518 	/**
519 	 * Adds buttons to this dialog's button bar.
520 	 *
521 	 * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar
522 	 */
523 	@Override
createButtonsForButtonBar(Composite parent)524 	protected void createButtonsForButtonBar(Composite parent) {
525 		okButton = createButton(parent, IDialogConstants.OK_ID,
526 				IDialogConstants.OK_LABEL, true);
527 		okButton.setEnabled(type == EXISTING_VARIABLE);
528 
529 		createButton(parent, IDialogConstants.CANCEL_ID,
530 				IDialogConstants.CANCEL_LABEL, false);
531 	}
532 
533 	/**
534 	 * Validates the current variable name, and updates this dialog's message.
535 	 *
536 	 * @return true if the name is valid, false otherwise
537 	 */
validateVariableName()538 	private boolean validateVariableName() {
539 		boolean allowFinish = false;
540 
541 		if (operationMode == EDIT_LINK_LOCATION)
542 			return true;
543 
544 		// if the current validationStatus is ERROR, no additional validation applies
545 		if (validationStatus == IMessageProvider.ERROR) {
546 			return false;
547 		}
548 
549 		// assumes everything will be ok
550 		String message = standardMessage;
551 		int newValidationStatus = IMessageProvider.NONE;
552 
553 		if (variableName.length() == 0) {
554 			// the variable name is empty
555 			if (nameEntered) {
556 				// a name was entered before and is now empty
557 				newValidationStatus = IMessageProvider.ERROR;
558 				message = IDEWorkbenchMessages.PathVariableDialog_variableNameEmptyMessage;
559 			}
560 		} else {
561 			IStatus status = pathVariableManager.validateName(variableName);
562 			if (!status.isOK()) {
563 				// the variable name is not valid
564 				newValidationStatus = IMessageProvider.ERROR;
565 				message = status.getMessage();
566 			} else if (namesInUse.contains(variableName)
567 					&& !variableName.equals(originalName)) {
568 				// the variable name is already in use
569 				message = IDEWorkbenchMessages.PathVariableDialog_variableAlreadyExistsMessage;
570 				newValidationStatus = IMessageProvider.ERROR;
571 			} else {
572 				allowFinish = true;
573 			}
574 		}
575 
576 		// overwrite the current validation status / message only if everything is ok (clearing them)
577 		// or if we have a more serious problem than the current one
578 		if (validationStatus == IMessageProvider.NONE
579 				|| newValidationStatus == IMessageProvider.ERROR) {
580 			validationStatus = newValidationStatus;
581 			validationMessage = message;
582 		}
583 		// only set the message here if it is not going to be set in
584 		// validateVariableValue to avoid flashing.
585 		if (allowFinish == false) {
586 			setMessage(validationMessage, validationStatus);
587 		}
588 		return allowFinish;
589 	}
590 
591 	/**
592 	 * Validates the current variable value, and updates this dialog's message.
593 	 *
594 	 * @return true if the value is valid, false otherwise
595 	 */
validateVariableValue()596 	private boolean validateVariableValue() {
597 		boolean allowFinish = false;
598 
599 		// if the current validationStatus is ERROR, no additional validation applies
600 		if (validationStatus == IMessageProvider.ERROR) {
601 			return false;
602 		}
603 
604 		// assumes everything will be ok
605 		String message = standardMessage;
606 		int newValidationStatus = IMessageProvider.NONE;
607 
608 		if (variableValue.length() == 0) {
609 			// the variable value is empty
610 			if (locationEntered) {
611 				// a location value was entered before and is now empty
612 				newValidationStatus = IMessageProvider.ERROR;
613 				message = IDEWorkbenchMessages.PathVariableDialog_variableValueEmptyMessage;
614 			}
615 		}
616 		if (currentResource != null) {
617 			// While editing project path variables, the variable value can
618 			// contain macros such as "${foo}\etc"
619 			allowFinish = true;
620 			String resolvedValue = getVariableResolvedValue();
621 			IPath resolvedPath = Path.fromOSString(resolvedValue);
622 			if (!IDEResourceInfoUtils.exists(resolvedPath.toOSString())) {
623 				// the path does not exist (warning)
624 				message = IDEWorkbenchMessages.PathVariableDialog_pathDoesNotExistMessage;
625 				newValidationStatus = IMessageProvider.WARNING;
626 			} else {
627 				IFileInfo info = IDEResourceInfoUtils.getFileInfo(resolvedPath
628 						.toOSString());
629 				if ((info.isDirectory() && ((variableType & IResource.FOLDER) == 0)) ||
630 						(!info.isDirectory() && ((variableType & IResource.FILE) == 0))){
631 					allowFinish = false;
632 					newValidationStatus = IMessageProvider.ERROR;
633 					if (((variableType & IResource.FOLDER) != 0))
634 						message = IDEWorkbenchMessages.PathVariableDialog_variableValueIsWrongTypeFolder;
635 					else
636 						message = IDEWorkbenchMessages.PathVariableDialog_variableValueIsWrongTypeFile;
637 				}
638 			}
639 		} else if (!Path.EMPTY.isValidPath(variableValue)) {
640 			// the variable value is an invalid path
641 			message = IDEWorkbenchMessages.PathVariableDialog_variableValueInvalidMessage;
642 			newValidationStatus = IMessageProvider.ERROR;
643 		} else if (!new Path(variableValue).isAbsolute()) {
644 			// the variable value is a relative path
645 			message = IDEWorkbenchMessages.PathVariableDialog_pathIsRelativeMessage;
646 			newValidationStatus = IMessageProvider.ERROR;
647 		} else if (!IDEResourceInfoUtils.exists(variableValue)) {
648 			// the path does not exist (warning)
649 			message = IDEWorkbenchMessages.PathVariableDialog_pathDoesNotExistMessage;
650 			newValidationStatus = IMessageProvider.WARNING;
651 			allowFinish = true;
652 		} else {
653 			allowFinish = true;
654 		}
655 
656 		// overwrite the current validation status / message only if everything is ok (clearing them)
657 		// or if we have a more serious problem than the current one
658 		if (validationStatus == IMessageProvider.NONE
659 				|| newValidationStatus > validationStatus) {
660 			validationStatus = newValidationStatus;
661 			validationMessage = message;
662 		}
663 		setMessage(validationMessage, validationStatus);
664 		return allowFinish;
665 	}
666 
667 	/**
668 	 * Returns the variable name.
669 	 *
670 	 * @return the variable name
671 	 */
getVariableName()672 	public String getVariableName() {
673 		return variableName;
674 	}
675 
676 	/**
677 	 * Returns the variable value.
678 	 *
679 	 * @return the variable value
680 	 */
getVariableValue()681 	public String getVariableValue() {
682 		if (currentResource != null) {
683 			return getPathVariableManager().convertFromUserEditableFormat(variableValue, operationMode == EDIT_LINK_LOCATION);
684 		}
685 		return variableValue;
686 	}
687 
688 	/**
689 	 * Sets the variable name.
690 	 *
691 	 * @param variableName the new variable name
692 	 */
setVariableName(String variableName)693 	public void setVariableName(String variableName) {
694 		this.variableName = variableName.trim();
695 		this.originalName = this.variableName;
696 	}
697 
698 	/**
699 	 * Sets the variable value.
700 	 *
701 	 * @param variable the new variable value
702 	 */
setVariableValue(String variable)703 	public void setVariableValue(String variable) {
704 		String userEditableString = getPathVariableManager().convertToUserEditableFormat(variable, operationMode == EDIT_LINK_LOCATION);
705 		variableValue = userEditableString;
706 	}
707 
708 	/**
709 	 * @param resource
710 	 */
setResource(IResource resource)711 	public void setResource(IResource resource) {
712 		currentResource = resource;
713 	}
714 
715 	/**
716 	 * @param location
717 	 */
setLinkLocation(IPath location)718 	public void setLinkLocation(IPath location) {
719 		String userEditableString = getPathVariableManager().convertToUserEditableFormat(location.toOSString(), operationMode == EDIT_LINK_LOCATION);
720 		variableValue = userEditableString;
721 	}
722 
723 	@Override
isResizable()724 	protected boolean isResizable() {
725 		return true;
726 	}
727 
728 }
729