package org.openbel.framework.tools; import static org.openbel.framework.common.BELUtilities.deleteDirectory; import static org.openbel.framework.common.Strings.DIRECTORY_CREATION_FAILED; import static org.openbel.framework.common.Strings.DIRECTORY_DELETION_FAILED; import static org.openbel.framework.common.Strings.KAM_NAME_HELP; import static org.openbel.framework.common.Strings.LONG_OPT_NO_PRESERVE; import static org.openbel.framework.common.Strings.NO_PRESERVE_HELP; import static org.openbel.framework.common.Strings.SHORT_OPT_KAM_NAME; import static org.openbel.framework.common.Strings.LONG_OPT_KAM_NAME; import static org.openbel.framework.common.cfg.SystemConfiguration.getSystemConfiguration; import static org.openbel.framework.common.enums.BELFrameworkVersion.VERSION_NUMBER; import static org.openbel.framework.common.enums.ExitCode.GENERAL_FAILURE; import java.io.File; import java.sql.SQLException; import java.util.LinkedList; import java.util.List; import org.apache.commons.cli.Option; import org.openbel.framework.api.KAMStoreException; import org.openbel.framework.api.KAMStoreImpl; import org.openbel.framework.common.DBConnectionFailure; import org.openbel.framework.common.SimpleOutput; import org.openbel.framework.common.cfg.SystemConfiguration; import org.openbel.framework.common.enums.ExitCode; import org.openbel.framework.core.CommandLineApplication; import org.openbel.framework.core.df.DBConnection; import org.openbel.framework.core.df.DatabaseService; import org.openbel.framework.core.df.DatabaseServiceImpl; import org.openbel.framework.api.internal.KAMCatalogDao.KamInfo; /** * This application validates the command line arguments passed by the * <i>belc</i> frontend against all phase applications. * <p> * This class supplants a proper frontend to all phases. Each phase application * ignores unrecognized options and this class is a safety net to ensure all * phases have what they need before executing. * </p> * <p> * If <i>belc</i> ever dies and the BEL compiler gets a proper frontend, this * application should be removed. * </p> */ public class PhaseZeroApplication extends CommandLineApplication { private final String[] commandLineArgs; // These fields were added as part of --no-preserve implementation. private DBConnection dbConnection; private KAMStoreImpl kamStore; private List<KamInfo> kams; /** * Creates the phase zero application. * * @param args Command-line arguments * @param configs */ public PhaseZeroApplication(String[] args) { super(args); this.commandLineArgs = args; final SimpleOutput reportable = new SimpleOutput(); reportable.setErrorStream(System.err); reportable.setOutputStream(System.out); setReportable(reportable); } public void start() { printApplicationInfo("Compiler/Assembler"); PhaseOneApplication p1App = new PhaseOneApplication(commandLineArgs); if (!p1App.validCommandLine()) { printUsage(); bail(GENERAL_FAILURE); } PhaseTwoApplication p2App = new PhaseTwoApplication(commandLineArgs); if (!p2App.validCommandLine()) { printUsage(); bail(GENERAL_FAILURE); } PhaseThreeApplication p3App = new PhaseThreeApplication(commandLineArgs); if (!p3App.validCommandLine()) { printUsage(); bail(GENERAL_FAILURE); } PhaseFourApplication p4App = new PhaseFourApplication(commandLineArgs); if (!p4App.validCommandLine()) { printUsage(); bail(GENERAL_FAILURE); } initializeSystemConfiguration(); SystemConfiguration syscfg = getSystemConfiguration(); final File wrkdir = syscfg.getWorkingDirectory(); File[] dircontents = wrkdir.listFiles(); if (dircontents != null && dircontents.length > 0) { if (!deleteDirectory(wrkdir)) { reportable.error(DIRECTORY_DELETION_FAILED + wrkdir); bail(ExitCode.DIRECTORY_DELETION_FAILED); } if (!wrkdir.mkdir()) { reportable.error(DIRECTORY_CREATION_FAILED + wrkdir); bail(ExitCode.DIRECTORY_CREATION_FAILED); } wrkdir.mkdir(); } DatabaseService dbsvc = new DatabaseServiceImpl(); // validate kamstore connection final String url = syscfg.getKamURL(); final String user = syscfg.getKamUser(); final String pass = syscfg.getKamPassword(); try { if (!dbsvc.validConnection(url, user, pass)) { bail(ExitCode.KAM_CONNECTION_FAILURE); } } catch (DBConnectionFailure e) { reportable.error(e.getUserFacingMessage()); bail(ExitCode.KAM_CONNECTION_FAILURE); } // If "--no-preserve" is not specified, query the database for an // existing KAM w/same name. If one exists, exit with proper ExitCode. if (!hasOption(LONG_OPT_NO_PRESERVE)){ String kamName = getOptionValue("k"); try{ dbConnection = dbsvc.dbConnection( syscfg.getKamURL(), syscfg.getKamUser(), syscfg.getKamPassword()); kamStore = new KAMStoreImpl(dbConnection); kams = kamStore.getCatalog(); for (KamInfo kam : kams){ if (kam.getName().equals(kamName)){ bail(ExitCode.DUPLICATE_KAM_NAME); } } } catch (SQLException e){ reportable.error(e.getMessage()); } catch (KAMStoreException e) { reportable.error(e.getMessage()); } } } /** * Returns {@code "Phase 0: Command-line validation"}. * * @return String */ @Override public String getApplicationName() { return "BEL Framework Compiler/Assembler " + VERSION_NUMBER; } /** * Returns {@code "Backtrack"}. * * @return String */ @Override public String getApplicationShortName() { return "Compiler/Assembler"; } /** * Returns {@code "Validates the BEL Compiler command-line."}. * * @return String */ @Override public String getApplicationDescription() { return "Phase 0: Validates the Compiler/Assembler before execution."; } /** * {@inheritDoc} */ @Override public String getUsage() { StringBuilder bldr = new StringBuilder(); bldr.append("[OPTIONS]..."); bldr.append(" [-p <path> [-p <path 2> [...] ] ]"); bldr.append(" [-f <filename> [-f <filename 2> [...] ] ]"); bldr.append(" [-k <kam_name>]"); bldr.append(" [-d <kam_description>]"); return bldr.toString(); } /** * {@inheritDoc} */ @Override public List<Option> getCommandLineOptions() { List<Option> ret = new LinkedList<Option>(); String help = KAM_NAME_HELP; Option o = new Option(SHORT_OPT_KAM_NAME, LONG_OPT_KAM_NAME, true, help); o.setArgName("kam"); ret.add(o); help = NO_PRESERVE_HELP; o = new Option(null, LONG_OPT_NO_PRESERVE, false, help); ret.add(o); return ret; } /** * PhaseZeroApplication {@code main()}. * * @param args Command-line arguments */ public static void main(String[] args) { PhaseZeroApplication p = new PhaseZeroApplication(args); p.start(); } }