Skip to content

Commit 3da5e3f

Browse files
committedMar 13, 2025
8349350: Unable to print using InputSlot and OutputBin print attributes at the same time
Reviewed-by: prr, kizune, psadhukhan
1 parent aa047ee commit 3da5e3f

File tree

4 files changed

+270
-4
lines changed

4 files changed

+270
-4
lines changed
 

‎src/java.desktop/share/classes/sun/print/PSPrinterJob.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1579,7 +1579,7 @@ private String[] printExecCmd(String printer, String options,
15791579
}
15801580
if (options != null && !options.isEmpty()) {
15811581
pFlags |= OPTIONS;
1582-
ncomps+=1;
1582+
ncomps+=options.trim().split(" ").length;
15831583
}
15841584
if (jobTitle != null && !jobTitle.isEmpty()) {
15851585
pFlags |= JOBTITLE;

‎src/java.desktop/unix/classes/sun/print/UnixPrintJob.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -836,7 +836,7 @@ private String[] printExecCmd(String printer, String options,
836836
}
837837
if (options != null && !options.isEmpty()) {
838838
pFlags |= OPTIONS;
839-
ncomps+=1;
839+
ncomps+=options.trim().split(" ").length;
840840
}
841841
if (jobTitle != null && !jobTitle.isEmpty()) {
842842
pFlags |= JOBTITLE;
@@ -871,7 +871,9 @@ private String[] printExecCmd(String printer, String options,
871871
execCmd[n++] = "-o job-sheets=standard";
872872
}
873873
if ((pFlags & OPTIONS) != 0) {
874-
execCmd[n++] = "-o" + options;
874+
for (String option : options.trim().split(" ")) {
875+
execCmd[n++] = "-o " + option;
876+
}
875877
}
876878
execCmd[n++] = spoolFile;
877879
if (IPPPrintService.debugPrint) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2025, BELLSOFT. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
import javax.print.PrintService;
26+
import javax.print.PrintServiceLookup;
27+
import javax.print.attribute.HashPrintRequestAttributeSet;
28+
import javax.print.attribute.PrintRequestAttributeSet;
29+
import javax.print.attribute.standard.Media;
30+
import javax.print.attribute.standard.MediaTray;
31+
import javax.print.attribute.standard.OutputBin;
32+
import java.awt.Graphics;
33+
import java.awt.print.PageFormat;
34+
import java.awt.print.Printable;
35+
import java.awt.print.PrinterException;
36+
import java.awt.print.PrinterJob;
37+
38+
/*
39+
* @test
40+
* @bug 8349350
41+
* @key printer
42+
* @summary no ArrayIndexOutOfBoundsException with multiple print options
43+
* @run main PrintExecCmdOptionTest
44+
*/
45+
46+
public class PrintExecCmdOptionTest {
47+
48+
public static void main(String[] args) throws PrinterException {
49+
PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
50+
if (printServices.length == 0) {
51+
System.out.println("No print service found");
52+
return;
53+
}
54+
55+
PrintService testPrintService = null;
56+
OutputBin outputBin = null;
57+
MediaTray mediaTray = null;
58+
for (PrintService ps : printServices) {
59+
mediaTray = null;
60+
Media[] medias = (Media[]) ps.
61+
getSupportedAttributeValues(Media.class, null, null);
62+
if (medias != null) {
63+
for (Media m : medias) {
64+
if (m instanceof MediaTray) {
65+
mediaTray = (MediaTray) m;
66+
break;
67+
}
68+
}
69+
}
70+
if (mediaTray == null) {
71+
continue;
72+
}
73+
OutputBin[] outputBins = (OutputBin[]) ps.
74+
getSupportedAttributeValues(OutputBin.class, null, null);
75+
if (outputBins != null && outputBins.length > 0) {
76+
outputBin = outputBins[0];
77+
testPrintService = ps;
78+
break;
79+
}
80+
}
81+
if (testPrintService == null) {
82+
System.out.println("Test print service not found");
83+
return;
84+
}
85+
86+
PrinterJob printerJob = PrinterJob.getPrinterJob();
87+
printerJob.setPrintService(testPrintService);
88+
89+
PrintRequestAttributeSet attributeSet = new HashPrintRequestAttributeSet();
90+
attributeSet.add(outputBin);
91+
attributeSet.add(mediaTray);
92+
93+
printerJob.setPrintable(new Printable() {
94+
@Override
95+
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
96+
return NO_SUCH_PAGE;
97+
}
98+
});
99+
printerJob.print(attributeSet);
100+
}
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2025, BELLSOFT. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
import javax.print.DocFlavor;
26+
import javax.print.DocPrintJob;
27+
import javax.print.PrintException;
28+
import javax.print.PrintService;
29+
import javax.print.PrintServiceLookup;
30+
import javax.print.SimpleDoc;
31+
import javax.print.attribute.HashDocAttributeSet;
32+
import javax.print.attribute.HashPrintRequestAttributeSet;
33+
import javax.print.attribute.PrintRequestAttribute;
34+
import javax.print.attribute.PrintRequestAttributeSet;
35+
import javax.print.attribute.standard.NumberUp;
36+
import javax.print.attribute.standard.OrientationRequested;
37+
import javax.print.attribute.standard.Sides;
38+
import java.io.ByteArrayOutputStream;
39+
import java.io.PrintStream;
40+
import java.util.ArrayList;
41+
import java.util.HashMap;
42+
import java.util.List;
43+
import java.util.Map;
44+
import java.util.regex.Pattern;
45+
46+
/*
47+
* @test
48+
* @bug 8349350
49+
* @key printer
50+
* @requires (os.family == "linux" | os.family == "mac")
51+
* @summary lpr command syntax for options. lpr [ -o option[=value] ]
52+
* @run main/manual/othervm -Dsun.print.ippdebug=true UnixPrintJobOptionsTest
53+
*/
54+
55+
public class UnixPrintJobOptionsTest {
56+
57+
static final DocFlavor docFlavor = DocFlavor.STRING.TEXT_PLAIN;
58+
static final List<Class<? extends PrintRequestAttribute>> requiredAttributes = new ArrayList<>();
59+
static {
60+
requiredAttributes.add(NumberUp.class);
61+
requiredAttributes.add(OrientationRequested.class);
62+
requiredAttributes.add(Sides.class);
63+
}
64+
static Map<PrintService,Class<? extends PrintRequestAttribute>[]> printerSupportedAttrs = new HashMap<>();
65+
66+
public static void main(String[] args) {
67+
initializeTestPrintServices();
68+
if (printerSupportedAttrs.isEmpty()) {
69+
System.out.println("Print services not found");
70+
return;
71+
}
72+
73+
PrintStream origPrintStream = System.out;
74+
ByteArrayOutputStream debugOutputStream = new ByteArrayOutputStream();
75+
PrintStream printStream = new PrintStream(debugOutputStream);
76+
System.setOut(printStream);
77+
try {
78+
if (!executeTest(debugOutputStream)) {
79+
System.out.println("Acceptable print service not found");
80+
}
81+
} finally {
82+
System.setOut(origPrintStream);
83+
System.out.println(debugOutputStream.toString());
84+
}
85+
}
86+
87+
/**
88+
* Tries to execute the test on one of the available print services
89+
* @param debugOutputStream 'standard' output stream
90+
* @return true - test was run and pass, false - test was not run
91+
*/
92+
private static boolean executeTest(ByteArrayOutputStream debugOutputStream) {
93+
for (PrintService testPrintService : printerSupportedAttrs.keySet()) {
94+
String patternStr = "/usr/bin/lpr\\s+.*";
95+
PrintRequestAttributeSet attributeSet = new HashPrintRequestAttributeSet();
96+
for (Class<? extends PrintRequestAttribute> attrClass : printerSupportedAttrs.get(testPrintService)) {
97+
Object supportedValues = testPrintService
98+
.getSupportedAttributeValues(attrClass, docFlavor, attributeSet);
99+
if (supportedValues == null || ((Object[]) supportedValues).length == 0) {
100+
continue;
101+
}
102+
if (attrClass == NumberUp.class) {
103+
NumberUp numberUp = ((NumberUp[]) supportedValues)[0];
104+
patternStr = patternStr + "\\s-o number-up=" + numberUp.getValue();
105+
attributeSet.add(numberUp);
106+
} else if (attrClass == OrientationRequested.class) {
107+
for (OrientationRequested orientationRequested : ((OrientationRequested[]) supportedValues)) {
108+
if (orientationRequested != OrientationRequested.PORTRAIT) {
109+
patternStr = patternStr + "\\s-o orientation-requested=" + orientationRequested.getValue();
110+
attributeSet.add(orientationRequested);
111+
break;
112+
}
113+
}
114+
} else if (attrClass == Sides.class) {
115+
Sides s = ((Sides[]) supportedValues)[0];
116+
patternStr = patternStr + "\\s-o sides=" + s.toString();
117+
attributeSet.add(s);
118+
}
119+
}
120+
121+
if (attributeSet.size() < 2) {
122+
continue;
123+
}
124+
System.out.println("Debug pattern: " + patternStr);
125+
DocPrintJob docPrintJob = testPrintService.createPrintJob();
126+
try {
127+
docPrintJob.print(new SimpleDoc("UnixPrintJob options test",
128+
docFlavor, new HashDocAttributeSet()), attributeSet);
129+
} catch (PrintException ex) {
130+
throw new RuntimeException(ex);
131+
}
132+
String debug = debugOutputStream.toString();
133+
Pattern pattern = Pattern.compile(patternStr);
134+
if (!pattern.matcher(debug).find()) {
135+
throw new RuntimeException("Output does not contain necessary options");
136+
} else {
137+
return true;
138+
}
139+
}
140+
return false;
141+
}
142+
143+
private static void initializeTestPrintServices() {
144+
PrintService[] printServices = PrintServiceLookup.lookupPrintServices(docFlavor, null);
145+
if (printServices == null || printServices.length == 0) {
146+
return;
147+
}
148+
149+
List<Class<? extends PrintRequestAttribute>> printerAttrs;
150+
for (PrintService ps : printServices) {
151+
printerAttrs = new ArrayList<>();
152+
for (Class<? extends PrintRequestAttribute> attr : requiredAttributes) {
153+
if (ps.isAttributeCategorySupported(attr)) {
154+
printerAttrs.add(attr);
155+
}
156+
}
157+
if (printerAttrs.size() > 1) {
158+
printerSupportedAttrs.put(ps, printerAttrs.toArray(new Class[0]));
159+
}
160+
}
161+
}
162+
163+
}

0 commit comments

Comments
 (0)
Please sign in to comment.