diff --git a/src/main/java/org/apache/nifi/flow/Bundle.java b/src/main/java/org/apache/nifi/flow/Bundle.java index ddfd567..ec9d1a2 100644 --- a/src/main/java/org/apache/nifi/flow/Bundle.java +++ b/src/main/java/org/apache/nifi/flow/Bundle.java @@ -25,14 +25,24 @@ public class Bundle { private String group; private String artifact; private String version; + private boolean isRemote; + private String dependencyGroup; + private String dependencyArtifact; + private String dependencyVersion; + private String systemApiVersion; public Bundle() { } public Bundle(final String group, final String artifact, final String version) { + this(group, artifact, version, false); + } + + public Bundle(final String group, final String artifact, final String version, final boolean isRemote) { this.group = group; this.artifact = artifact; this.version = version; + this.isRemote = isRemote; } @Schema(description = "The group of the bundle") @@ -62,6 +72,51 @@ public void setVersion(String version) { this.version = version; } + @Schema(description = "If the bundle is currently remote or not") + public boolean isRemote() { + return isRemote; + } + + public void setRemote(final boolean isRemote) { + this.isRemote = isRemote; + } + + @Schema(description = "If present, the group of the bundle this bundle depends on (Nar-Dependency-Group).") + public String getDependencyGroup() { + return dependencyGroup; + } + + public void setDependencyGroup(final String dependencyGroup) { + this.dependencyGroup = dependencyGroup; + } + + @Schema(description = "If present, the artifact of the bundle this bundle depends on (Nar-Dependency-Id).") + public String getDependencyArtifact() { + return dependencyArtifact; + } + + public void setDependencyArtifact(final String dependencyArtifact) { + this.dependencyArtifact = dependencyArtifact; + } + + @Schema(description = "If present, the version of the bundle this bundle depends on (Nar-Dependency-Version).") + public String getDependencyVersion() { + return dependencyVersion; + } + + public void setDependencyVersion(final String dependencyVersion) { + this.dependencyVersion = dependencyVersion; + } + + @Schema(description = "The NiFi system API version this bundle targets, as declared in the extension manifest.") + public String getSystemApiVersion() { + return systemApiVersion; + } + + public void setSystemApiVersion(final String systemApiVersion) { + this.systemApiVersion = systemApiVersion; + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/src/main/java/org/apache/nifi/flow/resource/ExternalResourceConflictResolutionStrategy.java b/src/main/java/org/apache/nifi/flow/resource/ExternalResourceConflictResolutionStrategy.java index 85f781d..fe130ae 100644 --- a/src/main/java/org/apache/nifi/flow/resource/ExternalResourceConflictResolutionStrategy.java +++ b/src/main/java/org/apache/nifi/flow/resource/ExternalResourceConflictResolutionStrategy.java @@ -20,7 +20,9 @@ /** * Might be used by provider service in order to decide if an available resource should be acquired from the external provider. + * @deprecated This interface is deprecated and will be removed in a future release. Use {@link org.apache.nifi.registry.extension.ExtensionRegistryClient} instead */ +@Deprecated(forRemoval = true) public interface ExternalResourceConflictResolutionStrategy { /** * @param targetDirectory The target directory. diff --git a/src/main/java/org/apache/nifi/flow/resource/ExternalResourceDescriptor.java b/src/main/java/org/apache/nifi/flow/resource/ExternalResourceDescriptor.java index ed832c8..adf4a5b 100644 --- a/src/main/java/org/apache/nifi/flow/resource/ExternalResourceDescriptor.java +++ b/src/main/java/org/apache/nifi/flow/resource/ExternalResourceDescriptor.java @@ -18,7 +18,9 @@ /** * Describes an available resource might be fetched from the external source. + * @deprecated This interface is deprecated and will be removed in a future release. Use {@link org.apache.nifi.registry.extension.ExtensionRegistryClient} instead */ +@Deprecated(forRemoval = true) public interface ExternalResourceDescriptor { /** diff --git a/src/main/java/org/apache/nifi/flow/resource/ExternalResourceProvider.java b/src/main/java/org/apache/nifi/flow/resource/ExternalResourceProvider.java index 7cf7c96..113b7d5 100644 --- a/src/main/java/org/apache/nifi/flow/resource/ExternalResourceProvider.java +++ b/src/main/java/org/apache/nifi/flow/resource/ExternalResourceProvider.java @@ -23,7 +23,9 @@ /** * Represents an external source where the resource files might be acquired from. These external resources might be * various: database drivers, different kind of configurations and so on. + * @deprecated This interface is deprecated and will be removed in a future release. Use {@link org.apache.nifi.registry.extension.ExtensionRegistryClient} instead */ +@Deprecated(forRemoval = true) public interface ExternalResourceProvider { /** diff --git a/src/main/java/org/apache/nifi/flow/resource/ExternalResourceProviderInitializationContext.java b/src/main/java/org/apache/nifi/flow/resource/ExternalResourceProviderInitializationContext.java index 196f689..214bff7 100644 --- a/src/main/java/org/apache/nifi/flow/resource/ExternalResourceProviderInitializationContext.java +++ b/src/main/java/org/apache/nifi/flow/resource/ExternalResourceProviderInitializationContext.java @@ -22,7 +22,9 @@ /** * Contains necessary information for extensions of external resource provider functionality. + * @deprecated This interface is deprecated and will be removed in a future release. Use {@link org.apache.nifi.registry.extension.ExtensionRegistryClient} instead */ +@Deprecated(forRemoval = true) public interface ExternalResourceProviderInitializationContext { /** diff --git a/src/main/java/org/apache/nifi/registry/extension/AbstractExtensionRegistryClient.java b/src/main/java/org/apache/nifi/registry/extension/AbstractExtensionRegistryClient.java new file mode 100644 index 0000000..490c476 --- /dev/null +++ b/src/main/java/org/apache/nifi/registry/extension/AbstractExtensionRegistryClient.java @@ -0,0 +1,51 @@ +/* + * 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.registry.extension; + +import org.apache.nifi.components.AbstractConfigurableComponent; +import org.apache.nifi.logging.ComponentLog; + +import javax.net.ssl.SSLContext; + +import java.util.Optional; + +public abstract class AbstractExtensionRegistryClient extends AbstractConfigurableComponent implements ExtensionRegistryClient { + + private volatile String identifier; + private volatile Optional systemSslContext; + private volatile ComponentLog logger; + + @Override + public void initialize(final ExtensionRegistryClientInitializationContext context) { + this.identifier = context.getIdentifier(); + this.logger = context.getLogger(); + this.systemSslContext = context.getSystemSslContext(); + } + + @Override + public final String getIdentifier() { + return identifier; + } + + protected final ComponentLog getLogger() { + return logger; + } + + protected final Optional getSystemSslContext() { + return systemSslContext; + } +} diff --git a/src/main/java/org/apache/nifi/registry/extension/ExtensionBundleMetadata.java b/src/main/java/org/apache/nifi/registry/extension/ExtensionBundleMetadata.java new file mode 100644 index 0000000..d6b8494 --- /dev/null +++ b/src/main/java/org/apache/nifi/registry/extension/ExtensionBundleMetadata.java @@ -0,0 +1,38 @@ +/* + * 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.registry.extension; + +import org.apache.nifi.flow.Bundle; + +import java.io.InputStream; + +/** + * Metadata about a remotely available bundle, including its dependency coordinate and manifest contents. + * Implementations may choose to lazily stream the manifest InputStream; callers are responsible for closing it. + */ +public interface ExtensionBundleMetadata { + + /** + * @return the bundle coordinates (including dependency if populated) + */ + Bundle getBundle(); + + /** + * @return InputStream for the extension manifest (META-INF/docs/extension-manifest.xml). Caller must close. + */ + InputStream getExtensionManifest(); +} diff --git a/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClient.java b/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClient.java new file mode 100644 index 0000000..240c33b --- /dev/null +++ b/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClient.java @@ -0,0 +1,109 @@ +/* + * 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.registry.extension; + +import org.apache.nifi.components.ConfigurableComponent; +import org.apache.nifi.flow.Bundle; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Set; + +/** + *

+ * Represents an external source from which NiFi extension bundles (NARs) can be + * discovered, inspected, and retrieved at runtime. The interface allows multiple + * types of registries to back NiFi (local filesystem, Maven repositories, cloud + * storage, etc.). + *

+ * + *

+ * Implementations are packaged as NARs and configured via {@code nifi.properties} + * using a prefix-based multi-provider convention. Each provider must: + *

+ * + * + * + *

+ * After {@link #initialize(ExtensionRegistryClientInitializationContext)} is called, + * implementations should expect incoming requests at any time. The request methods + * receive an {@link ExtensionRegistryClientConfigurationContext} that always reflects + * the current state of the configured properties. Caching properties between method + * calls is not recommended. + *

+ * + *

Implementation Note: This API is currently experimental, as it is under + * very active development. As such, it is subject to change without notice between + * minor releases.

+ */ +public interface ExtensionRegistryClient extends ConfigurableComponent { + + /** + * Initializes the extension registry client with the given context. + * + * @param context the context + */ + void initialize(ExtensionRegistryClientInitializationContext context); + + /** + * Returns the NAR file for the given bundle. + * + * @param context the context + * @param bundle the bundle + * @return the NAR file + * @throws ExtensionRegistryException if an error occurs + * @throws IOException if an error occurs + */ + InputStream getNARFile(ExtensionRegistryClientConfigurationContext context, Bundle bundle) throws ExtensionRegistryException, IOException; + + /** + * Returns the manifest file for the given bundle. + * + * @param context the context + * @param bundle the bundle + * @return the manifest file + * @throws ExtensionRegistryException if an error occurs + * @throws IOException if an error occurs + */ + InputStream getManifestFile(ExtensionRegistryClientConfigurationContext context, Bundle bundle) throws ExtensionRegistryException, IOException; + + /** + * Returns the list of bundles. + * + * @param context the context + * @return the list of bundles + * @throws ExtensionRegistryException if an error occurs + * @throws IOException if an error occurs + */ + Set listBundles(ExtensionRegistryClientConfigurationContext context) throws ExtensionRegistryException, IOException; + + /** + * Returns metadata for a bundle, including its dependency coordinate and extension manifest stream. This allows callers to + * build dependency graphs without downloading the entire NAR separately. + * + * @param context the context + * @param bundle the bundle + * @return metadata for the bundle + * @throws ExtensionRegistryException if an error occurs + * @throws IOException if an error occurs + */ + ExtensionBundleMetadata getBundleMetadata(ExtensionRegistryClientConfigurationContext context, Bundle bundle) throws ExtensionRegistryException, IOException; + +} diff --git a/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClientConfigurationContext.java b/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClientConfigurationContext.java new file mode 100644 index 0000000..25f8326 --- /dev/null +++ b/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClientConfigurationContext.java @@ -0,0 +1,25 @@ +/* + * 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.registry.extension; + +import org.apache.nifi.context.PropertyContext; + +import java.util.Optional; + +public interface ExtensionRegistryClientConfigurationContext extends PropertyContext { + Optional getNiFiUserIdentity(); +} diff --git a/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClientInitializationContext.java b/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClientInitializationContext.java new file mode 100644 index 0000000..a98dc8a --- /dev/null +++ b/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryClientInitializationContext.java @@ -0,0 +1,31 @@ +/* + * 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.registry.extension; + +import org.apache.nifi.logging.ComponentLog; + +import javax.net.ssl.SSLContext; +import java.util.Optional; + +public interface ExtensionRegistryClientInitializationContext { + + String getIdentifier(); + + ComponentLog getLogger(); + + Optional getSystemSslContext(); +} diff --git a/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryException.java b/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryException.java new file mode 100644 index 0000000..a9483d4 --- /dev/null +++ b/src/main/java/org/apache/nifi/registry/extension/ExtensionRegistryException.java @@ -0,0 +1,32 @@ +/* + * 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.registry.extension; + +/** + * Indicates an error interacting with the extension registry for a reason other + * than IOException. + */ +public class ExtensionRegistryException extends Exception { + + public ExtensionRegistryException(final String message) { + super(message); + } + + public ExtensionRegistryException(final String message, final Throwable cause) { + super(message, cause); + } +}