| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.versioning.system.cvss.installer; |
| |
| import java.awt.Dialog; |
| import java.awt.EventQueue; |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.io.File; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.swing.JButton; |
| import org.netbeans.api.autoupdate.InstallSupport; |
| import org.netbeans.api.autoupdate.OperationContainer; |
| import org.netbeans.api.autoupdate.OperationException; |
| import org.netbeans.api.autoupdate.OperationSupport; |
| import org.netbeans.api.autoupdate.OperationSupport.Restarter; |
| import org.netbeans.api.autoupdate.UpdateElement; |
| import org.netbeans.api.autoupdate.UpdateManager; |
| import org.netbeans.api.autoupdate.UpdateUnit; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.api.project.ui.OpenProjects; |
| import org.netbeans.modules.autoupdate.ui.api.PluginManager; |
| import org.netbeans.modules.versioning.spi.VersioningSupport; |
| import org.netbeans.modules.versioning.spi.VersioningSystem; |
| import org.netbeans.modules.versioning.system.cvss.installer.util.Utils; |
| import org.openide.DialogDescriptor; |
| import org.openide.DialogDisplayer; |
| import org.openide.NotifyDescriptor; |
| import org.openide.awt.Mnemonics; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.FileUtil; |
| import org.openide.util.NbBundle; |
| import org.openide.util.RequestProcessor; |
| import org.openide.util.WeakListeners; |
| |
| /** |
| * |
| * @author ondra |
| */ |
| @VersioningSystem.Registration( |
| displayName="#CTL_CvsInstaller_DisplayName", |
| menuLabel="", |
| actionsCategory="CVS", |
| metadataFolderNames="CVS") |
| public final class CvsInstaller extends VersioningSystem { |
| |
| public static final Logger LOG = Logger.getLogger(CvsInstaller.class.getName()); |
| private final Set<File> unversionedParents = Collections.synchronizedSet(new HashSet<File>(20)); |
| public static final String FILENAME_CVS = "CVS"; //NOI18N |
| public static final String FILENAME_CVS_REPOSITORY = FILENAME_CVS + "/Repository"; // NOI18N |
| public static final String FILENAME_CVS_ENTRIES = FILENAME_CVS + "/Entries"; // NOI18N |
| private static final RequestProcessor RP = new RequestProcessor("CVS Installer", 1, false, false); //NOI18N |
| private final RequestProcessor.Task task; |
| private final AsyncTask installTask; |
| private static final String CVS_CODENAME = "org.netbeans.modules.versioning.system.cvss"; //NOI18N |
| private static final String INSTALLER_CODENAME = "org.netbeans.modules.versioning.system.cvss.installer"; //NOI18N |
| |
| public CvsInstaller () { |
| installTask = new AsyncTask(); |
| task = RP.create(installTask); |
| } |
| |
| @Override |
| public File getTopmostManagedAncestor (File file) { |
| if (CvsInstallerModuleConfig.getInstance().isCvsInstalled()) { |
| // no need for this module, will be uninstalled |
| task.schedule(0); |
| return null; |
| } |
| if (CvsInstallerModuleConfig.getInstance().isIgnored()) { |
| return null; |
| } |
| return getTopmostManagedAncestor (file, false); |
| } |
| |
| public File getTopmostManagedAncestor (File file, boolean internal) { |
| long t = System.currentTimeMillis(); |
| LOG.log(Level.FINE, "getTopmostManagedParent {0}", new Object[] { file }); |
| if(unversionedParents.contains(file)) { |
| LOG.fine(" cached as unversioned"); |
| return null; |
| } |
| if (Utils.isPartOfCVSMetadata(file)) { |
| LOG.fine(" part of metaddata"); |
| for (;file != null; file = file.getParentFile()) { |
| if (file.getName().equals(FILENAME_CVS) && (file.isDirectory() || !file.exists())) { |
| file = file.getParentFile(); |
| LOG.log(Level.FINE, " will use parent {0}", new Object[] { file }); |
| break; |
| } |
| } |
| } |
| |
| Set<File> done = new HashSet<File>(); |
| File topmost = null; |
| for (; file != null; file = file.getParentFile()) { |
| if(unversionedParents.contains(file)) { |
| LOG.log(Level.FINE, " already known as unversioned {0}", new Object[] { file }); |
| break; |
| } |
| if (VersioningSupport.isExcluded(file)) break; |
| if (Utils.containsMetadata(file)) { |
| LOG.log(Level.FINE, " found managed parent {0}", new Object[] { file }); |
| topmost = file; |
| done.clear(); // all folders added before must be removed, they ARE in fact managed by CVS |
| } else { |
| LOG.log(Level.FINE, " found unversioned {0}", new Object[] { file }); |
| if(file.exists()) { // could be created later ... |
| done.add(file); |
| } |
| } |
| } |
| if(done.size() > 0) { |
| LOG.log(Level.FINE, " storing unversioned"); |
| unversionedParents.addAll(done); |
| } |
| if(LOG.isLoggable(Level.FINE)) { |
| LOG.log(Level.FINE, " getTopmostManagedParent returns {0} after {1} millis", new Object[] { topmost, System.currentTimeMillis() - t }); |
| } |
| if (internal) { |
| return topmost; |
| } else { |
| if (topmost != null) { |
| // now we have a cvs checkout and the download dialog has not been displayed or we're running with a fresh userdir |
| task.schedule(0); |
| } |
| return null; |
| } |
| } |
| |
| private boolean isCvsInstalled () { |
| assert !EventQueue.isDispatchThread(); |
| for (UpdateUnit u : UpdateManager.getDefault().getUpdateUnits()) { |
| if (CVS_CODENAME.equals(u.getCodeName())) { |
| return u.getInstalled() != null; |
| } |
| } |
| return false; |
| } |
| |
| private static boolean downloadWindowDisplayed; |
| private class AsyncTask implements Runnable { |
| |
| private PropertyChangeListener listener; |
| |
| @Override |
| public void run () { |
| // cvs might have been installed manually, check that |
| if (CvsInstallerModuleConfig.getInstance().isCvsInstalled() || isCvsInstalled()) { |
| doFinish(); |
| return; |
| } |
| if (downloadWindowDisplayed || CvsInstallerModuleConfig.getInstance().isIgnored()) { |
| return; |
| } |
| // cvs not yet installed, attach a listener to open projects and wait for a cvs project to be opened |
| OpenProjects projs = OpenProjects.getDefault(); |
| if (listener == null) { |
| projs.addPropertyChangeListener(WeakListeners.propertyChange(listener = new PropertyChangeListener() { |
| @Override |
| public void propertyChange (PropertyChangeEvent evt) { |
| if (OpenProjects.PROPERTY_OPEN_PROJECTS.equals(evt.getPropertyName())) { |
| task.schedule(0); |
| } |
| } |
| }, projs)); |
| } |
| Project[] projects; |
| try { |
| projects = projs.openProjects().get(); |
| } catch (Exception ex) { |
| LOG.log(Level.INFO, null, ex); |
| projects = projs.getOpenProjects(); |
| } |
| for (Project p : projects) { |
| FileObject fo = p.getProjectDirectory(); |
| File f = FileUtil.toFile(fo); |
| // is the project directory under CVS control? |
| if (f != null && getTopmostManagedAncestor(f, true) != null) { |
| processCvsProject(p); |
| break; |
| } |
| } |
| } |
| |
| private void doFinish () { |
| CvsInstallerModuleConfig.getInstance().setCvsInstalled(true); |
| if (listener != null) { |
| OpenProjects.getDefault().removePropertyChangeListener(listener); |
| listener = null; |
| } |
| assert !EventQueue.isDispatchThread(); |
| for (UpdateUnit u : UpdateManager.getDefault().getUpdateUnits()) { |
| if (INSTALLER_CODENAME.equals(u.getCodeName()) && u.getInstalled() != null && !u.isPending()) { |
| OperationContainer<OperationSupport> container = OperationContainer.createForUninstall(); |
| if (container.canBeAdded(u, u.getInstalled())) { |
| container.add(u, u.getInstalled()); |
| try { |
| LOG.log(Level.INFO, "doFinish: uninstalling"); //NOI18N |
| OperationSupport support = container.getSupport(); |
| Restarter restarter = support.doOperation(null); |
| LOG.log(Level.INFO, "doFinish: uninstalled"); //NOI18N |
| if (restarter != null) { |
| LOG.log(Level.INFO, "doFinish: restart scheduled"); //NOI18N |
| support.doRestartLater(restarter); |
| } |
| } catch (OperationException ex) { |
| LOG.log(Level.INFO, null, ex); |
| } |
| } |
| } |
| } |
| } |
| |
| private void processCvsProject (Project p) { |
| JButton installButton = new JButton(); |
| Mnemonics.setLocalizedText(installButton, NbBundle.getMessage(CvsInstallDialog.class, "CvsInstallDialog.downloadButton.text")); //NOI18N |
| CvsInstallDialog panel = new CvsInstallDialog(); |
| DialogDescriptor dd = new DialogDescriptor(panel, NbBundle.getMessage(CvsInstallDialog.class, "CvsInstallDialog.title"), //NOI18N |
| true, new Object[] { installButton, DialogDescriptor.CANCEL_OPTION }, installButton, DialogDescriptor.DEFAULT_ALIGN, null, null); |
| Dialog dialog = DialogDisplayer.getDefault().createDialog(dd); |
| dialog.setVisible(true); |
| // no more dialog in the future |
| downloadWindowDisplayed = true; |
| if (listener != null) { |
| OpenProjects.getDefault().removePropertyChangeListener(listener); |
| listener = null; |
| } |
| // handle result |
| if (panel.cbDoNotAsk.isSelected()) { |
| CvsInstallerModuleConfig.getInstance().setIgnored(true); |
| } |
| if (dd.getValue() == installButton) { |
| // install CVS support |
| if (installCvsSupport()) { |
| // and uninstall me |
| doFinish(); |
| } else { |
| // huh? probably a connection issue? user canceled the download or did not accept the license? |
| CvsInstallerModuleConfig.getInstance().setIgnored(false); |
| DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message(NbBundle.getMessage(CvsInstaller.class, "CvsInstaller.installFailed"), //NOI18N |
| NotifyDescriptor.ERROR_MESSAGE)); |
| } |
| } |
| } |
| |
| private boolean installCvsSupport () { |
| assert !EventQueue.isDispatchThread(); |
| for (UpdateUnit u : UpdateManager.getDefault().getUpdateUnits()) { |
| if (CVS_CODENAME.equals(u.getCodeName()) && u.getInstalled() == null) { |
| if (u.getAvailableUpdates().size() > 0) { |
| UpdateElement element = u.getAvailableUpdates().get(0); |
| OperationContainer<InstallSupport> container = OperationContainer.createForInstall(); |
| if (container.canBeAdded(u, element)) { |
| container.add(u, element); |
| LOG.log(Level.INFO, "installCvsSupport: installing CVS"); //NOI18N |
| return PluginManager.openInstallWizard(container); |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| } |
| } |