@NotNull
  private VirtualFilePointerImpl getOrCreate(
      @NotNull Disposable parentDisposable,
      @Nullable VirtualFilePointerListener listener,
      @NotNull String path,
      @NotNull Pair<VirtualFile, String> fileAndUrl) {
    FilePointerPartNode root = myPointers.get(listener);
    FilePointerPartNode node;
    if (root == null) {
      root = new FilePointerPartNode(path, null, fileAndUrl);
      myPointers.put(listener, root);
      node = root;
    } else {
      node = root.findPointerOrCreate(path, 0, fileAndUrl);
    }

    VirtualFilePointerImpl pointer;
    if (node.leaf == null) {
      pointer = new VirtualFilePointerImpl(listener, parentDisposable, fileAndUrl);
      node.associate(pointer, fileAndUrl);
    } else {
      pointer = node.leaf;
    }
    pointer.myNode.incrementUsageCount(1);

    root.checkConsistency();
    return pointer;
  }
 private IdentityVirtualFilePointer getOrCreateIdentity(@NotNull String url, VirtualFile found) {
   IdentityVirtualFilePointer pointer = myUrlToIdentity.get(url);
   if (pointer == null) {
     pointer = new IdentityVirtualFilePointer(found, url);
     myUrlToIdentity.put(url, pointer);
   }
   return pointer;
 }
 void removeNode(@NotNull FilePointerPartNode node, VirtualFilePointerListener listener) {
   boolean rootNodeEmpty = node.remove();
   if (rootNodeEmpty) {
     myPointers.remove(listener);
   } else {
     myPointers.get(listener).checkConsistency();
   }
 }
 private synchronized int getNodeId(String fullTestName) {
   Integer nodeId = nodeIdsByFullTestName.get(fullTestName);
   if (nodeId == null) {
     nodeId = nextNodeId++;
     nodeIdsByFullTestName.put(fullTestName, nodeId);
   }
   return nodeId;
 }
 public void clearState(Project project) {
   myGlobals = null;
   final String projectPath = getProjectPath(project);
   synchronized (myProjectDataMap) {
     final ProjectData data = myProjectDataMap.get(projectPath);
     if (data != null) {
       data.dropChanges();
     }
   }
 }
 @Override
 public final String getVersionString(String sdkHome) {
   String versionString = myCachedVersionStrings.get(sdkHome);
   if (versionString == null) {
     versionString = getJdkVersion(sdkHome);
     if (!StringUtil.isEmpty(versionString)) {
       myCachedVersionStrings.put(sdkHome, versionString);
     }
   }
   return versionString;
 }
    static void registerDisposable(Disposable parentDisposable, VirtualFilePointerImpl pointer) {
      synchronized (ourInstances) {
        DelegatingDisposable result = ourInstances.get(parentDisposable);
        if (result == null) {
          ourInstances.put(parentDisposable, result = new DelegatingDisposable(parentDisposable));
          Disposer.register(parentDisposable, result);
        }

        result.myCounts.put(pointer, result.myCounts.get(pointer) + 1);
      }
    }
  @Override
  public void after(@NotNull final List<? extends VFileEvent> events) {
    incModificationCount();

    for (FilePointerPartNode node : myPointersToUpdateUrl) {
      synchronized (this) {
        VirtualFilePointerImpl pointer = node.leaf;
        String urlBefore = pointer.getUrlNoUpdate();
        Pair<VirtualFile, String> after = node.update();
        String urlAfter = after.second;
        if (URL_COMPARATOR.compare(urlBefore, urlAfter) != 0) {
          // url has changed, reinsert
          FilePointerPartNode root = myPointers.get(pointer.getListener());
          int useCount = node.useCount;
          node.remove();
          FilePointerPartNode newNode =
              root.findPointerOrCreate(VfsUtilCore.urlToPath(urlAfter), 0, after);
          VirtualFilePointerImpl existingPointer = newNode.leaf;
          if (existingPointer != null) {
            // can happen when e.g. file renamed to the existing file
            // merge two pointers
            pointer.myNode = newNode;
          } else {
            newNode.associate(pointer, after);
          }
          newNode.incrementUsageCount(useCount);
        }
      }
    }

    VirtualFilePointer[] pointersToFireArray = toPointers(myPointersToFire);
    for (VirtualFilePointer pointer : pointersToFireArray) {
      ((VirtualFilePointerImpl) pointer).myNode.update();
    }

    for (EventDescriptor event : myEvents) {
      event.fireAfter();
    }

    if (pointersToFireArray.length != 0) {
      myBus.syncPublisher(VirtualFilePointerListener.TOPIC).validityChanged(pointersToFireArray);
    }

    myPointersToUpdateUrl = Collections.emptyList();
    myEvents = Collections.emptyList();
    myPointersToFire = Collections.emptyList();
    for (FilePointerPartNode root : myPointers.values()) {
      root.checkConsistency();
    }
  }
  private void updateEditorsFromProperties() {
    String propertyName = getSelectedPropertyName();
    ((CardLayout) myValuesPanel.getLayout())
        .show(myValuesPanel, propertyName == null ? NO_PROPERTY_SELECTED : VALUES);
    if (propertyName == null) return;

    for (final PropertiesFile propertiesFile : myResourceBundle.getPropertiesFiles(myProject)) {
      final EditorEx editor = (EditorEx) myEditors.get(propertiesFile);
      if (editor == null) continue;
      final IProperty property = propertiesFile.findPropertyByKey(propertyName);
      final Document document = editor.getDocument();
      CommandProcessor.getInstance()
          .executeCommand(
              null,
              new Runnable() {
                @Override
                public void run() {
                  ApplicationManager.getApplication()
                      .runWriteAction(
                          new Runnable() {
                            @Override
                            public void run() {
                              updateDocumentFromPropertyValue(
                                  getPropertyEditorValue(property), document, propertiesFile);
                            }
                          });
                }
              },
              "",
              this);

      JPanel titledPanel = myTitledPanels.get(propertiesFile);
      ((TitledBorder) titledPanel.getBorder())
          .setTitleColor(property == null ? JBColor.RED : UIUtil.getLabelTextForeground());
      titledPanel.repaint();
    }
  }
 @TestOnly
 public int countDupContainers() {
   Map<VirtualFilePointerContainer, Integer> c =
       new THashMap<VirtualFilePointerContainer, Integer>();
   for (VirtualFilePointerContainerImpl container : myContainers) {
     Integer count = c.get(container);
     if (count == null) count = 0;
     count++;
     c.put(container, count);
   }
   int i = 0;
   for (Integer count : c.values()) {
     if (count > 1) {
       i++;
     }
   }
   return i;
 }
  private void restoreCopy(VirtualFile file) {
    try {
      if (file == null) return; // Externally deleted actually.
      if (!file.isWritable()) return; // IDEA was unable to save it as well. So no need to restore.

      final byte[] bytes = mySavedCopies.get(file);
      if (bytes != null) {
        try {
          file.setBinaryContent(bytes, -1, mySavedTimestamps.get(file));
        } catch (IOException e) {
          Messages.showWarningDialog(
              ProjectBundle.message("project.reload.write.failed", file.getPresentableUrl()),
              ProjectBundle.message("project.reload.write.failed.title"));
        }
      }
    } finally {
      mySavedCopies.remove(file);
      mySavedTimestamps.remove(file);
    }
  }
  @Override
  public int getId(
      @NotNull final VirtualFile parent,
      @NotNull final String childName,
      @NotNull final NewVirtualFileSystem fs) {
    if (parent == mySuperRoot) {
      String rootUrl = normalizeRootUrl(childName, fs);
      VirtualFileSystemEntry root = myRoots.get(rootUrl);
      return root == null ? 0 : root.getId();
    }

    int parentId = getFileId(parent);
    int[] children = FSRecords.list(parentId);

    if (children.length > 0) {
      // fast path, check that some child has same nameId as given name, this avoid O(N) on
      // retrieving names for processing non-cached children
      int nameId = FSRecords.getNameId(childName);
      for (final int childId : children) {
        if (nameId == FSRecords.getNameId(childId)) {
          return childId;
        }
      }
      // for case sensitive system the above check is exhaustive in consistent state of vfs
    }

    for (final int childId : children) {
      if (namesEqual(fs, childName, FSRecords.getName(childId))) return childId;
    }

    final VirtualFile fake = new FakeVirtualFile(parent, childName);
    final FileAttributes attributes = fs.getAttributes(fake);
    if (attributes != null) {
      final int child = createAndFillRecord(fs, fake, parentId, attributes);
      FSRecords.updateList(parentId, ArrayUtil.append(children, child));
      return child;
    }

    return 0;
  }
