001/*
002 * #%L
003 * Netarchivesuite - common
004 * %%
005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library,
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023package dk.netarkivet.common.tools;
024
025import java.io.File;
026import java.io.IOException;
027
028import org.archive.io.arc.ARCWriter;
029
030import dk.netarkivet.common.exceptions.IOFailure;
031import dk.netarkivet.common.utils.FileUtils;
032import dk.netarkivet.common.utils.arc.ARCUtils;
033
034/**
035 * Command line tool for merging several ARC files into a single ARC file.
036 * <p>
037 * Usage: java dk.netarkivet.common.tools.ArcMerge file1 [file2] ... > myarchive.arc
038 * <p>
039 * Note: Does not depend on logging - communicates failure on stderr
040 */
041public class ArcMerge extends ToolRunnerBase {
042
043    /**
044     * Main method. Reads all ARC files specified (as arguments) and outputs a merged ARC file on stdout.
045     *
046     * @param args The command line arguments should be a list of ARC files to be merged. At least one input ARC file
047     * should be given.
048     */
049    public static void main(String[] args) {
050        ArcMerge instance = new ArcMerge();
051        instance.runTheTool(args);
052    }
053
054    protected SimpleCmdlineTool makeMyTool() {
055        return new ArcMergeTool();
056    }
057
058    private static class ArcMergeTool implements SimpleCmdlineTool {
059
060        /**
061         * This instance is declared outside of run method to ensure reliable teardown in ase of exceptions during
062         * execution.
063         */
064        private ARCWriter aw;
065
066        /**
067         * Accept only at least one parameter.
068         *
069         * @param args the arguments
070         * @return false, if length of args is zero; returns true otherwise
071         */
072        public boolean checkArgs(String... args) {
073            return args.length > 0;
074        }
075
076        /**
077         * Create the ARCWriter instance here for reliable execution of close method in teardown.
078         *
079         * @param args the arguments (presently not used)
080         */
081        public void setUp(String... args) {
082            try {
083                // The name "dummy.arc" is used for the first (file metadata)
084                // record
085                aw = ARCUtils.getToolsARCWriter(System.out, new File("dummy.arc"));
086            } catch (IOException e) {
087                throw new IOFailure(e.getMessage());
088            }
089        }
090
091        /**
092         * Ensure reliable execution of the ARCWriter.close() method. Remember to check if aw was actually created.
093         */
094        public void tearDown() {
095            try {
096                if (aw != null) {
097                    aw.close();
098                }
099            } catch (IOException e) {
100                throw new IOFailure(e.getMessage());
101            }
102        }
103
104        /**
105         * Perform the actual work. Iterate over the input files passed in args (from command line), inert in file and
106         * close. Creating and closing the ARCWriter is done in setup and teardown methods.
107         *
108         * @param args the input files (represented as a String array)
109         */
110        public void run(String... args) {
111            for (String s : args) {
112                ARCUtils.insertARCFile(FileUtils.makeValidFileFromExisting(s), aw);
113            }
114        }
115
116        /**
117         * Return the list of parameters accepted by the ArcMergeTool class.
118         *
119         * @return the list of parameters accepted.
120         */
121        public String listParameters() {
122            return "file1 [file2] ...";
123        }
124    }
125}