| 
									
										
										
										
											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-06-10 07:54:22 +08:00
										 |  |  | defmodule RabbitMQ.CLI.Ctl.CommandModules do | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |   def module_map do | 
					
						
							|  |  |  |     case Application.get_env(:rabbitmqctl, :commands) do | 
					
						
							|  |  |  |       nil -> load; | 
					
						
							|  |  |  |       val -> val | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def load do | 
					
						
							|  |  |  |     scope = script_scope | 
					
						
							|  |  |  |     commands = load_commands(scope) | 
					
						
							|  |  |  |     Application.put_env(:rabbitmqctl, :commands, commands) | 
					
						
							|  |  |  |     commands | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def script_scope do | 
					
						
							|  |  |  |     scopes = Application.get_env(:rabbitmqctl, :scopes, []) | 
					
						
							|  |  |  |     scopes[script_name] || :all | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 18:49:50 +08:00
										 |  |  |   def script_name do | 
					
						
							|  |  |  |     Path.basename(:escript.script_name()) |> String.to_atom | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |   defp load_commands(scope) do | 
					
						
							|  |  |  |     modules = loadable_modules() | 
					
						
							|  |  |  |     modules | 
					
						
							|  |  |  |     |> Enum.filter(fn(path) -> | 
					
						
							| 
									
										
										
										
											2016-06-17 18:49:50 +08:00
										 |  |  |                      to_string(path) =~ ~r/RabbitMQ.CLI.*.Commands/ | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |                    end) | 
					
						
							|  |  |  |     |> Enum.map(fn(path) -> | 
					
						
							|  |  |  |                   Path.rootname(path, '.beam') | 
					
						
							|  |  |  |                   |> String.to_atom | 
					
						
							|  |  |  |                   |> Code.ensure_loaded | 
					
						
							|  |  |  |                 end) | 
					
						
							|  |  |  |     |> Enum.filter_map(fn({res, _}) -> res == :module end, | 
					
						
							|  |  |  |                        fn({_, mod}) -> command_tuple(mod) end) | 
					
						
							| 
									
										
										
										
											2016-06-16 23:29:06 +08:00
										 |  |  |     |> Enum.filter(fn({_, cmd}) -> command_in_scope(cmd, scope) end) | 
					
						
							| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  |     |> Map.new | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |   defp loadable_modules do | 
					
						
							|  |  |  |     :code.get_path() | 
					
						
							|  |  |  |     |> Enum.flat_map(fn(path) -> | 
					
						
							|  |  |  |          {:ok, modules} = :erl_prim_loader.list_dir(path) | 
					
						
							|  |  |  |          modules | 
					
						
							|  |  |  |        end) | 
					
						
							| 
									
										
										
										
											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-16 23:29:06 +08:00
										 |  |  |   defp command_in_scope(_cmd, :all) do | 
					
						
							|  |  |  |     true | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   defp command_in_scope(cmd, scope) do | 
					
						
							| 
									
										
										
										
											2016-06-17 17:49:38 +08:00
										 |  |  |     Code.ensure_loaded(cmd) | 
					
						
							| 
									
										
										
										
											2016-06-16 23:29:06 +08:00
										 |  |  |     if :erlang.function_exported(cmd, :scopes, 0) do | 
					
						
							|  |  |  |       Enum.member?(cmd.scopes(), scope) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-03-05 01:42:43 +08:00
										 |  |  | end |