2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.openapi
.vfs
;
18 import com
.intellij
.openapi
.application
.ApplicationManager
;
19 import com
.intellij
.openapi
.diagnostic
.Logger
;
20 import com
.intellij
.openapi
.fileTypes
.FileTypeManager
;
21 import com
.intellij
.openapi
.fileTypes
.FileTypes
;
22 import com
.intellij
.openapi
.util
.*;
23 import com
.intellij
.openapi
.util
.io
.FileUtil
;
24 import com
.intellij
.openapi
.util
.text
.StringUtil
;
25 import com
.intellij
.openapi
.vfs
.encoding
.EncodingManager
;
26 import com
.intellij
.util
.ArrayUtil
;
27 import com
.intellij
.util
.Function
;
28 import com
.intellij
.util
.PathUtil
;
29 import com
.intellij
.util
.Processor
;
30 import com
.intellij
.util
.containers
.Convertor
;
31 import com
.intellij
.util
.io
.URLUtil
;
32 import com
.intellij
.util
.io
.fs
.FileSystem
;
33 import com
.intellij
.util
.io
.fs
.IFile
;
34 import gnu
.trove
.THashSet
;
35 import org
.jetbrains
.annotations
.NonNls
;
36 import org
.jetbrains
.annotations
.NotNull
;
37 import org
.jetbrains
.annotations
.Nullable
;
40 import java
.net
.MalformedURLException
;
42 import java
.nio
.charset
.Charset
;
45 public class VfsUtil
{
46 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.vfs.VfsUtil");
48 public static String
loadText(@NotNull VirtualFile file
) throws IOException
{
49 InputStreamReader reader
= new InputStreamReader(file
.getInputStream(), file
.getCharset());
51 return new String(FileUtil
.loadText(reader
, (int)file
.getLength()));
58 public static void saveText(@NotNull VirtualFile file
, @NotNull String text
) throws IOException
{
59 Charset charset
= file
.getCharset();
60 file
.setBinaryContent(text
.getBytes(charset
.name()));
64 * Checks whether the <code>ancestor {@link VirtualFile}</code> is parent of <code>file
65 * {@link VirtualFile}</code>.
67 * @param ancestor the file
68 * @param file the file
69 * @param strict if <code>false</code> then this method returns <code>true</code> if <code>ancestor</code>
70 * and <code>file</code> are equal
71 * @return <code>true</code> if <code>ancestor</code> is parent of <code>file</code>; <code>false</code> otherwise
73 public static boolean isAncestor(@NotNull VirtualFile ancestor
, @NotNull VirtualFile file
, boolean strict
) {
74 if (!file
.getFileSystem().equals(ancestor
.getFileSystem())) return false;
75 VirtualFile parent
= strict ? file
.getParent() : file
;
77 if (parent
== null) return false;
78 if (parent
.equals(ancestor
)) return true;
79 parent
= parent
.getParent();
84 * Gets the relative path of <code>file</code> to its <code>ancestor</code>. Uses <code>separator</code> for
87 * @param file the file
88 * @param ancestor parent file
89 * @param separator character to use as files separator
90 * @return the relative path
92 public static String
getRelativePath(@NotNull VirtualFile file
, @NotNull VirtualFile ancestor
, char separator
) {
93 if (!file
.getFileSystem().equals(ancestor
.getFileSystem())) return null;
96 VirtualFile parent
= file
;
98 if (parent
== null) return null;
99 if (parent
.equals(ancestor
)) break;
103 length
+= parent
.getName().length();
104 parent
= parent
.getParent();
107 char[] chars
= new char[length
];
108 int index
= chars
.length
;
111 if (parent
.equals(ancestor
)) break;
112 if (index
< length
) {
113 chars
[--index
] = separator
;
115 String name
= parent
.getName();
116 for (int i
= name
.length() - 1; i
>= 0; i
--) {
117 chars
[--index
] = name
.charAt(i
);
119 parent
= parent
.getParent();
121 return new String(chars
);
125 * Copies all files matching the <code>filter</code> from <code>fromDir</code> to <code>toDir</code>.
127 * @param requestor any object to control who called this method. Note that
128 * it is considered to be an external change if <code>requestor</code> is <code>null</code>.
129 * See {@link VirtualFileEvent#getRequestor}
130 * @param fromDir the directory to copy from
131 * @param toDir the directory to copy to
132 * @param filter {@link VirtualFileFilter}
133 * @throws IOException if files failed to be copied
135 public static void copyDirectory(Object requestor
, @NotNull VirtualFile fromDir
, @NotNull VirtualFile toDir
, @Nullable VirtualFileFilter filter
)
137 VirtualFile
[] children
= fromDir
.getChildren();
138 for (VirtualFile child
: children
) {
139 if (filter
== null || filter
.accept(child
)) {
140 if (!child
.isDirectory()) {
141 copyFile(requestor
, child
, toDir
);
144 VirtualFile newChild
= toDir
.createChildDirectory(requestor
, child
.getName());
145 copyDirectory(requestor
, child
, newChild
, filter
);
152 * Makes a copy of the <code>file</code> in the <code>toDir</code> folder and returns it.
154 * @param requestor any object to control who called this method. Note that
155 * it is considered to be an external change if <code>requestor</code> is <code>null</code>.
156 * See {@link VirtualFileEvent#getRequestor}
157 * @param file file to make a copy of
158 * @param toDir directory to make a copy in
159 * @return a copy of the file
160 * @throws IOException if file failed to be copied
162 public static VirtualFile
copyFile(Object requestor
, @NotNull VirtualFile file
, @NotNull VirtualFile toDir
) throws IOException
{
163 return copyFile(requestor
, file
, toDir
, file
.getName());
167 * Makes a copy of the <code>file</code> in the <code>toDir</code> folder with the <code>newName</code> and returns it.
169 * @param requestor any object to control who called this method. Note that
170 * it is considered to be an external change if <code>requestor</code> is <code>null</code>.
171 * See {@link VirtualFileEvent#getRequestor}
172 * @param file file to make a copy of
173 * @param toDir directory to make a copy in
174 * @param newName new name of the file
175 * @return a copy of the file
176 * @throws IOException if file failed to be copied
178 public static VirtualFile
copyFile(Object requestor
, @NotNull VirtualFile file
, @NotNull VirtualFile toDir
, @NotNull @NonNls String newName
)
180 final VirtualFile newChild
= toDir
.createChildData(requestor
, newName
);
181 // [jeka] TODO: to be duscussed if the copy should have the same timestamp as the original
182 //OutputStream out = newChild.getOutputStream(requestor, -1, file.getActualTimeStamp());
183 newChild
.setBinaryContent(file
.contentsToByteArray());
188 * Copies content of resource to the given file
190 * @param file to copy to
191 * @param resourceUrl url of the resource to be copied
192 * @throws java.io.IOException if resource not found or copying failed
194 public static void copyFromResource(@NotNull VirtualFile file
, @NonNls @NotNull String resourceUrl
) throws IOException
{
195 InputStream out
= VfsUtil
.class.getResourceAsStream(resourceUrl
);
197 throw new FileNotFoundException(resourceUrl
);
200 byte[] bytes
= FileUtil
.adaptiveLoadBytes(out
);
201 file
.setBinaryContent(bytes
);
208 * Gets the array of common ancestors for passed files.
210 * @param files array of files
211 * @return array of common ancestors for passed files
214 public static VirtualFile
[] getCommonAncestors(@NotNull VirtualFile
[] files
) {
215 // Separate files by first component in the path.
216 HashMap
<VirtualFile
,Set
<VirtualFile
>> map
= new HashMap
<VirtualFile
, Set
<VirtualFile
>>();
217 for (VirtualFile aFile
: files
) {
218 VirtualFile directory
= aFile
.isDirectory() ? aFile
: aFile
.getParent();
219 if (directory
== null) return VirtualFile
.EMPTY_ARRAY
;
220 VirtualFile
[] path
= getPathComponents(directory
);
221 Set
<VirtualFile
> filesSet
;
222 final VirtualFile firstPart
= path
[0];
223 if (map
.containsKey(firstPart
)) {
224 filesSet
= map
.get(firstPart
);
227 filesSet
= new THashSet
<VirtualFile
>();
228 map
.put(firstPart
, filesSet
);
230 filesSet
.add(directory
);
232 // Find common ancestor for each set of files.
233 ArrayList
<VirtualFile
> ancestorsList
= new ArrayList
<VirtualFile
>();
234 for (Set
<VirtualFile
> filesSet
: map
.values()) {
235 VirtualFile ancestor
= null;
236 for (VirtualFile file
: filesSet
) {
237 if (ancestor
== null) {
241 ancestor
= getCommonAncestor(ancestor
, file
);
242 //assertTrue(ancestor != null);
244 ancestorsList
.add(ancestor
);
247 return VfsUtil
.toVirtualFileArray(ancestorsList
);
251 * Gets the common ancestor for passed files, or null if the files do not have common ancestors.
253 * @param file1 fist file
254 * @param file2 second file
255 * @return common ancestor for the passed files. Returns <code>null</code> if
256 * the files do not have common ancestor
258 public static VirtualFile
getCommonAncestor(@NotNull VirtualFile file1
, @NotNull VirtualFile file2
) {
259 if (!file1
.getFileSystem().equals(file2
.getFileSystem())) {
263 VirtualFile
[] path1
= getPathComponents(file1
);
264 VirtualFile
[] path2
= getPathComponents(file2
);
266 VirtualFile
[] minLengthPath
;
267 VirtualFile
[] maxLengthPath
;
268 if (path1
.length
< path2
.length
) {
269 minLengthPath
= path1
;
270 maxLengthPath
= path2
;
273 minLengthPath
= path2
;
274 maxLengthPath
= path1
;
277 int lastEqualIdx
= -1;
278 for (int i
= 0; i
< minLengthPath
.length
; i
++) {
279 if (minLengthPath
[i
].equals(maxLengthPath
[i
])) {
286 return lastEqualIdx
== -1 ?
null : minLengthPath
[lastEqualIdx
];
290 * Gets an array of files representing paths from root to the passed file.
292 * @param file the file
293 * @return virtual files which represents paths from root to the passed file
296 private static VirtualFile
[] getPathComponents(@NotNull VirtualFile file
) {
297 ArrayList
<VirtualFile
> componentsList
= new ArrayList
<VirtualFile
>();
298 while (file
!= null) {
299 componentsList
.add(file
);
300 file
= file
.getParent();
302 int size
= componentsList
.size();
303 VirtualFile
[] components
= new VirtualFile
[size
];
304 for (int i
= 0; i
< size
; i
++) {
305 components
[i
] = componentsList
.get(size
- i
- 1);
310 @SuppressWarnings({"HardCodedStringLiteral"})
312 public static VirtualFile
findRelativeFile(@NotNull String uri
, VirtualFile base
) {
314 if (!base
.isValid()){
315 LOG
.error("Invalid file name: " + base
.getName() + ", url: " + uri
);
319 uri
= uri
.replace('\\', '/');
321 if (uri
.startsWith("file:///")) {
322 uri
= uri
.substring("file:///".length());
323 if (!SystemInfo
.isWindows
) uri
= "/" + uri
;
325 else if (uri
.startsWith("file:/")) {
326 uri
= uri
.substring("file:/".length());
327 if (!SystemInfo
.isWindows
) uri
= "/" + uri
;
329 else if (uri
.startsWith("file:")) {
330 uri
= uri
.substring("file:".length());
333 VirtualFile file
= null;
335 if (uri
.startsWith("jar:file:/")) {
336 uri
= uri
.substring("jar:file:/".length());
337 if (!SystemInfo
.isWindows
) uri
= "/" + uri
;
338 file
= VirtualFileManager
.getInstance().findFileByUrl(JarFileSystem
.PROTOCOL_PREFIX
+ uri
);
341 if (!SystemInfo
.isWindows
&& StringUtil
.startsWithChar(uri
, '/')) {
342 file
= LocalFileSystem
.getInstance().findFileByPath(uri
);
344 else if (SystemInfo
.isWindows
&& uri
.length() >= 2 && Character
.isLetter(uri
.charAt(0)) && uri
.charAt(1) == ':') {
345 file
= LocalFileSystem
.getInstance().findFileByPath(uri
);
349 if (file
== null && uri
.contains(JarFileSystem
.JAR_SEPARATOR
)) {
350 file
= JarFileSystem
.getInstance().findFileByPath(uri
);
351 if (file
== null && base
== null) {
352 file
= VirtualFileManager
.getInstance().findFileByUrl(uri
);
357 if (base
== null) return LocalFileSystem
.getInstance().findFileByPath(uri
);
358 if (!base
.isDirectory()) base
= base
.getParent();
359 if (base
== null) return LocalFileSystem
.getInstance().findFileByPath(uri
);
360 file
= VirtualFileManager
.getInstance().findFileByUrl(base
.getUrl() + "/" + uri
);
361 if (file
== null) return null;
367 @NonNls private static final String FILE
= "file";
368 @NonNls private static final String JAR
= "jar";
369 @NonNls private static final String MAILTO
= "mailto";
370 private static final String PROTOCOL_DELIMITER
= ":";
373 * Searches for the file specified by given java,net.URL.
374 * Note that this method currently tested only for "file" and "jar" protocols under Unix and Windows
376 * @param url the URL to find file by
377 * @return <code>{@link VirtualFile}</code> if the file was found, <code>null</code> otherwise
379 public static VirtualFile
findFileByURL(@NotNull URL url
) {
380 VirtualFileManager virtualFileManager
= VirtualFileManager
.getInstance();
381 return findFileByURL(url
, virtualFileManager
);
384 public static VirtualFile
findFileByURL(@NotNull URL url
, @NotNull VirtualFileManager virtualFileManager
) {
385 String vfUrl
= convertFromUrl(url
);
386 return virtualFileManager
.findFileByUrl(vfUrl
);
390 * Converts VsfUrl info java.net.URL. Does not support "jar:" protocol.
392 * @param vfsUrl VFS url (as constructed by VfsFile.getUrl())
393 * @return converted URL or null if error has occured
397 public static URL
convertToURL(@NotNull String vfsUrl
) {
398 if (vfsUrl
.startsWith(JAR
)) {
399 LOG
.error("jar: protocol not supported.");
403 // [stathik] for supporting mail URLs in Plugin Manager
404 if (vfsUrl
.startsWith(MAILTO
)) {
406 return new URL (vfsUrl
);
408 catch (MalformedURLException e
) {
413 String
[] split
= vfsUrl
.split("://");
415 if (split
.length
!= 2) {
416 LOG
.debug("Malformed VFS URL: " + vfsUrl
);
420 String protocol
= split
[0];
421 String path
= split
[1];
424 if (protocol
.equals(FILE
)) {
425 return new URL(protocol
, "", path
);
428 return new URL(vfsUrl
);
431 catch (MalformedURLException e
) {
432 LOG
.debug("MalformedURLException occured:" + e
.getMessage());
438 private static String
convertFromUrl(@NotNull URL url
) {
439 String protocol
= url
.getProtocol();
440 String path
= url
.getPath();
441 if (protocol
.equals(JAR
)) {
442 if (StringUtil
.startsWithConcatenationOf(path
, FILE
, PROTOCOL_DELIMITER
)) {
444 URL subURL
= new URL(path
);
445 path
= subURL
.getPath();
447 catch (MalformedURLException e
) {
448 throw new RuntimeException(VfsBundle
.message("url.parse.unhandled.exception"), e
);
452 throw new RuntimeException(new IOException(VfsBundle
.message("url.parse.error", url
.toExternalForm())));
455 if (SystemInfo
.isWindows
|| SystemInfo
.isOS2
) {
456 while (path
.length() > 0 && path
.charAt(0) == '/') {
457 path
= path
.substring(1, path
.length());
461 path
= URLUtil
.unescapePercentSequences(path
);
462 return protocol
+ "://" + path
;
465 public static String
urlToPath(@NonNls String url
) {
466 if (url
== null) return "";
467 return VirtualFileManager
.extractPath(url
);
471 public static String
pathToUrl(@NotNull String path
) {
472 return VirtualFileManager
.constructUrl(LocalFileSystem
.PROTOCOL
, path
);
476 public static File
virtualToIoFile(@NotNull VirtualFile file
) {
477 return new File(PathUtil
.toPresentableUrl(file
.getUrl()));
481 public static IFile
virtualToIFile(@NotNull VirtualFile file
) {
482 return FileSystem
.FILE_SYSTEM
.createFile(PathUtil
.toPresentableUrl(file
.getUrl()));
485 public static VirtualFile
copyFileRelative(Object requestor
, @NotNull VirtualFile file
, @NotNull VirtualFile toDir
, @NotNull String relativePath
) throws IOException
{
486 StringTokenizer tokenizer
= new StringTokenizer(relativePath
,"/");
487 VirtualFile curDir
= toDir
;
490 String token
= tokenizer
.nextToken();
491 if (tokenizer
.hasMoreTokens()) {
492 VirtualFile childDir
= curDir
.findChild(token
);
493 if (childDir
== null) {
494 childDir
= curDir
.createChildDirectory(requestor
, token
);
499 return copyFile(requestor
, file
, curDir
, token
);
505 public static String
fixIDEAUrl(@NotNull String ideaUrl
) {
506 int idx
= ideaUrl
.indexOf("://");
508 String s
= ideaUrl
.substring(0, idx
);
510 if (s
.equals(JarFileSystem
.PROTOCOL
)) {
511 //noinspection HardCodedStringLiteral
514 ideaUrl
= s
+":/"+ideaUrl
.substring(idx
+3);
520 public static String
fixURLforIDEA(@NotNull String url
) {
521 int idx
= url
.indexOf(":/");
522 if( idx
>= 0 && idx
+2 < url
.length() && url
.charAt(idx
+2) != '/' ) {
523 String prefix
= url
.substring(0, idx
);
524 String suffix
= url
.substring(idx
+2);
526 if (SystemInfo
.isWindows
) {
527 url
= prefix
+"://"+suffix
;
529 url
= prefix
+":///"+suffix
;
535 public static boolean isAncestor(@NotNull File ancestor
, @NotNull File file
, boolean strict
) {
536 File parent
= strict ? file
.getParentFile() : file
;
537 while (parent
!= null) {
538 if (parent
.equals(ancestor
)) return true;
539 parent
= parent
.getParentFile();
546 * Returns the relative path from one virtual file to another.
548 * @param src the file from which the relative path is built.
549 * @param dst the file to which the path is built.
550 * @param separatorChar the separator for the path components.
551 * @return the relative path, or null if the files have no common ancestor.
556 public static String
getPath(@NotNull VirtualFile src
, @NotNull VirtualFile dst
, char separatorChar
) {
557 final VirtualFile commonAncestor
= getCommonAncestor(src
, dst
);
558 if (commonAncestor
!= null) {
559 StringBuilder buffer
= new StringBuilder();
560 if (src
!= commonAncestor
) {
561 while (src
.getParent() != commonAncestor
) {
562 buffer
.append("..").append(separatorChar
);
563 src
= src
.getParent();
567 buffer
.append(getRelativePath(dst
, commonAncestor
, separatorChar
));
568 return buffer
.toString();
574 public static boolean isValidName(@NotNull String name
) {
575 return name
.indexOf('\\') < 0 && name
.indexOf('/') < 0;
578 public static String
getUrlForLibraryRoot(@NotNull File libraryRoot
) {
579 String path
= FileUtil
.toSystemIndependentName(libraryRoot
.getAbsolutePath());
580 if (FileTypeManager
.getInstance().getFileTypeByFileName(libraryRoot
.getName()) == FileTypes
.ARCHIVE
) {
581 return VirtualFileManager
.constructUrl(JarFileSystem
.getInstance().getProtocol(), path
+ JarFileSystem
.JAR_SEPARATOR
);
584 return VirtualFileManager
.constructUrl(LocalFileSystem
.getInstance().getProtocol(), path
);
588 public static VirtualFile
createChildSequent(Object requestor
, @NotNull VirtualFile dir
, @NotNull String prefix
, @NotNull String extension
) throws IOException
{
589 String fileName
= prefix
+ "." + extension
;
591 while (dir
.findChild(fileName
) != null) {
592 fileName
= prefix
+ i
+ "." + extension
;
595 return dir
.createChildData(requestor
, fileName
);
599 public static String
[] filterNames(@NotNull String
[] names
) {
600 int filteredCount
= 0;
601 for (String string
: names
) {
602 if (isBadName(string
)) filteredCount
++;
604 if (filteredCount
== 0) return names
;
606 String
[] result
= ArrayUtil
.newStringArray(names
.length
- filteredCount
);
608 for (String string
: names
) {
609 if (isBadName(string
)) continue;
610 result
[count
++] = string
;
616 public static boolean isBadName(String name
) {
617 return name
== null || name
.length() == 0 || "/".equals(name
) || "\\".equals(name
);
620 public static VirtualFile
createDirectories(@NotNull final String dir
) throws IOException
{
621 final Ref
<IOException
> err
= new Ref
<IOException
>();
622 VirtualFile result
= ApplicationManager
.getApplication().runWriteAction(new Computable
<VirtualFile
>() {
623 public VirtualFile
compute() {
625 return createDirectoryIfMissing(dir
);
627 catch (IOException e
) {
633 if (!err
.isNull()) throw err
.get();
638 public static VirtualFile
createDirectoryIfMissing(@NotNull String dir
) throws IOException
{
639 return doCreateDirectoriesIfMissing(FileUtil
.toSystemIndependentName(dir
));
642 private static VirtualFile
doCreateDirectoriesIfMissing(String dir
) throws IOException
{
643 final VirtualFile file
= LocalFileSystem
.getInstance().refreshAndFindFileByPath(dir
);
645 int pos
= dir
.lastIndexOf('/');
646 if (pos
< 0) return null;
647 VirtualFile parent
= createDirectoryIfMissing(dir
.substring(0, pos
));
648 if (parent
== null) return null;
649 final String dirName
= dir
.substring(pos
+ 1);
650 return parent
.createChildDirectory(LocalFileSystem
.getInstance(), dirName
);
655 public static <E
extends Throwable
> VirtualFile
doActionAndRestoreEncoding(@NotNull VirtualFile fileBefore
, @NotNull ThrowableComputable
<VirtualFile
, E
> action
) throws E
{
656 Charset charsetBefore
= EncodingManager
.getInstance().getEncoding(fileBefore
, true);
657 VirtualFile fileAfter
= null;
659 fileAfter
= action
.compute();
663 if (fileAfter
!= null) {
664 Charset actual
= EncodingManager
.getInstance().getEncoding(fileAfter
, true);
665 if (!Comparing
.equal(actual
, charsetBefore
)) {
666 EncodingManager
.getInstance().setEncoding(fileAfter
, charsetBefore
);
672 public static void processFileRecursivelyWithoutIgnored(@NotNull final VirtualFile root
, @NotNull final Processor
<VirtualFile
> processor
) {
673 final FileTypeManager ftm
= FileTypeManager
.getInstance();
674 processFilesRecursively(root
, processor
, new Convertor
<VirtualFile
, Boolean
>() {
675 public Boolean
convert(final VirtualFile vf
) {
676 return ! ftm
.isFileIgnored(vf
.getName());
681 public static void processFilesRecursively(@NotNull VirtualFile root
, @NotNull Processor
<VirtualFile
> processor
,
682 @NotNull Convertor
<VirtualFile
, Boolean
> directoryFilter
) {
683 final LinkedList
<VirtualFile
> queue
= new LinkedList
<VirtualFile
>();
685 while (!queue
.isEmpty()) {
686 final VirtualFile file
= queue
.removeFirst();
687 if (!processor
.process(file
)) return;
688 if (file
.isDirectory() && directoryFilter
.convert(file
)) {
689 queue
.addAll(Arrays
.asList(file
.getChildren()));
694 public static boolean processFilesRecursively(@NotNull VirtualFile root
, @NotNull Processor
<VirtualFile
> processor
) {
695 final LinkedList
<VirtualFile
> queue
= new LinkedList
<VirtualFile
>();
697 while (!queue
.isEmpty()) {
698 final VirtualFile file
= queue
.removeFirst();
699 if (!processor
.process(file
)) return false;
700 if (file
.isDirectory()) {
701 queue
.addAll(Arrays
.asList(file
.getChildren()));
708 public static <T
> T
processInputStream(@NotNull final VirtualFile file
, @NotNull Function
<InputStream
, T
> function
) {
709 InputStream stream
= null;
711 stream
= file
.getInputStream();
712 return function
.fun(stream
);
714 catch (IOException e
) {
718 if (stream
!= null) {
722 catch (IOException e
) {
730 public static VirtualFile
[] toVirtualFileArray(@NotNull Collection
<?
extends VirtualFile
> files
) {
731 int size
= files
.size();
732 if (size
== 0) return VirtualFile
.EMPTY_ARRAY
;
733 return files
.toArray(new VirtualFile
[size
]);