@Override
    public PluginBean create(NewPluginBean bean) throws PluginAlreadyExistsException, PluginNotFoundException, NotAuthorizedException {
        securityContext.checkAdminPermissions();

        PluginCoordinates coordinates = new PluginCoordinates(bean.getGroupId(), bean.getArtifactId(), bean.getVersion(),
                bean.getClassifier(), bean.getType());

        boolean isSnapshot = PluginUtils.isSnapshot(coordinates);
        if (isSnapshot) {
            LOGGER.debug("Loading a snapshot version of plugin: " + coordinates); //$NON-NLS-1$
        }
        boolean isUpgrade = isSnapshot || bean.isUpgrade();

        Plugin plugin;
        try {
            plugin = pluginRegistry.loadPlugin(coordinates);
            bean.setName(plugin.getName());
            bean.setDescription(plugin.getDescription());
        } catch (InvalidPluginException e) {
            throw new PluginNotFoundException(coordinates.toString(), e);
        }

        PluginBean pluginBean = new PluginBean();
        pluginBean.setGroupId(bean.getGroupId());
        pluginBean.setArtifactId(bean.getArtifactId());
        pluginBean.setVersion(bean.getVersion());
        pluginBean.setClassifier(bean.getClassifier());
        pluginBean.setType(bean.getType());
        pluginBean.setName(bean.getName());
        pluginBean.setDescription(bean.getDescription());
        pluginBean.setCreatedBy(securityContext.getCurrentUser());
        pluginBean.setCreatedOn(new Date());
        try {
            PluginBean existingPlugin = storage.getPlugin(bean.getGroupId(), bean.getArtifactId());

            boolean hasExistingPlugin = existingPlugin != null && !existingPlugin.isDeleted();
            boolean isUpdatePolicyDefs = false;

            if (hasExistingPlugin && !isUpgrade) {
                throw ExceptionFactory.pluginAlreadyExistsException();
            } else if (hasExistingPlugin && isUpgrade) {
                isUpdatePolicyDefs = true;
                existingPlugin.setName(pluginBean.getName());
                existingPlugin.setDescription(pluginBean.getDescription());
                existingPlugin.setVersion(pluginBean.getVersion());
                existingPlugin.setClassifier(pluginBean.getClassifier());
                existingPlugin.setType(pluginBean.getType());
                pluginBean.setId(existingPlugin.getId());
                storage.updatePlugin(existingPlugin);
            } else if (!hasExistingPlugin && existingPlugin != null) {
                isUpdatePolicyDefs = true;
                existingPlugin.setName(pluginBean.getName());
                existingPlugin.setDescription(pluginBean.getDescription());
                existingPlugin.setVersion(pluginBean.getVersion());
                existingPlugin.setClassifier(pluginBean.getClassifier());
                existingPlugin.setType(pluginBean.getType());
                existingPlugin.setCreatedOn(new Date());
                existingPlugin.setCreatedBy(securityContext.getCurrentUser());
                existingPlugin.setDeleted(false);
                pluginBean.setId(existingPlugin.getId());
                storage.updatePlugin(existingPlugin);
            } else {
                if (bean.isUpgrade()) {
                    throw ExceptionFactory.pluginNotFoundException(0L);
                }
                storage.createPlugin(pluginBean);
            }

            // Process any contributed policy definitions.
            List<URL> policyDefs = plugin.getPolicyDefinitions();
            int createdPolicyDefCounter = 0;
            int updatedPolicyDefCounter = 0;
            for (URL url : policyDefs) {
                PolicyDefinitionBean policyDef = (PolicyDefinitionBean) MAPPER.reader(PolicyDefinitionBean.class).readValue(url);
                if (policyDef.getId() == null || policyDef.getId().trim().isEmpty()) {
                    throw ExceptionFactory.policyDefInvalidException(Messages.i18n.format("PluginResourceImpl.MissingPolicyDefId", policyDef.getName())); //$NON-NLS-1$
                }
                policyDef.setPluginId(pluginBean.getId());
                if (policyDef.getId() == null) {
                    policyDef.setId(BeanUtils.idFromName(policyDef.getName()));
                } else {
                    policyDef.setId(BeanUtils.idFromName(policyDef.getId()));
                }
                if (policyDef.getFormType() == null) {
                    policyDef.setFormType(PolicyFormType.Default);
                }
                PolicyDefinitionBean existingPolicyDef = storage.getPolicyDefinition(policyDef.getId());
                if (existingPolicyDef == null) {
                    storage.createPolicyDefinition(policyDef);
                    createdPolicyDefCounter++;
                } else if (isUpdatePolicyDefs) {
                    existingPolicyDef.setName(policyDef.getName());
                    existingPolicyDef.setDescription(policyDef.getDescription());
                    existingPolicyDef.setIcon(policyDef.getIcon());
                    existingPolicyDef.getTemplates().clear();
                    existingPolicyDef.getTemplates().addAll(policyDef.getTemplates());
                    existingPolicyDef.setFormType(policyDef.getFormType());
                    existingPolicyDef.setForm(policyDef.getForm());
                    existingPolicyDef.setDeleted(false);
                    existingPolicyDef.setPolicyImpl(policyDef.getPolicyImpl());
                    storage.updatePolicyDefinition(existingPolicyDef);
                    updatedPolicyDefCounter++;
                } else {
                    throw ExceptionFactory.policyDefInvalidException(Messages.i18n.format("PluginResourceImpl.DuplicatePolicyDef", policyDef.getId())); //$NON-NLS-1$
                }
            }

            LOGGER.info(String.format("Created plugin mvn:%s:%s:%s", pluginBean.getGroupId(), pluginBean.getArtifactId(),  //$NON-NLS-1$
                    pluginBean.getVersion()));
            LOGGER.info(String.format("\tCreated %s policy definitions from plugin.", String.valueOf(createdPolicyDefCounter))); //$NON-NLS-1$
            if (isUpdatePolicyDefs) {
                LOGGER.info(String.format("\tUpdated %s policy definitions from plugin.", String.valueOf(updatedPolicyDefCounter))); //$NON-NLS-1$
            }
        } catch (AbstractRestException e) {
            throw e;
        } catch (Exception e) {
            throw new SystemErrorException(e);
        }
        return pluginBean;
    }
@see IPluginResource#create(io.apiman.manager.api.beans.plugins.NewPluginBean)
manager/api/rest-impl/src/main/java/io/apiman/manager/api/rest/impl/PluginResourceImpl.java