Exemple #1
0
void PluginManager::Load()
{
    wxString ext;
#if defined(__WXGTK__)
    ext = wxT("so");

#elif defined(__WXMAC__)
    ext = wxT("dylib");

#else
    ext = wxT("dll");
#endif

    wxString fileSpec(wxT("*.") + ext);
    clConfig conf("plugins.conf");

    conf.ReadItem(&m_pluginsData);

    // set the managers
    // this code assures us that the shared objects will see the same instances as the application
    // does
    LanguageST::Get()->SetTagsManager(GetTagsManager());
    TagsManagerST::Get()->SetLanguage(LanguageST::Get());

    // Plugin loading policy
    CodeLiteApp* app = static_cast<CodeLiteApp*>(GetTheApp());
    CodeLiteApp::PluginPolicy pp = app->GetPluginLoadPolicy();
    wxArrayString allowedPlugins;
    if(pp == CodeLiteApp::PP_None) {
        return;
    }

    else if(pp == CodeLiteApp::PP_FromList)
        allowedPlugins = app->GetAllowedPlugins();

    wxString pluginsDir = clStandardPaths::Get().GetPluginsDirectory();
    if(wxDir::Exists(pluginsDir)) {
        // get list of dlls
        wxArrayString files;
        wxDir::GetAllFiles(pluginsDir, &files, fileSpec, wxDIR_FILES);

        // Sort the plugins by A-Z
        std::sort(files.begin(), files.end());
        for(size_t i = 0; i < files.GetCount(); i++) {

            wxString fileName(files.Item(i));
#if defined(__WXMSW__) && !defined(NDEBUG)

            // Under MSW loading a release plugin while in debug mode will cause a crash
            if(!fileName.EndsWith("-dbg.dll")) {
                continue;
            }
#elif defined(__WXMSW__)

            // filter debug plugins
            if(fileName.EndsWith("-dbg.dll")) {
                continue;
            }
#endif

#ifdef __WXGTK__
            wxFileName fnDLL(fileName);
            if(fnDLL.GetFullName().StartsWith("lib")) {
                // don't attempt to load a library
                continue;
            }
#endif

            clDynamicLibrary* dl = new clDynamicLibrary();
            if(!dl->Load(fileName)) {
                CL_ERROR(wxT("Failed to load plugin's dll: ") + fileName);
                if(!dl->GetError().IsEmpty()) {
                    CL_ERROR(dl->GetError());
                }
                wxDELETE(dl);
                continue;
            }

            bool success(false);
            GET_PLUGIN_INFO_FUNC pfnGetPluginInfo = (GET_PLUGIN_INFO_FUNC)dl->GetSymbol(wxT("GetPluginInfo"), &success);
            if(!success) {
                wxDELETE(dl);
                continue;
            }

            // load the plugin version method
            // if the methods does not exist, handle it as if it has value of 100 (lowest version API)
            int interface_version(100);
            GET_PLUGIN_INTERFACE_VERSION_FUNC pfnInterfaceVersion =
                (GET_PLUGIN_INTERFACE_VERSION_FUNC)dl->GetSymbol(wxT("GetPluginInterfaceVersion"), &success);
            if(success) {
                interface_version = pfnInterfaceVersion();
            } else {
                CL_WARNING(wxT("Failed to find GetPluginInterfaceVersion() in dll: ") + fileName);
                if(!dl->GetError().IsEmpty()) {
                    CL_WARNING(dl->GetError());
                }
            }

            if(interface_version != PLUGIN_INTERFACE_VERSION) {
                CL_WARNING(wxString::Format(wxT("Version interface mismatch error for plugin '%s'. Plugin's interface "
                                                "version is '%d', CodeLite interface version is '%d'"),
                                            fileName.c_str(), interface_version, PLUGIN_INTERFACE_VERSION));
                wxDELETE(dl);
                continue;
            }

            // Check if this dll can be loaded
            PluginInfo* pluginInfo = pfnGetPluginInfo();

            wxString pname = pluginInfo->GetName();
            pname.MakeLower().Trim().Trim(false);

            // Check the policy
            if(pp == CodeLiteApp::PP_FromList && allowedPlugins.Index(pname) == wxNOT_FOUND) {
                // Policy is set to 'from list' and this plugin does not match any plugins from
                // the list, don't allow it to be loaded
                wxDELETE(dl);
                continue;
            }

            // If the plugin does not exist in the m_pluginsData, assume its the first time we see it
            bool firstTimeLoading = (m_pluginsData.GetPlugins().count(pluginInfo->GetName()) == 0);

            // Add the plugin information
            m_pluginsData.AddPlugin((*pluginInfo));

            if(firstTimeLoading && pluginInfo->HasFlag(PluginInfo::kDisabledByDefault)) {
                m_pluginsData.DisablePlugin(pluginInfo->GetName());
                wxDELETE(dl);
                continue;
            }

            // Can we load it?
            if(!m_pluginsData.CanLoad(*pluginInfo)) {
                CL_WARNING(wxT("Plugin ") + pluginInfo->GetName() + wxT(" is not enabled"));
                wxDELETE(dl);
                continue;
            }

            // try and load the plugin
            GET_PLUGIN_CREATE_FUNC pfn = (GET_PLUGIN_CREATE_FUNC)dl->GetSymbol(wxT("CreatePlugin"), &success);
            if(!success) {
                CL_WARNING(wxT("Failed to find CreatePlugin() in dll: ") + fileName);
                if(!dl->GetError().IsEmpty()) {
                    CL_WARNING(dl->GetError());
                }

                m_pluginsData.DisablePlugin(pluginInfo->GetName());
                continue;
            }

            // Construct the plugin
            IPlugin* plugin = pfn((IManager*)this);
            CL_DEBUG(wxT("Loaded plugin: ") + plugin->GetLongName());
            m_plugins[plugin->GetShortName()] = plugin;

            // Load the toolbar
            clToolBar* tb = plugin->CreateToolBar(clMainFrame::Get()->GetDockingManager().GetManagedWindow());
            if(tb) {
                // When using AUI toolbars, use our own custom art-provider
                tb->SetArtProvider(new CLMainAuiTBArt());
                clMainFrame::Get()->GetDockingManager().AddPane(tb, wxAuiPaneInfo()
                                                                        .Name(plugin->GetShortName())
                                                                        .LeftDockable(true)
                                                                        .RightDockable(true)
                                                                        .Caption(plugin->GetShortName())
                                                                        .ToolbarPane()
                                                                        .Top()
                                                                        .Position(999));

                // Add menu entry at the 'View->Toolbars' menu for this toolbar
                wxMenuItem* item = clMainFrame::Get()->GetMenuBar()->FindItem(XRCID("toolbars_menu"));
                if(item) {
                    wxMenu* submenu = NULL;
                    submenu = item->GetSubMenu();
                    // add the new toolbar entry at the end of this menu

                    int id = wxNewId();
                    wxString text(plugin->GetShortName());
                    wxMenuItem* newItem = new wxMenuItem(submenu, id, text, wxEmptyString, wxITEM_CHECK);
                    submenu->Append(newItem);
                    clMainFrame::Get()->RegisterToolbar(id, plugin->GetShortName());
                }
            }

            // Keep the dynamic load library
            m_dl.push_back(dl);
        }
        clMainFrame::Get()->GetDockingManager().Update();

        // Let the plugins plug their menu in the 'Plugins' menu at the menu bar
        // the create menu will be placed as a sub menu of the 'Plugin' menu
        wxMenu* pluginsMenu = NULL;
        wxMenuItem* menuitem = clMainFrame::Get()->GetMenuBar()->FindItem(XRCID("manage_plugins"), &pluginsMenu);
        if(pluginsMenu && menuitem) {
            std::map<wxString, IPlugin*>::iterator iter = m_plugins.begin();
            for(; iter != m_plugins.end(); ++iter) {
                IPlugin* plugin = iter->second;
                plugin->CreatePluginMenu(pluginsMenu);
            }
        }

        // save the plugins data
        conf.WriteItem(&m_pluginsData);
    }

    // Now that all the plugins are loaded, load from the configuration file
    // list of visible tabs
    static wxArrayString DefaultArray;
    if(DefaultArray.IsEmpty()) {
        DefaultArray.Add("NOT-FOUND");
    }

    DetachedPanesInfo dpi;
    GetConfigTool()->ReadObject(wxT("DetachedPanesList"), &dpi);
    const wxArrayString& detachedPanes = dpi.GetPanes();

    {
        // Hide workspace tabs
        const wxArrayString& tabs = GetWorkspaceTabs();
        wxArrayString visibleTabs = clConfig::Get().Read("VisibleWorkspaceTabs", DefaultArray);
        if(!((visibleTabs.size() == 1) && (visibleTabs.Item(0) == "NOT-FOUND"))) {
            for(size_t i = 0; i < tabs.size(); ++i) {
                if((visibleTabs.Index(tabs.Item(i)) == wxNOT_FOUND) &&
                   (detachedPanes.Index(tabs.Item(i)) == wxNOT_FOUND)) {
                    // hidden tab - post an event
                    clCommandEvent eventHide(wxEVT_SHOW_WORKSPACE_TAB);
                    eventHide.SetSelected(false).SetString(tabs.Item(i));
                    EventNotifier::Get()->AddPendingEvent(eventHide);
                }
            }
        }
    }

    {
        // Hide output tabs
        const wxArrayString& tabs = GetOutputTabs();
        wxArrayString visibleTabs = clConfig::Get().Read("VisibleOutputTabs", DefaultArray);
        if(!((visibleTabs.size() == 1) && (visibleTabs.Item(0) == "NOT-FOUND"))) {
            for(size_t i = 0; i < tabs.size(); ++i) {
                if((visibleTabs.Index(tabs.Item(i)) == wxNOT_FOUND) &&
                   (detachedPanes.Index(tabs.Item(i)) == wxNOT_FOUND)) {
                    // hidden tab - post an event
                    clCommandEvent eventHide(wxEVT_SHOW_OUTPUT_TAB);
                    eventHide.SetSelected(false).SetString(tabs.Item(i));
                    EventNotifier::Get()->AddPendingEvent(eventHide);
                }
            }
        }
    }
}