001    /*
002     * 
003     * $Revision: 13085 $ $Date: 2008-02-06 18:27:24 +0100 (Mi, 06 Feb 2008) $
004     *
005     * This file is part of ***  M y C o R e  ***
006     * See http://www.mycore.de/ for details.
007     *
008     * This program is free software; you can use it, redistribute it
009     * and / or modify it under the terms of the GNU General Public License
010     * (GPL) as published by the Free Software Foundation; either version 2
011     * of the License or (at your option) any later version.
012     *
013     * This program is distributed in the hope that it will be useful, but
014     * WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program, in a file called gpl.txt or license.txt.
020     * If not, write to the Free Software Foundation Inc.,
021     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
022     */
023    
024    package org.mycore.backend.videocharger;
025    
026    import java.io.ByteArrayInputStream;
027    import java.io.ByteArrayOutputStream;
028    import java.io.File;
029    import java.io.FileOutputStream;
030    import java.io.InputStream;
031    import java.io.OutputStream;
032    
033    import org.apache.log4j.Logger;
034    import org.mycore.common.MCRConfiguration;
035    import org.mycore.common.MCRPersistenceException;
036    import org.mycore.datamodel.ifs.MCRContentInputStream;
037    import org.mycore.datamodel.ifs.MCRContentStore;
038    import org.mycore.datamodel.ifs.MCRFileReader;
039    
040    import com.enterprisedt.net.ftp.FTPClient;
041    import com.enterprisedt.net.ftp.FTPTransferType;
042    
043    /**
044     * This class implements the MCRContentStore interface to store the content of
045     * MCRFile objects in IBM VideoCharger Server. This allows the content to be
046     * streamed. This implementation uses FTP to manage the files in VideoCharger.
047     * The FTP connection parameters are configured in mycore.properties:
048     * 
049     * <code>
050     *   MCR.IFS.ContentStore.<StoreID>.Hostname   Hostname of VideoCharger Server
051     *   MCR.IFS.ContentStore.<StoreID>.FTPPort    Port of VideoCharger FTP interface, default is 4324
052     *   MCR.IFS.ContentStore.<StoreID>.UserID     User ID for FTP connections, e. g. vsloader
053     *   MCR.IFS.ContentStore.<StoreID>.Password   Password for this user
054     *   MCR.IFS.ContentStore.<StoreID>.DebugFTP   If true, FTP debug messages are written to stdout, default is false
055     *   MCR.IFS.ContentStore.<StoreID>.AssetGroup Asset group, default is 'AG'
056     * </code>
057     * 
058     * This class also provides a method to backup all assets stored in VideoCharger
059     * to a directory.
060     * 
061     * @author Frank Lützenkirchen
062     * @version $Revision: 13085 $ $Date: 2008-02-06 18:27:24 +0100 (Mi, 06 Feb 2008) $
063     * 
064     * @see MCRAVExtVideoCharger
065     */
066    public class MCRCStoreVideoCharger extends MCRContentStore {
067        private static Logger logger = Logger.getLogger(MCRCStoreVideoCharger.class.getName());
068    
069        /** Hostname of VideoCharger server */
070        protected String host;
071    
072        /** Port of VideoCharger server FTP interface */
073        protected int port;
074    
075        /** User ID for FTP login */
076        protected String user;
077    
078        /** Password for FTP login */
079        protected String password;
080    
081        /** If true, FTP debug messages are written to stdout */
082        protected boolean debugFTP;
083        
084        /** Asset group **/
085        protected String assetGroup;
086    
087        /** FTP Return code if "quote site avs attr" is successful */
088        protected final static String[] ok = { "200" };
089    
090        public void init(String storeID) {
091            super.init(storeID);
092    
093            MCRConfiguration config = MCRConfiguration.instance();
094    
095            host = config.getString(prefix + "Hostname");
096            port = config.getInt(prefix + "FTPPort", 4324);
097            user = config.getString(prefix + "UserID");
098            password = config.getString(prefix + "Password");
099            debugFTP = config.getBoolean(prefix + "DebugFTP", false);
100            assetGroup = config.getString(prefix + "AssetGroup", "AG" );
101        }
102    
103        protected String doStoreContent(MCRFileReader file, MCRContentInputStream source) throws Exception {
104            String storageID = buildNextID(file);
105    
106            FTPClient connection = connect();
107    
108            try {
109                connection.quote("site avs attr assetgroup=" + assetGroup, ok);
110                connection.quote("site avs attr title=" + storageID, ok);
111                connection.put(source, storageID);
112    
113                return storageID;
114            } finally {
115                disconnect(connection);
116            }
117        }
118    
119        protected void doDeleteContent(String storageID) throws Exception {
120            FTPClient connection = connect();
121    
122            try {
123                connection.quote("site avs attr assetgroup=" + assetGroup, ok);
124                connection.delete(storageID);
125            } finally {
126                disconnect(connection);
127            }
128        }
129    
130        protected void doRetrieveContent(MCRFileReader file, OutputStream target) throws Exception {
131            retrieveContent(file.getStorageID(), target);
132        }
133    
134        protected InputStream doRetrieveContent(MCRFileReader file) throws Exception {
135            //FTPClient does not provide GET and InputStreams, we need to copy
136            ByteArrayOutputStream bout=new ByteArrayOutputStream();
137            doRetrieveContent(file, bout);
138            bout.close();
139            return new ByteArrayInputStream(bout.toByteArray());
140        }
141    
142        protected void retrieveContent(String assetID, OutputStream target) throws Exception {
143            FTPClient connection = connect();
144    
145            try {
146                connection.quote("site avs attr assetgroup=" + assetGroup, ok);
147                connection.get(target, assetID);
148            } finally {
149                disconnect(connection);
150            }
151        }
152    
153        /**
154         * Reads all assets stored in VideoCharger server and writes the contents to
155         * a directory for backup. If the directory already contains an asset with
156         * the same name, that assets is skipped and not backed up.
157         * 
158         * @param storeID
159         *            the store ID fo the VideoCharger store to be backed up
160         * @param directory
161         *            the local directory to write the assets to
162         */
163        public static void backupContentTo(String storeID, String directory) throws MCRPersistenceException, Exception {
164            MCRAVExtVideoCharger extender = new MCRAVExtVideoCharger();
165            extender.readConfig(storeID);
166            MCRCStoreVideoCharger store = new MCRCStoreVideoCharger();
167            store.init( storeID );
168    
169            String[] list = extender.listAssets();
170    
171            for (int i = 0; i < list.length; i++) {
172                logger.info("Backup of asset with ID = " + list[i]);
173    
174                File local = new File(directory, list[i]);
175    
176                if (local.exists()) {
177                    continue;
178                }
179    
180                FileOutputStream target = new FileOutputStream(local);
181                store.retrieveContent(list[i], target);
182                target.close();
183            }
184        }
185    
186        /**
187         * Connects to IBM VideoCharger Server via FTP
188         */
189        protected FTPClient connect() throws MCRPersistenceException {
190            try {
191                FTPClient connection = new FTPClient(host, port);
192                connection.debugResponses(debugFTP);
193                connection.login(user, password);
194                connection.setType(FTPTransferType.BINARY);
195    
196                return connection;
197            } catch (Exception exc) {
198                String msg = "Could not connect to " + host + ":" + port + " via FTP";
199                throw new MCRPersistenceException(msg, exc);
200            }
201        }
202    
203        /**
204         * Closes the FTP connection to VideoCharger server
205         * 
206         * @param connection
207         *            the FTP connection to close
208         */
209        protected void disconnect(FTPClient connection) {
210            try {
211                connection.quit();
212            } catch (Exception ignored) {
213            }
214        }
215    }