~ubuntu-branches/ubuntu/quantal/mysql-workbench/quantal

« back to all changes in this revision

Viewing changes to backend/wbpublic/grt/plugin_manager.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-03-01 21:57:30 UTC
  • Revision ID: package-import@ubuntu.com-20120301215730-o7y8av8y38n162ro
Tags: upstream-5.2.38+dfsg
ImportĀ upstreamĀ versionĀ 5.2.38+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License as
 
6
 * published by the Free Software Foundation; version 2 of the
 
7
 * License.
 
8
 * 
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
12
 * GNU General Public License for more details.
 
13
 * 
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 
17
 * 02110-1301  USA
 
18
 */
 
19
 
 
20
#include "stdafx.h"
 
21
 
 
22
#include "plugin_manager.h"
 
23
#include "editor_base.h"
 
24
#include "grt_manager.h"
 
25
#include "base/string_utilities.h"
 
26
 
 
27
#include "interfaces/plugin.h"
 
28
 
 
29
using namespace bec;
 
30
using namespace grt;
 
31
 
 
32
 
 
33
 
 
34
static std::string get_args_hash(const grt::BaseListRef &list)
 
35
{
 
36
  std::string hash;
 
37
 
 
38
  for (size_t c= list.count(), i= 0; i < c; i++)
 
39
  {
 
40
    switch (list.get(i).type())
 
41
    {
 
42
    case ObjectType:
 
43
      hash+= grt::ObjectRef::cast_from(list.get(i)).id();
 
44
      break;
 
45
    case ListType:
 
46
      hash+= get_args_hash(grt::BaseListRef::cast_from(list.get(i)));
 
47
      break;
 
48
    default:
 
49
      hash+= list.get(i).repr();
 
50
      break;
 
51
    }
 
52
  }
 
53
 
 
54
  return hash;
 
55
}
 
56
 
 
57
 
 
58
PluginManagerImpl::PluginManagerImpl(grt::CPPModuleLoader *loader)
 
59
  : superclass(loader)
 
60
{
 
61
  _grtm= GRTManager::get_instance_for(loader->get_grt());
 
62
  
 
63
  InterfaceImplBase::Register<PluginInterfaceImpl>(loader->get_grt());
 
64
}
 
65
 
 
66
 
 
67
/** 
 
68
 ****************************************************************************
 
69
 * @brief Sets the GRT tree path where the plugin registry is located
 
70
 *
 
71
 * @param plugins_path
 
72
 * @param groups_path
 
73
 ****************************************************************************
 
74
 */
 
75
void PluginManagerImpl::set_registry_paths(const std::string &plugins_path,
 
76
                                           const std::string &groups_path)
 
77
{
 
78
  _registry_path= plugins_path;
 
79
  _group_registry_path= groups_path;
 
80
}
 
81
 
 
82
 
 
83
bool PluginManagerImpl::check_plugin_validity(const app_PluginRef &plugin, grt::Module *module)
 
84
{
 
85
  if (plugin->pluginType() == GUI_PLUGIN_TYPE)
 
86
  {
 
87
    // not much that can be tested here, maybe check if the dll actually exists
 
88
    return true;
 
89
  }
 
90
  else if (plugin->pluginType() == STANDALONE_GUI_PLUGIN_TYPE
 
91
           || plugin->pluginType() == NORMAL_PLUGIN_TYPE)
 
92
  {
 
93
    // check if the module matches and the function exists
 
94
    if (plugin->moduleName() != module->name())
 
95
    {
 
96
      g_warning("Plugin '%s' from module %s declares moduleName() as '%s', which doesn't match the module it belongs to",
 
97
                plugin->name().c_str(), module->name().c_str(), plugin->moduleName().c_str());
 
98
      return false;
 
99
    }
 
100
    
 
101
    {
 
102
      std::string f= plugin->moduleFunctionName();
 
103
      if (!module->has_function(f))
 
104
      {
 
105
         g_warning("Plugin '%s' from module %s has invalid moduleFunctionName '%s'",
 
106
                  plugin->name().c_str(), module->name().c_str(), f.c_str());
 
107
        return false;
 
108
      }
 
109
    } 
 
110
    return true;
 
111
  }
 
112
  else if (plugin->pluginType() == INTERNAL_PLUGIN_TYPE)
 
113
  {
 
114
    return true;
 
115
  }
 
116
  else if (0 == (*plugin->pluginType()).find(CUSTOM_PLUGIN_TYPE))
 
117
  {
 
118
    return true;
 
119
  }
 
120
  else
 
121
  {    
 
122
    g_warning("Plugin '%s' from module %s has invalid type '%s'", plugin->name().c_str(), 
 
123
              module->name().c_str(), plugin->pluginType().c_str());
 
124
  }
 
125
  return false;
 
126
}
 
127
 
 
128
 
 
129
void PluginManagerImpl::set_plugin_enabled(const app_PluginRef &plugin, bool flag)
 
130
{
 
131
  grt::StringListRef disabled_list(get_disabled_plugin_names());  
 
132
  size_t idx= disabled_list.get_index(plugin->name());
 
133
  
 
134
  if (flag && idx != grt::BaseListRef::npos)
 
135
  {
 
136
    disabled_list.remove(idx);
 
137
    if (plugin->groups().count() == 0)
 
138
      add_plugin_to_group(plugin, "Others/Menu/Ungrouped");
 
139
    else
 
140
    {
 
141
      for (size_t d= plugin->groups().count(), j= 0; j < d; j++)
 
142
        add_plugin_to_group(plugin, plugin->groups()[j]);
 
143
    }
 
144
  }
 
145
  else if (!flag && idx == grt::BaseListRef::npos)
 
146
  {
 
147
    disabled_list.insert(plugin->name());
 
148
    // remove the plugin from all groups
 
149
    grt::ListRef<app_PluginGroup> groups(get_plugin_groups());
 
150
    for (unsigned int c= groups.count(), i= 0; i < c; i++)
 
151
      groups[i]->plugins().remove_value(plugin);
 
152
  }
 
153
}
 
154
 
 
155
 
 
156
bool PluginManagerImpl::plugin_enabled(const std::string &plugin_name)
 
