xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/history/RCSget.java (revision c6f0939b1c668e9f8e1e276424439c3106b3a029)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * See LICENSE.txt included in this distribution for the specific
9  * language governing permissions and limitations under the License.
10  *
11  * When distributing Covered Code, include this CDDL HEADER in each
12  * file and include the License file at LICENSE.txt.
13  * If applicable, add the following below this CDDL HEADER, with the
14  * fields enclosed by brackets "[]" replaced with your own identifying
15  * information: Portions Copyright [yyyy] [name of copyright owner]
16  *
17  * CDDL HEADER END
18  */
19 
20 /*
21  * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
22  * Portions Copyright (c) 2020, Chris Fraire <cfraire@me.com>.
23  */
24 package org.opengrok.indexer.history;
25 
26 import java.io.ByteArrayInputStream;
27 import java.io.FileNotFoundException;
28 import java.io.IOException;
29 import java.io.InputStream;
30 
31 import org.suigeneris.jrcs.diff.PatchFailedException;
32 import org.suigeneris.jrcs.rcs.Archive;
33 import org.suigeneris.jrcs.rcs.InvalidFileFormatException;
34 import org.suigeneris.jrcs.rcs.impl.NodeNotFoundException;
35 import org.suigeneris.jrcs.rcs.parse.ParseException;
36 import org.opengrok.indexer.util.IOUtils;
37 
38 /**
39  * Virtualize RCS log as an input stream.
40  */
41 public class RCSget extends InputStream {
42     private final InputStream stream;
43 
44     /**
45      * Pass null in version to get current revision.
46      * @param file file contents to get
47      * @param version specified revision or @{code null}
48      * @throws java.io.IOException if I/O exception occurred
49      * @throws java.io.FileNotFoundException if the file cannot be found
50      */
RCSget(String file, String version)51     public RCSget(String file, String version) throws IOException, FileNotFoundException {
52         try {
53             Archive archive = new Archive(file);
54             Object[] lines;
55 
56             if (version == null) {
57                 lines = archive.getRevision(false);
58             } else {
59                 lines = archive.getRevision(version, false);
60             }
61 
62             StringBuilder sb = new StringBuilder();
63             for (Object line : lines) {
64                 sb.append((String) line);
65                 sb.append("\n");
66             }
67             stream = new ByteArrayInputStream(sb.toString().getBytes());
68         } catch (ParseException e) {
69             throw RCSRepository.wrapInIOException("Parse error", e);
70         } catch (InvalidFileFormatException e) {
71             throw RCSRepository.wrapInIOException("Invalid RCS file format", e);
72         } catch (PatchFailedException e) {
73             throw RCSRepository.wrapInIOException("Patch failed", e);
74         } catch (NodeNotFoundException e) {
75             throw RCSRepository.wrapInIOException(
76                     "Revision " + version + " not found", e);
77         }
78     }
79 
80     @Override
reset()81     public synchronized void reset() throws IOException {
82         stream.reset();
83     }
84 
85     @Override
close()86     public void close() throws IOException {
87         IOUtils.close(stream);
88     }
89 
90     @Override
mark(int readlimit)91     public synchronized void mark(int readlimit) {
92         stream.mark(readlimit);
93     }
94 
95     @Override
read(byte[] buffer, int pos, int len)96     public int read(byte[] buffer, int pos, int len) throws IOException {
97         return stream.read(buffer, pos, len);
98     }
99 
100     @Override
read()101     public int read() throws IOException {
102         throw new IOException("use a BufferedInputStream. just read() is not supported!");
103     }
104 }
105