class CVSAnnotationParser implements Executor.StreamHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(CVSAnnotationParser.class);

    /**
     * Pattern used to extract author/revision from {@code cvs annotate}.
     */
    private static final Pattern ANNOTATE_PATTERN = Pattern.compile("([\\.\\d]+)\\W+\\((\\w+)");

    /**
     * Store annotation created by processStream.
     */
    private final Annotation annotation;

    private final String fileName;

    /**
     * @param fileName the name of the file being annotated
     */
    public CVSAnnotationParser(String fileName) {
        annotation = new Annotation(fileName);
        this.fileName = fileName;
    }

    /**
     * Returns the annotation that has been created.
     *
     * @return annotation an annotation object
     */
    public Annotation getAnnotation() {
        return annotation;
    }

    @Override
    public void processStream(InputStream input) throws IOException {<FILL_FUNCTION_BODY>}
}

        BufferedReader in = new BufferedReader(new InputStreamReader(input));
        String line = "";
        int lineno = 0;
        boolean hasStarted = false;
        Matcher matcher = ANNOTATE_PATTERN.matcher(line);
        while ((line = in.readLine()) != null) {
            // Skip header
            if (!hasStarted && (line.length() == 0 || !Character.isDigit(line.charAt(0)))) {
                continue;
            }
            hasStarted = true;

            // Start parsing
            ++lineno;
            matcher.reset(line);
            if (matcher.find()) {
                String rev = matcher.group(1);
                String author = matcher.group(2).trim();
                annotation.addLine(rev, author, true);
            } else {
                LOGGER.log(Level.WARNING,
                        "Error: did not find annotation in line {0} for ''{1}'': [{2}]",
                        new Object[]{String.valueOf(lineno), this.fileName, line});
            }
        }
    
<no_super_class>