summaryrefslogtreecommitdiffstats
path: root/src/extension/loader.cpp
blob: 8893f3f1d3a1e7bcbec22d50d87fb035ab6f366f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * Loader for external plug-ins.
 *
 * Authors:
 *   Moritz Eberl <moritz@semiodesk.com>
 *
 * Copyright (C) 2016 Authors
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#include "loader.h"
#include "system.h"
#include <exception>
#include <string.h>
#include "dependency.h"

namespace Inkscape {
namespace Extension {

typedef Implementation::Implementation *(*_getImplementation)(void);

bool Loader::load_dependency(Dependency *dep)
{
    GModule *module = NULL;
    module = g_module_open(dep->get_name(), (GModuleFlags)0);
    if (module == NULL) {
        return false;
    }
    return true;
}

/**
 * @brief Load the actual implementation of a plugin supplied by the plugin.
 * @param doc The xml representation of the INX extension configuration.
 * @return The implementation of the extension loaded from the plugin.
 */
Implementation::Implementation *Loader::load_implementation(Inkscape::XML::Document *doc)
{
    try {
        Inkscape::XML::Node *repr = doc->root();
        Inkscape::XML::Node *child_repr = repr->firstChild();
        while (child_repr != NULL) {
            char const *chname = child_repr->name();
            if (!strncmp(chname, INKSCAPE_EXTENSION_NS_NC, strlen(INKSCAPE_EXTENSION_NS_NC))) {
                chname += strlen(INKSCAPE_EXTENSION_NS);
            }

            if (!strcmp(chname, "dependency")) {
                Dependency dep = Dependency(child_repr);
                bool success = load_dependency(&dep);
                if( !success ){
                    const char *res = g_module_error();
                    g_warning("Unable to load dependency %s of plugin %s.\nDetails: %s\n", dep.get_name(), res);
                    return NULL;
                }
            } 

            if (!strcmp(chname, "plugin")) {
                if (const gchar *name = child_repr->attribute("name")) {
                    GModule *module = NULL;
                    _getImplementation GetImplementation = NULL;
                    gchar *path = g_build_filename(_baseDirectory, name, (char *) NULL);
                    module = g_module_open(path, G_MODULE_BIND_LOCAL);
                    g_free(path);
                    if (module == NULL) {
                        const char *res = g_module_error();
                        g_warning("Unable to load extension %s.\nDetails: %s\n", name, res);
                        return NULL;
                    }

                    if (g_module_symbol(module, "GetImplementation", (gpointer *) &GetImplementation) == FALSE) {
                        const char *res = g_module_error();
                        g_warning("Unable to load extension %s.\nDetails: %s\n", name, res);
                        return NULL;
                    }

                    Implementation::Implementation *i = GetImplementation();
                    return i;
                }
            } 

            child_repr = child_repr->next();
        }
    } catch (std::exception &e) {
        g_warning("Unable to load extension.");
    }
    return NULL;
}

} // namespace Extension
} // namespace Inkscape

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace .0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99: