1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.nutch.plugin;
18
19 import java.util.HashMap;
20
21 import org.apache.hadoop.conf.Configuration;
22 import org.apache.hadoop.conf.Configurable;
23
24 /**
25 * An <code>Extension</code> is a kind of listener descriptor that will be
26 * installed on a concrete <code>ExtensionPoint</code> that acts as kind of
27 * Publisher.
28 *
29 * @author joa23
30 */
31 public class Extension {
32 private PluginDescriptor fDescriptor;
33 private String fId;
34 private String fTargetPoint;
35 private String fClazz;
36 private HashMap<String, String> fAttributes;
37 private Configuration conf;
38 private PluginRepository pluginRepository;
39
40 /**
41 * @param pDescriptor
42 * a plugin descriptor
43 * @param pExtensionPoint
44 * an extension porin
45 * @param pId
46 * an unique id of the plugin
47 */
48 public Extension(PluginDescriptor pDescriptor, String pExtensionPoint,
49 String pId, String pExtensionClass, Configuration conf,
50 PluginRepository pluginRepository) {
51 fAttributes = new HashMap<String, String>();
52 setDescriptor(pDescriptor);
53 setExtensionPoint(pExtensionPoint);
54 setId(pId);
55 setClazz(pExtensionClass);
56 this.conf = conf;
57 this.pluginRepository = pluginRepository;
58 }
59
60 /**
61 * @param point
62 */
63 private void setExtensionPoint(String point) {
64 fTargetPoint = point;
65 }
66
67 /**
68 * Returns a attribute value, that is setuped in the manifest file and is
69 * definied by the extension point xml schema.
70 *
71 * @param pKey
72 * a key
73 * @return String a value
74 */
75 public String getAttribute(String pKey) {
76 return fAttributes.get(pKey);
77 }
78
79 /**
80 * Returns the full class name of the extension point implementation
81 *
82 * @return String
83 */
84 public String getClazz() {
85 return fClazz;
86 }
87
88 /**
89 * Return the unique id of the extension.
90 *
91 * @return String
92 */
93 public String getId() {
94 return fId;
95 }
96
97 /**
98 * Adds a attribute and is only used until model creation at plugin system
99 * start up.
100 *
101 * @param pKey a key
102 * @param pValue a value
103 */
104 public void addAttribute(String pKey, String pValue) {
105 fAttributes.put(pKey, pValue);
106 }
107
108 /**
109 * Sets the Class that implement the concret extension and is only used until
110 * model creation at system start up.
111 *
112 * @param extensionClazz The extensionClasname to set
113 */
114 public void setClazz(String extensionClazz) {
115 fClazz = extensionClazz;
116 }
117
118 /**
119 * Sets the unique extension Id and is only used until model creation at
120 * system start up.
121 *
122 * @param extensionID The extensionID to set
123 */
124 public void setId(String extensionID) {
125 fId = extensionID;
126 }
127
128 /**
129 * Returns the Id of the extension point, that is implemented by this
130 * extension.
131 */
132 public String getTargetPoint() {
133 return fTargetPoint;
134 }
135
136 /**
137 * Return an instance of the extension implementatio. Before we create a
138 * extension instance we startup the plugin if it is not already done. The
139 * plugin instance and the extension instance use the same
140 * <code>PluginClassLoader</code>. Each Plugin use its own classloader. The
141 * PluginClassLoader knows only own <i>Plugin runtime libraries </i> setuped
142 * in the plugin manifest file and exported libraries of the depenedend
143 * plugins.
144 *
145 * @return Object An instance of the extension implementation
146 */
147 public Object getExtensionInstance() throws PluginRuntimeException {
148 // Must synchronize here to make sure creation and initialization
149 // of a plugin instance and it extension instance are done by
150 // one and only one thread.
151 // The same is in PluginRepository.getPluginInstance().
152 // Suggested by Stefan Groschupf <sg@media-style.com>
153 synchronized (getId()) {
154 try {
155 PluginClassLoader loader = fDescriptor.getClassLoader();
156 Class extensionClazz = loader.loadClass(getClazz());
157 // lazy loading of Plugin in case there is no instance of the plugin
158 // already.
159 this.pluginRepository.getPluginInstance(getDescriptor());
160 Object object = extensionClazz.newInstance();
161 if (object instanceof Configurable) {
162 ((Configurable) object).setConf(this.conf);
163 }
164 return object;
165 } catch (ClassNotFoundException e) {
166 throw new PluginRuntimeException(e);
167 } catch (InstantiationException e) {
168 throw new PluginRuntimeException(e);
169 } catch (IllegalAccessException e) {
170 throw new PluginRuntimeException(e);
171 }
172 }
173 }
174
175 /**
176 * return the plugin descriptor.
177 *
178 * @return PluginDescriptor
179 */
180 public PluginDescriptor getDescriptor() {
181 return fDescriptor;
182 }
183
184 /**
185 * Sets the plugin descriptor and is only used until model creation at system
186 * start up.
187 *
188 * @param pDescriptor
189 */
190 public void setDescriptor(PluginDescriptor pDescriptor) {
191 fDescriptor = pDescriptor;
192 }
193 }