001/*
002 * #%L
003 * Netarchivesuite - archive
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 */
023
024package dk.netarkivet.archive.tools;
025
026import java.io.BufferedReader;
027import java.io.File;
028import java.io.IOException;
029import java.io.InputStream;
030import java.io.InputStreamReader;
031import java.net.URI;
032import java.net.URISyntaxException;
033
034import dk.netarkivet.common.distribute.JMSConnectionFactory;
035import dk.netarkivet.common.distribute.arcrepository.ARCLookup;
036import dk.netarkivet.common.distribute.arcrepository.ArcRepositoryClientFactory;
037import dk.netarkivet.common.distribute.arcrepository.ResultStream;
038import dk.netarkivet.common.distribute.arcrepository.ViewerArcRepositoryClient;
039import dk.netarkivet.common.exceptions.ArgumentNotValid;
040import dk.netarkivet.common.exceptions.IOFailure;
041import dk.netarkivet.common.exceptions.NetarkivetException;
042import dk.netarkivet.common.tools.SimpleCmdlineTool;
043import dk.netarkivet.common.tools.ToolRunnerBase;
044
045/**
046 * A command-line tool to get ARC records from the bitarchive. Requires an Lucene index file
047 * <p>
048 * Usage: java dk.netarkivet.archive.tools.GetRecord indexfile uri > myrecord.arcrec
049 */
050
051public class GetRecord extends ToolRunnerBase {
052
053    /**
054     * Main method. Reads a record from the bitarchive and copies it to stdout. Setup, teardown and run is delegated to
055     * the GetRecordTool class. Management of this, exception handling etc. is delegated to ToolRunnerBase class.
056     *
057     * @param argv Takes two command line paramers: - indexdir (the Lucene index directory) - uri (the URI to get the
058     * record from)
059     */
060    public static void main(String[] argv) {
061        GetRecord instance = new GetRecord();
062        instance.runTheTool(argv);
063    }
064
065    /**
066     * Method for creating the simple command line tool.
067     *
068     * @return The commandline tool for GetRecord.
069     */
070    protected SimpleCmdlineTool makeMyTool() {
071        return new GetRecordTool();
072    }
073
074    /**
075     * Command line tool for running this tool.
076     */
077    private static class GetRecordTool implements SimpleCmdlineTool {
078        /**
079         * This instance is declared outside of run method to ensure reliable teardown in case of exceptions during
080         * execution.
081         */
082        private ViewerArcRepositoryClient arcrep;
083
084        /**
085         * Accept only exactly 2 parameters.
086         *
087         * @param args the arguments
088         * @return true, if length of args list is 2; returns false otherwise
089         */
090        public boolean checkArgs(String... args) {
091            return args.length == 2;
092        }
093
094        /**
095         * Create the ArcRepositoryClient instance here for reliable execution of close method in teardown.
096         *
097         * @param args the arguments (not used)
098         */
099        public void setUp(String... args) {
100            arcrep = ArcRepositoryClientFactory.getViewerInstance();
101            ArgumentNotValid.checkNotNull(arcrep, "arcrep");
102        }
103
104        /**
105         * Ensure reliable execution of the ArcRepositoryClient.close() method. Remember to check if arcrep was actually
106         * created. Also reliably clean up JMSConnection.
107         */
108        public void tearDown() {
109            if (arcrep != null) {
110                arcrep.close();
111            }
112            JMSConnectionFactory.getInstance().cleanup();
113        }
114
115        /**
116         * Perform the actual work. Procure the necessary information to run the ARCArchiveAccess from command line
117         * parameters and system settings, and perform the write. Creating and closing the ArcRepositoryClient (arcrep)
118         * is done in setup and teardown methods.
119         *
120         * @param args the arguments
121         */
122        public void run(String... args) {
123            try {
124                String indexPath = args[0];
125                String uri = args[1];
126                ARCLookup lookup = new ARCLookup(arcrep);
127                lookup.setIndex(new File(indexPath));
128                ResultStream rs = lookup.lookup(new URI(uri));
129                if (rs == null) {
130                    throw new IOFailure("Resource missing in index or repository for '" + uri + "' in '" + indexPath
131                            + "'");
132                }
133                processRecord(rs.getInputStream());
134            } catch (NetarkivetException e) {
135                throw new IOFailure("NetarkivetException while performing " + "ARCArchiveAccess.lookup", e);
136            } catch (URISyntaxException e) {
137                throw new IOFailure("URI has illegal syntax", e);
138            }
139        }
140
141        /**
142         * Copy a record from content to System.out.
143         *
144         * @param content The InputStream containing the record to copy to System.out.
145         */
146        private static void processRecord(InputStream content) {
147            try {
148                BufferedReader br = new BufferedReader(new InputStreamReader(content));
149                try {
150                    int i;
151                    while ((i = br.read()) != -1) {
152                        System.out.append((char) i);
153                    }
154                } finally {
155                    br.close();
156                }
157            } catch (IOException e) {
158                throw new IOFailure("Internal error: Could not read InputStream from " + "repository", e);
159            }
160        }
161
162        /**
163         * Return the list of parameters accepted by the GetRecordTool class.
164         *
165         * @return the list parameters accepted.
166         */
167        public String listParameters() {
168            return "indexfile uri";
169        }
170
171    }
172}