Cache core jar's vfs children/parent. It'd better be done in normal jar vfs though
[idea/community.git] / platform / core-impl / src / com / intellij / openapi / vfs / impl / jar / CoreJarVirtualFile.java
1 /*
2  * Copyright 2000-2011 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.openapi.vfs.impl.jar;
17
18 import com.intellij.openapi.vfs.VirtualFile;
19 import com.intellij.openapi.vfs.VirtualFileSystem;
20 import org.jetbrains.annotations.NotNull;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 /**
29  * @author yole
30  */
31 public class CoreJarVirtualFile extends VirtualFile {
32   private final CoreJarFileSystem myFileSystem;
33   private final CoreJarHandler myHandler;
34   private final String myPathInJar;
35   private final VirtualFile myParent;
36   private VirtualFile[] myChildren;
37
38   public CoreJarVirtualFile(CoreJarFileSystem fileSystem, CoreJarHandler handler, String pathInJar) {
39     myFileSystem = fileSystem;
40     myHandler = handler;
41     myPathInJar = pathInJar;
42     myParent = calcParent();
43   }
44
45   @NotNull
46   @Override
47   public String getName() {
48     final int lastSlash = myPathInJar.lastIndexOf('/');
49     if (lastSlash < 0) {
50       return myPathInJar;
51     }
52     return myPathInJar.substring(lastSlash+1);
53   }
54
55   @NotNull
56   @Override
57   public VirtualFileSystem getFileSystem() {
58     return myFileSystem;
59   }
60
61   @Override
62   public String getPath() {
63     return myHandler.myBasePath + "!/" + myPathInJar;
64   }
65
66   @Override
67   public boolean isWritable() {
68     return false;
69   }
70
71   @Override
72   public boolean isDirectory() {
73     return myHandler.isDirectory(this);
74   }
75
76   @Override
77   public boolean isValid() {
78     return true;
79   }
80
81   @Override
82   public VirtualFile getParent() {
83     return myParent;
84   }
85
86   private VirtualFile calcParent() {
87     if (myPathInJar.length() == 0) {
88       return null;
89     }
90     int lastSlash = myPathInJar.lastIndexOf('/');
91     if (lastSlash < 0) {
92       return myHandler.findFileByPath("");
93     }
94     return myHandler.findFileByPath(myPathInJar.substring(0, lastSlash));
95   }
96
97   @Override
98   public VirtualFile[] getChildren() {
99     VirtualFile[] answer = myChildren;
100     if (answer == null) {
101       answer = calcChildren();
102       myChildren = answer;
103     }
104     return answer;
105   }
106
107   private VirtualFile[] calcChildren() {
108     List<VirtualFile> result = new ArrayList<VirtualFile>();
109     final String[] children = myHandler.list(this);
110     for (String child : children) {
111       final VirtualFile childFile = myPathInJar.isEmpty() ? myHandler.findFileByPath(child) : myHandler.findFileByPath(myPathInJar + "/" + child);
112       result.add(childFile);
113     }
114     return result.toArray(new VirtualFile[result.size()]);
115   }
116
117   @NotNull
118   @Override
119   public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
120     throw new UnsupportedOperationException("JarFileSystem is read-only");
121   }
122
123   @NotNull
124   @Override
125   public byte[] contentsToByteArray() throws IOException {
126     return myHandler.contentsToByteArray(this);
127   }
128
129   @Override
130   public long getTimeStamp() {
131     return myHandler.getTimeStamp(this);
132   }
133
134   @Override
135   public long getLength() {
136     return myHandler.getLength(this);
137   }
138
139   @Override
140   public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
141   }
142
143   @Override
144   public InputStream getInputStream() throws IOException {
145     return myHandler.getInputStream(this);
146   }
147
148   @Override
149   public long getModificationStamp() {
150     return 0;
151   }
152 }