/** * 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 com.apachecon.camel.filesplit; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; import org.apache.camel.CamelException; import org.apache.camel.Converter; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Message; import org.apache.camel.Predicate; import org.apache.camel.Processor; import org.apache.camel.component.file.GenericFile; import org.apache.camel.component.file.GenericFileConverter; import org.apache.camel.impl.DefaultMessage; import org.apache.camel.util.ObjectHelper; @Converter public final class FileSplitter { public static final String CHUNK_INDEX = "SplitterChunkIndex"; public static final String SEQUENCE_INDEX = "SplitterSequenceIndex"; public static final String SEQUENCE_LAST = "SplitterSequenceLast"; public static final Message EMPTY_MESSAGE = new DefaultMessage(); public static Expression nullBody() { return new Expression() { @Override public <T> T evaluate(Exchange exchange, Class<T> type) { return (T)null; } }; } public static Expression blocks(final long blockSize) { return new Expression() { @Override @SuppressWarnings("unchecked") public <T> T evaluate(Exchange exchange, Class<T> type) { if (type.isAssignableFrom(List.class) && exchange.getIn().getBody() instanceof GenericFile) { GenericFile<?> input = (GenericFile<?>)exchange.getIn().getBody(); long size = input.getFileLength(); int count = (int)((size + blockSize - 1) / blockSize); List<FileBlock> answer = new ArrayList<FileBlock>(count); for (int i = 0; i < count; i++) { answer.add(new FileBlock(input, blockSize, i)); } return (T)answer; } return null; } }; } public static Processor delayLine(final int length) { return new Processor() { private Queue<Message> queue = new LinkedList<Message>(); private int index = 0; @Override public void process(Exchange exchange) throws Exception { queue.add(exchange.getIn()); Message out = length < queue.size() ? queue.poll() : EMPTY_MESSAGE; if (out.getBody() != null) { out.setHeader(SEQUENCE_INDEX, index++); Message prev = queue.size() > 0 ? queue.peek() : EMPTY_MESSAGE; out.setHeader(SEQUENCE_LAST, prev.getBody() == null); } else { index = 0; } exchange.setOut(out); } }; } public static Predicate notEmpty() { return new Predicate() { @Override public boolean matches(Exchange exchange) { Integer index = exchange.getIn().getHeader(SEQUENCE_INDEX, Integer.class); return exchange.getIn().getBody() != null && index != 0; } }; } @Converter public static InputStream toInputStream(FileBlock block, Exchange exchange) throws IOException, CamelException { if (block.getFile().getFile() instanceof java.io.File) { ObjectHelper.notNull(exchange, "Exchange"); exchange.getIn().setHeader(CHUNK_INDEX, block.getIndex()); return new BlockInputStream(new FileInputStream((File)block.getFile().getFile()), block.getChunk(), block.getIndex()); } return GenericFileConverter.genericFileToInputStream(block.getFile(), exchange); } }