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.FileOutputStream;
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.RandomAccessFile;
024    import java.nio.ByteBuffer;
025    import java.nio.channels.FileChannel;
026    
027    import org.apache.camel.Exchange;
028    import org.apache.camel.Message;
029    import org.apache.camel.Producer;
030    import org.apache.camel.impl.DefaultProducer;
031    import org.apache.camel.util.ExchangeHelper;
032    import org.apache.commons.logging.Log;
033    import org.apache.commons.logging.LogFactory;
034    
035    /**
036     * A {@link Producer} implementation for File
037     *
038     * @version $Revision: 640438 $
039     */
040    public class FileProducer extends DefaultProducer {
041        private static final transient Log LOG = LogFactory.getLog(FileProducer.class);
042        private final FileEndpoint endpoint;
043    
044        public FileProducer(FileEndpoint endpoint) {
045            super(endpoint);
046            this.endpoint = endpoint;
047        }
048    
049        public FileEndpoint getEndpoint() {
050            return (FileEndpoint) super.getEndpoint();
051        }
052    
053        /**
054         * @param exchange
055         * @see org.apache.camel.Processor#process(Exchange)
056         */
057        public void process(Exchange exchange) throws Exception {
058            // TODO is it really worth using a FileExchange as the core type?
059            FileExchange fileExchange = endpoint.createExchange(exchange);
060            process(fileExchange);
061            ExchangeHelper.copyResults(exchange, fileExchange);
062        }
063    
064        public void process(FileExchange exchange) throws Exception {
065            if (ExchangeHelper.isOutCapable(exchange)) {
066                // lets poll the file
067                Message out = exchange.getOut(true);
068                endpoint.configureMessage(endpoint.getFile(), out);
069                return;
070            }
071            InputStream in = ExchangeHelper.getMandatoryInBody(exchange, InputStream.class);
072            File file = createFileName(exchange.getIn());
073            buildDirectory(file);
074            if (LOG.isDebugEnabled()) {
075                LOG.debug("About to write to: " + file + " from exchange: " + exchange);
076            }
077            FileChannel fc = null;
078            try {
079                if (getEndpoint().isAppend()) {
080                    fc = new RandomAccessFile(file, "rw").getChannel();
081                    fc.position(fc.size());
082                } else {
083                    fc = new FileOutputStream(file).getChannel();
084                }
085                int size = getEndpoint().getBufferSize();
086                byte[] buffer = new byte[size];
087                ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
088                while (true) {
089                    int count = in.read(buffer);
090                    if (count <= 0) {
091                        break;
092                    } else if (count < size) {
093                        byteBuffer = ByteBuffer.wrap(buffer, 0, count);
094                        fc.write(byteBuffer);
095                        break;
096                    } else {
097                        fc.write(byteBuffer);
098                        byteBuffer.clear();
099                    }
100                }
101            } finally {
102                if (in != null) {
103                    try {
104                        in.close();
105                    } catch (IOException e) {
106                        LOG.warn("Failed to close input: " + e, e);
107                    }
108                }
109                if (fc != null) {
110                    try {
111                        fc.close();
112                    } catch (IOException e) {
113                        LOG.warn("Failed to close output: " + e, e);
114                    }
115                }
116            }
117            /*
118            ByteBuffer payload = exchange.getIn().getBody(ByteBuffer.class);
119            if (payload == null) {
120                InputStream in = ExchangeHelper.getMandatoryInBody(exchange, InputStream.class);
121                payload = ExchangeHelper.convertToMandatoryType(exchange, ByteBuffer.class, in);
122            }
123            payload.flip();
124            File file = createFileName(exchange);
125            buildDirectory(file);
126            if (LOG.isDebugEnabled()) {
127                LOG.debug("Creating file: " + file);
128            }
129            FileChannel fc = null;
130            try {
131                if (getEndpoint().isAppend()) {
132                    fc = new RandomAccessFile(file, "rw").getChannel();
133                    fc.position(fc.size());
134                }
135                else {
136                    fc = new FileOutputStream(file).getChannel();
137                }
138                fc.write(payload);
139            }
140            catch (Throwable e) {
141                LOG.error("Failed to write to File: " + file, e);
142            }
143            finally {
144                if (fc != null) {
145                    fc.close();
146                }
147            }
148            */
149        }
150    
151        protected File createFileName(Message message) {
152            File answer;
153            File endpointFile = endpoint.getFile();
154            String name = null;
155            if (!endpoint.isIgnoreFileNameHeader()) {
156                name = message.getHeader(FileComponent.HEADER_FILE_NAME, String.class);
157            }
158            if (endpointFile.isDirectory()) {
159                if (name != null) {
160                    answer = new File(endpointFile, name);
161                    if (answer.isDirectory()) {
162                        answer = new File(answer, message.getMessageId());
163                    }
164                } else {
165                    answer = new File(endpointFile, message.getMessageId());
166                }
167            } else {
168                if (name == null) {
169                    answer = endpointFile;
170                } else {
171                    answer = new File(endpointFile, name);
172                }
173            }
174            return answer;
175        }
176    
177        private void buildDirectory(File file) {
178            String dirName = file.getAbsolutePath();
179            int index = dirName.lastIndexOf(File.separatorChar);
180            if (index > 0) {
181                dirName = dirName.substring(0, index);
182                File dir = new File(dirName);
183                dir.mkdirs();
184            }
185        }
186    }