1 /******************************************************************************
2
3 This source file is part of the Avogadro project.
4
5 Copyright 2012 Kitware, Inc.
6
7 This source code is released under the New BSD License, (the "License").
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14
15 ******************************************************************************/
16
17 #include "pluginmanager.h"
18
19 #include "molequeueconfig.h"
20
21 #include <molequeue/servercore/connectionlistenerfactory.h>
22
23 #include <QtCore/QCoreApplication>
24 #include <QtCore/QMutex>
25 #include <QtCore/QPluginLoader>
26 #include <QtCore/QDir>
27 #include <QtCore/QFileInfo>
28
29 #include <QtCore/QDebug>
30
31 namespace MoleQueue
32 {
33
34 namespace
35 {
36 // Compiler initializes this static pointer to 0.
37 static PluginManager *pluginManagerInstance;
38 }
39
PluginManager(QObject * p)40 PluginManager::PluginManager(QObject *p) : QObject(p)
41 {
42 QString libDir(MoleQueue_LIB_DIR);
43 // http://doc.qt.digia.com/qt/deployment-plugins.html#debugging-plugins
44 bool debugPlugins = !qgetenv("QT_DEBUG_PLUGINS").isEmpty();
45 QDir baseDir(QCoreApplication::applicationDirPath() + "/..");
46 m_relativeToApp = "/../" + libDir + "/molequeue/plugins";
47 #ifdef __APPLE__
48 // But if NOT running from the installed bundle on the Mac, the plugins are
49 // relative to the build directory instead:
50 if (!QFileInfo(baseDir.absolutePath() + "/Resources/qt.conf").exists()) {
51 QDir buildDir(QCoreApplication::applicationDirPath() + "/../../../..");
52 baseDir = buildDir;
53 if (debugPlugins)
54 qDebug() << " using buildDir:" << buildDir.absolutePath();
55 }
56 #endif
57
58 // For multi configuration types add correct one to search path.
59 #ifdef MULTI_CONFIG_BUILD
60 // First extract the build type (the name of the application dir).
61 QDir appDir(QCoreApplication::applicationDirPath());
62 QString buildType = appDir.dirName();
63
64 QDir condir(QCoreApplication::applicationDirPath()
65 + "/../../" + libDir + "/molequeue/plugins/" + buildType);
66 m_pluginDirs.append(condir.absolutePath());
67 #endif
68 // If the environment variable is set, use that as the base directory.
69 QByteArray pluginDir = qgetenv("MOLEQUEUE_PLUGIN_DIR");
70 if (!pluginDir.isEmpty())
71 baseDir.setPath(pluginDir);
72 if (debugPlugins)
73 qDebug() << " baseDir:" << baseDir.absolutePath();
74 QDir pluginsDir(baseDir.absolutePath() + "/" + libDir + "/molequeue/plugins");
75 m_pluginDirs.append(pluginsDir.absolutePath());
76 if (debugPlugins) {
77 qDebug() << " pluginsDir:" << pluginsDir.absolutePath();
78 int count = 0;
79 foreach(const QString &pluginPath, pluginsDir.entryList(QDir::Files)) {
80 ++count;
81 qDebug() << " " << pluginsDir.absolutePath() + "/" + pluginPath;
82 }
83
84 if (count > 0)
85 qDebug() << " " << count << "files found in" << pluginsDir.absolutePath();
86 else
87 qDebug() << " no plugin files found in" << pluginsDir.absolutePath();
88 }
89 }
90
~PluginManager()91 PluginManager::~PluginManager()
92 {
93 }
94
instance()95 PluginManager * PluginManager::instance()
96 {
97 static QMutex mutex;
98 if (!pluginManagerInstance) {
99 mutex.lock();
100 if (!pluginManagerInstance)
101 pluginManagerInstance = new PluginManager(QCoreApplication::instance());
102 mutex.unlock();
103 }
104 return pluginManagerInstance;
105 }
106
load()107 void PluginManager::load()
108 {
109 foreach(const QString &dir, m_pluginDirs)
110 load(dir);
111 }
112
load(const QString & path)113 void PluginManager::load(const QString &path)
114 {
115 QDir dir(path);
116 qDebug() << "Checking for plugins in" << path;
117 qDebug() << dir.entryList(QDir::Files);
118 foreach(const QString &pluginPath, dir.entryList(QDir::Files)) {
119 QPluginLoader pluginLoader(dir.absolutePath() + QDir::separator() + pluginPath);
120
121 if (pluginLoader.isLoaded()) {
122 qDebug() << "Plugin already loaded: " << pluginLoader.fileName();
123 continue;
124 }
125
126 QObject *pluginInstance = pluginLoader.instance();
127
128 // Check if the plugin loaded correctly. Keep debug output for now, should
129 // go away once we have verified this (or added to a logger).
130 if (!pluginInstance) {
131 qDebug() << "Failed to load" << pluginPath << "error"
132 << pluginLoader.errorString();
133 }
134 else {
135 qDebug() << "Loaded" << pluginPath << "->";
136 pluginInstance->dumpObjectInfo();
137 }
138
139 // Now attempt to cast to known factory types, and make it available.
140 ConnectionListenerFactory *connectionListenerFactory =
141 qobject_cast<ConnectionListenerFactory *>(pluginInstance);
142 if (connectionListenerFactory &&
143 !m_connectionListenerFactories.contains(connectionListenerFactory))
144 m_connectionListenerFactories.append(connectionListenerFactory);
145 }
146 }
147
connectionListenerFactories() const148 QList<ConnectionListenerFactory *> PluginManager::connectionListenerFactories() const
149 {
150 return m_connectionListenerFactories;
151 }
152
153 } // End MoleQueue namespace
154