All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.extexecution.InputOutputManager Maven / Gradle / Ivy

The newest version!
/*
 * 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.extexecution;

import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Action;
import org.netbeans.spi.extexecution.open.OptionOpenHandler;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.windows.IOProvider;
import org.openide.windows.InputOutput;

public final class InputOutputManager {

    private static final Logger LOGGER = Logger.getLogger(InputOutputManager.class.getName());

    /**
     * All tabs which were used for some process which has now ended.
     * These are closed when you start a fresh process.
     * Map from tab to tab display name.
     * @see "#43001"
     */
    private static final Map AVAILABLE =
            new WeakHashMap();

    private static final Set ACTIVE_DISPLAY_NAMES = new HashSet();

    private InputOutputManager() {
        super();
    }

    public static void addInputOutput(InputOutputData data) {
        synchronized (InputOutputManager.class) {
            AVAILABLE.put(data.inputOutput, data);
            ACTIVE_DISPLAY_NAMES.remove(data.displayName);
        }
    }

    /**
     * Tries to find free Output Window tab for the given name.
     *
     * @param name the name of the free tab. Other free tabs are ignored.
     * @return free tab and its current display name or null
     */
    public static InputOutputData getInputOutput(String name, boolean actions, String optionsPath) {
        InputOutputData result = null;

        TreeSet candidates = new TreeSet(InputOutputData.DISPLAY_NAME_COMPARATOR);

        synchronized (InputOutputManager.class) {
            for (Iterator> it = AVAILABLE.entrySet().iterator(); it.hasNext();) {
                Entry entry = it.next();

                final InputOutput free = entry.getKey();
                final InputOutputData data = entry.getValue();

                if (free.isClosed()) {
                    it.remove();
                    continue;
                }

                if (isAppropriateName(name, data.displayName)) {
                    if ((actions && data.rerunAction != null && data.stopAction != null)
                            || !actions && data.rerunAction == null && data.stopAction == null) {
                        if (optionsPath != null && data.optionsAction != null && data.optionsAction.getOptionsPath().equals(optionsPath)
                                || optionsPath == null && data.optionsAction == null) {
                            // Reuse it.
                            candidates.add(data);
                        }
                    } // continue to remove all closed tabs
                }

                LOGGER.log(Level.FINEST, "InputOutputManager pool: {0}", data.getDisplayName());
            }

            if (!candidates.isEmpty()) {
                result = candidates.first();
                AVAILABLE.remove(result.inputOutput);
                ACTIVE_DISPLAY_NAMES.add(result.displayName);
            }
        }
        return result;
    }

    public static InputOutputData getInputOutput(InputOutput inputOutput) {
        InputOutputData result = null;

        synchronized (InputOutputManager.class) {
            for (Iterator> it = AVAILABLE.entrySet().iterator(); it.hasNext();) {
                Entry entry = it.next();

                final InputOutput free = entry.getKey();
                final InputOutputData data = entry.getValue();

                if (free.isClosed()) {
                    it.remove();
                    continue;
                }

                if (free.equals(inputOutput)) {
                    result = data;
                    ACTIVE_DISPLAY_NAMES.add(result.displayName);
                    it.remove();
                }
                LOGGER.log(Level.FINEST, "InputOutputManager pool: {0}", data.getDisplayName());
            }
        }
        return result;
    }

    public static InputOutputData createInputOutput(String originalDisplayName,
            boolean controlActions, String optionsPath) {

        synchronized (InputOutputManager.class) {
            String displayName = getNonActiveDisplayName(originalDisplayName);

            InputOutput io;
            StopAction stopAction = null;
            RerunAction rerunAction = null;
            OptionsAction optionsAction = null;

            if (controlActions) {
                stopAction = new StopAction();
                rerunAction = new RerunAction();
                if (optionsPath != null) {
                    OptionOpenHandler handler = Lookup.getDefault().lookup(OptionOpenHandler.class);
                    if (handler != null) {
                        optionsAction = new OptionsAction(handler, optionsPath);
                        io = IOProvider.getDefault().getIO(displayName,
                                new Action[] {rerunAction, stopAction, optionsAction});
                    } else {
                        LOGGER.log(Level.WARNING, "No available OptionsOpenHandler so no Options button");
                        io = IOProvider.getDefault().getIO(displayName,
                            new Action[] {rerunAction, stopAction});
                    }
                } else {
                    io = IOProvider.getDefault().getIO(displayName,
                            new Action[] {rerunAction, stopAction});
                }
                rerunAction.setParent(io);
            } else {
                if (optionsPath != null) {
                    OptionOpenHandler handler = Lookup.getDefault().lookup(OptionOpenHandler.class);
                    if (handler != null) {
                        optionsAction = new OptionsAction(handler, optionsPath);
                        io = IOProvider.getDefault().getIO(displayName,
                                new Action[] {optionsAction});
                    } else {
                        LOGGER.log(Level.WARNING, "No available OptionsOpenHandler so no Options button");
                        io = IOProvider.getDefault().getIO(displayName, true);
                    }
                } else {
                    io = IOProvider.getDefault().getIO(displayName, true);
                }
            }

            ACTIVE_DISPLAY_NAMES.add(displayName);
            return new InputOutputData(io, displayName, stopAction, rerunAction, optionsAction);
        }
    }

    // unit test only
    public static void clear() {
        synchronized (InputOutputManager.class) {
            AVAILABLE.clear();
            ACTIVE_DISPLAY_NAMES.clear();
        }
    }

    private static boolean isAppropriateName(String base, String toMatch) {
        if (!toMatch.startsWith(base)) {
            return false;
        }
        return toMatch.substring(base.length()).matches("^(\\ #[0-9]+)?$"); // NOI18N
    }

    private static String getNonActiveDisplayName(String displayNameBase) {
        String nonActiveDN = displayNameBase;
        if (ACTIVE_DISPLAY_NAMES.contains(nonActiveDN)) {
            // Uniquify: "prj (targ) #2", "prj (targ) #3", etc.
            int i = 2;
            String testdn;

            do {
                testdn = NbBundle.getMessage(InputOutputManager.class, "Uniquified", nonActiveDN, i++);
            } while (ACTIVE_DISPLAY_NAMES.contains(testdn));

            nonActiveDN = testdn;
        }
        assert !ACTIVE_DISPLAY_NAMES.contains(nonActiveDN);
        return nonActiveDN;
    }

    public static final class InputOutputData {

        private static final Comparator DISPLAY_NAME_COMPARATOR = new Comparator() {

            @Override
            public int compare(InputOutputData o1, InputOutputData o2) {
                return o1.displayName.compareTo(o2.displayName);
            }
        };

        private final InputOutput inputOutput;

        private final String displayName;

        private final StopAction stopAction;

        private final RerunAction rerunAction;

        private final OptionsAction optionsAction;

        public InputOutputData(InputOutput inputOutput, String displayName,
                StopAction stopAction, RerunAction rerunAction, OptionsAction optionsAction) {
            this.displayName = displayName;
            this.stopAction = stopAction;
            this.rerunAction = rerunAction;
            this.inputOutput = inputOutput;
            this.optionsAction = optionsAction;
        }

        public InputOutput getInputOutput() {
            return inputOutput;
        }

        public String getDisplayName() {
            return displayName;
        }

        public RerunAction getRerunAction() {
            return rerunAction;
        }

        public StopAction getStopAction() {
            return stopAction;
        }

        public OptionsAction getOptionsAction() {
            return optionsAction;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy