View Javadoc

1   /**
2    * Copyright (C) 2008 Atlassian
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  
17  package com.atlassian.theplugin.idea.jira.editor.vfs;
18  
19  import com.intellij.openapi.diagnostic.Logger;
20  import com.intellij.openapi.util.text.StringUtil;
21  import com.intellij.openapi.vfs.DeprecatedVirtualFileSystem;
22  import com.intellij.openapi.vfs.VirtualFile;
23  import com.intellij.openapi.vfs.VirtualFileEvent;
24  import com.intellij.openapi.vfs.VirtualFileListener;
25  import com.intellij.openapi.vfs.VirtualFileManager;
26  import org.jetbrains.annotations.NonNls;
27  import org.jetbrains.annotations.NotNull;
28  import org.jetbrains.annotations.Nullable;
29  
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.io.OutputStream;
33  import java.util.ArrayList;
34  import java.util.HashMap;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.StringTokenizer;
38  
39  /**
40   * A file system for content that resides only in memory.
41   *
42   * @author Steve Chaloner
43   */
44  public final class MemoryVirtualFileSystem extends DeprecatedVirtualFileSystem {
45  	/**
46  	 * The name of the component.
47  	 */
48  	private static final String COMPONENT_NAME = "JIRA-MemoryFileSystem";
49  
50  	/**
51  	 * The files.
52  	 */
53  	private final Map<String, MemoryVirtualFile> files = new HashMap<String, MemoryVirtualFile>();
54  
55  	/**
56  	 * Listeners for file system events.
57  	 */
58  	private final List<VirtualFileListener> listeners = new ArrayList<VirtualFileListener>();
59  
60  	private static MemoryVirtualFileSystem instance = new MemoryVirtualFileSystem();
61  
62  	private MemoryVirtualFileSystem() {
63  	}
64  
65  	public static MemoryVirtualFileSystem getInstance() {
66  		return instance;
67  	}
68  
69  	/**
70  	 * {@inheritDoc}
71  	 */
72  	public void addVirtualFileListener(VirtualFileListener virtualFileListener) {
73  		super.addVirtualFileListener(virtualFileListener);
74  		if (virtualFileListener != null) {
75  			listeners.add(virtualFileListener);
76  		}
77  	}
78  
79  	/**
80  	 * {@inheritDoc}
81  	 */
82  	public void removeVirtualFileListener(VirtualFileListener virtualFileListener) {
83  		super.removeVirtualFileListener(virtualFileListener);
84  		listeners.remove(virtualFileListener);
85  	}
86  
87  	/**
88  	 * Add a file to the file system.
89  	 *
90  	 * @param file the file to add
91  	 */
92  	public void addFile(@NotNull MemoryVirtualFile file) {
93  		files.put(file.getName(),
94  				file);
95  		fireFileCreated(file);
96  	}
97  
98  	/**
99  	 * Notifies listeners of a new file.
100 	 *
101 	 * @param file the new file
102 	 */
103 	private void fireFileCreated(MemoryVirtualFile file) {
104 		VirtualFileEvent e = new VirtualFileEvent(this,
105 				file,
106 				file.getName(),
107 				file.getParent());
108 		for (VirtualFileListener listener : listeners) {
109 			listener.fileCreated(e);
110 		}
111 	}
112 
113 	/**
114 	 * {@inheritDoc}
115 	 */
116 	public String getProtocol() {
117 		return Constants.JIRAISSUE_PROTOCOL;
118 	}
119 
120 	/**
121 	 * {@inheritDoc}
122 	 */
123 	@Nullable
124 	public VirtualFile findFileByPath(@NotNull String string) {
125 		// todo rewrite this so it doesn't look like crap
126 		VirtualFile file = null;
127 		if (!StringUtil.isEmptyOrSpaces(string)) {
128 			String path = VirtualFileManager.extractPath(string);
129 			StringTokenizer st = new StringTokenizer(path, "/");
130 			VirtualFile currentFile = files.get(Constants.JIRAISSUE_ROOT);
131 			boolean keepLooking = true;
132 			String targetName = null;
133 			while (keepLooking && st.hasMoreTokens()) {
134 				String element = st.nextToken();
135 				if (!st.hasMoreTokens()) {
136 					targetName = element;
137 				}
138 				VirtualFile child = currentFile.findChild(element);
139 				if (child != null) {
140 					currentFile = child;
141 				} else {
142 					keepLooking = false;
143 				}
144 			}
145 
146 			if (currentFile != null && targetName != null &&  targetName.equals(currentFile.getName())) {
147 				file = currentFile;
148 			}
149 		}
150 		return file;
151 	}
152 
153 	/**
154 	 * {@inheritDoc}
155 	 */
156 	public void refresh(boolean b) {
157 	}
158 
159 	/**
160 	 * {@inheritDoc}
161 	 */
162 	@Nullable
163 	public VirtualFile refreshAndFindFileByPath(String string) {
164 		return files.get(string);
165 	}
166 
167 	/**
168 	 * {@inheritDoc}
169 	 */
170 	public void deleteFile(Object object,
171 						   VirtualFile virtualFile) throws IOException {
172 		files.remove(virtualFile.getName());
173 
174 		MemoryVirtualFile parent = (MemoryVirtualFile) virtualFile.getParent();
175 		if (parent != null) {
176 			parent.deleteChild((MemoryVirtualFile) virtualFile);
177 		}
178 	}
179 
180 	/**
181 	 * {@inheritDoc}
182 	 */
183 	public void moveFile(Object object,
184 						 VirtualFile virtualFile,
185 						 VirtualFile virtualFile1) throws IOException {
186 		files.remove(virtualFile.getName());
187 		files.put(virtualFile1.getName(),
188 				(MemoryVirtualFile) virtualFile1);
189 	}
190 
191 	/**
192 	 * {@inheritDoc}
193 	 */
194 	public void renameFile(Object object,
195 						   VirtualFile virtualFile,
196 						   String string) throws IOException {
197 		files.remove(virtualFile.getName());
198 		files.put(string,
199 				(MemoryVirtualFile) virtualFile);
200 	}
201 
202 	/**
203 	 * {@inheritDoc}
204 	 */
205 	public MemoryVirtualFile createChildFile(Object object,
206 											 VirtualFile parent,
207 											 String name) throws IOException {
208 		MemoryVirtualFile file = new MemoryVirtualFile(name,
209 				null);
210 		file.setParent(parent);
211 		addFile(file);
212 		return file;
213 	}
214 
215 	/**
216 	 * {@inheritDoc}
217 	 */
218 	public MemoryVirtualFile createChildDirectory(Object object,
219 												  VirtualFile parent,
220 												  String name) throws IOException {
221 		MemoryVirtualFile file = new MemoryVirtualFile(name);
222 		((MemoryVirtualFile) parent).addChild(file);
223 		addFile(file);
224 		return file;
225 	}
226 
227 
228 	/**
229 	 * {@inheritDoc}
230 	 */
231 	@NonNls
232 	@NotNull
233 	public String getComponentName() {
234 		return COMPONENT_NAME;
235 	}
236 
237 	/**
238 	 * {@inheritDoc}
239 	 */
240 	public void initComponent() {
241 		MemoryVirtualFile root = new MemoryVirtualFile(Constants.JIRAISSUE_ROOT);
242 		addFile(root);
243 	}
244 
245 	/**
246 	 * {@inheritDoc}
247 	 */
248 	public void disposeComponent() {
249 		files.clear();
250 	}
251 
252 	/**
253 	 * For a given package, e.g. net.stevechaloner.intellijad, get the file corresponding
254 	 * to the last element, e.g. intellijad.  If the file or any part of the directory tree
255 	 * does not exist, it is created dynamically.
256 	 *
257 	 * @param packageName the name of the package
258 	 * @return the file corresponding to the final location of the package
259 	 */
260 	public MemoryVirtualFile getFileForPackage(@NotNull String packageName) {
261 		StringTokenizer st = new StringTokenizer(packageName, ".");
262 		List<String> names = new ArrayList<String>();
263 		while (st.hasMoreTokens()) {
264 			names.add(st.nextToken());
265 		}
266 		return getFileForPackage(names, files.get(Constants.JIRAISSUE_ROOT));
267 	}
268 
269 	/**
270 	 * Recursively search for, and if necessary create, the final file in the
271 	 * name list.
272 	 *
273 	 * @param names  the name list
274 	 * @param parent the parent file
275 	 * @return a file corresponding to the last entry in the name list
276 	 */
277 	private MemoryVirtualFile getFileForPackage(@NotNull List<String> names,
278 												@NotNull MemoryVirtualFile parent) {
279 		MemoryVirtualFile child = null;
280 		if (!names.isEmpty()) {
281 			String name = names.remove(0);
282 			child = parent.getChild(name);
283 			if (child == null) {
284 				try {
285 					child = createChildDirectory(null, parent, name);
286 				} catch (IOException e) {
287 					Logger.getInstance(getClass().getName()).error(e);
288 				}
289 			}
290 		}
291 
292 		if (child != null && !names.isEmpty()) {
293 			child = getFileForPackage(names, child);
294 		}
295 		return child;
296 	}
297 
298 	/**
299 	 * {@inheritDoc}
300 	 */
301 	public void projectOpened() {
302 	}
303 
304 	/**
305 	 * {@inheritDoc}
306 	 */
307 	public void projectClosed() {
308 		files.clear();
309 	}
310 
311 	public boolean isCaseSensitive() {
312 		return true;
313 	}
314 
315 	protected String extractRootPath(@NotNull String s) {
316 		return s;
317 	}
318 
319 	public int getRank() {
320 		return 0;
321 	}
322 
323 	/**
324 	 * {@inheritDoc}
325 	 */
326 	public VirtualFile copyFile(Object o, VirtualFile virtualFile, VirtualFile virtualFile1, String s) throws IOException {
327 		return null;
328 	}
329 
330 	/**
331 	 * {@inheritDoc}
332 	 */
333 	public boolean isReadOnly() {
334 		return false;
335 	}
336 
337 	/**
338 	 * {@inheritDoc}
339 	 */
340 	public boolean exists(VirtualFile virtualFile) {
341 		return files.containsValue(virtualFile);
342 	}
343 
344 	/**
345 	 * {@inheritDoc}
346 	 */
347 	public String[] list(VirtualFile virtualFile) {
348 		return new String[0];
349 	}
350 
351 	/**
352 	 * {@inheritDoc}
353 	 */
354 	public boolean isDirectory(VirtualFile virtualFile) {
355 		return virtualFile.isDirectory();
356 	}
357 
358 	/**
359 	 * {@inheritDoc}
360 	 */
361 	public long getTimeStamp(VirtualFile virtualFile) {
362 		return virtualFile.getTimeStamp();
363 	}
364 
365 	/**
366 	 * {@inheritDoc}
367 	 */
368 	public void setTimeStamp(VirtualFile virtualFile,
369 							 long l) throws IOException {
370 		// no-op
371 	}
372 
373 	/**
374 	 * {@inheritDoc}
375 	 */
376 	public boolean isWritable(VirtualFile virtualFile) {
377 		return virtualFile.isWritable();
378 	}
379 
380 	/**
381 	 * {@inheritDoc}
382 	 */
383 	public void setWritable(VirtualFile virtualFile,
384 							boolean b) throws IOException {
385 		// no-op
386 	}
387 
388 	/**
389 	 * {@inheritDoc}
390 	 */
391 	public InputStream getInputStream(VirtualFile virtualFile) throws IOException {
392 		return virtualFile.getInputStream();
393 	}
394 
395 	/**
396 	 * {@inheritDoc}
397 	 */
398 	public OutputStream getOutputStream(VirtualFile virtualFile,
399 										Object o,
400 										long l,
401 										long l1) throws IOException {
402 		return virtualFile.getOutputStream(o, l, l1);
403 	}
404 
405 	/**
406 	 * {@inheritDoc}
407 	 */
408 	public long getLength(VirtualFile virtualFile) {
409 		return virtualFile.getLength();
410 	}
411 }