Java tutorial
/* * Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.oomph.p2.internal.ui; import org.eclipse.oomph.p2.core.Agent; import org.eclipse.oomph.p2.core.AgentManager; import org.eclipse.oomph.p2.core.AgentManagerElement; import org.eclipse.oomph.p2.core.BundlePool; import org.eclipse.oomph.p2.core.P2Util; import org.eclipse.oomph.p2.core.Profile; import org.eclipse.oomph.p2.internal.core.AgentAnalyzer; import org.eclipse.oomph.p2.internal.core.AgentAnalyzer.AnalyzedArtifact; import org.eclipse.oomph.p2.internal.core.AgentAnalyzer.AnalyzedBundlePool; import org.eclipse.oomph.p2.internal.core.AgentAnalyzer.AnalyzedProfile; import org.eclipse.oomph.p2.internal.core.AgentManagerElementImpl; import org.eclipse.oomph.ui.ErrorDialog; import org.eclipse.oomph.ui.UIUtil; import org.eclipse.oomph.util.OomphPlugin.Preference; import org.eclipse.oomph.util.PropertiesUtil; import org.eclipse.oomph.util.SubMonitor; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Tree; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Collection; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; /** * @author Eike Stepper */ public class AgentManagerComposite extends Composite { // The standalone installer doesn't remember instance preferences in debug mode. private static final Preference PREF_SHOW_PROFILES = P2UIPlugin.INSTANCE .getConfigurationPreference("showProfiles"); private TreeViewer treeViewer; private Object selectedElement; private Button refreshButton; private Button newAgentButton; private Button newPoolButton; private Button deleteButton; private Button cleanupButton; private Button analyzeButton; private Button showProfilesButton; private Button profileDetailsButton; public AgentManagerComposite(Composite parent, int style, final Object selection) { super(parent, style); setBackground(getDisplay().getSystemColor(SWT.COLOR_TRANSPARENT)); setLayout(UIUtil.createGridLayout(2)); final P2ContentProvider contentProvider = new P2ContentProvider(); treeViewer = new TreeViewer(this, SWT.BORDER); treeViewer.setContentProvider(contentProvider); treeViewer.setLabelProvider(new P2LabelProvider()); treeViewer.setSorter(new P2ViewerSorter()); treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { selectedElement = ((IStructuredSelection) treeViewer.getSelection()).getFirstElement(); elementChanged(selectedElement); } }); Tree tree = treeViewer.getTree(); tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); tree.addMouseListener(new MouseAdapter() { @Override public void mouseDoubleClick(MouseEvent e) { if (selectedElement instanceof Profile) { showProfileDetails(); } else { treeViewer.setExpandedState(selectedElement, !treeViewer.getExpandedState(selectedElement)); } } }); tree.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.DEL && deleteButton.isEnabled()) { deletePressed(); } } }); GridLayout buttonLayout = new GridLayout(1, false); buttonLayout.marginWidth = 0; buttonLayout.marginHeight = 0; Composite buttonComposite = new Composite(this, SWT.NONE); buttonComposite.setLayout(buttonLayout); buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true)); buttonComposite.setBounds(0, 0, 64, 64); newAgentButton = new Button(buttonComposite, SWT.NONE); newAgentButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); newAgentButton.setText("New Agent..."); newAgentButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { String path = openDirectoryDialog("Select the location of the new agent.", PropertiesUtil.getUserHome()); if (path != null) { Agent agent = P2Util.getAgentManager().addAgent(new File(path)); BundlePool bundlePool = agent.addBundlePool(new File(path, BundlePool.DEFAULT_NAME)); refreshFor(bundlePool); } } }); cleanupButton = new Button(buttonComposite, SWT.NONE); cleanupButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); cleanupButton.setText("Cleanup Agent..."); cleanupButton.setEnabled(false); cleanupButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Agent agent = getAgent(selectedElement); if (agent != null) { cleanup(agent); treeViewer.refresh(); } } }); analyzeButton = new Button(buttonComposite, SWT.NONE); analyzeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); analyzeButton.setText("Analyze Agent..."); analyzeButton.setEnabled(false); analyzeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Agent agent = getAgent(selectedElement); if (agent != null) { analyze(agent); treeViewer.refresh(); } } }); newPoolButton = new Button(buttonComposite, SWT.NONE); newPoolButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); newPoolButton.setText("New Bundle Pool..."); newPoolButton.setEnabled(false); newPoolButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Agent selectedAgent = (Agent) selectedElement; String path = openDirectoryDialog("Select the location of the new pool.", selectedAgent.getLocation().getAbsolutePath()); if (path != null) { BundlePool bundlePool = selectedAgent.addBundlePool(new File(path)); refreshFor(bundlePool); } } }); deleteButton = new Button(buttonComposite, SWT.NONE); deleteButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); deleteButton.setText("Delete..."); deleteButton.setEnabled(false); deleteButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { deletePressed(); } }); refreshButton = new Button(buttonComposite, SWT.NONE); refreshButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); refreshButton.setText("Refresh"); refreshButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { try { ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell()); dialog.run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { P2Util.getAgentManager().refreshAgents(monitor); } }); } catch (InvocationTargetException ex) { P2UIPlugin.INSTANCE.log(ex); } catch (InterruptedException ex) { //$FALL-THROUGH$ } treeViewer.refresh(); } }); new Label(buttonComposite, SWT.NONE); showProfilesButton = new Button(buttonComposite, SWT.CHECK); showProfilesButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); showProfilesButton.setText("Show Profiles"); showProfilesButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { boolean showProfiles = showProfilesButton.getSelection(); PREF_SHOW_PROFILES.set(showProfiles); profileDetailsButton.setVisible(showProfiles); contentProvider.setShowProfiles(showProfiles); treeViewer.refresh(); if (selectedElement instanceof BundlePool) { treeViewer.setExpandedState(selectedElement, true); } profilesShown(showProfiles); } }); profileDetailsButton = new Button(buttonComposite, SWT.NONE); profileDetailsButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); profileDetailsButton.setText("Details..."); profileDetailsButton.setVisible(false); profileDetailsButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { showProfileDetails(); } }); if (PREF_SHOW_PROFILES.get(false)) { showProfilesButton.setSelection(true); profileDetailsButton.setVisible(true); contentProvider.setShowProfiles(true); profilesShown(true); } UIUtil.asyncExec(new Runnable() { public void run() { final AgentManager agentManager = P2Util.getAgentManager(); BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { public void run() { treeViewer.setInput(agentManager); treeViewer.expandAll(); } }); if (selection == null) { Collection<Agent> agents = agentManager.getAgents(); if (!agents.isEmpty()) { treeViewer.setSelection(new StructuredSelection(agents.iterator().next())); } } else { treeViewer.setSelection(new StructuredSelection(selection)); } } }); } @Override public boolean setFocus() { return treeViewer.getTree().setFocus(); } public Object getSelectedElement() { return selectedElement; } @Override public void setEnabled(boolean enabled) { treeViewer.getTree().setEnabled(enabled); refreshButton.setEnabled(enabled); newAgentButton.setEnabled(enabled); showProfilesButton.setEnabled(enabled); elementChanged(selectedElement); super.setEnabled(enabled); } private void deletePressed() { AgentManagerElementImpl agentManagerElement = (AgentManagerElementImpl) selectedElement; String type = agentManagerElement.getElementType(); String message = "Are you sure to delete " + type + " " + agentManagerElement + "?"; if (!(agentManagerElement instanceof Profile)) { message += "\n\nThe physical " + type + " files will remain on disk even if you answer Yes."; } if (MessageDialog.openQuestion(getShell(), AgentManagerDialog.TITLE, message)) { try { Object newSelection = null; IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); Object element = selection.getFirstElement(); if (element != null) { ITreeContentProvider contentProvider = (ITreeContentProvider) treeViewer.getContentProvider(); Object parent = contentProvider.getParent(element); if (parent != null) { newSelection = parent; Object[] elements = contentProvider.getChildren(parent); treeViewer.getComparator().sort(treeViewer, elements); List<Object> children = Arrays.asList(elements); int index = children.indexOf(element); if (index != -1) { if (index + 1 < children.size()) { newSelection = children.get(index + 1); } else if (index > 0) { newSelection = children.get(index - 1); } } } } agentManagerElement.delete(); treeViewer.refresh(); if (newSelection != null) { treeViewer.setSelection(new StructuredSelection(newSelection)); } } catch (Exception ex) { P2UIPlugin.INSTANCE.log(ex); } } } private void cleanup(final Agent agent) { final String title = "Cleanup"; final AgentAnalyzer[] analyzer = { null }; try { ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell()); dialog.run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { SubMonitor progress = SubMonitor.convert(monitor, "Analyzing...", 100).detectCancelation(); analyzer[0] = new AgentAnalyzer(agent, false, null, progress.newChild(90)); analyzer[0].awaitAnalyzing(progress.newChild(10)); } }); } catch (Exception ex) { ErrorDialog.open(ex); return; } final Map<AnalyzedProfile, AnalyzedProfile> unusedProfiles = new IdentityHashMap<AnalyzedProfile, AnalyzedProfile>(); final Map<AnalyzedArtifact, AnalyzedArtifact> unusedArtifacts = new IdentityHashMap<AnalyzedArtifact, AnalyzedArtifact>(); for (AnalyzedBundlePool bundlePool : analyzer[0].getBundlePools().values()) { for (AnalyzedProfile profile : bundlePool.getUnusedProfiles()) { unusedProfiles.put(profile, profile); } for (AnalyzedArtifact artifact : bundlePool.getArtifacts()) { if (isUnused(artifact, unusedProfiles)) { unusedArtifacts.put(artifact, artifact); } } } if (unusedProfiles.isEmpty() && unusedArtifacts.isEmpty()) { MessageDialog.openInformation(getShell(), title, "Nothing to clean up."); return; } final boolean showProfiles = showProfilesButton.getSelection(); final int profiles = unusedProfiles.size(); final int artifacts = unusedArtifacts.size(); String message = "Do you want to delete "; if (profiles != 0) { message += profiles + " unused profile" + (profiles == 1 ? "" : "s"); } if (artifacts != 0) { if (profiles != 0) { message += " and "; } message += artifacts + " unused artifact" + (artifacts == 1 ? "" : "s"); } message += "?"; if (artifacts != 0) { message += "\n\n" + "Note: Unused artifacts can always safely be deleted. " + "They will be deleted physically from your disk and logically from your bundle pool."; } if (MessageDialog.openQuestion(getShell(), title, message)) { try { UIUtil.runInProgressDialog(getShell(), new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { SubMonitor progress = SubMonitor.convert(monitor, "Deleting...", profiles + artifacts) .detectCancelation(); if (profiles != 0) { progress.setTaskName("Deleting unused profiles..."); for (AnalyzedProfile profile : unusedProfiles.keySet()) { profile.delete(progress.newChild()); if (showProfiles) { UIUtil.syncExec(new Runnable() { public void run() { treeViewer.refresh(); } }); } } } if (artifacts != 0) { progress.setTaskName("Deleting unused artifacts..."); for (AnalyzedArtifact artifact : unusedArtifacts.keySet()) { artifact.delete(progress.newChild()); } } } }); } catch (InvocationTargetException ex) { ErrorDialog.open(ex); } catch (InterruptedException ex) { // Ignore. } } } private void analyze(Agent agent) { AgentAnalyzerDialog dialog = new AgentAnalyzerDialog(getShell(), agent); dialog.open(); } protected void elementChanged(Object element) { newPoolButton.setEnabled(element instanceof Agent); deleteButton .setEnabled(element instanceof AgentManagerElement && !((AgentManagerElement) element).isUsed()); Agent agent = getAgent(element); cleanupButton.setEnabled(agent != null); analyzeButton.setEnabled(agent != null); profileDetailsButton.setEnabled(element instanceof Profile); } protected void profilesShown(boolean profilesShown) { } private void showProfileDetails() { ProfileDetailsDialog dialog = new ProfileDetailsDialog(getShell(), (Profile) selectedElement); dialog.open(); } private String openDirectoryDialog(String message, String path) { DirectoryDialog dialog = new DirectoryDialog(getShell()); dialog.setText(AgentManagerDialog.TITLE); dialog.setMessage(message); dialog.setFilterPath(path); return dialog.open(); } private void refreshFor(BundlePool bundlePool) { treeViewer.refresh(); treeViewer.setExpandedState(bundlePool.getAgent(), true); treeViewer.setSelection(new StructuredSelection(bundlePool)); treeViewer.getTree().setFocus(); } private static Agent getAgent(Object element) { if (element instanceof Profile) { Profile profile = (Profile) element; return profile.getAgent(); } if (element instanceof BundlePool) { BundlePool bundlePool = (BundlePool) element; return bundlePool.getAgent(); } if (element instanceof Agent) { return (Agent) element; } return null; } private static boolean isUnused(AnalyzedArtifact artifact, Map<AnalyzedProfile, AnalyzedProfile> unusedProfiles) { for (AnalyzedProfile profile : artifact.getProfiles()) { if (!unusedProfiles.containsKey(profile)) { return false; } } return true; } }