Exemple #13
0
  @Override
  @Nullable
  public VirtualFileSystemEntry findRoot(
      @NotNull String basePath, @NotNull NewVirtualFileSystem fs) {
    if (basePath.isEmpty()) {
      LOG.error("Invalid root, fs=" + fs);
      return null;
    }

    String rootUrl = normalizeRootUrl(basePath, fs);

    myRootsLock.readLock().lock();
    try {
      VirtualFileSystemEntry root = myRoots.get(rootUrl);
      if (root != null) return root;
    } finally {
      myRootsLock.readLock().unlock();
    }

    final VirtualFileSystemEntry newRoot;
    int rootId = FSRecords.findRootRecord(rootUrl);

    VfsData.Segment segment = VfsData.getSegment(rootId, true);
    VfsData.DirectoryData directoryData = new VfsData.DirectoryData();
    if (fs instanceof ArchiveFileSystem) {
      String parentPath =
          basePath.substring(0, basePath.indexOf(ArchiveFileSystem.ARCHIVE_SEPARATOR));
      VirtualFile parentFile = LocalFileSystem.getInstance().findFileByPath(parentPath);
      if (parentFile == null) return null;
      FileType type = FileTypeRegistry.getInstance().getFileTypeByFileName(parentFile.getName());
      if (!(type instanceof ArchiveFileType)) return null;
      newRoot = new ArchiveRoot(fs, rootId, segment, directoryData, parentFile);
    } else {
      newRoot = new FsRoot(fs, rootId, segment, directoryData, basePath);
    }

    FileAttributes attributes =
        fs.getAttributes(
            new StubVirtualFile() {
              @NotNull
              @Override
              public String getPath() {
                return newRoot.getPath();
              }

              @Nullable
              @Override
              public VirtualFile getParent() {
                return null;
              }
            });
    if (attributes == null || !attributes.isDirectory()) {
      return null;
    }

    boolean mark = false;

    myRootsLock.writeLock().lock();
    try {
      VirtualFileSystemEntry root = myRoots.get(rootUrl);
      if (root != null) return root;

      VfsData.initFile(rootId, segment, -1, directoryData);
      mark = writeAttributesToRecord(rootId, 0, newRoot, fs, attributes);

      myRoots.put(rootUrl, newRoot);
      myRootsById.put(rootId, newRoot);
    } finally {
      myRootsLock.writeLock().unlock();
    }

    if (!mark && attributes.lastModified != FSRecords.getTimestamp(rootId)) {
      newRoot.markDirtyRecursively();
    }

    LOG.assertTrue(
        rootId == newRoot.getId(),
        "root=" + newRoot + " expected=" + rootId + " actual=" + newRoot.getId());

    return newRoot;
  }
  @Override
  @Nullable
  public VirtualFileSystemEntry findRoot(
      @NotNull String basePath, @NotNull NewVirtualFileSystem fs) {
    String rootUrl = normalizeRootUrl(basePath, fs);
    boolean isFakeRoot = basePath.isEmpty();
    VirtualFileSystemEntry root;

    myRootsLock.readLock().lock();
    try {
      root = isFakeRoot ? mySuperRoot : myRoots.get(rootUrl);
      if (root != null) return root;
    } finally {
      myRootsLock.readLock().unlock();
    }

    myRootsLock.writeLock().lock();
    try {
      root = isFakeRoot ? mySuperRoot : myRoots.get(rootUrl);
      if (root != null) return root;

      int rootId = FSRecords.findRootRecord(rootUrl);
      root = myRootsById.get(rootId);
      if (root != null) return root;

      if (isFakeRoot) {
        // fake super-root
        root = new FakeRoot(fs, rootId);
      } else if (fs instanceof JarFileSystem) {
        // optimization: for jar roots do not store base path in the myName field, use local FS
        // file's getPath()
        String parentPath = basePath.substring(0, basePath.indexOf(JarFileSystem.JAR_SEPARATOR));
        VirtualFile parentLocalFile = LocalFileSystem.getInstance().findFileByPath(parentPath);
        if (parentLocalFile == null) return null;

        // check one more time since the findFileByPath could have created the root (by reentering
        // the findRoot)
        root = myRoots.get(rootUrl);
        if (root != null) return root;
        root = myRootsById.get(rootId);
        if (root != null) return root;

        root = new JarRoot(fs, rootId, parentLocalFile);
      } else {
        root = new FsRoot(fs, rootId, basePath);
      }

      if (isFakeRoot) {
        mySuperRoot = root;
      } else {
        FileAttributes attributes = fs.getAttributes(root);
        if (attributes == null || !attributes.isDirectory()) {
          return null;
        }
        final boolean newRoot = writeAttributesToRecord(rootId, 0, root, fs, attributes);
        if (!newRoot && attributes.lastModified != FSRecords.getTimestamp(rootId)) {
          root.markDirtyRecursively();
        }

        myRoots.put(rootUrl, root);
        myRootsById.put(rootId, root);

        if (rootId != root.getId()) throw new AssertionError();
      }

      return root;
    } finally {
      myRootsLock.writeLock().unlock();
    }
  }
  @Nullable
  public RequestFuture scheduleBuild(
      final Project project,
      final boolean isRebuild,
      final boolean isMake,
      final Collection<String> modules,
      final Collection<String> artifacts,
      final Collection<String> paths,
      final Map<String, String> userData,
      DefaultMessageHandler handler) {

    final String projectPath = getProjectPath(project);
    final UUID sessionId = UUID.randomUUID();
    final CmdlineRemoteProto.Message.ControllerMessage params;
    CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = myGlobals;
    if (globals == null) {
      globals = buildGlobalSettings();
      myGlobals = globals;
    }

    CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges = null;
    final SequentialTaskExecutor projectTaskQueue;
    synchronized (myProjectDataMap) {
      ProjectData data = myProjectDataMap.get(projectPath);
      if (data == null) {
        data = new ProjectData(new SequentialTaskExecutor(myPooledThreadExecutor));
        myProjectDataMap.put(projectPath, data);
      }
      if (isRebuild) {
        data.dropChanges();
      }
      currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent();
      projectTaskQueue = data.taskQueue;
    }

    if (isRebuild) {
      params = CmdlineProtoUtil.createRebuildRequest(projectPath, userData, globals);
    } else {
      params =
          isMake
              ? CmdlineProtoUtil.createMakeRequest(
                  projectPath, modules, artifacts, userData, globals, currentFSChanges)
              : CmdlineProtoUtil.createForceCompileRequest(
                  projectPath, modules, artifacts, paths, userData, globals, currentFSChanges);
    }

    myMessageDispatcher.registerBuildMessageHandler(sessionId, handler, params);

    // ensure server is listening
    if (myListenPort < 0) {
      try {
        myListenPort = startListening();
      } catch (Exception e) {
        myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
        handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
        handler.sessionTerminated();
        return null;
      }
    }

    final RequestFuture<BuilderMessageHandler> future =
        new RequestFuture<BuilderMessageHandler>(
            handler,
            sessionId,
            new RequestFuture.CancelAction<BuilderMessageHandler>() {
              @Override
              public void cancel(RequestFuture<BuilderMessageHandler> future) throws Exception {
                myMessageDispatcher.cancelSession(future.getRequestID());
              }
            });

    projectTaskQueue.submit(
        new Runnable() {
          @Override
          public void run() {
            try {
              if (project.isDisposed()) {
                future.cancel(false);
                return;
              }
              myBuildsInProgress.put(projectPath, future);
              final Process process = launchBuildProcess(project, myListenPort, sessionId);
              final OSProcessHandler processHandler =
                  new OSProcessHandler(process, null) {
                    @Override
                    protected boolean shouldDestroyProcessRecursively() {
                      return true;
                    }
                  };
              final StringBuilder stdErrOutput = new StringBuilder();
              processHandler.addProcessListener(
                  new ProcessAdapter() {
                    @Override
                    public void processTerminated(ProcessEvent event) {
                      final BuilderMessageHandler handler =
                          myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
                      if (handler != null) {
                        handler.sessionTerminated();
                      }
                    }

                    @Override
                    public void onTextAvailable(ProcessEvent event, Key outputType) {
                      // re-translate builder's output to idea.log
                      final String text = event.getText();
                      if (!StringUtil.isEmpty(text)) {
                        LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
                        if (stdErrOutput.length() < 1024
                            && ProcessOutputTypes.STDERR.equals(outputType)) {
                          stdErrOutput.append(text);
                        }
                      }
                    }
                  });
              processHandler.startNotify();
              final boolean terminated = processHandler.waitFor();
              if (terminated) {
                final int exitValue = processHandler.getProcess().exitValue();
                if (exitValue != 0) {
                  final StringBuilder msg = new StringBuilder();
                  msg.append("Abnormal build process termination: ");
                  if (stdErrOutput.length() > 0) {
                    msg.append("\n").append(stdErrOutput);
                  } else {
                    msg.append("unknown error");
                  }
                  future
                      .getMessageHandler()
                      .handleFailure(
                          sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
                }
              } else {
                future
                    .getMessageHandler()
                    .handleFailure(
                        sessionId,
                        CmdlineProtoUtil.createFailure("Disconnected from build process", null));
              }
            } catch (ExecutionException e) {
              myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
              future
                  .getMessageHandler()
                  .handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
              future.getMessageHandler().sessionTerminated();
            } finally {
              myBuildsInProgress.remove(projectPath);
              future.setDone();
            }
          }
        });

    return future;
  }