package net.sf.openrocket.database; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.util.List; import net.sf.openrocket.database.motor.ThrustCurveMotorSetDatabase; import net.sf.openrocket.file.iterator.DirectoryIterator; import net.sf.openrocket.file.iterator.FileIterator; import net.sf.openrocket.file.motor.GeneralMotorLoader; import net.sf.openrocket.gui.util.SimpleFileFilter; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.ThrustCurveMotor; import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An asynchronous database loader that loads the internal thrust curves * and external user-supplied thrust curves to a ThrustCurveMotorSetDatabase. * The resulting database is obtained using getDatabase(). * * @author Sampo Niskanen <sampo.niskanen@iki.fi> */ public class MotorDatabaseLoader extends AsynchronousDatabaseLoader { private final static Logger log = LoggerFactory.getLogger(MotorDatabaseLoader.class); private static final String THRUSTCURVE_DIRECTORY = "datafiles/thrustcurves/"; private static final long STARTUP_DELAY = 0; private final ThrustCurveMotorSetDatabase database = new ThrustCurveMotorSetDatabase(); private int motorCount = 0; public MotorDatabaseLoader() { super(STARTUP_DELAY); } @Override protected void loadDatabase() { GeneralMotorLoader loader = new GeneralMotorLoader(); SimpleFileFilter fileFilter = new SimpleFileFilter("", loader.getSupportedExtensions()); log.info("Starting reading serialized motor database"); FileIterator iterator = DirectoryIterator.findDirectory(THRUSTCURVE_DIRECTORY, new SimpleFileFilter("", false, "ser")); while (iterator.hasNext()) { Pair<String, InputStream> f = iterator.next(); loadSerialized(f); } log.info("Ending reading serialized motor database, motorCount=" + motorCount); log.info("Starting reading user-defined motors"); for (File file : ((SwingPreferences) Application.getPreferences()).getUserThrustCurveFiles()) { if (file.isFile()) { loadFile(loader, file); } else if (file.isDirectory()) { loadDirectory(loader, fileFilter, file); } else { log.warn("User-defined motor file " + file + " is neither file nor directory"); } } log.info("Ending reading user-defined motors, motorCount=" + motorCount); } @SuppressWarnings("unchecked") private void loadSerialized(Pair<String, InputStream> f) { try { log.debug("Reading motors from file " + f.getU()); ObjectInputStream ois = new ObjectInputStream(f.getV()); List<Motor> motors = (List<Motor>) ois.readObject(); addMotors(motors); } catch (Exception ex) { throw new BugException(ex); } } private void loadFile(GeneralMotorLoader loader, File file) { BufferedInputStream bis = null; try { log.debug("Loading motors from file " + file); bis = new BufferedInputStream(new FileInputStream(file)); List<Motor> motors = loader.load(bis, file.getName()); addMotors(motors); bis.close(); } catch (IOException e) { log.warn("IOException while reading " + file + ": " + e, e); if (bis != null) { try { bis.close(); } catch (IOException e1) { } } } } private void loadDirectory(GeneralMotorLoader loader, SimpleFileFilter fileFilter, File file) { FileIterator iterator; try { iterator = new DirectoryIterator(file, fileFilter, true); } catch (IOException e) { log.warn("Unable to read directory " + file + ": " + e, e); return; } while (iterator.hasNext()) { Pair<String, InputStream> f = iterator.next(); try { List<Motor> motors = loader.load(f.getV(), f.getU()); addMotors(motors); f.getV().close(); } catch (IOException e) { log.warn("IOException while loading file " + f.getU() + ": " + e, e); try { f.getV().close(); } catch (IOException e1) { } } } } private synchronized void addMotors(List<Motor> motors) { for (Motor m : motors) { motorCount++; database.addMotor((ThrustCurveMotor) m); } } /** * Returns the loaded database. If the database has not fully loaded, * this blocks until it is. * * @return the motor database */ public ThrustCurveMotorSetDatabase getDatabase() { blockUntilLoaded(); return database; } }