From 1d8cd24c0af4530b5a0d5feb84bbf9a03b3edfc5 Mon Sep 17 00:00:00 2001 From: David Mason Date: Fri, 18 Oct 2013 14:48:40 +1000 Subject: [PATCH 01/11] add mapping for optional hooks element in client config --- .../org/zanata/client/config/CommandHook.java | 73 +++++++++++++++++++ .../zanata/client/config/ZanataConfig.java | 16 +++- 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 zanata-client-commands/src/main/java/org/zanata/client/config/CommandHook.java diff --git a/zanata-client-commands/src/main/java/org/zanata/client/config/CommandHook.java b/zanata-client-commands/src/main/java/org/zanata/client/config/CommandHook.java new file mode 100644 index 00000000..179dadd1 --- /dev/null +++ b/zanata-client-commands/src/main/java/org/zanata/client/config/CommandHook.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013, Red Hat, Inc. and individual contributors as indicated by the + * @author tags. See the copyright.txt file in the distribution for a full + * listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this software; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF + * site: http://www.fsf.org. + */ +package org.zanata.client.config; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlType; + +@XmlType(name = "hookType", propOrder = { "befores", "afters" }) +public class CommandHook implements Serializable { + + private static final long serialVersionUID = 1L; + + private String command; + private List before = new ArrayList(); + private List after = new ArrayList(); + + @XmlAttribute(name = "command", required = true) + public String getCommand() { + return command; + } + + public void setCommand(String command) { + this.command = command; + } + + @XmlElements({ @XmlElement(name = "before", type = String.class) }) + public List getBefores() { + return before; + } + + @XmlElements({ @XmlElement(name = "after", type = String.class) }) + public List getAfters() { + return after; + } + + @Override + public String toString() { + StringBuilder sb = + new StringBuilder("hook{ before-").append(command).append("["); + for (String bef : before) { + sb.append("\"").append(bef).append("\","); + } + sb.append("], after-").append(command).append("["); + for (String aft : after) { + sb.append("\"").append(aft).append("\","); + } + return sb.append("] }").toString(); + } +} diff --git a/zanata-client-commands/src/main/java/org/zanata/client/config/ZanataConfig.java b/zanata-client-commands/src/main/java/org/zanata/client/config/ZanataConfig.java index 6197c96d..0b7ebc24 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/config/ZanataConfig.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/config/ZanataConfig.java @@ -22,6 +22,8 @@ import java.io.Serializable; import java.net.URL; +import java.util.ArrayList; +import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; @@ -36,7 +38,7 @@ * */ @XmlType(name = "configType", propOrder = { "url", "project", "projectVersion", - "projectType", "locales" }) + "projectType", "hooks", "locales" }) @XmlRootElement(name = "config") public class ZanataConfig implements Serializable { private static final long serialVersionUID = 1L; @@ -45,6 +47,7 @@ public class ZanataConfig implements Serializable { private URL url; private String projectType; private String projectVersion; + private List hooks = new ArrayList(); public ZanataConfig() { } @@ -59,6 +62,16 @@ public void setLocales(LocaleList locales) { this.locales = locales; } + @XmlElementWrapper(name = "hooks", required = false) + @XmlElement(name = "hook") + public List getHooks() { + return hooks; + } + + public void setHooks(List commandHooks) { + this.hooks = commandHooks; + } + @XmlElement(name = "project") public String getProject() { return project; @@ -94,4 +107,5 @@ public String getProjectVersion() { public void setProjectVersion(String version) { this.projectVersion = version; } + } From ddcca68cc6de2da7901fd019446bb334031d779e Mon Sep 17 00:00:00 2001 From: David Mason Date: Fri, 18 Oct 2013 17:14:51 +1000 Subject: [PATCH 02/11] add list of command hooks to project options --- .../commands/ConfigurableProjectOptions.java | 5 +++++ .../commands/ConfigurableProjectOptionsImpl.java | 13 +++++++++++++ .../org/zanata/maven/ConfigurableProjectMojo.java | 14 ++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java index 9020efc8..4b3af533 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java @@ -1,8 +1,10 @@ package org.zanata.client.commands; import java.io.File; +import java.util.List; import org.kohsuke.args4j.Option; +import org.zanata.client.config.CommandHook; import org.zanata.client.config.LocaleList; /** @@ -53,4 +55,7 @@ public interface ConfigurableProjectOptions extends ConfigurableOptions { public void setLocaleMapList(LocaleList locales); + public List getCommandHooks(); + + public void setCommandHooks(List commandHooks); } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java index d0c91f66..58c14dd8 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java @@ -21,8 +21,10 @@ package org.zanata.client.commands; import java.io.File; +import java.util.List; import org.kohsuke.args4j.Option; +import org.zanata.client.config.CommandHook; import org.zanata.client.config.LocaleList; /** @@ -47,6 +49,7 @@ public abstract class ConfigurableProjectOptionsImpl extends private String projectVersion; private String projectType; private LocaleList locales; + private List commandHooks; @Override public String getProj() { @@ -124,4 +127,14 @@ public void setLocaleMapList(LocaleList locales) { this.locales = locales; } + @Override + public void setCommandHooks(List commandHooks) { + this.commandHooks = commandHooks; + } + + @Override + public List getCommandHooks() { + return commandHooks; + } + } diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableProjectMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableProjectMojo.java index 19b1479b..da20b1f3 100644 --- a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableProjectMojo.java +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableProjectMojo.java @@ -1,9 +1,11 @@ package org.zanata.maven; import java.io.File; +import java.util.List; import org.zanata.client.commands.ConfigurableOptions; import org.zanata.client.commands.ConfigurableProjectOptions; +import org.zanata.client.config.CommandHook; import org.zanata.client.config.LocaleList; /** @@ -61,6 +63,8 @@ public abstract class ConfigurableProjectMojo private LocaleList localeMapList; + private List commandHooks; + public ConfigurableProjectMojo() { super(); } @@ -115,4 +119,14 @@ public void setLocaleMapList(LocaleList localeMapList) { this.localeMapList = localeMapList; } + @Override + public void setCommandHooks(List commandHooks) { + this.commandHooks = commandHooks; + } + + @Override + public List getCommandHooks() { + return commandHooks; + } + } From 317b862481e6962b2cf092c32646878de38d8e03 Mon Sep 17 00:00:00 2001 From: David Mason Date: Fri, 18 Oct 2013 17:16:20 +1000 Subject: [PATCH 03/11] populate command hooks in project options from zanata.xml --- .../src/main/java/org/zanata/client/commands/OptionsUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java index 16840967..cfca9798 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java @@ -90,6 +90,9 @@ private static void applyProjectConfig(ConfigurableProjectOptions opts, } LocaleList locales = config.getLocales(); opts.setLocaleMapList(locales); + + // command hooks cannot be set via parameters + opts.setCommandHooks(config.getHooks()); } /** From 9f466598ef7c0a32779b50dd0608b69254a88840 Mon Sep 17 00:00:00 2001 From: David Mason Date: Fri, 18 Oct 2013 17:19:33 +1000 Subject: [PATCH 04/11] Replace run() with performWork() below ConfigurableProjectCommand This prepares to split run() into phases to:- - run preparatory checks, possibly aborting - run "before" command - perform work - run "after" command To avoid the upfront cost of rewriting each implementation, this simple rename and wrapper will allow us to update subclasses as we have time. --- .../client/commands/ConfigurableProjectCommand.java | 8 ++++++++ .../java/org/zanata/client/commands/ListLocalCommand.java | 2 +- .../org/zanata/client/commands/ListRemoteCommand.java | 2 +- .../org/zanata/client/commands/PublicanPullCommand.java | 2 +- .../org/zanata/client/commands/PublicanPushCommand.java | 2 +- .../java/org/zanata/client/commands/pull/PullCommand.java | 2 +- .../org/zanata/client/commands/pull/RawPullCommand.java | 2 +- .../java/org/zanata/client/commands/push/PushCommand.java | 2 +- .../org/zanata/client/commands/push/RawPushCommand.java | 2 +- 9 files changed, 16 insertions(+), 8 deletions(-) diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java index 2aee2df3..e882a4e6 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java @@ -59,4 +59,12 @@ public ConfigurableProjectCommand(O opts) { protected String getProjectType() { return this.getOpts().getProjectType(); } + + + @Override + public void run() throws Exception { + performWork(); + }; + + protected abstract void performWork() throws Exception; } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ListLocalCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ListLocalCommand.java index e4564acc..66b90987 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ListLocalCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ListLocalCommand.java @@ -24,7 +24,7 @@ public ListLocalCommand(ConfigurableProjectOptions opts) { } @Override - public void run() { + public void performWork() { // TODO remove this log.debug("listlocal"); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ListRemoteCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ListRemoteCommand.java index 1ad954c4..b71c595f 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ListRemoteCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ListRemoteCommand.java @@ -43,7 +43,7 @@ public ListRemoteCommand(ConfigurableProjectOptions opts) { } @Override - public void run() throws Exception { + public void performWork() throws Exception { log.info("Server: " + getOpts().getUrl()); log.info("Project: " + getOpts().getProj()); log.info("Version: " + getOpts().getProjectVersion()); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPullCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPullCommand.java index 4e22c1e6..9ab4f313 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPullCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPullCommand.java @@ -68,7 +68,7 @@ protected String getProjectType() { } @Override - public void run() throws Exception { + public void performWork() throws Exception { log.info("Server: {}", getOpts().getUrl()); log.info("Project: {}", getOpts().getProj()); log.info("Version: {}", getOpts().getProjectVersion()); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPushCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPushCommand.java index 6987ec87..891e5cb0 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPushCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPushCommand.java @@ -79,7 +79,7 @@ protected String getProjectType() { } @Override - public void run() throws Exception { + public void performWork() throws Exception { log.info("Server: {}", getOpts().getUrl()); log.info("Project: {}", getOpts().getProj()); log.info("Version: {}", getOpts().getProjectVersion()); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java index 88165682..62600683 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java @@ -138,7 +138,7 @@ public static void logOptions(Logger logger, PullOptions opts) { } @Override - public void run() throws Exception { + public void performWork() throws Exception { logOptions(); LocaleList locales = getOpts().getLocaleMapList(); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java index 7d749508..f1ea0786 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java @@ -59,7 +59,7 @@ public RawPullCommand(PullOptions opts) { } @Override - public void run() throws Exception { + public void performWork() throws Exception { PullCommand.logOptions(log, getOpts()); if (getOpts().isDryRun()) { log.info("DRY RUN: no permanent changes will be made"); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java index 3b97895e..429cd84d 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java @@ -197,7 +197,7 @@ private boolean pushTrans() { } @Override - public void run() throws Exception { + public void performWork() throws Exception { logOptions(log, getOpts()); pushCurrentModule(); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/RawPushCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/RawPushCommand.java index b9a50fef..578f49ed 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/RawPushCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/RawPushCommand.java @@ -82,7 +82,7 @@ public RawPushCommand(PushOptions opts, ZanataProxyFactory factory, } @Override - public void run() throws Exception { + public void performWork() throws Exception { PushCommand.logOptions(log, getOpts()); log.warn("Using EXPERIMENTAL project type 'file'."); From cc94d9a4683e7d481563454340aaef4f4358b330 Mon Sep 17 00:00:00 2001 From: David Mason Date: Fri, 18 Oct 2013 17:52:17 +1000 Subject: [PATCH 05/11] run befores, command and afters in order, abort if any fails. Before and after commands will always run without waiting for command confirmation, but all remaining commands will be aborted if any command fails. Since the main use case of commands is to prepare files before push, waiting until after the initial analysis and confirmation does not make sense. For now I am implementing only the basic functionality that meets the use-case. --- .../commands/ConfigurableProjectCommand.java | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java index e882a4e6..146f0df2 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java @@ -20,6 +20,12 @@ */ package org.zanata.client.commands; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.zanata.client.commands.pull.PullCommand; +import org.zanata.client.config.CommandHook; import org.zanata.client.exceptions.ConfigException; import org.zanata.rest.client.ZanataProxyFactory; @@ -33,6 +39,9 @@ public abstract class ConfigurableProjectCommand extends ConfigurableCommand { + private static final Logger log = LoggerFactory + .getLogger(PullCommand.class); + protected static final String PROJECT_TYPE_UTF8_PROPERTIES = "utf8properties"; protected static final String PROJECT_TYPE_PROPERTIES = "properties"; @@ -60,11 +69,72 @@ protected String getProjectType() { return this.getOpts().getProjectType(); } - @Override public void run() throws Exception { + runBeforeActions(); performWork(); + runAfterActions(); }; protected abstract void performWork() throws Exception; + + /** + * @throws Exception + * if any of the commands fail + */ + private void runBeforeActions() throws Exception { + List hooks = getOpts().getCommandHooks(); + if (hooks != null) { + for (CommandHook hook : hooks) { + if (isForThisCommand(hook)) { + runSystemCommands(hook.getBefores()); + } + } + } + } + + /** + * @throws Exception + * if any of the commands fail. + */ + private void runAfterActions() throws Exception { + List hooks = getOpts().getCommandHooks(); + if (hooks != null) { + for (CommandHook hook : hooks) { + if (isForThisCommand(hook)) { + runSystemCommands(hook.getAfters()); + } + } + } + } + + /** + * @throws Exception + * if any of the commands fail. + */ + private void runSystemCommands(List commands) throws Exception { + for (String command : commands) { + log.info("[Running command]$ " + command); + try { + Process proc = Runtime.getRuntime().exec(command); + proc.waitFor(); + if (proc.exitValue() != 0) { + throw new Exception( + "Command returned non-zero exit value: " + + proc.exitValue()); + } + log.info(" Completed with exit value: " + proc.exitValue()); + } catch (java.io.IOException e) { + throw new Exception("Failed to run command. " + e.getMessage(), + e); + } catch (InterruptedException e) { + throw new Exception("Interrupted while running command. " + + e.getMessage(), e); + } + } + } + + private boolean isForThisCommand(CommandHook hook) { + return this.getName().equals(hook.getCommand()); + } } From db8f11eb5358e387f2ad18b25ba5ed98d4c67965 Mon Sep 17 00:00:00 2001 From: David Mason Date: Tue, 19 Nov 2013 10:04:22 +1000 Subject: [PATCH 06/11] prevent command hook list being null --- .../commands/ConfigurableProjectCommand.java | 18 ++++++------------ .../commands/ConfigurableProjectOptions.java | 6 ++++-- .../ConfigurableProjectOptionsImpl.java | 3 ++- .../zanata/client/commands/OptionsUtil.java | 8 ++++++-- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java index 146f0df2..ac4d4b5b 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java @@ -83,12 +83,9 @@ public void run() throws Exception { * if any of the commands fail */ private void runBeforeActions() throws Exception { - List hooks = getOpts().getCommandHooks(); - if (hooks != null) { - for (CommandHook hook : hooks) { - if (isForThisCommand(hook)) { - runSystemCommands(hook.getBefores()); - } + for (CommandHook hook : getOpts().getCommandHooks()) { + if (isForThisCommand(hook)) { + runSystemCommands(hook.getBefores()); } } } @@ -98,12 +95,9 @@ private void runBeforeActions() throws Exception { * if any of the commands fail. */ private void runAfterActions() throws Exception { - List hooks = getOpts().getCommandHooks(); - if (hooks != null) { - for (CommandHook hook : hooks) { - if (isForThisCommand(hook)) { - runSystemCommands(hook.getAfters()); - } + for (CommandHook hook : getOpts().getCommandHooks()) { + if (isForThisCommand(hook)) { + runSystemCommands(hook.getAfters()); } } } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java index 4b3af533..861d5cb3 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java @@ -3,6 +3,8 @@ import java.io.File; import java.util.List; +import javax.annotation.Nonnull; + import org.kohsuke.args4j.Option; import org.zanata.client.config.CommandHook; import org.zanata.client.config.LocaleList; @@ -55,7 +57,7 @@ public interface ConfigurableProjectOptions extends ConfigurableOptions { public void setLocaleMapList(LocaleList locales); - public List getCommandHooks(); + public @Nonnull List getCommandHooks(); - public void setCommandHooks(List commandHooks); + public void setCommandHooks(@Nonnull List commandHooks); } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java index 58c14dd8..f4b60365 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java @@ -21,6 +21,7 @@ package org.zanata.client.commands; import java.io.File; +import java.util.ArrayList; import java.util.List; import org.kohsuke.args4j.Option; @@ -49,7 +50,7 @@ public abstract class ConfigurableProjectOptionsImpl extends private String projectVersion; private String projectType; private LocaleList locales; - private List commandHooks; + private List commandHooks = new ArrayList(); @Override public String getProj() { diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java index cfca9798..23af7c97 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java @@ -2,6 +2,7 @@ import java.io.File; import java.net.URISyntaxException; +import java.util.ArrayList; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -12,6 +13,7 @@ import org.apache.commons.configuration.SubnodeConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.zanata.client.config.CommandHook; import org.zanata.client.config.ConfigUtil; import org.zanata.client.config.LocaleList; import org.zanata.client.config.ZanataConfig; @@ -91,8 +93,10 @@ private static void applyProjectConfig(ConfigurableProjectOptions opts, LocaleList locales = config.getLocales(); opts.setLocaleMapList(locales); - // command hooks cannot be set via parameters - opts.setCommandHooks(config.getHooks()); + if (opts.getCommandHooks() == null || opts.getCommandHooks().isEmpty()) { + opts.setCommandHooks(config.getHooks() == null ? new ArrayList() + : config.getHooks()); + } } /** From 407065e6e7f37b6cd092ae057af35217c169ac2c Mon Sep 17 00:00:00 2001 From: David Mason Date: Tue, 26 Nov 2013 17:33:05 +1000 Subject: [PATCH 07/11] move command hooks to top level of Options hierarchy --- .../org/zanata/client/commands/BasicOptions.java | 9 +++++++++ .../zanata/client/commands/BasicOptionsImpl.java | 16 ++++++++++++++++ .../client/commands/ConfigurableOptions.java | 4 ++++ .../commands/ConfigurableProjectOptions.java | 7 ------- .../commands/ConfigurableProjectOptionsImpl.java | 14 -------------- .../org/zanata/client/commands/OptionsUtil.java | 5 ++--- .../java/org/zanata/maven/ConfigurableMojo.java | 14 ++++++++++++++ .../zanata/maven/ConfigurableProjectMojo.java | 14 -------------- 8 files changed, 45 insertions(+), 38 deletions(-) diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/BasicOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/BasicOptions.java index 43397cdf..322bd346 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/BasicOptions.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/BasicOptions.java @@ -1,5 +1,11 @@ package org.zanata.client.commands; +import java.util.List; + +import javax.annotation.Nonnull; + +import org.zanata.client.config.CommandHook; + public interface BasicOptions { ZanataCommand initCommand(); @@ -64,4 +70,7 @@ public interface BasicOptions { */ public String getCommandDescription(); + public @Nonnull List getCommandHooks(); + + public void setCommandHooks(@Nonnull List commandHooks); } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/BasicOptionsImpl.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/BasicOptionsImpl.java index caedae0e..c0292933 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/BasicOptionsImpl.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/BasicOptionsImpl.java @@ -20,7 +20,11 @@ */ package org.zanata.client.commands; +import java.util.ArrayList; +import java.util.List; + import org.kohsuke.args4j.Option; +import org.zanata.client.config.CommandHook; /** * Base class for commands @@ -38,6 +42,7 @@ public abstract class BasicOptionsImpl implements BasicOptions { private boolean quiet = false; private boolean quietSet; private boolean interactiveMode = true; + private List commandHooks = new ArrayList(); public BasicOptionsImpl() { } @@ -127,4 +132,15 @@ public boolean isErrorsSet() { public boolean isQuietSet() { return quietSet; } + + @Override + public void setCommandHooks(List commandHooks) { + this.commandHooks = commandHooks; + } + + @Override + public List getCommandHooks() { + return commandHooks; + } + } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableOptions.java index 360ef3d3..5eb944b6 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableOptions.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableOptions.java @@ -2,8 +2,12 @@ import java.io.File; import java.net.URL; +import java.util.List; + +import javax.annotation.Nonnull; import org.kohsuke.args4j.Option; +import org.zanata.client.config.CommandHook; /** * Base options for commands which supports configuration by the user's diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java index 861d5cb3..cc8dcbae 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptions.java @@ -1,12 +1,9 @@ package org.zanata.client.commands; import java.io.File; -import java.util.List; -import javax.annotation.Nonnull; import org.kohsuke.args4j.Option; -import org.zanata.client.config.CommandHook; import org.zanata.client.config.LocaleList; /** @@ -56,8 +53,4 @@ public interface ConfigurableProjectOptions extends ConfigurableOptions { public LocaleList getLocaleMapList(); public void setLocaleMapList(LocaleList locales); - - public @Nonnull List getCommandHooks(); - - public void setCommandHooks(@Nonnull List commandHooks); } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java index f4b60365..d0c91f66 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectOptionsImpl.java @@ -21,11 +21,8 @@ package org.zanata.client.commands; import java.io.File; -import java.util.ArrayList; -import java.util.List; import org.kohsuke.args4j.Option; -import org.zanata.client.config.CommandHook; import org.zanata.client.config.LocaleList; /** @@ -50,7 +47,6 @@ public abstract class ConfigurableProjectOptionsImpl extends private String projectVersion; private String projectType; private LocaleList locales; - private List commandHooks = new ArrayList(); @Override public String getProj() { @@ -128,14 +124,4 @@ public void setLocaleMapList(LocaleList locales) { this.locales = locales; } - @Override - public void setCommandHooks(List commandHooks) { - this.commandHooks = commandHooks; - } - - @Override - public List getCommandHooks() { - return commandHooks; - } - } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java index 23af7c97..2f4a2baa 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java @@ -93,9 +93,8 @@ private static void applyProjectConfig(ConfigurableProjectOptions opts, LocaleList locales = config.getLocales(); opts.setLocaleMapList(locales); - if (opts.getCommandHooks() == null || opts.getCommandHooks().isEmpty()) { - opts.setCommandHooks(config.getHooks() == null ? new ArrayList() - : config.getHooks()); + if (opts.getCommandHooks().isEmpty() && config.getHooks() != null) { + opts.setCommandHooks(config.getHooks()); } } diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java index 83d7fc08..9e8d35d9 100644 --- a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java @@ -2,6 +2,7 @@ import java.io.File; import java.net.URL; +import java.util.List; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; @@ -10,6 +11,7 @@ import org.zanata.client.commands.ConfigurableOptions; import org.zanata.client.commands.OptionsUtil; import org.zanata.client.commands.ZanataCommand; +import org.zanata.client.config.CommandHook; import com.pyx4j.log4j.MavenLogAppender; @@ -71,6 +73,8 @@ public abstract class ConfigurableMojo extends */ private String key; + private List commandHooks; + /** * Interactive mode is enabled by default, but can be disabled using Maven's * -B/--batch-mode option. @@ -273,6 +277,16 @@ public File getUserConfig() { return userConfig; } + @Override + public void setCommandHooks(List commandHooks) { + this.commandHooks = commandHooks; + } + + @Override + public List getCommandHooks() { + return commandHooks; + } + @Override public boolean getLogHttp() { return logHttp; diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableProjectMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableProjectMojo.java index da20b1f3..19b1479b 100644 --- a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableProjectMojo.java +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableProjectMojo.java @@ -1,11 +1,9 @@ package org.zanata.maven; import java.io.File; -import java.util.List; import org.zanata.client.commands.ConfigurableOptions; import org.zanata.client.commands.ConfigurableProjectOptions; -import org.zanata.client.config.CommandHook; import org.zanata.client.config.LocaleList; /** @@ -63,8 +61,6 @@ public abstract class ConfigurableProjectMojo private LocaleList localeMapList; - private List commandHooks; - public ConfigurableProjectMojo() { super(); } @@ -119,14 +115,4 @@ public void setLocaleMapList(LocaleList localeMapList) { this.localeMapList = localeMapList; } - @Override - public void setCommandHooks(List commandHooks) { - this.commandHooks = commandHooks; - } - - @Override - public List getCommandHooks() { - return commandHooks; - } - } From 076b558804cdebd66ac967e1701108f2d5d1526a Mon Sep 17 00:00:00 2001 From: David Mason Date: Tue, 26 Nov 2013 17:37:05 +1000 Subject: [PATCH 08/11] move handling of command hooks to top of command hierarchy --- .../org/zanata/client/ZanataClientTest.java | 2 +- .../org/zanata/client/commands/ArgsUtil.java | 3 +- .../client/commands/ConfigurableCommand.java | 71 ++++++++++++++++++ .../client/commands/ConfigurableOptions.java | 3 - .../commands/ConfigurableProjectCommand.java | 72 ------------------- .../client/commands/ListLocalCommand.java | 2 +- .../client/commands/ListRemoteCommand.java | 2 +- .../zanata/client/commands/OptionsUtil.java | 2 - .../client/commands/PublicanPullCommand.java | 2 +- .../client/commands/PublicanPushCommand.java | 2 +- .../zanata/client/commands/ZanataCommand.java | 2 +- .../client/commands/pull/PullCommand.java | 2 +- .../client/commands/pull/RawPullCommand.java | 2 +- .../client/commands/push/PushCommand.java | 2 +- .../client/commands/push/RawPushCommand.java | 2 +- .../pull/PublicanPullCommandTest.java | 2 +- .../push/PublicanPushCommandTest.java | 2 +- .../client/commands/push/PushCommandTest.java | 2 +- .../org/zanata/maven/ConfigurableMojo.java | 2 +- .../java/org/zanata/maven/ZanataMojoTest.java | 2 +- 20 files changed, 87 insertions(+), 94 deletions(-) diff --git a/zanata-cli/src/test/java/org/zanata/client/ZanataClientTest.java b/zanata-cli/src/test/java/org/zanata/client/ZanataClientTest.java index d24c8f00..f323691c 100644 --- a/zanata-cli/src/test/java/org/zanata/client/ZanataClientTest.java +++ b/zanata-cli/src/test/java/org/zanata/client/ZanataClientTest.java @@ -189,7 +189,7 @@ Mockito. anyObject())).thenReturn( verify(mockOptions).setUrl(new URL(url)); verify(mockOptions).setProj(project); verify(mockOptions).setProjectVersion(version); - verify(mockCommand).run(); + verify(mockCommand).runWithActions(); } /** diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ArgsUtil.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ArgsUtil.java index 711c445e..011af594 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ArgsUtil.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ArgsUtil.java @@ -3,7 +3,6 @@ */ package org.zanata.client.commands; -import java.io.PrintStream; import java.io.PrintWriter; import org.apache.log4j.Level; @@ -46,7 +45,7 @@ public void runCommand() { log.info("Error stacktraces are turned on."); } ZanataCommand cmd = opts.initCommand(); - cmd.run(); + cmd.runWithActions(); } catch (Exception e) { handleException(e, opts.getErrors(), abortStrategy); } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java index 61032546..e3e6a0d8 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java @@ -20,6 +20,11 @@ */ package org.zanata.client.commands; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.zanata.client.config.CommandHook; import org.zanata.rest.client.ZanataProxyFactory; /** @@ -35,6 +40,10 @@ public abstract class ConfigurableCommand private boolean deprecated; private String deprecationMessage; + + private static final Logger log = LoggerFactory + .getLogger(ConfigurableCommand.class); + public ConfigurableCommand(O opts, ZanataProxyFactory factory) { this.opts = opts; if (factory != null) @@ -75,4 +84,66 @@ public String getName() { return opts.getCommandName(); } + @Override + public void runWithActions() throws Exception { + runBeforeActions(); + run(); + runAfterActions(); + }; + + protected abstract void run() throws Exception; + + /** + * @throws Exception + * if any of the commands fail + */ + private void runBeforeActions() throws Exception { + for (CommandHook hook : getOpts().getCommandHooks()) { + if (isForThisCommand(hook)) { + runSystemCommands(hook.getBefores()); + } + } + } + + /** + * @throws Exception + * if any of the commands fail. + */ + private void runAfterActions() throws Exception { + for (CommandHook hook : getOpts().getCommandHooks()) { + if (isForThisCommand(hook)) { + runSystemCommands(hook.getAfters()); + } + } + } + + /** + * @throws Exception + * if any of the commands fail. + */ + private void runSystemCommands(List commands) throws Exception { + for (String command : commands) { + log.info("[Running command]$ " + command); + try { + Process proc = Runtime.getRuntime().exec(command); + proc.waitFor(); + if (proc.exitValue() != 0) { + throw new Exception( + "Command returned non-zero exit value: " + + proc.exitValue()); + } + log.info(" Completed with exit value: " + proc.exitValue()); + } catch (java.io.IOException e) { + throw new Exception("Failed to run command. " + e.getMessage(), + e); + } catch (InterruptedException e) { + throw new Exception("Interrupted while running command. " + + e.getMessage(), e); + } + } + } + + private boolean isForThisCommand(CommandHook hook) { + return this.getName().equals(hook.getCommand()); + } } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableOptions.java index 5eb944b6..dad5d62f 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableOptions.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableOptions.java @@ -2,12 +2,9 @@ import java.io.File; import java.net.URL; -import java.util.List; -import javax.annotation.Nonnull; import org.kohsuke.args4j.Option; -import org.zanata.client.config.CommandHook; /** * Base options for commands which supports configuration by the user's diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java index ac4d4b5b..2aee2df3 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableProjectCommand.java @@ -20,12 +20,6 @@ */ package org.zanata.client.commands; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.zanata.client.commands.pull.PullCommand; -import org.zanata.client.config.CommandHook; import org.zanata.client.exceptions.ConfigException; import org.zanata.rest.client.ZanataProxyFactory; @@ -39,9 +33,6 @@ public abstract class ConfigurableProjectCommand extends ConfigurableCommand { - private static final Logger log = LoggerFactory - .getLogger(PullCommand.class); - protected static final String PROJECT_TYPE_UTF8_PROPERTIES = "utf8properties"; protected static final String PROJECT_TYPE_PROPERTIES = "properties"; @@ -68,67 +59,4 @@ public ConfigurableProjectCommand(O opts) { protected String getProjectType() { return this.getOpts().getProjectType(); } - - @Override - public void run() throws Exception { - runBeforeActions(); - performWork(); - runAfterActions(); - }; - - protected abstract void performWork() throws Exception; - - /** - * @throws Exception - * if any of the commands fail - */ - private void runBeforeActions() throws Exception { - for (CommandHook hook : getOpts().getCommandHooks()) { - if (isForThisCommand(hook)) { - runSystemCommands(hook.getBefores()); - } - } - } - - /** - * @throws Exception - * if any of the commands fail. - */ - private void runAfterActions() throws Exception { - for (CommandHook hook : getOpts().getCommandHooks()) { - if (isForThisCommand(hook)) { - runSystemCommands(hook.getAfters()); - } - } - } - - /** - * @throws Exception - * if any of the commands fail. - */ - private void runSystemCommands(List commands) throws Exception { - for (String command : commands) { - log.info("[Running command]$ " + command); - try { - Process proc = Runtime.getRuntime().exec(command); - proc.waitFor(); - if (proc.exitValue() != 0) { - throw new Exception( - "Command returned non-zero exit value: " - + proc.exitValue()); - } - log.info(" Completed with exit value: " + proc.exitValue()); - } catch (java.io.IOException e) { - throw new Exception("Failed to run command. " + e.getMessage(), - e); - } catch (InterruptedException e) { - throw new Exception("Interrupted while running command. " - + e.getMessage(), e); - } - } - } - - private boolean isForThisCommand(CommandHook hook) { - return this.getName().equals(hook.getCommand()); - } } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ListLocalCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ListLocalCommand.java index 66b90987..e4564acc 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ListLocalCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ListLocalCommand.java @@ -24,7 +24,7 @@ public ListLocalCommand(ConfigurableProjectOptions opts) { } @Override - public void performWork() { + public void run() { // TODO remove this log.debug("listlocal"); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ListRemoteCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ListRemoteCommand.java index b71c595f..1ad954c4 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ListRemoteCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ListRemoteCommand.java @@ -43,7 +43,7 @@ public ListRemoteCommand(ConfigurableProjectOptions opts) { } @Override - public void performWork() throws Exception { + public void run() throws Exception { log.info("Server: " + getOpts().getUrl()); log.info("Project: " + getOpts().getProj()); log.info("Version: " + getOpts().getProjectVersion()); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java index 2f4a2baa..e217fe64 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java @@ -2,7 +2,6 @@ import java.io.File; import java.net.URISyntaxException; -import java.util.ArrayList; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -13,7 +12,6 @@ import org.apache.commons.configuration.SubnodeConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.zanata.client.config.CommandHook; import org.zanata.client.config.ConfigUtil; import org.zanata.client.config.LocaleList; import org.zanata.client.config.ZanataConfig; diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPullCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPullCommand.java index 9ab4f313..4e22c1e6 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPullCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPullCommand.java @@ -68,7 +68,7 @@ protected String getProjectType() { } @Override - public void performWork() throws Exception { + public void run() throws Exception { log.info("Server: {}", getOpts().getUrl()); log.info("Project: {}", getOpts().getProj()); log.info("Version: {}", getOpts().getProjectVersion()); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPushCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPushCommand.java index 891e5cb0..6987ec87 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPushCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/PublicanPushCommand.java @@ -79,7 +79,7 @@ protected String getProjectType() { } @Override - public void performWork() throws Exception { + public void run() throws Exception { log.info("Server: {}", getOpts().getUrl()); log.info("Project: {}", getOpts().getProj()); log.info("Version: {}", getOpts().getProjectVersion()); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ZanataCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ZanataCommand.java index 5881d035..cb9d6616 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ZanataCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ZanataCommand.java @@ -5,7 +5,7 @@ public interface ZanataCommand { * Executes the command, using the parameters which have been previously * set. This method must be called after initConfig(). */ - public void run() throws Exception; + public void runWithActions() throws Exception; /** * Returns true if the command has been deprecated. diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java index 62600683..88165682 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/PullCommand.java @@ -138,7 +138,7 @@ public static void logOptions(Logger logger, PullOptions opts) { } @Override - public void performWork() throws Exception { + public void run() throws Exception { logOptions(); LocaleList locales = getOpts().getLocaleMapList(); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java index f1ea0786..7d749508 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/pull/RawPullCommand.java @@ -59,7 +59,7 @@ public RawPullCommand(PullOptions opts) { } @Override - public void performWork() throws Exception { + public void run() throws Exception { PullCommand.logOptions(log, getOpts()); if (getOpts().isDryRun()) { log.info("DRY RUN: no permanent changes will be made"); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java index e1b0486d..2a43c77f 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java @@ -198,7 +198,7 @@ private boolean pushTrans() { } @Override - public void performWork() throws Exception { + public void run() throws Exception { logOptions(log, getOpts()); pushCurrentModule(); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/RawPushCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/RawPushCommand.java index 578f49ed..b9a50fef 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/RawPushCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/RawPushCommand.java @@ -82,7 +82,7 @@ public RawPushCommand(PushOptions opts, ZanataProxyFactory factory, } @Override - public void performWork() throws Exception { + public void run() throws Exception { PushCommand.logOptions(log, getOpts()); log.warn("Using EXPERIMENTAL project type 'file'."); diff --git a/zanata-client-commands/src/test/java/org/zanata/client/commands/pull/PublicanPullCommandTest.java b/zanata-client-commands/src/test/java/org/zanata/client/commands/pull/PublicanPullCommandTest.java index df5ce407..1ef0a425 100644 --- a/zanata-client-commands/src/test/java/org/zanata/client/commands/pull/PublicanPullCommandTest.java +++ b/zanata-client-commands/src/test/java/org/zanata/client/commands/pull/PublicanPullCommandTest.java @@ -117,7 +117,7 @@ private void publicanPull(boolean exportPot, boolean mapLocale) new PublicanPullCommand(opts, mockRequestFactory, mockSourceDocResource, mockTranslationResources, new URI("http://example.com/")); - cmd.run(); + cmd.runWithActions(); } private void mockExpectGetTranslationsAndReturnResponse(String id, diff --git a/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PublicanPushCommandTest.java b/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PublicanPushCommandTest.java index 2d10260c..8b7b2234 100644 --- a/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PublicanPushCommandTest.java +++ b/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PublicanPushCommandTest.java @@ -118,7 +118,7 @@ private void publicanPush(boolean importPo, boolean mapLocale) new PublicanPushCommand(opts, mockRequestFactory, mockSourceDocResource, mockTranslationResources, new URI("http://example.com/")); - cmd.run(); + cmd.runWithActions(); } } diff --git a/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PushCommandTest.java b/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PushCommandTest.java index eac07a48..74645101 100644 --- a/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PushCommandTest.java +++ b/zanata-client-commands/src/test/java/org/zanata/client/commands/push/PushCommandTest.java @@ -227,7 +227,7 @@ private void push(boolean pushTrans, boolean mapLocale) throws Exception { // .thenReturn(okResponse); } ZanataCommand cmd = generatePushCommand(pushTrans, mapLocale); - cmd.run(); + cmd.runWithActions(); } } diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java index 9e8d35d9..358dd37a 100644 --- a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java @@ -156,7 +156,7 @@ protected void runCommand() throws Exception { getLog().warn("Command \"" + name + "\" has been deprecated"); } } - command.run(); + command.runWithActions(); } public abstract ConfigurableCommand initCommand(); diff --git a/zanata-maven-plugin/src/test/java/org/zanata/maven/ZanataMojoTest.java b/zanata-maven-plugin/src/test/java/org/zanata/maven/ZanataMojoTest.java index 76a00346..ce34301c 100644 --- a/zanata-maven-plugin/src/test/java/org/zanata/maven/ZanataMojoTest.java +++ b/zanata-maven-plugin/src/test/java/org/zanata/maven/ZanataMojoTest.java @@ -38,7 +38,7 @@ protected void applyPomParams(String pomFile) throws Exception { // This will work with "mvn test", but not with Eclipse's JUnit runner: // PushSimpleMojo mojo = (PushSimpleMojo) lookupMojo("push", testPom); // assertNotNull(mojo); - getMockCommand().run(); + getMockCommand().runWithActions(); EasyMock.expectLastCall(); control.replay(); configureMojo(getMojo(), "zanata-maven-plugin", testPom); From 5e233a2487787af29867f29015e7040d7c73585f Mon Sep 17 00:00:00 2001 From: David Mason Date: Wed, 27 Nov 2013 09:54:04 +1000 Subject: [PATCH 09/11] rhbz978072 add default empty list of command hooks in Maven Plugin --- .../src/main/java/org/zanata/maven/ConfigurableMojo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java index 358dd37a..bd3edccc 100644 --- a/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/ConfigurableMojo.java @@ -2,6 +2,7 @@ import java.io.File; import java.net.URL; +import java.util.ArrayList; import java.util.List; import org.apache.maven.plugin.AbstractMojo; @@ -73,7 +74,7 @@ public abstract class ConfigurableMojo extends */ private String key; - private List commandHooks; + private List commandHooks = new ArrayList(); /** * Interactive mode is enabled by default, but can be disabled using Maven's From 81e875aefbbeeef0c8b117fe22db2cb9cc639d5b Mon Sep 17 00:00:00 2001 From: David Mason Date: Wed, 27 Nov 2013 12:23:14 +1000 Subject: [PATCH 10/11] rhbz978072 add javadoc for command hooks and related methods --- .../client/commands/ConfigurableCommand.java | 6 +++- .../zanata/client/commands/ZanataCommand.java | 9 +++-- .../org/zanata/client/config/CommandHook.java | 33 +++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java index e3e6a0d8..624930ab 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java @@ -40,7 +40,6 @@ public abstract class ConfigurableCommand private boolean deprecated; private String deprecationMessage; - private static final Logger log = LoggerFactory .getLogger(ConfigurableCommand.class); @@ -91,6 +90,11 @@ public void runWithActions() throws Exception { runAfterActions(); }; + /** + * Runs the specific command, not including before- or after- actions. + * + * @throws Exception + */ protected abstract void run() throws Exception; /** diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ZanataCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ZanataCommand.java index cb9d6616..ba7d0194 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ZanataCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ZanataCommand.java @@ -2,8 +2,13 @@ public interface ZanataCommand { /** - * Executes the command, using the parameters which have been previously - * set. This method must be called after initConfig(). + * Executes before-actions, the command, then after-actions. Before- and + * after-actions are specified in command hooks, and will be skipped if they + * are not supported for the command or if none are specified. The command + * is executed using the parameters which have been previously set. This + * method must be called after initConfig(). + * + * @see {@link org.zanata.client.config.CommandHook} */ public void runWithActions() throws Exception; diff --git a/zanata-client-commands/src/main/java/org/zanata/client/config/CommandHook.java b/zanata-client-commands/src/main/java/org/zanata/client/config/CommandHook.java index 179dadd1..49d4eafe 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/config/CommandHook.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/config/CommandHook.java @@ -29,6 +29,39 @@ import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlType; +/** + *

