/* * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.util; import consulo.fileTypes.ArchiveFileType; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.StandardFileSystems; import com.intellij.openapi.vfs.VirtualFile; import consulo.vfs.util.ArchiveVfsUtil; import com.intellij.util.containers.FilteringIterator; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.*; import static com.intellij.util.containers.ContainerUtil.*; public class PathsList { private final List<String> myPath = new ArrayList<String>(); private final List<String> myPathTail = new ArrayList<String>(); private final Set<String> myPathSet = new HashSet<String>(); private static final Function<String, VirtualFile> PATH_TO_LOCAL_VFILE = new NullableFunction<String, VirtualFile>() { @Override public VirtualFile fun(String path) { return StandardFileSystems.local().findFileByPath(path.replace(File.separatorChar, '/')); } }; private static final Function<VirtualFile, String> LOCAL_PATH = new Function<VirtualFile, String>() { @Override public String fun(VirtualFile file) { return PathUtil.getLocalPath(file); } }; private static final Function<String, VirtualFile> PATH_TO_DIR = new NullableFunction<String, VirtualFile>() { @Override public VirtualFile fun(String s) { final FileType fileType = FileTypeRegistry.getInstance().getFileTypeByFileName(s); final VirtualFile localFile = PATH_TO_LOCAL_VFILE.fun(s); if (localFile == null) return null; if (fileType instanceof ArchiveFileType && !localFile.isDirectory()) { return ArchiveVfsUtil.getArchiveRootForLocalFile(localFile); } return localFile; } }; public void add(@NonNls String path) { addAllLast(chooseFirstTimeItems(path), myPath); } public void remove(@NotNull String path) { myPath.remove(path); myPathTail.remove(path); myPathSet.remove(path); } public void add(VirtualFile file) { add(LOCAL_PATH.fun(file)); } public void addFirst(@NonNls String path) { final Iterator<String> elements = chooseFirstTimeItems(path); int index = 0; while (elements.hasNext()) { final String element = elements.next(); myPath.add(index, element); myPathSet.add(element); index++; } } public void addTail(String path) { addAllLast(chooseFirstTimeItems(path), myPathTail); } private Iterator<String> chooseFirstTimeItems(String path) { if (path == null) { return emptyIterator(); } final StringTokenizer tokenizer = new StringTokenizer(path, File.pathSeparator); // in JDK 1.5 StringTokenizer implements Enumeration<Object> rather then Enumeration<String>, need to convert final Enumeration<String> en = new Enumeration<String>() { @Override public boolean hasMoreElements() { return tokenizer.hasMoreElements(); } @Override public String nextElement() { return (String)tokenizer.nextElement(); } }; return FilteringIterator.create(iterate(en), new Condition<String>() { @Override public boolean value(String element) { element = element.trim(); return !element.isEmpty() && !myPathSet.contains(element); } }); } private void addAllLast(Iterator<String> elements, List<String> toArray) { while (elements.hasNext()) { final String element = elements.next(); toArray.add(element); myPathSet.add(element); } } @NotNull public String getPathsString() { return StringUtil.join(getPathList(), File.pathSeparator); } public List<String> getPathList() { final List<String> result = new ArrayList<String>(); result.addAll(myPath); result.addAll(myPathTail); return result; } /** * @return {@link VirtualFile}s on local file system (returns jars as files). */ public List<VirtualFile> getVirtualFiles() { return skipNulls(map(getPathList(), PATH_TO_LOCAL_VFILE)); } /** * @return The same as {@link #getVirtualFiles()} but returns jars as {@link JarFileSystem} roots. */ public List<VirtualFile> getRootDirs() { return skipNulls(map(getPathList(), PATH_TO_DIR)); } public void addAll(List<String> allClasspath) { for (String path : allClasspath) { add(path); } } public void addAllFiles(File[] classpathList) { addAllFiles(Arrays.asList(classpathList)); } public void addAllFiles(List<File> classpathList) { for (File file : classpathList) { add(file); } } public void add(File file) { add(FileUtil.toCanonicalPath(file.getAbsolutePath()).replace('/', File.separatorChar)); } public void addVirtualFiles(Collection<VirtualFile> files) { for (final VirtualFile file : files) { add(file); } } public void addVirtualFiles(VirtualFile[] files) { for (VirtualFile file : files) { add(file); } } }