private boolean tryToReloadApplication() { try { final Application app = ApplicationManager.getApplication(); if (app.isDisposed()) return false; final HashSet<Pair<VirtualFile, StateStorage>> causes = new HashSet<Pair<VirtualFile, StateStorage>>(myChangedApplicationFiles); if (causes.isEmpty()) return true; final boolean[] reloadOk = {false}; final LinkedHashSet<String> components = new LinkedHashSet<String>(); ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { try { reloadOk[0] = ((ApplicationImpl) app).getStateStore().reload(causes, components); } catch (StateStorageException e) { Messages.showWarningDialog( ProjectBundle.message("project.reload.failed", e.getMessage()), ProjectBundle.message("project.reload.failed.title")); } catch (IOException e) { Messages.showWarningDialog( ProjectBundle.message("project.reload.failed", e.getMessage()), ProjectBundle.message("project.reload.failed.title")); } } }); if (!reloadOk[0] && !components.isEmpty()) { String message = "Application components were changed externally and cannot be reloaded:\n"; for (String component : components) { message += component + "\n"; } final boolean canRestart = ApplicationManager.getApplication().isRestartCapable(); message += "Would you like to " + (canRestart ? "restart " : "shutdown "); message += ApplicationNamesInfo.getInstance().getProductName() + "?"; if (Messages.showYesNoDialog( message, "Application Configuration Reload", Messages.getQuestionIcon()) == Messages.YES) { for (Pair<VirtualFile, StateStorage> cause : causes) { StateStorage stateStorage = cause.getSecond(); if (stateStorage instanceof XmlElementStorage) { ((XmlElementStorage) stateStorage).disableSaving(); } } ApplicationManagerEx.getApplicationEx().restart(true); } } return reloadOk[0]; } finally { myChangedApplicationFiles.clear(); } }
private void initProject(@NotNull ProjectImpl project, @Nullable ProjectImpl template) throws IOException { final ProgressIndicator indicator = myProgressManager.getProgressIndicator(); if (indicator != null && !project.isDefault()) { indicator.setText(ProjectBundle.message("loading.components.for", project.getName())); indicator.setIndeterminate(true); } ApplicationManager.getApplication() .getMessageBus() .syncPublisher(ProjectLifecycleListener.TOPIC) .beforeProjectLoaded(project); try { if (template != null) { project.getStateStore().loadProjectFromTemplate(template); } else { project.getStateStore().load(); } project.loadProjectComponents(); project.init(); } catch (IOException e) { scheduleDispose(project); throw e; } catch (ProcessCanceledException e) { scheduleDispose(project); throw e; } }
private void scheduleReloadApplicationAndProject() { // todo: commented due to "IDEA-61938 Libraries configuration is kept if switching branches" // because of save which may happen _before_ project reload ;( // ApplicationManager.getApplication().invokeLater(new Runnable() { // public void run() { // IdeEventQueue.getInstance().addIdleListener(new Runnable() { // @Override // public void run() { // IdeEventQueue.getInstance().removeIdleListener(this); ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { if (!tryToReloadApplication()) return; askToReloadProjectIfConfigFilesChangedExternally(); } }, ModalityState.NON_MODAL); // } // }, 2000); // } // }, ModalityState.NON_MODAL); }
@Override @NotNull public Project[] getOpenProjects() { synchronized (myOpenProjects) { if (myOpenProjectsArrayCache.length != myOpenProjects.size()) { LOG.error( "Open projects: " + myOpenProjects + "; cache: " + Arrays.asList(myOpenProjectsArrayCache)); } if (myOpenProjectsArrayCache.length > 0 && myOpenProjectsArrayCache[0] != myOpenProjects.get(0)) { LOG.error( "Open projects cache corrupted. Open projects: " + myOpenProjects + "; cache: " + Arrays.asList(myOpenProjectsArrayCache)); } if (ApplicationManager.getApplication().isUnitTestMode()) { Project[] testProjects = myTestProjects.toArray(new Project[myTestProjects.size()]); for (Project testProject : testProjects) { assert !testProject.isDisposed() : testProject; } return ArrayUtil.mergeArrays(myOpenProjectsArrayCache, testProjects); } return myOpenProjectsArrayCache; } }
private static void notifyProjectOpenFailed() { ApplicationManager.getApplication() .getMessageBus() .syncPublisher(AppLifecycleListener.TOPIC) .projectOpenFailed(); WelcomeFrame.showIfNoProjectOpened(); }
@Override public boolean isProjectOpened(Project project) { synchronized (myOpenProjects) { return ApplicationManager.getApplication().isUnitTestMode() && myTestProjects.contains(project) || myOpenProjects.contains(project); } }
@Override public void openTestProject(@NotNull final Project project) { synchronized (myOpenProjects) { assert ApplicationManager.getApplication().isUnitTestMode(); assert !project.isDisposed() : "Must not open already disposed project"; myTestProjects.add(project); } }
@Override public Collection<Project> closeTestProject(@NotNull Project project) { synchronized (myOpenProjects) { assert ApplicationManager.getApplication().isUnitTestMode(); myTestProjects.remove(project); return myTestProjects; } }
public static void addExcludedRoot(Module module, VirtualFile dir) { ModuleRootModificationUtil.updateModel( module, model -> ApplicationManager.getApplication() .runReadAction( () -> { findContentEntryWithAssertion(model, dir).addExcludeFolder(dir); })); }
@Override public void disposeComponent() { ApplicationManager.getApplication().assertWriteAccessAllowed(); Disposer.dispose(myChangedFilesAlarm); if (myDefaultProject != null) { Disposer.dispose(myDefaultProject); myDefaultProject = null; myDefaultProjectWasDisposed = true; } }
@Override @Nullable public Project newProject( final String projectName, @NotNull String filePath, boolean useDefaultProjectSettings, boolean isDummy) { filePath = toCanonicalName(filePath); //noinspection ConstantConditions if (LOG_PROJECT_LEAKAGE_IN_TESTS && ApplicationManager.getApplication().isUnitTestMode()) { for (int i = 0; i < 42; i++) { if (myProjects.size() < MAX_LEAKY_PROJECTS) break; System.gc(); TimeoutUtil.sleep(100); System.gc(); } if (myProjects.size() >= MAX_LEAKY_PROJECTS) { List<Project> copy = new ArrayList<Project>(myProjects.keySet()); myProjects.clear(); throw new TooManyProjectLeakedException(copy); } } ProjectImpl project = createProject( projectName, filePath, false, ApplicationManager.getApplication().isUnitTestMode()); try { initProject(project, useDefaultProjectSettings ? (ProjectImpl) getDefaultProject() : null); if (LOG_PROJECT_LEAKAGE_IN_TESTS) { myProjects.put(project, null); } return project; } catch (final Exception e) { LOG.info(e); Messages.showErrorDialog(message(e), ProjectBundle.message("project.load.default.error")); } return null; }
public void reloadProjectImpl(@NotNull final Project p, final boolean clearCopyToRestore) { if (clearCopyToRestore) { mySavedCopies.clear(); mySavedTimestamps.clear(); } final Project[] project = {p}; ProjectReloadState.getInstance(project[0]).onBeforeAutomaticProjectReload(); final Application application = ApplicationManager.getApplication(); application.invokeLater( new Runnable() { @Override public void run() { LOG.debug("Reloading project."); ProjectImpl projectImpl = (ProjectImpl) project[0]; if (projectImpl.isDisposed()) return; IProjectStore projectStore = projectImpl.getStateStore(); final String location = projectImpl.getPresentableUrl(); final List<IFile> original; try { final IComponentStore.SaveSession saveSession = projectStore.startSave(); original = saveSession.getAllStorageFiles(true); saveSession.finishSave(); } catch (IOException e) { LOG.error(e); return; } if (project[0].isDisposed() || ProjectUtil.closeAndDispose(project[0])) { application.runWriteAction( new Runnable() { @Override public void run() { for (final IFile originalFile : original) { restoreCopy( LocalFileSystem.getInstance().refreshAndFindFileByIoFile(originalFile)); } } }); project[0] = null; // Let it go. ProjectUtil.openProject(location, null, true); } } }, ModalityState.NON_MODAL); }
public boolean closeProject( @NotNull final Project project, final boolean save, final boolean dispose, boolean checkCanClose) { if (isLight(project)) { throw new AssertionError("must not close light project"); } if (!isProjectOpened(project)) return true; if (checkCanClose && !canClose(project)) return false; final ShutDownTracker shutDownTracker = ShutDownTracker.getInstance(); shutDownTracker.registerStopperThread(Thread.currentThread()); try { if (save) { FileDocumentManager.getInstance().saveAllDocuments(); project.save(); } if (checkCanClose && !ensureCouldCloseIfUnableToSave(project)) { return false; } fireProjectClosing(project); // somebody can start progress here, do not wrap in write action ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { synchronized (myOpenProjects) { myOpenProjects.remove(project); cacheOpenProjects(); myTestProjects.remove(project); } myChangedProjectFiles.remove(project); fireProjectClosed(project); if (dispose) { Disposer.dispose(project); } } }); } finally { shutDownTracker.unregisterStopperThread(Thread.currentThread()); } return true; }
@Override @NotNull public synchronized Project getDefaultProject() { LOG.assertTrue(!myDefaultProjectWasDisposed, "Default project has been already disposed!"); if (myDefaultProject == null) { try { myDefaultProject = createProject(null, "", true, ApplicationManager.getApplication().isUnitTestMode()); initProject(myDefaultProject, null); myDefaultProjectRootElement = null; } catch (IOException e) { LOG.error(e); } catch (StateStorageException e) { LOG.error(e); } } return myDefaultProject; }
private static void scheduleDispose(final ProjectImpl project) { if (project.isDefault()) { return; } ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { if (!project.isDisposed()) { Disposer.dispose(project); } } }); } }); }
@Override public Project loadAndOpenProject(@NotNull final String filePath) throws IOException { final Project project = convertAndLoadProject(filePath); if (project == null) { WelcomeFrame.showIfNoProjectOpened(); return null; } // todo unify this logic with PlatformProjectOpenProcessor if (!openProject(project)) { WelcomeFrame.showIfNoProjectOpened(); ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { Disposer.dispose(project); } }); } return project; }
@Override public boolean openProject(final Project project) { if (isLight(project)) { throw new AssertionError("must not open light project"); } final Application application = ApplicationManager.getApplication(); if (!application.isUnitTestMode() && !((ProjectEx) project).getStateStore().checkVersion()) { return false; } synchronized (myOpenProjects) { if (myOpenProjects.contains(project)) { return false; } myOpenProjects.add(project); cacheOpenProjects(); } fireProjectOpened(project); final StartupManagerImpl startupManager = (StartupManagerImpl) StartupManager.getInstance(project); waitForFileWatcher(project); boolean ok = myProgressManager.runProcessWithProgressSynchronously( new Runnable() { @Override public void run() { startupManager.runStartupActivities(); // dumb mode should start before post-startup activities // only when startCacheUpdate is called from UI thread, we can guarantee that // when the method returns, the application has entered dumb mode UIUtil.invokeAndWaitIfNeeded( new Runnable() { @Override public void run() { startupManager.startCacheUpdate(); } }); startupManager.runPostStartupActivitiesFromExtensions(); UIUtil.invokeLaterIfNeeded( new Runnable() { @Override public void run() { startupManager.runPostStartupActivities(); } }); } }, ProjectBundle.message("project.load.progress"), true, project); if (!ok) { closeProject(project, false, false, true); notifyProjectOpenFailed(); return false; } if (!application.isHeadlessEnvironment() && !application.isUnitTestMode()) { // should be invoked last startupManager.runWhenProjectIsInitialized( new Runnable() { @Override public void run() { final TrackingPathMacroSubstitutor macroSubstitutor = ((ProjectEx) project) .getStateStore() .getStateStorageManager() .getMacroSubstitutor(); if (macroSubstitutor != null) { StorageUtil.notifyUnknownMacros(macroSubstitutor, project, null); } } }); } return true; }
/** @noinspection UnusedParameters */ public ProjectManagerImpl( VirtualFileManager virtualFileManager, RecentProjectsManagerBase recentProjectsManager, ProgressManager progressManager) { myProgressManager = progressManager; Application app = ApplicationManager.getApplication(); MessageBus messageBus = app.getMessageBus(); MessageBusConnection connection = messageBus.connect(app); connection.subscribe( StateStorage.STORAGE_TOPIC, new StateStorage.Listener() { @Override public void storageFileChanged( @NotNull final VirtualFileEvent event, @NotNull final StateStorage storage) { VirtualFile file = event.getFile(); if (!file.isDirectory() && !(event.getRequestor() instanceof StateStorage.SaveSession)) { saveChangedProjectFile(file, null, storage); } } }); final ProjectManagerListener busPublisher = messageBus.syncPublisher(TOPIC); addProjectManagerListener( new ProjectManagerListener() { @Override public void projectOpened(final Project project) { MessageBus messageBus = project.getMessageBus(); MessageBusConnection connection = messageBus.connect(project); connection.subscribe( StateStorage.STORAGE_TOPIC, new StateStorage.Listener() { @Override public void storageFileChanged( @NotNull final VirtualFileEvent event, @NotNull final StateStorage storage) { VirtualFile file = event.getFile(); if (!file.isDirectory() && !(event.getRequestor() instanceof StateStorage.SaveSession)) { saveChangedProjectFile(file, project, storage); } } }); busPublisher.projectOpened(project); for (ProjectManagerListener listener : getListeners(project)) { listener.projectOpened(project); } } @Override public void projectClosed(Project project) { busPublisher.projectClosed(project); for (ProjectManagerListener listener : getListeners(project)) { listener.projectClosed(project); } } @Override public boolean canCloseProject(Project project) { for (ProjectManagerListener listener : getListeners(project)) { if (!listener.canCloseProject(project)) { return false; } } return true; } @Override public void projectClosing(Project project) { busPublisher.projectClosing(project); for (ProjectManagerListener listener : getListeners(project)) { listener.projectClosing(project); } } }); registerExternalProjectFileListener(virtualFileManager); }
public static boolean isLight(@NotNull Project project) { return ApplicationManager.getApplication().isUnitTestMode() && project.toString().contains("light_temp_"); }
private boolean shouldReloadProject(final Project project) { if (project.isDisposed()) return false; final HashSet<Pair<VirtualFile, StateStorage>> causes = new HashSet<Pair<VirtualFile, StateStorage>>(); synchronized (myChangedProjectFiles) { final List<Pair<VirtualFile, StateStorage>> changes = myChangedProjectFiles.remove(project); if (changes != null) { causes.addAll(changes); } if (causes.isEmpty()) return false; } final boolean[] reloadOk = {false}; ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { try { LOG.debug("[RELOAD] Reloading project/components..."); reloadOk[0] = ((ProjectEx) project).getStateStore().reload(causes); } catch (StateStorageException e) { Messages.showWarningDialog( ProjectBundle.message("project.reload.failed", e.getMessage()), ProjectBundle.message("project.reload.failed.title")); } catch (IOException e) { Messages.showWarningDialog( ProjectBundle.message("project.reload.failed", e.getMessage()), ProjectBundle.message("project.reload.failed.title")); } } }); if (reloadOk[0]) return false; String message; if (causes.size() == 1) { message = ProjectBundle.message( "project.reload.external.change.single", causes.iterator().next().first.getPresentableUrl()); } else { StringBuilder filesBuilder = new StringBuilder(); boolean first = true; Set<String> alreadyShown = new HashSet<String>(); for (Pair<VirtualFile, StateStorage> cause : causes) { String url = cause.first.getPresentableUrl(); if (!alreadyShown.contains(url)) { if (alreadyShown.size() > 10) { filesBuilder .append("\n" + "and ") .append(causes.size() - alreadyShown.size()) .append(" more"); break; } if (!first) filesBuilder.append("\n"); first = false; filesBuilder.append(url); alreadyShown.add(url); } } message = ProjectBundle.message("project.reload.external.change.multiple", filesBuilder.toString()); } return Messages.showTwoStepConfirmationDialog( message, ProjectBundle.message("project.reload.external.change.title"), "Reload project", Messages.getQuestionIcon()) == 0; }