All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.javadpkg.impl.ChangeLogParserImpl Maven / Gradle / Ivy

/*
 * dpkg - Debian Package library and the Debian Package Maven plugin
 * (c) Copyright 2016 Gerrit Hohl
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package net.sourceforge.javadpkg.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import net.sourceforge.javadpkg.ChangeLog;
import net.sourceforge.javadpkg.ChangeLogConstants;
import net.sourceforge.javadpkg.ChangeLogParser;
import net.sourceforge.javadpkg.ChangeLogUrgency;
import net.sourceforge.javadpkg.ChangeLogUrgencyParser;
import net.sourceforge.javadpkg.ChangeLogVersionEntryDetail;
import net.sourceforge.javadpkg.Context;
import net.sourceforge.javadpkg.ParseException;
import net.sourceforge.javadpkg.control.PackageMaintainer;
import net.sourceforge.javadpkg.control.PackageMaintainerParser;
import net.sourceforge.javadpkg.control.PackageName;
import net.sourceforge.javadpkg.control.PackageNameParser;
import net.sourceforge.javadpkg.control.PackageVersion;
import net.sourceforge.javadpkg.control.PackageVersionParser;
import net.sourceforge.javadpkg.control.impl.PackageMaintainerParserImpl;
import net.sourceforge.javadpkg.control.impl.PackageNameParserImpl;
import net.sourceforge.javadpkg.control.impl.PackageVersionParserImpl;
import net.sourceforge.javadpkg.io.DataSource;


/**
 * 

* A {@link ChangeLogParser} implementation. *

* * @author Gerrit Hohl ([email protected]) * @version 1.0, 04.05.2016 by Gerrit Hohl */ public class ChangeLogParserImpl implements ChangeLogParser, ChangeLogConstants { /** The parser for the package name. */ private PackageNameParser packageNameParser; /** The parser for the version. */ private PackageVersionParser packageVersionParser; /** The parser for the urgency. */ private ChangeLogUrgencyParser changeLogUrgencyParser; /** The parser for the maintainer. */ private PackageMaintainerParser packageMaintainerParser; /** *

* Creates a parser. *

*/ public ChangeLogParserImpl() { super(); this.packageNameParser = new PackageNameParserImpl(); this.packageVersionParser = new PackageVersionParserImpl(); this.changeLogUrgencyParser = new ChangeLogUrgencyParserImpl(); this.packageMaintainerParser = new PackageMaintainerParserImpl(); } @Override public ChangeLog parseChangeLog(DataSource source, Context context) throws IOException, ParseException { ChangeLogImpl changeLog; String line = null; int lineNumber = 0; ChangeLogVersionEntryImpl entry = null; StringBuilder sb = null; ChangeLogVersionEntryDetail detail; if (source == null) throw new IllegalArgumentException("Argument source is null."); if (context == null) throw new IllegalArgumentException("Argument context is null."); changeLog = new ChangeLogImpl(); try { try (BufferedReader in = new BufferedReader(new InputStreamReader(source.getInputStream(), UTF_8_CHARSET))) { while ((line = in.readLine()) != null) { lineNumber++; // --- Ignore comments -- if ("#".equals(line) || line.startsWith("# ")) { continue; } else // --- Is this the first line of a version block? --- if (entry == null) { // --- Ignore empty lines between entries --- if (line.isEmpty() || line.trim().isEmpty()) { continue; } entry = this.parseInitialLine(line, context); if (entry == null) { break; } changeLog.addEntry(entry); } // --- Is this the last line of a version block? --- else if (line.startsWith(TERMINATION_PREFIX)) { // --- Do we have some detail text left? --- if (sb != null) { // --- Add the detail --- detail = new ChangeLogVersionEntryDetailImpl(sb.toString()); entry.addDetail(detail); sb = null; } this.parseTerminationLine(line, entry, context); entry = null; } // --- Is this a new detail of the current version entry? --- else if (line.startsWith(DETAIL_START_PREFIX)) { // --- Do we have some detail text left? --- if (sb != null) { // --- Add the detail --- detail = new ChangeLogVersionEntryDetailImpl(sb.toString()); entry.addDetail(detail); sb = null; } sb = this.parseDetailLine(line, null, context); } // --- Is this an additional line of the current detail? --- else if (line.startsWith(DETAIL_LINE_PREFIX)) { if (sb == null) { context.addWarning(new ChangeLogUnsupportedLineWarning(line)); } else { sb = this.parseDetailLine(line, sb, context); } } // --- Empty lines are stripped away. But is this line empty? --- else if (!line.isEmpty()) { context.addWarning(new ChangeLogUnsupportedLineWarning(line)); } } // --- Did we not reach the end? --- if (entry != null) throw new ParseException("End of last version entry in the change log is missing."); if (lineNumber == 0) throw new ParseException("Change log is empty."); } } catch (IOException e) { throw new IOException("An error occurred while parsing source |" + source.getName() + "|: " + e.getMessage(), e); } catch (ParseException e) { throw new ParseException( "Line |" + line + "| (Line number: " + lineNumber + ") couldn't be parsed: " + e.getMessage(), e); } return changeLog; } /** *

* Parses the initial line of a version. *

* * @param line * The line. * @param context * The context. * @return The entry containing the content of the first line. * @throws ParseException * If an error occurs while parsing. */ private ChangeLogVersionEntryImpl parseInitialLine(String line, Context context) throws ParseException { ChangeLogVersionEntryImpl entry; int index, lastIndex; String value; PackageName packageName; PackageVersion version; List distributions; ChangeLogUrgency urgency; // --- Package name --- index = line.indexOf(' '); if (index == -1) { context.addWarning(new ChangeLogInitialLineUnsupportedWarning(line, "Didn't find first whitespace in the first line of the change log entry.")); return null; } value = line.substring(0, index); try { packageName = this.packageNameParser.parsePackageName(value, context); } catch (ParseException e) { context.addWarning(new ChangeLogInitialLineUnsupportedWarning(line, "Couldn't parser package name |" + value + "| of first line of change log entry: " + e.getMessage())); return null; } // --- Version --- index++; if (line.length() <= index) { context.addWarning(new ChangeLogInitialLineUnsupportedWarning(line, "First line of change log entry is too short. Only found the package name.")); return null; } if (line.charAt(index) != '(') { context.addWarning(new ChangeLogInitialLineUnsupportedWarning(line, "Couldn't find the beginning of version of the package in the first line of change log entry.")); return null; } lastIndex = ++index; index = line.indexOf(')', lastIndex); if (index == -1) { context.addWarning(new ChangeLogInitialLineUnsupportedWarning(line, "Couldn't find the end of version of the package in the first line of change log entry.")); return null; } value = line.substring(lastIndex, index); try { version = this.packageVersionParser.parsePackageVersion(value, context); } catch (ParseException e) { context.addWarning(new ChangeLogInitialLineUnsupportedWarning(line, "Couldn't parser version |" + value + "| of first line of change log entry: " + e.getMessage())); return null; } lastIndex = index + 1; // --- Distributions --- index = line.indexOf(';', lastIndex); if (index == -1) { context.addWarning(new ChangeLogInitialLineUnsupportedWarning(line, "Couldn't find the semi-colon between the distributions and the urgency in the first line of change log entry.")); return null; } value = line.substring(lastIndex, index).trim(); distributions = new ArrayList<>(Arrays.asList(value.split(" "))); lastIndex = index + 1; // --- Urgency --- value = line.substring(lastIndex).trim(); if (!value.startsWith("urgency=")) { context.addWarning( new ChangeLogInitialLineUnsupportedWarning(line, "Couldn't the urgency prefix |urgency=| in the part |" + value + "| after the semi-colon in the first line of change log entry.")); return null; } value = value.substring(8); try { urgency = this.changeLogUrgencyParser.parseChangeLogUrgency(value, context); } catch (ParseException e) { context.addWarning(new ChangeLogInitialLineUnsupportedWarning(line, "Couldn't parser urgency |" + value + "| of first line of change log entry: " + e.getMessage())); return null; } entry = new ChangeLogVersionEntryImpl(); entry.setPackageName(packageName); entry.setVersion(version); entry.setDistributions(distributions); entry.setUrgency(urgency); return entry; } /** *

* Parses a line of a detail. *

* * @param line * The line. * @param detail * The current detail (optional). * @param context * The context. * @return The current detail. * @throws ParseException * If an error occurs while parsing. */ private StringBuilder parseDetailLine(String line, StringBuilder detail, Context context) throws ParseException { StringBuilder sb; String value; if (detail == null) { sb = new StringBuilder(); } else { sb = detail; } value = line.substring(4); if (sb.length() > 0) { sb.append('\n'); } // --- Only add the value if it is not just an empty line --- if (!".".equals(value)) { sb.append(value); } return sb; } /** *

* Parses the termination line of a version. *

* * @param line * The line. * @param entry * The entry. * @param context * The context. * @throws ParseException * If an error occurs while parsing. */ private void parseTerminationLine(String line, ChangeLogVersionEntryImpl entry, Context context) throws ParseException { int index; String rest, value; PackageMaintainer maintainer; Date date; rest = line.substring(TERMINATION_PREFIX.length()); index = rest.indexOf(MAINTAINER_TIMESTAMP_SEPARATOR); if (index == -1) throw new ParseException("Couldn't parse last line |" + line + "| of change log entry as the separator between maintainer and timestamp couldn't be found."); // --- Maintainer --- value = rest.substring(0, index); try { maintainer = this.packageMaintainerParser.parsePackageMaintainer(value, context); } catch (ParseException e) { throw new ParseException( "Couldn't parser maintainer |" + value + "| of last line of change log entry: " + e.getMessage(), e); } // --- Timestamp --- value = rest.substring(index + 2); try { date = TIMESTAMP_FORMAT.parse(value); } catch (java.text.ParseException e) { throw new ParseException( "Couldn't parse timestamp |" + value + "| of last line of change log entry: " + e.getMessage(), e); } entry.setMaintainer(maintainer); entry.setDate(date); } @Override public ChangeLog parseChangeLogHtml(DataSource source, Context context) throws IOException, ParseException { // TODO Implement method. throw new ParseException("Not yet implemented"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy