0

I'm trying to add values to an ImmutableMap. The field's name is commands.

Here's my code:

            Field field = this.getDescription().getClass().getDeclaredField("commands");
            Map<String, Map<String, Object>> commands = new HashMap<>();

            this.getDescription().getCommands().forEach((c, v) -> commands.put(c, v));

            for (String alias : this.aliasManager.getAllAliases()) {
                Map<String, Object> map = new HashMap<>();
                map.put("description", "An alias for " + aliasManager.getAlias(alias).getCommand());
                map.put("usage", "/<command>");
                map.put("name", alias);
                commands.put(alias, map);
            }

            Map<String, Map<String, Object>> immutableMap = ImmutableMap.copyOf(commands);

            field.setAccessible(true);
            field.set(this.getDescription().getCommands(), immutableMap);

The error I am getting is:

java.lang.IllegalArgumentException: Can not set java.util.Map field 
org.bukkit.plugin.PluginDescriptionFile.commands to com.google.common.collect.SingletonImmutableBiMap

The field is declared in the following way: private Map<String, Map<String, Object>> commands = (Map<String, Map<String, Object>>)ImmutableMap.of();

Any ideas on how I could fix the issue?

Gargant
  • 11
  • 2
  • I must mention performing the cast they did in the field results in the same error. – Gargant Mar 23 '23 at 18:51
  • 1
    If I understood your intent correctly, `field.set(this.getDescription().getCommands(), immutableMap);` should be `field.set(this.getDescription(), immutableMap);` no? Also, if coming from `org.bukkit.plugin.PluginDescriptionFile`, https://github.com/Bukkit/Bukkit/blob/f210234e59275330f83b994e199c76f6abd41ee7/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java#L219 the field is initialized with `null`, not `ImmutableMap.of()` – LouizFC Mar 23 '23 at 19:03
  • The `getDescription()` return an object of type `PluginDescriptionFile`. That instance contains the `commands` object I want to modify. – Gargant Mar 23 '23 at 19:05
  • I may be misunderstanding your intent but, java `Field.set` works somewhat like this: the first param is the object that containts `field`, the second param is the value you want to set. You already "extracted" the field you want to modify in the first line of code, now you pass your "target" object, in your case `PluginDescriptionFile`, to the `Field.set` object first parameter. The second parameter is your modified `commands` object – LouizFC Mar 23 '23 at 19:09

1 Answers1

0

As said in the comments, the last line of your code should be:

field.set(this.getDescription(), immutableMap);

Because the way Field#set works is:

The first parameter should be the object that has that field. In your case, your this.getDescription(), which is a PluginDescriptionFile that contains the field that you declared in the first line.

The second parameter should be the value that you want to set, in your case, immutableMap.

You were passing a this.getDescription().getCommands() obj field.set first parameter, but this object is a Map (or null as we saw in the source code).

A (naive but easy to undestand) way to interpret the raised error is "I cannot set the field commands in Map, because there is no field called commands in Map".

LouizFC
  • 161
  • 1
  • 10