0N/A/*
0N/A * CDDL HEADER START
0N/A *
0N/A * The contents of this file are subject to the terms of the
25N/A * Common Development and Distribution License (the "License").
0N/A * You may not use this file except in compliance with the License.
0N/A *
0N/A * See LICENSE.txt included in this distribution for the specific
0N/A * language governing permissions and limitations under the License.
0N/A *
0N/A * When distributing Covered Code, include this CDDL HEADER in each
0N/A * file and include the License file at LICENSE.txt.
0N/A * If applicable, add the following below this CDDL HEADER, with the
0N/A * fields enclosed by brackets "[]" replaced with your own identifying
0N/A * information: Portions Copyright [yyyy] [name of copyright owner]
0N/A *
0N/A * CDDL HEADER END
0N/A */
0N/A
0N/A/*
1072N/A * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A */
0N/Apackage org.opensolaris.opengrok.history;
0N/A
176N/Aimport java.io.BufferedReader;
176N/Aimport java.io.File;
176N/Aimport java.io.FileReader;
176N/Aimport java.io.IOException;
176N/Aimport java.io.Reader;
176N/Aimport java.text.DateFormat;
176N/Aimport java.text.ParseException;
176N/Aimport java.text.SimpleDateFormat;
176N/Aimport java.util.ArrayList;
176N/Aimport java.util.Date;
456N/Aimport java.util.Locale;
1327N/Aimport java.util.logging.Logger;
1327N/A
1195N/Aimport org.opensolaris.opengrok.util.IOUtils;
0N/A
0N/A/**
0N/A * Reads and filters out junk from a SCCS history file
0N/A * see sccsfile(4) for details of the file format
0N/A * Wrote it since invoking sccs prs for each file was
0N/A * taking a lot of time. Time to index history has reduced 4 to 1!
0N/A */
770N/Aclass SCCSHistoryParser {
1327N/A private static final Logger logger = Logger.getLogger(SCCSHistoryParser.class.getName());
0N/A boolean pass;
0N/A boolean passRecord;
0N/A boolean active;
0N/A int field;
0N/A boolean sep;
0N/A StringBuilder record = new StringBuilder(128);
0N/A private String revision;
0N/A private String author;
0N/A private Date rdate;
0N/A private String comment;
0N/A DateFormat sccsDateFormat;
25N/A Reader in;
25N/A
770N/A History parse(File file, Repository repos) throws HistoryException {
749N/A sccsDateFormat = repos.getDateFormat();
615N/A try {
615N/A return parseFile(file);
615N/A } catch (IOException ioe) {
615N/A throw new HistoryException(ioe);
615N/A }
615N/A }
615N/A
615N/A private History parseFile(File file) throws IOException {
212N/A File f = getSCCSFile(file);
212N/A if (f == null) {
212N/A return null;
212N/A }
1190N/A
154N/A in = new BufferedReader(new FileReader(getSCCSFile(file)));
0N/A pass = sep = false;
0N/A passRecord = true;
0N/A active = true;
0N/A field = 0;
1072N/A sccsDateFormat = new SimpleDateFormat("yy/MM/dd", Locale.getDefault());
25N/A
56N/A ArrayList<HistoryEntry> entries = new ArrayList<HistoryEntry>();
25N/A while (next()) {
25N/A HistoryEntry entry = new HistoryEntry();
25N/A entry.setRevision(getRevision());
25N/A entry.setDate(getDate());
25N/A entry.setAuthor(getAuthor());
25N/A entry.setMessage(getComment());
25N/A entry.setActive(isActive());
56N/A entries.add(entry);
25N/A }
25N/A
1195N/A IOUtils.close(in);
25N/A
56N/A History history = new History();
56N/A history.setHistoryEntries(entries);
25N/A return history;
0N/A }
25N/A
0N/A /**
0N/A * Read a single line of delta record
0N/A *
0N/A * @throws java.io.IOException
0N/A * @return a String representing a single log delta entry
0N/A * rev date time author comments(s)
0N/A */
25N/A private boolean next() throws java.io.IOException {
0N/A sep = true;
0N/A record.setLength(0);
0N/A int c;
0N/A while ((c = read()) > 01) {
0N/A record.append((char)c);
0N/A }
0N/A // to flag that revision needs to be re populated if you really need it
0N/A revision = null;
421N/A return (record.length() > 2);
0N/A }
25N/A
0N/A private void initFields() {
0N/A if(revision == null) {
0N/A String[] f = record.toString().split(" ", 6);
0N/A if (f.length > 5) {
0N/A revision = f[1];
0N/A try {
0N/A rdate = sccsDateFormat.parse(f[2] + " " + f[3]);
0N/A } catch (ParseException e) {
1473N/A logger.warning("An error occured while parsing date: "
1473N/A + e.getMessage());
0N/A rdate = null;
0N/A }
0N/A author = f[4];
0N/A comment = f[5];
0N/A } else {
0N/A rdate = null;
0N/A author = null;
0N/A comment = null;
0N/A }
0N/A }
0N/A }
25N/A
0N/A /**
0N/A * @return get the revision string of current log record
0N/A */
25N/A private String getRevision() {
0N/A initFields();
0N/A return revision;
0N/A }
25N/A
0N/A /**
0N/A * @return get the date assosiated with current log record
0N/A */
25N/A private Date getDate() {
0N/A initFields();
0N/A return rdate;
0N/A }
25N/A
0N/A /**
0N/A * @return get the author of current log record
0N/A */
25N/A private String getAuthor() {
0N/A initFields();
0N/A return author;
0N/A }
0N/A /**
0N/A * @return get the comments of current log record
0N/A */
25N/A private String getComment() {
0N/A initFields();
0N/A return comment;
0N/A }
25N/A
25N/A private boolean isActive() {
0N/A return active;
0N/A }
25N/A
25N/A private int read() throws java.io.IOException {
0N/A int c, d, dt;
0N/A while((c = in.read()) != -1) {
860N/A switch (c) { //NOPMD
0N/A case 01:
0N/A d = in.read();
0N/A switch (d) {
0N/A case 'c':
0N/A case 't':
0N/A case 'u':
0N/A d = in.read();
0N/A if(d != ' ') {
0N/A return (d);
0N/A }
0N/A pass = true;
0N/A break;
0N/A case 'd':
0N/A d = in.read();
460N/A if (d == ' ') {
0N/A dt = in.read();
0N/A if (dt == 'R') {
0N/A active = false;
0N/A } else {
0N/A active = true;
0N/A }
0N/A passRecord = true;
0N/A field = 1;
460N/A } else {
460N/A return (d);
0N/A }
0N/A break;
0N/A case -1:
972N/A case 'I': //the file contents start
0N/A case 'D':
0N/A case 'E':
0N/A case 'T':
0N/A return(-1);
0N/A case 'e':
0N/A pass = false;
0N/A if (sep && passRecord) {
0N/A return 01;
0N/A }
1182N/A passRecord = true;
0N/A break;
0N/A default:
0N/A pass = false;
0N/A }
0N/A break;
0N/A case ' ':
0N/A if (passRecord) {
0N/A if (field > 0) {
0N/A field ++;
0N/A pass = true;
0N/A }
0N/A if(field > 5) {
0N/A field = 0;
0N/A pass = false;
0N/A return(c);
0N/A }
0N/A }
0N/A default:
0N/A if (pass && passRecord) {
0N/A return(c);
0N/A }
0N/A }
0N/A }
0N/A return(-1);
0N/A }
154N/A
212N/A protected static File getSCCSFile(File file)
212N/A {
154N/A return getSCCSFile(file.getParent(), file.getName());
154N/A }
154N/A
212N/A protected static File getSCCSFile(String parent, String name)
212N/A {
212N/A File f = new File(parent + "/SCCS/s." + name);
212N/A if (!f.exists()) {
212N/A return null;
212N/A }
212N/A return f;
154N/A }
0N/A}