157
{
 
158
  grt::StringListRef names(get_disabled_plugin_names());
 
159
  if (names.get_index(plugin_name) == grt::BaseListRef::npos)
 
160
    return true;
 
161
  return false;
 
162
}
 
163
 
 
164
 
 
165
grt::StringListRef PluginManagerImpl::get_disabled_plugin_names()
 
166
{
 
167
  std::string disabled_path(_registry_path);
 
168
  base::pop_path_back(disabled_path);
 
169
  base::pop_path_back(disabled_path);
 
170
  disabled_path.append("/options/disabledPlugins");
 
171
  return grt::StringListRef::cast_from(_grtm->get_grt()->get(disabled_path));
 
172
}
 
173
 
 
174
/** 
 
175
 ****************************************************************************
 
176
 * @brief Refreshes the list of plugins from the list of modules and DLLs
 
177
 *
 
178
 * Scans the list of registered modules for plugins.
 
179
 * Modules exporting plugins must implement PluginInterface.
 
180
 * The list of scanned plugins is stored in the GRT tree.
 
181
 *
 
182
 ****************************************************************************
 
183
 */
 
184
void PluginManagerImpl::rescan_plugins()
 
185
{
 
186
  grt::ListRef<app_Plugin> plugin_list= get_plugin_list();
 
187
  grt::GRT *grt= _grtm->get_grt();
 
188
  std::set<std::string> disabled_plugins;
 
189
 
 
190
  // make a set of disabled plugin names
 
191
  {
 
192
    grt::StringListRef list= get_disabled_plugin_names();
 
193
    if (list.is_valid())
 
194
      for (grt::StringListRef::const_iterator i= list.begin(); i != list.end(); ++i)
 
195
      {
 
196
        disabled_plugins.insert(*i);
 
197
      }
 
198
  }
 
199
 
 
200
  // clear plugin list
 
201
  while (plugin_list.count() > 0)
 
202
    plugin_list.remove(0);
 
203
  
 
204
  // clear group contents
 
205
  {
 
206
    grt::ListRef<app_PluginGroup> groups;
 
207
    app_PluginGroupRef group;
 
208
  
 
209
    groups= get_plugin_groups();
 
210
    for (unsigned int c= groups.count(), i= 0; i < c; i++)
 
211
    {
 
212
      group= groups[i];
 
213
      while (group->plugins().count() > 0)
 
214
        group->plugins().remove(0);
 
215
    }
 
216
  }
 
217
    
 
218
  // get list of modules that implement the plugin interface
 
219
  std::vector<Module*> plugin_modules= grt->find_modules_matching("PluginInterface", "");
 
220
 
 
221
  _plugin_source_module.clear();
 
222
  
 
223
  // add all modules to the plugins list
 
224
  for (std::vector<Module*>::const_iterator pm= plugin_modules.begin(); pm != plugin_modules.end(); ++pm)
 
225
  {
 
226
    grt::ListRef<app_Plugin> plist;
 
227
    try
 
228
    {
 
229
      grt::ValueRef result= (*pm)->call_function("getPluginInfo", grt::BaseListRef());
 
230
      
 
231
      plist= grt::ListRef<app_Plugin>::cast_from(result);
 
232
      if (!plist.is_valid() || plist.count() == 0)
 
233
      {
 
234
        grt->send_warning("Module "+(*pm)->name()+" implements PluginInterface but does not export any plugins", "");
 
235
        continue;
 
236
      }
 
237
    }
 
238
    catch (std::exception &exc)
 
239
    {
 
240
      grt->send_error("Module "+(*pm)->name()+" had an error while executing getPluginInfo: "+exc.what(), 
 
241
        "Location: "+(*pm)->path());
 
242
      continue;
 
243
    }
 
244
    
 
245
    size_t i, c= plist.count();
 
246
    for (i= 0; i < c; i++)
 
247
    {
 
248
      app_PluginRef plugin= plist[i];
 
249
      
 
250
      if (_plugin_source_module.find(plugin->name()) != _plugin_source_module.end())
 
251
      {
 
252
        grt->send_warning("Duplicate plugin name "+*plugin->name(),
 
253
                          base::strfmt("There is more than one plugin with the name %s (in %s and %s).",
 
254
                          plugin->name().c_str(), (*pm)->name().c_str(), _plugin_source_module[plugin->name()].c_str()));
 
255
        // must reset internal references in the object or we get a leak because of the cycles
 
256
        plugin->reset_references();
 
257
        continue;
 
258
      }
 
259
      
 
260
      if (!check_plugin_validity(plugin, *pm))
 
261
      {
 
262
        continue;
 
263
      }
 
264
      _plugin_source_module[plugin->name()]= (*pm)->name();
 
265
 
 
266
      // add to the plugin list
 
267
      if (plugin_list.is_valid())
 
268
        plugin_list.insert(plugin);
 
269
 
 
270
      if (disabled_plugins.find(*plugin->name()) != disabled_plugins.end())
 
271
      {
 
272
        if (grt->verbose())
 
273
          grt->send_info("Plugin "+*plugin->name()+" is disabled, skipping...", "");
 
274
        continue;
 
275
      }
 
276
 
 
277
      if (plugin->groups().count() == 0)
 
278
        add_plugin_to_group(plugin, "Others/Menu/Ungrouped");
 
279
      else
 
280
      {
 
281
        for (size_t d= plugin->groups().count(), j= 0; j < d; j++)
 
282
          add_plugin_to_group(plugin, plugin->groups()[j]);
 
283
      }
 
284
    }
 
285
  }
 
286
}
 
287
 
 
288
 
 
289
 
 
290
 
 
291
app_PluginGroupRef PluginManagerImpl::get_group(const std::string &group_name)
 
292
{
 
293
  grt::ListRef<app_PluginGroup> groups;
 
294
  app_PluginGroupRef group;
 
295
 
 
296
  groups= get_plugin_groups();
 
297
 
 
298
  for (unsigned int c= groups.count(), i= 0; i < c; i++)
 
299
  {
 
300
    if (groups[i]->name() == group_name)
 
301
    {
 
302
      group= groups[i];
 
303
      break;
 
304
    }
 
305
  }
 
306
 
 
307
  return group;
 
308
}
 
309
 
 
310
 
 
311
void PluginManagerImpl::add_plugin_to_group(const app_PluginRef &plugin, const std::string &group_name)
 
312
{
 
313
  app_PluginGroupRef group= get_group(group_name);
 
314
 
 
315
  if (group.is_valid())
 
316
    group->plugins().insert(plugin);
 
317
  // TODO: warning for now disabled, fix group loading
 
318
  //else 
 
319
  //  g_warning("Plugin %s could not be added to unknown group %s", plugin->name().c_str(), group_name.c_str());
 
320
}
 
321
 
 
322
 
 
323
 
 
324
/** 
 
325
 ****************************************************************************
 
326
 * @brief Sets callbacks for handling of GUI plugins
 
327
 *
 
328
 * @param open callback for opening a plugin
 
329
 * @param show callback for showing a plugin
 
330
 * @param close callback for closing a plugin
 
331
 * 
 
332
 ****************************************************************************
 
333
 */
 
334
void PluginManagerImpl::set_gui_plugin_callbacks(const OpenGUIPluginSlot &open,
 
335
                                                 const ShowGUIPluginSlot &show,
 
336
                                                 const CloseGUIPluginSlot &close)
 
337
{
 
338
  _open_gui_plugin_slot= open;
 
339
  _show_gui_plugin_slot= show;
 
340
  _close_gui_plugin_slot= close;
 
341
}
 
342
 
 
343
 
 
344
 
 
345
 
 
346
/** 
 
347
 ****************************************************************************
 
348
 * @brief Adds a list of plugins to the plugin registry
 
349
 *
 
350
 * @param list of plugins
 
351
 * 
 
352
 ****************************************************************************
 
353
 */
 
354
void PluginManagerImpl::register_plugins(grt::ListRef<app_Plugin> plugins)
 
355
{
 
356
  grt::ListRef<app_Plugin> list= get_plugin_list();
 
357
  
 
358
  for (unsigned int c= plugins.count(), i= 0; i < c; i++)
 
359
    list.insert(plugins[i]);
 
360
}
 
361
 
 
362
 
 
363
 
 
364
 
 
365
/** 
 
366
 ****************************************************************************
 
367
 * @brief Return list of registered plugin groups 
 
368
 *
 
369
 * @return List of plugin groups
 
370
 ****************************************************************************
 
371
 */
 
372
grt::ListRef<app_PluginGroup> PluginManagerImpl::get_plugin_groups()
 
373
{
 
374
  return grt::ListRef<app_PluginGroup>::cast_from(_grtm->get_grt()->get(_group_registry_path));
 
375
}
 
376
 
 
377
 
 
378
 
 
379
/** 
 
380
 ****************************************************************************
 
381
 * @brief Returns list of all registered plugins.
 
382
 * 
 
383
 * The list of plugins is looked up at the GRT tree path set with
 
384
 * set_registry_path()
 
385
 *
 
386
 * @param group optional name of plugin group (allows * wildcards)
 
387
 * 
 
388
 * @return List of plugins.
 
389
 ****************************************************************************
 
390
 */
 
391
grt::ListRef<app_Plugin> PluginManagerImpl::get_plugin_list(const std::string &group)
 
392
{
 
393
  if (group.empty())
 
394
    return grt::ListRef<app_Plugin>::cast_from(_grtm->get_grt()->get(_registry_path));
 
395
  else
 
396
  {
 
397
    grt::ListRef<app_Plugin> rlist(_grtm->get_grt()), list;
 
398
    std::string left, right;
 
399
 
 
400
    // groups are expected to be either in group/subgroup format or group (which will be interpreted as group/*)
 
401
    
 
402
    if (group.find('/') != std::string::npos)
 
403
    {
 
404
      left= group.substr(0, group.find('/'));
 
405
      right= group.substr(group.find('/')+1);
 
406
    }
 
407
    else
 
408
    {
 
409
      left= group;
 
410
      right= "*";
 
411
    }
 
412
    
 
413
    list= grt::ListRef<app_Plugin>::cast_from(_grtm->get_grt()->get(_registry_path));
 
414
 
 
415
    for (size_t c= list.count(), i= 0; i < c; i++)
 
416
    {
 
417
      app_PluginRef plugin(list[i]);
 
418
      grt::StringListRef groups(plugin->groups());
 
419
      bool found= false;
 
420
 
 
421
      if (!plugin_enabled(plugin->name()))
 
422
        continue;
 
423
      
 
424
      for (size_t gc= groups.count(), g= 0; g < gc; g++)
 
425
      {
 
426
        std::string gstr(groups[g]);
 
427
        std::string gleft, gright;
 
428
        std::string::size_type pos;
 
429
 
 
430
        if ((pos= gstr.find('/')))
 
431
        {
 
432
          gleft= gstr.substr(0, pos);
 
433
          gright= gstr.substr(pos+1);
 
434
        }
 
435
        else
 
436
        {
 
437
          gleft= gstr;
 
438
          gright= "";
 
439
        }
 
440
 
 
441
        if ((left=="*" || left == gleft) && (right=="*" || right == gright))
 
442
        {
 
443
          found= true;
 
444
          break;
 
445
        }
 
446
      }
 
447
      if (found)
 
448
        rlist.insert(plugin);
 
449
    }
 
450
    
 
451
    return rlist;
 
452
  }
 
453
}
 
454
 
 
455
 
 
456
bool PluginManagerImpl::check_plugin_input(const app_PluginInputDefinitionRef &def,
 
457
                                           const grt::ValueRef &value)
 
458
{
 
459
  if (def.is_instance(app_PluginFileInput::static_class_name()))
 
460
  {
 
461
    if (value.is_valid() && value.type() != StringType)
 
462
      return false;
 
463
  }
 
464
  else if (def.is_instance(app_PluginSelectionInput::static_class_name()))
 
465
  {
 
466
    if (!value.is_valid() || value.type() != ListType)
 
467
      return false;
 
468
 
 
469
    app_PluginSelectionInputRef sdef(app_PluginSelectionInputRef::cast_from(def));
 
470
    grt::ObjectListRef olist(grt::ObjectListRef::cast_from(value));
 
471
 
 
472
    for (size_t d= olist.count(), j= 0; j < d; j++)
 
473
    {
 
474
      grt::ObjectRef value(olist.get(j));
 
475
      bool ok= false;
 
476
 
 
477
      for (size_t c= sdef->objectStructNames().count(), i= 0; i < c; i++)
 
478
      {
 
479
        if (value.is_instance(sdef->objectStructNames()[i]))
 
480
        {
 
481
          ok= true;
 
482
          break;
 
483
        }
 
484
      }
 
485
      if (!ok)
 
486
        return false;
 
487
    }
 
488
 
 
489
    std::string card= *sdef->argumentCardinality();
 
490
    if (card == "1")
 
491
    {
 
492
      if (olist.count() != 1)
 
493
        return false;
 
494
    }
 
495
    else if (card == "?")
 
496
    {
 
497
      if (olist.count() > 1)
 
498
        return false;
 
499
    }
 
500
    else if (card == "+")
 
501
    {
 
502
      if (olist.count() == 0)
 
503
        return false;
 
504
    }
 
505
    else if (card == "*")
 
506
      ;
 
507
    else
 
508
    {
 
509
      if (olist.count() != 1)
 
510
        return false;
 
511
    }
 
512
  }
 
513
  else if (def.is_instance(app_PluginObjectInput::static_class_name()))
 
514
  {
 
515
    if (!value.is_valid() || value.type() != ObjectType)
 
516
      return false;
 
517
 
 
518
    app_PluginObjectInputRef odef(app_PluginObjectInputRef::cast_from(def));
 
519
 
 
520
    if (!grt::ObjectRef::cast_from(value).is_instance(odef->objectStructName()))
 
521
      return false;
 
522
  }
 
523
  else
 
524
    return false;
 
525
 
 
526
  return true;
 
527
}
 
528
 
 
529
 
 
530
bool PluginManagerImpl::check_input_for_plugin(const app_PluginRef &plugin, const grt::BaseListRef &args)
 
531
{
 
532
  if (args.count() != plugin->inputValues().count())
 
533
    return false;
 
534
 
 
535
  for (size_t c= plugin->inputValues().count(), i= 0; i < c; i++)
 
536
  {
 
537
    if (!check_plugin_input(plugin->inputValues()[i], args[i]))
 
538
      return false;
 
539
  }
 
540
  return true;
 
541
}
 
542
 
 
543
 
 
544
app_PluginRef PluginManagerImpl::select_plugin_for_input(const std::string &group, const grt::BaseListRef &args)
 
545
{
 
546
  ListRef<app_Plugin> plugins= get_plugin_list(group);
 
547
  app_PluginRef best_match;
 
548
  int rating= -1;
 
549
 
 
550
  for (size_t c= plugins.count(), i= 0; i < c; i++)
 
551
  {
 
552
    app_PluginRef plugin= plugins[i];
 
553
 
 
554
    if (check_input_for_plugin(plugin, args) && *plugin->rating() > rating)
 
555
    {
 
556
      best_match= plugin;
 
557
      rating= *plugin->rating();
 
558
    }
 
559
  }
 
560
 
 
561
  return best_match;
 
562
}
 
563
 
 
564
 
 
565
 
 
566
/** 
 
567
 ****************************************************************************
 
568
 * @brief Returns list of plugins that can be called on the objects
 
569
 *
 
570
 *
 
571
 * @param objects list of objects
 
572
 * @param group optional name of group for filtering (eg: catalog/Editors)
 
573
 *
 
574
 * @return list of plugins
 
575
 ****************************************************************************
 
576
 */
 
577
//TODO: delete?
 
578
std::vector<app_PluginRef> PluginManagerImpl::get_plugins_for_objects(const grt::ObjectListRef &objects,
 
579
                                                                   const std::string &group)
 
580
{
 
581
  std::vector<app_PluginRef> plist;
 
582
  grt::ListRef<app_Plugin> plugins;
 
583
 
 
584
  plugins= get_plugin_list(group);
 
585
  size_t i, c= plugins.count();
 
586
 
 
587
  // look for plugins that take 1 ObjectInput arg that is compatible with the obj list
 
588
  if (objects.count() == 1)
 
589
    for (i= 0; i < c; i++)
 
590
    {
 
591
      app_PluginRef plugin(plugins[i]);
 
592
 
 
593
      if (plugin->inputValues().count() == 1 && 
 
594
        plugin->inputValues()[0]->is_instance(app_PluginObjectInput::static_class_name()))
 
595
      {
 
596
        app_PluginObjectInputRef oinput(app_PluginObjectInputRef::cast_from(plugin->inputValues()[0]));
 
597
        std::string struct_name= oinput->objectStructName();
 
598
        bool ok= true;
 
599
 
 
600
        for (size_t oc= objects.count(), oi= 0; oi < oc; oi++)
 
601
        {
 
602
          if (!objects[oi].is_instance(struct_name))
 
603
          {
 
604
            ok= false;
 
605
            break;
 
606
          }
 
607
        }
 
608
      
 
609
        if (ok)
 
610
          plist.push_back(plugin);
 
611
      }
 
612
    }
 
613
 
 
614
  // look for plugins that take selection as input and are compatible with the obj list
 
615
  for (i= 0; i < c; i++)
 
616
  {
 
617
    app_PluginRef plugin(plugins[i]);
 
618
 
 
619
    if (plugin->inputValues().count() == 1 && 
 
620
      plugin->inputValues()[0]->is_instance(app_PluginSelectionInput::static_class_name()))
 
621
    {
 
622
      app_PluginSelectionInputRef oinput(app_PluginSelectionInputRef::cast_from(plugin->inputValues()[0]));
 
623
      std::string card= *oinput->argumentCardinality();
 
624
      grt::StringListRef struct_names(oinput->objectStructNames());
 
625
      bool ok= true;
 
626
 
 
627
      if (card == "1")
 
628
      {
 
629
        if (objects.count() != 1)
 
630
          continue;
 
631
      }
 
632
      else if (card == "?")
 
633
      {
 
634
        if (objects.count() > 1)
 
635
          continue;
 
636
      }
 
637
      else if (card == "+")
 
638
      {
 
639
        if (objects.count() == 0)
 
640
          continue;
 
641
      }
 
642
      else if (card == "*")
 
643
        ;
 
644
      else
 
645
      {
 
646
        if (objects.count() != 1)
 
647
          continue;
 
648
      }
 
649
 
 
650
      for (size_t oc= objects.count(), oi= 0; oi < oc && ok; oi++)
 
651
      {
 
652
        for (size_t sc= struct_names.count(), si= 0; si < sc && ok; si++)
 
653
        {
 
654
          if (!objects[oi].is_instance(struct_names[si]))
 
655
          {
 
656
            ok= false;
 
657
            break;
 
658
          }
 
659
        }
 
660
      }
 
661
 
 
662
      if (ok)
 
663
        plist.push_back(plugin);
 
664
    }
 
665
  }
 
666
 
 
667
  return plist;
 
668
}
 
