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.servicemix.vfs;
018    
019    import java.io.IOException;
020    import java.io.OutputStream;
021    
022    import javax.jbi.messaging.MessageExchange;
023    import javax.jbi.messaging.MessagingException;
024    import javax.jbi.messaging.NormalizedMessage;
025    
026    import org.apache.commons.logging.Log;
027    import org.apache.commons.logging.LogFactory;
028    import org.apache.commons.vfs.FileContent;
029    import org.apache.commons.vfs.FileObject;
030    import org.apache.commons.vfs.FileSystemManager;
031    import org.apache.servicemix.common.endpoints.ProviderEndpoint;
032    import org.apache.servicemix.components.util.DefaultFileMarshaler;
033    import org.apache.servicemix.components.util.FileMarshaler;
034    
035    /**
036     * An endpoint which receives messages from the NMR and writes the message to 
037     * the virtual file system.
038     *
039     * @org.apache.xbean.XBean element="sender"
040     * 
041     * @author lhein
042     */
043    public class VFSSendingEndpoint extends ProviderEndpoint implements VFSEndpointType {
044        private static final Log logger = LogFactory.getLog(VFSSendingEndpoint.class);
045    
046        private FileObject file;
047        private FileMarshaler marshaler = new DefaultFileMarshaler();
048        private String path;
049        private FileSystemManager fileSystemManager;
050    
051        /**
052         * resolves the given path to a file object
053         */
054        protected void resolvePath() throws Exception {
055            if (file == null) {
056                    file = FileObjectResolver.resolveToFileObject(getFileSystemManager(), getPath());
057            }
058        }
059        
060        @Override
061        protected void processInOnly(MessageExchange exchange, NormalizedMessage in)
062                    throws Exception {
063            // resolve the file path
064            resolvePath();
065            
066            OutputStream out = null;
067            String tmpName = null;
068            String name = null;
069            FileObject tmpFile = null;
070            FileObject newFile = null;
071            FileContent content = null;
072            try {
073                name = marshaler.getOutputName(exchange, in);
074                if (name == null) {
075                    throw new MessagingException("No output name available. Cannot output message!");
076                }
077                tmpName = marshaler.getTempOutputName(exchange, in);
078                file.close(); // remove any cached informations
079                if (tmpName != null) {
080                    // writing to temp file first
081                    tmpFile = tmpName != null ? file.resolveFile(tmpName) : null;
082                    tmpFile.close();
083                    content = tmpFile.getContent();
084                } else {
085                    // writing to target file
086                    newFile = file.resolveFile(name);
087                    newFile.close(); // remove any cached informations
088                    content = newFile.getContent();
089                }
090                // remove any cached informations
091                content.close();
092                if (content != null) {
093                    out = content.getOutputStream();
094                }
095                if (out == null) {
096                    throw new MessagingException("No output stream available for output name: " + name);
097                }
098                marshaler.writeMessage(exchange, in, out, name);
099            }
100            finally {
101                if (out != null) {
102                    try {
103                        out.close();
104                    }
105                    catch (IOException e) {
106                        logger.error("Caught exception while closing stream on error: " + e, e);
107                    }
108                }
109                if (tmpName != null && name != null && !name.equals(tmpName)) {
110                    if (!tmpFile.canRenameTo(newFile)) {
111                            throw new IOException("File " + tmpName + " could not be renamed to " + name);
112                    } else {
113                            tmpFile.moveTo(newFile);
114                    }
115                }
116            }
117        }
118        
119        /**
120         * Specifies a <code>String</code> object representing the path of the 
121         * file/folder to be polled.<br /><br />
122         * <b><u>Examples:</u></b><br />
123         * <ul>
124         *  <li>file:///home/lhein/pollFolder</li>
125         *  <li>zip:file:///home/lhein/pollFolder/myFile.zip</li>
126         *  <li>jar:http://www.myhost.com/files/Examples.jar</li>
127         *  <li>jar:../lib/classes.jar!/META-INF/manifest.mf</li>
128         *  <li>tar:gz:http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt</li>
129         *  <li>tgz:file://anyhost/dir/mytar.tgz!/somepath/somefile</li>
130         *  <li>gz:/my/gz/file.gz</li>
131         *  <li>http://myusername@somehost/index.html</li>
132         *  <li>webdav://somehost:8080/dist</li>
133         *  <li>ftp://myusername:mypassword@somehost/pub/downloads/somefile.tgz</li>
134         *  <li>sftp://myusername:mypassword@somehost/pub/downloads/somefile.tgz</li>
135         *  <li>smb://somehost/home</li>
136         *  <li>tmp://dir/somefile.txt</li>
137         *  <li>res:path/in/classpath/image.png</li>
138         *  <li>ram:///any/path/to/file.txt</li>
139         *  <li>mime:file:///your/path/mail/anymail.mime!/filename.pdf</li>
140         * </ul>
141         * 
142         * For further details have a look at {@link http://commons.apache.org/vfs/filesystems.html}.
143         * <br /><br />
144         * 
145         * @param path a <code>String</code> object that represents a file/folder/vfs
146         */
147        public void setPath(String path) {
148            this.path = path;
149        }
150    
151        public String getPath() {
152            return this.path;
153        }
154    
155        /**
156         * sets the file system manager
157         * 
158         * @param fileSystemManager the file system manager
159         */
160        public void setFileSystemManager(FileSystemManager fileSystemManager) {
161            this.fileSystemManager = fileSystemManager;
162        }
163    
164        public FileSystemManager getFileSystemManager() {
165            return this.fileSystemManager;
166        }
167    
168        /**
169         * Specifies a <code>FileMarshaler</code> object that will marshal file data
170         * into the NMR. The default file marshaller can read valid XML data.
171         * <code>FileMarshaler</code> objects are implementations of
172         * <code>org.apache.servicemix.components.util.FileMarshaler</code>.
173         * 
174         * @param marshaler a <code>FileMarshaler</code> object that can read data
175         *            from the file system.
176         */
177        public void setMarshaler(FileMarshaler marshaler) {
178            this.marshaler = marshaler;
179        }
180    
181        public FileMarshaler getMarshaler() {
182            return marshaler;
183        }
184    }