package org.springframework.roo.addon.oscommands; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.logging.Logger; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.Validate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.springframework.roo.process.manager.ActiveProcessManager; import org.springframework.roo.process.manager.ProcessManager; import org.springframework.roo.project.PathResolver; import org.springframework.roo.support.logging.HandlerUtils; /** * Implementation of {@link OsOperations} interface. * * @author Stefan Schmidt * @since 1.2.0 */ @Component @Service public class OsOperationsImpl implements OsOperations { private static class LoggingInputStream extends Thread { private final ProcessManager processManager; private final Reader reader; public LoggingInputStream(final InputStream inputStream, final ProcessManager processManager) { reader = new InputStreamReader(inputStream); this.processManager = processManager; } @Override public void run() { ActiveProcessManager.setActiveProcessManager(processManager); // Prevent thread name from being presented in Roo shell Thread.currentThread().setName(""); try { for (String line : IOUtils.readLines(reader)) { if (line.startsWith("[ERROR]")) { LOGGER.severe(line); } else if (line.startsWith("[WARNING]")) { LOGGER.warning(line); } else { LOGGER.info(line); } } } catch (final IOException e) { if (e.getMessage().contains("No such file or directory") || e.getMessage().contains("CreateProcess error=2")) { LOGGER.severe("Could not locate executable; please ensure command is in your path"); } } finally { IOUtils.closeQuietly(reader); ActiveProcessManager.clearActiveProcessManager(); } } } private static final Logger LOGGER = HandlerUtils.getLogger(OsOperationsImpl.class); @Reference private PathResolver pathResolver; @Reference private ProcessManager processManager; public void executeCommand(final String command) throws IOException { final File root = new File(getProjectRoot()); Validate.isTrue(root.isDirectory() && root.exists(), "Project root does not currently exist as a directory ('%s')", root.getCanonicalPath()); // Prevent thread name from being presented in Roo shell Thread.currentThread().setName(""); final Process p = Runtime.getRuntime().exec(command, null, root); // Ensure separate threads are used for logging, as per ROO-652 final LoggingInputStream input = new LoggingInputStream(p.getInputStream(), processManager); final LoggingInputStream errors = new LoggingInputStream(p.getErrorStream(), processManager); p.getOutputStream().close(); input.start(); errors.start(); try { if (p.waitFor() != 0) { LOGGER.warning("The command '" + command + "' did not complete successfully"); } } catch (final InterruptedException e) { throw new IllegalStateException(e); } } private String getProjectRoot() { return pathResolver.getRoot(); } }