1/*
2 * Copyright (c) 2000, 2015, 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.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.print;
27
28import java.util.Vector;
29
30import javax.print.PrintService;
31import javax.print.attribute.PrintServiceAttributeSet;
32import javax.print.attribute.HashPrintServiceAttributeSet;
33import javax.print.event.PrintServiceAttributeEvent;
34import javax.print.event.PrintServiceAttributeListener;
35
36/*
37 * A utility class usable by all print services for managing listeners
38 * The services create an instance and delegate the listener callback
39 * management to this class. The ServiceNotifier calls back to the service
40 * to obtain the state of the attributes and notifies the listeners of
41 * any changes.
42 */
43class ServiceNotifier extends Thread {
44
45    private PrintService service;
46    private Vector<PrintServiceAttributeListener> listeners;
47    private boolean stop = false;
48    private PrintServiceAttributeSet lastSet;
49
50    /*
51     * If adding any other constructors, always call the 5-args
52     * super-class constructor passing "false" for inherit-locals.
53     */
54    ServiceNotifier(PrintService service) {
55        super(null, null, service.getName() + " notifier", 0, false);
56        this.service = service;
57        listeners = new Vector<>();
58        try {
59              setPriority(Thread.NORM_PRIORITY-1);
60              setDaemon(true);
61              start();
62        } catch (SecurityException e) {
63        }
64    }
65
66    void addListener(PrintServiceAttributeListener listener) {
67        synchronized (this) {
68            if (listener == null || listeners == null) {
69                return;
70            }
71            listeners.add(listener);
72        }
73    }
74
75   void removeListener(PrintServiceAttributeListener listener) {
76         synchronized (this) {
77            if (listener == null || listeners == null) {
78                return;
79            }
80            listeners.remove(listener);
81        }
82    }
83
84   boolean isEmpty() {
85     return (listeners == null || listeners.isEmpty());
86   }
87
88   void stopNotifier() {
89      stop = true;
90   }
91
92    /* If a service submits a job it may call this method which may prompt
93     * immediate notification of listeners.
94     */
95    void wake() {
96        try {
97            interrupt();
98        } catch (SecurityException e) {
99        }
100    }
101
102   /* A heuristic is used to calculate sleep time.
103     * 10 times the time taken to loop through all the listeners, with
104     * a minimum of 15 seconds. Ensures this won't take more than 10%
105     * of available time.
106     */
107    public void run() {
108
109       long minSleepTime = 15000;
110       long sleepTime = 2000;
111       HashPrintServiceAttributeSet attrs;
112       PrintServiceAttributeEvent attrEvent;
113       PrintServiceAttributeListener listener;
114       PrintServiceAttributeSet psa;
115
116       while (!stop) {
117           try {
118                Thread.sleep(sleepTime);
119           } catch (InterruptedException e) {
120           }
121           synchronized (this) {
122               if (listeners == null) {
123                   continue;
124               }
125               long startTime = System.currentTimeMillis();
126               if (listeners != null) {
127                    if (service instanceof AttributeUpdater) {
128                       psa =
129                          ((AttributeUpdater)service).getUpdatedAttributes();
130                    } else {
131                       psa = service.getAttributes();
132                    }
133                    if (psa != null && !psa.isEmpty()) {
134                        for (int i = 0; i < listeners.size() ; i++) {
135                            listener = listeners.elementAt(i);
136                            attrs =
137                                new HashPrintServiceAttributeSet(psa);
138                            attrEvent =
139                                new PrintServiceAttributeEvent(service, attrs);
140                            listener.attributeUpdate(attrEvent);
141                        }
142                    }
143               }
144               sleepTime = (System.currentTimeMillis()-startTime)*10;
145               if (sleepTime < minSleepTime) {
146                   sleepTime = minSleepTime;
147               }
148           }
149       }
150    }
151
152}
153