Skip to content

Commit a6510f9

Browse files
committed
Add File.java to forbidden APIs
This commit cuts over all of core (not quite all tests) to java.nio.Path It also adds the file class to the core forbidden APIs to prevent its usage. This commit also resolves #8254 since we now consistently useing the NIO Path API. The Changes in this commit allow for more information if IO operations fail since the NIO API throws exceptions instead of boolean return values. The build-in methods used in this commit are also more resillient to encodeing errors like unmappable characters and throw exceptions if those chars are present in a file. Closes #8254 Closes #8666
1 parent d8f1617 commit a6510f9

File tree

63 files changed

+1096
-1383
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1096
-1383
lines changed

dev-tools/forbidden/core-signatures.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,17 @@ org.apache.lucene.search.TimeLimitingCollector#getGlobalCounter()
114114

115115
@defaultMessage Don't interrupt threads use FutureUtils#cancel(Future<T>) instead
116116
java.util.concurrent.Future#cancel(boolean)
117+
118+
@defaultMessage Use java.nio.file.Path / java.nio.file.Files instead of java.io.File API
119+
java.util.jar.JarFile
120+
java.util.zip.ZipFile
121+
java.io.File
122+
java.io.FileInputStream
123+
java.io.FileOutputStream
124+
java.io.PrintStream#<init>(java.lang.String,java.lang.String)
125+
java.io.PrintWriter#<init>(java.lang.String,java.lang.String)
126+
java.util.Formatter#<init>(java.lang.String,java.lang.String,java.util.Locale)
127+
java.io.RandomAccessFile
128+
java.nio.file.Path#toFile()
129+
130+

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1218,7 +1218,7 @@
12181218
<exclude>org/elasticsearch/common/logging/log4j/ConsoleAppender*</exclude>
12191219
<exclude>org/elasticsearch/common/http/client/HttpDownloadHelper*</exclude>
12201220
<exclude>org/elasticsearch/common/cli/Terminal*</exclude>
1221-
<exclude>org/elasticsearch/plugins/PluginManager.class</exclude>
1221+
<exclude>org/elasticsearch/plugins/PluginManager$SysOut.class</exclude>
12221222
<exclude>org/elasticsearch/common/http/client/HttpDownloadHelper.class</exclude>
12231223
<exclude>org/elasticsearch/bootstrap/Bootstrap.class</exclude>
12241224
<exclude>org/elasticsearch/Version.class</exclude>

src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportSnapshotsStatusAction.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.elasticsearch.threadpool.ThreadPool;
4343
import org.elasticsearch.transport.TransportService;
4444

45+
import java.io.IOException;
4546
import java.util.Map;
4647
import java.util.Set;
4748