669
 
 
670
 
 
671
/** 
 
672
 ****************************************************************************
 
673
 * @brief Returns list of plugins in the named group.
 
674
 *
 
675
 * @param group
 
676
 *
 
677
 * @return List of plugins
 
678
 *
 
679
 ****************************************************************************
 
680
 */
 
681
std::vector<app_PluginRef> PluginManagerImpl::get_plugins_for_group(const std::string &group)
 
682
{
 
683
  std::vector<app_PluginRef> rlist;
 
684
  grt::ListRef<app_Plugin> list= get_plugin_list(group);
 
685
  
 
686
  for (size_t c= list.count(), i= 0; i < c; i++)
 
687
    rlist.push_back(list[i]);
 
688
  
 
689
  return rlist;
 
690
}
 
691
 
 
692
 
 
693
/** 
 
694
 ****************************************************************************
 
695
 * @brief Return named plugin 
 
696
 *
 
697
 * @param name
 
698
 *
 
699
 * @return plugin
 
700
 ****************************************************************************
 
701
 */
 
702
app_PluginRef PluginManagerImpl::get_plugin(const std::string &name)
 
703
{
 
704
  grt::ListRef<app_Plugin> plugins= get_plugin_list();
 
705
  
 
706
  for (size_t c= plugins.count(), i= 0; i < c; i++)
 
707
  {
 
708
    if (*plugins[i]->name() == name)
 
709
      return plugins[i];
 
710
  }
 
711
  return app_PluginRef();
 
712
}
 
713
 
 
714
 
 
715
static std::string make_open_plugin_id(const grt::Module *module,
 
716
                                       const std::string &class_name,
 
717
                                       const grt::BaseListRef &args)
 
718
{
 
719
  std::string argshash= get_args_hash(args);
 
720
  
 
721
  return module->name()+"/"+class_name+"//"+argshash;
 
722
}
 
723
 
 
724
 
 
725
 
 
726
 
 
727
std::vector<NativeHandle> PluginManagerImpl::get_similar_open_plugins(grt::Module *module, const std::string &class_name, grt::BaseListRef)
 
728
{
 
729
  std::vector<NativeHandle> handles;
 
730
 
 
731
  std::string prefix= module->name()+"/"+class_name+"//";
 
732
 
 
733
  for (std::map<std::string, NativeHandle>::const_iterator iter= _open_gui_plugins.begin();
 
734
       iter != _open_gui_plugins.end(); ++iter)
 
735
  {
 
736
    if (iter->first.substr(0, prefix.size()) == prefix)
 
737
      handles.push_back(iter->second);
 
738
  }
 
739
 
 
740
  return handles;
 
741
}
 
742
 
 
743
 
 
744
 
 
745
std::string PluginManagerImpl::open_gui_plugin(const app_PluginRef &plugin, const grt::BaseListRef &args, GUIPluginFlags flags)
 
746
{
 
747
  if (!plugin.is_valid())
 
748
    throw std::invalid_argument("Attempt to open an invalid plugin");
 
749
  
 
750
  if (*plugin->pluginType() == GUI_PLUGIN_TYPE)
 
751
  {
 
752
    if (_grtm->in_main_thread())
 
753
      return open_gui_plugin_main(plugin, args, flags);
 
754
    else
 
755
    {
 
756
      GRTDispatcher *disp= _grtm->get_dispatcher();
 
757
 
 
758
      // request the plugin to be executed and opened by the frontend in the main thread
 
759
      DispatcherCallback<std::string> *cb= new DispatcherCallback<std::string>(boost::bind(&PluginManagerImpl::open_gui_plugin_main,this,
 
760
                                                                plugin, args, flags));
 
761
 
 
762
      disp->call_from_main_thread(cb, false, false);
 
763
      
 
764
      cb->release();
 
765
 
 
766
      grt::Module *module= _grtm->get_grt()->get_module(_plugin_source_module[plugin->name()]);
 
767
      // build the handle name ourselves
 
768
      return make_open_plugin_id(module, plugin->moduleFunctionName(), args);
 
769
    }
 
770
  }
 
771
  else if (*plugin->pluginType() == STANDALONE_GUI_PLUGIN_TYPE)
 
772
  {
 
773
    if (_grtm->in_main_thread())
 
774
      open_standalone_plugin_main(plugin, args);
 
775
    else
 
776
    {
 
777
      GRTDispatcher *disp= _grtm->get_dispatcher();
 
778
      
 
779
      // request the plugin to be executed and opened by the frontend in the main thread
 
780
      DispatcherCallback<void> *cb= new DispatcherCallback<void>(boost::bind(&PluginManagerImpl::open_standalone_plugin_main, this, 
 
781
                                                                  plugin, args));
 
782
      
 
783
      disp->call_from_main_thread(cb, false, false);
 
784
      
 
785
      cb->release();
 
786
    }
 
787
  }
 
788
  else if (*plugin->pluginType() == INTERNAL_PLUGIN_TYPE)
 
789
  {
 
790
    if (_grtm->in_main_thread())
 
791
      open_normal_plugin_grt(_grtm->get_grt(), plugin, args);
 
792
    else
 
793
    {
 
794
      GRTDispatcher *disp= _grtm->get_dispatcher();
 
795
      
 
796
      // request the plugin to be executed and opened by the frontend in the main thread
 
797
      DispatcherCallback<grt::ValueRef> *cb= new DispatcherCallback<grt::ValueRef>(boost::bind(&PluginManagerImpl::open_normal_plugin_grt, this, 
 
798
                                                                  _grtm->get_grt(), plugin, args));
 
799
      
 
800
      disp->call_from_main_thread(cb, false, false);
 
801
      
 
802
      cb->release();
 
803
    }
 
804
  }
 
805
  else // a normal plugin implemented by a GRT module
 
806
  {
 
807
    if (_grtm->in_main_thread())
 
808
    {
 
809
      _grtm->get_dispatcher()->execute_simple_function("Open normal plugin",
 
810
        boost::bind(&PluginManagerImpl::open_normal_plugin_grt, this, _1, plugin, args));
 
811
    }
 
812
    else
 
813
      open_normal_plugin_grt(_grtm->get_grt(), plugin, args);
 
814
  }
 
815
  return "";
 
816
}
 
