| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.nutch.plugin; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.lang.invoke.MethodHandles; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.MissingResourceException; |
| import java.util.ResourceBundle; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.apache.hadoop.conf.Configuration; |
| |
| /** |
| * The <code>PluginDescriptor</code> provide access to all meta information of a |
| * nutch-plugin, as well to the internationalizable resources and the plugin own |
| * classloader. There are meta information about <code>Plugin</code>, |
| * <code>ExtensionPoint</code> and <code>Extension</code>. To provide access to |
| * the meta data of a plugin via a descriptor allow a lazy loading mechanism. |
| */ |
| public class PluginDescriptor { |
| private String fPluginPath; |
| private String fPluginClass = Plugin.class.getName(); |
| private String fPluginId; |
| private String fVersion; |
| private String fName; |
| private String fProviderName; |
| private HashMap<String, ResourceBundle> fMessages = new HashMap<>(); |
| private ArrayList<ExtensionPoint> fExtensionPoints = new ArrayList<>(); |
| private ArrayList<String> fDependencies = new ArrayList<>(); |
| private ArrayList<URL> fExportedLibs = new ArrayList<>(); |
| private ArrayList<URL> fNotExportedLibs = new ArrayList<>(); |
| private ArrayList<Extension> fExtensions = new ArrayList<>(); |
| private PluginClassLoader fClassLoader; |
| private static final Logger LOG = LoggerFactory |
| .getLogger(MethodHandles.lookup().lookupClass()); |
| private Configuration fConf; |
| |
| /** |
| * Constructor |
| * |
| * @param pId |
| * @param pVersion |
| * @param pName |
| * @param pProviderName |
| * @param pPluginclazz |
| * @param pPath |
| */ |
| public PluginDescriptor(String pId, String pVersion, String pName, |
| String pProviderName, String pPluginclazz, String pPath, |
| Configuration conf) { |
| setPath(pPath); |
| setPluginId(pId); |
| setVersion(pVersion); |
| setName(pName); |
| setProvidername(pProviderName); |
| |
| if (pPluginclazz != null) |
| setPluginClass(pPluginclazz); |
| |
| this.fConf = conf; |
| } |
| |
| /** |
| * @param pPath |
| */ |
| private void setPath(String pPath) { |
| fPluginPath = pPath; |
| } |
| |
| /** |
| * Returns the name of the plugin. |
| * |
| * @return String |
| */ |
| public String getName() { |
| return fName; |
| } |
| |
| /** |
| * @param providerName |
| */ |
| private void setProvidername(String providerName) { |
| fProviderName = providerName; |
| } |
| |
| /** |
| * @param name |
| */ |
| private void setName(String name) { |
| fName = name; |
| } |
| |
| /** |
| * @param version |
| */ |
| private void setVersion(String version) { |
| fVersion = version; |
| } |
| |
| /** |
| * Returns the fully qualified name of the class which implements the abstarct |
| * <code>Plugin</code> class. |
| * |
| * @return the name of this plug-in's runtime class or <code>null</code>. |
| */ |
| public String getPluginClass() { |
| return fPluginClass; |
| } |
| |
| /** |
| * Returns the unique identifier of the plug-in or <code>null</code>. |
| * |
| * @return String |
| */ |
| public String getPluginId() { |
| return fPluginId; |
| } |
| |
| /** |
| * Returns an array of extensions. |
| * |
| * @return Exception[] |
| */ |
| public Extension[] getExtensions() { |
| return fExtensions.toArray(new Extension[fExtensions.size()]); |
| } |
| |
| /** |
| * Adds a extension. |
| * |
| * @param pExtension |
| */ |
| public void addExtension(Extension pExtension) { |
| fExtensions.add(pExtension); |
| } |
| |
| /** |
| * Sets the pluginClass. |
| * |
| * @param pluginClass |
| * The pluginClass to set |
| */ |
| private void setPluginClass(String pluginClass) { |
| fPluginClass = pluginClass; |
| } |
| |
| /** |
| * Sets the plugin Id. |
| * |
| * @param pluginId |
| * The pluginId to set |
| */ |
| private void setPluginId(String pluginId) { |
| fPluginId = pluginId; |
| } |
| |
| /** |
| * Adds a extension point. |
| * |
| * @param extensionPoint |
| */ |
| public void addExtensionPoint(ExtensionPoint extensionPoint) { |
| fExtensionPoints.add(extensionPoint); |
| } |
| |
| /** |
| * Returns a array of extension points. |
| * |
| * @return ExtensionPoint[] |
| */ |
| public ExtensionPoint[] getExtenstionPoints() { |
| return fExtensionPoints |
| .toArray(new ExtensionPoint[fExtensionPoints.size()]); |
| } |
| |
| /** |
| * Returns a array of plugin ids. |
| * |
| * @return String[] |
| */ |
| public String[] getDependencies() { |
| return fDependencies.toArray(new String[fDependencies.size()]); |
| } |
| |
| /** |
| * Adds a dependency |
| * |
| * @param pId |
| * id of the dependent plugin |
| */ |
| public void addDependency(String pId) { |
| fDependencies.add(pId); |
| } |
| |
| /** |
| * Adds a exported library with a relative path to the plugin directory. We |
| * automatically escape characters that are illegal in URLs. It is recommended |
| * that code converts an abstract pathname into a URL by first converting it |
| * into a URI, via the toURI method, and then converting the URI into a URL |
| * via the URI.toURL method. |
| * |
| * @param pLibPath |
| */ |
| public void addExportedLibRelative(String pLibPath) |
| throws MalformedURLException { |
| URI uri = new File(getPluginPath() + File.separator + pLibPath).toURI(); |
| URL url = uri.toURL(); |
| fExportedLibs.add(url); |
| } |
| |
| /** |
| * Returns the directory path of the plugin. |
| * |
| * @return String |
| */ |
| public String getPluginPath() { |
| return fPluginPath; |
| } |
| |
| /** |
| * Returns a array exported librareis as URLs |
| * |
| * @return URL[] |
| */ |
| public URL[] getExportedLibUrls() { |
| return fExportedLibs.toArray(new URL[0]); |
| } |
| |
| /** |
| * Adds a exported library with a relative path to the plugin directory. We |
| * automatically escape characters that are illegal in URLs. It is recommended |
| * that code converts an abstract pathname into a URL by first converting it |
| * into a URI, via the toURI method, and then converting the URI into a URL |
| * via the URI.toURL method. |
| * |
| * @param pLibPath |
| */ |
| public void addNotExportedLibRelative(String pLibPath) |
| throws MalformedURLException { |
| URI uri = new File(getPluginPath() + File.separator + pLibPath).toURI(); |
| URL url = uri.toURL(); |
| fNotExportedLibs.add(url); |
| } |
| |
| /** |
| * Returns a array of libraries as URLs that are not exported by the plugin. |
| * |
| * @return URL[] |
| */ |
| public URL[] getNotExportedLibUrls() { |
| return fNotExportedLibs.toArray(new URL[fNotExportedLibs.size()]); |
| } |
| |
| /** |
| * Returns a cached classloader for a plugin. Until classloader creation all |
| * needed libraries are collected. A classloader use as first the plugins own |
| * libraries and add then all exported libraries of dependend plugins. |
| * |
| * @return PluginClassLoader the classloader for the plugin |
| */ |
| public PluginClassLoader getClassLoader() { |
| if (fClassLoader != null) |
| return fClassLoader; |
| ArrayList<URL> arrayList = new ArrayList<>(); |
| arrayList.addAll(fExportedLibs); |
| arrayList.addAll(fNotExportedLibs); |
| arrayList.addAll(getDependencyLibs()); |
| File file = new File(getPluginPath()); |
| try { |
| for (File file2 : file.listFiles()) { |
| if (file2.getAbsolutePath().endsWith("properties")) |
| arrayList.add(file2.getParentFile().toURI().toURL()); |
| } |
| } catch (MalformedURLException e) { |
| LOG.debug(getPluginId() + " " + e.toString()); |
| } |
| URL[] urls = arrayList.toArray(new URL[arrayList.size()]); |
| fClassLoader = new PluginClassLoader(urls, |
| PluginDescriptor.class.getClassLoader()); |
| return fClassLoader; |
| } |
| |
| /** |
| * @return Collection |
| */ |
| private ArrayList<URL> getDependencyLibs() { |
| ArrayList<URL> list = new ArrayList<>(); |
| collectLibs(list, this); |
| return list; |
| } |
| |
| /** |
| * @param pLibs |
| * @param pDescriptor |
| */ |
| private void collectLibs(ArrayList<URL> pLibs, PluginDescriptor pDescriptor) { |
| |
| for (String id : pDescriptor.getDependencies()) { |
| PluginDescriptor descriptor = PluginRepository.get(fConf) |
| .getPluginDescriptor(id); |
| for (URL url : descriptor.getExportedLibUrls()) { |
| pLibs.add(url); |
| } |
| collectLibs(pLibs, descriptor); |
| } |
| } |
| |
| /** |
| * Returns a I18N'd resource string. The resource bundles could be stored in |
| * root directory of a plugin in the well know i18n file name conventions. |
| * |
| * @param pKey |
| * @param pLocale |
| * @return String |
| * @throws IOException |
| */ |
| public String getResourceString(String pKey, Locale pLocale) |
| throws IOException { |
| if (fMessages.containsKey(pLocale.toString())) { |
| ResourceBundle bundle = fMessages.get(pLocale.toString()); |
| try { |
| return bundle.getString(pKey); |
| } catch (MissingResourceException e) { |
| return '!' + pKey + '!'; |
| } |
| } |
| try { |
| ResourceBundle res = ResourceBundle.getBundle("messages", pLocale, |
| getClassLoader()); |
| return res.getString(pKey); |
| } catch (MissingResourceException x) { |
| return '!' + pKey + '!'; |
| } |
| } |
| |
| public String getProviderName() { |
| return fProviderName; |
| } |
| |
| public String getVersion() { |
| return fVersion; |
| } |
| } |