Skip to content

Commit 1658d35

Browse files
committed
refaractor(api/filesystems): move FileInputIterator implementation to commons-fs
This commits adds the new interfaces FileInputIteratorFactory and Storage in order to decouple iterator from the underlying file-system
1 parent 06385b3 commit 1658d35

File tree

40 files changed

+1221
-574
lines changed

40 files changed

+1221
-574
lines changed

connect-file-pulse-api/src/main/java/io/streamthoughts/kafka/connect/filepulse/internal/StringUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ public static boolean isFastSplit(final String regex) {
3939
}
4040

4141
public static boolean isNotBlank(final String string) {
42-
return !(Objects.isNull(string) || string.isBlank());
42+
return !isBlank(string);
43+
}
44+
45+
public static boolean isBlank(final String string) {
46+
return Objects.isNull(string) || string.isBlank();
4347
}
4448
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2019-2021 StreamThoughts.
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership.
7+
* The ASF licenses this file to You under the Apache License, Version 2.0
8+
* (the "License"); you may not use this file except in compliance with
9+
* the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package io.streamthoughts.kafka.connect.filepulse.reader;
20+
21+
import io.streamthoughts.kafka.connect.filepulse.data.TypedStruct;
22+
import io.streamthoughts.kafka.connect.filepulse.source.FileRecord;
23+
24+
import java.net.URI;
25+
26+
/**
27+
* A {@code FileInputIteratorFactory} can be used to get a new {@link FileInputIterator}.
28+
*/
29+
public interface FileInputIteratorFactory {
30+
31+
/**
32+
* Creates a new {@link FileInputIterator} for the given object file.
33+
*
34+
* @param objectURI the {@link URI} of the object file.
35+
* @return a new {@link FileInputIterator}.
36+
*/
37+
FileInputIterator<FileRecord<TypedStruct>> newIterator(final URI objectURI);
38+
}

connect-file-pulse-api/src/main/java/io/streamthoughts/kafka/connect/filepulse/reader/FileInputReader.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@
1919
package io.streamthoughts.kafka.connect.filepulse.reader;
2020

2121
import io.streamthoughts.kafka.connect.filepulse.data.TypedStruct;
22-
import io.streamthoughts.kafka.connect.filepulse.source.FileContext;
23-
import io.streamthoughts.kafka.connect.filepulse.source.FileRecord;
2422
import io.streamthoughts.kafka.connect.filepulse.source.FileObjectMeta;
23+
import io.streamthoughts.kafka.connect.filepulse.source.FileRecord;
2524
import org.apache.kafka.common.Configurable;
2625

