Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 285804 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/ui/internal/wizards/datatransfer/WizardFileSystemResourceImportPage1.java (-5 / +7 lines)
Lines 57-65 Link Here
57
import org.eclipse.ui.dialogs.FileSystemElement;
57
import org.eclipse.ui.dialogs.FileSystemElement;
58
import org.eclipse.ui.dialogs.WizardResourceImportPage;
58
import org.eclipse.ui.dialogs.WizardResourceImportPage;
59
import org.eclipse.ui.internal.ide.dialogs.IElementFilter;
59
import org.eclipse.ui.internal.ide.dialogs.IElementFilter;
60
import org.eclipse.ui.internal.ide.filesystem.FileSystemStructureProvider;
60
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
61
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
61
import org.eclipse.ui.model.WorkbenchContentProvider;
62
import org.eclipse.ui.model.WorkbenchContentProvider;
62
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
63
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
63
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
64
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
64
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
65
65
Lines 87-92 Link Here
87
87
88
    //A boolean to indicate if the user has typed anything
88
    //A boolean to indicate if the user has typed anything
89
    private boolean entryChanged = false;
89
    private boolean entryChanged = false;
90
    
91
    private FileSystemStructureProvider fileSystemStructureProvider = new FileSystemStructureProvider();
90
92
91
    // dialog store id constants
93
    // dialog store id constants
92
    private final static String STORE_SOURCE_NAMES_ID = "WizardFileSystemResourceImportPage1.STORE_SOURCE_NAMES_ID";//$NON-NLS-1$
94
    private final static String STORE_SOURCE_NAMES_ID = "WizardFileSystemResourceImportPage1.STORE_SOURCE_NAMES_ID";//$NON-NLS-1$
Lines 478-484 Link Here
478
                if (o instanceof MinimizedFileSystemElement) {
480
                if (o instanceof MinimizedFileSystemElement) {
479
                    MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
481
                    MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
480
                    return element.getFiles(
482
                    return element.getFiles(
481
                            FileSystemStructureProvider.INSTANCE).getChildren(
483
                    		fileSystemStructureProvider).getChildren(
482
                            element);
484
                            element);
483
                }
485
                }
484
                return new Object[0];
486
                return new Object[0];
Lines 499-505 Link Here
499
		}
501
		}
500
502
501
        return selectFiles(sourceDirectory,
503
        return selectFiles(sourceDirectory,
502
                FileSystemStructureProvider.INSTANCE);
504
        		fileSystemStructureProvider);
503
    }
505
    }
504
506
505
    /**
507
    /**
Lines 512-518 Link Here
512
                if (o instanceof MinimizedFileSystemElement) {
514
                if (o instanceof MinimizedFileSystemElement) {
513
                    MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
515
                    MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
514
                    return element.getFolders(
516
                    return element.getFolders(
515
                            FileSystemStructureProvider.INSTANCE).getChildren(
517
                    		fileSystemStructureProvider).getChildren(
516
                            element);
518
                            element);
517
                }
519
                }
518
                return new Object[0];
520
                return new Object[0];
Lines 644-650 Link Here
644
     */
646
     */
