source: main/trunk/gli/src/org/greenstone/gatherer/greenstone/Plugins.java@ 31776

Last change on this file since 31776 was 31776, checked in by ak19, 7 years ago

Kathy described a problem on the mailing list about the AutoLoadConverters msg appearing before XML content when connecting with a client-GLI to a remote GS3, which breaks parsing of the XML. (I found it was present in my GS3 installation from 4 May 2016.) I've narrowed it down to running client-gli with the debug flag turned on, which seemed related to the same problem I'd seen when running gli -debug after the change to SafeProcess in Plugins.java, which I fixed by removing lines preceding XML content before parsing the XML. For client-gli, SafeProcess isn't used which is also why the problem with client-gli is much older, but I'm now using a common and existing solution for both: doing what Plugins.java used to do before the change to SafeProcess, which is call XMLTools.readXMLStream(), which would parse out content before XML. The RemoteGreenstoneServer should only call this method if it actually has some XML content it's dealing with. Could have solved this in RemoteGreenstoneServerAction.java's GetScriptOptions, but am solving it in RemoteGreenstoneServer's sendCommandToServerInternal, since there may be many Actions returning XML, not just GetScriptOptions.

  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: Michael Dewsnip, NZDL Project, University of Waikato
9 *
10 * Copyright (C) 2006 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.greenstone;
28
29import java.io.*;
30import java.util.*;
31import javax.swing.*;
32import org.greenstone.gatherer.Configuration;
33import org.greenstone.gatherer.DebugStream;
34import org.greenstone.gatherer.Dictionary;
35import org.greenstone.gatherer.Gatherer;
36import org.greenstone.gatherer.cdm.Argument;
37import org.greenstone.gatherer.cdm.Plugin;
38import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
39import org.greenstone.gatherer.util.SafeProcess;
40import org.greenstone.gatherer.util.StaticStrings;
41import org.greenstone.gatherer.util.Utility;
42import org.greenstone.gatherer.util.XMLTools;
43import org.w3c.dom.*;
44import org.xml.sax.*;
45
46
47/** This class is for maintaining a list of known plug-ins, and importing new plugins using the parser. */
48public class Plugins
49{
50 // A list of all the plugins in the core Greenstone "perllib/plugins" folder (arguments may not be loaded)
51 static private ArrayList core_greenstone_plugins_list = null;
52 // The name of the loaded collection
53 static private String collection_name = null;
54 // A list of all the plugins in the loaded collection's "perllib/plugins" folder (arguments may not be loaded)
55 static private ArrayList collection_specific_plugins_list = new ArrayList();
56
57
58 static public Plugin getPlugin(String plugin_name, boolean arguments_required)
59 {
60 Plugin plugin = null;
61 boolean collection_specific = false;
62
63 // Check the collection-specific plugins first
64 for (int i = 0; i < collection_specific_plugins_list.size(); i++) {
65 Plugin collection_specific_plugin = (Plugin) collection_specific_plugins_list.get(i);
66 if (collection_specific_plugin.getName().equals(plugin_name)) {
67 plugin = collection_specific_plugin;
68 collection_specific = true;
69 break;
70 }
71 }
72
73 // Try the core Greenstone plugins if necessary
74 if (plugin == null) {
75 for (int i = 0; i < core_greenstone_plugins_list.size(); i++) {
76 Plugin core_greenstone_plugin = (Plugin) core_greenstone_plugins_list.get(i);
77 if (core_greenstone_plugin.getName().equals(plugin_name)) {
78 plugin = core_greenstone_plugin;
79 break;
80 }
81 }
82 }
83
84 // If we've found the plugin, load its arguments now, if required
85 if (plugin != null && arguments_required) {
86 if (!plugin.hasLoadedOptions()) {
87 loadPluginInfo(plugin, collection_specific);
88 }
89 else {
90 DebugStream.println("Already loaded arguments for " + plugin_name + "!");
91 }
92 }
93
94 return plugin;
95 }
96
97
98 /** Returns a new list from merging the collection-specific and the core Greenstone plugins. */
99 static public ArrayList getPluginsList()
100 {
101 ArrayList plugins_list = new ArrayList();
102 plugins_list.addAll(collection_specific_plugins_list);
103
104 // Add in the core Greenstone plugins, taking care not to overwrite any collection-specific ones
105 for (int i = 0; i < core_greenstone_plugins_list.size(); i++) {
106 Plugin core_greenstone_plugin = (Plugin) core_greenstone_plugins_list.get(i);
107
108 boolean found = false;
109 for (int j = 0; j < collection_specific_plugins_list.size(); j++) {
110 Plugin collection_specific_plugin = (Plugin) collection_specific_plugins_list.get(j);
111 if (core_greenstone_plugin.getName().equals(collection_specific_plugin.getName())) {
112 found = true;
113 break;
114 }
115 }
116
117 if (!found) {
118 plugins_list.add(core_greenstone_plugin);
119 }
120 }
121
122 return plugins_list;
123 }
124
125
126 static private void loadPluginInfo(Plugin plugin, boolean collection_specific)
127 {
128 DebugStream.println("Loading arguments for " + plugin.getName() + "...");
129
130 // Run pluginfo.pl to get the list of plugins
131 try {
132 String pluginfo_xml = null;
133 if (Gatherer.isGsdlRemote) {
134 String pluginfo_options = "&plugin=" + plugin;
135 if (collection_specific) {
136 pluginfo_options += "&collection=" + collection_name;
137 }
138 pluginfo_xml = Gatherer.remoteGreenstoneServer.getScriptOptions("pluginfo.pl", pluginfo_options);
139 }
140 else {
141 ArrayList args = new ArrayList();
142 args.add(Configuration.perl_path);
143 args.add("-S");
144 args.add(LocalGreenstone.getBinScriptDirectoryPath() + "pluginfo.pl");
145 args.add("-gs_version");
146 if (Gatherer.GS3) {
147 args.add("3");
148 } else {
149 args.add("2");
150 }
151 if (collection_specific) {
152 args.add("-collection");
153 args.add(collection_name);
154 if (Gatherer.GS3) {
155 args.add("-site");
156 args.add(Configuration.site_name);
157 }
158 }
159 args.add("-xml");
160 args.add("-language");
161 args.add(Configuration.getLanguage());
162 args.add(plugin.getName());
163
164 // Run the pluginfo.pl process:
165 // Create the process.
166 SafeProcess process = new SafeProcess((String[]) args.toArray(new String[] { }));
167 process.setSplitStdErrorNewLines(true);
168
169 // run the SafeProcess
170 int exitVal = process.runProcess();
171 if(exitVal != 0) {
172 throw new Exception("*** Error running pluginfo.pl loadPlugInfo, process exited with: "
173 + exitVal);
174 }
175 // get the result: We expect XML to have come out of the process std error stream.
176 pluginfo_xml = process.getStdError();
177 // make sure to have parsed out any lines preceding the XML content
178 pluginfo_xml = XMLTools.readXMLStream(pluginfo_xml).toString();
179 ///System.err.println("*********\nPluginInfo, got:\n" + pluginfo_xml + "\n**********\n");
180 }
181
182 // Check the XML output was obtained successfully
183 if (pluginfo_xml == null || pluginfo_xml.length() == 0) {
184 plugin.setHasLoadedOptions(false); // failure to load options
185 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PlugInManager.PlugIn_XML_Parse_Failed", plugin.getName()), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
186 return;
187 } else {
188 plugin.setHasLoadedOptions(true);
189 }
190
191 parsePluginInfoXML(plugin, pluginfo_xml);
192 }
193 catch (Exception exception) {
194 DebugStream.printStackTrace(exception);
195 }
196 }
197
198
199 static public void loadPluginsList(String collection_name_arg)
200 {
201 DebugStream.println("In loadPluginsList()...");
202
203 // If we're getting the collection-specific plugins, clear the old list no matter what
204 if (collection_name_arg != null) {
205 collection_name = collection_name_arg;
206 collection_specific_plugins_list = new ArrayList();
207 }
208
209 // Run pluginfo.pl to get the list of plugins
210 try {
211 String xml = null;
212 if (Gatherer.isGsdlRemote) {
213 String pluginfo_options = "&listall";
214 if (collection_name != null) {
215 pluginfo_options += "&collection=" + collection_name;
216 }
217 String pluginfo_output = Gatherer.remoteGreenstoneServer.getScriptOptions("pluginfo.pl", pluginfo_options);
218 xml = pluginfo_output;
219 }
220 else {
221 ArrayList args = new ArrayList();
222 args.add(Configuration.perl_path);
223 args.add("-S");
224 args.add(LocalGreenstone.getBinScriptDirectoryPath() + "pluginfo.pl");
225 args.add("-gs_version");
226 if (Gatherer.GS3) {
227 args.add("3");
228 } else {
229 args.add("2");
230 }
231 if (collection_name != null) {
232 args.add("-collection");
233 args.add(collection_name);
234 if (Gatherer.GS3) {
235 args.add("-site");
236 args.add(Configuration.site_name);
237 }
238 }
239 args.add("-listall");
240 args.add("-xml");
241
242 // Run the pluginfo.pl process:
243 // Create the process.
244 SafeProcess process = new SafeProcess((String[]) args.toArray(new String[] { }));
245 process.setSplitStdErrorNewLines(true);
246
247 // run the SafeProcess
248 int exitVal = process.runProcess();
249 if(exitVal != 0) {
250 throw new Exception("*** Error running pluginfo.pl loadPluginsList, process exited with: "
251 + exitVal);
252 }
253 // get the result: We expect XML to have come out of the process std error stream.
254 xml = process.getStdError();
255 // make sure to parse out any lines before the XML content, else running "gli -debug" results in an XML error:
256 // for pluginfo.pl -listall, we see a "AutoloadConverters" (PDFBox) message
257 // before actual XML output, which breaks XML parsing.
258 // This gets rid of output before "<?xml" in the way that the code did before the change to SafeProcess
259 // Then we can call the same from method RemoteGreenstoneServer.java, so that running "client-gli -debug"
260 // will work too.
261 xml = XMLTools.readXMLStream(xml).toString();
262
263 ///System.err.println("*********\nPluginsList, got:\n" + xml + "\n**********\n");
264 }
265
266 // Check the XML output was obtained successfully
267 if (xml == null || xml.length() == 0) {
268 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PluginManager.Plugin_List_XML_Parse_Failed"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
269 return;
270 }
271
272 if (collection_name != null) {
273 collection_specific_plugins_list = parsePluginsListXML(xml);
274 }
275 else {
276 core_greenstone_plugins_list = parsePluginsListXML(xml);
277 }
278 }
279 catch (Exception exception) {
280 DebugStream.printStackTrace(exception);
281 }
282 }
283
284
285 static private void parsePluginInfoXML(Plugin plugin, String xml)
286 {
287 Document document = XMLTools.parseXML(new StringReader(xml));
288 if (document == null) {
289 plugin.setHasLoadedOptions(false); // failure to load the options/failed plugin
290 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PlugInManager.PlugIn_XML_Parse_Failed", plugin.getName()), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
291 return;
292 } else {
293 plugin.setHasLoadedOptions(true);
294 }
295
296 parsePluginInfoXMLNode(plugin, document.getDocumentElement());
297 }
298
299
300 static private void parsePluginInfoXMLNode(Plugin plugin, Node root_node)
301 {
302 for (Node node = root_node.getFirstChild(); node != null; node = node.getNextSibling()) {
303 String node_name = node.getNodeName();
304
305 if (node_name.equalsIgnoreCase("Name")) {
306 plugin.setName(XMLTools.getValue(node));
307 }
308 else if (node_name.equals("Desc")) {
309 plugin.setDescription(XMLTools.getValue(node));
310 }
311 else if (node_name.equals("Abstract")) {
312 plugin.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
313 }
314 else if (node_name.equalsIgnoreCase("Explodes")) {
315 plugin.setDoesExplodeMetadataDatabases(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
316 }
317 else if (node_name.equalsIgnoreCase("SourceReplaceable")) { // looking for <SourceReplaceable> tag
318 plugin.setDoesReplaceSrcDocsWithHtml(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
319 }
320 else if (node_name.equalsIgnoreCase("Processes")) {
321 plugin.setDefaultProcessExpression(XMLTools.getValue(node));
322 }
323 else if (node_name.equalsIgnoreCase("Blocks")) {
324 plugin.setDefaultBlockExpression(XMLTools.getValue(node));
325 }
326 // Parse the plugin arguments
327 else if (node_name.equalsIgnoreCase("Arguments")) {
328 for (Node argument_node = node.getFirstChild(); argument_node != null; argument_node = argument_node.getNextSibling()) {
329 // An option
330 if (argument_node.getNodeName().equalsIgnoreCase("Option")) {
331 Argument argument = new Argument();
332 argument.parseXML((Element) argument_node);
333 plugin.addArgument(argument);
334 }
335 }
336 }
337 // A super plugin class
338 else if (node_name.equalsIgnoreCase("PlugInfo")) {
339 Plugin super_plugin = new Plugin();
340 parsePluginInfoXMLNode(super_plugin, node);
341 plugin.setSuper(super_plugin);
342 }
343 }
344 }
345
346
347 static private ArrayList parsePluginsListXML(String xml)
348 {
349 ArrayList plugins_list = new ArrayList();
350
351 Document document = XMLTools.parseXML(new StringReader(xml));
352 Node root = document.getDocumentElement();
353 for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {
354 String node_name = node.getNodeName();
355
356 if (node_name.equals("PlugInfo")) {
357 Plugin plugin = new Plugin();
358 parsePluginInfoXMLNode(plugin, node);
359 plugins_list.add(plugin);
360 }
361 }
362
363 return plugins_list;
364 }
365}
Note: See TracBrowser for help on using the repository browser.