/* * Mibble MIB Parser (www.mibble.org) * * See LICENSE.txt for licensing information. * * Copyright (c) 2004-2017 Per Cederberg. All rights reserved. */ package net.percederberg.mibble; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.net.MalformedURLException; import java.util.ArrayList; /** * A program that parses and validates a MIB file. If the MIB file(s) * specified on the command-line uses constructs or syntax that are * not supported, an error message will be printed to the standard * output. The program will also return the number of validation * failures as its exit code. * * @author Per Cederberg * @version 2.10 * @since 2.0 */ public class MibbleValidator { /** * The command-line help output. */ private static final String COMMAND_HELP = "Validates a set of SNMP MIB files. This program comes with\n" + "ABSOLUTELY NO WARRANTY; for details see the LICENSE.txt file.\n" + "\n" + "Syntax: MibbleValidator <file(s) or URL(s)>"; /** * The internal error message. */ private static final String INTERNAL_ERROR = "INTERNAL ERROR: An internal error has been found. Please report\n" + " this error to the maintainers (see the web site for\n" + " instructions). Be sure to include the version number, as\n" + " well as the text below:\n"; /** * The application main entry point. * * @param args the command-line parameters */ public static void main(String[] args) { // Check command-line arguments if (args.length < 1) { printHelp("No file(s) specified"); System.exit(1); } ArrayList<Object> queue = new ArrayList<>(); for (String arg : args) { try { if (arg.contains(":")) { queue.add(new URL(arg)); } else { File file = new File(arg); if (!file.exists()) { System.out.println("Warning: Skipping " + arg + ": file not found"); } else if (file.isDirectory()) { addMibs(file, queue); } else { queue.add(file); } } } catch (MalformedURLException e) { System.out.println("Warning: Skipping " + arg + ": " + e.getMessage()); } } // Parse MIB files MibLoader loader = new MibLoader(); int errors = 0; int warnings = 0; for (int i = 0; i < queue.size(); i++) { Object src = queue.get(i); System.out.print(i + 1); System.out.print("/"); System.out.print(queue.size()); System.out.print(": Reading " + src + "... "); System.out.flush(); try { loader.unloadAll(); Mib mib = null; if (src instanceof URL) { loader.removeAllDirs(); mib = loader.load((URL) src); } else { File file = (File) src; if (!loader.hasDir(file.getParentFile())) { loader.removeAllDirs(); loader.addDir(file.getParentFile()); } mib = loader.load(file); } System.out.println("[OK]"); if (mib.getLog().warningCount() > 0) { mib.getLog().printTo(System.out); warnings++; } } catch (FileNotFoundException e) { System.out.println("[FAILED]"); printError(src.toString(), e); errors++; } catch (IOException e) { System.out.println("[FAILED]"); printError(src.toString(), e); errors++; } catch (MibLoaderException e) { System.out.println("[FAILED]"); e.getLog().printTo(System.out); errors++; } catch (RuntimeException e) { System.out.println(); printInternalError(e); System.exit(1); } } // Print error count System.out.println(); System.out.println("Files processed: " + queue.size()); System.out.println(" with errors: " + errors); System.out.println(" with warnings: " + warnings); if (errors > 0) { System.err.println("Error: validation errors were encountered"); } // Return error count System.exit(errors); } /** * Prints command-line help information. * * @param error an optional error message, or null */ private static void printHelp(String error) { System.err.println(COMMAND_HELP); System.err.println(); if (error != null) { System.err.print("Error: "); System.err.println(error); System.err.println(); } } /** * Prints an internal error message. This type of error should * only be reported when run-time exceptions occur, such as null * pointer and the likes. All these error should be reported as * bugs to the program maintainers. * * @param e the exception to be reported */ private static void printInternalError(Exception e) { System.err.println(INTERNAL_ERROR); e.printStackTrace(); } /** * Prints a file not found error message. * * @param file the file name not found * @param e the detailed exception */ private static void printError(String file, FileNotFoundException e) { StringBuilder buffer = new StringBuilder(); buffer.append("Error: couldn't open file:"); buffer.append("\n "); buffer.append(file); System.out.println(buffer.toString()); } /** * Prints a URL not found error message. * * @param url the URL not found * @param e the detailed exception */ private static void printError(String url, IOException e) { StringBuilder buffer = new StringBuilder(); buffer.append("Error: couldn't open URL:"); buffer.append("\n "); buffer.append(url); System.out.println(buffer.toString()); } /** * Adds all MIB files from a directory to the specified queue. * * @param dir the directory to check * @param queue the queue to add files to * * @since 2.9 */ private static void addMibs(File dir, ArrayList<Object> queue) { File[] files = dir.listFiles(); if (files != null) { for (File file : files) { if (file.isHidden()) { // Hidden file or directories are ignored } else if (file.isDirectory()) { addMibs(file, queue); } else if (isMib(file)) { queue.add(file); } } } } /** * Checks if the first lines of a text files looks like a MIB. * * @param file the file to check * * @return true if the file is probably a MIB file, or * false otherwise * * @since 2.9 */ private static boolean isMib(File file) { if (!file.canRead() || !file.isFile()) { return false; } try ( BufferedReader in = new BufferedReader(new FileReader(file)); ) { while (true) { String str = in.readLine(); if (str == null) { break; } str = str.trim(); if (!str.equals("") && !str.startsWith("--")) { return str.contains("DEFINITIONS"); } } } catch (Exception ignore) { // Do nothing } return false; } }