/**
* 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.pdf;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import org.apache.camel.Exchange;
import org.apache.camel.component.pdf.text.AutoFormattedWriterAbstractFactory;
import org.apache.camel.component.pdf.text.LineBuilderStrategy;
import org.apache.camel.component.pdf.text.LineTerminationWriterAbstractFactory;
import org.apache.camel.component.pdf.text.SplitStrategy;
import org.apache.camel.component.pdf.text.TextProcessingAbstractFactory;
import org.apache.camel.component.pdf.text.WriteStrategy;
import org.apache.camel.impl.DefaultProducer;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.exceptions.CryptographyException;
import org.apache.pdfbox.exceptions.InvalidPasswordException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.BadSecurityHandlerException;
import org.apache.pdfbox.pdmodel.encryption.DecryptionMaterial;
import org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy;
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
import org.apache.pdfbox.util.PDFTextStripper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.camel.component.pdf.PdfHeaderConstants.*;
public class PdfProducer extends DefaultProducer {
private static final Logger LOG = LoggerFactory.getLogger(PdfProducer.class);
private final WriteStrategy writeStrategy;
private final SplitStrategy splitStrategy;
private final LineBuilderStrategy lineBuilderStrategy;
private final PdfConfiguration pdfConfiguration;
public PdfProducer(PdfEndpoint endpoint) {
super(endpoint);
this.pdfConfiguration = endpoint.getPdfConfiguration();
TextProcessingAbstractFactory textProcessingFactory = createTextProcessingFactory(pdfConfiguration);
this.writeStrategy = textProcessingFactory.createWriteStrategy();
this.splitStrategy = textProcessingFactory.createSplitStrategy();
this.lineBuilderStrategy = textProcessingFactory.createLineBuilderStrategy();
}
@Override
public void process(Exchange exchange) throws Exception {
Object result;
switch (pdfConfiguration.getOperation()) {
case append:
result = doAppend(exchange);
break;
case create:
result = doCreate(exchange);
break;
case extractText:
result = doExtractText(exchange);
break;
default:
throw new IllegalArgumentException(String.format("Unknown operation %s", pdfConfiguration.getOperation()));
}
// propagate headers
exchange.getOut().setHeaders(exchange.getIn().getHeaders());
exchange.getOut().setAttachments(exchange.getIn().getAttachments());
// and set result
exchange.getOut().setBody(result);
}
private Object doAppend(Exchange exchange) throws IOException, BadSecurityHandlerException, CryptographyException, InvalidPasswordException, COSVisitorException {
LOG.debug("Got {} operation, going to append text to provided pdf.", pdfConfiguration.getOperation());
String body = exchange.getIn().getBody(String.class);
PDDocument document = exchange.getIn().getHeader(PDF_DOCUMENT_HEADER_NAME, PDDocument.class);
if (document == null) {
throw new IllegalArgumentException(String.format("%s header is expected for append operation",
PDF_DOCUMENT_HEADER_NAME));
}
if (document.isEncrypted()) {
DecryptionMaterial decryptionMaterial = exchange.getIn().getHeader(DECRYPTION_MATERIAL_HEADER_NAME,
DecryptionMaterial.class);
if (decryptionMaterial == null) {
throw new IllegalArgumentException(String.format("%s header is expected for %s operation "
+ "on encrypted document",
DECRYPTION_MATERIAL_HEADER_NAME,
pdfConfiguration.getOperation()));
}
document.openProtection(decryptionMaterial);
document.setAllSecurityToBeRemoved(true);
}
ProtectionPolicy protectionPolicy = exchange.getIn().getHeader(
PROTECTION_POLICY_HEADER_NAME, ProtectionPolicy.class);
appendToPdfDocument(body, document, protectionPolicy);
OutputStream byteArrayOutputStream = new ByteArrayOutputStream();
document.save(byteArrayOutputStream);
return byteArrayOutputStream;
}
private String doExtractText(Exchange exchange) throws IOException, CryptographyException, InvalidPasswordException, BadSecurityHandlerException {
LOG.debug("Got {} operation, going to extract text from provided pdf.", pdfConfiguration.getOperation());
PDDocument document = exchange.getIn().getBody(PDDocument.class);
if (document.isEncrypted()) {
DecryptionMaterial decryptionMaterial = exchange.getIn().getHeader(DECRYPTION_MATERIAL_HEADER_NAME,
DecryptionMaterial.class);
if (decryptionMaterial == null) {
throw new IllegalArgumentException(String.format("%s header is expected for %s operation "
+ "on encrypted document",
DECRYPTION_MATERIAL_HEADER_NAME,
pdfConfiguration.getOperation()));
}
document.openProtection(decryptionMaterial);
}
PDFTextStripper pdfTextStripper = new PDFTextStripper();
return pdfTextStripper.getText(document);
}
private OutputStream doCreate(Exchange exchange) throws IOException, BadSecurityHandlerException, COSVisitorException {
LOG.debug("Got {} operation, going to create and write provided string to pdf document.",
pdfConfiguration.getOperation());
String body = exchange.getIn().getBody(String.class);
PDDocument document = new PDDocument();
StandardProtectionPolicy protectionPolicy = exchange.getIn().getHeader(
PROTECTION_POLICY_HEADER_NAME, StandardProtectionPolicy.class);
appendToPdfDocument(body, document, protectionPolicy);
OutputStream byteArrayOutputStream = new ByteArrayOutputStream();
document.save(byteArrayOutputStream);
return byteArrayOutputStream;
}
private void appendToPdfDocument(String text, PDDocument document, ProtectionPolicy protectionPolicy) throws IOException, BadSecurityHandlerException {
Collection<String> words = splitStrategy.split(text);
Collection<String> lines = lineBuilderStrategy.buildLines(words);
writeStrategy.write(lines, document);
if (protectionPolicy != null) {
document.protect(protectionPolicy);
}
}
private TextProcessingAbstractFactory createTextProcessingFactory(PdfConfiguration pdfConfiguration) {
TextProcessingAbstractFactory result;
switch (pdfConfiguration.getTextProcessingFactory()) {
case autoFormatting:
result = new AutoFormattedWriterAbstractFactory(pdfConfiguration);
break;
case lineTermination:
result = new LineTerminationWriterAbstractFactory(pdfConfiguration);
break;
default:
throw new IllegalArgumentException(String.format("Unknown text processing factory %s",
pdfConfiguration.getTextProcessingFactory()));
}
return result;
}
}