@@ -113,7 +113,7 @@ def register(hooks, settings)
113113
114114 attr_reader :hooks
115115
116- def initialize
116+ def initialize ( alias_registry = nil )
117117 @mutex = Mutex . new
118118 # We need a threadsafe class here because we may perform
119119 # get/set operations concurrently despite the fact we don't use
@@ -123,6 +123,7 @@ def initialize
123123 @registry = java . util . concurrent . ConcurrentHashMap . new
124124 @java_plugins = java . util . concurrent . ConcurrentHashMap . new
125125 @hooks = HooksRegistry . new
126+ @alias_registry = alias_registry || Java ::org . logstash . plugins . AliasRegistry . new
126127 end
127128
128129 def setup!
@@ -196,41 +197,47 @@ def lookup(type, plugin_name, &block)
196197 # a plugin and will do a lookup on the namespace of the required class to find a matching
197198 # plugin with the appropriate type.
198199 def legacy_lookup ( type , plugin_name )
199- begin
200- path = "logstash/#{ type } s/#{ plugin_name } "
200+ klass = load_plugin_class ( type , plugin_name )
201201
202- klass = begin
203- namespace_lookup ( type , plugin_name )
204- rescue UnknownPlugin => e
205- # Plugin not registered. Try to load it.
206- begin
207- require path
208- namespace_lookup ( type , plugin_name )
209- rescue LoadError => e
210- logger . error ( "Tried to load a plugin's code, but failed." , :exception => e , :path => path , :type => type , :name => plugin_name )
211- raise
212- end
213- end
202+ if !klass && @alias_registry . alias? ( type . to_java , plugin_name )
203+ resolved_plugin_name = @alias_registry . original_from_alias ( type . to_java , plugin_name )
204+ logger . debug ( "Loading #{ type } plugin #{ resolved_plugin_name } via its alias #{ plugin_name } ..." )
205+ klass = load_plugin_class ( type , resolved_plugin_name )
206+ lazy_add ( type , resolved_plugin_name , klass ) if klass
207+ end
214208
215- plugin = lazy_add ( type , plugin_name , klass )
216- rescue => e
217- logger . error ( "Problems loading a plugin with" ,
218- :type => type ,
219- :name => plugin_name ,
220- :path => path ,
221- :error_message => e . message ,
222- :error_class => e . class ,
223- :error_backtrace => e . backtrace )
224-
225- raise LoadError , "Problems loading the requested plugin named #{ plugin_name } of type #{ type } . Error: #{ e . class } #{ e . message } "
209+ unless klass
210+ logger . error ( "Unable to load plugin." , :type => type , :name => plugin_name )
211+ raise LoadError , "Unable to load the requested plugin named #{ plugin_name } of type #{ type } . The plugin is not installed."
226212 end
227213
228- plugin
214+ lazy_add ( type , plugin_name , klass )
215+ end
216+
217+ # load a plugin's class, or return nil if the plugin cannot be loaded.
218+ # attempts to load the class purely through namespace lookup,
219+ # and falls back to requiring the path of the expected plugin.
220+ # @param type [String]: plugin type, such as "input", "output", "filter", "codec"
221+ # @param plugin_name [String]: plugin name, such as "grok", "elasticsearch"
222+ # @return [Class,nil] the plugin class, or nil
223+ private
224+ def load_plugin_class ( type , plugin_name )
225+ klass = namespace_lookup ( type , plugin_name )
226+
227+ unless klass
228+ require ( "logstash/#{ type } s/#{ plugin_name } " )
229+ klass = namespace_lookup ( type , plugin_name )
230+ end
231+ klass
232+ rescue LoadError => e
233+ logger . debug ( "Tried to load a plugin's code, but failed." , :exception => e , :path => e . path , :type => type , :name => plugin_name )
234+ nil
229235 end
230236
237+ public
231238 def lookup_pipeline_plugin ( type , name )
232239 LogStash ::PLUGIN_REGISTRY . lookup ( type , name ) do |plugin_klass , plugin_name |
233- is_a_plugin ?( plugin_klass , plugin_name )
240+ is_a_plugin_or_alias ?( plugin_klass , type . to_java , plugin_name )
234241 end
235242 rescue LoadError , NameError => e
236243 logger . debug ( "Problems loading the plugin with" , :type => type , :name => name )
@@ -268,19 +275,15 @@ def size
268275 # ex.: namespace_lookup("filter", "grok") looks for LogStash::Filters::Grok
269276 # @param type [String] plugin type, "input", "output", "filter"
270277 # @param name [String] plugin name, ex.: "grok"
271- # @return [Class] the plugin class or raises NameError
272- # @raise NameError if plugin class does not exist or is invalid
278+ # @return [Class,nil] the plugin class or nil
273279 def namespace_lookup ( type , name )
274280 type_const = "#{ type . capitalize } s"
275281 namespace = LogStash . const_get ( type_const )
276282 # the namespace can contain constants which are not for plugins classes (do not respond to :config_name)
277283 # namespace.constants is the shallow collection of all constants symbols in namespace
278284 # note that below namespace.const_get(c) should never result in a NameError since c is from the constants collection
279285 klass_sym = namespace . constants . find { |c | is_a_plugin? ( namespace . const_get ( c ) , name ) }
280- klass = klass_sym && namespace . const_get ( klass_sym )
281-
282- raise ( UnknownPlugin ) unless klass
283- klass
286+ klass_sym && namespace . const_get ( klass_sym )
284287 end
285288
286289 # check if klass is a valid plugin for name
@@ -290,7 +293,19 @@ def namespace_lookup(type, name)
290293 def is_a_plugin? ( klass , name )
291294 ( klass . class == Java ::JavaLang ::Class && klass . simple_name . downcase == name . gsub ( '_' , '' ) ) ||
292295 ( klass . class == Java ::JavaClass && klass . simple_name . downcase == name . gsub ( '_' , '' ) ) ||
293- ( klass . ancestors . include? ( LogStash ::Plugin ) && klass . respond_to? ( :config_name ) && klass . config_name == name )
296+ ( klass . ancestors . include? ( LogStash ::Plugin ) && klass . respond_to? ( :config_name ) &&
297+ klass . config_name == name )
298+ end
299+
300+ # check if klass is a valid plugin for name,
301+ # including alias resolution
302+ def is_a_plugin_or_alias? ( klass , type , plugin_name )
303+ return true if is_a_plugin? ( klass , plugin_name )
304+
305+ resolved_plugin_name = @alias_registry . resolve_alias ( type , plugin_name )
306+ return true if is_a_plugin? ( klass , resolved_plugin_name )
307+
308+ false
294309 end
295310
296311 def add_plugin ( type , name , klass )
0 commit comments