817
 
 
818
 
 
819
/** 
 
820
 ****************************************************************************
 
821
 * @brief Executes the plugin with the given list of arguments
 
822
 *
 
823
 * If the plugin is a GUI type plugin, the GUI plugin callbacks are executed
 
824
 * in the main thread and may return a handle to pass back to the frontend
 
825
 * and be processed.
 
826
 * 
 
827
 * If the plugin is a normal type plugin, it will be just executed in the 
 
828
 * GRT thread, as usual.
 
829
 *
 
830
 * @param plugin object
 
831
 * @param args list of 
 
832
 *
 
833
 * @return An identifier/handle for the opened plugin, if it's a GUI plugin
 
834
 * or "" for other types of plugins.
 
835
 ****************************************************************************
 
836
 */
 
837
std::string PluginManagerImpl::open_plugin(const app_PluginRef &plugin, const grt::BaseListRef &args)
 
838
{
 
839
  return open_gui_plugin(plugin, args, NoFlags);
 
840
}
 
841
 
 
842
 
 
843
grt::ValueRef PluginManagerImpl::execute_plugin_function(const app_PluginRef &plugin, const grt::BaseListRef &args)
 
844
{
 
845
  grt::Module *module= _grtm->get_grt()->get_module(plugin->moduleName());
 
846
  
 
847
  if (!module)
 
848
    throw grt::grt_runtime_error("Cannot execute plugin "+*plugin->name(), "Called module "+*plugin->moduleName()+" not found");
 
849
  
 
850
  return module->call_function(*plugin->moduleFunctionName(), args);
 
851
}
 
852
 
 
853
grt::ValueRef PluginManagerImpl::open_normal_plugin_grt(grt::GRT *grt, const app_PluginRef &plugin,
 
854
                                                            const grt::BaseListRef &args)
 
855
{
 
856
  grt::Module *module= _grtm->get_grt()->get_module(plugin->moduleName());
 
857
 
 
858
  if (!module)
 
859
    throw grt::grt_runtime_error("Cannot execute plugin "+*plugin->name(), "Called module "+*plugin->moduleName()+" not found");
 
860
 
 
861
  return module->call_function(*plugin->moduleFunctionName(), args);
 
862
}
 
863
 
 
864
 
 
865
void PluginManagerImpl::open_standalone_plugin_main(const app_PluginRef &plugin, const grt::BaseListRef &args)
 
866
{
 
867
  grt::Module *module= _grtm->get_grt()->get_module(plugin->moduleName());
 
868
  
 
869
  if (!module)
 
870
    throw grt::grt_runtime_error("Cannot execute plugin "+*plugin->name(), "Called module "+*plugin->moduleName()+" not found");
 
871
  
 
872
  module->call_function(*plugin->moduleFunctionName(), args);
 
873
}
 
874
 
 
875
 
 
876
 
 
877
std::string PluginManagerImpl::open_gui_plugin_main(const app_PluginRef &plugin,
 
878
                                                    const grt::BaseListRef &args,
 
879
                                                    GUIPluginFlags flags)
 
880
{
 
881
  NativeHandle handle;
 
882
  grt::Module *module= _grtm->get_grt()->get_module(_plugin_source_module[plugin->name()]);
 
883
  std::string open_plugin_id= make_open_plugin_id(module, plugin->moduleFunctionName(), args);
 
884
 
 
885
  if (_open_gui_plugins.find(open_plugin_id) != _open_gui_plugins.end())
 
886
  {
 
887
    handle= _open_gui_plugins[open_plugin_id];
 
888
    _show_gui_plugin_slot(handle);
 
889
  }
 
890
  else
 
891
  {
 
892
    grt::Module *module= _grtm->get_grt()->get_module(_plugin_source_module[plugin->name()]);
 
893
 
 
894
    // open the editor and get a handle for the GUI object to pass to the frontend
 
895
    NativeHandle handle= _open_gui_plugin_slot(_grtm,
 
896
                                               module,
 
897
                                               *plugin->moduleName(),
 
898
                                               *plugin->moduleFunctionName(),
 
899
                                               args,
 
900
                                               flags);
 
901
    if (handle)
 
902
    {
 
903
      _open_gui_plugins[open_plugin_id]= handle;
 
904
      _show_gui_plugin_slot(handle);
 
905
    }
 
906
  }
 
907
 
 
908
  return open_plugin_id;
 
909
}
 
910
 
 
911
 
 
912
 
 
913
/** 
 
914
 ****************************************************************************
 
915
 * @brief Shows a previously opened (GUI) plugin.
 
916
 *
 
917
 * @param handle returned by open_plugin
 
918
 * 
 
919
 * @return always 0 at the moment
 
920
 ****************************************************************************
 
921
 */
 
922
int PluginManagerImpl::show_plugin(const std::string &handle)
 
923
{
 
924
  if (_grtm->in_main_thread())
 
925
    return show_gui_plugin_main(handle);
 
926
  else
 
927
  {
 
928
    GRTDispatcher *disp= _grtm->get_dispatcher();
 
929
    // request the plugin to be executed and opened by the frontend in the main thread
 
930
 
 
931
    DispatcherCallback<int> *cb= new DispatcherCallback<int>(boost::bind(&PluginManagerImpl::show_gui_plugin_main, this, handle));
 
932
    
 
933
    disp->call_from_main_thread(cb, false, false);
 
934
 
 
935
    cb->release();
 
936
 
 
937
    // return value is ignored atm.
 
938
 
 
939
    return 0;
 
940
  }
 
941
}
 
