Merge changes Id139d43f,I906eac5e
* changes:
Revert "Allow REST endpoints and SSH commands to accept and handle unknown options"
Revert "Ignore unknown plugin options in REST endpoints that support dynamic options"
diff --git a/java/com/google/gerrit/server/DynamicOptions.java b/java/com/google/gerrit/server/DynamicOptions.java
index 90bb50b..44d3493 100644
--- a/java/com/google/gerrit/server/DynamicOptions.java
+++ b/java/com/google/gerrit/server/DynamicOptions.java
@@ -14,12 +14,9 @@
package com.google.gerrit.server;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.server.plugins.DelegatingClassLoader;
import com.google.gerrit.util.cli.CmdLineParser;
-import com.google.gerrit.util.cli.UnknownOptionHandler;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
@@ -33,8 +30,6 @@
/** Helper class to define and parse options from plugins on ssh and RestAPI commands. */
public class DynamicOptions {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
/**
* To provide additional options, bind a DynamicBean. For example:
*
@@ -156,7 +151,7 @@
* }
* </pre>
*/
- public interface BeanReceiver extends UnknownOptionHandler {
+ public interface BeanReceiver {
void setDynamicBean(String plugin, DynamicBean dynamicBean);
/**
@@ -169,17 +164,6 @@
default Class<? extends BeanReceiver> getExportedBeanReceiver() {
return getClass();
}
-
- @Override
- default boolean accept(String name, @Nullable String value) {
- // Ignore unknown plugin options, so that callers who set a plugin option do not fail if the
- // plugin is disabled.
- boolean isPluginOption = UnknownOptionHandler.isPluginOption(name);
- if (isPluginOption) {
- logger.atFine().log("Unknown plugin option %s is ignored.", name);
- }
- return isPluginOption;
- }
}
public interface BeanProvider {
diff --git a/java/com/google/gerrit/util/cli/CmdLineParser.java b/java/com/google/gerrit/util/cli/CmdLineParser.java
index d8b9b58..1c430fc 100644
--- a/java/com/google/gerrit/util/cli/CmdLineParser.java
+++ b/java/com/google/gerrit/util/cli/CmdLineParser.java
@@ -314,32 +314,26 @@
public void parseOptionMap(ListMultimap<String, String> params) throws CmdLineException {
logger.atFinest().log("Command-line parameters: %s", params.keySet());
- List<String> knownArgs = Lists.newArrayListWithCapacity(2 * params.size());
+ List<String> tmp = Lists.newArrayListWithCapacity(2 * params.size());
for (String key : params.keySet()) {
String name = makeOption(key);
- if (isKnownOption(name)) {
- if (isBooleanOption(name)) {
- boolean on = false;
- for (String value : params.get(key)) {
- on = toBoolean(key, value);
- }
- if (on) {
- knownArgs.add(name);
- }
- } else {
- for (String value : params.get(key)) {
- knownArgs.add(name);
- knownArgs.add(value);
- }
+ if (isBooleanOption(name)) {
+ boolean on = false;
+ for (String value : params.get(key)) {
+ on = toBoolean(key, value);
+ }
+ if (on) {
+ tmp.add(name);
}
} else {
for (String value : params.get(key)) {
- parser.handleUnknownOption(name, value);
+ tmp.add(name);
+ tmp.add(value);
}
}
}
- parser.parseArgument(knownArgs.toArray(new String[knownArgs.size()]));
+ parser.parseArgument(tmp.toArray(new String[tmp.size()]));
}
public void parseWithPrefix(String prefix, Object bean) {
@@ -365,10 +359,6 @@
return name;
}
- private boolean isKnownOption(String name) {
- return findHandler(name) != null;
- }
-
@SuppressWarnings("rawtypes")
private OptionHandler findHandler(String name) {
if (options == null) {
@@ -436,8 +426,6 @@
}
public class MyParser extends org.kohsuke.args4j.CmdLineParser {
- private final Object bean;
-
boolean help;
@SuppressWarnings("rawtypes")
@@ -465,22 +453,11 @@
MyParser(Object bean) {
super(bean, ParserProperties.defaults().withAtSyntax(false));
- this.bean = bean;
parseAdditionalOptions(bean, new HashSet<>());
addOptionsWithMetRequirements();
ensureOptionsInitialized();
}
- public void handleUnknownOption(String name, String value) throws CmdLineException {
- if (bean instanceof UnknownOptionHandler
- && ((UnknownOptionHandler) bean).accept(name, Strings.emptyToNull(value))) {
- return;
- }
-
- // Parse argument to trigger a CmdLineException for the unknown option.
- parseArgument(name, value);
- }
-
public int addOptionsWithMetRequirements() {
int count = 0;
for (Iterator<Map.Entry<String, QueuedOption>> it = queuedOptionsByName.entrySet().iterator();
diff --git a/java/com/google/gerrit/util/cli/UnknownOptionHandler.java b/java/com/google/gerrit/util/cli/UnknownOptionHandler.java
deleted file mode 100644
index 8d47765..0000000
--- a/java/com/google/gerrit/util/cli/UnknownOptionHandler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.util.cli;
-
-import com.google.gerrit.common.Nullable;
-
-/**
- * Classes that define command-line options by using the {@link org.kohsuke.args4j.Option}
- * annotation can implement this class to accept and handle unknown options.
- *
- * <p>If a user specifies an unknown option and this unknown option doesn't get accepted, the
- * parsing of the command-line options fails and the user gets an error (this is the default
- * behavior if classes do not implement this interface).
- */
-public interface UnknownOptionHandler {
- /**
- * Checks whether the given option name matches the naming pattern of options that are defined by
- * plugins that were defined by registering a {@link
- * com.google.gerrit.server.DynamicOptions.DynamicBean}.
- *
- * @param optionName name of the option
- * @return {@code true} if it's a plugin option, otherwise {@code false}
- */
- public static boolean isPluginOption(String optionName) {
- // Options from plugins have the following name pattern: '--<plugin-name>--<option-name>'
- if (optionName.startsWith("--")) {
- optionName = optionName.substring(2);
- }
- return optionName.contains("--");
- }
-
- /**
- * Whether an unknown option should be accepted.
- *
- * <p>If an unknown option is not accepted, the parsing of the command-line options fails and the
- * user gets an error.
- *
- * <p>This method can be used to ignore unknown options (without failure for the user) or to
- * handle them.
- *
- * @param name the name of an unknown option that was provided by the user
- * @param value the value of the unknown option that was provided by the user
- * @return whether this unknown options is accepted
- */
- boolean accept(String name, @Nullable String value);
-}
diff --git a/javatests/com/google/gerrit/acceptance/rest/BUILD b/javatests/com/google/gerrit/acceptance/rest/BUILD
index c766934..84887da 100644
--- a/javatests/com/google/gerrit/acceptance/rest/BUILD
+++ b/javatests/com/google/gerrit/acceptance/rest/BUILD
@@ -6,6 +6,5 @@
labels = ["rest"],
deps = [
"//java/com/google/gerrit/server/logging",
- "//java/com/google/gerrit/util/cli",
],
)
diff --git a/javatests/com/google/gerrit/acceptance/rest/UnknownOptionIT.java b/javatests/com/google/gerrit/acceptance/rest/UnknownOptionIT.java
deleted file mode 100644
index 99c727e..0000000
--- a/javatests/com/google/gerrit/acceptance/rest/UnknownOptionIT.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.acceptance.rest;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.server.change.ChangeResource.CHANGE_KIND;
-import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
-import static org.apache.http.HttpStatus.SC_OK;
-
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.RestResponse;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.restapi.Response;
-import com.google.gerrit.extensions.restapi.RestApiModule;
-import com.google.gerrit.extensions.restapi.RestReadView;
-import com.google.gerrit.server.change.ChangeResource;
-import com.google.gerrit.util.cli.UnknownOptionHandler;
-import com.google.inject.Module;
-import org.junit.Test;
-
-public class UnknownOptionIT extends AbstractDaemonTest {
- @Override
- public Module createModule() {
- return new RestApiModule() {
- @Override
- protected void configure() {
- get(CHANGE_KIND, "test").to(MyChangeView.class);
- }
- };
- }
-
- @Test
- public void unknownOptionIsRejectedIfRestEndpointDoesNotHandleUnknownOptions() throws Exception {
- RestResponse response = adminRestSession.get("/accounts/self/detail?foo-bar");
- assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);
- }
-
- @Test
- public void unknownOptionIsIgnoredIfRestEndpointAcceptsIt() throws Exception {
- String changeId = createChange().getChangeId();
- RestResponse response = adminRestSession.get("/changes/" + changeId + "/test?ignore-foo");
- assertThat(response.getStatusCode()).isEqualTo(SC_OK);
- }
-
- @Test
- public void unknownOptionCausesFailureIfRestEndpointDoesNotAcceptIt() throws Exception {
- String changeId = createChange().getChangeId();
- RestResponse response = adminRestSession.get("/changes/" + changeId + "/test?foo-bar");
- assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);
- }
-
- @Test
- public void unknownPluginOptionIsIgnoredIfRestEndpointSupportsDynamicOptions() throws Exception {
- String changeId = createChange().getChangeId();
- RestResponse response = adminRestSession.get("/changes/" + changeId + "?foo--bar");
- assertThat(response.getStatusCode()).isEqualTo(SC_OK);
- }
-
- @Test
- public void unknownNonPluginOptionCausesFailureIfRestEndpointSupportsDynamicOptions()
- throws Exception {
- String changeId = createChange().getChangeId();
- RestResponse response = adminRestSession.get("/changes/" + changeId + "?foo-bar");
- assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);
- }
-
- @Test
- public void unknownPluginOptionCausesFailureIfRestEndpointDoesNotSupportDynamicOptions()
- throws Exception {
- String changeId = createChange().getChangeId();
- RestResponse response = adminRestSession.get("/changes/" + changeId + "/comments?foo--bar");
- assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);
- }
-
- private static class MyChangeView implements RestReadView<ChangeResource>, UnknownOptionHandler {
- @Override
- public Response<String> apply(ChangeResource resource) {
- return Response.ok("OK");
- }
-
- @Override
- public boolean accept(String name, @Nullable String value) {
- return name.startsWith("--ignore");
- }
- }
-}