Gridarta Editor
PluginExecutor.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.plugin;
21 
22 import bsh.ConsoleInterface;
23 import bsh.EvalError;
24 import bsh.Interpreter;
25 import bsh.TargetError;
26 import java.io.CharArrayWriter;
27 import java.io.InputStreamReader;
28 import java.io.PrintStream;
29 import java.io.PrintWriter;
30 import java.io.Reader;
31 import java.util.HashMap;
32 import java.util.Map;
39 import org.jetbrains.annotations.NotNull;
40 import org.jetbrains.annotations.Nullable;
41 
46 @SuppressWarnings("UseOfSystemOutOrSystemErr")
47 public class PluginExecutor<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
48 
52  @NotNull
54 
58  @NotNull
60 
66  public PluginExecutor(@NotNull final PluginModel<G, A, R> pluginModel, @NotNull final PluginParameters pluginParameters) {
67  this.pluginModel = pluginModel;
68  this.pluginParameters = pluginParameters;
69  }
70 
77  public int executePlugin(@NotNull final String plugin, @NotNull final Iterable<String> parameters) {
78  final Plugin<G, A, R> modelTemplate = pluginModel.getPlugin(plugin);
79  if (modelTemplate == null) {
80  System.err.println("plugin " + plugin + " does not exist");
81  return 1;
82  }
83 
84  final Plugin<G, A, R> clonedPlugin = modelTemplate.clonePlugin();
85  final Map<String, Object> runValues = new HashMap<>();
86  for (final String parameter : parameters) {
87  final String[] tmp = StringUtils.PATTERN_EQUAL.split(parameter, 2);
88  if (tmp.length != 2) {
89  System.err.println("syntax error: " + parameter);
90  return 1;
91  }
92 
93  final int index = clonedPlugin.getParameter(tmp[0]);
94  if (index == -1) {
95  final StringBuilder sb = new StringBuilder();
96  boolean firstParameter = true;
97  for (final PluginParameter<?, ?, ?, ?> clonedParameter : clonedPlugin) {
98  sb.append(firstParameter ? " " : ", ");
99  sb.append(clonedParameter.getName());
100  firstParameter = false;
101  }
102  System.err.println("plugin " + plugin + " has no parameter " + tmp[0] + "; available parameters:" + sb);
103  return 1;
104  }
105 
106  final PluginParameter<G, A, R, ?> clonedParameter;
107  try {
108  clonedParameter = clonedPlugin.getParameter(index);
109  } catch (final NoSuchParameterException ex) {
110  throw new AssertionError(ex);
111  }
112  if (!clonedParameter.setStringValue(tmp[1])) {
113  System.out.println("invalid value " + tmp[1] + " for parameter " + tmp[0]);
114  return 1;
115  }
116 
117  runValues.put(clonedParameter.getName(), tmp[1]);
118  }
119  for (final PluginParameter<G, A, R, ?> parameter : clonedPlugin) {
120  final String parameterName = parameter.getName();
121  if (!runValues.containsKey(parameterName)) {
122  final Object parameterValue = parameter.getValueOrNull();
123  if (parameterValue == null) {
124  System.err.println("no value for parameter " + parameterName);
125  return 1;
126  }
127  runValues.put(parameterName, parameterValue);
128  }
129  }
130 
131  final ConsoleInterface console = new ConsoleInterface() {
132 
133  @Override
134  public Reader getIn() {
135  return new InputStreamReader(System.in);
136  }
137 
138  @Override
139  public PrintStream getOut() {
140  return System.out;
141  }
142 
143  @Override
144  public PrintStream getErr() {
145  return System.err;
146  }
147 
148  @Override
149  public void println(final Object o) {
150  System.out.println(o);
151  }
152 
153  @Override
154  public void print(final Object o) {
155  System.out.print(o);
156  }
157 
158  @Override
159  public void error(final Object o) {
160  System.err.println(o);
161  }
162 
163  };
164  final BshThread<G, A, R> pluginThread = doRunPlugin(clonedPlugin, console, runValues);
165  if (pluginThread == null) {
166  return 1;
167  }
168  try {
169  pluginThread.join();
170  } catch (final InterruptedException ignored) {
171  pluginThread.interrupt();
172  Thread.currentThread().interrupt();
173  System.out.println("interrupted");
174  return 1;
175  }
176 
177  if (!pluginThread.isSuccess()) {
178  System.err.println("plugin failed");
179  return 1;
180  }
181 
182  return 0;
183  }
184 
192  @Nullable
193  public BshThread<G, A, R> doRunPlugin(@NotNull final Plugin<G, A, R> plugin, @NotNull final ConsoleInterface console, @NotNull final Map<String, Object> parameters) {
194  final Interpreter runner = new Interpreter();
195  runner.setConsole(console);
196  try {
197  pluginParameters.setInterpreterValues(runner, PluginRunMode.BATCH);
198  for (final Map.Entry<String, Object> parameter : parameters.entrySet()) {
199  runner.set(parameter.getKey(), parameter.getValue());
200  }
201  } catch (final TargetError ex) {
202  final CharArrayWriter charArrayWriter = new CharArrayWriter();
203  try {
204  try (PrintWriter printWriter = new PrintWriter(charArrayWriter)) {
205  ex.getTarget().printStackTrace(printWriter);
206  }
207  } finally {
208  charArrayWriter.close();
209  }
210  console.print("target error: " + charArrayWriter);
211  return null;
212  } catch (final EvalError ex) {
213  console.print("evaluation error: " + ex.getMessage());
214  return null;
215  }
216  final BshThread<G, A, R> pluginThread = new BshThread<>(plugin.getName(), plugin, runner);
217  pluginThread.start();
218  return pluginThread;
219  }
220 
221 }
int executePlugin(@NotNull final String plugin, @NotNull final Iterable< String > parameters)
Executes an editor plugin.
Utility class for string manipulation.
static final Pattern PATTERN_EQUAL
The pattern that matches a single equal sign ("=").
Plugin< G, A, R > getPlugin(@NotNull final String name)
PluginExecutor(@NotNull final PluginModel< G, A, R > pluginModel, @NotNull final PluginParameters pluginParameters)
Creates a new instance.
int getParameter(@NotNull final String parameterName)
Returns the index for a plugin parameter name.
Definition: Plugin.java:186
boolean isSuccess()
Returns whether the plugin has been executed successfully.
Definition: BshThread.java:80
Allows execution of Plugins.
Base package of all Gridarta classes.
Reflects a game object (object on a map).
Definition: GameObject.java:36
Plugin< G, A, R > clonePlugin()
Returns a clone copy of this plugin.
Definition: Plugin.java:263
GameObjects are the objects based on Archetypes found on maps.
final PluginModel< G, A, R > pluginModel
The PluginModel to execute.
The run mode of a plugin plugin.
BshThread< G, A, R > doRunPlugin(@NotNull final Plugin< G, A, R > plugin, @NotNull final ConsoleInterface console, @NotNull final Map< String, Object > parameters)
Runs a plugin model.
Makes basic Gridarta classes available to scripts.
void setInterpreterValues(@NotNull final Interpreter interpreter, @NotNull final PluginRunMode pluginRunMode)
Adds variables to a Interpreter instance.
String getName()
The name of the parameter.
final PluginParameters pluginParameters
The parameters to pass to the plugin.
boolean setStringValue(@NotNull String stringValue)
Sets the parameter value from string representation.