Apache Camelで指定ディレクトリのファイル一覧をファイル出力

Apache Camelで自分の細かい作業を自動化しようとした時のメモ。
以前にも同じ目的で実装方法が違うのをApache Camelで作ったけど今回のが多分一番マシだと思う。

入り口は`direct:report`でBodyにディレクトリのパスを設定するとそのディレクトリ配下のファイル一覧を`reports/report.tsv`に出力する。

DateTimeAPIじゃなくてJodaTime使ってるのはただの気まぐれ。

まずはpom.xml。

```xml:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>net.camel.client</groupId>
	<artifactId>camel-client</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
		<camel.version>2.13.2</camel.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-core</artifactId>
			<version>${camel.version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>slf4j-api</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-simple</artifactId>
			<version>1.7.7</version>
		</dependency>
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>17.0</version>
		</dependency>
		<dependency>
			<groupId>joda-time</groupId>
			<artifactId>joda-time</artifactId>
			<version>2.4</version>
		</dependency>
	</dependencies>
</project>
```

そしてmainメソッドを実装したクラスとファイルのリストを取得するクラス、ファイルのリストからTSVの文字列を作成するクラス。
processメソッドに自作のProcessorを実装したクラスを指定しているだけ。

```java:Application.java
package net.camel.client;

import net.camel.client.processor.FileListProcessor;
import net.camel.client.processor.FileListToTsvStringProcessor;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class Application {

	public static void main(String[] args) throws Exception {
		CamelContext context = new DefaultCamelContext();

		context.addRoutes(new RouteBuilder() {

			@Override
			public void configure() throws Exception {
				// 指定ディレクトリ内のファイルの一覧を出力
				from("direct:report")
						.process(new FileListProcessor())
						.process(new FileListToTsvStringProcessor())
						.to("file:reports/?fileName=report.tsv");
			}
		});

		context.start();

		context.createProducerTemplate().sendBody("direct:report", "e:\\");

		Runtime.getRuntime().addShutdownHook(new Thread(() -> {
			try {
				context.stop();
			} catch (Exception e) {
			}
		}));

		while (true) {
		}
	}
}
```

```java:FileListProcessor.java
package net.camel.client.processor;

import java.io.File;
import java.util.List;
import java.util.stream.Stream;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;

import com.google.common.collect.Lists;

public class FileListProcessor implements Processor {

	@Override
	public void process(Exchange exchange) throws Exception {
		List<File> files = getFiles(exchange.getIn().getBody(String.class));
		exchange.getIn().setBody(files);
	}

	private List<File> getFiles(String path) {
		File directory = new File(path);
		List<File> files = Lists.newArrayList();
		Stream<File> stream = Stream.of(directory.listFiles((dir, name) -> {
			return !(name.contains("RECYCLE.BIN")
				|| name.contains("System Volume Information"));
		}));
		stream.forEach(file -> {
			if (file.isDirectory()) {
				files.addAll(getFiles(file.getAbsolutePath()));
			} else {
				files.add(file);
			}
		});
		return files;
	}
}
```

```java:FileListToTsvStringProcessor.java
package net.camel.client.processor;

import java.io.File;
import java.util.List;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class FileListToTsvStringProcessor implements Processor {

	@SuppressWarnings("unchecked")
	@Override
	public void process(Exchange exchange) throws Exception {
		List<File> files = exchange.getIn().getBody(List.class);
		StringBuilder tsv = new StringBuilder();
		DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss");
		files.forEach(file -> {
			tsv.append(file.getAbsolutePath());
			tsv.append("\t");
			tsv.append(formatter.print(file.lastModified()));
			tsv.append("\n");
		});
		exchange.getIn().setBody(tsv.toString());
	}
}
```