| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| var Q = require('q'); |
| var fs = require('fs-extra'); |
| var path = require('path'); |
| |
| var ActionStack = require('./ActionStack'); |
| var PlatformJson = require('./PlatformJson'); |
| var CordovaError = require('./CordovaError/CordovaError'); |
| var PlatformMunger = require('./ConfigChanges/ConfigChanges').PlatformMunger; |
| var PluginInfoProvider = require('./PluginInfo/PluginInfoProvider'); |
| |
| /** |
| * @constructor |
| * @class PluginManager |
| * Represents an entity for adding/removing plugins for platforms |
| * |
| * @param {String} platform Platform name |
| * @param {Object} locations - Platform files and directories |
| * @param {IDEProject} ideProject The IDE project to add/remove plugin changes to/from |
| */ |
| function PluginManager (platform, locations, ideProject) { |
| this.platform = platform; |
| this.locations = locations; |
| this.project = ideProject; |
| |
| var platformJson = PlatformJson.load(locations.root, platform); |
| this.munger = new PlatformMunger(platform, locations.root, platformJson, new PluginInfoProvider()); |
| } |
| |
| /** |
| * @constructs PluginManager |
| * A convenience shortcut to new PluginManager(...) |
| * |
| * @param {String} platform Platform name |
| * @param {Object} locations - Platform files and directories |
| * @param {IDEProject} ideProject The IDE project to add/remove plugin changes to/from |
| * @returns new PluginManager instance |
| */ |
| PluginManager.get = function (platform, locations, ideProject) { |
| return new PluginManager(platform, locations, ideProject); |
| }; |
| |
| PluginManager.INSTALL = 'install'; |
| PluginManager.UNINSTALL = 'uninstall'; |
| |
| module.exports = PluginManager; |
| |
| /** |
| * Describes and implements common plugin installation/uninstallation routine. The flow is the following: |
| * * Validate and set defaults for options. Note that options are empty by default. Everything |
| * needed for platform IDE project must be passed from outside. Plugin variables (which |
| * are the part of the options) also must be already populated with 'PACKAGE_NAME' variable. |
| * * Collect all plugin's native and web files, get installers/uninstallers and process |
| * all these via ActionStack. |
| * * Save the IDE project, so the changes made by installers are persisted. |
| * * Generate config changes munge for plugin and apply it to all required files |
| * * Generate metadata for plugin and plugin modules and save it to 'cordova_plugins.js' |
| * |
| * @param {PluginInfo} plugin A PluginInfo structure representing plugin to install |
| * @param {Object} [options={}] An installation options. It is expected but is not necessary |
| * that options would contain 'variables' inner object with 'PACKAGE_NAME' field set by caller. |
| * |
| * @returns {Promise} Returns a Q promise, either resolved in case of success, rejected otherwise. |
| */ |
| PluginManager.prototype.doOperation = function (operation, plugin, options) { |
| if (operation !== PluginManager.INSTALL && operation !== PluginManager.UNINSTALL) { return Q.reject(new CordovaError('The parameter is incorrect. The opeation must be either "add" or "remove"')); } |
| |
| if (!plugin || plugin.constructor.name !== 'PluginInfo') { return Q.reject(new CordovaError('The parameter is incorrect. The first parameter should be a PluginInfo instance')); } |
| |
| // Set default to empty object to play safe when accesing properties |
| options = options || {}; |
| |
| var self = this; |
| var actions = new ActionStack(); |
| |
| // gather all files need to be handled during operation ... |
| plugin.getFilesAndFrameworks(this.platform, options) |
| .concat(plugin.getAssets(this.platform)) |
| .concat(plugin.getJsModules(this.platform)) |
| // ... put them into stack ... |
| .forEach(function (item) { |
| var installer = self.project.getInstaller(item.itemType); |
| var uninstaller = self.project.getUninstaller(item.itemType); |
| var actionArgs = [item, plugin, self.project, options]; |
| |
| var action; |
| if (operation === PluginManager.INSTALL) { |
| action = actions.createAction.apply(actions, [installer, actionArgs, uninstaller, actionArgs]); /* eslint no-useless-call: 0 */ |
| } else /* op === PluginManager.UNINSTALL */{ |
| action = actions.createAction.apply(actions, [uninstaller, actionArgs, installer, actionArgs]); /* eslint no-useless-call: 0 */ |
| } |
| actions.push(action); |
| }); |
| |
| // ... and run through the action stack |
| return actions.process(this.platform) |
| .then(function () { |
| if (self.project.write) { |
| self.project.write(); |
| } |
| |
| if (operation === PluginManager.INSTALL) { |
| // Ignore passed `is_top_level` option since platform itself doesn't know |
| // anything about managing dependencies - it's responsibility of caller. |
| self.munger.add_plugin_changes(plugin, options.variables, /* is_top_level= */true, /* should_increment= */true, options.force); |
| self.munger.platformJson.addPluginMetadata(plugin); |
| } else { |
| self.munger.remove_plugin_changes(plugin, /* is_top_level= */true); |
| self.munger.platformJson.removePluginMetadata(plugin); |
| } |
| |
| // Save everything (munge and plugin/modules metadata) |
| self.munger.save_all(); |
| |
| var metadata = self.munger.platformJson.generateMetadata(); |
| fs.writeFileSync(path.join(self.locations.www, 'cordova_plugins.js'), metadata, 'utf-8'); |
| |
| // CB-11022 save plugin metadata to both www and platform_www if options.usePlatformWww is specified |
| if (options.usePlatformWww) { |
| fs.writeFileSync(path.join(self.locations.platformWww, 'cordova_plugins.js'), metadata, 'utf-8'); |
| } |
| }); |
| }; |
| |
| PluginManager.prototype.addPlugin = function (plugin, installOptions) { |
| return this.doOperation(PluginManager.INSTALL, plugin, installOptions); |
| }; |
| |
| PluginManager.prototype.removePlugin = function (plugin, uninstallOptions) { |
| return this.doOperation(PluginManager.UNINSTALL, plugin, uninstallOptions); |
| }; |