/** * 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.apache.camel.component.printer; import java.io.FileInputStream; import java.io.InputStream; import java.util.Map; import javax.print.Doc; import javax.print.DocFlavor; import javax.print.DocPrintJob; import javax.print.PrintService; import javax.print.PrintServiceLookup; import javax.print.attribute.Attribute; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.standard.Media; import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.MediaTray; import javax.print.attribute.standard.OrientationRequested; import javax.print.attribute.standard.Sides; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.camel.util.IOHelper; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class PrinterPrintTest extends CamelTestSupport { @Before public void setup() { setupJavaPrint(); } @Override public boolean isUseRouteBuilder() { return false; } // Check if there is an awt library private boolean isAwtHeadless() { return Boolean.getBoolean("java.awt.headless"); } private void sendFile() throws Exception { template.send("direct:start", new Processor() { public void process(Exchange exchange) throws Exception { // Read from an input stream InputStream is = IOHelper.buffered(new FileInputStream("src/test/resources/test.txt")); byte buffer[] = new byte[is.available()]; int n = is.available(); for (int i = 0; i < n; i++) { buffer[i] = (byte) is.read(); } is.close(); // Set the property of the charset encoding exchange.setProperty(Exchange.CHARSET_NAME, "UTF-8"); Message in = exchange.getIn(); in.setBody(buffer); } }); } private void sendGIF() throws Exception { template.send("direct:start", new Processor() { public void process(Exchange exchange) throws Exception { // Read from an input stream InputStream is = IOHelper.buffered(new FileInputStream("src/test/resources/asf-logo.gif")); byte buffer[] = new byte[is.available()]; int n = is.available(); for (int i = 0; i < n; i++) { buffer[i] = (byte) is.read(); } is.close(); // Set the property of the charset encoding exchange.setProperty(Exchange.CHARSET_NAME, "UTF-8"); Message in = exchange.getIn(); in.setBody(buffer); } }); } private void sendJPEG() throws Exception { template.send("direct:start", new Processor() { public void process(Exchange exchange) throws Exception { // Read from an input stream InputStream is = IOHelper.buffered(new FileInputStream("src/test/resources/asf-logo.JPG")); byte buffer[] = new byte[is.available()]; int n = is.available(); for (int i = 0; i < n; i++) { buffer[i] = (byte) is.read(); } is.close(); // Set the property of the charset encoding exchange.setProperty(Exchange.CHARSET_NAME, "UTF-8"); Message in = exchange.getIn(); in.setBody(buffer); } }); } @Test @Ignore public void testSendingFileToPrinter() throws Exception { if (isAwtHeadless()) { return; } context.addRoutes(new RouteBuilder() { public void configure() { from("direct:start"). to("lpr://localhost/default?copies=1&flavor=DocFlavor.BYTE_ARRAY&mimeType=AUTOSENSE&mediaSize=na-letter&sides=one-sided&sendToPrinter=false"); } }); context.start(); sendFile(); } @Test @Ignore public void testSendingGIFToPrinter() throws Exception { if (isAwtHeadless()) { return; } context.addRoutes(new RouteBuilder() { public void configure() { from("direct:start"). to("lpr://localhost/default?flavor=DocFlavor.INPUT_STREAM&mimeType=GIF&mediaSize=na-letter&sides=one-sided&sendToPrinter=false"); } }); context.start(); sendGIF(); } @Test @Ignore public void testSendingJPEGToPrinter() throws Exception { if (isAwtHeadless()) { return; } context.addRoutes(new RouteBuilder() { public void configure() { from("direct:start").to("lpr://localhost/default?copies=2&flavor=DocFlavor.INPUT_STREAM" + "&mimeType=JPEG&mediaSize=na-letter&sides=one-sided&sendToPrinter=false"); } }); context.start(); sendJPEG(); } @Test @Ignore public void testSendingJPEGToPrinterWithLandscapePageOrientation() throws Exception { if (isAwtHeadless()) { return; } context.addRoutes(new RouteBuilder() { public void configure() { from("direct:start").to("lpr://localhost/default?flavor=DocFlavor.INPUT_STREAM" + "&mimeType=JPEG&sendToPrinter=false&orientation=landscape"); } }); context.start(); sendJPEG(); } /** * Test for resolution of bug CAMEL-3446. * Not specifying mediaSize nor sides attributes make it use * default values when starting the route. */ @Test @Ignore public void testDefaultPrinterConfiguration() throws Exception { if (isAwtHeadless()) { return; } context.addRoutes(new RouteBuilder() { public void configure() { from("direct:start").to("lpr://localhost/default?sendToPrinter=false"); } }); context.start(); } @Test public void moreThanOneLprEndpoint() throws Exception { if (isAwtHeadless()) { return; } int numberOfPrintservicesBefore = PrintServiceLookup.lookupPrintServices(null, null).length; // setup javax.print PrintService ps1 = mock(PrintService.class); when(ps1.getName()).thenReturn("printer1"); when(ps1.isDocFlavorSupported(any(DocFlavor.class))).thenReturn(Boolean.TRUE); PrintService ps2 = mock(PrintService.class); when(ps2.getName()).thenReturn("printer2"); boolean res1 = PrintServiceLookup.registerService(ps1); assertTrue("PrintService #1 should be registered.", res1); boolean res2 = PrintServiceLookup.registerService(ps2); assertTrue("PrintService #2 should be registered.", res2); PrintService[] pss = PrintServiceLookup.lookupPrintServices(null, null); assertEquals("lookup should report two PrintServices.", numberOfPrintservicesBefore + 2, pss.length); DocPrintJob job1 = mock(DocPrintJob.class); when(ps1.createPrintJob()).thenReturn(job1); context.addRoutes(new RouteBuilder() { public void configure() { from("direct:start1").to("lpr://localhost/printer1?sendToPrinter=true"); from("direct:start2").to("lpr://localhost/printer2?sendToPrinter=false"); } }); context.start(); // Are there two different PrintConfigurations? Map<String, Endpoint> epm = context().getEndpointMap(); assertEquals("Four endpoints", 4, epm.size()); Endpoint lp1 = null; Endpoint lp2 = null; for (Map.Entry<String, Endpoint> ep : epm.entrySet()) { if (ep.getKey().contains("printer1")) { lp1 = ep.getValue(); } if (ep.getKey().contains("printer2")) { lp2 = ep.getValue(); } } assertNotNull(lp1); assertNotNull(lp2); assertEquals("printer1", ((PrinterEndpoint) lp1).getConfig().getPrintername()); assertEquals("printer2", ((PrinterEndpoint) lp2).getConfig().getPrintername()); template.sendBody("direct:start1", "Hello Printer 1"); context.stop(); verify(job1, times(1)).print(any(Doc.class), any(PrintRequestAttributeSet.class)); } @Test public void printerNameTest() throws Exception { if (isAwtHeadless()) { return; } // setup javax.print PrintService ps1 = mock(PrintService.class); when(ps1.getName()).thenReturn("MyPrinter\\\\remote\\printer1"); when(ps1.isDocFlavorSupported(any(DocFlavor.class))).thenReturn(Boolean.TRUE); boolean res1 = PrintServiceLookup.registerService(ps1); assertTrue("The Remote PrintService #1 should be registered.", res1); DocPrintJob job1 = mock(DocPrintJob.class); when(ps1.createPrintJob()).thenReturn(job1); context.addRoutes(new RouteBuilder() { public void configure() { from("direct:start1").to("lpr://remote/printer1?sendToPrinter=true"); } }); context.start(); template.sendBody("direct:start1", "Hello Printer 1"); context.stop(); verify(job1, times(1)).print(any(Doc.class), any(PrintRequestAttributeSet.class)); } @Test public void setJobName() throws Exception { if (isAwtHeadless()) { return; } getMockEndpoint("mock:output").setExpectedMessageCount(1); context.addRoutes(new RouteBuilder() { public void configure() { from("direct:start").to("lpr://localhost/default").to("mock:output"); } }); context.start(); template.sendBodyAndHeader("direct:start", "Hello Printer", PrinterEndpoint.JOB_NAME, "Test-Job-Name"); context.stop(); assertMockEndpointsSatisfied(); } @Test public void printToMiddleTray() throws Exception { PrinterEndpoint endpoint = new PrinterEndpoint(); PrinterConfiguration configuration = new PrinterConfiguration(); configuration.setHostname("localhost"); configuration.setPort(631); configuration.setPrintername("DefaultPrinter"); configuration.setMediaSizeName(MediaSizeName.ISO_A4); configuration.setInternalSides(Sides.ONE_SIDED); configuration.setInternalOrientation(OrientationRequested.PORTRAIT); configuration.setMediaTray("middle"); PrinterProducer producer = new PrinterProducer(endpoint, configuration); producer.start(); PrinterOperations printerOperations = producer.getPrinterOperations(); PrintRequestAttributeSet attributeSet = printerOperations.getPrintRequestAttributeSet(); Attribute attribute = attributeSet.get(javax.print.attribute.standard.Media.class); assertNotNull(attribute); assertTrue(attribute instanceof MediaTray); MediaTray mediaTray = (MediaTray) attribute; assertEquals("middle", mediaTray.toString()); } @Test public void printsWithLandscapeOrientation() throws Exception { PrinterEndpoint endpoint = new PrinterEndpoint(); PrinterConfiguration configuration = new PrinterConfiguration(); configuration.setHostname("localhost"); configuration.setPort(631); configuration.setPrintername("DefaultPrinter"); configuration.setMediaSizeName(MediaSizeName.ISO_A4); configuration.setInternalSides(Sides.ONE_SIDED); configuration.setInternalOrientation(OrientationRequested.REVERSE_LANDSCAPE); configuration.setMediaTray("middle"); configuration.setSendToPrinter(false); PrinterProducer producer = new PrinterProducer(endpoint, configuration); producer.start(); PrinterOperations printerOperations = producer.getPrinterOperations(); PrintRequestAttributeSet attributeSet = printerOperations.getPrintRequestAttributeSet(); Attribute attribute = attributeSet.get(OrientationRequested.class); assertNotNull(attribute); assertEquals("reverse-landscape", attribute.toString()); } protected void setupJavaPrint() { // "install" another default printer PrintService psDefault = mock(PrintService.class); when(psDefault.getName()).thenReturn("DefaultPrinter"); when(psDefault.isDocFlavorSupported(any(DocFlavor.class))).thenReturn(Boolean.TRUE); PrintServiceLookup psLookup = mock(PrintServiceLookup.class); when(psLookup.getPrintServices()).thenReturn(new PrintService[]{psDefault}); when(psLookup.getDefaultPrintService()).thenReturn(psDefault); DocPrintJob docPrintJob = mock(DocPrintJob.class); when(psDefault.createPrintJob()).thenReturn(docPrintJob); MediaTray[] trays = new MediaTray[]{ MediaTray.TOP, MediaTray.MIDDLE, MediaTray.BOTTOM }; when(psDefault.getSupportedAttributeValues(Media.class, null, null)).thenReturn(trays); PrintServiceLookup.registerServiceProvider(psLookup); } }