All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.launchdarkly.sdk.server.integrations.FileDataSourceBuilder Maven / Gradle / Ivy

There is a newer version: 7.5.0
Show newest version
package com.launchdarkly.sdk.server.integrations;

import com.google.common.io.ByteStreams;
import com.launchdarkly.logging.LDLogger;
import com.launchdarkly.sdk.server.interfaces.ClientContext;
import com.launchdarkly.sdk.server.interfaces.DataSource;
import com.launchdarkly.sdk.server.interfaces.DataSourceFactory;
import com.launchdarkly.sdk.server.interfaces.DataSourceUpdates;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * To use the file data source, obtain a new instance of this class with {@link FileData#dataSource()};
 * call the builder method {@link #filePaths(String...)} to specify file path(s), and/or
 * {@link #classpathResources(String...)} to specify classpath data resources; then pass the resulting
 * object to {@link com.launchdarkly.sdk.server.LDConfig.Builder#dataSource(DataSourceFactory)}.
 * 

* For more details, see {@link FileData}. * * @since 4.12.0 */ public final class FileDataSourceBuilder implements DataSourceFactory { final List sources = new ArrayList<>(); // visible for tests private boolean autoUpdate = false; private FileData.DuplicateKeysHandling duplicateKeysHandling = FileData.DuplicateKeysHandling.FAIL; /** * Adds any number of source files for loading flag data, specifying each file path as a string. The files will * not actually be loaded until the LaunchDarkly client starts up. *

* Files will be parsed as JSON if their first non-whitespace character is '{'. Otherwise, they will be parsed as YAML. * * @param filePaths path(s) to the source file(s); may be absolute or relative to the current working directory * @return the same factory object * * @throws InvalidPathException if one of the parameters is not a valid file path */ public FileDataSourceBuilder filePaths(String... filePaths) throws InvalidPathException { for (String p: filePaths) { sources.add(new FilePathSourceInfo(Paths.get(p))); } return this; } /** * Adds any number of source files for loading flag data, specifying each file path as a Path. The files will * not actually be loaded until the LaunchDarkly client starts up. *

* Files will be parsed as JSON if their first non-whitespace character is '{'. Otherwise, they will be parsed as YAML. * * @param filePaths path(s) to the source file(s); may be absolute or relative to the current working directory * @return the same factory object */ public FileDataSourceBuilder filePaths(Path... filePaths) { for (Path p: filePaths) { sources.add(new FilePathSourceInfo(p)); } return this; } /** * Adds any number of classpath resources for loading flag data. The resources will not actually be loaded until the * LaunchDarkly client starts up. *

* Files will be parsed as JSON if their first non-whitespace character is '{'. Otherwise, they will be parsed as YAML. * * @param resourceLocations resource location(s) in the format used by {@code ClassLoader.getResource()}; these * are absolute paths, so for instance a resource called "data.json" in the package "com.mypackage" would have * the location "/com/mypackage/data.json" * @return the same factory object */ public FileDataSourceBuilder classpathResources(String... resourceLocations) { for (String location: resourceLocations) { sources.add(new ClasspathResourceSourceInfo(location)); } return this; } /** * Specifies whether the data source should watch for changes to the source file(s) and reload flags * whenever there is a change. By default, it will not, so the flags will only be loaded once. This feature * only works with real files, not with {@link #classpathResources(String...)}. *

* Note that auto-updating will only work if all of the files you specified have valid directory paths at * startup time; if a directory does not exist, creating it later will not result in files being loaded from it. *

* The performance of this feature depends on what implementation of {@code java.nio.file.WatchService} is * available in the Java runtime. On Linux and Windows, an implementation based on native filesystem APIs * should be available. On MacOS, there is a long-standing known issue where due to the lack of such an * implementation, it must use a file polling approach that can take up to 10 seconds to detect a change. * * @param autoUpdate true if flags should be reloaded whenever a source file changes * @return the same factory object */ public FileDataSourceBuilder autoUpdate(boolean autoUpdate) { this.autoUpdate = autoUpdate; return this; } /** * Specifies how to handle keys that are duplicated across files. *

* By default, data loading will fail if keys are duplicated across files ({@link FileData.DuplicateKeysHandling#FAIL}). * * @param duplicateKeysHandling specifies how to handle duplicate keys * @return the same factory object * @since 5.3.0 */ public FileDataSourceBuilder duplicateKeysHandling(FileData.DuplicateKeysHandling duplicateKeysHandling) { this.duplicateKeysHandling = duplicateKeysHandling; return this; } /** * Used internally by the LaunchDarkly client. */ @Override public DataSource createDataSource(ClientContext context, DataSourceUpdates dataSourceUpdates) { LDLogger logger = context.getBasic().getBaseLogger().subLogger("DataSource"); return new FileDataSourceImpl(dataSourceUpdates, sources, autoUpdate, duplicateKeysHandling, logger); } static abstract class SourceInfo { abstract byte[] readData() throws IOException; abstract Path toFilePath(); } static final class FilePathSourceInfo extends SourceInfo { final Path path; FilePathSourceInfo(Path path) { this.path = path; } @Override byte[] readData() throws IOException { return Files.readAllBytes(path); } @Override Path toFilePath() { return path; } @Override public String toString() { return path.toString(); } } static final class ClasspathResourceSourceInfo extends SourceInfo { String location; ClasspathResourceSourceInfo(String location) { this.location = location; } @Override byte[] readData() throws IOException { try (InputStream is = getClass().getClassLoader().getResourceAsStream(location)) { if (is == null) { throw new IOException("classpath resource not found"); } return ByteStreams.toByteArray(is); } } @Override Path toFilePath() { return null; } @Override public String toString() { return "classpath:" + location; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy