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 import java.io.Serializable; 021 022 import org.apache.camel.util.FileUtil; 023 import org.apache.camel.util.ObjectHelper; 024 import org.apache.commons.logging.Log; 025 import org.apache.commons.logging.LogFactory; 026 027 /** 028 * Generic File. Specific implementations of a file based endpoint need to 029 * provide a File for transfer. 030 */ 031 public class GenericFile<T> implements Cloneable, Serializable { 032 033 private static final Log LOG = LogFactory.getLog(GenericFile.class); 034 035 private String endpointPath; 036 private String fileName; 037 private String fileNameOnly; 038 private String relativeFilePath; 039 private String absoluteFilePath; 040 private long fileLength; 041 private long lastModified; 042 private T file; 043 private GenericFileBinding<T> binding; 044 private boolean absolute; 045 046 public char getFileSeparator() { 047 return File.separatorChar; 048 } 049 050 @Override 051 public GenericFile<T> clone() { 052 return copyFrom(this); 053 } 054 055 /** 056 * Creates a clone based on the source 057 * 058 * @param source the source 059 * @return a clone of the source 060 */ 061 @SuppressWarnings("unchecked") 062 public GenericFile<T> copyFrom(GenericFile<T> source) { 063 GenericFile<T> result; 064 try { 065 result = source.getClass().newInstance(); 066 } catch (Exception e) { 067 throw ObjectHelper.wrapRuntimeCamelException(e); 068 } 069 result.setEndpointPath(source.getEndpointPath()); 070 result.setAbsolute(source.isAbsolute()); 071 result.setAbsoluteFilePath(source.getAbsoluteFilePath()); 072 result.setRelativeFilePath(source.getRelativeFilePath()); 073 result.setFileName(source.getFileName()); 074 result.setFileNameOnly(source.getFileNameOnly()); 075 result.setFileLength(source.getFileLength()); 076 result.setLastModified(source.getLastModified()); 077 result.setFile(source.getFile()); 078 result.setBody(source.getBody()); 079 result.setBinding(source.getBinding()); 080 return result; 081 } 082 083 protected boolean isAbsolute(String name) { 084 File file = new File(name); 085 return file.isAbsolute(); 086 } 087 088 protected String normalizePath(String name) { 089 return FileUtil.normalizePath(name); 090 } 091 092 /** 093 * Changes the name of this remote file. This method alters the absolute and 094 * relative names as well. 095 * 096 * @param newName the new name 097 */ 098 public void changeFileName(String newName) { 099 if (LOG.isTraceEnabled()) { 100 LOG.trace("Changing name to: " + newName); 101 } 102 103 // Make sure the newName is normalized. 104 String newFileName = normalizePath(newName); 105 106 if (LOG.isTraceEnabled()) { 107 LOG.trace("Normalized endpointPath: " + endpointPath); 108 LOG.trace("Normalized newFileName: " + newFileName); 109 } 110 111 File file = new File(newFileName); 112 if (!absolute) { 113 // for relative then we should avoid having the endpoint path duplicated so clip it 114 if (ObjectHelper.isNotEmpty(endpointPath) && newFileName.startsWith(endpointPath)) { 115 // clip starting endpoint in case it was added 116 newFileName = ObjectHelper.after(newFileName, endpointPath + getFileSeparator()); 117 118 // reconstruct file with clipped name 119 file = new File(newFileName); 120 } 121 } 122 123 // store the file name only 124 setFileNameOnly(file.getName()); 125 setFileName(file.getName()); 126 127 // relative path 128 if (file.getParent() != null) { 129 setRelativeFilePath(file.getParent() + getFileSeparator() + file.getName()); 130 } else { 131 setRelativeFilePath(file.getName()); 132 } 133 134 // absolute path 135 if (isAbsolute(newFileName)) { 136 setAbsolute(true); 137 setAbsoluteFilePath(newFileName); 138 } else { 139 setAbsolute(false); 140 // construct a pseudo absolute filename that the file operations uses even for relative only 141 String path = ObjectHelper.isEmpty(endpointPath) ? "" : endpointPath + getFileSeparator(); 142 setAbsoluteFilePath(path + getRelativeFilePath()); 143 } 144 145 if (LOG.isTraceEnabled()) { 146 LOG.trace("FileNameOnly: " + getFileNameOnly()); 147 LOG.trace("FileName: " + getFileName()); 148 LOG.trace("Absolute: " + isAbsolute()); 149 LOG.trace("Relative path: " + getRelativeFilePath()); 150 LOG.trace("Absolute path: " + getAbsoluteFilePath()); 151 LOG.trace("Name changed to: " + this); 152 } 153 } 154 155 public String getRelativeFilePath() { 156 return relativeFilePath; 157 } 158 159 public void setRelativeFilePath(String relativeFilePath) { 160 this.relativeFilePath = normalizePathToProtocol(relativeFilePath); 161 } 162 163 public String getFileName() { 164 return fileName; 165 } 166 167 public void setFileName(String fileName) { 168 this.fileName = normalizePathToProtocol(fileName); 169 } 170 171 public long getFileLength() { 172 return fileLength; 173 } 174 175 public void setFileLength(long fileLength) { 176 this.fileLength = fileLength; 177 } 178 179 public long getLastModified() { 180 return lastModified; 181 } 182 183 public void setLastModified(long lastModified) { 184 this.lastModified = lastModified; 185 } 186 187 public T getFile() { 188 return file; 189 } 190 191 public void setFile(T file) { 192 this.file = file; 193 } 194 195 public Object getBody() { 196 return getBinding().getBody(this); 197 } 198 199 public void setBody(Object os) { 200 getBinding().setBody(this, os); 201 } 202 203 public String getParent() { 204 String parent; 205 if (isAbsolute()) { 206 String name = getAbsoluteFilePath(); 207 File path = new File(name); 208 parent = path.getParent(); 209 } else { 210 String name = getRelativeFilePath(); 211 File path = new File(endpointPath, name); 212 parent = path.getParent(); 213 } 214 return normalizePathToProtocol(parent); 215 } 216 217 public GenericFileBinding<T> getBinding() { 218 if (binding == null) { 219 binding = new GenericFileDefaultBinding<T>(); 220 } 221 return binding; 222 } 223 224 public void setBinding(GenericFileBinding<T> binding) { 225 this.binding = binding; 226 } 227 228 public void setAbsoluteFilePath(String absoluteFilePath) { 229 this.absoluteFilePath = normalizePathToProtocol(absoluteFilePath); 230 } 231 232 public String getAbsoluteFilePath() { 233 return absoluteFilePath; 234 } 235 236 public boolean isAbsolute() { 237 return absolute; 238 } 239 240 public void setAbsolute(boolean absolute) { 241 this.absolute = absolute; 242 } 243 244 public String getEndpointPath() { 245 return endpointPath; 246 } 247 248 public void setEndpointPath(String endpointPath) { 249 this.endpointPath = normalizePathToProtocol(endpointPath); 250 } 251 252 public String getFileNameOnly() { 253 return fileNameOnly; 254 } 255 256 public void setFileNameOnly(String fileNameOnly) { 257 this.fileNameOnly = fileNameOnly; 258 } 259 260 /** 261 * Fixes the path separator to be according to the protocol 262 */ 263 protected String normalizePathToProtocol(String path) { 264 if (ObjectHelper.isEmpty(path)) { 265 return path; 266 } 267 path = path.replace('/', getFileSeparator()); 268 path = path.replace('\\', getFileSeparator()); 269 return path; 270 } 271 272 @Override 273 public String toString() { 274 return "GenericFile[" + (absolute ? absoluteFilePath : relativeFilePath) + "]"; 275 } 276 277 }