@@ -86,7 +87,7 @@ protected SnapshotsStatusResponse newResponse() {
8687
@Override
8788
protected void masterOperation(final SnapshotsStatusRequest request,
8889
final ClusterState state,
89-
final ActionListener<SnapshotsStatusResponse> listener) throws ElasticsearchException {
90+
final ActionListener<SnapshotsStatusResponse> listener) throws Exception {
9091
ImmutableList<SnapshotMetaData.Entry> currentSnapshots = snapshotsService.currentSnapshots(request.repository(), request.snapshots());
9192

9293
if (currentSnapshots.isEmpty()) {
@@ -136,7 +137,7 @@ public void onFailure(Throwable e) {
136137
}
137138

138139
private SnapshotsStatusResponse buildResponse(SnapshotsStatusRequest request, ImmutableList<SnapshotMetaData.Entry> currentSnapshots,
139-
TransportNodesSnapshotsStatus.NodesSnapshotStatus nodeSnapshotStatuses) {
140+
TransportNodesSnapshotsStatus.NodesSnapshotStatus nodeSnapshotStatuses) throws IOException {
140141
// First process snapshot that are currently processed
141142
ImmutableList.Builder<SnapshotStatus> builder = ImmutableList.builder();
142143
Set<SnapshotId> currentSnapshotIds = newHashSet();

src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeOperationAction.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.ElasticsearchException;
2323
import org.elasticsearch.action.ActionListener;
2424
import org.elasticsearch.action.ActionResponse;
25+
import org.elasticsearch.action.ActionRunnable;
2526
import org.elasticsearch.action.support.ActionFilters;
2627
import org.elasticsearch.action.support.TransportAction;
2728
import org.elasticsearch.cluster.ClusterChangedEvent;
@@ -32,6 +33,7 @@
3233
import org.elasticsearch.cluster.node.DiscoveryNodes;
3334
import org.elasticsearch.common.settings.Settings;
3435
import org.elasticsearch.common.unit.TimeValue;
36+
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
3537
import org.elasticsearch.discovery.MasterNotDiscoveredException;
3638
import org.elasticsearch.node.NodeClosedException;
3739
import org.elasticsearch.threadpool.ThreadPool;
@@ -64,7 +66,7 @@ protected TransportMasterNodeOperationAction(Settings settings, String actionNam
6466

6567
protected abstract Response newResponse();
6668

67-
protected abstract void masterOperation(Request request, ClusterState state, ActionListener<Response> listener) throws ElasticsearchException;
69+
protected abstract void masterOperation(Request request, ClusterState state, ActionListener<Response> listener) throws Exception;
6870

6971
protected boolean localExecute(Request request) {
7072
return false;
@@ -126,20 +128,12 @@ protected boolean validate(ClusterState newState) {
126128
);
127129

128130
} else {
129-
try {
130-
threadPool.executor(executor).execute(new Runnable() {
131-
@Override
132-
public void run() {
133-
try {
134-
masterOperation(request, clusterService.state(), listener);
135-
} catch (Throwable e) {
136-
listener.onFailure(e);
137-
}
138-
}
139-
});
140-
} catch (Throwable t) {
141-
listener.onFailure(t);
142-
}
131+
threadPool.executor(executor).execute(new ActionRunnable(listener) {
132+
@Override
133+
protected void doRun() throws Exception {
134+
masterOperation(request, clusterService.state(), listener);
135+
}
136+
});
143137
}
144138
} else {
145139
if (nodes.masterNode() == null) {

src/main/java/org/elasticsearch/bootstrap/Bootstrap.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040

4141
import java.io.File;
4242
import java.io.FileOutputStream;
43+
import java.io.OutputStream;
44+
import java.nio.file.*;
4345
import java.util.Locale;
4446
import java.util.Set;
4547
import java.util.concurrent.CountDownLatch;
@@ -149,15 +151,12 @@ public static void main(String[] args) {
149151

150152
if (pidFile != null) {
151153
try {
152-
File fPidFile = new File(pidFile);
153-
if (fPidFile.getParentFile() != null) {
154-
FileSystemUtils.mkdirs(fPidFile.getParentFile());
155-
}
156-
FileOutputStream outputStream = new FileOutputStream(fPidFile);
154+
Path fPidFile = Paths.get(pidFile);
155+
Files.createDirectories(fPidFile.getParent());
156+
OutputStream outputStream = Files.newOutputStream(fPidFile, StandardOpenOption.DELETE_ON_CLOSE);
157157
outputStream.write(Long.toString(JvmInfo.jvmInfo().pid()).getBytes(Charsets.UTF_8));
158-
outputStream.close();
159-
160-
fPidFile.deleteOnExit();
158+
outputStream.flush(); // make those bytes visible...
159+
// don't close this stream we will delete on JVM exit
161160
} catch (Exception e) {
162161
String errorMessage = buildErrorMessage("pid", e);
163162
System.err.println(errorMessage);

src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,13 @@
7070
import org.elasticsearch.script.ScriptService;
7171
import org.elasticsearch.threadpool.ThreadPool;
7272

73-
import java.io.File;
74-
import java.io.FileInputStream;
73+
import java.io.BufferedReader;
74+
import java.io.IOException;
7575
import java.io.InputStreamReader;
7676
import java.io.UnsupportedEncodingException;
77+
import java.nio.file.DirectoryStream;
78+
import java.nio.file.Files;
79+
import java.nio.file.Path;
7780
import java.util.*;
7881
import java.util.concurrent.Semaphore;
7982
import java.util.concurrent.TimeUnit;
@@ -303,17 +306,17 @@ public ClusterState execute(ClusterState currentState) throws Exception {
303306
}
304307

305308
// now add config level mappings
306-
File mappingsDir = new File(environment.configFile(), "mappings");
307-
if (mappingsDir.exists() && mappingsDir.isDirectory()) {
309+
Path mappingsDir = environment.configFile().resolve("mappings");
310+
if (Files.isDirectory(mappingsDir)) {
308311
// first index level
309-
File indexMappingsDir = new File(mappingsDir, request.index());
310-
if (indexMappingsDir.exists() && indexMappingsDir.isDirectory()) {
312+
Path indexMappingsDir = mappingsDir.resolve(request.index());
313+
if (Files.isDirectory(indexMappingsDir)) {
311314
addMappings(mappings, indexMappingsDir);
312315
}
313316

314317
// second is the _default mapping
315-
File defaultMappingsDir = new File(mappingsDir, "_default");
316-
if (defaultMappingsDir.exists() && defaultMappingsDir.isDirectory()) {
318+
Path defaultMappingsDir = mappingsDir.resolve("_default");
319+
if (Files.isDirectory(defaultMappingsDir)) {
317320
addMappings(mappings, defaultMappingsDir);
318321
}
319322
}
@@ -485,28 +488,30 @@ private Map<String, Object> parseMapping(String mappingSource) throws Exception
485488
return XContentFactory.xContent(mappingSource).createParser(mappingSource).mapAndClose();
486489
}
487490

488-
private void addMappings(Map<String, Map<String, Object>> mappings, File mappingsDir) {
489-
File[] mappingsFiles = mappingsDir.listFiles();
490-
for (File mappingFile : mappingsFiles) {
491-
if (mappingFile.isHidden()) {
492-
continue;
493-
}
494-
int lastDotIndex = mappingFile.getName().lastIndexOf('.');
495-
String mappingType = lastDotIndex != -1 ? mappingFile.getName().substring(0, lastDotIndex) : mappingFile.getName();
496-
try {
497-
String mappingSource = Streams.copyToString(new InputStreamReader(new FileInputStream(mappingFile), Charsets.UTF_8));
498-
if (mappings.containsKey(mappingType)) {
499-
XContentHelper.mergeDefaults(mappings.get(mappingType), parseMapping(mappingSource));
500-
} else {
501-
mappings.put(mappingType, parseMapping(mappingSource));
491+
private void addMappings(Map<String, Map<String, Object>> mappings, Path mappingsDir) throws IOException {
492+
try (DirectoryStream<Path> stream = Files.newDirectoryStream(mappingsDir)) {
493+
for (Path mappingFile : stream) {
494+
final String fileName = mappingFile.getFileName().toString();
495+
if (Files.isHidden(mappingFile)) {
496+
continue;
497+
}
498+
int lastDotIndex = fileName.lastIndexOf('.');
499+
String mappingType = lastDotIndex != -1 ? mappingFile.getFileName().toString().substring(0, lastDotIndex) : mappingFile.getFileName().toString();
500+
try (BufferedReader reader = Files.newBufferedReader(mappingFile, Charsets.UTF_8)) {
501+
String mappingSource = Streams.copyToString(reader);
502+
if (mappings.containsKey(mappingType)) {
503+
XContentHelper.mergeDefaults(mappings.get(mappingType), parseMapping(mappingSource));
504+
} else {
505+
mappings.put(mappingType, parseMapping(mappingSource));
506+
}
507+
} catch (Exception e) {
508+
logger.warn("failed to read / parse mapping [" + mappingType + "] from location [" + mappingFile + "], ignoring...", e);
502509
}
503-
} catch (Exception e) {
504-
logger.warn("failed to read / parse mapping [" + mappingType + "] from location [" + mappingFile + "], ignoring...", e);
505510
}
506511
}
507512
}
508513

509-
private List<IndexTemplateMetaData> findTemplates(CreateIndexClusterStateUpdateRequest request, ClusterState state, IndexTemplateFilter indexTemplateFilter) {
514+
private List<IndexTemplateMetaData> findTemplates(CreateIndexClusterStateUpdateRequest request, ClusterState state, IndexTemplateFilter indexTemplateFilter) throws IOException {
510515
List<IndexTemplateMetaData> templates = Lists.newArrayList();
511516
for (ObjectCursor<IndexTemplateMetaData> cursor : state.metaData().templates().values()) {
512517
IndexTemplateMetaData template = cursor.value;
@@ -516,22 +521,21 @@ private List<IndexTemplateMetaData> findTemplates(CreateIndexClusterStateUpdateR
516521
}
517522

518523
// see if we have templates defined under config
519-
File templatesDir = new File(environment.configFile(), "templates");
520-
if (templatesDir.exists() && templatesDir.isDirectory()) {
521-
File[] templatesFiles = templatesDir.listFiles();
522-
if (templatesFiles != null) {
523-
for (File templatesFile : templatesFiles) {
524-
if (templatesFile.isFile()) {
524+
final Path templatesDir = environment.configFile().resolve("templates");
525+
if (Files.exists(templatesDir) && Files.isDirectory(templatesDir)) {
526+
try (DirectoryStream<Path> stream = Files.newDirectoryStream(templatesDir)) {
527+
for (Path templatesFile : stream) {
528+
if (Files.isRegularFile(templatesFile)) {
525529
XContentParser parser = null;
526530
try {
527-
byte[] templatesData = Streams.copyToByteArray(templatesFile);
531+
final byte[] templatesData = Files.readAllBytes(templatesFile);
528532
parser = XContentHelper.createParser(templatesData, 0, templatesData.length);
529-
IndexTemplateMetaData template = IndexTemplateMetaData.Builder.fromXContent(parser, templatesFile.getName());
533+
IndexTemplateMetaData template = IndexTemplateMetaData.Builder.fromXContent(parser, templatesFile.getFileName().toString());
530534
if (indexTemplateFilter.apply(request, template)) {
531535
templates.add(template);
532536
}
533537
} catch (Exception e) {
534-
logger.warn("[{}] failed to read template [{}] from config", e, request.index(), templatesFile.getAbsolutePath());
538+
logger.warn("[{}] failed to read template [{}] from config", e, request.index(), templatesFile.toAbsolutePath());
535539
} finally {
536540
Releasables.closeWhileHandlingException(parser);
537541
}

0 commit comments

Comments
 (0)