942
 
 
943
 
 
944
int PluginManagerImpl::show_gui_plugin_main(const std::string &handle)
 
945
{
 
946
  if (_open_gui_plugins.find(handle) != _open_gui_plugins.end())
 
947
  {
 
948
    NativeHandle hdl= _open_gui_plugins[handle];
 
949
    _show_gui_plugin_slot(hdl);
 
950
  }
 
951
 
 
952
  return 1;
 
953
}
 
954
 
 
955
 
 
956
 
 
957
 
 
958
/** 
 
959
 ****************************************************************************
 
960
 * @brief Closes a previously opened (GUI) plugin.
 
961
 *
 
962
 * @param handle return by open_plugin
 
963
 * 
 
964
 * @return always 0 at the moment
 
965
 ****************************************************************************
 
966
 */
 
967
int PluginManagerImpl::close_plugin(const std::string &handle)
 
968
{
 
969
  if (_grtm->in_main_thread())
 
970
    return close_gui_plugin_main(handle);
 
971
  else
 
972
  {
 
973
    GRTDispatcher *disp= _grtm->get_dispatcher();
 
974
    // request the plugin to be executed and opened by the frontend in the main thread
 
975
 
 
976
    DispatcherCallback<int> *cb= new DispatcherCallback<int>(boost::bind(&PluginManagerImpl::close_gui_plugin_main, this, handle));
 
977
    
 
978
    disp->call_from_main_thread(cb, false, false);
 
979
 
 
980
    cb->release();
 
981
 
 
982
    // return value is ignored atm.
 
983
 
 
984
    return 0;
 
985
  }
 
986
}
 
987
 
 
988
//--------------------------------------------------------------------------------------------------
 
989
 
 
990
int PluginManagerImpl::close_gui_plugin_main(const std::string &handle)
 
991
{
 
992
  if (_open_gui_plugins.find(handle) != _open_gui_plugins.end())
 
993
  {
 
994
    NativeHandle hdl= _open_gui_plugins[handle];
 
995
    _close_gui_plugin_slot(hdl);
 
996
  }
 
997
 
 
998
  return 1;
 
999
}
 
1000
 
 
1001
//--------------------------------------------------------------------------------------------------
 
1002
 
 
1003
void PluginManagerImpl::forget_gui_plugin_handle(NativeHandle handle)
 
1004
{
 
1005
  for (std::map<std::string,NativeHandle>::iterator iter= _open_gui_plugins.begin();
 
1006
       iter != _open_gui_plugins.end(); ++iter)
 
1007
  {
 
1008
    if (iter->second == handle)
 
1009
    {
 
1010
      _open_gui_plugins.erase(iter);
 
1011
      break;
 
1012
    }
 
1013
  }
 
1014
}
 
1015
 
 
1016
//--------------------------------------------------------------------------------------------------
 
1017
 
 
1018
void PluginManagerImpl::close_and_forget_gui_plugin(NativeHandle handle)
 
1019
{
 
1020
  for (std::map<std::string,NativeHandle>::iterator iter= _open_gui_plugins.begin();
 
1021
    iter != _open_gui_plugins.end(); ++iter)
 
1022
  {
 
1023
    if (iter->second == handle)
 
1024
    {
 
1025
       _close_gui_plugin_slot(handle);
 
1026
      _open_gui_plugins.erase(iter);
 
1027
      break;
 
1028
    }
 
1029
  }
 
1030
}
 
1031
 
 
1032
 
 
1033
//--------------------------------------------------------------------------------------------------
 
1034
 
 
1035
grt::ValueRef ArgumentPool::find_match(const app_PluginInputDefinitionRef &pdef, std::string &searched_key_name_ret, bool strict) const
 
1036
{
 
1037
  std::string key = pdef.class_name();
 
1038
  
 
1039
  if (pdef.class_name() == app_PluginSelectionInput::static_class_name())
 
1040
  {
 
1041
    app_PluginSelectionInputRef sdef(app_PluginSelectionInputRef::cast_from(pdef));
 
1042
 
 
1043
    // add source
 
1044
    key.append(":").append(*pdef->name()).append(":");
 
1045
    searched_key_name_ret= key;
 
1046
    
 
1047
    // find entry
 
1048
    const_iterator iter;
 
1049
    if ((iter= find(key)) == end())
 
1050
      return grt::ValueRef();
 
1051
    
 
1052
    if (!iter->second.is_valid() || !grt::ObjectListRef::can_wrap(iter->second))
 
1053
      return grt::ValueRef();
 
1054
 
 
1055
    grt::ObjectListRef olist(grt::ObjectListRef::cast_from(iter->second));
 
1056
    
 
1057
    bool matches= true;
 
1058
    
 
1059
    // check if value matches the requirements
 
1060
    for (size_t d= olist.count(), j= 0; j < d; j++)
 
1061
    {
 
1062
      grt::ObjectRef value(olist.get(j));
 
1063
      bool ok= false;
 
1064
 
 
1065
      for (size_t c= sdef->objectStructNames().count(), i= 0; i < c; i++)
 
1066
      {
 
1067
        if (value.is_instance(sdef->objectStructNames()[i]))
 
1068
        {
 
1069
          ok= true;
 
1070
          break;
 
1071
        }
 
1072
      }
 
1073
      if (!ok)
 
1074
      {
 
1075
        matches= false;
 
1076
        break;
 
1077
      }
 
1078
    }
 
1079
    
 
1080
    std::string card= *sdef->argumentCardinality();
 
1081
    if (card == "1")
 
1082
    {
 
1083
      if (olist.count() != 1)
 
1084
        matches= false;
 
1085
    }
 
1086
    else if (card == "?")
 
1087
    {
 
1088
      if (olist.count() > 1)
 
1089
        matches= false;
 
1090
    }
 
1091
    else if (card == "+")
 
1092
    {
 
1093
      if (olist.count() == 0)
 
1094
        matches= false;
 
1095
    }
 
1096
    else if (card == "*")
 
1097
      ;
 
1098
    else
 
1099
    {
 
1100
      if (olist.count() != 1)
 
1101
        matches= false;
 
1102
    }
 
1103
    
 
1104
    if (matches)
 
1105
      return olist;
 
1106
  }
 
1107
  else
 
1108
  {
 
1109
    if (pdef.class_name() == app_PluginObjectInput::static_class_name())
 
1110
      key.append(":").append(*pdef->name()).append(":").append(*app_PluginObjectInputRef::cast_from(pdef)->objectStructName());
 
1111
    else if (pdef.class_name() == app_PluginFileInput::static_class_name())
 
1112
    {
 
1113
      if (strict)
 
1114
        key.append(":").append(*pdef->name()).append(":").append(app_PluginFileInputRef::cast_from(pdef)->dialogType());
 
1115
      else
 
1116
        key.append(":").append(":").append(app_PluginFileInputRef::cast_from(pdef)->dialogType());
 
1117
    }
 
1118
    else if (pdef.class_name() == app_PluginInputDefinition::static_class_name())
 
1119
      key.append(":").append(*pdef->name());
 
1120
    
 
1121
    searched_key_name_ret= key;
 
1122
 
 
1123
    const_iterator iter;
 
1124
    if ((iter= find(key)) != end())
 
1125
      return iter->second;
 
1126
  }
 
1127
 
 
1128
  return grt::ValueRef();
 
1129
}
 
