001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.component.file; 018 019 import java.io.BufferedReader; 020 import java.io.File; 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.io.Reader; 024 import java.io.Serializable; 025 026 import org.apache.camel.Converter; 027 import org.apache.camel.Exchange; 028 import org.apache.camel.FallbackConverter; 029 import org.apache.camel.NoTypeConversionAvailableException; 030 import org.apache.camel.TypeConverter; 031 import org.apache.camel.converter.IOConverter; 032 import org.apache.camel.spi.TypeConverterRegistry; 033 import org.slf4j.Logger; 034 import org.slf4j.LoggerFactory; 035 036 /** 037 * A set of converter methods for working with generic file types 038 */ 039 @Converter 040 public final class GenericFileConverter { 041 042 private static final Logger LOG = LoggerFactory.getLogger(GenericFileConverter.class); 043 044 private GenericFileConverter() { 045 // Helper Class 046 } 047 048 @FallbackConverter 049 public static Object convertTo(Class<?> type, Exchange exchange, Object value, TypeConverterRegistry registry) 050 throws IOException, NoTypeConversionAvailableException { 051 052 // use a fallback type converter so we can convert the embedded body if the value is GenericFile 053 if (GenericFile.class.isAssignableFrom(value.getClass())) { 054 055 GenericFile<?> file = (GenericFile<?>) value; 056 Class<?> from = file.getBody().getClass(); 057 058 // maybe from is already the type we want 059 if (from.isAssignableFrom(type)) { 060 return file.getBody(); 061 } 062 063 // no then try to lookup a type converter 064 TypeConverter tc = registry.lookup(type, from); 065 if (tc != null) { 066 Object body = file.getBody(); 067 // if its a file and we have a charset then use a reader to ensure we read the content using the given charset 068 // this is a bit complicated, but a file consumer can be configured with an explicit charset, which means 069 // we should read the file content with that given charset, and ignore any other charset properties 070 071 // if the desired type is InputStream or Reader we can use the optimized methods 072 if (Reader.class.isAssignableFrom(type)) { 073 Reader reader = genericFileToReader(file, exchange); 074 if (reader != null) { 075 return reader; 076 } 077 } 078 if (InputStream.class.isAssignableFrom(type)) { 079 InputStream is = genericFileToInputStream(file, exchange); 080 if (is != null) { 081 return is; 082 } 083 } 084 085 // okay if the file has a charset configured then we must try to load the file using that charset 086 // which mean we have to use the Reader first, and then convert from there 087 if (body instanceof File && file.getCharset() != null) { 088 Reader reader = genericFileToReader(file, exchange); 089 // we dont want a reader back, so use the type converter registry to find a suitable converter 090 TypeConverter readerTc = registry.lookup(type, Reader.class); 091 if (readerTc != null) { 092 // use the reader based type converter 093 return readerTc.convertTo(type, exchange, reader); 094 } 095 } 096 // fallback and use the type suitable type converter 097 return tc.convertTo(type, exchange, body); 098 } 099 } 100 101 return null; 102 } 103 104 @Converter 105 public static InputStream genericFileToInputStream(GenericFile<?> file, Exchange exchange) throws IOException, NoTypeConversionAvailableException { 106 if (file.getFile() instanceof File) { 107 // prefer to use a file input stream if its a java.io.File 108 File f = (File) file.getFile(); 109 // the file must exists 110 if (f.exists()) { 111 // read the file using the specified charset 112 String charset = file.getCharset(); 113 if (charset != null) { 114 LOG.debug("Read file {} with charset {}", f, file.getCharset()); 115 } else { 116 LOG.debug("Read file {} (no charset)", f); 117 } 118 return IOConverter.toInputStream(f, charset); 119 } 120 } 121 if (exchange != null) { 122 // otherwise ensure the body is loaded as we want the input stream of the body 123 file.getBinding().loadContent(exchange, file); 124 return exchange.getContext().getTypeConverter().convertTo(InputStream.class, exchange, file.getBody()); 125 } else { 126 // should revert to fallback converter if we don't have an exchange 127 return null; 128 } 129 } 130 131 @Converter 132 public static String genericFileToString(GenericFile<?> file, Exchange exchange) throws IOException, NoTypeConversionAvailableException { 133 // use reader first as it supports the file charset 134 BufferedReader reader = genericFileToReader(file, exchange); 135 if (reader != null) { 136 return IOConverter.toString(reader); 137 } 138 if (exchange != null) { 139 // otherwise ensure the body is loaded as we want the content of the body 140 file.getBinding().loadContent(exchange, file); 141 return exchange.getContext().getTypeConverter().convertTo(String.class, exchange, file.getBody()); 142 } else { 143 // should revert to fallback converter if we don't have an exchange 144 return null; 145 } 146 } 147 148 @Converter 149 public static Serializable genericFileToSerializable(GenericFile<?> file, Exchange exchange) throws IOException, NoTypeConversionAvailableException { 150 if (exchange != null) { 151 // load the file using input stream 152 InputStream is = genericFileToInputStream(file, exchange); 153 if (is != null) { 154 return exchange.getContext().getTypeConverter().convertTo(Serializable.class, exchange, is); 155 } 156 } 157 // should revert to fallback converter if we don't have an exchange 158 return null; 159 } 160 161 private static BufferedReader genericFileToReader(GenericFile<?> file, Exchange exchange) throws IOException, NoTypeConversionAvailableException { 162 if (file.getFile() instanceof File) { 163 // prefer to use a file input stream if its a java.io.File 164 File f = (File) file.getFile(); 165 // the file must exists 166 if (!f.exists()) { 167 return null; 168 } 169 // and use the charset if the file was explicit configured with a charset 170 String charset = file.getCharset(); 171 if (charset != null) { 172 LOG.debug("Read file {} with charset {}", f, file.getCharset()); 173 return IOConverter.toReader(f, charset); 174 } else { 175 LOG.debug("Read file {} (no charset)", f); 176 return IOConverter.toReader(f, exchange); 177 } 178 } 179 return null; 180 } 181 }