@Override public void onEvent(Event event, Object source, Object data) { if (event instanceof ExtensionUpgradedEvent) { InstalledExtension installedExtension = (InstalledExtension) source; try { if (migrationManager.hasAvailableMigrations(installedExtension.getId())) { migrationManager.applyMigrationsForVersion(installedExtension.getId()); } } catch (MigrationException e) { logger.error("Failed to apply extension migrations correctly.", e); } } } }
if (getRequest().getExcludedExtensions().contains(extension.getId())) { return true; if (!extension.isDependency(namespace)) { return false; if (extension.getNamespaces() == null) { hasBackwardDependencies = !this.installedExtensionRepository.getBackwardDependencies(extension.getId()).isEmpty(); } else { hasBackwardDependencies = !this.installedExtensionRepository .getBackwardDependencies(extension.getId().getId(), namespace).isEmpty(); } catch (ResolveException e) { this.logger.error("Failed to gather backward dependencies for extension [{}]", extension.getId(), e);
@Override public void initialize() throws InitializationException { // Load installed extensions for (InstalledExtension extension : this.installedRepository.getInstalledExtensions()) { if (extension.getType().equals(EXTENSION_TYPE)) { if (extension.isInstalled(null)) { extensionAdded(extension, null); } else { for (String namespace : extension.getNamespaces()) { extensionAdded(extension, namespace); } } } } }
@Override public Map<String, Object> provideData() { Collection<InstalledExtension> installedExtensions = this.extensionRepository.getInstalledExtensions(); JSONObject[] extensions = new JSONObject[installedExtensions.size()]; Iterator<InstalledExtension> it = installedExtensions.iterator(); int i = 0; while (it.hasNext()) { InstalledExtension extension = it.next(); Map<String, Object> extensionMap = new HashMap<>(); extensionMap.put(PROPERTY_ID, extension.getId().getId()); extensionMap.put(PROPERTY_VERSION, extension.getId().getVersion().toString()); extensionMap.put(PROPERTY_FEATURES, extension.getFeatures().toArray()); extensions[i] = new JSONObject(extensionMap); i++; } return Collections.singletonMap(PROPERTY_EXTENSIONS, (Object) extensions); } }
@Override public void uninstall(InstalledExtension installedExtension, String namespace, Request request) throws UninstallException { if (installedExtension.isValid(namespace)) { NamespaceURLClassLoader classLoader = this.jarExtensionClassLoader.getURLClassLoader(namespace, false); // There might be no classloading matching the passed namespace when installing a new JAR at the same time // than an upgrade on root if (classLoader != null && StringUtils.equals(namespace, classLoader.getNamespace())) { // unregister components try { unloadComponents(installedExtension.getFile(), classLoader, namespace); } catch (Throwable e) { // We failed to unregister some components, we probably failed to register them in the first // place too so let's just ignore it. Better than making impossible to uninstall the extension. // We catch Throwable because most of the time we end up with a LinkageError this.logger.warn("Failed to unregister some components of the JAR extension [{}]", installedExtension.getId(), e); } // The ClassLoader(s) will be replaced and reloaded at the end of the job // @see org.xwiki.extension.jar.internal.handler.JarExtensionJobFinishedListener } } }
if (installedExtension.isValid(namespace)) { ExtensionId feature = installedExtension.getExtensionFeature(extensionDependency.getId()); this.logger.debug( "There is already an installed extension [{}] covering extension dependency [{}]", installedExtension.getId(), extensionDependency); new ModifableExtensionPlanNode(extensionDependency, versionConstraint); node.setAction(new DefaultExtensionPlanAction(installedExtension, installedExtension, null, Action.NONE, namespace, installedExtension.isDependency(namespace))); if (namespace != null && installedExtension.isInstalled(null)) { if (!getRequest().isRootModificationsAllowed()) { throw new InstallException( String.format("Dependency [%s] is incompatible with installed root extension [%s]", extensionDependency, installedExtension.getId())); if (installedExtension.isInstalled(null)) { Map<String, Collection<InstalledExtension>> backwardDependencies = this.installedExtensionRepository.getBackwardDependencies(installedExtension.getId()); .getBackwardDependencies(installedExtension.getId().getId(), namespace);
if (installedExtension.isInstalled(null)) { try { Map<String, Collection<InstalledExtension>> bDependencies = this.installedExtensionRepository.getBackwardDependencies(installedExtension.getId()); unloadedExtensionsInNamespace.add(installedExtension); } else { for (String namespace2 : installedExtension.getNamespaces()) { unloadJAR(installedExtension, namespace2, unloadedExtensions);
if (installedExtension.getNamespaces() == null || !installedExtension.getNamespaces().contains(namespace)) { throw new UninstallException( String.format(EXCEPTION_NOTINSTALLEDNAMESPACE, installedExtension, namespace)); "Uninstalling extension [" + installedExtension.getId() + "] is not allowed in this job"); extensionHandler = this.componentManager.getInstance(ExtensionHandler.class, installedExtension.getType()); } catch (ComponentLookupException e) { throw new UninstallException(String.format("Unsupported type [%s]", installedExtension.getType()), e); if (namespace != null) { this.logger.info(LOG_RESOLVE_NAMESPACE, "Resolving extension [{}] from namespace [{}]", installedExtension.getId(), namespace); } else { this.logger.info(LOG_RESOLVE, "Resolving extension [{}]", installedExtension.getId());
private NavigableSet<Version> getVersions(InstalledExtension extension, String namespace) { NavigableSet<Version> versionList = new TreeSet<>(); // Search local versions try { IterableResult<Version> versions = this.localExtensionRepository.resolveVersions(extension.getId().getId(), 0, -1); for (Version version : versions) { versionList.add(version); } } catch (ResolveException e) { this.logger.debug("Failed to resolve local versions for extension id [{}]", extension.getId().getId(), e); } // Search remote versions try { IterableResult<Version> versions = this.repositoryManager.resolveVersions(extension.getId().getId(), 0, -1); for (Version version : versions) { versionList.add(version); } } catch (ResolveException e) { this.logger.debug("Failed to resolve remote versions for extension id [{}]", extension.getId().getId(), e); } // Make sure the current version is included if the extension is invalid (it's possible this version does // not exist on any repository) if (!extension.isValid(namespace)) { versionList.add(extension.getId().getVersion()); } return versionList; }
@Override public void initialize(String namespaceToInitialize, String type) { Map<String, Set<InstalledExtension>> initializedExtensions = new HashMap<>(); // Load extensions from local repository Collection<InstalledExtension> installedExtensions; if (namespaceToInitialize != null) { installedExtensions = this.installedExtensionRepository.getInstalledExtensions(namespaceToInitialize); } else { installedExtensions = this.installedExtensionRepository.getInstalledExtensions(); } for (InstalledExtension installedExtension : installedExtensions) { if (type == null || type.equals(installedExtension.getType())) { try { initializeExtension(installedExtension, namespaceToInitialize, initializedExtensions); } catch (Throwable t) { this.logger.error("Failed to initialize local extension [{}]", installedExtension.getId(), t); } } } }
@Override public Collection<InstalledExtension> getInstalledExtensions(String namespace) { List<InstalledExtension> installedExtensions = new ArrayList<InstalledExtension>(extensions.size()); for (InstalledExtension localExtension : this.extensions.values()) { if (localExtension.isInstalled(namespace)) { installedExtensions.add(localExtension); } } return installedExtensions; }
/** * @param installedExtension the existing extension * @param namespace the namespace in which to perform the action * @throws ExtensionException failed to initialize extension */ private void repairExtension(InstalledExtension installedExtension, String namespace) throws ExtensionException { this.observationManager.notify(new ExtensionInstallingEvent(installedExtension.getId(), namespace), installedExtension); boolean success = false; try { // Initialize extension (invalid extensions are not initialized at startup) this.extensionHandlerManager.initialize(installedExtension, namespace); // Repair the extension this.installedExtensionRepository.installExtension(installedExtension, namespace, installedExtension.isDependency(namespace)); success = true; } finally { if (success) { this.observationManager.notify(new ExtensionInstalledEvent(installedExtension.getId(), namespace), installedExtension); } else { this.observationManager.notify(new ExtensionInstallFailedEvent(installedExtension.getId(), namespace), installedExtension); } } }
private void getInstalledExtensions(String feature, Set<InstalledExtension> installedExtensions) { for (InstalledExtension installedExtension : this.installedExtensionRepository.getInstalledExtensions()) { // Check id if (installedExtension.getId().getId().equals(feature)) { installedExtensions.add(installedExtension); continue; } // Check features for (ExtensionId installedFeature : installedExtension.getExtensionFeatures()) if (installedFeature.getId().equals(feature)) { installedExtensions.add(installedExtension); break; } } } }
@Override public Collection<String> getNamespaces() { return getWrapped().getNamespaces(); }
private void unloadJARsFromNamespace(String namespace, Map<String, Set<InstalledExtension>> unloadedExtensions) { Map<String, Set<InstalledExtension>> unloadedExtensionsMap = unloadedExtensions; if (unloadedExtensionsMap == null) { unloadedExtensionsMap = new HashMap<>(); } // Load extensions from local repository Collection<InstalledExtension> installedExtensions; if (namespace != null) { installedExtensions = this.installedExtensionRepository.getInstalledExtensions(namespace); } else { installedExtensions = this.installedExtensionRepository.getInstalledExtensions(); } for (InstalledExtension installedExtension : installedExtensions) { if (JarExtensionHandler.isSupported(installedExtension.getType())) { if (namespace == null || !installedExtension.isInstalled(null)) { try { unloadJAR(installedExtension, namespace, unloadedExtensionsMap); } catch (Exception e) { this.logger.error("Failed to unload installed extension [{}]", installedExtension, e); } } } } }
private Extension checkInstalledExtension(Extension extension, String namespace) throws InstallException { // Check if the extension conflict with an extension installed on root namespace if (namespace != null) { checkRootExtension(extension); } // Check if the exact same valid extension is already installed on target namespace InstalledExtension installedExtension = this.installedExtensionRepository.getInstalledExtension(extension.getId()); if (installedExtension != null && installedExtension.isInstalled(namespace)) { if (installedExtension.isValid(namespace)) { throw new InstallException(String.format("Extension [%s] is already installed on namespace [%s]", extension.getId(), namespace)); } // In case the extension is already installed on the namespace but is invalid continue with it to make clear // to following code we are actually repairing it return installedExtension; } return extension; }
@Override public boolean isDependency(String namespace) { return getWrapped().isDependency(namespace); }
Set<InstalledExtension> initializedExtensionsInNamespace) throws ExtensionException if (namespace != null && installedExtension.getNamespaces() == null) { } else { for (ExtensionDependency dependency : installedExtension.getDependencies()) { if (!this.coreExtensionRepository.exists(dependency.getId())) { InstalledExtension dependencyExtension =
@Override public boolean isValid(String namespace) { return getWrapped().isValid(namespace); }
private void onExtensionRemovedEvent(ExtensionEvent event, InstalledExtension extension) { if (JarExtensionHandler.isSupported(extension.getType())) { addUninstalledExtension(event.getNamespace()); } }