1/*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.netbeans.jemmy.util;
24
25import java.awt.Component;
26import java.awt.Dialog;
27import java.awt.Window;
28import java.util.Vector;
29
30import org.netbeans.jemmy.JemmyProperties;
31import org.netbeans.jemmy.Outputable;
32import org.netbeans.jemmy.TestOut;
33import org.netbeans.jemmy.Timeoutable;
34import org.netbeans.jemmy.Timeouts;
35import org.netbeans.jemmy.WindowWaiter;
36import org.netbeans.jemmy.operators.WindowOperator;
37
38/**
39 * Class allows to make periodical window jobs like error window closing.
40 *
41 * @see WindowJob
42 * @author Alexandre Iline (alexandre.iline@oracle.com)
43 */
44public class WindowManager implements Timeoutable, Outputable {
45
46    /**
47     * Default value for WindowManager.TimeDelta timeout.
48     */
49    private static long TIME_DELTA = 1000;
50
51    private static WindowManager manager;
52
53    private Vector<JobThread> jobs;
54    private Timeouts timeouts;
55    private TestOut output;
56
57    private WindowManager() {
58        super();
59        setTimeouts(JemmyProperties.getCurrentTimeouts());
60        setOutput(JemmyProperties.getCurrentOutput());
61        jobs = new Vector<>();
62    }
63
64    /**
65     * Adds job to list.
66     *
67     * @param job a job to perform.
68     */
69    public static void addJob(WindowJob<?, Window> job) {
70        manager.add(job);
71    }
72
73    /**
74     * Removes job from list.
75     *
76     * @param job a job to remove.
77     */
78    public static void removeJob(WindowJob<?, ?> job) {
79        manager.remove(job);
80    }
81
82    public static void performJob(WindowJob<?, Window> job) {
83        while (manager.performJobOnce(job)) {
84        }
85    }
86
87    static {
88        Timeouts.initDefault("WindowManager.TimeDelta", TIME_DELTA);
89        manager = new WindowManager();
90    }
91
92    @Override
93    public void setTimeouts(Timeouts timeouts) {
94        this.timeouts = timeouts;
95    }
96
97    @Override
98    public Timeouts getTimeouts() {
99        return timeouts;
100    }
101
102    @Override
103    public void setOutput(TestOut output) {
104        this.output = output;
105    }
106
107    @Override
108    public TestOut getOutput() {
109        return output;
110    }
111
112    /**
113     * Adds job to list.
114     *
115     * @param job a job to perform.
116     */
117    public void add(WindowJob<?, Window> job) {
118        output.printLine("Starting job \""
119                + job.getDescription()
120                + "\"");
121        synchronized (jobs) {
122            JobThread thread = new JobThread(job);
123            jobs.add(thread);
124            thread.start();
125        }
126    }
127
128    /**
129     * Removes job from list.
130     *
131     * @param job a job to remove.
132     */
133    public void remove(WindowJob<?, ?> job) {
134        output.printLine("Killing job \""
135                + job.getDescription()
136                + "\"");
137        synchronized (jobs) {
138            for (int i = 0; i < jobs.size(); i++) {
139                if (jobs.get(i).job == job) {
140                    jobs.get(i).needStop = true;
141                    jobs.remove(i);
142                    break;
143                }
144            }
145        }
146    }
147
148    private boolean performJobOnce(WindowJob<?, Window> job) {
149        Window win = WindowWaiter.getWindow(job);
150        if (win != null) {
151            job.launch(win);
152            return true;
153        } else {
154            return false;
155        }
156    }
157
158    public static class ModalDialogChoosingJob implements WindowJob<Void, Window> {
159
160        @Override
161        public boolean checkComponent(Component comp) {
162            return (comp instanceof Dialog
163                    && ((Dialog) comp).isModal());
164        }
165
166        @Override
167        public Void launch(Window obj) {
168            new WindowOperator(obj).requestCloseAndThenHide();
169            return null;
170        }
171
172        @Override
173        public String getDescription() {
174            return "A job of closing modal dialogs";
175        }
176
177        @Override
178        public String toString() {
179            return "ModalDialogChoosingJob{description = " + getDescription() + '}';
180        }
181    }
182
183    private static class JobThread extends Thread {
184
185        WindowJob<?, Window> job;
186        volatile boolean needStop = false;
187
188        public JobThread(WindowJob<?, Window> job) {
189            this.job = job;
190        }
191
192        private boolean getNS() {
193            return needStop;
194        }
195
196        @Override
197        public void run() {
198            while (!getNS()) {
199                manager.performJobOnce(job);
200                manager.timeouts.sleep("WindowManager.TimeDelta");
201            }
202        }
203    }
204
205}
206