53812bd2f9b5cb6fb0292ccf02ce641bedd713df
[idea/community.git] / platform / platform-impl / src / com / intellij / openapi / vfs / impl / VirtualFilePointerImpl.java
1 /*
2  * Copyright 2000-2015 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;
17
18 import com.intellij.openapi.Disposable;
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.progress.ProgressManager;
22 import com.intellij.openapi.util.Pair;
23 import com.intellij.openapi.util.TraceableDisposable;
24 import com.intellij.openapi.vfs.VirtualFile;
25 import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
26 import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener;
27 import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
28 import com.intellij.util.PathUtil;
29 import org.jetbrains.annotations.NotNull;
30
31 class VirtualFilePointerImpl extends TraceableDisposable implements VirtualFilePointer {
32   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.VirtualFilePointerImpl");
33
34   private final VirtualFilePointerListener myListener;
35   private static final boolean TRACE_CREATION = LOG.isDebugEnabled() || ApplicationManager.getApplication().isUnitTestMode();
36
37   volatile FilePointerPartNode myNode; // null means disposed
38
39   VirtualFilePointerImpl(VirtualFilePointerListener listener, @NotNull Disposable parentDisposable, Pair<VirtualFile, String> fileAndUrl) {
40     super(TRACE_CREATION);
41     myListener = listener;
42   }
43
44   @Override
45   @NotNull
46   public String getFileName() {
47     if (!checkDisposed()) return "";
48     Pair<VirtualFile, String> result = myNode.update();
49     VirtualFile file = result.first;
50     if (file != null) {
51       return file.getName();
52     }
53     String url = result.second;
54     int index = url.lastIndexOf('/');
55     return index >= 0 ? url.substring(index + 1) : url;
56   }
57
58   @Override
59   public VirtualFile getFile() {
60     if (!checkDisposed()) return null;
61     Pair<VirtualFile, String> result = myNode.update();
62     return result.first;
63   }
64
65   @Override
66   @NotNull
67   public String getUrl() {
68     if (isDisposed()) return "";
69     Pair<VirtualFile, String> update = myNode.update();
70     return update.second;
71   }
72
73   @NotNull
74   String getUrlNoUpdate() {
75     return isDisposed() ? "" : myNode.myFileAndUrl.second;
76   }
77
78   @Override
79   @NotNull
80   public String getPresentableUrl() {
81     if (!checkDisposed()) return "";
82     return PathUtil.toPresentableUrl(getUrl());
83   }
84
85   private boolean checkDisposed() {
86     if (isDisposed()) {
87       ProgressManager.checkCanceled();
88       LOG.error("Already disposed: URL='" + this + "'");
89       return false;
90     }
91     return true;
92   }
93
94
95   @Override
96   public boolean isValid() {
97     Pair<VirtualFile, String> result = isDisposed() ? null : myNode.update();
98     return result != null && result.first != null;
99   }
100
101   @Override
102   public String toString() {
103     return getUrlNoUpdate();
104   }
105
106   public void dispose() {
107     checkDisposed();
108     if (myNode.incrementUsageCount(-1) == 0) {
109       kill("URL when die: "+ toString());
110       VirtualFilePointerManager pointerManager = VirtualFilePointerManager.getInstance();
111       if (pointerManager instanceof VirtualFilePointerManagerImpl) {
112         ((VirtualFilePointerManagerImpl)pointerManager).removeNode(myNode, myListener); // remove from the tree
113       }
114       myNode = null;
115     }
116   }
117
118   public boolean isDisposed() {
119     return myNode == null;
120   }
121
122   VirtualFilePointerListener getListener() {
123     return myListener;
124   }
125 }