-
-
Notifications
You must be signed in to change notification settings - Fork 32
WIP: load SentryOptions from external sources. #536
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package io.sentry.core.config.location; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
|
||
/** | ||
* Wraps multiple resource locators and returns the first non-null configuration file path. | ||
*/ | ||
public final class CompoundResourceLocator implements ConfigurationResourceLocator { | ||
private final Collection<ConfigurationResourceLocator> locators; | ||
|
||
/** | ||
* Instantiates a new compound configuration resource locator. | ||
* @param locators the locators to iterate through | ||
*/ | ||
public CompoundResourceLocator(ConfigurationResourceLocator ... locators) { | ||
this.locators = Arrays.asList(locators); | ||
} | ||
|
||
/** | ||
* Tries to find the location of the resource containing the Sentry configuration file. | ||
* | ||
* @return the first non-null configuration file path (in the iteration order of the collection provided to | ||
* the constructor) or null if none such exists. | ||
*/ | ||
@Override | ||
@Nullable | ||
public String getConfigurationResourcePath() { | ||
for (ConfigurationResourceLocator l : locators) { | ||
String path = l.getConfigurationResourcePath(); | ||
if (path != null) { | ||
return path; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package io.sentry.core.config.location; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
|
||
/** | ||
* Tries to find the Sentry configuration file. | ||
*/ | ||
public interface ConfigurationResourceLocator { | ||
/** | ||
* Tries to find the location of the resource containing the Sentry configuration file. | ||
* | ||
* @return the location on which some {@link io.sentry.core.config.provider.resource.ResourceLoader} can find the configuration file or null if this | ||
* locator could not find any. | ||
*/ | ||
@Nullable | ||
String getConfigurationResourcePath(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package io.sentry.core.config.location; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
|
||
/** | ||
* Tries to find the location of the Sentry configuration file in some environment variable. | ||
*/ | ||
public final class EnvironmentBasedLocator implements ConfigurationResourceLocator { | ||
/** | ||
* The default environment variable to use for obtaining the location of the Sentry configuration file. | ||
*/ | ||
public static final String DEFAULT_ENV_VAR_NAME = "SENTRY_PROPERTIES_FILE"; | ||
|
||
private final String envVarName; | ||
|
||
/** | ||
* Constructs a new instance that will use the environment variable defined in {@link #DEFAULT_ENV_VAR_NAME}. | ||
*/ | ||
public EnvironmentBasedLocator() { | ||
this(DEFAULT_ENV_VAR_NAME); | ||
} | ||
|
||
/** | ||
* Constructs a new instance that will use the provided environment variable. | ||
* | ||
* @param envVarName the name of the environment variable to use | ||
*/ | ||
public EnvironmentBasedLocator(String envVarName) { | ||
this.envVarName = envVarName; | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public String getConfigurationResourcePath() { | ||
return System.getenv(envVarName); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package io.sentry.core.config.location; | ||
|
||
/** | ||
* Provides the configuration file location using a file name provided at instantiation time. | ||
*/ | ||
public final class StaticFileLocator implements ConfigurationResourceLocator { | ||
/** | ||
* The default file name of the Sentry configuration file. | ||
*/ | ||
public static final String DEFAULT_FILE_PATH = "sentry.properties"; | ||
|
||
private final String path; | ||
|
||
/** | ||
* Constructs a new instance using the {@link #DEFAULT_FILE_PATH}. | ||
*/ | ||
public StaticFileLocator() { | ||
this(DEFAULT_FILE_PATH); | ||
} | ||
|
||
/** | ||
* Constructs a new instance that will return the provided path as the path of the Sentry configuration. | ||
* | ||
* @param filePath the path to the Sentry configuration | ||
*/ | ||
public StaticFileLocator(String filePath) { | ||
this.path = filePath; | ||
} | ||
|
||
@Override | ||
public String getConfigurationResourcePath() { | ||
return path; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package io.sentry.core.config.location; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
|
||
/** | ||
* Tries to find the location of the Sentry configuration file using the value of some system property. | ||
*/ | ||
public final class SystemPropertiesBasedLocator implements ConfigurationResourceLocator { | ||
/** | ||
* The default system property to use for obtaining the location of the Sentry configuration file. | ||
*/ | ||
public static final String DEFAULT_PROPERTY_NAME = "sentry.properties.file"; | ||
|
||
private final String propertyName; | ||
|
||
/** | ||
* Constructs a new instance that will use the {@link #DEFAULT_PROPERTY_NAME}. | ||
*/ | ||
public SystemPropertiesBasedLocator() { | ||
this(DEFAULT_PROPERTY_NAME); | ||
} | ||
|
||
/** | ||
* Constructs a new instance that will use the provided system property name. | ||
* | ||
* @param propertyName the name of the property to load the location of the Sentry configuration file from | ||
*/ | ||
public SystemPropertiesBasedLocator(String propertyName) { | ||
this.propertyName = propertyName; | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public String getConfigurationResourcePath() { | ||
return System.getProperty(propertyName); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package io.sentry.core.config.provider; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.util.Collection; | ||
|
||
/** | ||
* Wraps a couple of other configuration providers to act as one, returning the first non-null value for given | ||
* configuration key, in the iteration order of the wrapped providers. | ||
*/ | ||
final class CompoundConfigurationProvider implements ConfigurationProvider { | ||
private final Collection<ConfigurationProvider> providers; | ||
|
||
/** | ||
* Instantiates the new compound provider by wrapping the provided collection of providers. | ||
* @param providers the providers to wrap | ||
*/ | ||
public CompoundConfigurationProvider(Collection<ConfigurationProvider> providers) { | ||
this.providers = providers; | ||
} | ||
|
||
@Nullable | ||
@Override | ||
public String getProperty(String key) { | ||
for (ConfigurationProvider p : providers) { | ||
String val = p.getProperty(key); | ||
if (val != null) { | ||
return val; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package io.sentry.core.config.provider; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
|
||
/** | ||
* Sentry is able to load configuration from various sources. This interface is implemented by each one of them. | ||
*/ | ||
public interface ConfigurationProvider { | ||
|
||
/** | ||
* Returns the value of the configuration property with the provided key. | ||
* | ||
* @param key the name of the configuration property | ||
* @return the value of the property as found in this provider or null if none found | ||
*/ | ||
@Nullable | ||
String getProperty(String key); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package io.sentry.core.config.provider; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
|
||
/** | ||
* Tries to find the configuration properties in the environment. | ||
*/ | ||
final class EnvironmentConfigurationProvider implements ConfigurationProvider { | ||
/** | ||
* The prefix of the environment variables holding Sentry configuration. | ||
*/ | ||
public static final String ENV_VAR_PREFIX = "SENTRY_"; | ||
|
||
// private static final Logger logger = LoggerFactory.getLogger(EnvironmentConfigurationProvider.class); | ||
|
||
@Nullable | ||
@Override | ||
public String getProperty(String key) { | ||
String ret = System.getenv(ENV_VAR_PREFIX + key.replace(".", "_").toUpperCase()); | ||
|
||
if (ret != null) { | ||
// logger.debug("Found {}={} in System Environment Variables.", key, ret); | ||
} | ||
|
||
return ret; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package io.sentry.core.config.provider; | ||
|
||
|
||
import io.sentry.core.ILogger; | ||
import io.sentry.core.SentryLevel; | ||
|
||
import javax.naming.Context; | ||
import javax.naming.InitialContext; | ||
import javax.naming.NamingException; | ||
import javax.naming.NoInitialContextException; | ||
|
||
/** | ||
* A configuration provider that looks up the configuration in the JNDI registry. | ||
* | ||
* @see JndiSupport to check whether Jndi is available in the current JVM without needing to load this class | ||
*/ | ||
final class JndiConfigurationProvider implements ConfigurationProvider { | ||
/** | ||
* The default prefix of the JNDI names of Sentry configuration. This, concatenated with the configuration key name | ||
* provided to the {@link #getProperty(String)} method, must form a valid JNDI name. | ||
*/ | ||
public static final String DEFAULT_JNDI_PREFIX = "java:comp/env/sentry/"; | ||
|
||
private final String prefix; | ||
private final JndiContextProvider contextProvider; | ||
private final ILogger logger; | ||
|
||
/** | ||
* Constructs a new instance using the {@link #DEFAULT_JNDI_PREFIX} and {@link JndiContextProvider} that returns | ||
* a new {@link InitialContext} each time it is asked for a context. This ensures that any changes in the JNDI | ||
* environment are taken into account on the next configuration property lookup. | ||
*/ | ||
public JndiConfigurationProvider(ILogger logger) { | ||
this(DEFAULT_JNDI_PREFIX, new JndiContextProvider() { | ||
@Override | ||
public Context getContext() throws NamingException { | ||
return new InitialContext(); | ||
} | ||
}, logger); | ||
} | ||
|
||
/** | ||
* Constructs a new instance that will look up the Sentry configuration keys using the provided prefix and using | ||
* the context obtained from the JNDI context provider. Because the JNDI environment is dynamic, Sentry uses the | ||
* JNDI context provider to obtain a fresh copy of the environment (if the provider chooses to return such). | ||
* @param jndiNamePrefix The prefix of the JNDI names of Sentry configuration. This, concatenated with | ||
* the configuration key name provided to the {@link #getProperty(String)} method, must form | ||
* a valid JNDI name. | ||
* @param contextProvider an object able to provide instances of the JNDI context | ||
* @param logger the logger | ||
*/ | ||
public JndiConfigurationProvider(String jndiNamePrefix, JndiContextProvider contextProvider, ILogger logger) { | ||
this.prefix = jndiNamePrefix; | ||
this.contextProvider = contextProvider; | ||
this.logger = logger; | ||
} | ||
|
||
@Override | ||
public String getProperty(String key) { | ||
String value = null; | ||
try { | ||
Context ctx = contextProvider.getContext(); | ||
value = (String) ctx.lookup(prefix + key); | ||
} catch (NoInitialContextException e) { | ||
logger.log(SentryLevel.DEBUG, "JNDI not configured for Sentry (NoInitialContextEx)"); | ||
} catch (NamingException e) { | ||
logger.log(SentryLevel.DEBUG, "No " + prefix + key + " in JNDI"); | ||
} catch (RuntimeException e) { | ||
logger.log(SentryLevel.WARNING, "Odd RuntimeException while testing for JNDI", e); | ||
} | ||
return value; | ||
} | ||
|
||
/** | ||
* A helper interface to be able to obtain application-specific JNDI context during Sentry configuration lookup. | ||
*/ | ||
public interface JndiContextProvider { | ||
/** | ||
* Returns the context to use when looking for a property in JNDI. Note that it is supposed that this method | ||
* returns a new context each time, but that might not be required or even correct depending on that | ||
* requirements of the supplier of the implementation of this interface. | ||
* | ||
* @return a possibly new instance of the JNDI context | ||
* @throws NamingException on JNDI error | ||
*/ | ||
Context getContext() throws NamingException; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package io.sentry.core.config.provider; | ||
|
||
|
||
/** | ||
* A helper class to check whether JNDI is available in the current JVM. | ||
*/ | ||
final class JndiSupport { | ||
// private static final Logger logger = LoggerFactory.getLogger(JndiSupport.class); | ||
|
||
private JndiSupport() { | ||
} | ||
|
||
/** | ||
* Checks whether JNDI is available. | ||
* @return true if JNDI is available, false otherwise | ||
*/ | ||
public static boolean isAvailable() { | ||
try { | ||
Class.forName("javax.naming.InitialContext", false, JndiSupport.class.getClassLoader()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isnt' very Android friendly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd say that none of the providers should be "executed" on Android, but just its own AndroidProvider. it doesnt make sense to try to read system envs, locate the file etc if the only thing that makes sense for android is its own provider. we'll also need a new module/package like io.sentry.config that has non android related things, I dont want customers needing to add extra rules to not fail their build because of unknown classes, this happened with the older version of the SDK and a lot of people complained. |
||
return true; | ||
} catch (ClassNotFoundException | NoClassDefFoundError e) { | ||
// logger.trace("JNDI is not available: " + e.getMessage()); | ||
return false; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package io.sentry.core.config.provider; | ||
|
||
import io.sentry.core.ILogger; | ||
import io.sentry.core.config.provider.resource.ResourceLoader; | ||
import io.sentry.core.config.location.ConfigurationResourceLocator; | ||
import io.sentry.core.config.provider.resource.ResourceLoaderConfigurationProvider; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.io.IOException; | ||
import java.nio.charset.Charset; | ||
|
||
/** | ||
* Similar to {@link ResourceLoaderConfigurationProvider} but uses a {@link ConfigurationResourceLocator} to find | ||
* the path to the configuration file. | ||
*/ | ||
final class LocatorBasedConfigurationProvider extends ResourceLoaderConfigurationProvider { | ||
/** | ||
* Instantiates a new configuration provider using the parameters. | ||
* | ||
* @param rl the resource loader to load the contents of the configuration file with | ||
* @param locator the locator to find the configuration file with | ||
* @param charset the charset of the configuration file | ||
* @param logger the logger | ||
* @throws IOException on failure to process the configuration file | ||
*/ | ||
public LocatorBasedConfigurationProvider(ResourceLoader rl, ConfigurationResourceLocator locator, Charset charset, @NotNull ILogger logger) | ||
throws IOException { | ||
super(rl, locator.getConfigurationResourcePath(), charset, logger); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this cant live in the sentry-core package.
Android SDK has a subset of the Java SDK, javax is not one of them