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 }