645
    protected boolean importResources(List fileSystemObjects) {
647
    protected boolean importResources(List fileSystemObjects) {
646
        ImportOperation operation = new ImportOperation(getContainerFullPath(),
648
        ImportOperation operation = new ImportOperation(getContainerFullPath(),
647
                getSourceDirectory(), FileSystemStructureProvider.INSTANCE,
649
                getSourceDirectory(), fileSystemStructureProvider,
648
                this, fileSystemObjects);
650
                this, fileSystemObjects);
649
651
650
        operation.setContext(getShell());
652
        operation.setContext(getShell());
(-)src/org/eclipse/ui/internal/ide/filesystem/PrefixPool.java (+210 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Wind River Systems, Inc. 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
 * Martin Oberhuber (Wind River) - initial API and implementation for [105554] 
10
 *******************************************************************************/
11
12
package org.eclipse.ui.internal.ide.filesystem;
13
14
import java.util.Arrays;
15
16
/**
17
 * A pool of Strings for doing prefix checks against multiple
18
 * candidates.
19
 * <p>
20
 * Allows to enter a list of Strings, and then perform the
21
 * following checks:
22
 * <ul>
23
 *   <li>{@link #containsAsPrefix(String)} - check whether a given
24
 *       String s is a prefix of any String in the pool.</li>
25
 *   <li>{@link #hasPrefixOf(String)} - check whether any String
26
 *       in the pool is a prefix of the given String s. 
27
 * </ul>
28
 * The prefix pool is always kept normalized, i.e. no element of
29
 * the pool is a prefix of any other element in the pool. In order
30
 * to maintain this constraint, there are two methods for adding
31
 * Strings to the pool:
32
 * <ul>
33
 *   <li>{@link #insertLonger(String)} - add a String s to the pool,
34
 *       and remove any existing prefix of s from the pool.</li>
35
 *   <li>{@link #insertShorter(String)} - add a String s to the pool,
36
 *       and remove any existing Strings sx from the pool which 
37
 *       contain s as prefix.</li>
38
 * </ul>
39
 * The PrefixPool grows as needed when adding Strings. Typically,
40
 * it is used for prefix checks on absolute paths of a tree.
41
 * </p><p> 
42
 * This class is not thread-safe: no two threads may add or
43
 * check items at the same time.
44
 * 
45
 * @since 3.5.1
46
 * 
47
 * Class copied from org.eclipse.core.internal.localstore.PrefixPool
48
 * 
49
 */
50
public class PrefixPool {
51
	private String[] pool;
52
	private int size;
53
54
	/**
55
	 * Constructor.
56
	 * @param initialCapacity the initial size of the 
57
	 *     internal array holding the String pool. Must
58
	 *     be greater than 0.
59
	 */
60
	public PrefixPool(int initialCapacity) {
61
		if (initialCapacity <= 0)
62
			throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); //$NON-NLS-1$
63
		pool = new String[initialCapacity];
64
		size = 0;
65
	}
66
67
	/**
68
	 * Clears the prefix pool, allowing all items to be
69
	 * garbage collected. Does not change the capacity
70
	 * of the pool.
71
	 */
72
	public/*synchronized*/void clear() {
73
		Arrays.fill(pool, 0, size, null);
74
		size = 0;
75
	}
76
77
	/**
78
	 * Return the current size of prefix pool.
79
	 * @return the number of elements in the pool. 
80
	 */
81
	public/*synchronized*/int size() {
82
		return size;
83
	}
84
85
	/**
86
	 * Ensure that there is room for at least one more element.
87
	 */
88
	private void checkCapacity() {
89
		if (size + 1 >= pool.length) {
90
			String[] newprefixList = new String[2 * pool.length];
91
			System.arraycopy(pool, 0, newprefixList, 0, pool.length);
92
			Arrays.fill(pool, null); //help the garbage collector
93
			pool = newprefixList;
94
		}
95
	}
96
97
	/**
98
	 * Insert a String s into the pool of known prefixes, removing
99
	 * any existing prefix of it.
100
	 * <p>
101
	 * If any existing prefix of this String is found in the pool,
102
	 * it is replaced by the new longer one in order to maintain
103
	 * the constraint of keeping the pool normalized.
104
	 * </p><p>
105
	 * If it turns out that s is actually a prefix or equal to
106
	 * an existing element in the pool (so it is essentially
107
	 * shorter), this method returns with no operation in order
108
	 * to maintain the constraint that the pool remains normalized.
109
	 * </p>
110
	 * @param s the String to insert.
111
	 */
112
	public/*synchronized*/void insertLonger(String s) {
113
		//check in reverse order since we expect some locality
114
		for (int i = size - 1; i >= 0; i--) {
115
			if (pool[i].startsWith(s)) {
116
				//prefix of an existing String --> no-op
117
				return;
118
			} else if (s.startsWith(pool[i])) {
119
				//replace, since a longer s has more prefixes than a short one
120
				pool[i] = s;
121
				return;
122
			}
123
		}
124
		checkCapacity();
125
		pool[size] = s;
126
		size++;
127
	}
128
129
	/**
130
	 * Insert a String s into the pool of known prefixes, removing
131
	 * any Strings that have s as prefix.
132
	 * <p>
133
	 * If this String is a prefix of any existing String in the pool,
134
	 * all elements that contain the new String as prefix are removed
135
	 * and return value <code>true</code> is returned.
136
	 * </p><p>
137
	 * Otherwise, the new String is added to the pool unless an 
138
	 * equal String or e prefix of it exists there already (so
139
	 * it is essentially equal or longer than an existing prefix).
140
	 * In all these cases, <code>false</code> is returned since
141
	 * no prefixes were replaced.
142
	 * </p>
143
	 * @param s the String to insert.
144
	 * @return <code>true</code>if any longer elements have been
145
	 *     removed.
146
	 */
147
	public/*synchronized*/boolean insertShorter(String s) {
148
		boolean replaced = false;
149
		//check in reverse order since we expect some locality
150
		for (int i = size - 1; i >= 0; i--) {
151
			if (s.startsWith(pool[i])) {
152
				//longer or equal to an existing prefix - nothing to do
153
				return false;
154
			} else if (pool[i].startsWith(s)) {
155
				if (replaced) {
156
					//replaced before, so shrink the array.
157
					//Safe since we are iterating in reverse order.
158
					System.arraycopy(pool, i + 1, pool, i, size - i - 1);
159
					size--;
160
					pool[size] = null;
161
				} else {
162
					//replace, since this is a shorter s
163
					pool[i] = s;
164
					replaced = true;
165
				}
166
			}
167
		}
168
		if (!replaced) {
169
			//append at the end
170
			checkCapacity();
171
			pool[size] = s;
172
			size++;
173
		}
174
		return replaced;
175
	}
176
177
	/**
178
	 * Check if the given String s is a prefix of any of Strings
179
	 * in the pool.
180
	 * @param s a s to check for being a prefix
181
	 * @return <code>true</code> if the passed s is a prefix
182
	 *     of any of the Strings contained in the pool.
183
	 */
184
	public/*synchronized*/boolean containsAsPrefix(String s) {
185
		//check in reverse order since we expect some locality
186
		for (int i = size - 1; i >= 0; i--) {
187
			if (pool[i].startsWith(s)) {
188
				return true;
189
			}
190
		}
191
		return false;
192
	}
193
194
	/**
195
	 * Test if the String pool contains any one that is a prefix
196
	 * of the given String s. 
197
	 * @param s the String to test
198
	 * @return <code>true</code> if the String pool contains a
199
	 *     prefix of the given String.
200
	 */
201
	public/*synchronized*/boolean hasPrefixOf(String s) {
202
		for (int i = size - 1; i >= 0; i--) {
203
			if (s.startsWith(pool[i])) {
204
				return true;
205
			}
206
		}
207
		return false;
208
	}
209
210
}
(-)src/org/eclipse/ui/internal/ide/filesystem/FileSystemStructureProvider.java (+146 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 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.ui.internal.ide.filesystem;
12
13
import java.io.File;
14
import java.io.FileInputStream;
15
import java.io.FileNotFoundException;
16
import java.io.IOException;
17
import java.io.InputStream;
18
import java.util.ArrayList;
19
import java.util.List;
20
21
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
22
import org.eclipse.ui.internal.ide.filesystem.PrefixPool;
23
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
24
25
/**
26
 * This class provides information regarding the structure and
27
 * content of specified file system File objects.
28
 * 
29
 * class copied from org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider as its singleton
30
 */
31
public class FileSystemStructureProvider implements IImportStructureProvider {
32
33
    private PrefixPool pathPrefixHistory;
34
    private PrefixPool rootPathHistory; 
35
36
    /**
37
     * Creates an instance of <code>FileSystemStructureProvider</code>.
38
     */
39
    public FileSystemStructureProvider() {
40
        super();
41
    }
42
43
    /* (non-Javadoc)
44
     * Method declared on IImportStructureProvider
45
     */
46
    public List getChildren(Object element) {
47
        File folder = (File) element;
48
        String[] children = folder.list();
49
        int childrenLength = children == null ? 0 : children.length;
50
        List result = new ArrayList(childrenLength);
51
52
        for (int i = 0; i < childrenLength; i++) {
53
        	File file = new File(folder, children[i]);
54
        	if(file.isDirectory() && isRecursiveLink(folder, file))
55
        		continue;
56
        	result.add(file);
57
		}
58
        
59
        return result;
60
    }
61
62
    private void initLinkHistoriesIfNeeded(){
63
    	if(pathPrefixHistory == null){
64
    		pathPrefixHistory = new PrefixPool(20);
65
    		rootPathHistory = new PrefixPool(20);
66
    	}
67
    }
68
    
69
	private boolean isRecursiveLink(File parentFile, File childFile) {
70
71
		boolean isRecursive = false;
72
		try {
73
74
			//Need canonical paths to check all other possibilities
75
			String parentPath = parentFile.getCanonicalPath() + '/';
76
			String childPath = childFile.getCanonicalPath() + '/';
77
			
78
			//get or instantiate the prefix and root path histories.
79
			//Might be done earlier - for now, do it on demand.
80
			
81
			initLinkHistoriesIfNeeded();
82
			
83
			//insert the parent for checking loops
84
			pathPrefixHistory.insertLonger(parentPath);
85
			if (pathPrefixHistory.containsAsPrefix(childPath)) {
86
				//found a potential loop: is it spanning up a new tree?
87
				if (!rootPathHistory.insertShorter(childPath)) {
88
					//not spanning up a new tree, so it is a real loop.
89
					isRecursive = true;
90
				}
91
			} else if (rootPathHistory.hasPrefixOf(childPath)) {
92
				//child points into a different portion of the tree that we visited already before, or will certainly visit.
93
				//This does not introduce a loop yet, but introduces duplicate resources.
94
				//TODO Ideally, such duplicates should be modelled as linked resources. See bug 105534
95
				isRecursive = false;
96
			} else {
97
				//child neither introduces a loop nor points to a known tree.
98
				//It probably spans up a new tree of potential prefixes.
99
				rootPathHistory.insertShorter(childPath);
100
			}
101
		} catch (IOException e) {
102
			//ignore
103
		}
104
		return isRecursive;
105
	}
106
107
	/* (non-Javadoc)
108
     * Method declared on IImportStructureProvider
109
     */
110
    public InputStream getContents(Object element) {
111
        try {
112
            return new FileInputStream((File) element);
113
        } catch (FileNotFoundException e) {
114
        	IDEWorkbenchPlugin.log(e.getLocalizedMessage(), e);
115
            return null;
116
        }
117
    }
118
119
    /* (non-Javadoc)
120
     * Method declared on IImportStructureProvider
121
     */
122
    public String getFullPath(Object element) {
123
        return ((File) element).getPath();
124
    }
125
126
    /* (non-Javadoc)
127
     * Method declared on IImportStructureProvider
128
     */
129
    public String getLabel(Object element) {
130
131
        //Get the name - if it is empty then return the path as it is a file root
132
        File file = (File) element;
133
        String name = file.getName();
134
        if (name.length() == 0) {
135
			return file.getPath();
136
		}
137
        return name;
138
    }
139
140
    /* (non-Javadoc)
141
     * Method declared on IImportStructureProvider
142
     */
143
    public boolean isFolder(Object element) {
144
        return ((File) element).isDirectory();
145
    }
146
}

Return to bug 285804