2726
import java.net.URI;
@@ -30,7 +29,7 @@
3029
/**
3130
* A {@code FileInputReader} is the principal class used to read an input file/object.
3231
*/
33-
public interface FileInputReader extends Configurable, AutoCloseable {
32+
public interface FileInputReader extends FileInputIteratorFactory, Configurable, AutoCloseable {
3433

3534
/**
3635
* Configure this class with the given key-value pairs.
@@ -45,27 +44,27 @@ default void configure(final Map<String, ?> configs) {
4544
/**
4645
* Gets the metadata for the source object identified by the given {@link URI}.
4746
*
48-
* @param sourceURI the {@link URI} of the source object.
47+
* @param objectURI the {@link URI} of the file object.
4948
* @return a new {@link FileObjectMeta} instance.
5049
*/
51-
FileObjectMeta readMetadata(final URI sourceURI);
50+
FileObjectMeta getObjectMetadata(final URI objectURI);
5251

5352
/**
5453
* Checks whether the source object identified by the given {@link URI} can be read.
5554
*
56-
* @param sourceURI the {@link URI} of the source object.
55+
* @param objectURI the {@link URI} of the file object.
5756
* @return the {@code true}.
5857
*/
59-
boolean isReadable(final URI sourceURI);
58+
boolean canBeRead(final URI objectURI);
6059

6160
/**
62-
* Creates a new {@link FileInputIterator} instance.
61+
* Creates a new {@link FileInputIterator} for the given {@link URI}.
6362
*
64-
* @param context the context of the file on which to create the iterator.
63+
* @param objectURI the {@link URI} of the file object.
6564
* @return a new {@link FileInputIterator} iterator instance.
6665
*
6766
*/
68-
FileInputIterator<FileRecord<TypedStruct>> newIterator(final FileContext context);
67+
FileInputIterator<FileRecord<TypedStruct>> newIterator(final URI objectURI);
6968

7069
/**
7170
* Close this reader and any remaining un-close iterators.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Copyright 2019-2020 StreamThoughts.
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership.
7+
* The ASF licenses this file to You under the Apache License, Version 2.0
8+
* (the "License"); you may not use this file except in compliance with
9+
* the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package io.streamthoughts.kafka.connect.filepulse.source;
20+
21+
import io.streamthoughts.kafka.connect.filepulse.data.TypedStruct;
22+
import io.streamthoughts.kafka.connect.filepulse.reader.FileInputIterator;
23+
import io.streamthoughts.kafka.connect.filepulse.reader.FileInputReader;
24+
import io.streamthoughts.kafka.connect.filepulse.reader.RecordsIterable;
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
28+
import java.net.URI;
29+
import java.util.Objects;
30+
import java.util.concurrent.atomic.AtomicBoolean;
31+
32+
/**
33+
* {@code DelegateFileInputIterator}.
34+
*/
35+
public class DelegateFileInputIterator implements FileInputIterator<FileRecord<TypedStruct>> {
36+
37+
private static final Logger LOG = LoggerFactory.getLogger(DelegateFileInputIterator.class);
38+
39+
private final URI objectURI;
40+
private final FileInputReader reader;
41+
private final AtomicBoolean isClosed = new AtomicBoolean(false);
42+
43+
private FileInputIterator<FileRecord<TypedStruct>> iterator;
44+
45+
/**
46+
* Creates a new {@link DelegateFileInputIterator} instance.
47+
*
48+
* @param objectURI the input source file.
49+
* @param reader the input source reader used to create a new {@link FileInputIterator}.
50+
*/
51+
DelegateFileInputIterator(final URI objectURI, final FileInputReader reader) {
52+
this.objectURI = Objects.requireNonNull(objectURI, "source can't be null");
53+
this.reader = Objects.requireNonNull(reader, "reader can't be null");
54+
}
55+
56+
/**
57+
* Gets the metadata of the backed object file.
58+
*
59+
* @return the {@link FileObjectMeta}
60+
*/
61+
public FileObjectMeta getMetadata() {
62+
return reader.getObjectMetadata(objectURI);
63+
}
64+
65+
/**
66+
* Gets the URI of the backed object file.
67+
*
68+
* @return the {@link URI}
69+
*/
70+
public URI getObjectURI() {
71+
return objectURI;
72+
}
73+
74+
/**
75+
* Gets the {@link FileInputIterator} or create a new one if none has been initialized yet.
76+
*/
77+
public void open() {
78+
if (isOpen()) throw new IllegalStateException("Iterator is already open");
79+
LOG.info("Opening new iterator for: {}", objectURI);
80+
iterator = reader.newIterator(objectURI);
81+
}
82+
83+
/**
84+
* @return {@code true} if an iterator is already opened.
85+
*/
86+
boolean isOpen() {
87+
return iterator != null && !iterator.isClose();
88+
}
89+
90+
/**
91+
*
92+
* @return {@code true} if the backed object file can be read and is accessible.
93+
*/
94+
boolean isValid() {
95+
return reader.canBeRead(objectURI);
96+
}
97+
98+
/**
99+
* {@inheritDoc}
100+
*/
101+
@Override
102+
public FileContext context() {
103+
checkIsOpen();
104+
return iterator.context();
105+
}
106+
107+
/**
108+
* {@inheritDoc}
109+
*/
110+
@Override
111+
public void seekTo(final FileObjectOffset offset) {
112+
checkIsOpen();
113+
iterator.seekTo(offset);
114+
}
115+
116+
/**
117+
* {@inheritDoc}
118+
*/
119+
@Override
120+
public RecordsIterable<FileRecord<TypedStruct>> next() {
121+
checkIsOpen();
122+
return iterator.next();
123+
}
124+
125+
/**
126+
* {@inheritDoc}
127+
*/
128+
@Override
129+
public boolean hasNext() {
130+
checkIsOpen();
131+
return iterator.hasNext();
132+
}
133+
134+
/**
135+
* {@inheritDoc}
136+
*/
137+
@Override
138+
public void close() {
139+
if (!isClosed.get()) {
140+
LOG.info("Closing iterator for: {} ", iterator.context().metadata());
141+
iterator.close();
142+
isClosed.set(true);
143+
}
144+
}
145+
146+
/**
147+
* {@inheritDoc}
148+
*/
149+
@Override
150+
public boolean isClose() {
151+
return isClosed.get();
152+
}
153+
154+
private void checkIsOpen() {
155+
if (!isOpen()) throw new IllegalStateException("This iterator is not initialized yet or already closed");
156+
}
157+
158+
}

connect-file-pulse-api/src/main/java/io/streamthoughts/kafka/connect/filepulse/source/FileInputIterable.java

Lines changed: 0 additions & 107 deletions
This file was deleted.

connect-file-pulse-api/src/main/java/io/streamthoughts/kafka/connect/filepulse/source/FileObjectMeta.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ default String stringURI() {
5353
* @return the content-length of the source object.
5454
*/
5555
@JsonProperty("contentLength")
56-
long contentLength();
56+
Long contentLength();
5757

5858
/**
5959
* @return the creation date or the last modified date, whichever is the latest.
6060
*/
6161
@JsonProperty("lastModified")
62-
long lastModified();
62+
Long lastModified();
6363

6464
/**
6565
* @return the digest of the source object content.

0 commit comments

Comments
 (0)