/*
* 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.
*/
package org.apache.nifi.util;
import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.bundle.BundleCoordinate;
import org.apache.nifi.nar.ExtensionManager;
import org.apache.nifi.web.api.dto.BundleDTO;
import java.util.List;
import java.util.stream.Collectors;
/**
* Utility class for Bundles.
*/
public final class BundleUtils {
private static BundleCoordinate findBundleForType(final String type, final BundleCoordinate desiredCoordinate) {
final List<Bundle> bundles = ExtensionManager.getBundles(type);
if (bundles.isEmpty()) {
throw new IllegalStateException(String.format("%s is not known to this NiFi instance.", type));
} else if (bundles.size() > 1) {
if (desiredCoordinate == null) {
throw new IllegalStateException(String.format("Multiple versions of %s exist.", type));
} else {
throw new IllegalStateException(String.format("Multiple versions of %s exist. No exact match for %s.", type, desiredCoordinate));
}
} else {
return bundles.get(0).getBundleDetails().getCoordinate();
}
}
private static BundleCoordinate findCompatibleBundle(final String type, final BundleDTO bundleDTO, final boolean allowCompatibleBundle) {
final BundleCoordinate coordinate = new BundleCoordinate(bundleDTO.getGroup(), bundleDTO.getArtifact(), bundleDTO.getVersion());
final Bundle bundle = ExtensionManager.getBundle(coordinate);
if (bundle == null) {
if (allowCompatibleBundle) {
return findBundleForType(type, coordinate);
} else {
throw new IllegalStateException(String.format("%s from %s is not known to this NiFi instance.", type, coordinate));
}
} else {
final List<BundleCoordinate> bundlesForType = ExtensionManager.getBundles(type).stream().map(b -> b.getBundleDetails().getCoordinate()).collect(Collectors.toList());
if (bundlesForType.contains(coordinate)) {
return coordinate;
} else {
throw new IllegalStateException(String.format("Found bundle %s but does not support %s", coordinate, type));
}
}
}
/**
* Gets a bundle that supports the specified type. If the bundle is specified, an
* exact match must be available.
*
* <ul>
* <li>If bundleDTO is specified</li>
* <ul>
* <li>Matching bundle found</li>
* <ul>
* <li>If bundle supports type, use it</li>
* <li>If bundle doesn't support type, throw IllegalStateException</li>
* </ul>
* <li>No matching bundle found, IllegalStateException</li>
* </ul>
* <li>If bundleDTO is not specified</li>
* <ul>
* <li>One bundle that supports the specified type, use it</li>
* <li>No bundle that supports the specified type, IllegalStateException</li>
* <li>Multiple bundle that supports the specified type, IllegalStateException</li>
* </ul>
* </ul>
*
* @param type the component type
* @param bundleDTO bundle to find the component
* @return the bundle coordinate
* @throws IllegalStateException bundle not found
*/
public static BundleCoordinate getBundle(final String type, final BundleDTO bundleDTO) {
if (bundleDTO == null) {
return findBundleForType(type, null);
} else {
return findCompatibleBundle(type, bundleDTO, false);
}
}
/**
* Gets a compatible bundle that supports the specified type. If the bundle is
* specified but is not available, a compatible bundle may be returned if there
* is only one.
*
* <ul>
* <li>If bundleDTO is specified</li>
* <ul>
* <li>Matching bundle found</li>
* <ul>
* <li>If bundle supports type, use it</li>
* <li>If bundle doesn't support type, throw IllegalStateException</li>
* </ul>
* <li>No matching bundle found</li>
* <ul>
* <li>One bundle that supports the specified type, use it</li>
* <li>No bundle that supports the specified type, IllegalStateException</li>
* <li>Multiple bundle that supports the specified type, IllegalStateException</li>
* </ul>
* </ul>
* <li>If bundleDTO is not specified</li>
* <ul>
* <li>One bundle that supports the specified type, use it</li>
* <li>No bundle that supports the specified type, IllegalStateException</li>
* <li>Multiple bundle that supports the specified type, IllegalStateException</li>
* </ul>
* </ul>
*
* @param type the component type
* @param bundleDTO bundle to find the component
* @return the bundle coordinate
* @throws IllegalStateException no compatible bundle found
*/
public static BundleCoordinate getCompatibleBundle(final String type, final BundleDTO bundleDTO) {
if (bundleDTO == null) {
return findBundleForType(type, null);
} else {
return findCompatibleBundle(type, bundleDTO, true);
}
}
}