001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.apache.tools.ant.module.run;
043:
044: import java.awt.EventQueue;
045: import java.util.HashMap;
046: import java.util.Map;
047: import java.util.WeakHashMap;
048: import javax.swing.JComponent;
049: import javax.swing.JMenuItem;
050: import org.openide.awt.DynamicMenuContent;
051: import org.openide.awt.Mnemonics;
052: import org.openide.util.HelpCtx;
053: import org.openide.util.NbBundle;
054: import org.openide.util.actions.CallableSystemAction;
055: import org.openide.util.actions.SystemAction;
056:
057: /**
058: * Action which stops the currently running Ant process.
059: * If there is more than one, a dialog appears asking you to select one.
060: * @author Jesse Glick
061: * @see "issue #43143"
062: */
063: public final class StopBuildingAction extends CallableSystemAction {
064:
065: /**
066: * Map from active processing threads to their process display names.
067: */
068: private static final Map<Thread, String> activeProcesses = new WeakHashMap<Thread, String>();
069:
070: static void registerProcess(Thread t, String displayName) {
071: synchronized (activeProcesses) {
072: assert !activeProcesses.containsKey(t);
073: activeProcesses.put(t, displayName);
074: }
075: EventQueue.invokeLater(new Runnable() {
076: public void run() {
077: SystemAction.get(StopBuildingAction.class).setEnabled(
078: true);
079: }
080: });
081: }
082:
083: static void unregisterProcess(Thread t) {
084: final boolean enable;
085: synchronized (activeProcesses) {
086: assert activeProcesses.containsKey(t);
087: activeProcesses.remove(t);
088: enable = !activeProcesses.isEmpty();
089: }
090: EventQueue.invokeLater(new Runnable() {
091: public void run() {
092: SystemAction.get(StopBuildingAction.class).setEnabled(
093: enable);
094: }
095: });
096: }
097:
098: @Override
099: public void performAction() {
100: Thread[] toStop = null;
101: synchronized (activeProcesses) {
102: assert !activeProcesses.isEmpty();
103: if (activeProcesses.size() == 1) {
104: toStop = activeProcesses.keySet()
105: .toArray(new Thread[1]);
106: }
107: }
108: if (toStop == null) {
109: // More than one, need to select one.
110: Map<Thread, String> activeProcessesClone;
111: synchronized (activeProcesses) {
112: activeProcessesClone = new HashMap<Thread, String>(
113: activeProcesses);
114: }
115: toStop = StopBuildingAlert
116: .selectProcessToKill(activeProcessesClone);
117: synchronized (activeProcesses) {
118: for (int i = 0; i < toStop.length; i++) {
119: if (!activeProcesses.containsKey(toStop[i])) {
120: // Oops, process ended while it was being selected... just ignore.
121: toStop[i] = null;
122: }
123: }
124: }
125: }
126: for (Thread t : toStop) {
127: if (t != null) {
128: TargetExecutor.stopProcess(t);
129: }
130: }
131: }
132:
133: @Override
134: public String getName() {
135: return NbBundle.getMessage(StopBuildingAction.class,
136: "LBL_stop_building");
137: }
138:
139: @Override
140: public HelpCtx getHelpCtx() {
141: return null;
142: }
143:
144: @Override
145: protected void initialize() {
146: super .initialize();
147: setEnabled(false); // no processes initially
148: }
149:
150: @Override
151: protected boolean asynchronous() {
152: return false;
153: }
154:
155: @Override
156: public JMenuItem getMenuPresenter() {
157: class SpecialMenuItem extends JMenuItem implements
158: DynamicMenuContent {
159: public SpecialMenuItem() {
160: super (StopBuildingAction.this );
161: }
162:
163: public JComponent[] getMenuPresenters() {
164: String label;
165: synchronized (activeProcesses) {
166: switch (activeProcesses.size()) {
167: case 0:
168: label = NbBundle.getMessage(
169: StopBuildingAction.class,
170: "LBL_stop_building");
171: break;
172: case 1:
173: label = NbBundle.getMessage(
174: StopBuildingAction.class,
175: "LBL_stop_building_one",
176: activeProcesses.values().iterator()
177: .next());
178: break;
179: default:
180: label = NbBundle.getMessage(
181: StopBuildingAction.class,
182: "LBL_stop_building_many");
183: }
184: }
185: Mnemonics.setLocalizedText(this , label);
186: return new JComponent[] { this };
187: }
188:
189: public JComponent[] synchMenuPresenters(JComponent[] items) {
190: return getMenuPresenters();
191: }
192: }
193: return new SpecialMenuItem();
194: }
195:
196: }
|