diff --git a/spring-integration-print/README.md b/spring-integration-print/README.md index fb02625..8a76de3 100644 --- a/spring-integration-print/README.md +++ b/spring-integration-print/README.md @@ -1,70 +1,121 @@ -Spring Integration Print Adapter -================================================= +Spring Integration Print Support +================================ -Welcome to the Spring Integration Adapter Template. This template is meant as a starting point for new Spring Integration Adapters. This temaplate provides the following -stubbed out components: +## Overview -* Outbound Channel Adapter -* Outbound Gateway -* Inbound Channel Adapter +The *Spring Integration Print* allows you to print payloads using the [Java Print Service][]. As such one *Outbound Channel Adapter* is provided. -# STS issues to be aware of +## Requirements -* [STS-1790](https://issuetracker.springsource.com/browse/STS-1790) - Allow for more flexibility in defining top level packages in the Spring STS Template Wizard -* [STS-2680](https://issuetracker.springsource.com/browse/STS-2680) - New Template Wizard projects aren't categorized on first launch +This module depends by default on Spring Integration 2.2. When using this module, please be aware that printing using [Java Print Service] can be unpredictable depending on the uses platform and the used printer. For some more details, please see: -# FAQ +* http://hillert.blogspot.com/2011/12/java-print-service-frustrations.html -## I need to add AOP Advices to my Adapters +Currently the Print Support has been tested using a *Brother HL-4070CDW* which exhibits several issues such as the inability to execute a print job that prints more than one copy for each page. If you use the Print Module, please report back any compatibility issues with your used printers. -Use FactoryBeans that wrap your adapter. See JPA Adapter for example. +## Dependency Declaration -## More to come... +### Gradle -# Building + dependencies { + … + compile "org.springframework.integration:spring-integration-print:1.0.0.BUILD-SNAPSHOT" + … + } -If you encounter out of memory errors during the build, increase available heap and permgen for Gradle: +### Maven - GRADLE_OPTS='-XX:MaxPermSize=1024m -Xmx1024m' + + … + + org.springframework.integration + spring-integration-print + 1.0.0.BUILD-SNAPSHOT + + … + -To build and install jars into your local Maven cache: +## Print Outbound Channel Adapter - ./gradlew install +The *Print Outbound Channel Adapter* is implemented using the *PrintMessageHandler* class. It in turn delegates to the *PrintServiceExecutor* class. The *PrintServiceExecutor* is responsible for initializing the Java *[PrintService][]*. As such, you can initialize the *PrintServiceExecutor* with providing a: -To build api Javadoc (results will be in `build/api`): +* Printer Name +* Custom implementation of the *[PrintService][]* interface (Useful for testing) - ./gradlew api +If you provide neither a printer name nor an implementation of the *[PrintService][]* interface, then the systems default printer is chosen. -To build reference documentation (results will be in `build/reference`): +The following properties can be set on the *Print Outbound Channel Adapter*: - ./gradlew reference +### printJobName -To build complete distribution including `-dist`, `-docs`, and `-schema` zip files (results will be in `build/distributions`) +*Optional* property that let's you specify the name of the print job as it is added to the print queue. Under the covers, this property will create a *javax.print.attribute.standard.JobName* and add it to the respective *PrintRequestAttributeSet*. This property is not used, if not specified (No explicit default value). - ./gradlew dist +### mediaSizeName -# Using SpringSource Tool Suite +*Optional* property that let's you specify the [MediaSizeName][]. Under the covers, this property will add the provided [MediaSizeName][] to the respective *PrintRequestAttributeSet*. This property is not used, if not specified (No explicit default value). - Gradle projects can be directly imported into STS +### sides -# Using PLain Eclipse +Let's you specify how the pages are are printed to the selected medium, e.g. duplex or one-sided. Under the covers, this property will add the provided [Sides][] instance to the respective *PrintRequestAttributeSet*. This property is not used, if not specified (No explicit default value). -To generate Eclipse metadata (.classpath and .project files), do the following: +### copies - ./gradlew eclipse +Let's you specify an integer value that indicates how many time each print page shall be printed. Under the covers, this property will add a [Copies][] instance to the respective *PrintRequestAttributeSet*. This property is not used, if not specified (No explicit default value). -Once complete, you may then import the projects into Eclipse as usual: +### mediaTray - *File -> Import -> Existing projects into workspace* +Let's you specify the media tray/bin for the print job. This property can be used instead of providing the *mediaSizeName* property. Under the covers, this property will add the provided [MediaTray][] instance to the respective *PrintRequestAttributeSet*. This property is not used, if not specified (No explicit default value). -Browse to the *'spring-integration'* root directory. All projects should import -free of errors. +### chromaticity -# Using IntelliJ IDEA +Let's you specify whether you want to do monochrome or color printing. Under the covers, this property will add the provided [Chromaticity][] instance to the respective *PrintRequestAttributeSet*. This property is not used, if not specified (No explicit default value). -To generate IDEA metadata (.iml and .ipr files), do the following: +### docFlavor - ./gradlew idea +Let's you specify the [DocFlavor]. If not specified, this property will default to *DocFlavor.STRING.TEXT_PLAIN*. -For more information, please visit the Spring Integration website at: -[http://www.springsource.org/spring-integration](http://www.springsource.org/spring-integration) +**IMPORTANT!** Every property is validated against the to be used [Java Print Service]. Therefore, if the selected [Java Print Service] is not supported, an *IllegalArgumentException* will be thrown. + +### Determining you printer capabilities. + +In order to get some indication what capabilities are supported by your printer, you may want to too look at the *PrintServiceExecutor*'s *getPrinterInfo()* method. When executed, it returns a list of: + +* Supported [DocFlavor][]s +* Supported Attribute Categories +* Supported [Print Attribute][]s + +## Namespace Support + +*Spring Integration* also provides XML Namespace support for the Print support. Simply add the following Namespace declaration: + + + + … + + +An example of declaring a *Print Outbound Channel Adapter* is shown below: + + + + +[Java Print Service]: http://docs.oracle.com/javase/6/docs/technotes/guides/jps/index.html +[PrintService]: http://docs.oracle.com/javase/6/docs/api/javax/print/PrintService.html +[Chromaticity]: http://docs.oracle.com/javase/6/docs/api/javax/print/attribute/standard/Chromaticity.html +[Copies]: http://docs.oracle.com/javase/6/docs/api/javax/print/attribute/standard/Copies.html +[DocFlavor]: http://docs.oracle.com/javase/6/docs/api/javax/print/DocFlavor.html +[MediaTray]: http://docs.oracle.com/javase/6/docs/api/javax/print/attribute/standard/MediaTray.html +[Print Attribute]: http://docs.oracle.com/javase/6/docs/api/javax/print/attribute/Attribute.html +[MediaSizeName]: http://docs.oracle.com/javase/6/docs/api/javax/print/attribute/standard/MediaSizeName.html +[Sides]: http://docs.oracle.com/javase/6/docs/api/javax/print/attribute/standard/Sides.html \ No newline at end of file diff --git a/spring-integration-print/build.gradle b/spring-integration-print/build.gradle index 025c7ad..6cd26ba 100644 --- a/spring-integration-print/build.gradle +++ b/spring-integration-print/build.gradle @@ -4,9 +4,6 @@ buildscript { repositories { maven { url 'https://repo.springsource.org/plugins-snapshot' } } - dependencies { - classpath 'org.springframework.build.gradle:docbook-reference-plugin:0.1.5' - } } apply plugin: 'java' @@ -21,9 +18,8 @@ repositories { maven { url 'http://repo.springsource.org/plugins-release' } // for bundlor } -// ensure JDK 5 compatibility (GRADLE-18; INT-1578) -sourceCompatibility=1.5 -targetCompatibility=1.5 +sourceCompatibility=1.6 +targetCompatibility=1.6 ext { aspectjVersion = '1.6.8' @@ -303,5 +299,5 @@ task dist(dependsOn: assemble) { task wrapper(type: Wrapper) { description = 'Generates gradlew[.bat] scripts' - gradleVersion = '1.0-rc-3' + gradleVersion = '1.0' } diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/config/xml/PrintOutboundChannelAdapterParser.java b/spring-integration-print/src/main/java/org/springframework/integration/print/config/xml/PrintOutboundChannelAdapterParser.java index ad626f8..621332e 100644 --- a/spring-integration-print/src/main/java/org/springframework/integration/print/config/xml/PrintOutboundChannelAdapterParser.java +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/config/xml/PrintOutboundChannelAdapterParser.java @@ -15,12 +15,17 @@ */ package org.springframework.integration.print.config.xml; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.integration.print.outbound.PrintMessageHandler; +import org.springframework.integration.print.support.ChromaticityEnum; +import org.springframework.integration.print.support.MediaSizeNameEnum; +import org.springframework.integration.print.support.MediaTrayEnum; import org.springframework.integration.print.support.PrintSides; import org.springframework.util.StringUtils; import org.w3c.dom.Element; @@ -30,7 +35,7 @@ import org.w3c.dom.Element; * The parser for the Print Outbound Channel Adapter. * * @author Gunnar Hillert - * @since 2.2 + * @since 1.0 * */ public class PrintOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { @@ -49,6 +54,16 @@ public class PrintOutboundChannelAdapterParser extends AbstractOutboundChannelAd protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { final BeanDefinitionBuilder printOutboundChannelAdapterBuilder = BeanDefinitionBuilder.genericBeanDefinition(PrintMessageHandler.class); + final BeanDefinitionBuilder printServiceExecutorBuilder = PrintParserUtils.getPrintServiceExecutorBuilder(element, parserContext); + + final BeanDefinition printServiceExecutorBeanDefinition = printServiceExecutorBuilder.getBeanDefinition(); + + final String channelAdapterId = this.resolveId(element, printServiceExecutorBuilder.getRawBeanDefinition(), parserContext); + final String printServiceExecutorBeanName = channelAdapterId + ".jpaExecutor"; + + parserContext.registerBeanComponent(new BeanComponentDefinition(printServiceExecutorBeanDefinition, printServiceExecutorBeanName)); + + printOutboundChannelAdapterBuilder.addConstructorArgReference(printServiceExecutorBeanName); String docFlavor = element.getAttribute("doc-flavor"); String mimeType = element.getAttribute("mime-type"); @@ -62,11 +77,30 @@ public class PrintOutboundChannelAdapterParser extends AbstractOutboundChannelAd printOutboundChannelAdapterBuilder.addConstructorArgValue(docFlavor); } - String sides = element.getAttribute("sides"); + final String sides = element.getAttribute("sides"); - PrintSides printSides = PrintSides.fromString(sides); + if (StringUtils.hasText(sides)) { + final PrintSides printSides = PrintSides.fromString(sides); + printOutboundChannelAdapterBuilder.addPropertyValue("sides", printSides.getSides()); + } - printOutboundChannelAdapterBuilder.addPropertyValue("sides", printSides.getSides()); + final String mediaSizeName = element.getAttribute("media-size-name"); + + if (StringUtils.hasText(mediaSizeName)) { + printOutboundChannelAdapterBuilder.addPropertyValue("mediaSizeName", MediaSizeNameEnum.getForString(mediaSizeName)); + } + + final String mediaTray = element.getAttribute("media-tray"); + + if (StringUtils.hasText(mediaTray)) { + printOutboundChannelAdapterBuilder.addPropertyValue("mediaTray", MediaTrayEnum.getForString(mediaTray)); + } + + final String chromaticity = element.getAttribute("chromaticity"); + + if (StringUtils.hasText(chromaticity)) { + printOutboundChannelAdapterBuilder.addPropertyValue("chromaticity", ChromaticityEnum.getForString(chromaticity)); + } IntegrationNamespaceUtils.setValueIfAttributeDefined(printOutboundChannelAdapterBuilder, element, "copies"); diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/config/xml/PrintParserUtils.java b/spring-integration-print/src/main/java/org/springframework/integration/print/config/xml/PrintParserUtils.java index 65f51e7..2bf6c07 100644 --- a/spring-integration-print/src/main/java/org/springframework/integration/print/config/xml/PrintParserUtils.java +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/config/xml/PrintParserUtils.java @@ -18,17 +18,17 @@ package org.springframework.integration.print.config.xml; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.integration.print.core.PrintExecutor; +import org.springframework.integration.print.core.PrintServiceExecutor; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; import org.w3c.dom.Element; - /** - * Contains various utility methods for parsing Print Adapter - * specific namesspace elements as well as for the generation of the the - * respective {@link BeanDefinition}s. + * Contains various utility methods for parsing Print Adapter specific namesspace + * elements and generating the respective {@link BeanDefinition}s. * * @author Gunnar Hillert + * * @since 1.0 * */ @@ -40,22 +40,43 @@ public final class PrintParserUtils { } /** - * Create a new {@link BeanDefinitionBuilder} for the class {@link PrintExecutor}. - * Initialize the wrapped {@link PrintExecutor} with common properties. + * Create a new {@link BeanDefinitionBuilder} for the class {@link JpaExecutor}. + * Initialize the wrapped {@link JpaExecutor} with common properties. * * @param element Must not be null * @param parserContext Must not be null - * @return The BeanDefinitionBuilder for the PrintExecutor + * @return The BeanDefinitionBuilder for the JpaExecutor */ - public static BeanDefinitionBuilder getPrintExecutorBuilder(final Element element, + public static BeanDefinitionBuilder getPrintServiceExecutorBuilder(final Element element, final ParserContext parserContext) { Assert.notNull(element, "The provided element must not be null."); Assert.notNull(parserContext, "The provided parserContext must not be null."); - final BeanDefinitionBuilder printExecutorBuilder = BeanDefinitionBuilder.genericBeanDefinition(PrintExecutor.class); + final Object source = parserContext.extractSource(element); - return printExecutorBuilder; + final BeanDefinitionBuilder printServiceExecutorBuilder = BeanDefinitionBuilder.genericBeanDefinition(PrintServiceExecutor.class); + + final String printServiceRef = element.getAttribute("print-service-ref"); + final String printerName = element.getAttribute("printer-name"); + + if (StringUtils.hasText(printServiceRef) + && StringUtils.hasText(printerName)) { + + parserContext.getReaderContext().error("Exactly only one of the attributes 'print-service-ref' or " + + "'printer-name' must be be set.", source); + + } + + if (StringUtils.hasText(printServiceRef)) { + printServiceExecutorBuilder.addConstructorArgReference(printServiceRef); + } + + if (StringUtils.hasText(printerName)) { + printServiceExecutorBuilder.addConstructorArgReference(printerName); + } + + return printServiceExecutorBuilder; } diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/core/PrintExecutor.java b/spring-integration-print/src/main/java/org/springframework/integration/print/core/PrintExecutor.java deleted file mode 100644 index 804c3ff..0000000 --- a/spring-integration-print/src/main/java/org/springframework/integration/print/core/PrintExecutor.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed 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.springframework.integration.print.core; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.integration.Message; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.util.Assert; - -/** - * Bundles common core logic for the Print components. - * - * @author Gunnar Hillert - * @since 1.0 - * - */ -public class PrintExecutor implements InitializingBean { - - private static final Log logger = LogFactory.getLog(PrintExecutor.class); - - private volatile String exampleProperty; - - /** - * Constructor. - */ - public PrintExecutor() {} - - /** - * Verifies and sets the parameters. E.g. initializes the to be used - */ - public void afterPropertiesSet() { - Assert.hasText(this.exampleProperty, "exampleProperty must not be empty."); - } - - /** - * Executes the outbound Print Operation. - * - */ - public Object executeOutboundOperation(final Message message) { - - if (logger.isWarnEnabled()) { - logger.warn("Logic not implemented, yet."); - } - - return message.getPayload(); - - } - - /** - * Execute the Print operation. Delegates to - * {@link PrintExecutor#poll(Message)}. - */ - public Object poll() { - return poll(null); - } - - /** - * Execute a retrieving (polling) Print operation. - * - * @param requestMessage May be null. - * @return The payload object, which may be null. - */ - public Object poll(final Message requestMessage) { - - if (logger.isWarnEnabled()) { - logger.warn("Logic not implemented, yet."); - } - - return MessageBuilder.fromMessage(requestMessage).build(); - } - - /** - * Example property to illustrate usage of properties in Spring Integration - * components. Replace with your own logic. - * - * @param exampleProperty Must not be null - */ - public void setExampleProperty(String exampleProperty) { - Assert.hasText(exampleProperty, "exampleProperty must be neither null nor empty"); - this.exampleProperty = exampleProperty; - } - -} diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/core/PrintServiceExecutor.java b/spring-integration-print/src/main/java/org/springframework/integration/print/core/PrintServiceExecutor.java new file mode 100644 index 0000000..2732a2f --- /dev/null +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/core/PrintServiceExecutor.java @@ -0,0 +1,177 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed 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.springframework.integration.print.core; + +import java.util.Arrays; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.print.DocFlavor; +import javax.print.PrintService; +import javax.print.PrintServiceLookup; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSet; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.integration.print.support.AttributeComparator; +import org.springframework.integration.print.support.DocFlavorComparator; +import org.springframework.integration.print.support.PrintServiceComparator; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * @author Gunnar Hillert + * @since 1.0 + * + */ +public final class PrintServiceExecutor { + + private final Log logger = LogFactory.getLog(PrintServiceExecutor.class); + + private PrintService printService; + + public PrintServiceExecutor() { + this(""); + } + + public PrintServiceExecutor(PrintService printService) { + this.printService = printService; + } + + public PrintServiceExecutor(String printerName) { + + if (!StringUtils.hasText(printerName)) { + this.printService = PrintServiceLookup.lookupDefaultPrintService(); + Assert.notNull(this.printService, "Did not find a the default print service."); + } + else { + PrintService matchingPrintService = null; + + for (PrintService printService : PrintServiceExecutor.getAvailablePrinterServices()) { + if (printerName.equalsIgnoreCase(printService.getName())) { + matchingPrintService = printService; + break; + } + } + + this.printService = matchingPrintService; + + Assert.notNull(this.printService, String.format("Did not find the" + + "print service for printer '%s'.", printerName)); + } + + if (logger.isInfoEnabled()) { + logger.info("Setting up print service for printer '" + this.printService.getName() + "'."); + } + else if (logger.isDebugEnabled()) { + logger.debug(this.getPrinterInfo()); + } + + } + + public SortedSet getDocFlavors() { + final SortedSet docFlavors = new TreeSet(new DocFlavorComparator()); + docFlavors.addAll(Arrays.asList(this.printService.getSupportedDocFlavors())); + return docFlavors; + } + + public String getPrinterInfo() { + StringBuilder sb = new StringBuilder(); + + final SortedSet docFlavors = this.getDocFlavors(); + final AttributeSet attributes = this.printService.getAttributes(); + + sb.append("\nPrinter Information\n"); + sb.append("==========================================================\n"); + sb.append("Name: " + this.printService.getName() + "\n"); + sb.append("Supported DocFlavors:\n"); + + for (DocFlavor docFlavor : docFlavors) { + sb.append(" " + docFlavor + "\n"); + } + + @SuppressWarnings("unchecked") + Class[] categories = (Class[]) this.printService + .getSupportedAttributeCategories(); + + sb.append("Supported Categories:\n"); + for (Class clazz : categories) { + sb.append(" " + clazz.getName() + "\n"); + } + + final SortedSet supportedAttributes = new TreeSet(new AttributeComparator()); + + for (Class clazz : categories) { + for (DocFlavor docFlavor : docFlavors) { + + Object value = this.printService.getSupportedAttributeValues(clazz, docFlavor, attributes); + + if (value != null) { + if (value instanceof Attribute) { + supportedAttributes.add((Attribute) value); + } + else if (value instanceof Attribute[]) { + supportedAttributes.addAll(Arrays.asList((Attribute[]) value)); + } + } + } + } + + sb.append("Supported Attributes:\n"); + + for (Attribute attribute : supportedAttributes) { + sb.append(" " + attribute + "(" + attribute.getCategory().getSimpleName() + ")\n"); + } + + return sb.toString(); + } + + public static SortedSet getAvailablePrinterServices() { + PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null); + printServices[0].getName(); + + SortedSet printServicesList = new TreeSet(new PrintServiceComparator()); + printServicesList.addAll(Arrays.asList(printServices)); + + return printServicesList; + } + + public SortedSet getDocFlavorsSupportingAttribute(Attribute attribute) { + + final SortedSet docFlavors = this.getDocFlavors(); + final AttributeSet attributes = this.printService.getAttributes(); + + final SortedSet matchedDocFlavors = new TreeSet(new DocFlavorComparator()); + + for (DocFlavor docFlavor : docFlavors) { + + final Object value = this.printService.getSupportedAttributeValues(attribute.getCategory(), docFlavor, attributes); + + if (value != null) { + matchedDocFlavors.add(docFlavor); + } + + } + + return matchedDocFlavors; + } + + public PrintService getPrintService() { + return printService; + } + +} diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/core/package-info.java b/spring-integration-print/src/main/java/org/springframework/integration/print/core/package-info.java deleted file mode 100644 index bf8bf0c..0000000 --- a/spring-integration-print/src/main/java/org/springframework/integration/print/core/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Provides core classes of the Print module. - */ -package org.springframework.integration.print.core; diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/outbound/PrintMessageHandler.java b/spring-integration-print/src/main/java/org/springframework/integration/print/outbound/PrintMessageHandler.java index 645f949..82dda44 100644 --- a/spring-integration-print/src/main/java/org/springframework/integration/print/outbound/PrintMessageHandler.java +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/outbound/PrintMessageHandler.java @@ -16,82 +16,225 @@ package org.springframework.integration.print.outbound; +import java.io.InputStream; +import java.util.Locale; + import javax.print.Doc; import javax.print.DocFlavor; import javax.print.DocPrintJob; -import javax.print.PrintService; -import javax.print.PrintServiceLookup; import javax.print.SimpleDoc; +import javax.print.attribute.DocAttributeSet; +import javax.print.attribute.HashDocAttributeSet; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Chromaticity; import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.JobName; +import javax.print.attribute.standard.MediaSizeName; +import javax.print.attribute.standard.MediaTray; import javax.print.attribute.standard.Sides; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.integration.Message; import org.springframework.integration.handler.AbstractMessageHandler; +import org.springframework.integration.print.core.PrintServiceExecutor; +import org.springframework.integration.print.support.PrintJobMonitor; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** - * Simple adapter to support printing of payloads. + * Outbound Adapter that supports printing of payloads. * * @author Gunnar Hillert - * @since 2.2 + * @since 1.0 */ public class PrintMessageHandler extends AbstractMessageHandler { private static final Log LOG = LogFactory.getLog(PrintMessageHandler.class); - private volatile Sides sides = Sides.ONE_SIDED; - private volatile Copies copies = new Copies(1); + private final PrintServiceExecutor printServiceExecutor; + private volatile String printJobName; + private volatile MediaSizeName mediaSizeName; + private volatile Sides sides; + private volatile Copies copies; + private volatile MediaTray mediaTray; + private volatile Chromaticity chromaticity; private final DocFlavor docFlavor; - public PrintMessageHandler(String mimeType, String className) { + private volatile PrintRequestAttributeSet printRequestAttributeSet = new HashPrintRequestAttributeSet(); + + public PrintMessageHandler(PrintServiceExecutor printServiceExecutor, DocFlavor docFlavor) { + Assert.notNull(docFlavor, "'docFlavor' must not be null."); + this.docFlavor = docFlavor; + this.printServiceExecutor = printServiceExecutor; + + } + + public PrintMessageHandler(PrintServiceExecutor printServiceExecutor, String mimeType, String className) { Assert.hasText(className, "'className' must be neither null nor empty."); Assert.hasText(mimeType, "'mimeType' must be neither null nor empty."); this.docFlavor = new DocFlavor(mimeType, className); + this.printServiceExecutor = printServiceExecutor; } - public PrintMessageHandler() { - this.docFlavor = DocFlavor.BYTE_ARRAY.AUTOSENSE; + public PrintMessageHandler(PrintServiceExecutor printServiceExecutor) { + this.docFlavor = DocFlavor.STRING.TEXT_PLAIN; + this.printServiceExecutor = printServiceExecutor; } @Override protected void handleMessageInternal(Message message) throws Exception { - final PrintService printService = PrintServiceLookup.lookupDefaultPrintService(); - - Assert.notNull(printService, "Did not find a 'printService'."); - - if (LOG.isInfoEnabled()) { - LOG.info("Printing to default printer: " + printService.getName()); + if (LOG.isDebugEnabled()) { + LOG.debug("Printing using printer '" + this.printServiceExecutor.getPrintService().getName() + "'."); } - final Doc doc = new SimpleDoc(((String) message.getPayload()).getBytes(), docFlavor, null); + DocAttributeSet das = new HashDocAttributeSet(); + das.add(Chromaticity.MONOCHROME); - final PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet(); + Object payload = message.getPayload(); - attributes.add(copies); - attributes.add(sides); + final Doc doc = new SimpleDoc(message.getPayload(), docFlavor, das); - final DocPrintJob job = printService.createPrintJob(); - job.print(doc, attributes); + final DocPrintJob job = this.printServiceExecutor.getPrintService().createPrintJob(); + + PrintJobMonitor printJobMonitor = new PrintJobMonitor(job); + + job.print(doc, this.printRequestAttributeSet); + + printJobMonitor.waitForDone(); + + if (payload instanceof InputStream) { + ((InputStream) payload).close(); + } } + @Override + protected void onInit() throws Exception { + + if (this.copies != null) { + //Assert.isTrue(printService.isAttributeValueSupported(this.copies, this.docFlavor, this.printService.getAttributes()), + // "Attribute '" + this.copies.getName() + "' with value '" + this.copies.getValue() + "' is not supported."); + this.printRequestAttributeSet.add(this.copies); + } + + if (this.chromaticity != null) { + Assert.isTrue(this.printServiceExecutor.getPrintService().isAttributeValueSupported(this.chromaticity, this.docFlavor, this.printServiceExecutor.getPrintService().getAttributes()), + "Attribute '" + this.chromaticity.getName() + "' with value '" + this.chromaticity.getValue() + "' is not supported."); + this.printRequestAttributeSet.add(this.chromaticity); + } + + if (this.mediaSizeName != null) { + Assert.isTrue(this.printServiceExecutor.getPrintService().isAttributeValueSupported(this.mediaSizeName, null, null), + "Attribute '" + this.mediaSizeName.getName() + + "' with value '" + this.mediaSizeName.getValue() + "' is not supported."); + this.printRequestAttributeSet.add(this.mediaSizeName); + } + + if (this.mediaTray != null) { + Assert.isTrue(this.printServiceExecutor.getPrintService().isAttributeValueSupported(this.mediaTray, this.docFlavor, this.printServiceExecutor.getPrintService().getAttributes()), + "Attribute value '" + this.mediaTray + "' is not supported."); + this.printRequestAttributeSet.add(this.mediaTray); + } + + if (this.sides!=null) { + Assert.isTrue(this.printServiceExecutor.getPrintService().isAttributeValueSupported(this.sides, this.docFlavor, this.printServiceExecutor.getPrintService().getAttributes()), + "Attribute value '" + this.sides + "' is not supported."); + this.printRequestAttributeSet.add(this.sides); + } + + if (StringUtils.hasText(this.printJobName)) { + this.printRequestAttributeSet.add(new JobName(this.printJobName, Locale.getDefault())); + } + + super.onInit(); + + } + + /** + * Specifies how the pages are are printed to the selected medium, + * e.g. duplex or one-sided. Under the covers, this property will add the + * provided {@link Sides} instance to the respective {@link PrintRequestAttributeSet}. + * + * This property is not used, if not specified (No explicit default value). + * + * @param sides Must not be null + */ public void setSides(Sides sides) { - Assert.notNull(sides, "'sides' must not be null"); + Assert.notNull(sides, "'sides' must not be null."); this.sides = sides; } + /** + * LetÕs you specify an integer value that indicates how many time each + * print page shall be printed. Under the covers, this property will add a + * + * {@link Copies} instance to the respective {@link PrintRequestAttributeSet}. + * This property is not used, if not specified (No explicit default value). + * + * @param numberOfCopies Must be greater than 0 + */ public void setCopies(int numberOfCopies) { - Assert.isTrue(numberOfCopies > 0, "'copies' must be greater than 0"); + Assert.isTrue(numberOfCopies > 0, "'copies' must be greater than 0."); this.copies = new Copies(numberOfCopies); } + /** + * Specifies the media tray/bin for the print job. This property can be used + * instead of providing the {@link #mediaSizeName} property. Under the covers, + * this property will add the provided {@link MediaTray} instance to the + * respective {@link PrintRequestAttributeSet}. This property is not used, + * if not specified (No explicit default value). + * + * @param mediaTray Must not be null + */ + public void setMediaTray(MediaTray mediaTray) { + Assert.notNull(mediaTray, "'mediaTray' must not be null."); + this.mediaTray = mediaTray; + } + + /** + * Specifies whether you want to do monochrome or color printing. Under the + * covers, this property will add the provided {@link Chromaticity} instance + * to the respective {@link PrintRequestAttributeSet}. This property is not + * used, if not specified (No explicit default value). + * + * @param chromaticity Must not be null. + */ + public void setChromaticity(Chromaticity chromaticity) { + Assert.notNull(chromaticity, "'chromaticity' must not be null."); + this.chromaticity = chromaticity; + } + + /** + * Sets the {@link MediaSizeName}. Under the covers, this property will add + * the provided {@link MediaSizeName} to the respective {@link PrintRequestAttributeSet}. + * This property is not used, if not specified (No explicit default value). + * + * @param mediaSizeName Must not be null. + */ + public void setMediaSizeName(MediaSizeName mediaSizeName) { + Assert.notNull(mediaSizeName, "'mediaSizeName' must not be null."); + this.mediaSizeName = mediaSizeName; + } + + /** + * Optional property that letÕs you specify the name of the print job as it + * is added to the print queue. Under the covers, this property will create + * a {@link JobName} instance and add it to the respective {@link PrintRequestAttributeSet}. + * This property is not used, if not specified (No explicit default value). + * + * @param printJobName Must neither be null nor empty. + */ + public void setPrintJobName(String printJobName) { + Assert.hasText(printJobName, "'mediaSizeName' must neither be null nor empty."); + this.printJobName = printJobName; + } + } diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/support/AttributeComparator.java b/spring-integration-print/src/main/java/org/springframework/integration/print/support/AttributeComparator.java new file mode 100644 index 0000000..cab1d98 --- /dev/null +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/support/AttributeComparator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed 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.springframework.integration.print.support; + +import java.util.Comparator; + +import javax.print.attribute.Attribute; + +/** + * @author Gunnar Hillert + * @since 1.0 + */ +public class AttributeComparator implements Comparator { + + public int compare(Attribute attribute1, Attribute attribute2) { + + int comparison = attribute1.getCategory().getName().compareTo(attribute2.getCategory().getName()); + + if (comparison == 0) { + return attribute1.toString().compareTo(attribute2.toString()); + } + + return comparison; + } + +} diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/support/ChromaticityEnum.java b/spring-integration-print/src/main/java/org/springframework/integration/print/support/ChromaticityEnum.java new file mode 100644 index 0000000..6f40350 --- /dev/null +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/support/ChromaticityEnum.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed 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.springframework.integration.print.support; + +import javax.print.attribute.standard.Chromaticity; + +import org.springframework.util.Assert; + +/** + * @author Gunnar Hillert + * @since 1.0 + */ +public enum ChromaticityEnum { + + COLOR(Chromaticity.COLOR), + MONOCHROME(Chromaticity.MONOCHROME); + + private Chromaticity chromaticity; + + private ChromaticityEnum(Chromaticity chromaticity) { + this.chromaticity = chromaticity; + } + + public Chromaticity getChromaticity() { + return chromaticity; + } + + public static Chromaticity getForString(String chromaticityAsString) { + + Assert.hasText(chromaticityAsString, "'chromaticityAsString' must neither be null nor empty."); + + final ChromaticityEnum[] chromaticityEnumValues = ChromaticityEnum.values(); + + for (ChromaticityEnum chromaticityEnum : chromaticityEnumValues) { + if (chromaticityEnum.name().equalsIgnoreCase(chromaticityAsString)) { + return chromaticityEnum.getChromaticity(); + } + } + + throw new IllegalArgumentException("Invalid chromaticity '" + chromaticityAsString + + "' provided."); + + } +} diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/PrintHeaders.java b/spring-integration-print/src/main/java/org/springframework/integration/print/support/DocFlavorComparator.java similarity index 59% rename from spring-integration-print/src/main/java/org/springframework/integration/print/PrintHeaders.java rename to spring-integration-print/src/main/java/org/springframework/integration/print/support/DocFlavorComparator.java index 98ba0ca..7e0bac5 100644 --- a/spring-integration-print/src/main/java/org/springframework/integration/print/PrintHeaders.java +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/support/DocFlavorComparator.java @@ -13,24 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package org.springframework.integration.print.support; -package org.springframework.integration.print; +import java.util.Comparator; + +import javax.print.DocFlavor; /** - * Print adapter specific message headers. - * * @author Gunnar Hillert * @since 1.0 */ -public class PrintHeaders { +public class DocFlavorComparator implements Comparator { - private static final String PREFIX = "print_"; + public int compare(DocFlavor docFlavor1, DocFlavor docFlavor2) { - public static final String EXAMPLE = PREFIX + "example_"; + int comparison = docFlavor1.getMimeType().compareTo(docFlavor2.getMimeType()); - /** Noninstantiable utility class */ - private PrintHeaders() { - throw new AssertionError(); + if (comparison == 0) { + return docFlavor1.getMediaSubtype().compareTo(docFlavor2.getMediaSubtype()); + } + + return comparison; } } diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/support/MediaSizeNameEnum.java b/spring-integration-print/src/main/java/org/springframework/integration/print/support/MediaSizeNameEnum.java new file mode 100644 index 0000000..9b01343 --- /dev/null +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/support/MediaSizeNameEnum.java @@ -0,0 +1,126 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed 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.springframework.integration.print.support; + +import javax.print.attribute.standard.MediaSizeName; + +import org.springframework.util.Assert; + +/** + * @author Gunnar Hillert + * @since 1.0 + */ +public enum MediaSizeNameEnum { + ISO_A0(MediaSizeName.ISO_A0), + ISO_A1(MediaSizeName.ISO_A1), + ISO_A2(MediaSizeName.ISO_A2), + ISO_A3(MediaSizeName.ISO_A3), + ISO_A4(MediaSizeName.ISO_A4), + ISO_A5(MediaSizeName.ISO_A5), + ISO_A6(MediaSizeName.ISO_A6), + ISO_A7(MediaSizeName.ISO_A7), + ISO_A8(MediaSizeName.ISO_A8), + ISO_A9(MediaSizeName.ISO_A9), + ISO_A10(MediaSizeName.ISO_A10), + ISO_B0(MediaSizeName.ISO_B0), + ISO_B1(MediaSizeName.ISO_B1), + ISO_B2(MediaSizeName.ISO_B2), + ISO_B3(MediaSizeName.ISO_B3), + ISO_B4(MediaSizeName.ISO_B4), + ISO_B5(MediaSizeName.ISO_B5), + ISO_B6(MediaSizeName.ISO_B6), + ISO_B7(MediaSizeName.ISO_B7), + ISO_B8(MediaSizeName.ISO_B8), + ISO_B9(MediaSizeName.ISO_B9), + ISO_B10(MediaSizeName.ISO_B10), + JIS_B0(MediaSizeName.JIS_B0), + JIS_B1(MediaSizeName.JIS_B1), + JIS_B2(MediaSizeName.JIS_B2), + JIS_B3(MediaSizeName.JIS_B3), + JIS_B4(MediaSizeName.JIS_B4), + JIS_B5(MediaSizeName.JIS_B5), + JIS_B6(MediaSizeName.JIS_B6), + JIS_B7(MediaSizeName.JIS_B7), + JIS_B8(MediaSizeName.JIS_B8), + JIS_B9(MediaSizeName.JIS_B9), + JIS_B10(MediaSizeName.JIS_B10), + ISO_C0(MediaSizeName.ISO_C0), + ISO_C1(MediaSizeName.ISO_C1), + ISO_C2(MediaSizeName.ISO_C2), + ISO_C3(MediaSizeName.ISO_C3), + ISO_C4(MediaSizeName.ISO_C4), + ISO_C5(MediaSizeName.ISO_C5), + ISO_C6(MediaSizeName.ISO_C6), + NA_LETTER(MediaSizeName.NA_LETTER), + NA_LEGAL(MediaSizeName.NA_LEGAL), + LEDGER(MediaSizeName.LEDGER), + TABLOID(MediaSizeName.TABLOID), + INVOICE(MediaSizeName.INVOICE), + FOLIO(MediaSizeName.FOLIO), + QUARTO(MediaSizeName.QUARTO), + JAPANESE_POSTCARD(MediaSizeName.JAPANESE_POSTCARD), + JAPANESE_DOUBLE_POSTCARD(MediaSizeName.JAPANESE_DOUBLE_POSTCARD), + A(MediaSizeName.A), + B(MediaSizeName.B), + C(MediaSizeName.C), + D(MediaSizeName.D), + E(MediaSizeName.E), + ISO_DESIGNATED_LONG(MediaSizeName.ISO_DESIGNATED_LONG), + ITALY_ENVELOPE(MediaSizeName.ITALY_ENVELOPE), + MONARCH_ENVELOPE(MediaSizeName.MONARCH_ENVELOPE), + PERSONAL_ENVELOPE(MediaSizeName.PERSONAL_ENVELOPE), + NA_NUMBER_9_ENVELOPE(MediaSizeName.NA_NUMBER_9_ENVELOPE), + NA_NUMBER_10_ENVELOPE(MediaSizeName.NA_NUMBER_10_ENVELOPE), + NA_NUMBER_11_ENVELOPE(MediaSizeName.NA_NUMBER_11_ENVELOPE), + NA_NUMBER_12_ENVELOPE(MediaSizeName.NA_NUMBER_12_ENVELOPE), + NA_NUMBER_14_ENVELOPE(MediaSizeName.NA_NUMBER_14_ENVELOPE), + NA_6X9_ENVELOPE(MediaSizeName.NA_6X9_ENVELOPE), + NA_7X9_ENVELOPE(MediaSizeName.NA_7X9_ENVELOPE), + NA_9X11_ENVELOPE(MediaSizeName.NA_9X11_ENVELOPE), + NA_9X12_ENVELOPE(MediaSizeName.NA_9X12_ENVELOPE), + NA_10X13_ENVELOPE(MediaSizeName.NA_10X13_ENVELOPE), + NA_10X14_ENVELOPE(MediaSizeName.NA_10X14_ENVELOPE), + NA_10X15_ENVELOPE(MediaSizeName.NA_10X15_ENVELOPE), + NA_5X7(MediaSizeName.NA_5X7), + NA_8X10(MediaSizeName.NA_8X10); + + private MediaSizeName mediaSizeName; + + private MediaSizeNameEnum(MediaSizeName mediaSizeName) { + this.mediaSizeName = mediaSizeName; + } + + public MediaSizeName getMediaSizeName() { + return mediaSizeName; + } + + public static MediaSizeName getForString(String mediaSizeNameAsString) { + + Assert.hasText(mediaSizeNameAsString, "'mediaSizeNameAsString' must neither be null nor empty."); + + final MediaSizeNameEnum[] mediaSizeNameEnumValues = MediaSizeNameEnum.values(); + + for (MediaSizeNameEnum mediaSizeNameEnum : mediaSizeNameEnumValues) { + if (mediaSizeNameEnum.name().equalsIgnoreCase(mediaSizeNameAsString)) { + return mediaSizeNameEnum.mediaSizeName; + } + } + + throw new IllegalArgumentException("Invalid mediaSizeName '" + mediaSizeNameAsString + + "' provided."); + + } +} diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/support/MediaTrayEnum.java b/spring-integration-print/src/main/java/org/springframework/integration/print/support/MediaTrayEnum.java new file mode 100644 index 0000000..159fb10 --- /dev/null +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/support/MediaTrayEnum.java @@ -0,0 +1,63 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed 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.springframework.integration.print.support; + +import javax.print.attribute.standard.MediaTray; + +import org.springframework.util.Assert; + +/** + * @author Gunnar Hillert + * @since 1.0 + */ +public enum MediaTrayEnum { + + BOTTOM(MediaTray.BOTTOM), + ENVELOPE(MediaTray.ENVELOPE), + LARGE_CAPACITY(MediaTray.LARGE_CAPACITY), + MAIN(MediaTray.MAIN), + MANUAL(MediaTray.MANUAL), + MIDDLE(MediaTray.MIDDLE), + SIDE(MediaTray.SIDE), + TOP(MediaTray.TOP); + + private MediaTray mediaTray; + + private MediaTrayEnum(MediaTray mediaTray) { + this.mediaTray = mediaTray; + } + + public MediaTray getMediaTray() { + return mediaTray; + } + + public static MediaTray getForString(String mediaTrayAsString) { + + Assert.hasText(mediaTrayAsString, "'mediaTrayAsString' must neither be null nor empty."); + + final MediaTrayEnum[] mediaTrayEnumValues = MediaTrayEnum.values(); + + for (MediaTrayEnum mediaTrayEnum : mediaTrayEnumValues) { + if (mediaTrayEnum.name().equalsIgnoreCase(mediaTrayAsString)) { + return mediaTrayEnum.getMediaTray(); + } + } + + throw new IllegalArgumentException("Invalid mediaTray '" + mediaTrayAsString + + "' provided."); + + } +} diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintUtils.java b/spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintServiceComparator.java similarity index 72% rename from spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintUtils.java rename to spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintServiceComparator.java index ce3f5b3..0570006 100644 --- a/spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintUtils.java +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintServiceComparator.java @@ -15,19 +15,18 @@ */ package org.springframework.integration.print.support; +import java.util.Comparator; + +import javax.print.PrintService; /** - * Contains utility methods used by the Print components. - * * @author Gunnar Hillert * @since 1.0 - * */ -public final class PrintUtils { +public class PrintServiceComparator implements Comparator { - /** Prevent instantiation. */ - private PrintUtils() { - throw new AssertionError(); + public int compare(PrintService printService1, PrintService printService2) { + return printService1.getName().compareTo(printService2.getName()); } } diff --git a/spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintSides.java b/spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintSides.java index 6225af7..cc76e4a 100644 --- a/spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintSides.java +++ b/spring-integration-print/src/main/java/org/springframework/integration/print/support/PrintSides.java @@ -1,3 +1,18 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed 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.springframework.integration.print.support; import javax.print.attribute.standard.Sides; diff --git a/spring-integration-print/src/main/resources/org/springframework/integration/print/config/xml/spring-integration-print-2.2.xsd b/spring-integration-print/src/main/resources/org/springframework/integration/print/config/xml/spring-integration-print-2.2.xsd index 429d838..7d943f1 100644 --- a/spring-integration-print/src/main/resources/org/springframework/integration/print/config/xml/spring-integration-print-2.2.xsd +++ b/spring-integration-print/src/main/resources/org/springframework/integration/print/config/xml/spring-integration-print-2.2.xsd @@ -78,27 +78,58 @@ - + - The number of copies to print. Defaults to 1 if not set. + If the printer name is not provided the sytem's default printer + is being used if available if available. Otherwise an + exceptions is thrown. - + + + + Allows you to provide a custom print-service implementation. + + + + + + + + + + + + The number of copies to print. Uses the default of the printer. + + + + + + + + + + + + @@ -108,6 +139,7 @@ + See: http://docs.oracle.com/javase/6/docs/api/javax/print/DocFlavor.html @@ -123,6 +155,13 @@ + + + + + + + @@ -136,4 +175,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-print/src/reference/docbook/SIAdapterLowerPrefix.xml b/spring-integration-print/src/reference/docbook/SIAdapterLowerPrefix.xml deleted file mode 100644 index 68c1390..0000000 --- a/spring-integration-print/src/reference/docbook/SIAdapterLowerPrefix.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - Print Adapter - - The Spring Integration Print Adapter provides... - - - - Outbound Channel adapter - - - Outbound Gateway - - - Inbound Channel Adapter - - - -
- Java Implementation - Each of the provided components will use the - org.springframework.integration.print.core.PrintExecutor - class... - -
-
- Common Configuration Attributes - - Certain configuration parameters are shared amongst all Print - components and are described below: - - - auto-startup - - Lifecycle attribute signaling if this component should - be started during Application Context startup. - Defaults to true. - Optional. - - - id - - Identifies the underlying Spring bean definition, which - is an instance of either EventDrivenConsumer - or PollingConsumer. - Optional. - - -
- -
- Outbound Channel Adapter - - The Print Outbound channel adapter allows you to... - -
-
- Outbound Gateway - - Outbound gateways are similar to outbound channel adapters except that it can also be used to - get a result on the reply channel after performing - the given... - -
-
- Inbound Channel Adapter - - An inbound channel adapter is used to execute... - -
- -
diff --git a/spring-integration-print/src/reference/docbook/history.xml b/spring-integration-print/src/reference/docbook/history.xml deleted file mode 100644 index 549be21..0000000 --- a/spring-integration-print/src/reference/docbook/history.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - Change History - - - diff --git a/spring-integration-print/src/reference/docbook/images/logo.png b/spring-integration-print/src/reference/docbook/images/logo.png deleted file mode 100644 index e1c2a0e..0000000 Binary files a/spring-integration-print/src/reference/docbook/images/logo.png and /dev/null differ diff --git a/spring-integration-print/src/reference/docbook/index.xml b/spring-integration-print/src/reference/docbook/index.xml deleted file mode 100644 index c1ac2a5..0000000 --- a/spring-integration-print/src/reference/docbook/index.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - Spring Integration Print Adapter - Print Adapter ${version} - Spring Integration - ${version} - - - - - - - - - - - - - - Gunnar Hillert - - - © SpringSource Inc., 2012 - - - - - - - What's new? - - - For those who are already familiar with Spring Integration, this - chapter - provides a brief overview of the new features of version 2.2. If you are - interested in the changes and features, that were introduced in - earlier - versions, please take a look at chapter: - - - - - - - - - - Integration Adapters - - This section covers the various Channel Adapters and Messaging - Gateways provided - by Spring Integration to support Message-based communication with - external systems. - - - - - - Appendices - - Advanced Topics and Additional Resources - - - - diff --git a/spring-integration-print/src/reference/docbook/resources.xml b/spring-integration-print/src/reference/docbook/resources.xml deleted file mode 100644 index 109faa9..0000000 --- a/spring-integration-print/src/reference/docbook/resources.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - Additional Resources - -
- Spring Integration Home - - The definitive source of information about Spring Integration is the - Spring Integration Home at - http://www.springsource.org. That site serves as a hub of - information and is the best place to find up-to-date announcements about the project as well as links to - articles, blogs, and new sample applications. - -
- -
diff --git a/spring-integration-print/src/reference/docbook/whats-new.xml b/spring-integration-print/src/reference/docbook/whats-new.xml deleted file mode 100644 index 6910c61..0000000 --- a/spring-integration-print/src/reference/docbook/whats-new.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - What's new? - - This chapter provides an overview of the new features and improvements - that have been added to the Print Adapter: - - - diff --git a/spring-integration-print/src/test/java/org/springframework/integration/print/PrintTests.java b/spring-integration-print/src/test/java/org/springframework/integration/print/PrintTests.java deleted file mode 100644 index 29468ab..0000000 --- a/spring-integration-print/src/test/java/org/springframework/integration/print/PrintTests.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.springframework.integration.print; - -import java.io.FileNotFoundException; -import java.io.InputStream; - -import javax.print.Doc; -import javax.print.DocFlavor; -import javax.print.DocPrintJob; -import javax.print.PrintException; -import javax.print.PrintService; -import javax.print.PrintServiceLookup; -import javax.print.SimpleDoc; -import javax.print.attribute.HashPrintRequestAttributeSet; -import javax.print.attribute.PrintRequestAttributeSet; -import javax.print.attribute.standard.Copies; -import javax.print.attribute.standard.Sides; - -public class PrintTests { - - public static void main(String args[]) throws FileNotFoundException, PrintException { - InputStream textStream = PrintTests.class.getResourceAsStream("/print.txt"); - DocFlavor myFormat = DocFlavor.INPUT_STREAM.AUTOSENSE; - Doc myDoc = new SimpleDoc(textStream, myFormat, null); - - PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); - - aset.add(new Copies(1)); - aset.add(Sides.ONE_SIDED); - - PrintService printService = PrintServiceLookup.lookupDefaultPrintService(); - - System.out.println("Printing to default printer: " + printService.getName()); - - DocPrintJob job = printService.createPrintJob(); - job.print(myDoc, aset); - } - -} diff --git a/spring-integration-print/src/test/java/org/springframework/integration/print/config/xml/PrintMessageHandlerParserTests-context.xml b/spring-integration-print/src/test/java/org/springframework/integration/print/config/xml/PrintMessageHandlerParserTests-context.xml index cee6bc4..8ee941c 100644 --- a/spring-integration-print/src/test/java/org/springframework/integration/print/config/xml/PrintMessageHandlerParserTests-context.xml +++ b/spring-integration-print/src/test/java/org/springframework/integration/print/config/xml/PrintMessageHandlerParserTests-context.xml @@ -9,14 +9,17 @@ http://www.springframework.org/schema/integration/print http://www.springframework.org/schema/integration/print/spring-integration-print.xsd"> + + + print-service-ref="printService" + copies="14" + doc-flavor="java.lang.String" + mime-type="text/plain; charset=utf-16" + sides="DUPLEX" + auto-startup="true" + order="2" + channel="input"> diff --git a/spring-integration-print/src/test/java/org/springframework/integration/print/config/xml/PrintMessageHandlerParserTests.java b/spring-integration-print/src/test/java/org/springframework/integration/print/config/xml/PrintMessageHandlerParserTests.java index e1cb98c..a7da1fc 100644 --- a/spring-integration-print/src/test/java/org/springframework/integration/print/config/xml/PrintMessageHandlerParserTests.java +++ b/spring-integration-print/src/test/java/org/springframework/integration/print/config/xml/PrintMessageHandlerParserTests.java @@ -13,22 +13,15 @@ package org.springframework.integration.print.config.xml; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import javax.print.DocFlavor; import javax.print.attribute.standard.Copies; import javax.print.attribute.standard.Sides; -import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.integration.channel.AbstractMessageChannel; import org.springframework.integration.core.MessageHandler; -import org.springframework.integration.endpoint.EventDrivenConsumer; -import org.springframework.integration.print.core.PrintExecutor; import org.springframework.integration.test.util.TestUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -60,7 +53,6 @@ public class PrintMessageHandlerParserTests { final Sides sides = TestUtils.getPropertyValue(messageHandler, "sides", Sides.class); assertEquals(Sides.DUPLEX, sides); - } } diff --git a/spring-integration-print/src/test/java/org/springframework/integration/print/outbound/PrintMessageHandlerTest.java b/spring-integration-print/src/test/java/org/springframework/integration/print/outbound/PrintMessageHandlerTest.java index 7a08a77..47ab73c 100644 --- a/spring-integration-print/src/test/java/org/springframework/integration/print/outbound/PrintMessageHandlerTest.java +++ b/spring-integration-print/src/test/java/org/springframework/integration/print/outbound/PrintMessageHandlerTest.java @@ -1,17 +1,37 @@ package org.springframework.integration.print.outbound; -import org.junit.Ignore; +import java.io.InputStream; + +import javax.print.DocFlavor; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.junit.Test; +import org.springframework.integration.print.core.PrintServiceExecutor; import org.springframework.integration.support.MessageBuilder; public class PrintMessageHandlerTest { - //@Test - //@Ignore - public void test() { - PrintMessageHandler handler = new PrintMessageHandler(); + private static final Log LOG = LogFactory.getLog(PrintMessageHandler.class); + + //@Test + public void testPdfPrint() { + + PrintServiceExecutor printServiceExecutor = new PrintServiceExecutor(); + PrintMessageHandler handler = new PrintMessageHandler(printServiceExecutor, DocFlavor.INPUT_STREAM.AUTOSENSE); + + InputStream is = PrintMessageHandlerTest.class.getResourceAsStream("Spring Integration Print Testing.pdf"); + handler.setCopies(2); + handler.setPrintJobName("My Spring Integration Print test."); + handler.afterPropertiesSet(); + handler.handleMessage(MessageBuilder.withPayload(is).build()); - handler.handleMessage(MessageBuilder.withPayload("This is a test".getBytes()).build()); } + @Test + public void testShowSupportedAttributes() { + final PrintServiceExecutor printServiceExecutor = new PrintServiceExecutor(); + final String info = printServiceExecutor.getPrinterInfo(); + LOG.info(info); + } } diff --git a/spring-integration-print/src/test/java/org/springframework/integration/print/outbound/PrintOutboundChannelAdapterTest.java b/spring-integration-print/src/test/java/org/springframework/integration/print/outbound/PrintOutboundChannelAdapterTest.java index 9a23ed5..a135f39 100644 --- a/spring-integration-print/src/test/java/org/springframework/integration/print/outbound/PrintOutboundChannelAdapterTest.java +++ b/spring-integration-print/src/test/java/org/springframework/integration/print/outbound/PrintOutboundChannelAdapterTest.java @@ -1,6 +1,5 @@ package org.springframework.integration.print.outbound; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-integration-print/src/test/java/org/springframework/integration/print/support/MockPrintService.java b/spring-integration-print/src/test/java/org/springframework/integration/print/support/MockPrintService.java new file mode 100644 index 0000000..97fbf15 --- /dev/null +++ b/spring-integration-print/src/test/java/org/springframework/integration/print/support/MockPrintService.java @@ -0,0 +1,97 @@ +package org.springframework.integration.print.support; + +import javax.print.DocFlavor; +import javax.print.DocPrintJob; +import javax.print.PrintService; +import javax.print.ServiceUIFactory; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSet; +import javax.print.attribute.PrintServiceAttribute; +import javax.print.attribute.PrintServiceAttributeSet; +import javax.print.event.PrintServiceAttributeListener; + +public class MockPrintService implements PrintService { + + public void addPrintServiceAttributeListener( + PrintServiceAttributeListener listener) { + // TODO Auto-generated method stub + + } + + public DocPrintJob createPrintJob() { + // TODO Auto-generated method stub + return null; + } + + public T getAttribute(Class category) { + // TODO Auto-generated method stub + return null; + } + + public PrintServiceAttributeSet getAttributes() { + // TODO Auto-generated method stub + return null; + } + + public Object getDefaultAttributeValue(Class category) { + // TODO Auto-generated method stub + return null; + } + + public String getName() { + // TODO Auto-generated method stub + return "Mock Printer"; + } + + public ServiceUIFactory getServiceUIFactory() { + // TODO Auto-generated method stub + return null; + } + + public Class[] getSupportedAttributeCategories() { + // TODO Auto-generated method stub + return null; + } + + public Object getSupportedAttributeValues( + Class category, DocFlavor flavor, + AttributeSet attributes) { + // TODO Auto-generated method stub + return null; + } + + public DocFlavor[] getSupportedDocFlavors() { + // TODO Auto-generated method stub + return null; + } + + public AttributeSet getUnsupportedAttributes(DocFlavor flavor, + AttributeSet attributes) { + // TODO Auto-generated method stub + return null; + } + + public boolean isAttributeCategorySupported( + Class category) { + // TODO Auto-generated method stub + return false; + } + + public boolean isAttributeValueSupported(Attribute attrval, + DocFlavor flavor, AttributeSet attributes) { + // TODO Auto-generated method stub + return true; + } + + public boolean isDocFlavorSupported(DocFlavor flavor) { + // TODO Auto-generated method stub + return false; + } + + public void removePrintServiceAttributeListener( + PrintServiceAttributeListener listener) { + // TODO Auto-generated method stub + + } + +} diff --git a/spring-integration-print/src/test/java/org/springframework/integration/print/support/PrintJobMonitor.java b/spring-integration-print/src/test/java/org/springframework/integration/print/support/PrintJobMonitor.java new file mode 100644 index 0000000..bb7635f --- /dev/null +++ b/spring-integration-print/src/test/java/org/springframework/integration/print/support/PrintJobMonitor.java @@ -0,0 +1,66 @@ +package org.springframework.integration.print.support; + +import javax.print.DocPrintJob; +import javax.print.event.PrintJobAdapter; +import javax.print.event.PrintJobEvent; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class PrintJobMonitor { + + private static final Log LOG = LogFactory.getLog(PrintJobMonitor.class); + + boolean done = false; + + public PrintJobMonitor(DocPrintJob job) { + + job.addPrintJobListener(new PrintJobAdapter() { + + @Override + public void printJobCanceled(PrintJobEvent arg0) { + if (LOG.isWarnEnabled()) { + LOG.warn("PrintJob Job canceled."); + } + allDone(); + } + + @Override + public void printJobCompleted(PrintJobEvent printJobEvent) { + if (LOG.isDebugEnabled()) { + LOG.debug("PrintJob Job completed."); + } + allDone(); + } + + public void printJobFailed(PrintJobEvent pje) { + allDone(); + } + + public void printJobNoMoreEvents(PrintJobEvent pje) { + if (LOG.isDebugEnabled()) { + LOG.debug("PrintJob Job completed (No More Events)."); + } + allDone(); + } + + void allDone() { + synchronized (PrintJobMonitor.this) { + done = true; + PrintJobMonitor.this.notify(); + } + } + + }); + } + + public synchronized void waitForDone() { + try { + while (!done) { + wait(); + } + } catch (InterruptedException e) { + } + } + +} diff --git a/spring-integration-print/src/test/java/org/springframework/integration/print/support/PrintUtilsTest.java b/spring-integration-print/src/test/java/org/springframework/integration/print/support/PrintUtilsTest.java new file mode 100644 index 0000000..30c23c4 --- /dev/null +++ b/spring-integration-print/src/test/java/org/springframework/integration/print/support/PrintUtilsTest.java @@ -0,0 +1,40 @@ +/** + * + */ +package org.springframework.integration.print.support; + +import java.util.SortedSet; + +import javax.print.PrintService; + +import org.apache.log4j.Logger; +import org.junit.Test; +import org.springframework.integration.print.core.PrintServiceExecutor; +import org.springframework.util.StringUtils; + +/** + * @author ghillert + * + */ +public class PrintUtilsTest { + + private static final Logger LOGGER = Logger.getLogger(PrintUtilsTest.class); + + private PrintServiceExecutor printServiceExecutor = new PrintServiceExecutor(); + + /** + * Test method for {@link org.springframework.integration.print.core.PrintServiceExecutor#getAvailablePrinterServices()}. + */ + @Test + public void testGetAvailablePrinterServices() { + SortedSet printers = PrintServiceExecutor.getAvailablePrinterServices(); + LOGGER.info("Available Printers: " + StringUtils.collectionToCommaDelimitedString(printers)); + } + + @Test + public void testGetPrintServiceByName() { + PrintService printService = printServiceExecutor.getPrintService(); + LOGGER.info("Default Printer found: " + printService); + } + +} diff --git a/spring-integration-print/src/test/resources/log4j.properties b/spring-integration-print/src/test/resources/log4j.properties index 5513e80..62c983a 100644 --- a/spring-integration-print/src/test/resources/log4j.properties +++ b/spring-integration-print/src/test/resources/log4j.properties @@ -5,4 +5,4 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n log4j.category.org.springframework.integration=WARN -log4j.category.org.springframework.integration.print=INFO +log4j.category.org.springframework.integration.print=DEBUG \ No newline at end of file diff --git a/spring-integration-print/src/test/resources/org/springframework/integration/print/outbound/Spring Integration Print Testing.pdf b/spring-integration-print/src/test/resources/org/springframework/integration/print/outbound/Spring Integration Print Testing.pdf new file mode 100644 index 0000000..ca14d04 Binary files /dev/null and b/spring-integration-print/src/test/resources/org/springframework/integration/print/outbound/Spring Integration Print Testing.pdf differ