4163 |
28 Feb 08 |
nicklas |
1 |
/** |
4198 |
28 Mar 08 |
nicklas |
$Id:XmlLoader.java 4187 2008-03-20 11:15:25Z nicklas $ |
4163 |
28 Feb 08 |
nicklas |
3 |
|
4163 |
28 Feb 08 |
nicklas |
Copyright (C) Authors contributing to this file. |
4163 |
28 Feb 08 |
nicklas |
5 |
|
4163 |
28 Feb 08 |
nicklas |
This file is part of BASE - BioArray Software Environment. |
4163 |
28 Feb 08 |
nicklas |
Available at http://base.thep.lu.se/ |
4163 |
28 Feb 08 |
nicklas |
8 |
|
4163 |
28 Feb 08 |
nicklas |
BASE is free software; you can redistribute it and/or |
4163 |
28 Feb 08 |
nicklas |
modify it under the terms of the GNU General Public License |
4479 |
05 Sep 08 |
jari |
as published by the Free Software Foundation; either version 3 |
4163 |
28 Feb 08 |
nicklas |
of the License, or (at your option) any later version. |
4163 |
28 Feb 08 |
nicklas |
13 |
|
4163 |
28 Feb 08 |
nicklas |
BASE is distributed in the hope that it will be useful, |
4163 |
28 Feb 08 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
4163 |
28 Feb 08 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4163 |
28 Feb 08 |
nicklas |
GNU General Public License for more details. |
4163 |
28 Feb 08 |
nicklas |
18 |
|
4163 |
28 Feb 08 |
nicklas |
You should have received a copy of the GNU General Public License |
4515 |
11 Sep 08 |
jari |
along with BASE. If not, see <http://www.gnu.org/licenses/>. |
4163 |
28 Feb 08 |
nicklas |
21 |
*/ |
4170 |
07 Mar 08 |
nicklas |
22 |
package net.sf.basedb.util.extensions.xml; |
4163 |
28 Feb 08 |
nicklas |
23 |
|
4163 |
28 Feb 08 |
nicklas |
24 |
import java.io.IOException; |
4163 |
28 Feb 08 |
nicklas |
25 |
import java.io.InputStream; |
4163 |
28 Feb 08 |
nicklas |
26 |
import java.lang.reflect.InvocationTargetException; |
4163 |
28 Feb 08 |
nicklas |
27 |
import java.lang.reflect.Method; |
5519 |
23 Nov 10 |
nicklas |
28 |
import java.util.ArrayList; |
4198 |
28 Mar 08 |
nicklas |
29 |
import java.util.HashMap; |
4198 |
28 Mar 08 |
nicklas |
30 |
import java.util.LinkedHashSet; |
4163 |
28 Feb 08 |
nicklas |
31 |
import java.util.LinkedList; |
4163 |
28 Feb 08 |
nicklas |
32 |
import java.util.List; |
4198 |
28 Mar 08 |
nicklas |
33 |
import java.util.Map; |
4198 |
28 Mar 08 |
nicklas |
34 |
import java.util.Set; |
4163 |
28 Feb 08 |
nicklas |
35 |
|
6473 |
11 Jun 14 |
nicklas |
36 |
import org.jdom2.Attribute; |
6473 |
11 Jun 14 |
nicklas |
37 |
import org.jdom2.Document; |
6473 |
11 Jun 14 |
nicklas |
38 |
import org.jdom2.Element; |
6473 |
11 Jun 14 |
nicklas |
39 |
import org.jdom2.Namespace; |
6473 |
11 Jun 14 |
nicklas |
40 |
import org.jdom2.output.Format; |
6473 |
11 Jun 14 |
nicklas |
41 |
import org.jdom2.output.XMLOutputter; |
4163 |
28 Feb 08 |
nicklas |
42 |
|
6627 |
25 Nov 14 |
nicklas |
43 |
import net.sf.basedb.core.Application; |
5607 |
15 Apr 11 |
nicklas |
44 |
import net.sf.basedb.core.BaseException; |
4198 |
28 Mar 08 |
nicklas |
45 |
import net.sf.basedb.core.InvalidUseOfNullException; |
6627 |
25 Nov 14 |
nicklas |
46 |
import net.sf.basedb.core.Presets.Preset; |
5519 |
23 Nov 10 |
nicklas |
47 |
import net.sf.basedb.core.StringUtil; |
5607 |
15 Apr 11 |
nicklas |
48 |
import net.sf.basedb.core.Version; |
4198 |
28 Mar 08 |
nicklas |
49 |
import net.sf.basedb.core.plugin.About; |
4163 |
28 Feb 08 |
nicklas |
50 |
import net.sf.basedb.util.ClassUtil; |
4163 |
28 Feb 08 |
nicklas |
51 |
import net.sf.basedb.util.Values; |
6473 |
11 Jun 14 |
nicklas |
52 |
import net.sf.basedb.util.XmlUtil2; |
4170 |
07 Mar 08 |
nicklas |
53 |
import net.sf.basedb.util.extensions.AboutBean; |
4170 |
07 Mar 08 |
nicklas |
54 |
import net.sf.basedb.util.extensions.Action; |
4170 |
07 Mar 08 |
nicklas |
55 |
import net.sf.basedb.util.extensions.ActionFactory; |
5486 |
12 Nov 10 |
nicklas |
56 |
import net.sf.basedb.util.extensions.ErrorHandlerFactory; |
4170 |
07 Mar 08 |
nicklas |
57 |
import net.sf.basedb.util.extensions.Extension; |
4170 |
07 Mar 08 |
nicklas |
58 |
import net.sf.basedb.util.extensions.ExtensionBean; |
4170 |
07 Mar 08 |
nicklas |
59 |
import net.sf.basedb.util.extensions.ExtensionPoint; |
4170 |
07 Mar 08 |
nicklas |
60 |
import net.sf.basedb.util.extensions.ExtensionPointBean; |
4170 |
07 Mar 08 |
nicklas |
61 |
import net.sf.basedb.util.extensions.Registry; |
4170 |
07 Mar 08 |
nicklas |
62 |
import net.sf.basedb.util.extensions.RendererFactory; |
5598 |
30 Mar 11 |
nicklas |
63 |
import net.sf.basedb.util.filter.Filter; |
4163 |
28 Feb 08 |
nicklas |
64 |
|
4163 |
28 Feb 08 |
nicklas |
65 |
/** |
4163 |
28 Feb 08 |
nicklas |
Loads extension points and extensions from extension definition |
4163 |
28 Feb 08 |
nicklas |
XML files. This class may load extensions from more than one file |
4163 |
28 Feb 08 |
nicklas |
and register or unregister all loaded extensions and extension points |
4163 |
28 Feb 08 |
nicklas |
with a registry. |
4163 |
28 Feb 08 |
nicklas |
<p> |
4163 |
28 Feb 08 |
nicklas |
For a description of the XML file format this class can load |
5519 |
23 Nov 10 |
nicklas |
see the <a href="http://base.thep.lu.se/chrome/site/latest/html/developerdoc/extensions/extensions_developer.helloworld.html">BASE manual</a>. |
4163 |
28 Feb 08 |
nicklas |
73 |
|
4163 |
28 Feb 08 |
nicklas |
<p> |
4163 |
28 Feb 08 |
nicklas |
<b>Factory initialisation</b><br> |
4163 |
28 Feb 08 |
nicklas |
76 |
|
4163 |
28 Feb 08 |
nicklas |
This loader uses reflection to create and initialise factory |
4163 |
28 Feb 08 |
nicklas |
instances. The XML file contains the class name of the factory |
4163 |
28 Feb 08 |
nicklas |
to create. This class must declare a public no-argument |
4163 |
28 Feb 08 |
nicklas |
constructor and must also implement one of the specific |
4163 |
28 Feb 08 |
nicklas |
factory interfaces (for example {@link ActionFactory} |
4163 |
28 Feb 08 |
nicklas |
or {@link RendererFactory}). If the tag <code><parameters></code> |
4163 |
28 Feb 08 |
nicklas |
is present inside the factory declaration, the loader will |
4163 |
28 Feb 08 |
nicklas |
use reflection to find a setter method for each sub-tag inside |
4163 |
28 Feb 08 |
nicklas |
the <code><parameters></code> tag. Here is an example: |
4170 |
07 Mar 08 |
nicklas |
86 |
|
4163 |
28 Feb 08 |
nicklas |
<pre class="code"> |
4163 |
28 Feb 08 |
nicklas |
// XML contents |
4163 |
28 Feb 08 |
nicklas |
<parameters> |
4163 |
28 Feb 08 |
nicklas |
<image>button.png</image> |
4163 |
28 Feb 08 |
nicklas |
<title>Click button</title> |
4163 |
28 Feb 08 |
nicklas |
</parameters> |
4163 |
28 Feb 08 |
nicklas |
93 |
|
4163 |
28 Feb 08 |
nicklas |
// Factory initialization |
4163 |
28 Feb 08 |
nicklas |
factory.setImage("button.png"); |
4163 |
28 Feb 08 |
nicklas |
factory.setTitle("Click button"); |
4163 |
28 Feb 08 |
nicklas |
</pre> |
4163 |
28 Feb 08 |
nicklas |
98 |
|
4207 |
04 Apr 08 |
nicklas |
The setter methods must be public and accept a single <code>String</code> |
4207 |
04 Apr 08 |
nicklas |
parameter. |
4207 |
04 Apr 08 |
nicklas |
<p> |
4207 |
04 Apr 08 |
nicklas |
102 |
|
4207 |
04 Apr 08 |
nicklas |
The loader also looks for the <code>setParameter(String, String)</code> |
4207 |
04 Apr 08 |
nicklas |
method signature. If the method exists it will be called for each |
4207 |
04 Apr 08 |
nicklas |
parameter found with the tagname as the first parameter and the |
5519 |
23 Nov 10 |
nicklas |
value as the second parameter. Continuing the above example: |
4207 |
04 Apr 08 |
nicklas |
107 |
|
4207 |
04 Apr 08 |
nicklas |
<pre class="code"> |
4207 |
04 Apr 08 |
nicklas |
factory.setParameter("image", "button.png"); |
4207 |
04 Apr 08 |
nicklas |
factory.setParameter("title", "Click button"); |
4207 |
04 Apr 08 |
nicklas |
</pre> |
4207 |
04 Apr 08 |
nicklas |
112 |
|
4207 |
04 Apr 08 |
nicklas |
<p> |
4163 |
28 Feb 08 |
nicklas |
Tags that doesn't have a corresponding setter method are simply ignored. |
4163 |
28 Feb 08 |
nicklas |
The XML file format allows any tags as parameters, but only the first level |
4163 |
28 Feb 08 |
nicklas |
will be parsed. |
4170 |
07 Mar 08 |
nicklas |
117 |
|
4170 |
07 Mar 08 |
nicklas |
<p> |
4170 |
07 Mar 08 |
nicklas |
The parameter values may be subject to conversion by one or more |
4170 |
07 Mar 08 |
nicklas |
{@link ValueConverter}:s. Converters are added to the loader |
4170 |
07 Mar 08 |
nicklas |
by {@link #addValueConverter(ValueConverter)} and are usually |
4170 |
07 Mar 08 |
nicklas |
implemented to react on method annotations. For example, the web |
4170 |
07 Mar 08 |
nicklas |
client uses this for path and variable substitution. |
4163 |
28 Feb 08 |
nicklas |
124 |
|
4163 |
28 Feb 08 |
nicklas |
@author nicklas |
4163 |
28 Feb 08 |
nicklas |
@version 2.7 |
4198 |
28 Mar 08 |
nicklas |
@base.modified $Date:2008-03-20 12:15:25 +0100 (Thu, 20 Mar 2008) $ |
4163 |
28 Feb 08 |
nicklas |
128 |
*/ |
4163 |
28 Feb 08 |
nicklas |
129 |
public class XmlLoader |
4163 |
28 Feb 08 |
nicklas |
130 |
{ |
6444 |
09 Apr 14 |
nicklas |
131 |
private static final org.slf4j.Logger log = |
6444 |
09 Apr 14 |
nicklas |
132 |
org.slf4j.LoggerFactory.getLogger(XmlLoader.class); |
4163 |
28 Feb 08 |
nicklas |
133 |
|
4163 |
28 Feb 08 |
nicklas |
134 |
/** |
4163 |
28 Feb 08 |
nicklas |
The URL pointing to the extensions.xsd schema. |
4163 |
28 Feb 08 |
nicklas |
136 |
*/ |
5610 |
15 Apr 11 |
nicklas |
137 |
public static final String SCHEMA_FILE_URL = |
4163 |
28 Feb 08 |
nicklas |
138 |
XmlLoader.class.getResource("/net/sf/basedb/core/xsd/extensions.xsd").toString(); |
4163 |
28 Feb 08 |
nicklas |
139 |
|
4163 |
28 Feb 08 |
nicklas |
140 |
/** |
4163 |
28 Feb 08 |
nicklas |
The name of the extensions namespace. |
4163 |
28 Feb 08 |
nicklas |
142 |
*/ |
5610 |
15 Apr 11 |
nicklas |
143 |
public static final String NAMESPACE = "http://base.thep.lu.se/extensions.xsd"; |
4163 |
28 Feb 08 |
nicklas |
144 |
|
4198 |
28 Mar 08 |
nicklas |
// To convert XML elements to a string representation |
4198 |
28 Mar 08 |
nicklas |
146 |
private XMLOutputter xmlOut; |
4198 |
28 Mar 08 |
nicklas |
147 |
|
4163 |
28 Feb 08 |
nicklas |
// All loaded extension points |
5610 |
15 Apr 11 |
nicklas |
149 |
private final List<ExtensionPoint<Action>> extensionPoints; |
4163 |
28 Feb 08 |
nicklas |
150 |
|
4163 |
28 Feb 08 |
nicklas |
// All loaded extensions |
5610 |
15 Apr 11 |
nicklas |
152 |
private final List<Extension<Action>> extensions; |
4163 |
28 Feb 08 |
nicklas |
153 |
|
5610 |
15 Apr 11 |
nicklas |
// All loaded plug-in definitions |
5610 |
15 Apr 11 |
nicklas |
155 |
private final List<PluginInfo> pluginDefinitions; |
5610 |
15 Apr 11 |
nicklas |
156 |
|
4170 |
07 Mar 08 |
nicklas |
// List of registered converters |
4198 |
28 Mar 08 |
nicklas |
158 |
private Set<ValueConverter> converters; |
4170 |
07 Mar 08 |
nicklas |
159 |
|
4198 |
28 Mar 08 |
nicklas |
// Map with XML representation of factory parameters |
5610 |
15 Apr 11 |
nicklas |
161 |
private final Map<Object, String> factoryParameters; |
4198 |
28 Mar 08 |
nicklas |
162 |
|
6030 |
28 Mar 12 |
nicklas |
// Map with classloaders |
6030 |
28 Mar 12 |
nicklas |
164 |
private final Map<String, ClassLoader> classLoaders; |
6030 |
28 Mar 12 |
nicklas |
165 |
|
4202 |
01 Apr 08 |
nicklas |
// The last document that was validated |
4202 |
01 Apr 08 |
nicklas |
167 |
private Document validatedDom; |
4202 |
01 Apr 08 |
nicklas |
168 |
|
5598 |
30 Mar 11 |
nicklas |
// The name of the last document |
5598 |
30 Mar 11 |
nicklas |
170 |
private String lastName; |
5598 |
30 Mar 11 |
nicklas |
171 |
|
4163 |
28 Feb 08 |
nicklas |
172 |
/** |
4163 |
28 Feb 08 |
nicklas |
Create a new XML loader instance. |
4163 |
28 Feb 08 |
nicklas |
174 |
*/ |
4163 |
28 Feb 08 |
nicklas |
175 |
public XmlLoader() |
4163 |
28 Feb 08 |
nicklas |
176 |
{ |
4163 |
28 Feb 08 |
nicklas |
177 |
extensionPoints = new LinkedList<ExtensionPoint<Action>>(); |
4163 |
28 Feb 08 |
nicklas |
178 |
extensions = new LinkedList<Extension<Action>>(); |
5610 |
15 Apr 11 |
nicklas |
179 |
pluginDefinitions = new LinkedList<PluginInfo>(); |
4198 |
28 Mar 08 |
nicklas |
180 |
factoryParameters = new HashMap<Object, String>(); |
6030 |
28 Mar 12 |
nicklas |
181 |
classLoaders = new HashMap<String, ClassLoader>(); |
4198 |
28 Mar 08 |
nicklas |
182 |
xmlOut = new XMLOutputter(Format.getPrettyFormat()); |
4163 |
28 Feb 08 |
nicklas |
183 |
} |
4163 |
28 Feb 08 |
nicklas |
184 |
|
4198 |
28 Mar 08 |
nicklas |
185 |
/** |
4198 |
28 Mar 08 |
nicklas |
Add a value converter to this loader |
4198 |
28 Mar 08 |
nicklas |
@param converter The converter to add |
4198 |
28 Mar 08 |
nicklas |
@throws NullPointerException If the converter is null |
4198 |
28 Mar 08 |
nicklas |
189 |
*/ |
4170 |
07 Mar 08 |
nicklas |
190 |
public void addValueConverter(ValueConverter converter) |
4170 |
07 Mar 08 |
nicklas |
191 |
{ |
4198 |
28 Mar 08 |
nicklas |
192 |
if (converter == null) throw new InvalidUseOfNullException("converter"); |
4198 |
28 Mar 08 |
nicklas |
193 |
if (converters == null) converters = new LinkedHashSet<ValueConverter>(); |
4170 |
07 Mar 08 |
nicklas |
194 |
converters.add(converter); |
4170 |
07 Mar 08 |
nicklas |
195 |
} |
4198 |
28 Mar 08 |
nicklas |
196 |
|
4198 |
28 Mar 08 |
nicklas |
197 |
/** |
4198 |
28 Mar 08 |
nicklas |
Remove a converter. |
4198 |
28 Mar 08 |
nicklas |
@param converter The converter to remove, null values are ignored |
4198 |
28 Mar 08 |
nicklas |
200 |
*/ |
4198 |
28 Mar 08 |
nicklas |
201 |
public void removeValueConverter(ValueConverter converter) |
4198 |
28 Mar 08 |
nicklas |
202 |
{ |
4198 |
28 Mar 08 |
nicklas |
203 |
if (converter == null || converters == null) return; |
4198 |
28 Mar 08 |
nicklas |
204 |
converters.remove(converter); |
4198 |
28 Mar 08 |
nicklas |
205 |
} |
4170 |
07 Mar 08 |
nicklas |
206 |
|
4163 |
28 Feb 08 |
nicklas |
207 |
/** |
4198 |
28 Mar 08 |
nicklas |
Remove all value converters. |
4198 |
28 Mar 08 |
nicklas |
209 |
*/ |
4198 |
28 Mar 08 |
nicklas |
210 |
public void clearValueConverters() |
4198 |
28 Mar 08 |
nicklas |
211 |
{ |
4198 |
28 Mar 08 |
nicklas |
212 |
if (converters != null) converters.clear(); |
4198 |
28 Mar 08 |
nicklas |
213 |
} |
4198 |
28 Mar 08 |
nicklas |
214 |
|
5598 |
30 Mar 11 |
nicklas |
215 |
private Filter<Element> filter; |
4198 |
28 Mar 08 |
nicklas |
216 |
/** |
5615 |
19 Apr 11 |
nicklas |
Set a filter that all <extension-point>, <extension>, |
5615 |
19 Apr 11 |
nicklas |
<ref> and <plugin-definition> tags must pass to be loaded |
5615 |
19 Apr 11 |
nicklas |
and registered. |
5598 |
30 Mar 11 |
nicklas |
@param filter A filter or null to remove an existing filter |
5598 |
30 Mar 11 |
nicklas |
@since 3.0 |
5598 |
30 Mar 11 |
nicklas |
222 |
*/ |
5598 |
30 Mar 11 |
nicklas |
223 |
public void setFilter(Filter<Element> filter) |
5598 |
30 Mar 11 |
nicklas |
224 |
{ |
7224 |
14 Nov 16 |
nicklas |
225 |
log.debug("Using filter: " + filter); |
5598 |
30 Mar 11 |
nicklas |
226 |
this.filter = filter; |
5598 |
30 Mar 11 |
nicklas |
227 |
} |
5598 |
30 Mar 11 |
nicklas |
228 |
|
5598 |
30 Mar 11 |
nicklas |
229 |
/** |
4163 |
28 Feb 08 |
nicklas |
Load an extensions definition XML file. This method may be called |
4202 |
01 Apr 08 |
nicklas |
multiple times with different XML files. The loading may also be |
4202 |
01 Apr 08 |
nicklas |
done by a two-step process where the first step validates the file |
4202 |
01 Apr 08 |
nicklas |
and the second step loads the extensions. See {@link |
4202 |
01 Apr 08 |
nicklas |
#validateXmlFile(InputStream, String)} and {@link |
4202 |
01 Apr 08 |
nicklas |
#loadLastValidatedFile(ClassLoader, boolean)}. |
4163 |
28 Feb 08 |
nicklas |
236 |
|
4163 |
28 Feb 08 |
nicklas |
@param xmlFile An input stream to read the XML data from |
4163 |
28 Feb 08 |
nicklas |
@param filename The original filename the stream is coming from, or null |
4163 |
28 Feb 08 |
nicklas |
if not known. This value is only used when generating error messages |
4163 |
28 Feb 08 |
nicklas |
@param classLoader The classloader to use when loading classes that are |
4163 |
28 Feb 08 |
nicklas |
named in the XML file, or null to use the default classloader (=the same |
4163 |
28 Feb 08 |
nicklas |
class loader that loaded the BASE core classes) |
4198 |
28 Mar 08 |
nicklas |
@param clear TRUE to clear all already loaded extensions before loading |
4198 |
28 Mar 08 |
nicklas |
the extensions in this file |
4198 |
28 Mar 08 |
nicklas |
@return Information about the extension, or null if no such information |
4198 |
28 Mar 08 |
nicklas |
is available |
4163 |
28 Feb 08 |
nicklas |
@throws IOException If there is an error reading the XML file |
4163 |
28 Feb 08 |
nicklas |
@throws ClassNotFoundException If a class named in the XML file can't |
4163 |
28 Feb 08 |
nicklas |
be found |
4163 |
28 Feb 08 |
nicklas |
@throws NoSuchMethodException If a factory class doesn't implement a |
4163 |
28 Feb 08 |
nicklas |
public, no-argument constructor |
4163 |
28 Feb 08 |
nicklas |
@throws IllegalAccessException If a factory class constructor isn't |
4163 |
28 Feb 08 |
nicklas |
public |
4163 |
28 Feb 08 |
nicklas |
@throws InstantiationException If a factory class can't be instantiated, |
4163 |
28 Feb 08 |
nicklas |
for example, because it is an abstract class or an interface |
4202 |
01 Apr 08 |
nicklas |
@see #validateXmlFile(InputStream, String) |
4202 |
01 Apr 08 |
nicklas |
@see #loadLastValidatedFile(ClassLoader, boolean) |
4163 |
28 Feb 08 |
nicklas |
258 |
*/ |
4198 |
28 Mar 08 |
nicklas |
259 |
public About loadXmlFile(InputStream xmlFile, String filename, |
4198 |
28 Mar 08 |
nicklas |
260 |
ClassLoader classLoader, boolean clear) |
6473 |
11 Jun 14 |
nicklas |
261 |
throws IOException, ClassNotFoundException, NoSuchMethodException, |
7513 |
02 Nov 18 |
nicklas |
262 |
IllegalAccessException, InstantiationException, InvocationTargetException |
4163 |
28 Feb 08 |
nicklas |
263 |
{ |
4202 |
01 Apr 08 |
nicklas |
264 |
validateXmlFile(xmlFile, filename); |
4202 |
01 Apr 08 |
nicklas |
265 |
return loadLastValidatedFile(classLoader, clear); |
4202 |
01 Apr 08 |
nicklas |
266 |
} |
4202 |
01 Apr 08 |
nicklas |
267 |
|
4202 |
01 Apr 08 |
nicklas |
268 |
/** |
4202 |
01 Apr 08 |
nicklas |
Validate an XML file against the extensions definition schema. If the |
4202 |
01 Apr 08 |
nicklas |
file is valid you may continue to load the extensions. See |
4202 |
01 Apr 08 |
nicklas |
{@link #loadLastValidatedFile(ClassLoader, boolean)}. |
4202 |
01 Apr 08 |
nicklas |
272 |
|
4202 |
01 Apr 08 |
nicklas |
@param xmlFile An input stream to read the XML data from |
4202 |
01 Apr 08 |
nicklas |
@param filename The original filename the stream is coming from, or null |
4202 |
01 Apr 08 |
nicklas |
if not known. This value is only used when generating error messages |
4202 |
01 Apr 08 |
nicklas |
@return Information about the extension, or null if no such information |
4202 |
01 Apr 08 |
nicklas |
is available |
4202 |
01 Apr 08 |
nicklas |
@throws IOException If there is an error reading the XML file |
4202 |
01 Apr 08 |
nicklas |
279 |
*/ |
4202 |
01 Apr 08 |
nicklas |
280 |
public About validateXmlFile(InputStream xmlFile, String filename) |
6473 |
11 Jun 14 |
nicklas |
281 |
throws IOException |
4202 |
01 Apr 08 |
nicklas |
282 |
{ |
4202 |
01 Apr 08 |
nicklas |
283 |
validatedDom = null; |
4202 |
01 Apr 08 |
nicklas |
284 |
validatedDom = loadDocument(xmlFile, filename); |
5598 |
30 Mar 11 |
nicklas |
285 |
lastName = filename; |
4202 |
01 Apr 08 |
nicklas |
286 |
About globalAbout = loadGlobalAbout(validatedDom); |
5607 |
15 Apr 11 |
nicklas |
287 |
verifyBaseVersion(globalAbout, true); |
4202 |
01 Apr 08 |
nicklas |
288 |
return globalAbout; |
4202 |
01 Apr 08 |
nicklas |
289 |
} |
4202 |
01 Apr 08 |
nicklas |
290 |
|
4202 |
01 Apr 08 |
nicklas |
291 |
/** |
4202 |
01 Apr 08 |
nicklas |
Continue loading extensions from the last validated XML file. This is |
4202 |
01 Apr 08 |
nicklas |
the second step in a two-step process and requires that |
4202 |
01 Apr 08 |
nicklas |
{@link #validateXmlFile(InputStream, String)} has been successfully called |
4202 |
01 Apr 08 |
nicklas |
first. |
4202 |
01 Apr 08 |
nicklas |
296 |
|
4202 |
01 Apr 08 |
nicklas |
@param classLoader The classloader to use when loading classes that are |
4202 |
01 Apr 08 |
nicklas |
named in the XML file, or null to use the default classloader (=the same |
4202 |
01 Apr 08 |
nicklas |
class loader that loaded the BASE core classes) |
4202 |
01 Apr 08 |
nicklas |
@param clear TRUE to clear all already loaded extensions before loading |
4202 |
01 Apr 08 |
nicklas |
the extensions in this file |
4202 |
01 Apr 08 |
nicklas |
@return Information about the extension, or null if no such information |
4202 |
01 Apr 08 |
nicklas |
is available |
4202 |
01 Apr 08 |
nicklas |
@throws ClassNotFoundException If a class named in the XML file can't |
4202 |
01 Apr 08 |
nicklas |
be found |
4202 |
01 Apr 08 |
nicklas |
@throws NoSuchMethodException If a factory class doesn't implement a |
4202 |
01 Apr 08 |
nicklas |
public, no-argument constructor |
4202 |
01 Apr 08 |
nicklas |
@throws IllegalAccessException If a factory class constructor isn't |
4202 |
01 Apr 08 |
nicklas |
public |
4202 |
01 Apr 08 |
nicklas |
@throws InstantiationException If a factory class can't be instantiated, |
4202 |
01 Apr 08 |
nicklas |
for example, because it is an abstract class or an interface |
4202 |
01 Apr 08 |
nicklas |
312 |
*/ |
4202 |
01 Apr 08 |
nicklas |
313 |
public About loadLastValidatedFile(ClassLoader classLoader, boolean clear) |
4202 |
01 Apr 08 |
nicklas |
314 |
throws ClassNotFoundException, IllegalAccessException, |
7513 |
02 Nov 18 |
nicklas |
315 |
InstantiationException, NoSuchMethodException, InvocationTargetException |
4202 |
01 Apr 08 |
nicklas |
316 |
{ |
4202 |
01 Apr 08 |
nicklas |
317 |
if (validatedDom == null) |
4202 |
01 Apr 08 |
nicklas |
318 |
{ |
4202 |
01 Apr 08 |
nicklas |
319 |
throw new NullPointerException("No file has been validated"); |
4202 |
01 Apr 08 |
nicklas |
320 |
} |
4198 |
28 Mar 08 |
nicklas |
321 |
if (clear) |
4198 |
28 Mar 08 |
nicklas |
322 |
{ |
4198 |
28 Mar 08 |
nicklas |
323 |
extensionPoints.clear(); |
4198 |
28 Mar 08 |
nicklas |
324 |
extensions.clear(); |
5610 |
15 Apr 11 |
nicklas |
325 |
pluginDefinitions.clear(); |
4198 |
28 Mar 08 |
nicklas |
326 |
} |
4202 |
01 Apr 08 |
nicklas |
327 |
About globalAbout = loadGlobalAbout(validatedDom); |
4202 |
01 Apr 08 |
nicklas |
328 |
loadExtensionPoints(validatedDom, classLoader, globalAbout); |
4202 |
01 Apr 08 |
nicklas |
329 |
loadExtensions(validatedDom, classLoader, globalAbout); |
5610 |
15 Apr 11 |
nicklas |
330 |
loadPluginDefinitions(validatedDom, classLoader, globalAbout); |
4202 |
01 Apr 08 |
nicklas |
331 |
validatedDom = null; |
4198 |
28 Mar 08 |
nicklas |
332 |
return globalAbout; |
4163 |
28 Feb 08 |
nicklas |
333 |
} |
4163 |
28 Feb 08 |
nicklas |
334 |
|
4163 |
28 Feb 08 |
nicklas |
335 |
/** |
4202 |
01 Apr 08 |
nicklas |
Checks if an XML file has passed validation in the |
4202 |
01 Apr 08 |
nicklas |
{@link #validateXmlFile(InputStream, String)} method. If so, |
4202 |
01 Apr 08 |
nicklas |
the {@link #loadLastValidatedFile(ClassLoader, boolean)} can be called |
4202 |
01 Apr 08 |
nicklas |
to continue loading the extensions. |
4202 |
01 Apr 08 |
nicklas |
<p> |
4202 |
01 Apr 08 |
nicklas |
Note that once the file has been loaded this flag is reset to |
4202 |
01 Apr 08 |
nicklas |
FALSE. |
4202 |
01 Apr 08 |
nicklas |
343 |
|
4202 |
01 Apr 08 |
nicklas |
@return TRUE if a file has been validated, FALSE otherwise |
4202 |
01 Apr 08 |
nicklas |
345 |
*/ |
4202 |
01 Apr 08 |
nicklas |
346 |
public boolean hasValidFile() |
4202 |
01 Apr 08 |
nicklas |
347 |
{ |
4202 |
01 Apr 08 |
nicklas |
348 |
return validatedDom != null; |
4202 |
01 Apr 08 |
nicklas |
349 |
} |
4202 |
01 Apr 08 |
nicklas |
350 |
|
4202 |
01 Apr 08 |
nicklas |
351 |
/** |
4163 |
28 Feb 08 |
nicklas |
Get a list with all loaded extension points. |
4163 |
28 Feb 08 |
nicklas |
353 |
*/ |
4163 |
28 Feb 08 |
nicklas |
354 |
public List<ExtensionPoint<Action>> getExtensionPoints() |
4163 |
28 Feb 08 |
nicklas |
355 |
{ |
4163 |
28 Feb 08 |
nicklas |
356 |
return extensionPoints; |
4163 |
28 Feb 08 |
nicklas |
357 |
} |
4163 |
28 Feb 08 |
nicklas |
358 |
|
4163 |
28 Feb 08 |
nicklas |
359 |
/** |
4163 |
28 Feb 08 |
nicklas |
Get a list with all loaded extensions. |
4163 |
28 Feb 08 |
nicklas |
361 |
*/ |
4163 |
28 Feb 08 |
nicklas |
362 |
public List<Extension<Action>> getExtensions() |
4163 |
28 Feb 08 |
nicklas |
363 |
{ |
4163 |
28 Feb 08 |
nicklas |
364 |
return extensions; |
4163 |
28 Feb 08 |
nicklas |
365 |
} |
4163 |
28 Feb 08 |
nicklas |
366 |
|
4163 |
28 Feb 08 |
nicklas |
367 |
/** |
5610 |
15 Apr 11 |
nicklas |
Get a list with all loaded plug-in definitions. |
5610 |
15 Apr 11 |
nicklas |
@since 3.0 |
5610 |
15 Apr 11 |
nicklas |
370 |
*/ |
5610 |
15 Apr 11 |
nicklas |
371 |
public List<PluginInfo> getPluginDefinitions() |
5610 |
15 Apr 11 |
nicklas |
372 |
{ |
5610 |
15 Apr 11 |
nicklas |
373 |
return pluginDefinitions; |
5610 |
15 Apr 11 |
nicklas |
374 |
} |
5610 |
15 Apr 11 |
nicklas |
375 |
|
5610 |
15 Apr 11 |
nicklas |
376 |
/** |
4198 |
28 Mar 08 |
nicklas |
Get a XML-like string representation of the parameters that was |
4198 |
28 Mar 08 |
nicklas |
used to initialise a factory. |
4198 |
28 Mar 08 |
nicklas |
@param factory The factory object |
4198 |
28 Mar 08 |
nicklas |
@return The parameters as found in the XML file |
4198 |
28 Mar 08 |
nicklas |
381 |
*/ |
4198 |
28 Mar 08 |
nicklas |
382 |
public String getFactoryParameters(Object factory) |
4198 |
28 Mar 08 |
nicklas |
383 |
{ |
4198 |
28 Mar 08 |
nicklas |
384 |
return factoryParameters.get(factory); |
4198 |
28 Mar 08 |
nicklas |
385 |
} |
4198 |
28 Mar 08 |
nicklas |
386 |
|
4198 |
28 Mar 08 |
nicklas |
387 |
/** |
4163 |
28 Feb 08 |
nicklas |
Register all loaded extension points with a registry. |
4163 |
28 Feb 08 |
nicklas |
@param registry The registry |
4198 |
28 Mar 08 |
nicklas |
@param update TRUE to update already registered extension |
4198 |
28 Mar 08 |
nicklas |
points, FALSE to ignore |
4198 |
28 Mar 08 |
nicklas |
@return The number of extension points registered or updated |
7703 |
11 Apr 19 |
nicklas |
@see Registry#registerExtensionPoint(ExtensionPoint, ClassLoader) |
4163 |
28 Feb 08 |
nicklas |
394 |
*/ |
4198 |
28 Mar 08 |
nicklas |
395 |
public int registerExtensionPoints(Registry registry, boolean update) |
4163 |
28 Feb 08 |
nicklas |
396 |
{ |
4198 |
28 Mar 08 |
nicklas |
397 |
int numRegistered = 0; |
4163 |
28 Feb 08 |
nicklas |
398 |
for (ExtensionPoint<Action> ep : extensionPoints) |
4163 |
28 Feb 08 |
nicklas |
399 |
{ |
4198 |
28 Mar 08 |
nicklas |
400 |
if (update || !registry.extensionPointIsRegistered(ep.getId())) |
4198 |
28 Mar 08 |
nicklas |
401 |
{ |
6030 |
28 Mar 12 |
nicklas |
402 |
registry.registerExtensionPoint(ep, classLoaders.get(ep.getId())); |
4198 |
28 Mar 08 |
nicklas |
403 |
numRegistered++; |
4198 |
28 Mar 08 |
nicklas |
404 |
} |
4163 |
28 Feb 08 |
nicklas |
405 |
} |
4198 |
28 Mar 08 |
nicklas |
406 |
return numRegistered; |
4163 |
28 Feb 08 |
nicklas |
407 |
} |
4163 |
28 Feb 08 |
nicklas |
408 |
|
4163 |
28 Feb 08 |
nicklas |
409 |
/** |
4180 |
17 Mar 08 |
nicklas |
Unregister all loaded extension points from a registry. |
4198 |
28 Mar 08 |
nicklas |
All extensions will also be unregistered. |
4180 |
17 Mar 08 |
nicklas |
@param registry The registry |
4198 |
28 Mar 08 |
nicklas |
@return The number of extension points that was unregistered |
4198 |
28 Mar 08 |
nicklas |
@see Registry#unregisterExtensionPoint(String) |
4180 |
17 Mar 08 |
nicklas |
415 |
*/ |
4198 |
28 Mar 08 |
nicklas |
416 |
public int unregisterExtensionPoints(Registry registry) |
4180 |
17 Mar 08 |
nicklas |
417 |
{ |
4180 |
17 Mar 08 |
nicklas |
418 |
for (ExtensionPoint<Action> ep : extensionPoints) |
4180 |
17 Mar 08 |
nicklas |
419 |
{ |
4180 |
17 Mar 08 |
nicklas |
420 |
registry.unregisterExtensionPoint(ep.getId()); |
4180 |
17 Mar 08 |
nicklas |
421 |
} |
4198 |
28 Mar 08 |
nicklas |
422 |
return extensionPoints.size(); |
4180 |
17 Mar 08 |
nicklas |
423 |
} |
4180 |
17 Mar 08 |
nicklas |
424 |
|
4180 |
17 Mar 08 |
nicklas |
425 |
/** |
4163 |
28 Feb 08 |
nicklas |
Register all loaded extensions with a registry. |
4163 |
28 Feb 08 |
nicklas |
@param registry The registry |
4198 |
28 Mar 08 |
nicklas |
@param update TRUE to update already registered extensions |
4198 |
28 Mar 08 |
nicklas |
FALSE to ignore |
4198 |
28 Mar 08 |
nicklas |
@return The number of registered or updated extensions |
7703 |
11 Apr 19 |
nicklas |
@see Registry#registerExtension(Extension, ClassLoader) |
4163 |
28 Feb 08 |
nicklas |
432 |
*/ |
4198 |
28 Mar 08 |
nicklas |
433 |
public int registerExtensions(Registry registry, boolean update) |
4163 |
28 Feb 08 |
nicklas |
434 |
{ |
4198 |
28 Mar 08 |
nicklas |
435 |
int numRegistered = 0; |
4163 |
28 Feb 08 |
nicklas |
436 |
for (Extension<Action> ext : extensions) |
4163 |
28 Feb 08 |
nicklas |
437 |
{ |
4198 |
28 Mar 08 |
nicklas |
438 |
if (update || !registry.extensionIsRegistered(ext.getId())) |
4198 |
28 Mar 08 |
nicklas |
439 |
{ |
6030 |
28 Mar 12 |
nicklas |
440 |
registry.registerExtension(ext, classLoaders.get(ext.getId())); |
4198 |
28 Mar 08 |
nicklas |
441 |
numRegistered++; |
4198 |
28 Mar 08 |
nicklas |
442 |
} |
4163 |
28 Feb 08 |
nicklas |
443 |
} |
4198 |
28 Mar 08 |
nicklas |
444 |
return numRegistered; |
4163 |
28 Feb 08 |
nicklas |
445 |
} |
4163 |
28 Feb 08 |
nicklas |
446 |
|
4163 |
28 Feb 08 |
nicklas |
447 |
/** |
4180 |
17 Mar 08 |
nicklas |
Unregister all loaded extensions from a registry. |
4180 |
17 Mar 08 |
nicklas |
@param registry The registry |
4198 |
28 Mar 08 |
nicklas |
@return The number of extensions that was unregistered |
4198 |
28 Mar 08 |
nicklas |
@see Registry#unregisterExtension(String) |
4180 |
17 Mar 08 |
nicklas |
452 |
*/ |
4198 |
28 Mar 08 |
nicklas |
453 |
public int unregisterExtensions(Registry registry) |
4180 |
17 Mar 08 |
nicklas |
454 |
{ |
4180 |
17 Mar 08 |
nicklas |
455 |
for (Extension<Action> ext : extensions) |
4180 |
17 Mar 08 |
nicklas |
456 |
{ |
4180 |
17 Mar 08 |
nicklas |
457 |
registry.unregisterExtension(ext.getId()); |
4180 |
17 Mar 08 |
nicklas |
458 |
} |
4198 |
28 Mar 08 |
nicklas |
459 |
return extensions.size(); |
4180 |
17 Mar 08 |
nicklas |
460 |
} |
4180 |
17 Mar 08 |
nicklas |
461 |
|
4180 |
17 Mar 08 |
nicklas |
462 |
/** |
4198 |
28 Mar 08 |
nicklas |
Load and validate the XML file. |
4198 |
28 Mar 08 |
nicklas |
@return A JDOM document object |
4198 |
28 Mar 08 |
nicklas |
465 |
*/ |
4198 |
28 Mar 08 |
nicklas |
466 |
protected Document loadDocument(InputStream xmlFile, String filename) |
6473 |
11 Jun 14 |
nicklas |
467 |
throws IOException |
4198 |
28 Mar 08 |
nicklas |
468 |
{ |
5598 |
30 Mar 11 |
nicklas |
469 |
log.debug("Validating file: " + filename); |
6473 |
11 Jun 14 |
nicklas |
470 |
return XmlUtil2.getSchemaValidatedXML(xmlFile, filename, NAMESPACE, SCHEMA_FILE_URL); |
4198 |
28 Mar 08 |
nicklas |
471 |
} |
4198 |
28 Mar 08 |
nicklas |
472 |
|
5607 |
15 Apr 11 |
nicklas |
473 |
protected boolean verifyBaseVersion(About about, boolean throwException) |
5607 |
15 Apr 11 |
nicklas |
474 |
{ |
5607 |
15 Apr 11 |
nicklas |
475 |
if (about == null) return true; |
5607 |
15 Apr 11 |
nicklas |
476 |
String minVersion = about.getMinBaseVersion(); |
5607 |
15 Apr 11 |
nicklas |
477 |
String maxVersion = about.getMaxBaseVersion(); |
5607 |
15 Apr 11 |
nicklas |
478 |
if (minVersion != null && Version.compareWith(minVersion) > 0) |
5607 |
15 Apr 11 |
nicklas |
479 |
{ |
5607 |
15 Apr 11 |
nicklas |
480 |
if (throwException) |
5607 |
15 Apr 11 |
nicklas |
481 |
{ |
5607 |
15 Apr 11 |
nicklas |
482 |
throw new BaseException("BASE version "+ minVersion + " or higher is required"); |
5607 |
15 Apr 11 |
nicklas |
483 |
} |
5607 |
15 Apr 11 |
nicklas |
484 |
return false; |
5607 |
15 Apr 11 |
nicklas |
485 |
} |
5607 |
15 Apr 11 |
nicklas |
486 |
if (maxVersion != null && Version.compareWith(maxVersion) <= 0) |
5607 |
15 Apr 11 |
nicklas |
487 |
{ |
5607 |
15 Apr 11 |
nicklas |
488 |
if (throwException) |
5607 |
15 Apr 11 |
nicklas |
489 |
{ |
5607 |
15 Apr 11 |
nicklas |
490 |
throw new BaseException("BASE version "+ maxVersion + " or higher is not supported"); |
5607 |
15 Apr 11 |
nicklas |
491 |
} |
5607 |
15 Apr 11 |
nicklas |
492 |
return false; |
5607 |
15 Apr 11 |
nicklas |
493 |
} |
5607 |
15 Apr 11 |
nicklas |
494 |
return true; |
5607 |
15 Apr 11 |
nicklas |
495 |
} |
5607 |
15 Apr 11 |
nicklas |
496 |
|
4198 |
28 Mar 08 |
nicklas |
497 |
/** |
4198 |
28 Mar 08 |
nicklas |
Load the global about tag from the document. |
4198 |
28 Mar 08 |
nicklas |
@return An about bean or null if the about tag is not found. |
4198 |
28 Mar 08 |
nicklas |
500 |
*/ |
4198 |
28 Mar 08 |
nicklas |
501 |
protected AboutBean loadGlobalAbout(Document dom) |
4198 |
28 Mar 08 |
nicklas |
502 |
{ |
4198 |
28 Mar 08 |
nicklas |
503 |
Element root = dom.getRootElement(); |
4198 |
28 Mar 08 |
nicklas |
504 |
Namespace ns = root.getNamespace(); |
4198 |
28 Mar 08 |
nicklas |
505 |
return loadAbout(root.getChild("about", ns)); |
4198 |
28 Mar 08 |
nicklas |
506 |
} |
4198 |
28 Mar 08 |
nicklas |
507 |
|
4198 |
28 Mar 08 |
nicklas |
508 |
/** |
4198 |
28 Mar 08 |
nicklas |
Load information in an <code><about></code> tag. |
4198 |
28 Mar 08 |
nicklas |
@param aboutTag The about tag |
4198 |
28 Mar 08 |
nicklas |
511 |
*/ |
4198 |
28 Mar 08 |
nicklas |
512 |
protected AboutBean loadAbout(Element aboutTag) |
4198 |
28 Mar 08 |
nicklas |
513 |
{ |
4198 |
28 Mar 08 |
nicklas |
514 |
AboutBean about = null; |
4198 |
28 Mar 08 |
nicklas |
515 |
if (aboutTag != null) |
4198 |
28 Mar 08 |
nicklas |
516 |
{ |
4198 |
28 Mar 08 |
nicklas |
517 |
Namespace ns = aboutTag.getNamespace(); |
4198 |
28 Mar 08 |
nicklas |
518 |
about = new AboutBean(); |
4198 |
28 Mar 08 |
nicklas |
519 |
about.setName(Values.getStringOrNull(aboutTag.getChildText("name", ns))); |
4198 |
28 Mar 08 |
nicklas |
520 |
about.setDescription(Values.getStringOrNull(aboutTag.getChildText("description", ns))); |
4198 |
28 Mar 08 |
nicklas |
521 |
about.setVersion(Values.getStringOrNull(aboutTag.getChildText("version", ns))); |
5607 |
15 Apr 11 |
nicklas |
522 |
about.setMinBaseVersion(Values.getStringOrNull(aboutTag.getChildText("min-base-version", ns))); |
5607 |
15 Apr 11 |
nicklas |
523 |
about.setMaxBaseVersion(Values.getStringOrNull(aboutTag.getChildText("max-base-version", ns))); |
4198 |
28 Mar 08 |
nicklas |
524 |
about.setContact(Values.getStringOrNull(aboutTag.getChildText("contact", ns))); |
4198 |
28 Mar 08 |
nicklas |
525 |
about.setCopyright(Values.getStringOrNull(aboutTag.getChildText("copyright", ns))); |
4198 |
28 Mar 08 |
nicklas |
526 |
about.setEmail(Values.getStringOrNull(aboutTag.getChildText("email", ns))); |
4198 |
28 Mar 08 |
nicklas |
527 |
about.setUrl(Values.getStringOrNull(aboutTag.getChildText("url", ns))); |
6408 |
31 Jan 14 |
nicklas |
528 |
|
6473 |
11 Jun 14 |
nicklas |
529 |
List<Attribute> attributes = aboutTag.getAttributes(); |
6408 |
31 Jan 14 |
nicklas |
530 |
for (Attribute a : attributes) |
6408 |
31 Jan 14 |
nicklas |
531 |
{ |
6408 |
31 Jan 14 |
nicklas |
532 |
about.setAttribute(a.getName(), a.getValue()); |
6408 |
31 Jan 14 |
nicklas |
533 |
} |
4198 |
28 Mar 08 |
nicklas |
534 |
} |
4198 |
28 Mar 08 |
nicklas |
535 |
return about; |
4198 |
28 Mar 08 |
nicklas |
536 |
} |
4198 |
28 Mar 08 |
nicklas |
537 |
|
4198 |
28 Mar 08 |
nicklas |
538 |
|
4198 |
28 Mar 08 |
nicklas |
539 |
/** |
4163 |
28 Feb 08 |
nicklas |
Create extension points from an XML document. |
4163 |
28 Feb 08 |
nicklas |
541 |
*/ |
6875 |
20 Apr 15 |
nicklas |
542 |
@SuppressWarnings({ "unchecked", "rawtypes" }) |
4198 |
28 Mar 08 |
nicklas |
543 |
protected int loadExtensionPoints(Document dom, ClassLoader classLoader, About globalAbout) |
4163 |
28 Feb 08 |
nicklas |
544 |
throws ClassNotFoundException, NoSuchMethodException, |
7513 |
02 Nov 18 |
nicklas |
545 |
IllegalAccessException, InstantiationException, InvocationTargetException |
4163 |
28 Feb 08 |
nicklas |
546 |
{ |
5598 |
30 Mar 11 |
nicklas |
547 |
log.debug("Loading extension points from file: " + lastName); |
4198 |
28 Mar 08 |
nicklas |
548 |
int numLoaded = 0; |
4198 |
28 Mar 08 |
nicklas |
549 |
List<ExtensionPoint<Action>> temp = new LinkedList<ExtensionPoint<Action>>(); |
4163 |
28 Feb 08 |
nicklas |
550 |
/* |
4163 |
28 Feb 08 |
nicklas |
Format of an extension point is: |
4163 |
28 Feb 08 |
nicklas |
<extension-point |
4163 |
28 Feb 08 |
nicklas |
id="..." |
4163 |
28 Feb 08 |
nicklas |
554 |
> |
4168 |
04 Mar 08 |
nicklas |
<name>...</name> |
4163 |
28 Feb 08 |
nicklas |
<description>...</description> |
4163 |
28 Feb 08 |
nicklas |
<action-class>...</action-class> |
4163 |
28 Feb 08 |
nicklas |
<renderer-factory override="true|false"> |
4163 |
28 Feb 08 |
nicklas |
<factory-class>...</factory-class> |
4163 |
28 Feb 08 |
nicklas |
<parameters> |
4163 |
28 Feb 08 |
nicklas |
any-tags |
4163 |
28 Feb 08 |
nicklas |
</parameters> |
4163 |
28 Feb 08 |
nicklas |
</renderer-factory> |
5486 |
12 Nov 10 |
nicklas |
<error-handler-factory> |
5486 |
12 Nov 10 |
nicklas |
<factory-class>...</factory-class> |
5486 |
12 Nov 10 |
nicklas |
<parameters> |
5486 |
12 Nov 10 |
nicklas |
any-tags |
5486 |
12 Nov 10 |
nicklas |
</parameters> |
5486 |
12 Nov 10 |
nicklas |
</error-handler-factory> |
4163 |
28 Feb 08 |
nicklas |
</extension-point> |
4163 |
28 Feb 08 |
nicklas |
571 |
*/ |
4163 |
28 Feb 08 |
nicklas |
572 |
Element root = dom.getRootElement(); |
4163 |
28 Feb 08 |
nicklas |
573 |
Namespace ns = root.getNamespace(); |
4874 |
02 Apr 09 |
nicklas |
// ID base will be prepended to extension point id:s if defined |
4874 |
02 Apr 09 |
nicklas |
575 |
String idBase = Values.getStringOrNull(root.getAttributeValue("id-base")); |
4874 |
02 Apr 09 |
nicklas |
576 |
|
4163 |
28 Feb 08 |
nicklas |
577 |
List<Element> epTags = root.getChildren("extension-point", ns); |
5598 |
30 Mar 11 |
nicklas |
578 |
log.debug("Found " + epTags.size() + " extension point(s) in file: " + lastName); |
4163 |
28 Feb 08 |
nicklas |
579 |
for (Element epTag : epTags) |
4163 |
28 Feb 08 |
nicklas |
580 |
{ |
4163 |
28 Feb 08 |
nicklas |
581 |
String id = Values.getStringOrNull(epTag.getAttributeValue("id")); |
4874 |
02 Apr 09 |
nicklas |
582 |
if (idBase != null) id = idBase + id; |
5598 |
30 Mar 11 |
nicklas |
583 |
|
5598 |
30 Mar 11 |
nicklas |
584 |
log.debug("Processing extension point: " + id); |
4163 |
28 Feb 08 |
nicklas |
585 |
|
5598 |
30 Mar 11 |
nicklas |
586 |
if (filter == null || filter.evaluate(epTag)) |
4163 |
28 Feb 08 |
nicklas |
587 |
{ |
5598 |
30 Mar 11 |
nicklas |
588 |
ExtensionPointBean<Action> extensionPoint = new ExtensionPointBean<Action>(); |
5598 |
30 Mar 11 |
nicklas |
589 |
temp.add(extensionPoint); |
5598 |
30 Mar 11 |
nicklas |
590 |
numLoaded++; |
5598 |
30 Mar 11 |
nicklas |
591 |
|
6030 |
28 Mar 12 |
nicklas |
// Set ID (required) and classloader |
5598 |
30 Mar 11 |
nicklas |
593 |
extensionPoint.setId(id); |
5598 |
30 Mar 11 |
nicklas |
594 |
|
5598 |
30 Mar 11 |
nicklas |
// Set Name and Description (optional) |
5598 |
30 Mar 11 |
nicklas |
596 |
extensionPoint.setName(Values.getStringOrNull(epTag.getChildText("name", ns))); |
5598 |
30 Mar 11 |
nicklas |
597 |
extensionPoint.setDescription(Values.getStringOrNull(epTag.getChildText("description", ns))); |
5598 |
30 Mar 11 |
nicklas |
598 |
|
5598 |
30 Mar 11 |
nicklas |
// Load and set Action class (required) |
5598 |
30 Mar 11 |
nicklas |
600 |
String actionClassName = Values.getStringOrNull(epTag.getChildText("action-class", ns)); |
5598 |
30 Mar 11 |
nicklas |
601 |
Class actionClass = |
5598 |
30 Mar 11 |
nicklas |
602 |
ClassUtil.checkAndLoadClass(classLoader, actionClassName, false, Action.class); |
5598 |
30 Mar 11 |
nicklas |
603 |
extensionPoint.setActionClass(actionClass); |
5598 |
30 Mar 11 |
nicklas |
604 |
|
5598 |
30 Mar 11 |
nicklas |
// Load and set RendererFactory (optional) |
5598 |
30 Mar 11 |
nicklas |
606 |
Element rfTag = epTag.getChild("renderer-factory", ns); |
5598 |
30 Mar 11 |
nicklas |
607 |
if (rfTag != null) |
5598 |
30 Mar 11 |
nicklas |
608 |
{ |
6875 |
20 Apr 15 |
nicklas |
609 |
RendererFactory<? super Action> rf = createFactory(rfTag, classLoader, RendererFactory.class, null); |
5598 |
30 Mar 11 |
nicklas |
610 |
extensionPoint.setRendererFactory(rf); |
5598 |
30 Mar 11 |
nicklas |
611 |
extensionPoint.setAllowRendererOverrider( |
5598 |
30 Mar 11 |
nicklas |
612 |
Values.getBoolean(rfTag.getAttributeValue("override"))); |
5598 |
30 Mar 11 |
nicklas |
613 |
} |
5598 |
30 Mar 11 |
nicklas |
614 |
|
5598 |
30 Mar 11 |
nicklas |
615 |
Element ehfTag = epTag.getChild("error-handler-factory", ns); |
5598 |
30 Mar 11 |
nicklas |
616 |
if (ehfTag != null) |
5598 |
30 Mar 11 |
nicklas |
617 |
{ |
6875 |
20 Apr 15 |
nicklas |
618 |
ErrorHandlerFactory<? super Action> ehf = createFactory(ehfTag, classLoader, ErrorHandlerFactory.class, null); |
5598 |
30 Mar 11 |
nicklas |
619 |
extensionPoint.setErrorHandlerFactory(ehf); |
5598 |
30 Mar 11 |
nicklas |
620 |
} |
6030 |
28 Mar 12 |
nicklas |
621 |
|
6030 |
28 Mar 12 |
nicklas |
622 |
if (classLoader != null) classLoaders.put(extensionPoint.getId(), classLoader); |
4163 |
28 Feb 08 |
nicklas |
623 |
} |
4163 |
28 Feb 08 |
nicklas |
624 |
} |
4198 |
28 Mar 08 |
nicklas |
625 |
extensionPoints.addAll(temp); |
4198 |
28 Mar 08 |
nicklas |
626 |
return numLoaded; |
4163 |
28 Feb 08 |
nicklas |
627 |
} |
4163 |
28 Feb 08 |
nicklas |
628 |
|
4163 |
28 Feb 08 |
nicklas |
629 |
|
4163 |
28 Feb 08 |
nicklas |
630 |
/** |
4163 |
28 Feb 08 |
nicklas |
Create extensions from an XML document. |
4163 |
28 Feb 08 |
nicklas |
632 |
*/ |
4163 |
28 Feb 08 |
nicklas |
633 |
@SuppressWarnings("unchecked") |
4198 |
28 Mar 08 |
nicklas |
634 |
protected int loadExtensions(Document dom, ClassLoader classLoader, About globalAbout) |
4163 |
28 Feb 08 |
nicklas |
635 |
throws ClassNotFoundException, NoSuchMethodException, |
7513 |
02 Nov 18 |
nicklas |
636 |
IllegalAccessException, InstantiationException, InvocationTargetException |
4163 |
28 Feb 08 |
nicklas |
637 |
{ |
5598 |
30 Mar 11 |
nicklas |
638 |
log.debug("Loading extensions from file: " + lastName); |
4198 |
28 Mar 08 |
nicklas |
639 |
int numLoaded = 0; |
4198 |
28 Mar 08 |
nicklas |
640 |
List<Extension<Action>> temp = new LinkedList<Extension<Action>>(); |
4163 |
28 Feb 08 |
nicklas |
641 |
/* |
4163 |
28 Feb 08 |
nicklas |
Format of an extension is: |
4163 |
28 Feb 08 |
nicklas |
<extension |
4163 |
28 Feb 08 |
nicklas |
id="..." |
4163 |
28 Feb 08 |
nicklas |
extends="..." |
4163 |
28 Feb 08 |
nicklas |
646 |
> |
5519 |
23 Nov 10 |
nicklas |
<index>...</index> |
4163 |
28 Feb 08 |
nicklas |
<about> |
4163 |
28 Feb 08 |
nicklas |
<name>...</name> |
4163 |
28 Feb 08 |
nicklas |
<description>...</name> |
4163 |
28 Feb 08 |
nicklas |
<version>...</version> |
4163 |
28 Feb 08 |
nicklas |
<contact>...</contact> |
4163 |
28 Feb 08 |
nicklas |
<copyright>...</copyright> |
4163 |
28 Feb 08 |
nicklas |
<email>...</email> |
4163 |
28 Feb 08 |
nicklas |
<url>...</url> |
4163 |
28 Feb 08 |
nicklas |
</about> |
4163 |
28 Feb 08 |
nicklas |
<action-factory> |
4163 |
28 Feb 08 |
nicklas |
<factory-class>...</factory-class> |
4163 |
28 Feb 08 |
nicklas |
<parameters> |
4163 |
28 Feb 08 |
nicklas |
any-tags |
4163 |
28 Feb 08 |
nicklas |
</parameters> |
4163 |
28 Feb 08 |
nicklas |
</action-factory> |
4163 |
28 Feb 08 |
nicklas |
<action-factory> |
4163 |
28 Feb 08 |
nicklas |
<factory-class>...</factory-class> |
4163 |
28 Feb 08 |
nicklas |
<parameters> |
4163 |
28 Feb 08 |
nicklas |
any-tags |
4163 |
28 Feb 08 |
nicklas |
</parameters> |
4163 |
28 Feb 08 |
nicklas |
</action-factory> |
4163 |
28 Feb 08 |
nicklas |
</extension> |
4163 |
28 Feb 08 |
nicklas |
670 |
*/ |
4163 |
28 Feb 08 |
nicklas |
671 |
|
4163 |
28 Feb 08 |
nicklas |
672 |
Element root = dom.getRootElement(); |
4163 |
28 Feb 08 |
nicklas |
673 |
Namespace ns = root.getNamespace(); |
4874 |
02 Apr 09 |
nicklas |
// ID base will be prepended to extension point id:s if defined |
4874 |
02 Apr 09 |
nicklas |
675 |
String idBase = Values.getStringOrNull(root.getAttributeValue("id-base")); |
4874 |
02 Apr 09 |
nicklas |
676 |
|
4163 |
28 Feb 08 |
nicklas |
677 |
List<Element> epTags = root.getChildren("extension", ns); |
5598 |
30 Mar 11 |
nicklas |
678 |
log.debug("Found " + epTags.size() + " extension(s) in file: " + lastName); |
4163 |
28 Feb 08 |
nicklas |
679 |
for (Element epTag : epTags) |
4163 |
28 Feb 08 |
nicklas |
680 |
{ |
5519 |
23 Nov 10 |
nicklas |
// id |
4163 |
28 Feb 08 |
nicklas |
682 |
String id = Values.getStringOrNull(epTag.getAttributeValue("id")); |
4874 |
02 Apr 09 |
nicklas |
683 |
if (idBase != null) id = idBase + id; |
5598 |
30 Mar 11 |
nicklas |
684 |
log.debug("Processing extension: " + id); |
5519 |
23 Nov 10 |
nicklas |
685 |
|
5598 |
30 Mar 11 |
nicklas |
// <index> |
5598 |
30 Mar 11 |
nicklas |
687 |
float defaultIndex = Values.getFloat(epTag.getChildText("index", ns), 999.0f); |
5598 |
30 Mar 11 |
nicklas |
688 |
|
5519 |
23 Nov 10 |
nicklas |
// Pick up the extension points + index |
5519 |
23 Nov 10 |
nicklas |
690 |
List<String> extensionPoints = new ArrayList<String>(); |
5519 |
23 Nov 10 |
nicklas |
691 |
List<Float> indexes = new ArrayList<Float>(); |
5519 |
23 Nov 10 |
nicklas |
// First... the extends attribute |
5519 |
23 Nov 10 |
nicklas |
693 |
String epId = Values.getStringOrNull(epTag.getAttributeValue("extends")); |
5519 |
23 Nov 10 |
nicklas |
694 |
if (epId != null) |
5519 |
23 Nov 10 |
nicklas |
695 |
{ |
5598 |
30 Mar 11 |
nicklas |
696 |
if (filter == null || filter.evaluate(epTag)) |
5598 |
30 Mar 11 |
nicklas |
697 |
{ |
5598 |
30 Mar 11 |
nicklas |
698 |
extensionPoints.add(epId); |
5598 |
30 Mar 11 |
nicklas |
699 |
indexes.add(defaultIndex); |
5598 |
30 Mar 11 |
nicklas |
700 |
} |
5519 |
23 Nov 10 |
nicklas |
701 |
} |
5598 |
30 Mar 11 |
nicklas |
702 |
|
5519 |
23 Nov 10 |
nicklas |
// Then... any <extends>/<ref> subtags |
5519 |
23 Nov 10 |
nicklas |
704 |
Element extendsTag = epTag.getChild("extends", ns); |
5519 |
23 Nov 10 |
nicklas |
705 |
if (extendsTag != null) |
5519 |
23 Nov 10 |
nicklas |
706 |
{ |
6870 |
16 Apr 15 |
nicklas |
707 |
for (Element refTag : extendsTag.getChildren("ref", ns)) |
5519 |
23 Nov 10 |
nicklas |
708 |
{ |
5598 |
30 Mar 11 |
nicklas |
709 |
if (filter == null || filter.evaluate(refTag)) |
5519 |
23 Nov 10 |
nicklas |
710 |
{ |
5598 |
30 Mar 11 |
nicklas |
711 |
epId = Values.getStringOrNull(refTag.getText()); |
5598 |
30 Mar 11 |
nicklas |
712 |
if (epId != null) |
5598 |
30 Mar 11 |
nicklas |
713 |
{ |
5598 |
30 Mar 11 |
nicklas |
714 |
extensionPoints.add(epId); |
5598 |
30 Mar 11 |
nicklas |
715 |
indexes.add(Values.getFloat(refTag.getAttributeValue("index"), defaultIndex)); |
5598 |
30 Mar 11 |
nicklas |
716 |
} |
5519 |
23 Nov 10 |
nicklas |
717 |
} |
5519 |
23 Nov 10 |
nicklas |
718 |
} |
5519 |
23 Nov 10 |
nicklas |
719 |
} |
5598 |
30 Mar 11 |
nicklas |
720 |
|
5598 |
30 Mar 11 |
nicklas |
// Any extension points remaining after filtering? |
5598 |
30 Mar 11 |
nicklas |
722 |
if (extensionPoints.size() > 0) |
5519 |
23 Nov 10 |
nicklas |
723 |
{ |
5598 |
30 Mar 11 |
nicklas |
724 |
|
5598 |
30 Mar 11 |
nicklas |
// <about> |
5598 |
30 Mar 11 |
nicklas |
726 |
AboutBean about = loadAbout(epTag.getChild("about", ns)); |
5598 |
30 Mar 11 |
nicklas |
727 |
if (globalAbout != null) |
5598 |
30 Mar 11 |
nicklas |
728 |
{ |
5598 |
30 Mar 11 |
nicklas |
729 |
if (about == null) about = new AboutBean(); |
5598 |
30 Mar 11 |
nicklas |
730 |
about.copy(globalAbout, false); |
5598 |
30 Mar 11 |
nicklas |
731 |
} |
5607 |
15 Apr 11 |
nicklas |
732 |
|
5607 |
15 Apr 11 |
nicklas |
733 |
if (!verifyBaseVersion(about, false)) |
5598 |
30 Mar 11 |
nicklas |
734 |
{ |
5607 |
15 Apr 11 |
nicklas |
735 |
String min = about.getMinBaseVersion(); |
5607 |
15 Apr 11 |
nicklas |
736 |
String max = about.getMaxBaseVersion(); |
5607 |
15 Apr 11 |
nicklas |
737 |
log.info("Extension '" + id + "' require BASE version between " + |
5607 |
15 Apr 11 |
nicklas |
738 |
(min == null ? "*" : min) + " and " + (max == null ? "*" : max) |
5607 |
15 Apr 11 |
nicklas |
739 |
); |
5598 |
30 Mar 11 |
nicklas |
740 |
} |
5607 |
15 Apr 11 |
nicklas |
741 |
else |
5598 |
30 Mar 11 |
nicklas |
742 |
{ |
5607 |
15 Apr 11 |
nicklas |
// <action-factory> |
5607 |
15 Apr 11 |
nicklas |
744 |
Element afTag = epTag.getChild("action-factory", ns); |
6875 |
20 Apr 15 |
nicklas |
745 |
ActionFactory<? super Action> af = null; |
6627 |
25 Nov 14 |
nicklas |
746 |
Preset config = Application.getExtensionsManager().getSettings().getSettingsForExtension(id); |
5607 |
15 Apr 11 |
nicklas |
747 |
if (afTag != null) |
5607 |
15 Apr 11 |
nicklas |
748 |
{ |
6627 |
25 Nov 14 |
nicklas |
749 |
af = createFactory(afTag, classLoader, ActionFactory.class, config); |
5607 |
15 Apr 11 |
nicklas |
750 |
} |
5519 |
23 Nov 10 |
nicklas |
751 |
|
5607 |
15 Apr 11 |
nicklas |
// <renderer-factory> |
5607 |
15 Apr 11 |
nicklas |
753 |
Element rfTag = epTag.getChild("renderer-factory", ns); |
6875 |
20 Apr 15 |
nicklas |
754 |
RendererFactory<? super Action> rf = null; |
5607 |
15 Apr 11 |
nicklas |
755 |
if (rfTag != null) |
5607 |
15 Apr 11 |
nicklas |
756 |
{ |
6627 |
25 Nov 14 |
nicklas |
757 |
rf = createFactory(rfTag, classLoader, RendererFactory.class, config); |
5607 |
15 Apr 11 |
nicklas |
758 |
} |
5598 |
30 Mar 11 |
nicklas |
759 |
|
5607 |
15 Apr 11 |
nicklas |
760 |
String commonIdPrefix = null; |
5607 |
15 Apr 11 |
nicklas |
761 |
if (extensionPoints.size() > 1) |
5598 |
30 Mar 11 |
nicklas |
762 |
{ |
5607 |
15 Apr 11 |
nicklas |
// We need to calculate the common id prefix for the extension points |
5607 |
15 Apr 11 |
nicklas |
// so that we can create unique extension id:s |
5607 |
15 Apr 11 |
nicklas |
765 |
commonIdPrefix = StringUtil.getCommonPrefix(extensionPoints); |
5598 |
30 Mar 11 |
nicklas |
766 |
} |
5598 |
30 Mar 11 |
nicklas |
767 |
|
5607 |
15 Apr 11 |
nicklas |
768 |
for (int i = 0; i < extensionPoints.size(); ++i) |
5607 |
15 Apr 11 |
nicklas |
769 |
{ |
5607 |
15 Apr 11 |
nicklas |
770 |
epId = extensionPoints.get(i); |
5607 |
15 Apr 11 |
nicklas |
771 |
float index = indexes.get(i); |
5607 |
15 Apr 11 |
nicklas |
772 |
ExtensionBean<Action> ext = new ExtensionBean<Action>(); |
5607 |
15 Apr 11 |
nicklas |
773 |
temp.add(ext); |
5607 |
15 Apr 11 |
nicklas |
774 |
numLoaded++; |
5607 |
15 Apr 11 |
nicklas |
775 |
|
5607 |
15 Apr 11 |
nicklas |
776 |
String thisId = id; |
5607 |
15 Apr 11 |
nicklas |
777 |
if (commonIdPrefix != null) |
5607 |
15 Apr 11 |
nicklas |
778 |
{ |
5607 |
15 Apr 11 |
nicklas |
779 |
thisId += ":" + epId.substring(commonIdPrefix.length()); |
5607 |
15 Apr 11 |
nicklas |
780 |
} |
5607 |
15 Apr 11 |
nicklas |
781 |
|
5607 |
15 Apr 11 |
nicklas |
782 |
ext.setId(thisId); |
5607 |
15 Apr 11 |
nicklas |
783 |
ext.setExtends(epId); |
5607 |
15 Apr 11 |
nicklas |
784 |
ext.setIndex(index); |
5607 |
15 Apr 11 |
nicklas |
785 |
ext.setAbout(about); |
5607 |
15 Apr 11 |
nicklas |
786 |
ext.setActionFactory(af); |
5607 |
15 Apr 11 |
nicklas |
787 |
ext.setRendererFactory(rf); |
6030 |
28 Mar 12 |
nicklas |
788 |
if (classLoader != null) classLoaders.put(ext.getId(), classLoader); |
5607 |
15 Apr 11 |
nicklas |
789 |
} |
5598 |
30 Mar 11 |
nicklas |
790 |
} |
4163 |
28 Feb 08 |
nicklas |
791 |
} |
4163 |
28 Feb 08 |
nicklas |
792 |
} |
4198 |
28 Mar 08 |
nicklas |
793 |
extensions.addAll(temp); |
4198 |
28 Mar 08 |
nicklas |
794 |
return numLoaded; |
4163 |
28 Feb 08 |
nicklas |
795 |
} |
4163 |
28 Feb 08 |
nicklas |
796 |
|
4163 |
28 Feb 08 |
nicklas |
797 |
/** |
5610 |
15 Apr 11 |
nicklas |
Load plug-in information from an XML document. |
5610 |
15 Apr 11 |
nicklas |
@since 3.0 |
5610 |
15 Apr 11 |
nicklas |
800 |
*/ |
5610 |
15 Apr 11 |
nicklas |
801 |
protected int loadPluginDefinitions(Document dom, ClassLoader classLoader, About globalAbout) |
5610 |
15 Apr 11 |
nicklas |
802 |
throws ClassNotFoundException, NoSuchMethodException, |
5610 |
15 Apr 11 |
nicklas |
803 |
IllegalAccessException, InstantiationException |
5610 |
15 Apr 11 |
nicklas |
804 |
{ |
5610 |
15 Apr 11 |
nicklas |
805 |
log.debug("Loading plug-in definitions from file: " + lastName); |
5610 |
15 Apr 11 |
nicklas |
806 |
int numLoaded = 0; |
5610 |
15 Apr 11 |
nicklas |
807 |
List<PluginInfo> temp = new LinkedList<PluginInfo>(); |
5610 |
15 Apr 11 |
nicklas |
808 |
/* |
5610 |
15 Apr 11 |
nicklas |
Format of a plug-in definition is: |
5610 |
15 Apr 11 |
nicklas |
<plugin-definition |
5610 |
15 Apr 11 |
nicklas |
id="..." |
5610 |
15 Apr 11 |
nicklas |
812 |
> |
5610 |
15 Apr 11 |
nicklas |
<about> |
5610 |
15 Apr 11 |
nicklas |
<name>...</name> |
5610 |
15 Apr 11 |
nicklas |
<description>...</name> |
5610 |
15 Apr 11 |
nicklas |
<version>...</version> |
5610 |
15 Apr 11 |
nicklas |
<contact>...</contact> |
5610 |
15 Apr 11 |
nicklas |
<copyright>...</copyright> |
5610 |
15 Apr 11 |
nicklas |
<email>...</email> |
5610 |
15 Apr 11 |
nicklas |
<url>...</url> |
5610 |
15 Apr 11 |
nicklas |
</about> |
5610 |
15 Apr 11 |
nicklas |
<plugin-class>...</plugin-class> |
5610 |
15 Apr 11 |
nicklas |
</plugin-definition> |
5610 |
15 Apr 11 |
nicklas |
824 |
*/ |
5610 |
15 Apr 11 |
nicklas |
825 |
|
5610 |
15 Apr 11 |
nicklas |
826 |
Element root = dom.getRootElement(); |
5610 |
15 Apr 11 |
nicklas |
827 |
Namespace ns = root.getNamespace(); |
5610 |
15 Apr 11 |
nicklas |
// ID base will be prepended to extension point id:s if defined |
5610 |
15 Apr 11 |
nicklas |
829 |
String idBase = Values.getStringOrNull(root.getAttributeValue("id-base")); |
5610 |
15 Apr 11 |
nicklas |
830 |
|
5610 |
15 Apr 11 |
nicklas |
831 |
List<Element> pdTags = root.getChildren("plugin-definition", ns); |
5610 |
15 Apr 11 |
nicklas |
832 |
log.debug("Found " + pdTags.size() + " plug-in definitions in file: " + lastName); |
5610 |
15 Apr 11 |
nicklas |
833 |
for (Element pdTag : pdTags) |
5610 |
15 Apr 11 |
nicklas |
834 |
{ |
5610 |
15 Apr 11 |
nicklas |
// id |
5610 |
15 Apr 11 |
nicklas |
836 |
String id = Values.getStringOrNull(pdTag.getAttributeValue("id")); |
5610 |
15 Apr 11 |
nicklas |
837 |
if (idBase != null) id = idBase + id; |
5610 |
15 Apr 11 |
nicklas |
838 |
log.debug("Processing plug-in definition: " + id); |
5610 |
15 Apr 11 |
nicklas |
839 |
|
5615 |
19 Apr 11 |
nicklas |
840 |
if (filter == null || filter.evaluate(pdTag)) |
5610 |
15 Apr 11 |
nicklas |
841 |
{ |
5615 |
19 Apr 11 |
nicklas |
// <about> |
5615 |
19 Apr 11 |
nicklas |
843 |
AboutBean about = loadAbout(pdTag.getChild("about", ns)); |
5615 |
19 Apr 11 |
nicklas |
844 |
if (globalAbout != null) |
5610 |
15 Apr 11 |
nicklas |
845 |
{ |
5615 |
19 Apr 11 |
nicklas |
846 |
if (about == null) about = new AboutBean(); |
5615 |
19 Apr 11 |
nicklas |
847 |
about.copy(globalAbout, false); |
5610 |
15 Apr 11 |
nicklas |
848 |
} |
5615 |
19 Apr 11 |
nicklas |
849 |
|
5615 |
19 Apr 11 |
nicklas |
850 |
if (!verifyBaseVersion(about, false)) |
5615 |
19 Apr 11 |
nicklas |
851 |
{ |
5615 |
19 Apr 11 |
nicklas |
852 |
String min = about.getMinBaseVersion(); |
5615 |
19 Apr 11 |
nicklas |
853 |
String max = about.getMaxBaseVersion(); |
5615 |
19 Apr 11 |
nicklas |
854 |
log.info("Plug-in definition '" + id + "' require BASE version between " + |
5615 |
19 Apr 11 |
nicklas |
855 |
(min == null ? "*" : min) + " and " + (max == null ? "*" : max) |
5615 |
19 Apr 11 |
nicklas |
856 |
); |
5615 |
19 Apr 11 |
nicklas |
857 |
} |
5615 |
19 Apr 11 |
nicklas |
858 |
else |
5615 |
19 Apr 11 |
nicklas |
859 |
{ |
5616 |
27 Apr 11 |
nicklas |
// <plugin-class> |
5616 |
27 Apr 11 |
nicklas |
861 |
String className = Values.getStringOrNull(pdTag.getChildText("plugin-class", ns)); |
5616 |
27 Apr 11 |
nicklas |
862 |
|
5616 |
27 Apr 11 |
nicklas |
863 |
PluginInfo info = new PluginInfo(id); |
5616 |
27 Apr 11 |
nicklas |
864 |
info.setAbout(about); |
5616 |
27 Apr 11 |
nicklas |
865 |
info.setClassName(className); |
5616 |
27 Apr 11 |
nicklas |
866 |
|
5616 |
27 Apr 11 |
nicklas |
867 |
temp.add(info); |
5616 |
27 Apr 11 |
nicklas |
868 |
|
5616 |
27 Apr 11 |
nicklas |
// <settings> |
5616 |
27 Apr 11 |
nicklas |
870 |
Element settingsTag = pdTag.getChild("settings", ns); |
5616 |
27 Apr 11 |
nicklas |
871 |
if (settingsTag != null) |
5615 |
19 Apr 11 |
nicklas |
872 |
{ |
6473 |
11 Jun 14 |
nicklas |
873 |
for (Element propertyTag : settingsTag.getChildren("property", ns)) |
5616 |
27 Apr 11 |
nicklas |
874 |
{ |
5616 |
27 Apr 11 |
nicklas |
875 |
String name = propertyTag.getAttributeValue("name"); |
5616 |
27 Apr 11 |
nicklas |
876 |
String value = Values.getStringOrNull(propertyTag.getText()); |
5616 |
27 Apr 11 |
nicklas |
877 |
info.setProperty(name, value); |
5616 |
27 Apr 11 |
nicklas |
878 |
} |
5615 |
19 Apr 11 |
nicklas |
879 |
} |
5615 |
19 Apr 11 |
nicklas |
880 |
} |
5610 |
15 Apr 11 |
nicklas |
881 |
} |
5610 |
15 Apr 11 |
nicklas |
882 |
} |
5610 |
15 Apr 11 |
nicklas |
883 |
pluginDefinitions.addAll(temp); |
5610 |
15 Apr 11 |
nicklas |
884 |
return numLoaded; |
5610 |
15 Apr 11 |
nicklas |
885 |
} |
5610 |
15 Apr 11 |
nicklas |
886 |
|
5610 |
15 Apr 11 |
nicklas |
887 |
|
5610 |
15 Apr 11 |
nicklas |
888 |
/** |
4163 |
28 Feb 08 |
nicklas |
Create a new factory instance. The factory must be a class |
4163 |
28 Feb 08 |
nicklas |
with a public, no-argument constructor. The factory class name |
4163 |
28 Feb 08 |
nicklas |
is read from the <factory-class> tag and initialisation |
4163 |
28 Feb 08 |
nicklas |
parameters from the <parameters> tag. |
4163 |
28 Feb 08 |
nicklas |
893 |
|
4163 |
28 Feb 08 |
nicklas |
@param factoryTag The root tag of the factory definition |
4163 |
28 Feb 08 |
nicklas |
@param classLoader The classloader to use, or null to use |
4163 |
28 Feb 08 |
nicklas |
the BASE core classloader |
4163 |
28 Feb 08 |
nicklas |
@param factoryType Class type of the factory. The named class |
4163 |
28 Feb 08 |
nicklas |
must implement or be a subclass of this class |
4163 |
28 Feb 08 |
nicklas |
@return An initialised factory |
4163 |
28 Feb 08 |
nicklas |
900 |
*/ |
6627 |
25 Nov 14 |
nicklas |
901 |
protected <F> F createFactory(Element factoryTag, ClassLoader classLoader, Class<F> factoryType, Preset config) |
4163 |
28 Feb 08 |
nicklas |
902 |
throws ClassNotFoundException, NoSuchMethodException, |
7513 |
02 Nov 18 |
nicklas |
903 |
IllegalAccessException, InstantiationException, InvocationTargetException |
4163 |
28 Feb 08 |
nicklas |
904 |
{ |
4163 |
28 Feb 08 |
nicklas |
905 |
Namespace ns = factoryTag.getNamespace(); |
4163 |
28 Feb 08 |
nicklas |
906 |
String factoryClassName = Values.getStringOrNull(factoryTag.getChildText("factory-class", ns)); |
6875 |
20 Apr 15 |
nicklas |
907 |
Class<?> factoryClass = |
4163 |
28 Feb 08 |
nicklas |
908 |
ClassUtil.checkAndLoadClass(classLoader, factoryClassName, true, factoryType); |
7513 |
02 Nov 18 |
nicklas |
909 |
F factory = factoryType.cast(factoryClass.getDeclaredConstructor().newInstance()); |
6627 |
25 Nov 14 |
nicklas |
910 |
initBeanWithReflection(factory, factoryTag.getChild("parameters", ns), config); |
4163 |
28 Feb 08 |
nicklas |
911 |
return factory; |
4163 |
28 Feb 08 |
nicklas |
912 |
} |
4163 |
28 Feb 08 |
nicklas |
913 |
|
4163 |
28 Feb 08 |
nicklas |
914 |
/** |
4163 |
28 Feb 08 |
nicklas |
Initialise a bean using reflection. For each child tag |
4163 |
28 Feb 08 |
nicklas |
of the 'root' element, this method will check if the |
4163 |
28 Feb 08 |
nicklas |
bean implements a setter method that is compatible with the |
4163 |
28 Feb 08 |
nicklas |
child tag name. The method name should start with 'set' and |
4163 |
28 Feb 08 |
nicklas |
then the tag name with the first letter capitalized. The method |
4163 |
28 Feb 08 |
nicklas |
must take a single String argument. For example, if there is |
4163 |
28 Feb 08 |
nicklas |
a child tag <code><image>button.png</image></code> this will |
4163 |
28 Feb 08 |
nicklas |
be converted to the method call: <code>setImage("button.png")</code>. |
4163 |
28 Feb 08 |
nicklas |
<p> |
4163 |
28 Feb 08 |
nicklas |
Tags that has no matching public setter method are ignored. |
4163 |
28 Feb 08 |
nicklas |
925 |
|
4163 |
28 Feb 08 |
nicklas |
@param bean The bean to initialize |
4163 |
28 Feb 08 |
nicklas |
@param root The root element, if null nothing is done |
4163 |
28 Feb 08 |
nicklas |
928 |
*/ |
6627 |
25 Nov 14 |
nicklas |
929 |
protected void initBeanWithReflection(Object bean, Element root, Preset config) |
4163 |
28 Feb 08 |
nicklas |
930 |
{ |
4163 |
28 Feb 08 |
nicklas |
931 |
if (root == null) return; |
4163 |
28 Feb 08 |
nicklas |
932 |
Class<?> beanClass = bean.getClass(); |
4198 |
28 Mar 08 |
nicklas |
933 |
|
6473 |
11 Jun 14 |
nicklas |
934 |
List<Element> parameters = root.getChildren(); |
4198 |
28 Mar 08 |
nicklas |
935 |
factoryParameters.put(bean, xmlOut.outputString(root)); |
4198 |
28 Mar 08 |
nicklas |
936 |
|
4207 |
04 Apr 08 |
nicklas |
// Check for generic setParameter(String, String) method |
4207 |
04 Apr 08 |
nicklas |
938 |
Method setParameter = getSetParameterMethod(beanClass); |
4207 |
04 Apr 08 |
nicklas |
939 |
|
4198 |
28 Mar 08 |
nicklas |
// List all child tags |
4198 |
28 Mar 08 |
nicklas |
941 |
for (Element child : parameters) |
4163 |
28 Feb 08 |
nicklas |
942 |
{ |
4198 |
28 Mar 08 |
nicklas |
// childName is the name of the setter method --> set<ChildName> |
4163 |
28 Feb 08 |
nicklas |
944 |
String childName = child.getName(); |
4198 |
28 Mar 08 |
nicklas |
945 |
|
4198 |
28 Mar 08 |
nicklas |
// The value passed as an argument to the setter method |
6627 |
25 Nov 14 |
nicklas |
947 |
String value = config != null ? Values.getStringOrNull(config.getSetting(childName)) : null; |
6627 |
25 Nov 14 |
nicklas |
948 |
if (value == null) |
6627 |
25 Nov 14 |
nicklas |
949 |
{ |
6627 |
25 Nov 14 |
nicklas |
950 |
value = Values.getStringOrNull(child.getText()); |
6627 |
25 Nov 14 |
nicklas |
951 |
} |
5014 |
25 Jun 09 |
martin |
952 |
|
5014 |
25 Jun 09 |
martin |
953 |
if (value == null) |
5014 |
25 Jun 09 |
martin |
954 |
{ |
5014 |
25 Jun 09 |
martin |
/* #### CONTINUE-STATEMENT #### */ |
5014 |
25 Jun 09 |
martin |
956 |
continue; |
5014 |
25 Jun 09 |
martin |
957 |
} |
4198 |
28 Mar 08 |
nicklas |
958 |
|
6219 |
08 Jan 13 |
nicklas |
959 |
Method setter = getSetterMethod(beanClass, childName); |
6219 |
08 Jan 13 |
nicklas |
960 |
if (setter != null) |
4207 |
04 Apr 08 |
nicklas |
961 |
{ |
6219 |
08 Jan 13 |
nicklas |
// Specific setter method was found |
6219 |
08 Jan 13 |
nicklas |
// Convert the input value |
6219 |
08 Jan 13 |
nicklas |
964 |
String converted = getConvertedValue(value, setter); |
6219 |
08 Jan 13 |
nicklas |
965 |
|
6219 |
08 Jan 13 |
nicklas |
// Invoke the setter method -- ignore all errors |
6219 |
08 Jan 13 |
nicklas |
967 |
try |
6219 |
08 Jan 13 |
nicklas |
968 |
{ |
6219 |
08 Jan 13 |
nicklas |
969 |
setter.invoke(bean, converted); |
6219 |
08 Jan 13 |
nicklas |
970 |
} |
6219 |
08 Jan 13 |
nicklas |
971 |
catch (IllegalAccessException ex) |
6219 |
08 Jan 13 |
nicklas |
972 |
{} |
6219 |
08 Jan 13 |
nicklas |
973 |
catch (InvocationTargetException ex) |
6219 |
08 Jan 13 |
nicklas |
974 |
{} |
6219 |
08 Jan 13 |
nicklas |
975 |
} |
6219 |
08 Jan 13 |
nicklas |
976 |
else if (setParameter != null) |
6219 |
08 Jan 13 |
nicklas |
977 |
{ |
6219 |
08 Jan 13 |
nicklas |
// Call generic setParameter(String, String) method |
4208 |
07 Apr 08 |
nicklas |
979 |
String converted = getConvertedValue(value, setParameter); |
4207 |
04 Apr 08 |
nicklas |
980 |
try |
4207 |
04 Apr 08 |
nicklas |
981 |
{ |
4208 |
07 Apr 08 |
nicklas |
982 |
setParameter.invoke(bean, childName, converted); |
4207 |
04 Apr 08 |
nicklas |
983 |
} |
4207 |
04 Apr 08 |
nicklas |
984 |
catch (IllegalAccessException ex) |
4207 |
04 Apr 08 |
nicklas |
985 |
{} |
4207 |
04 Apr 08 |
nicklas |
986 |
catch (InvocationTargetException ex) |
4207 |
04 Apr 08 |
nicklas |
987 |
{} |
4207 |
04 Apr 08 |
nicklas |
988 |
} |
4163 |
28 Feb 08 |
nicklas |
989 |
} |
4163 |
28 Feb 08 |
nicklas |
990 |
} |
4163 |
28 Feb 08 |
nicklas |
991 |
|
4198 |
28 Mar 08 |
nicklas |
992 |
/** |
4198 |
28 Mar 08 |
nicklas |
Get the setter method for a given tag name. |
4198 |
28 Mar 08 |
nicklas |
@param beanClass The class to look for the setter method in |
4198 |
28 Mar 08 |
nicklas |
@param tagName The tag name in the XML file |
4207 |
04 Apr 08 |
nicklas |
@return A Method object, or null if no method is found |
4198 |
28 Mar 08 |
nicklas |
997 |
*/ |
4198 |
28 Mar 08 |
nicklas |
998 |
protected Method getSetterMethod(Class<?> beanClass, String tagName) |
4198 |
28 Mar 08 |
nicklas |
999 |
{ |
4198 |
28 Mar 08 |
nicklas |
1000 |
String methodName = getSetterMethodNameFromTag(tagName); |
4198 |
28 Mar 08 |
nicklas |
1001 |
Method setter = null; |
4198 |
28 Mar 08 |
nicklas |
1002 |
try |
4198 |
28 Mar 08 |
nicklas |
1003 |
{ |
4198 |
28 Mar 08 |
nicklas |
1004 |
setter = beanClass.getMethod(methodName, String.class); |
4198 |
28 Mar 08 |
nicklas |
1005 |
} |
4198 |
28 Mar 08 |
nicklas |
1006 |
catch (NoSuchMethodException ex) |
4198 |
28 Mar 08 |
nicklas |
1007 |
{} |
4198 |
28 Mar 08 |
nicklas |
1008 |
return setter; |
4198 |
28 Mar 08 |
nicklas |
1009 |
} |
4198 |
28 Mar 08 |
nicklas |
1010 |
|
4198 |
28 Mar 08 |
nicklas |
1011 |
/** |
4207 |
04 Apr 08 |
nicklas |
Check if the bean class has a <code>setParameter(String, String)</code> |
4207 |
04 Apr 08 |
nicklas |
method and return it's reference if it has. |
4207 |
04 Apr 08 |
nicklas |
@param beanClass The class to look for the method in |
4207 |
04 Apr 08 |
nicklas |
@return A Method object, or null if no method is found |
4207 |
04 Apr 08 |
nicklas |
1016 |
*/ |
4207 |
04 Apr 08 |
nicklas |
1017 |
protected Method getSetParameterMethod(Class<?> beanClass) |
4207 |
04 Apr 08 |
nicklas |
1018 |
{ |
4207 |
04 Apr 08 |
nicklas |
1019 |
Method setParameter = null; |
4207 |
04 Apr 08 |
nicklas |
1020 |
try |
4207 |
04 Apr 08 |
nicklas |
1021 |
{ |
4207 |
04 Apr 08 |
nicklas |
1022 |
setParameter = beanClass.getMethod("setParameter", String.class, String.class); |
4207 |
04 Apr 08 |
nicklas |
1023 |
} |
4207 |
04 Apr 08 |
nicklas |
1024 |
catch (NoSuchMethodException ex) |
4207 |
04 Apr 08 |
nicklas |
1025 |
{} |
4207 |
04 Apr 08 |
nicklas |
1026 |
return setParameter; |
4207 |
04 Apr 08 |
nicklas |
1027 |
|
4207 |
04 Apr 08 |
nicklas |
1028 |
} |
4207 |
04 Apr 08 |
nicklas |
1029 |
|
4207 |
04 Apr 08 |
nicklas |
1030 |
/** |
6219 |
08 Jan 13 |
nicklas |
Convert the tag name to a setter method name. The tag name is prefixed with |
6219 |
08 Jan 13 |
nicklas |
'set', the first letter is capitalized, hyphens in the tag name are removed and |
6219 |
08 Jan 13 |
nicklas |
the first letter after each is capitalized. |
4198 |
28 Mar 08 |
nicklas |
@param tagName The tag name |
6219 |
08 Jan 13 |
nicklas |
@return The converted tag name |
4198 |
28 Mar 08 |
nicklas |
1036 |
*/ |
4198 |
28 Mar 08 |
nicklas |
1037 |
protected String getSetterMethodNameFromTag(String tagName) |
4198 |
28 Mar 08 |
nicklas |
1038 |
{ |
6219 |
08 Jan 13 |
nicklas |
1039 |
String[] parts = tagName.split("\\-"); |
6219 |
08 Jan 13 |
nicklas |
1040 |
StringBuilder setterName = new StringBuilder(tagName.length()+3); |
6219 |
08 Jan 13 |
nicklas |
1041 |
setterName.append("set"); |
6219 |
08 Jan 13 |
nicklas |
1042 |
for (String part : parts) |
6219 |
08 Jan 13 |
nicklas |
1043 |
{ |
6219 |
08 Jan 13 |
nicklas |
1044 |
setterName.append(part.substring(0, 1).toUpperCase()); |
6219 |
08 Jan 13 |
nicklas |
1045 |
setterName.append(part.substring(1)); |
6219 |
08 Jan 13 |
nicklas |
1046 |
} |
6219 |
08 Jan 13 |
nicklas |
1047 |
return setterName.toString(); |
4198 |
28 Mar 08 |
nicklas |
1048 |
} |
4170 |
07 Mar 08 |
nicklas |
1049 |
|
4208 |
07 Apr 08 |
nicklas |
1050 |
protected String getConvertedValue(String original, Method method) |
4208 |
07 Apr 08 |
nicklas |
1051 |
{ |
4208 |
07 Apr 08 |
nicklas |
1052 |
String converted = original; |
4208 |
07 Apr 08 |
nicklas |
1053 |
if (converters != null) |
4208 |
07 Apr 08 |
nicklas |
1054 |
{ |
4208 |
07 Apr 08 |
nicklas |
1055 |
for (ValueConverter converter : converters) |
4208 |
07 Apr 08 |
nicklas |
1056 |
{ |
4208 |
07 Apr 08 |
nicklas |
1057 |
converted = converter.convert(converted, method); |
4208 |
07 Apr 08 |
nicklas |
1058 |
} |
4208 |
07 Apr 08 |
nicklas |
1059 |
} |
4208 |
07 Apr 08 |
nicklas |
1060 |
return converted; |
4208 |
07 Apr 08 |
nicklas |
1061 |
} |
4208 |
07 Apr 08 |
nicklas |
1062 |
|
4163 |
28 Feb 08 |
nicklas |
1063 |
} |