001/*
002 * #%L
003 * Netarchivesuite - common - test
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.common.arcrepository;
025
026import java.io.File;
027import java.io.FileInputStream;
028import java.io.FileOutputStream;
029import java.io.FilenameFilter;
030import java.io.IOException;
031import java.io.InputStream;
032import java.io.OutputStream;
033import java.util.ArrayList;
034import java.util.List;
035
036import org.archive.io.ArchiveReader;
037import org.archive.io.ArchiveReaderFactory;
038import org.archive.io.ArchiveRecord;
039
040import dk.netarkivet.common.distribute.TestRemoteFile;
041import dk.netarkivet.common.distribute.arcrepository.BatchStatus;
042import dk.netarkivet.common.distribute.arcrepository.BitarchiveRecord;
043import dk.netarkivet.common.distribute.arcrepository.Replica;
044import dk.netarkivet.common.exceptions.ArgumentNotValid;
045import dk.netarkivet.common.exceptions.IOFailure;
046import dk.netarkivet.common.utils.FileUtils;
047import dk.netarkivet.common.utils.batch.FileBatchJob;
048
049/**
050 * A local-file based arc repository client. Given one or more directories with ARC files, this client will serve them
051 * out like a normal arcrepository.
052 */
053
054// public class TestArcRepositoryClient extends JMSArcRepositoryClient {
055public class TestArcRepositoryClient extends TrivialArcRepositoryClient {
056    public File arcDir;
057    /** How many times batch has been called */
058    public int batchCounter;
059    /** Whether the batch call should die with an exception */
060    public boolean batchMustDie;
061    /** How many milliseconds the batch should pause before running */
062    public int batchPauseMilliseconds;
063    public File tmpDir;
064
065    public TestArcRepositoryClient(File arcdir) {
066        super();
067        this.arcDir = arcdir;
068        tmpDir = FileUtils.getTempDir();
069    }
070
071    @Override
072    public void getFile(String arcfilename, Replica replica, File toFile) {
073        ArgumentNotValid.checkNotNullOrEmpty(arcfilename, "arcfilename");
074        ArgumentNotValid.checkNotNull(replica, "replica");
075        ArgumentNotValid.checkNotNull(toFile, "toFile");
076        File actualFile = new File(arcDir, arcfilename);
077        try {
078            InputStream in = null;
079            try {
080                in = new FileInputStream(actualFile);
081                FileUtils.writeStreamToFile(in, toFile);
082            } finally {
083                if (in != null) {
084                    in.close();
085                }
086            }
087        } catch (IOException e) {
088            throw new IOFailure("Error reading file " + actualFile, e);
089        }
090    }
091
092    @Override
093    public BitarchiveRecord get(String arcfile, long index) throws ArgumentNotValid {
094        ArgumentNotValid.checkNotNull(arcfile, "arcfile");
095        ArgumentNotValid.checkNotNegative(index, "index");
096
097        File in = new File(arcDir, arcfile);
098        try {
099            ArchiveReader arcReader = ArchiveReaderFactory.get(in);
100            ArchiveRecord arc = arcReader.get(index);
101            BitarchiveRecord result = new BitarchiveRecord(arc, arcfile);
102            return result;
103        } catch (IOException e) {
104            throw new IOFailure("Error reading record from " + arcfile + " offset " + index, e);
105        }
106    }
107
108    @Override
109    public BatchStatus batch(FileBatchJob job, String replicaId, String... args) {
110        batchCounter++;
111        if (batchMustDie) {
112            throw new IOFailure("Committing suicide as ordered, SIR!");
113        }
114        if (batchPauseMilliseconds > 0) {
115            try {
116                Thread.sleep(batchPauseMilliseconds);
117            } catch (InterruptedException e) {
118                // Don't care.
119            }
120        }
121
122        File f = new File(tmpDir, "batchOutput");
123        OutputStream os = null;
124        try {
125            os = new FileOutputStream(f);
126        } catch (IOException e) {
127            return new BatchStatus(replicaId, new ArrayList<File>(), 0, null, job.getExceptions());
128        }
129        File[] files = arcDir.listFiles(new FilenameFilter() {
130            public boolean accept(File dir, String name) {
131                return name.endsWith(".arc");
132            }
133        });
134        job.initialize(os);
135        int processed = 0;
136        List<File> failures = new ArrayList<File>();
137        for (File f1 : files) {
138            if (job.getFilenamePattern().matcher(f1.getName()).matches()) {
139                processed++;
140                if (!job.processFile(f1, os)) {
141                    failures.add(f1);
142                }
143            }
144        }
145
146        job.finish(os);
147        try {
148            os.close();
149        } catch (IOException e) {
150            throw new IOFailure("Error in close", e);
151        }
152
153        return new BatchStatus(replicaId, failures, processed, new TestRemoteFile(f, batchMustDie, batchMustDie,
154                batchMustDie), job.getExceptions());
155    }
156}