forked from apache/nifi
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NIFI-13344 Implement backend for uploading and managing custom NARs
- Add NarPersistenceProvider to framework API with standard implementation - Add NarManager to orchestrate interactions with the persistence provider and framework - Add REST API for upload, download, list, and delete of custom NARs - Add CLI commands for call these REST APIs - Implement an upload request replicator for replicating a file upload across the cluster - Update ExtensionManager, NarLoader, and JettyServer to support unloading a NAR - Add ability to replace a NAR in place by unloading components, loading new NAR, and reloading components - Add system tests for uploading a NAR and verifying other APIs - Add NAR digest to NarNode and summary DTO, fix bug in digest utils - Sync NARs from cluster coordinator when joining the cluster
- Loading branch information
Showing
114 changed files
with
7,268 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 128 additions & 0 deletions
128
nifi-commons/nifi-utils/src/main/java/org/apache/nifi/stream/io/MaxLengthInputStream.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/* | ||
* 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.stream.io; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
|
||
public class MaxLengthInputStream extends InputStream { | ||
|
||
private static final String ERROR_MESSAGE_FORMAT = "Unable to read past maximum allowed length of %s bytes"; | ||
|
||
private final InputStream in; | ||
private final long limit; | ||
private long bytesRead = 0; | ||
private long markOffset = -1L; | ||
|
||
/** | ||
* Constructs an input stream that will throw an exception if reading past a maximum length of bytes. | ||
* | ||
* @param in the underlying input stream | ||
* @param limit maximum length of bytes to read from underlying input stream | ||
*/ | ||
public MaxLengthInputStream(final InputStream in, final long limit) { | ||
this.in = in; | ||
this.limit = (limit + 1); | ||
} | ||
|
||
@Override | ||
public int read() throws IOException { | ||
if (bytesRead >= limit) { | ||
throw new IOException(ERROR_MESSAGE_FORMAT.formatted(limit)); | ||
} | ||
|
||
final int val = in.read(); | ||
if (val > -1) { | ||
bytesRead++; | ||
} | ||
return val; | ||
} | ||
|
||
@Override | ||
public int read(final byte[] b) throws IOException { | ||
if (bytesRead >= limit) { | ||
throw new IOException(ERROR_MESSAGE_FORMAT.formatted(limit)); | ||
} | ||
|
||
final int maxToRead = (int) Math.min(b.length, limit - bytesRead); | ||
|
||
final int val = in.read(b, 0, maxToRead); | ||
if (val > 0) { | ||
bytesRead += val; | ||
} | ||
return val; | ||
} | ||
|
||
@Override | ||
public int read(byte[] b, int off, int len) throws IOException { | ||
if (bytesRead >= limit) { | ||
throw new IOException(ERROR_MESSAGE_FORMAT.formatted(limit)); | ||
} | ||
|
||
final int maxToRead = (int) Math.min(len, limit - bytesRead); | ||
|
||
final int val = in.read(b, off, maxToRead); | ||
if (val > 0) { | ||
bytesRead += val; | ||
} | ||
return val; | ||
} | ||
|
||
@Override | ||
public long skip(final long n) throws IOException { | ||
final long toSkip = Math.min(n, limit - bytesRead); | ||
final long skipped = in.skip(toSkip); | ||
bytesRead += skipped; | ||
return skipped; | ||
} | ||
|
||
@Override | ||
public int available() throws IOException { | ||
return in.available(); | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
in.close(); | ||
} | ||
|
||
@Override | ||
public void mark(int readlimit) { | ||
in.mark(readlimit); | ||
markOffset = bytesRead; | ||
} | ||
|
||
@Override | ||
public boolean markSupported() { | ||
return in.markSupported(); | ||
} | ||
|
||
@Override | ||
public void reset() throws IOException { | ||
in.reset(); | ||
|
||
if (markOffset >= 0) { | ||
bytesRead = markOffset; | ||
} | ||
markOffset = -1; | ||
} | ||
|
||
public long getLimit() { | ||
return limit; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
...-commons/nifi-utils/src/test/java/org/apache/nifi/stream/io/MaxLengthInputStreamTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* 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.stream.io; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
public class MaxLengthInputStreamTest { | ||
|
||
@Test | ||
public void testReadingLessThanMaxLength() throws IOException { | ||
final String content = "12345"; | ||
try (final InputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)); | ||
final InputStream maxLengthInputStream = new MaxLengthInputStream(inputStream, Integer.MAX_VALUE)) { | ||
final byte[] allBytes = maxLengthInputStream.readAllBytes(); | ||
assertEquals(5, allBytes.length); | ||
} | ||
} | ||
|
||
@Test | ||
public void testReadingMoreThanMaxLength() throws IOException { | ||
final String content = "12345"; | ||
try (final InputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)); | ||
final InputStream maxLengthInputStream = new MaxLengthInputStream(inputStream, 1)) { | ||
assertThrows(IOException.class, maxLengthInputStream::readAllBytes); | ||
} | ||
} | ||
|
||
@Test | ||
public void testReadingEqualToMaxLength() throws IOException { | ||
final String content = "12345"; | ||
try (final InputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)); | ||
final InputStream maxLengthInputStream = new MaxLengthInputStream(inputStream, 5)) { | ||
final byte[] allBytes = maxLengthInputStream.readAllBytes(); | ||
assertEquals(5, allBytes.length); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.