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.File; 020 021 import org.apache.camel.Consumer; 022 import org.apache.camel.ExchangePattern; 023 import org.apache.camel.Message; 024 import org.apache.camel.Processor; 025 import org.apache.camel.Producer; 026 import org.apache.camel.component.file.strategy.FileProcessStrategyFactory; 027 import org.apache.camel.component.file.strategy.FileProcessStrategySupport; 028 import org.apache.camel.component.file.strategy.NoOpFileProcessStrategy; 029 import org.apache.camel.impl.ScheduledPollEndpoint; 030 import org.apache.commons.logging.Log; 031 import org.apache.commons.logging.LogFactory; 032 033 /** 034 * A <a href="http://activemq.apache.org/camel/file.html">File Endpoint</a> for 035 * working with file systems 036 * 037 * @version $Revision: 41278 $ 038 */ 039 public class FileEndpoint extends ScheduledPollEndpoint<FileExchange> { 040 private static final transient Log LOG = LogFactory.getLog(FileEndpoint.class); 041 private File file; 042 private FileProcessStrategy fileProcessStrategy; 043 private boolean autoCreate = true; 044 private boolean lock = true; 045 private boolean delete; 046 private boolean noop; 047 private boolean append = true; 048 private String moveNamePrefix; 049 private String moveNamePostfix; 050 private String[] excludedNamePrefixes = {"."}; 051 private String[] excludedNamePostfixes = {FileProcessStrategySupport.DEFAULT_LOCK_FILE_POSTFIX}; 052 private int bufferSize = 128 * 1024; 053 private boolean ignoreFileNameHeader; 054 055 protected FileEndpoint(File file, String endpointUri, FileComponent component) { 056 super(endpointUri, component); 057 this.file = file; 058 } 059 060 public FileEndpoint(String endpointUri, File file) { 061 super(endpointUri); 062 this.file = file; 063 } 064 065 public Producer<FileExchange> createProducer() throws Exception { 066 Producer<FileExchange> result = new FileProducer(this); 067 return result; 068 } 069 070 public Consumer<FileExchange> createConsumer(Processor processor) throws Exception { 071 Consumer<FileExchange> result = new FileConsumer(this, processor); 072 configureConsumer(result); 073 return result; 074 } 075 076 /** 077 * Create a new exchange for communicating with this endpoint 078 * 079 * @param file the file 080 * @return the created exchange 081 */ 082 public FileExchange createExchange(File file) { 083 return new FileExchange(getCamelContext(), getExchangePattern(), file); 084 } 085 086 public FileExchange createExchange() { 087 return createExchange(getFile()); 088 } 089 090 public FileExchange createExchange(ExchangePattern pattern) { 091 return new FileExchange(getCamelContext(), pattern, file); 092 } 093 094 /** 095 * Configures the given message with the file which sets the body to the file object 096 * and sets the {@link FileComponent#HEADER_FILE_NAME} header. 097 */ 098 public void configureMessage(File file, Message message) { 099 message.setBody(file); 100 String relativePath = file.getPath().substring(getFile().getPath().length()); 101 if (relativePath.startsWith(File.separator) || relativePath.startsWith("/")) { 102 relativePath = relativePath.substring(1); 103 } 104 message.setHeader(FileComponent.HEADER_FILE_NAME, relativePath); 105 } 106 107 public File getFile() { 108 if (autoCreate && !file.exists()) { 109 file.mkdirs(); 110 } 111 return file; 112 } 113 114 public boolean isSingleton() { 115 return true; 116 } 117 118 public boolean isAutoCreate() { 119 return this.autoCreate; 120 } 121 122 public void setAutoCreate(boolean autoCreate) { 123 this.autoCreate = autoCreate; 124 } 125 126 public FileProcessStrategy getFileStrategy() { 127 if (fileProcessStrategy == null) { 128 fileProcessStrategy = createFileStrategy(); 129 LOG.debug("Using file process strategy: " + fileProcessStrategy); 130 } 131 return fileProcessStrategy; 132 } 133 134 /** 135 * Sets the strategy to be used when the file has been processed such as 136 * deleting or renaming it etc. 137 * 138 * @param fileProcessStrategy the new strategy to use 139 */ 140 public void setFileStrategy(FileProcessStrategy fileProcessStrategy) { 141 this.fileProcessStrategy = fileProcessStrategy; 142 } 143 144 public boolean isDelete() { 145 return delete; 146 } 147 148 public void setDelete(boolean delete) { 149 this.delete = delete; 150 } 151 152 public boolean isLock() { 153 return lock; 154 } 155 156 public void setLock(boolean lock) { 157 this.lock = lock; 158 } 159 160 public String getMoveNamePostfix() { 161 return moveNamePostfix; 162 } 163 164 /** 165 * Sets the name postfix appended to moved files. For example to rename all 166 * the files from <tt>*</tt> to <tt>*.done</tt> set this value to <tt>.done</tt> 167 */ 168 public void setMoveNamePostfix(String moveNamePostfix) { 169 this.moveNamePostfix = moveNamePostfix; 170 } 171 172 public String getMoveNamePrefix() { 173 return moveNamePrefix; 174 } 175 176 /** 177 * Sets the name prefix appended to moved files. For example to move 178 * processed files into a hidden directory called <tt>.camel</tt> set this value to 179 * <tt>.camel/</tt> 180 */ 181 public void setMoveNamePrefix(String moveNamePrefix) { 182 this.moveNamePrefix = moveNamePrefix; 183 } 184 185 public String[] getExcludedNamePrefixes() { 186 return excludedNamePrefixes; 187 } 188 189 /** 190 * Sets the excluded file name prefixes, such as <tt>"."</tt> for hidden files which 191 * are excluded by default 192 */ 193 public void setExcludedNamePrefixes(String[] excludedNamePrefixes) { 194 this.excludedNamePrefixes = excludedNamePrefixes; 195 } 196 197 public String[] getExcludedNamePostfixes() { 198 return excludedNamePostfixes; 199 } 200 201 /** 202 * Sets the excluded file name postfixes, such as {@link FileProcessStrategySupport#DEFAULT_LOCK_FILE_POSTFIX} 203 * to ignore lock files by default. 204 */ 205 public void setExcludedNamePostfixes(String[] excludedNamePostfixes) { 206 this.excludedNamePostfixes = excludedNamePostfixes; 207 } 208 209 public boolean isNoop() { 210 return noop; 211 } 212 213 /** 214 * If set to true then the default {@link FileProcessStrategy} will be to use the 215 * {@link NoOpFileProcessStrategy} to not move or copy processed files 216 */ 217 public void setNoop(boolean noop) { 218 this.noop = noop; 219 } 220 221 public boolean isAppend() { 222 return append; 223 } 224 225 /** 226 * When writing do we append to the end of the file, or replace it? 227 * The default is to append 228 */ 229 public void setAppend(boolean append) { 230 this.append = append; 231 } 232 233 public int getBufferSize() { 234 return bufferSize; 235 } 236 237 /** 238 * Sets the buffer size used to read/write files 239 */ 240 public void setBufferSize(int bufferSize) { 241 this.bufferSize = bufferSize; 242 } 243 244 public boolean isIgnoreFileNameHeader() { 245 return ignoreFileNameHeader; 246 } 247 248 /** 249 * If this flag is enabled then producers will ignore the {@link FileComponent#HEADER_FILE_NAME} 250 * header and generate a new dynamic file 251 */ 252 public void setIgnoreFileNameHeader(boolean ignoreFileNameHeader) { 253 this.ignoreFileNameHeader = ignoreFileNameHeader; 254 } 255 256 /** 257 * A strategy method to lazily create the file strategy 258 */ 259 protected FileProcessStrategy createFileStrategy() { 260 return FileProcessStrategyFactory.createFileProcessStrategy(isNoop(), isDelete(), isLock(), moveNamePrefix, moveNamePostfix); 261 } 262 263 }