blob: be737cbbe716d4324549c042ef6ddd761f20560c [file] [log] [blame]
/*
* 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.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configurable;
/**
* An <code>Extension</code> is a kind of listener descriptor that will be
* installed on a concrete <code>ExtensionPoint</code> that acts as kind of
* Publisher.
*/
public class Extension {
private PluginDescriptor fDescriptor;
private String fId;
private String fTargetPoint;
private String fClazz;
private HashMap<String, String> fAttributes;
private Configuration conf;
/**
* @param pDescriptor
* a plugin descriptor
* @param pExtensionPoint
* an extension porin
* @param pId
* an unique id of the plugin
*/
public Extension(PluginDescriptor pDescriptor, String pExtensionPoint,
String pId, String pExtensionClass, Configuration conf,
PluginRepository pluginRepository) {
fAttributes = new HashMap<>();
setDescriptor(pDescriptor);
setExtensionPoint(pExtensionPoint);
setId(pId);
setClazz(pExtensionClass);
this.conf = conf;
}
/**
* @param point
*/
private void setExtensionPoint(String point) {
fTargetPoint = point;
}
/**
* Returns a attribute value, that is setuped in the manifest file and is
* definied by the extension point xml schema.
*
* @param pKey
* a key
* @return String a value
*/
public String getAttribute(String pKey) {
return fAttributes.get(pKey);
}
/**
* Returns the full class name of the extension point implementation
*
* @return String
*/
public String getClazz() {
return fClazz;
}
/**
* Return the unique id of the extension.
*
* @return String
*/
public String getId() {
return fId;
}
/**
* Adds a attribute and is only used until model creation at plugin system
* start up.
*
* @param pKey
* a key
* @param pValue
* a value
*/
public void addAttribute(String pKey, String pValue) {
fAttributes.put(pKey, pValue);
}
/**
* Sets the Class that implement the concret extension and is only used until
* model creation at system start up.
*
* @param extensionClazz
* The extensionClasname to set
*/
public void setClazz(String extensionClazz) {
fClazz = extensionClazz;
}
/**
* Sets the unique extension Id and is only used until model creation at
* system start up.
*
* @param extensionID
* The extensionID to set
*/
public void setId(String extensionID) {
fId = extensionID;
}
/**
* Returns the Id of the extension point, that is implemented by this
* extension.
*/
public String getTargetPoint() {
return fTargetPoint;
}
/**
* Return an instance of the extension implementatio. Before we create a
* extension instance we startup the plugin if it is not already done. The
* plugin instance and the extension instance use the same
* <code>PluginClassLoader</code>. Each Plugin use its own classloader. The
* PluginClassLoader knows only own <i>Plugin runtime libraries </i> setuped
* in the plugin manifest file and exported libraries of the depenedend
* plugins.
*
* @return Object An instance of the extension implementation
*/
public Object getExtensionInstance() throws PluginRuntimeException {
// Must synchronize here to make sure creation and initialization
// of a plugin instance and it extension instance are done by
// one and only one thread.
// The same is in PluginRepository.getPluginInstance().
// Suggested by Stefan Groschupf <sg@media-style.com>
synchronized (getId()) {
try {
PluginRepository pluginRepository = PluginRepository.get(conf);
Class<?> extensionClazz = pluginRepository.getCachedClass(fDescriptor,
getClazz());
// lazy loading of Plugin in case there is no instance of the plugin
// already.
pluginRepository.getPluginInstance(getDescriptor());
Object object = null;
try {
object = extensionClazz.getConstructor().newInstance();
} catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
if (object != null && object instanceof Configurable) {
((Configurable) object).setConf(this.conf);
}
return object;
} catch (ClassNotFoundException e) {
throw new PluginRuntimeException(e);
} catch (InstantiationException e) {
throw new PluginRuntimeException(e);
} catch (IllegalAccessException e) {
throw new PluginRuntimeException(e);
}
}
}
/**
* return the plugin descriptor.
*
* @return PluginDescriptor
*/
public PluginDescriptor getDescriptor() {
return fDescriptor;
}
/**
* Sets the plugin descriptor and is only used until model creation at system
* start up.
*
* @param pDescriptor
*/
public void setDescriptor(PluginDescriptor pDescriptor) {
fDescriptor = pDescriptor;
}
public String toString() {
return getId() + ", " + getClazz() + ", " + getTargetPoint();
}
}