Optional element used to attach system commands to run before or after a + * Zanata command (the "hooked command"). The hooked command is specified in the + * "command" attribute.

+ * + *

Include {@code } elements within a {@code } element in the + * {@code } element of zanata.xml. Each command should have zero or one + * hooks. Each hook can have any number of {@code } and {@code } + * elements.

+ * + *

Commands specified in {@code } elements will be run before the hooked + * command, in the order that they are specified. Commands specified in + * {@code } elements are similarly run in order after the hooked command + * successfully completes. If any command fails, including the hooked command, + * no further commands will be run.

+ * + * e.g. + * + *
+ * {@code
+ * 
+ *   
+ *     po4a-gettextize -f man -m manpage.1 -p manpage.pot
+ *     rm -f manpage.pot
+ *   
+ *   
+ *     po4a-translate -f man -m manpage.1 -p trans/de/manpage.po -l manpage.de.1 --keep 1
+ *     rm -rf trans
+ *   
+ * 
+ * }
+ * 
+ */ @XmlType(name = "hookType", propOrder = { "befores", "afters" }) public class CommandHook implements Serializable { From 590033401d3702fd032c080a91b471a5b073846b Mon Sep 17 00:00:00 2001 From: David Mason Date: Wed, 27 Nov 2013 13:35:54 +1000 Subject: [PATCH 11/11] rhbz978072 show command hook output and ensure child processes will be terminated properly --- zanata-client-commands/pom.xml | 7 +++++++ .../client/commands/ConfigurableCommand.java | 18 +++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/zanata-client-commands/pom.xml b/zanata-client-commands/pom.xml index 83084b47..75082e9c 100644 --- a/zanata-client-commands/pom.xml +++ b/zanata-client-commands/pom.xml @@ -141,5 +141,12 @@ ant 1.8.2 + + + org.apache.commons + commons-exec + 1.1 + + diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java index 624930ab..11e8a47c 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableCommand.java @@ -22,6 +22,11 @@ import java.util.List; +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.exec.LogOutputStream; +import org.apache.commons.exec.ShutdownHookProcessDestroyer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zanata.client.config.CommandHook; @@ -129,14 +134,17 @@ private void runSystemCommands(List commands) throws Exception { for (String command : commands) { log.info("[Running command]$ " + command); try { - Process proc = Runtime.getRuntime().exec(command); - proc.waitFor(); - if (proc.exitValue() != 0) { + DefaultExecutor executor = new DefaultExecutor(); + executor.setProcessDestroyer(new ShutdownHookProcessDestroyer()); + CommandLine cmdLine = CommandLine.parse(command); + int exitValue = executor.execute(cmdLine); + + if (exitValue != 0) { throw new Exception( "Command returned non-zero exit value: " - + proc.exitValue()); + + exitValue); } - log.info(" Completed with exit value: " + proc.exitValue()); + log.info(" Completed with exit value: " + exitValue); } catch (java.io.IOException e) { throw new Exception("Failed to run command. " + e.getMessage(), e);