Gridarta Editor
PluginModelLoader.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 java.io.File;
23 import java.io.IOException;
30 import nu.xom.Builder;
31 import nu.xom.Document;
32 import nu.xom.Element;
33 import nu.xom.ParsingException;
34 import org.apache.log4j.Category;
35 import org.apache.log4j.Logger;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
38 import org.xml.sax.SAXException;
39 import org.xml.sax.XMLReader;
40 import org.xml.sax.helpers.XMLReaderFactory;
41 
47 public class PluginModelLoader<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
48 
52  private static final Category LOG = Logger.getLogger(PluginModelLoader.class);
53 
57  private PluginModelLoader() {
58  }
59 
67  @NotNull
68  public static <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> PluginModel<G, A, R> loadPlugins(@NotNull final PluginParameterFactory<G, A, R> pluginParameterFactory, @NotNull final PluginModelParser<G, A, R> pluginModelParser, @NotNull final ErrorView errorView, @NotNull final File pluginsDir) {
69  final PluginModel<G, A, R> pluginModel = new PluginModel<>(pluginParameterFactory, pluginModelParser);
70  final File[] files = pluginsDir.listFiles();
71  if (files == null) {
72  errorView.addWarning(ErrorViewCategory.SCRIPTS_DIR_INVALID, pluginsDir + ": directory not readable");
73  return pluginModel;
74  }
75 
76  final int pluginCount = pluginModel.getPluginCount();
77  for (final File pluginFile : files) {
78  final String name = pluginFile.getName();
79  if (!name.startsWith(".") && !name.endsWith("~") && pluginFile.isFile()) {
80  try {
81  final Plugin<G, A, R> plugin = loadXML(pluginModelParser, pluginFile);
82  if (pluginModel.getPlugin(plugin.getName()) != null) {
83  errorView.addWarning(ErrorViewCategory.SCRIPTS_FILE_INVALID, pluginFile + ": duplicate plugin '" + plugin.getName() + "'");
84  } else {
85  if (LOG.isDebugEnabled()) {
86  LOG.debug("storing with code " + plugin.getCode());
87  }
88  pluginModel.addPlugin(plugin);
89  }
90  } catch (final IOException ex) {
91  errorView.addWarning(ErrorViewCategory.SCRIPTS_FILE_INVALID, pluginFile + ": " + ex.getMessage());
92  } catch (final ParsingException ex) {
93  errorView.addWarning(ErrorViewCategory.SCRIPTS_FILE_INVALID, pluginFile + ": " + ex.getMessage());
94  } catch (final SAXException ex) {
95  errorView.addWarning(ErrorViewCategory.SCRIPTS_FILE_INVALID, pluginFile + ": " + ex.getMessage());
96  }
97  }
98  }
99  if (LOG.isInfoEnabled()) {
100  LOG.info("Loaded " + (pluginModel.getPluginCount() - pluginCount) + " plugins from '" + pluginsDir + "'.");
101  }
102  return pluginModel;
103  }
104 
105  public static <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> Plugin<G, A, R> loadXML(@NotNull final PluginModelParser<G, A, R> pluginModelParser, @NotNull final File file) throws IOException, ParsingException, SAXException {
106  final XMLReader xmlReader = XMLReaderFactory.createXMLReader();
107  final Builder builder = new Builder(xmlReader, false);
108  final Document d = builder.build(file);
109  return loadXML(pluginModelParser, d, file);
110  }
111 
112  @NotNull
113  private static <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> Plugin<G, A, R> loadXML(@NotNull final PluginModelParser<G, A, R> pluginModelParser, @NotNull final Document doc, @Nullable final File file) throws IOException {
114  final Element elt = doc.getRootElement();
115  if (elt == null) {
116  throw new IOException("plugin file is empty");
117  }
118  if (!elt.getLocalName().equalsIgnoreCase("script")) {
119  throw new IOException("missing root element named \"script\"");
120  }
121 
122  final Plugin<G, A, R> plugin = pluginModelParser.fromXML(elt);
123  plugin.setFile(file);
124  if (LOG.isDebugEnabled()) {
125  LOG.debug("plugin: " + plugin.getName());
126  }
127 
128  return plugin;
129  }
130 
131 }
void setFile(@Nullable final File file)
Sets the location to save this plugin to.
Definition: Plugin.java:426
Plugin< G, A, R > getPlugin(@NotNull final String name)
static final Category LOG
The Logger for printing log messages.
Utility class for loading plugins.
Defines possible error categories for ErrorView instances.
Interface for classes displaying error messages.
Definition: ErrorView.java:28
Base package of all Gridarta classes.
Reflects a game object (object on a map).
Definition: GameObject.java:36
PluginModelLoader()
Private constructor to prevent instantiation.
String getName()
Returns the name of this plugin.
Definition: Plugin.java:147
GameObjects are the objects based on Archetypes found on maps.
String getCode()
Returns the executable code of this plugin.
Definition: Plugin.java:156
boolean addPlugin(@NotNull final Plugin< G, A, R > plugin)
Add a new plugin.