001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.util; 006 007import java.io.BufferedReader; 008import java.io.IOException; 009import java.io.InputStream; 010import java.io.InputStreamReader; 011import java.nio.charset.StandardCharsets; 012import java.nio.file.Files; 013import java.nio.file.NoSuchFileException; 014import java.nio.file.Paths; 015 016/** 017 * Loads classes by name. Can be used at any time, but is most commonly used to preload classes at 018 * the start of the program to avoid unpredictable delays due to lazy classloading later in program 019 * execution. 020 */ 021public final class ClassPreloader { 022 private ClassPreloader() {} 023 024 /** 025 * Loads classes from an iterable. 026 * 027 * @param classNames iterable of class names 028 * @return Number of classes loaded. 029 */ 030 public static int preload(Iterable<String> classNames) { 031 int count = 0; 032 for (String i : classNames) { 033 try { 034 Class.forName(i); 035 count++; 036 } catch (ClassNotFoundException e) { 037 System.out.println("Could not preload " + i); 038 } 039 } 040 return count; 041 } 042 043 /** 044 * Loads classes. 045 * 046 * @param classNames array of class names 047 * @return Number of classes loaded. 048 */ 049 public static int preload(String... classNames) { 050 int count = 0; 051 for (String i : classNames) { 052 try { 053 Class.forName(i); 054 count++; 055 } catch (ClassNotFoundException e) { 056 System.out.println("Could not preload " + i); 057 } 058 } 059 return count; 060 } 061 062 /** 063 * Loads classes from a buffered reader. The input is expected to be one class name per line. 064 * Blank lines and lines starting with a semicolon are ignored. 065 * 066 * @param reader Reader 067 * @return Number of classes loaded. 068 */ 069 public static int preload(BufferedReader reader) { 070 int count = 0; 071 try { 072 String line = reader.readLine(); 073 while (line != null) { 074 if (!line.isEmpty() && !line.startsWith(";")) { 075 try { 076 Class.forName(line); 077 count++; 078 } catch (ClassNotFoundException e) { 079 System.out.println("Could not preload " + line); 080 } 081 } 082 line = reader.readLine(); 083 } 084 } catch (IOException e) { 085 System.out.println("Error when reading preload file: " + e); 086 } 087 return count; 088 } 089 090 /** 091 * Loads classes from an input stream. The input is expected to be one class name per line. Blank 092 * lines and lines starting with a semicolon are ignored. 093 * 094 * @param stream input stream 095 * @return Number of classes loaded. 096 */ 097 public static int preload(InputStream stream) { 098 return preload(new BufferedReader(new InputStreamReader(stream))); 099 } 100 101 /** 102 * Loads classes from a file. The input is expected to be one class name per line. Blank lines and 103 * lines starting with a semicolon are ignored. 104 * 105 * @param filename filename 106 * @return Number of classes loaded. 107 */ 108 public static int preloadFile(String filename) { 109 try (BufferedReader reader = 110 Files.newBufferedReader(Paths.get(filename), StandardCharsets.UTF_8)) { 111 return preload(reader); 112 } catch (NoSuchFileException e) { 113 System.out.println("Could not open preload file " + filename + ": " + e); 114 } catch (IOException e) { 115 System.out.println("Could not close preload file " + filename + ": " + e); 116 } 117 return 0; 118 } 119}