| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  | ## The contents of this file are subject to the Mozilla Public License | 
					
						
							|  |  |  | ## Version 1.1 (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.mozilla.org/MPL/ | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## Software distributed under the License is distributed on an "AS IS" | 
					
						
							|  |  |  | ## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See | 
					
						
							|  |  |  | ## the License for the specific language governing rights and | 
					
						
							|  |  |  | ## limitations under the License. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## The Original Code is RabbitMQ. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## The Initial Developer of the Original Code is GoPivotal, Inc. | 
					
						
							|  |  |  | ## Copyright (c) 2007-2016 Pivotal Software, Inc.  All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-31 19:21:10 +08:00
										 |  |  | alias RabbitMQ.CLI.Config, as: Config | 
					
						
							| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-10 07:54:22 +08:00
										 |  |  | defmodule RabbitMQ.CLI.Ctl.CommandModules do | 
					
						
							| 
									
										
										
										
											2016-06-20 23:52:36 +08:00
										 |  |  |   @commands_ns ~r/RabbitMQ.CLI.(.*).Commands/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |   def module_map do | 
					
						
							| 
									
										
										
										
											2016-10-31 19:21:10 +08:00
										 |  |  |     Application.get_env(:rabbitmqctl, :commands) || load(%{}) | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-31 19:21:10 +08:00
										 |  |  |   def load(opts) do | 
					
						
							|  |  |  |     scope = script_scope(opts) | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |     commands = load_commands(scope) | 
					
						
							|  |  |  |     Application.put_env(:rabbitmqctl, :commands, commands) | 
					
						
							|  |  |  |     commands | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-31 19:21:10 +08:00
										 |  |  |   def script_scope(opts) do | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |     scopes = Application.get_env(:rabbitmqctl, :scopes, []) | 
					
						
							| 
									
										
										
										
											2016-10-31 19:21:10 +08:00
										 |  |  |     scopes[Config.get_option(:script_name, opts)] || :none | 
					
						
							| 
									
										
										
										
											2016-06-17 18:49:50 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-23 19:33:39 +08:00
										 |  |  |   def load_commands(scope) do | 
					
						
							| 
									
										
										
										
											2016-06-20 23:52:36 +08:00
										 |  |  |     ctl_and_plugin_modules | 
					
						
							|  |  |  |     |> Enum.filter(fn(mod) -> | 
					
						
							|  |  |  |                      to_string(mod) =~ @commands_ns | 
					
						
							|  |  |  |                      and | 
					
						
							| 
									
										
										
										
											2016-06-23 19:33:39 +08:00
										 |  |  |                      module_exists?(mod) | 
					
						
							|  |  |  |                      and | 
					
						
							| 
									
										
										
										
											2016-06-20 23:52:36 +08:00
										 |  |  |                      implements_command_behaviour?(mod) | 
					
						
							|  |  |  |                      and | 
					
						
							|  |  |  |                      command_in_scope(mod, scope) | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |                    end) | 
					
						
							| 
									
										
										
										
											2016-06-20 23:52:36 +08:00
										 |  |  |     |> Enum.map(&command_tuple/1) | 
					
						
							| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  |     |> Map.new | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-20 23:52:36 +08:00
										 |  |  |   defp ctl_and_plugin_modules do | 
					
						
							|  |  |  |     # No plugins so far | 
					
						
							|  |  |  |     applications = [:rabbitmqctl] | 
					
						
							|  |  |  |     applications | 
					
						
							|  |  |  |     |> Enum.flat_map(fn(app) -> Application.spec(app, :modules) end) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-23 19:33:39 +08:00
										 |  |  |   defp module_exists?(nil) do | 
					
						
							|  |  |  |     false | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   defp module_exists?(mod) do | 
					
						
							|  |  |  |     Code.ensure_loaded?(mod) | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-06-20 23:52:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   defp implements_command_behaviour?(nil) do | 
					
						
							|  |  |  |     false | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   defp implements_command_behaviour?(module) do | 
					
						
							|  |  |  |     Enum.member?(module.module_info(:attributes)[:behaviour] || [], | 
					
						
							|  |  |  |                  RabbitMQ.CLI.CommandBehaviour) | 
					
						
							| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |   defp command_tuple(cmd) do | 
					
						
							| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |       cmd | 
					
						
							|  |  |  |       |> to_string | 
					
						
							|  |  |  |       |> strip_namespace | 
					
						
							|  |  |  |       |> to_snake_case | 
					
						
							|  |  |  |       |> String.replace_suffix("_command", ""), | 
					
						
							|  |  |  |       cmd | 
					
						
							| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-06-16 23:29:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |   def strip_namespace(str) do | 
					
						
							|  |  |  |     str | 
					
						
							|  |  |  |     |> String.split(".") | 
					
						
							|  |  |  |     |> List.last | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def to_snake_case(<<c, str :: binary>>) do | 
					
						
							|  |  |  |     tail = for <<c <- str>>, into: "", do: snake(c) | 
					
						
							|  |  |  |     <<to_lower_char(c), tail :: binary >> | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   defp snake(c) do | 
					
						
							|  |  |  |     if (c >= ?A) and (c <= ?Z) do | 
					
						
							|  |  |  |       <<"_", c+32>> | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       <<c>> | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   defp to_lower_char(c) do | 
					
						
							|  |  |  |     if (c >= ?A) and (c <= ?Z) do | 
					
						
							|  |  |  |       c+32 | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       c | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 20:07:47 +08:00
										 |  |  |   defp command_in_scope(_cmd, :none) do | 
					
						
							| 
									
										
										
										
											2016-06-23 01:00:21 +08:00
										 |  |  |     case Mix.env do | 
					
						
							|  |  |  |       :test -> true; | 
					
						
							|  |  |  |       _     -> false | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-06-16 23:29:06 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-06-23 19:33:39 +08:00
										 |  |  |   defp command_in_scope(_cmd, :all) do | 
					
						
							|  |  |  |     true | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-06-16 23:29:06 +08:00
										 |  |  |   defp command_in_scope(cmd, scope) do | 
					
						
							| 
									
										
										
										
											2016-06-20 23:52:36 +08:00
										 |  |  |     Enum.member?(command_scopes(cmd), scope) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   defp command_scopes(cmd) do | 
					
						
							|  |  |  |     case :erlang.function_exported(cmd, :scopes, 0) do | 
					
						
							|  |  |  |       true  -> | 
					
						
							|  |  |  |         cmd.scopes() | 
					
						
							|  |  |  |       false -> | 
					
						
							|  |  |  |         @commands_ns | 
					
						
							|  |  |  |         |> Regex.run(to_string(cmd), capture: :all_but_first) | 
					
						
							|  |  |  |         |> List.first | 
					
						
							|  |  |  |         |> to_snake_case | 
					
						
							|  |  |  |         |> String.to_atom | 
					
						
							|  |  |  |         |> List.wrap | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-06-16 23:29:06 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  | end |