blob: ead41ea3c385a64f1cba998be018992f1ccf7a90 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.file;
import java.io.File;
import java.util.Date;
import java.util.Map;
import org.apache.camel.Exchange;
import org.apache.camel.util.FileUtil;
import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Generic File. Specific implementations of a file based endpoint need to
* provide a File for transfer.
*/
public class GenericFile<T> {
private static final transient Logger LOG = LoggerFactory.getLogger(GenericFile.class);
private String endpointPath;
private String fileName;
private String fileNameOnly;
private String relativeFilePath;
private String absoluteFilePath;
private long fileLength;
private long lastModified;
private T file;
private GenericFileBinding<T> binding;
private boolean absolute;
public char getFileSeparator() {
return File.separatorChar;
}
/**
* Creates a copy based on the source
*
* @param source the source
* @return a copy of the source
*/
@SuppressWarnings("unchecked")
public GenericFile<T> copyFrom(GenericFile<T> source) {
GenericFile<T> result;
try {
result = source.getClass().newInstance();
} catch (Exception e) {
throw ObjectHelper.wrapRuntimeCamelException(e);
}
result.setEndpointPath(source.getEndpointPath());
result.setAbsolute(source.isAbsolute());
result.setAbsoluteFilePath(source.getAbsoluteFilePath());
result.setRelativeFilePath(source.getRelativeFilePath());
result.setFileName(source.getFileName());
result.setFileNameOnly(source.getFileNameOnly());
result.setFileLength(source.getFileLength());
result.setLastModified(source.getLastModified());
result.setFile(source.getFile());
result.setBody(source.getBody());
result.setBinding(source.getBinding());
copyFromPopulateAdditional(source, result);
return result;
}
/**
* Copies additional information from the source to the result.
* <p/>
* Inherited classes can override this method and copy their specific data.
*
* @param source the source
* @param result the result
*/
public void copyFromPopulateAdditional(GenericFile<T> source, GenericFile<T> result) {
// noop
}
/**
* Bind this GenericFile to an Exchange
*/
public void bindToExchange(Exchange exchange) {
Map<String, Object> headers;
exchange.setProperty(FileComponent.FILE_EXCHANGE_FILE, this);
GenericFileMessage<T> msg = new GenericFileMessage<T>(this);
if (exchange.hasOut()) {
headers = exchange.getOut().hasHeaders() ? exchange.getOut().getHeaders() : null;
exchange.setOut(msg);
} else {
headers = exchange.getIn().hasHeaders() ? exchange.getIn().getHeaders() : null;
exchange.setIn(msg);
}
// preserve any existing (non file) headers, before we re-populate headers
if (headers != null) {
msg.setHeaders(headers);
// remove any file related headers, as we will re-populate file headers
msg.removeHeaders("CamelFile*");
}
populateHeaders(msg);
}
/**
* Populates the {@link GenericFileMessage} relevant headers
*
* @param message the message to populate with headers
*/
public void populateHeaders(GenericFileMessage<T> message) {
if (message != null) {
message.setHeader(Exchange.FILE_NAME_ONLY, getFileNameOnly());
message.setHeader(Exchange.FILE_NAME, getFileName());
message.setHeader("CamelFileAbsolute", isAbsolute());
message.setHeader("CamelFileAbsolutePath", getAbsoluteFilePath());
if (isAbsolute()) {
message.setHeader(Exchange.FILE_PATH, getAbsoluteFilePath());
} else {
// we must normalize path according to protocol if we build our own paths
String path = normalizePathToProtocol(getEndpointPath() + File.separator + getRelativeFilePath());
message.setHeader(Exchange.FILE_PATH, path);
}
message.setHeader("CamelFileRelativePath", getRelativeFilePath());
message.setHeader(Exchange.FILE_PARENT, getParent());
if (getFileLength() >= 0) {
message.setHeader("CamelFileLength", getFileLength());
}
if (getLastModified() > 0) {
message.setHeader(Exchange.FILE_LAST_MODIFIED, new Date(getLastModified()));
}
}
}
protected boolean isAbsolute(String name) {
return FileUtil.isAbsolute(new File(name));
}
protected String normalizePath(String name) {
return FileUtil.normalizePath(name);
}
/**
* Changes the name of this remote file. This method alters the absolute and
* relative names as well.
*
* @param newName the new name
*/
public void changeFileName(String newName) {
LOG.trace("Changing name to: {}", newName);
// Make sure the newName is normalized.
String newFileName = normalizePath(newName);
LOG.trace("Normalized endpointPath: {}", endpointPath);
LOG.trace("Normalized newFileName: ()", newFileName);
File file = new File(newFileName);
if (!absolute) {
// for relative then we should avoid having the endpoint path duplicated so clip it
if (ObjectHelper.isNotEmpty(endpointPath) && newFileName.startsWith(endpointPath)) {
// clip starting endpoint in case it was added
if (endpointPath.endsWith("" + getFileSeparator())) {
newFileName = ObjectHelper.after(newFileName, endpointPath);
} else {
newFileName = ObjectHelper.after(newFileName, endpointPath + getFileSeparator());
}
// reconstruct file with clipped name
file = new File(newFileName);
}
}
// store the file name only
setFileNameOnly(file.getName());
setFileName(file.getName());
// relative path
if (file.getParent() != null) {
setRelativeFilePath(file.getParent() + getFileSeparator() + file.getName());
} else {
setRelativeFilePath(file.getName());
}
// absolute path
if (isAbsolute(newFileName)) {
setAbsolute(true);
setAbsoluteFilePath(newFileName);
} else {
setAbsolute(false);
// construct a pseudo absolute filename that the file operations uses even for relative only
String path = ObjectHelper.isEmpty(endpointPath) ? "" : endpointPath + getFileSeparator();
setAbsoluteFilePath(path + getRelativeFilePath());
}
if (LOG.isTraceEnabled()) {
LOG.trace("FileNameOnly: {}", getFileNameOnly());
LOG.trace("FileName: {}", getFileName());
LOG.trace("Absolute: {}", isAbsolute());
LOG.trace("Relative path: {}", getRelativeFilePath());
LOG.trace("Absolute path: {}", getAbsoluteFilePath());
LOG.trace("Name changed to: {}", this);
}
}
public String getRelativeFilePath() {
return relativeFilePath;
}
public void setRelativeFilePath(String relativeFilePath) {
this.relativeFilePath = normalizePathToProtocol(relativeFilePath);
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = normalizePathToProtocol(fileName);
}
public long getFileLength() {
return fileLength;
}
public void setFileLength(long fileLength) {
this.fileLength = fileLength;
}
public long getLastModified() {
return lastModified;
}
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
public T getFile() {
return file;
}
public void setFile(T file) {
this.file = file;
}
public Object getBody() {
return getBinding().getBody(this);
}
public void setBody(Object os) {
getBinding().setBody(this, os);
}
public String getParent() {
String parent;
if (isAbsolute()) {
String name = getAbsoluteFilePath();
File path = new File(name);
parent = path.getParent();
} else {
String name = getRelativeFilePath();
File path = new File(endpointPath, name);
parent = path.getParent();
}
return normalizePathToProtocol(parent);
}
public GenericFileBinding<T> getBinding() {
if (binding == null) {
binding = new GenericFileDefaultBinding<T>();
}
return binding;
}
public void setBinding(GenericFileBinding<T> binding) {
this.binding = binding;
}
public void setAbsoluteFilePath(String absoluteFilePath) {
this.absoluteFilePath = normalizePathToProtocol(absoluteFilePath);
}
public String getAbsoluteFilePath() {
return absoluteFilePath;
}
public boolean isAbsolute() {
return absolute;
}
public void setAbsolute(boolean absolute) {
this.absolute = absolute;
}
public String getEndpointPath() {
return endpointPath;
}
public void setEndpointPath(String endpointPath) {
this.endpointPath = normalizePathToProtocol(endpointPath);
}
public String getFileNameOnly() {
return fileNameOnly;
}
public void setFileNameOnly(String fileNameOnly) {
this.fileNameOnly = fileNameOnly;
}
/**
* Fixes the path separator to be according to the protocol
*/
protected String normalizePathToProtocol(String path) {
if (ObjectHelper.isEmpty(path)) {
return path;
}
path = path.replace('/', getFileSeparator());
path = path.replace('\\', getFileSeparator());
return path;
}
@Override
public String toString() {
return "GenericFile[" + (absolute ? absoluteFilePath : relativeFilePath) + "]";
}
}