1130
 
 
1131
void ArgumentPool::dump_keys(const boost::function<void (std::string)> &dump_function) const
 
1132
{
 
1133
  for (ArgumentPool::const_iterator i= begin(); i != end(); ++i)
 
1134
  {
 
1135
    if (dump_function)
 
1136
      dump_function(i->first+"\n");
 
1137
    else
 
1138
      g_message("%s", i->first.c_str());
 
1139
  }
 
1140
}
 
1141
 
 
1142
void ArgumentPool::add_simple_value(const std::string &name, const grt::ValueRef &value)
 
1143
{
 
1144
  std::string prefix= "app.PluginInputDefinition:"+name;
 
1145
  
 
1146
  (*this)[prefix]= value;
 
1147
}
 
1148
 
 
1149
void ArgumentPool::add_list_for_selection(const std::string &source_name,
 
1150
                                          const grt::ObjectListRef &list)
 
1151
{
 
1152
  std::string prefix= "app.PluginSelectionInput:"+source_name+":";
 
1153
  
 
1154
  (*this)[prefix]= list;
 
1155
}
 
1156
 
 
1157
 
 
1158
void ArgumentPool::add_entries_for_object(const std::string &name,
 
1159
                                          const grt::ObjectRef &object,
 
1160
                                          const std::string &topmost_class_name)
 
1161
{
 
1162
  if (object.is_valid())
 
1163
  {
 
1164
    grt::GRT *grt= object.get_grt();
 
1165
    std::string prefix= "app.PluginObjectInput:"+name+":";
 
1166
    std::string class_name= object.class_name();
 
1167
    bool done= false;
 
1168
    for (;;)
 
1169
    {
 
1170
      grt::MetaClass *mc= grt->get_metaclass(class_name);
 
1171
      (*this)[prefix+mc->name()]= object;
 
1172
 
 
1173
      class_name = mc->parent() ? mc->parent()->name() : "";
 
1174
      if (topmost_class_name.empty() || class_name.empty() || done)
 
1175
        break;
 
1176
      if (topmost_class_name == class_name)
 
1177
        done= true;
 
1178
    }
 
1179
  }
 
1180
}
 
1181
 
 
1182
bool ArgumentPool::needs_simple_input(const app_PluginRef &plugin, const std::string &name)
 
1183
{
 
1184
  const size_t c= plugin->inputValues().count();
 
1185
  for (size_t i= 0; i < c; i++)
 
1186
  {
 
1187
    app_PluginInputDefinitionRef pdef(plugin->inputValues().get(i));
 
1188
    
 
1189
    if (pdef.class_name() == app_PluginInputDefinition::static_class_name())
 
1190
    {
 
1191
      if (pdef->name() == name)
 
1192
        return true;
 
1193
    }
 
1194
  }
 
1195
  return false;
 
1196
}
 
1197
 
 
1198
app_PluginFileInputRef ArgumentPool::needs_file_input(const app_PluginRef &plugin)
 
1199
{
 
1200
  const size_t c= plugin->inputValues().count();
 
1201
  for (size_t i= 0; i < c; i++)
 
1202
  {
 
1203
    app_PluginInputDefinitionRef pdef(plugin->inputValues().get(i));
 
1204
    
 
1205
    if (pdef.is_instance(app_PluginFileInput::static_class_name()))
 
1206
      return app_PluginFileInputRef::cast_from(pdef);
 
1207
  }
 
1208
  return app_PluginFileInputRef();
 
1209
}
 
1210
 
 
1211
void ArgumentPool::add_file_input(const app_PluginFileInputRef &pdef,
 
1212
                                  const std::string &value)
 
1213
{
 
1214
  std::string key = app_PluginFileInput::static_class_name();
 
1215
  key.append(":").append(*pdef->name()).append(":").append(pdef->dialogType());
 
1216
  
 
1217
  (*this)[key]= grt::StringRef(value);
 
1218
}
 
1219
 
 
1220
grt::BaseListRef ArgumentPool::build_argument_list(const app_PluginRef &plugin)
 
1221
{
 
1222
  // build the argument list
 
1223
  grt::BaseListRef fargs(plugin->get_grt());
 
1224
  
 
1225
  const size_t c= plugin->inputValues().count();
 
1226
  for (size_t i= 0; i < c; i++)
 
1227
  {
 
1228
    app_PluginInputDefinitionRef pdef(plugin->inputValues().get(i));
 
1229
    std::string searched_key;
 
1230
    grt::ValueRef argument= find_match(pdef, searched_key);
 
1231
    if (!argument.is_valid())
 
1232
    {
 
1233
      g_message("Cannot satisfy plugin input for %s: %s", plugin->name().c_str(), searched_key.c_str());
 
1234
      g_message("Missing input: %s", pdef.repr().c_str());
 
1235
      
 
1236
      throw grt::grt_runtime_error("Cannot execute "+*plugin->name(),
 
1237
                                   "Plugin requires unavailable argument value.");
 
1238
    }
 
1239
    fargs.ginsert(argument);
 
1240
  }  
 
1241
  return fargs;
 
1242
}