Skip to content

Commit

Permalink
Bring forward improvements made on 2.1 branch (qzind#936)
Browse files Browse the repository at this point in the history
* bring forward improvements made on 2.1 branch:
- printer search
- idle action controls
- jetty upgrade
- log4j upgrade

Co-authored-by: Tres Finocchiaro <[email protected]>
  • Loading branch information
Brett Berenz and tresf authored Mar 23, 2022
1 parent eb57b8c commit 5a1a372
Show file tree
Hide file tree
Showing 37 changed files with 189 additions and 78 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed lib/websocket/jetty-client-9.4.21.v20190926.jar
Binary file not shown.
Binary file added lib/websocket/jetty-client-9.4.45.v20220203.jar
Binary file not shown.
Binary file removed lib/websocket/jetty-http-9.4.21.v20190926.jar
Binary file not shown.
Binary file added lib/websocket/jetty-http-9.4.45.v20220203.jar
Binary file not shown.
Binary file removed lib/websocket/jetty-io-9.4.21.v20190926.jar
Binary file not shown.
Binary file added lib/websocket/jetty-io-9.4.45.v20220203.jar
Binary file not shown.
Binary file removed lib/websocket/jetty-security-9.4.21.v20190926.jar
Binary file not shown.
Binary file not shown.
Binary file removed lib/websocket/jetty-server-9.4.21.v20190926.jar
Binary file not shown.
Binary file added lib/websocket/jetty-server-9.4.45.v20220203.jar
Binary file not shown.
Binary file removed lib/websocket/jetty-servlet-9.4.21.v20190926.jar
Binary file not shown.
Binary file added lib/websocket/jetty-servlet-9.4.45.v20220203.jar
Binary file not shown.
Binary file removed lib/websocket/jetty-util-9.4.21.v20190926.jar
Binary file not shown.
Binary file added lib/websocket/jetty-util-9.4.45.v20220203.jar
Binary file not shown.
Binary file not shown.
Binary file removed lib/websocket/websocket-client-9.4.21.v20190926.jar
Binary file not shown.
Binary file not shown.
Binary file removed lib/websocket/websocket-common-9.4.21.v20190926.jar
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions src/qz/common/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public class Constants {
public static final String PREFS_HEADLESS = "tray.headless";
public static final String PREFS_MONOCLE = "tray.monocle";
public static final String PREFS_STRICT_MODE = "tray.strictmode";
public static final String PREFS_IDLE_PRINTERS = "tray.idle.printers";
public static final String PREFS_IDLE_JFX = "tray.idle.javafx";

public static final String ALLOW_SITES_TEXT = "Permanently allowed \"%s\" to access local resources";
public static final String BLOCK_SITES_TEXT = "Permanently blocked \"%s\" from accessing local resources";
Expand Down
86 changes: 50 additions & 36 deletions src/qz/common/TrayManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
package qz.common;

import com.github.zafarkhaja.semver.Version;
import org.eclipse.jetty.server.Server;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jetty.server.Server;
import qz.App;
import qz.auth.Certificate;
import qz.auth.RequestState;
import qz.installer.shortcut.ShortcutCreator;
Expand All @@ -34,6 +35,7 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

/**
Expand Down Expand Up @@ -76,7 +78,7 @@ public class TrayManager {
private Thread reloadThread;

// Actions to run if idle after startup
private ArrayList<Timer> idleTimers;
private java.util.Timer idleTimer = new java.util.Timer();

public TrayManager() {
this(false);
Expand All @@ -91,10 +93,10 @@ public TrayManager(boolean isHeadless) {
prefs = new PropertyHelper(FileUtilities.USER_DIR + File.separator + Constants.PREFS_FILE + ".properties");

// Set strict certificate mode preference
Certificate.setTrustBuiltIn(!prefs.getBoolean(Constants.PREFS_STRICT_MODE, false));
Certificate.setTrustBuiltIn(!getPref(Constants.PREFS_STRICT_MODE, false));

//headless if turned on by user or unsupported by environment
headless = isHeadless || prefs.getBoolean(Constants.PREFS_HEADLESS, false) || GraphicsEnvironment.isHeadless();
headless = isHeadless || getPref(Constants.PREFS_HEADLESS, false) || GraphicsEnvironment.isHeadless();
if (headless) {
log.info("Running in headless mode");
}
Expand Down Expand Up @@ -198,23 +200,26 @@ public TrayManager(boolean isHeadless) {
}

// Initialize idle actions
idleTimers = new ArrayList<>();

// Slow to find printers the first time if a lot of printers are installed
performIfIdle((int)TimeUnit.SECONDS.toMillis(10), evt -> {
log.debug("IDLE: Performing first run of find printers");
PrintServiceMatcher.getNativePrinterList(false, true);
});
// Slow to start JavaFX the first time
performIfIdle((int)TimeUnit.SECONDS.toMillis(60), evt -> {
log.debug("IDLE: Starting up JFX for HTML printing");
try {
WebApp.initialize();
}
catch(IOException e) {
log.error("Idle runner failed to preemptively start JavaFX service");
}
});
if (getPref(Constants.PREFS_IDLE_JFX, true)) {
performIfIdle((int)TimeUnit.SECONDS.toMillis(60), evt -> {
log.debug("IDLE: Starting up JFX for HTML printing");
try {
WebApp.initialize();
}
catch(IOException e) {
log.error("Idle runner failed to preemptively start JavaFX service");
}
});
}
// Slow to find printers the first time if a lot of printers are installed
// Must run after JavaFX per https://github.com/qzind/tray/issues/924
if (getPref(Constants.PREFS_IDLE_PRINTERS, true)) {
performIfIdle((int)TimeUnit.SECONDS.toMillis(120), evt -> {
log.debug("IDLE: Performing first run of find printers");
PrintServiceMatcher.getNativePrinterList(false, true);
});
}
}

/**
Expand Down Expand Up @@ -268,14 +273,14 @@ private void addMenuItems() {
JCheckBoxMenuItem notificationsItem = new JCheckBoxMenuItem("Show all notifications");
notificationsItem.setToolTipText("Shows all connect/disconnect messages, useful for debugging purposes");
notificationsItem.setMnemonic(KeyEvent.VK_S);
notificationsItem.setState(prefs.getBoolean(Constants.PREFS_NOTIFICATIONS, false));
notificationsItem.setState(getPref(Constants.PREFS_NOTIFICATIONS, false));
notificationsItem.addActionListener(notificationsListener);
diagnosticMenu.add(notificationsItem);

JCheckBoxMenuItem monocleItem = new JCheckBoxMenuItem("Use Monocle for HTML");
monocleItem.setToolTipText("Use monocle platform for HTML printing (restart required)");
monocleItem.setMnemonic(KeyEvent.VK_U);
monocleItem.setState(prefs.getBoolean(Constants.PREFS_MONOCLE, true));
monocleItem.setState(getPref(Constants.PREFS_MONOCLE, true));
if(!SystemUtilities.hasMonocle()) {
log.warn("Monocle engine was not detected");
monocleItem.setEnabled(false);
Expand Down Expand Up @@ -458,7 +463,7 @@ public void actionPerformed(ActionEvent e) {

private final ActionListener exitListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean showAllNotifications = prefs.getBoolean(Constants.PREFS_NOTIFICATIONS, false);
boolean showAllNotifications = getPref(Constants.PREFS_NOTIFICATIONS, false);
if (!showAllNotifications || confirmDialog.prompt("Exit " + name + "?")) { exit(0); }
}
};
Expand Down Expand Up @@ -607,7 +612,7 @@ private void displayMessage(final String caption, final String text, final TrayI
if (!headless) {
if (tray != null) {
SwingUtilities.invokeLater(() -> {
boolean showAllNotifications = prefs.getBoolean(Constants.PREFS_NOTIFICATIONS, false);
boolean showAllNotifications = getPref(Constants.PREFS_NOTIFICATIONS, false);
if (showAllNotifications || level != TrayIcon.MessageType.INFO) {
tray.displayMessage(caption, text, level);
}
Expand All @@ -627,29 +632,38 @@ public void singleInstanceCheck(java.util.List<Integer> insecurePorts, Integer i
}

public boolean isMonoclePreferred() {
return prefs.getBoolean(Constants.PREFS_MONOCLE, true);
return getPref(Constants.PREFS_MONOCLE, true);
}

public boolean isHeadless() {
return headless;
}

private void performIfIdle(int idleQualifier, ActionListener performer) {
Timer timer = new Timer(idleQualifier, evt -> {
performer.actionPerformed(evt);
idleTimers.remove(evt.getSource());
});
timer.setRepeats(false);
timer.start();
/**
* Get boolean user pref: Searching "user", "app" and <code>System.getProperty(...)</code>.
*/
private boolean getPref(String name, boolean defaultVal) {
return "true".equalsIgnoreCase(PrefsSearch.get(prefs, App.getTrayProperties(), name, defaultVal + ""));
}

idleTimers.add(timer);
private void performIfIdle(int idleQualifier, ActionListener performer) {
if (idleTimer != null) {
idleTimer.schedule(new TimerTask() {
@Override
public void run() {
performer.actionPerformed(null);
}
}, idleQualifier);
} else {
log.warn("Idle actions have already been cleared due to activity, task not scheduled.");
}
}

public void voidIdleActions() {
if (idleTimers.size() > 0) {
if (idleTimer != null) {
log.trace("Not idle, stopping any actions that haven't ran yet");
idleTimers.forEach(Timer::stop);
idleTimers.clear();
idleTimer.cancel();
idleTimer = null;
}
}

Expand Down
56 changes: 41 additions & 15 deletions src/qz/printer/PrintServiceMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

package qz.printer;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import qz.printer.info.NativePrinter;
import qz.printer.info.NativePrinterMap;
import qz.utils.SystemUtilities;
Expand All @@ -34,8 +34,8 @@ public class PrintServiceMatcher {
public static NativePrinterMap getNativePrinterList(boolean silent, boolean withAttributes) {
NativePrinterMap printers = NativePrinterMap.getInstance();
printers.putAll(PrintServiceLookup.lookupPrintServices(null, null));
if(!silent) log.debug("Found {} printers", printers.size());
if(withAttributes) printers.values().forEach(NativePrinter::getDriverAttributes);
if (withAttributes) { printers.values().forEach(NativePrinter::getDriverAttributes); }
if (!silent) { log.debug("Found {} printers", printers.size()); }
return printers;
}

Expand All @@ -47,6 +47,17 @@ public static NativePrinterMap getNativePrinterList() {
return getNativePrinterList(false);
}

public static NativePrinter getDefaultPrinter() {
PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();

NativePrinterMap printers = NativePrinterMap.getInstance();
if (!printers.contains(defaultService)) {
printers.putAll(defaultService);
}

return printers.get(defaultService.getName());
}

public static String findPrinterName(String query) throws JSONException {
NativePrinter printer = PrintServiceMatcher.matchPrinter(query);

Expand All @@ -67,7 +78,13 @@ public static NativePrinter matchPrinter(String printerSearch, boolean silent) {
NativePrinter begins = null;
NativePrinter partial = null;

if(!silent) log.debug("Searching for PrintService matching {}", printerSearch);
if (!silent) { log.debug("Searching for PrintService matching {}", printerSearch); }

NativePrinter defaultPrinter = getDefaultPrinter();
if (printerSearch.equals(defaultPrinter.getName())) {
if (!silent) { log.debug("Matched default printer, skipping further search"); }
return defaultPrinter;
}

printerSearch = printerSearch.toLowerCase(Locale.ENGLISH);

Expand Down Expand Up @@ -132,26 +149,35 @@ public static NativePrinter matchPrinter(String printerSearch) {
return matchPrinter(printerSearch, false);
}

public static JSONArray getPrintersJSON() throws JSONException {
public static JSONArray getPrintersJSON(boolean includeDetails) throws JSONException {
JSONArray list = new JSONArray();

PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();

boolean mediaTrayCrawled = false;

for(NativePrinter printer : getNativePrinterList().values()) {
PrintService ps = printer.getPrintService().value();
JSONObject jsonService = new JSONObject();
jsonService.put("name", ps.getName());
jsonService.put("driver", printer.getDriver().value());
jsonService.put("connection", printer.getConnection());
jsonService.put("default", ps == defaultService);

for(Media m : (Media[])ps.getSupportedAttributeValues(Media.class, null, null)) {
if (m instanceof MediaTray) { jsonService.accumulate("trays", m.toString()); }
}
if (includeDetails) {
jsonService.put("driver", printer.getDriver().value());
jsonService.put("connection", printer.getConnection());
jsonService.put("default", ps == defaultService);

PrinterResolution res = printer.getResolution().value();
int density = -1; if (res != null) { density = res.getFeedResolution(ResolutionSyntax.DPI); }
jsonService.put("density", density);
if (!mediaTrayCrawled) {
log.info("Gathering printer MediaTray information...");
mediaTrayCrawled = true;
}
for(Media m : (Media[])ps.getSupportedAttributeValues(Media.class, null, null)) {
if (m instanceof MediaTray) { jsonService.accumulate("trays", m.toString()); }
}

PrinterResolution res = printer.getResolution().value();
int density = -1; if (res != null) { density = res.getFeedResolution(ResolutionSyntax.DPI); }
jsonService.put("density", density);
}

list.put(jsonService);
}
Expand Down
2 changes: 1 addition & 1 deletion src/qz/printer/action/WebApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import qz.common.Constants;
import qz.utils.LibUtilities;
import qz.utils.SystemUtilities;
import qz.ws.PrintSocketServer;

Expand Down Expand Up @@ -203,6 +202,7 @@ public static synchronized void initialize() throws IOException {
log.trace("Running a test snapshot to size the stage...");
try {
raster(new WebAppModel("<h1>startup</h1>", true, 0, 0, true, 2));
log.trace("JFX initialized successfully");
}
catch(Throwable t) {
throw new IOException(t);
Expand Down
4 changes: 2 additions & 2 deletions src/qz/printer/info/CupsPrinterMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ public class CupsPrinterMap extends NativePrinterMap {
private static final Logger log = LogManager.getLogger(CupsPrinterMap.class);
private Map<NativePrinter, List<PrinterResolution>> resolutionMap = new HashMap<>();

public synchronized NativePrinterMap putAll(PrintService[] services) {
public synchronized NativePrinterMap putAll(PrintService... services) {
ArrayList<PrintService> missing = findMissing(services);
if (missing.isEmpty()) return this;
if (missing.isEmpty()) { return this; }

String output = "\n" + ShellUtilities.executeRaw(new String[] {"lpstat", "-l", "-p"});
String[] devices = output.split("[\\r\\n]printer ");
Expand Down
29 changes: 19 additions & 10 deletions src/qz/printer/info/NativePrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import qz.utils.SystemUtilities;

import javax.print.PrintService;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.PrinterName;
import javax.print.attribute.standard.PrinterResolution;
import java.util.Arrays;
Expand Down Expand Up @@ -144,15 +145,6 @@ public PrinterProperty<PrintService> getPrintService() {
}

public void setPrintService(PrintService printService) {
// Fetch resolution, if available
try {
Object resolution = printService.getDefaultAttributeValue(PrinterResolution.class);
if (resolution != null) {
this.resolution.set((PrinterResolution)resolution);
}
} catch(IllegalArgumentException e) {
log.warn("Unable to obtain PrinterResolution from {}", printService.getName(), e);
}
this.printService.set(printService);
}

Expand All @@ -166,8 +158,18 @@ public void setResolution(PrinterResolution resolution) {

public PrinterProperty<PrinterResolution> getResolution() {
if (!resolution.isSet()) {
getDriverAttributes(this);
// Fetch resolution, if available
try {
Object resolution = printService.value().getDefaultAttributeValue(PrinterResolution.class);
if (resolution != null) {
this.resolution.set((PrinterResolution)resolution);
}
}
catch(IllegalArgumentException e) {
log.warn("Unable to obtain PrinterResolution from {}", printService.value().getName(), e);
}
}

return resolution;
}

Expand All @@ -187,9 +189,16 @@ public List<PrinterResolution> getResolutions() {
}

public static void getDriverAttributes(NativePrinter printer) {
// First, perform slow JDK operations, see issues #940, #932
printer.getPrintService().value().getSupportedAttributeValues(Media.class, null, null); // cached by JDK
printer.getResolution();

// Mark properties as "found" so we don't attempt to gather them again
printer.driver.set();
printer.resolution.set();
printer.connection.set();

// Gather properties not exposed by the JDK
NativePrinterMap.getInstance().fillAttributes(printer);
}

Expand Down
3 changes: 2 additions & 1 deletion src/qz/printer/info/NativePrinterMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public abstract class NativePrinterMap extends ConcurrentHashMap<String, NativeP

private static NativePrinterMap instance;

public abstract NativePrinterMap putAll(PrintService[] services);
public abstract NativePrinterMap putAll(PrintService... services);

abstract void fillAttributes(NativePrinter printer);

public static NativePrinterMap getInstance() {
Expand Down
6 changes: 3 additions & 3 deletions src/qz/printer/info/WindowsPrinterMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
public class WindowsPrinterMap extends NativePrinterMap {
private static final Logger log = LogManager.getLogger(WindowsPrinterMap.class);

public synchronized NativePrinterMap putAll(PrintService[] services) {
for (PrintService service : findMissing(services)) {
public synchronized NativePrinterMap putAll(PrintService... services) {
for(PrintService service : findMissing(services)) {
String name = service.getName();
if(name.equals("PageManager PDF Writer")) {
if (name.equals("PageManager PDF Writer")) {
log.warn("Printer \"{}\" is blacklisted, removing", name); // Per https://github.com/qzind/tray/issues/599
continue;
}
Expand Down
Loading

0 comments on commit 5a1a372

Please sign in to comment.