1 /*
2    Copyright (c) 2001, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23    */
24 
25 #include <vector>
26 #include <iostream>
27 #include "my_getopt.h"
28 #include "abstract_options_provider.h"
29 #include "i_options_provider.h"
30 
31 using std::vector;
32 using std::string;
33 using std::map;
34 using namespace Mysql::Tools::Base::Options;
35 using Mysql::Nullable;
36 
37 
create_new_option(string name,string description)38 Simple_option* Abstract_options_provider::create_new_option(
39   string name, string description)
40 {
41   return this->attach_new_option<Simple_option>(
42     new Simple_option(name, description));
43 }
44 
create_new_disabled_option(string name,string description)45 Disabled_option* Abstract_options_provider::create_new_disabled_option(
46   string name, string description)
47 {
48   return this->attach_new_option<Disabled_option>(
49     new Disabled_option(name, description));
50 }
51 
create_new_option(char ** value,string name,string description)52 Char_array_option* Abstract_options_provider::create_new_option(
53   char** value, string name, string description)
54 {
55   return this->attach_new_option<Char_array_option>(
56     new Char_array_option(value, false, name, description));
57 }
58 
create_new_password_option(Nullable<string> * value,string name,string description)59 Password_option* Abstract_options_provider::create_new_password_option(
60   Nullable<string>* value, string name, string description)
61 {
62   return this->attach_new_option<Password_option>(
63     new Password_option(value, name, description));
64 }
65 
create_new_option(Nullable<string> * value,string name,string description)66 String_option* Abstract_options_provider::create_new_option(
67   Nullable<string>* value, string name, string description)
68 {
69   return this->attach_new_option<String_option>(
70     new String_option(value, name, description));
71 }
72 
create_new_option(int32 * value,string name,string description)73 Number_option<int32>* Abstract_options_provider::create_new_option(
74   int32* value, string name, string description)
75 {
76   return this->attach_new_option<Number_option<int32> >(
77     new Number_option<int32>(value, name, description));
78 }
79 
create_new_option(uint32 * value,string name,string description)80 Number_option<uint32>* Abstract_options_provider::create_new_option(
81   uint32* value, string name, string description)
82 {
83   return this->attach_new_option<Number_option<uint32> >(
84     new Number_option<uint32>(value, name, description));
85 }
86 
create_new_option(int64 * value,string name,string description)87 Number_option<int64>* Abstract_options_provider::create_new_option(
88   int64* value, string name, string description)
89 {
90   return this->attach_new_option<Number_option<int64> >(
91     new Number_option<int64>(value, name, description));
92 }
93 
create_new_option(uint64 * value,string name,string description)94 Number_option<uint64>* Abstract_options_provider::create_new_option(
95   uint64* value, string name, string description)
96 {
97   return this->attach_new_option<Number_option<uint64> >(
98     new Number_option<uint64>(value, name, description));
99 }
100 
create_new_option(double * value,string name,string description)101 Number_option<double>* Abstract_options_provider::create_new_option(
102   double* value, string name, string description)
103 {
104   return this->attach_new_option<Number_option<double> >(
105     new Number_option<double>(value, name, description));
106 }
107 
create_new_option(bool * value,string name,string description)108 Bool_option* Abstract_options_provider::create_new_option(
109   bool* value, string name, string description)
110 {
111   return this->attach_new_option<Bool_option>(
112     new Bool_option(value, name, description));
113 }
114 
115 
generate_options()116 vector<my_option> Abstract_options_provider::generate_options()
117 {
118   if (this->m_are_options_created == false)
119   {
120     this->m_are_options_created= true;
121     this->create_options();
122   }
123 
124   vector<my_option> res;
125   for (vector<I_option*>::iterator it= this->m_options_created.begin();
126     it != this->m_options_created.end();
127     it++)
128   {
129     res.push_back((*it)->get_my_option());
130   }
131 
132   return res;
133 }
134 
135 
options_parsed()136 void Abstract_options_provider::options_parsed()
137 {}
138 
139 
Abstract_options_provider()140 Abstract_options_provider::Abstract_options_provider()
141   : m_are_options_created(false),
142   m_option_changed_listener(NULL)
143 {}
144 
~Abstract_options_provider()145 Abstract_options_provider::~Abstract_options_provider()
146 {
147   for (vector<I_option*>::iterator it= this->m_options_created.begin();
148     it != this->m_options_created.end();
149     it++)
150   {
151     delete *it;
152   }
153 }
154 
set_option_changed_listener(I_option_changed_listener * listener)155 void Abstract_options_provider::set_option_changed_listener(I_option_changed_listener* listener)
156 {
157   assert(this->m_option_changed_listener == NULL);
158   this->m_option_changed_listener= listener;
159 }
160 
161 
notify_option_name_changed(I_option * source,string old_name)162 void Abstract_options_provider::notify_option_name_changed(I_option* source,
163                                                             string old_name)
164 {
165   // Check if it is modification or new assignment
166   if (old_name != "")
167   {
168     this->m_name_usage.erase(this->m_name_usage.find(old_name));
169   }
170 
171   string new_name= source->get_my_option().name;
172 
173   // Try to find existing option with that name.
174   map<string, I_option*>::iterator name_item =
175     this->m_name_usage.find(new_name);
176 
177   // Report error if already used.
178   if (name_item != this->m_name_usage.end())
179   {
180     std::cerr << "Cannot register new option \"" << new_name
181       << "\" as it collides with existing one with following name \""
182       << name_item->second->get_my_option().name << "\" and description: "
183       << name_item->second->get_my_option().comment << std::endl;
184     exit(1);
185   }
186   // Add name usage.
187   this->m_name_usage.insert(std::make_pair(new_name, source));
188 
189   // If we have listener we should inform it too.
190   if (this->m_option_changed_listener != NULL)
191   {
192     this->m_option_changed_listener->notify_option_name_changed(source, old_name);
193   }
194 }
195 
notify_option_optid_changed(I_option * source,uint32 old_optid)196 void Abstract_options_provider::notify_option_optid_changed(I_option* source,
197                                                             uint32 old_optid)
198 {
199   // Check if it is modification or new assignment
200   if (old_optid != 0)
201   {
202     this->m_optid_usage.erase(this->m_optid_usage.find(old_optid));
203   }
204 
205   uint32 new_optid= source->get_my_option().id;
206 
207   // Try to find existing option with that optid.
208   map<uint32, I_option*>::iterator optid_item =
209     this->m_optid_usage.find(new_optid);
210 
211   // Report error if already used.
212   if (optid_item != this->m_optid_usage.end())
213   {
214     string name= source->get_my_option().name;
215 
216     std::cerr << "Cannot register new option \"" << name
217       << "\" as it collides with existing one with following name \""
218       << optid_item->second->get_my_option().name << "\" and description: "
219       << optid_item->second->get_my_option().comment << std::endl;
220     exit(1);
221   }
222   // Add optid usage.
223   this->m_optid_usage.insert(std::make_pair(new_optid, source));
224 
225   // If we have listener we should inform it too.
226   if (this->m_option_changed_listener != NULL)
227   {
228     this->m_option_changed_listener->notify_option_optid_changed(source, old_optid);
229   }
230 }
231 
232