Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import java.time.Clock;
import org.apache.polaris.core.PolarisConfigurationStore;
import org.apache.polaris.core.PolarisDiagnostics;
import org.apache.polaris.core.context.RealmContext;
import org.apache.polaris.core.context.RealmId;
import org.apache.polaris.core.persistence.LocalPolarisMetaStoreManagerFactory;
import org.apache.polaris.core.persistence.PolarisCredentialsBootstrap;
import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
Expand Down Expand Up @@ -71,16 +71,16 @@ protected PolarisEclipseLinkStore createBackingStore(@Nonnull PolarisDiagnostics
@Override
protected PolarisMetaStoreSession createMetaStoreSession(
@Nonnull PolarisEclipseLinkStore store,
@Nonnull RealmContext realmContext,
@Nonnull RealmId realmId,
@Nullable PolarisCredentialsBootstrap credentialsBootstrap,
@Nonnull PolarisDiagnostics diagnostics) {
return new PolarisEclipseLinkMetaStoreSessionImpl(
store,
storageIntegrationProvider,
realmContext,
realmId,
configurationFile(),
persistenceUnitName(),
secretsGenerator(realmContext, credentialsBootstrap),
secretsGenerator(realmId, credentialsBootstrap),
diagnostics);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.polaris.core.PolarisDiagnostics;
import org.apache.polaris.core.context.RealmContext;
import org.apache.polaris.core.context.RealmId;
import org.apache.polaris.core.entity.PolarisBaseEntity;
import org.apache.polaris.core.entity.PolarisChangeTrackingVersions;
import org.apache.polaris.core.entity.PolarisEntitiesActiveKey;
Expand Down Expand Up @@ -88,22 +88,21 @@ public class PolarisEclipseLinkMetaStoreSessionImpl implements PolarisMetaStoreS
*
* @param store Backing store of EclipseLink implementation
* @param storageIntegrationProvider Storage integration provider
* @param realmContext Realm context used to communicate with different database.
* @param realmId Realm context used to communicate with different database.
* @param confFile Optional EclipseLink configuration file. Default to 'META-INF/persistence.xml'.
* @param persistenceUnitName Optional persistence-unit name in confFile. Default to 'polaris'.
*/
public PolarisEclipseLinkMetaStoreSessionImpl(
@Nonnull PolarisEclipseLinkStore store,
@Nonnull PolarisStorageIntegrationProvider storageIntegrationProvider,
@Nonnull RealmContext realmContext,
@Nonnull RealmId realmId,
@Nullable String confFile,
@Nullable String persistenceUnitName,
@Nonnull PrincipalSecretsGenerator secretsGenerator,
@Nonnull PolarisDiagnostics diagnostics) {
this.diagnostics = diagnostics;
LOGGER.debug(
"Creating EclipseLink Meta Store Session for realm {}", realmContext.getRealmIdentifier());
emf = createEntityManagerFactory(realmContext, confFile, persistenceUnitName);
LOGGER.debug("Creating EclipseLink Meta Store Session for realm {}", realmId.id());
emf = createEntityManagerFactory(realmId, confFile, persistenceUnitName);

// init store
this.store = store;
Expand All @@ -121,18 +120,16 @@ public PolarisEclipseLinkMetaStoreSessionImpl(
* realm.
*/
private EntityManagerFactory createEntityManagerFactory(
@Nonnull RealmContext realmContext,
@Nullable String confFile,
@Nullable String persistenceUnitName) {
String realm = realmContext.getRealmIdentifier();
@Nonnull RealmId realmId, @Nullable String confFile, @Nullable String persistenceUnitName) {
String realm = realmId.id();
return realmFactories.computeIfAbsent(
realm,
key -> {
try {
PolarisEclipseLinkPersistenceUnit persistenceUnit =
PolarisEclipseLinkPersistenceUnit.locatePersistenceUnit(
confFile, persistenceUnitName);
return persistenceUnit.createEntityManagerFactory(realmContext);
return persistenceUnit.createEntityManagerFactory(realmId);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.polaris.core.context.RealmContext;
import org.apache.polaris.core.context.RealmId;
import org.apache.polaris.extension.persistence.impl.eclipselink.PolarisEclipseLinkPersistenceUnit.ClasspathResourcePolarisEclipseLinkPersistenceUnit;
import org.apache.polaris.extension.persistence.impl.eclipselink.PolarisEclipseLinkPersistenceUnit.FileSystemPolarisEclipseLinkPersistenceUnit;
import org.apache.polaris.extension.persistence.impl.eclipselink.PolarisEclipseLinkPersistenceUnit.JarFilePolarisEclipseLinkPersistenceUnit;
Expand All @@ -57,16 +57,15 @@ sealed interface PolarisEclipseLinkPersistenceUnit
FileSystemPolarisEclipseLinkPersistenceUnit,
JarFilePolarisEclipseLinkPersistenceUnit {

EntityManagerFactory createEntityManagerFactory(RealmContext realmContext) throws IOException;
EntityManagerFactory createEntityManagerFactory(RealmId realmId) throws IOException;

record ClasspathResourcePolarisEclipseLinkPersistenceUnit(
URL resource, String resourceName, String persistenceUnitName)
implements PolarisEclipseLinkPersistenceUnit {

@Override
public EntityManagerFactory createEntityManagerFactory(RealmContext realmContext)
throws IOException {
Map<String, String> properties = loadProperties(resource, persistenceUnitName, realmContext);
public EntityManagerFactory createEntityManagerFactory(RealmId realmId) throws IOException {
Map<String, String> properties = loadProperties(resource, persistenceUnitName, realmId);
properties.put(ECLIPSELINK_PERSISTENCE_XML, resourceName);
return Persistence.createEntityManagerFactory(persistenceUnitName, properties);
}
Expand All @@ -76,10 +75,9 @@ record FileSystemPolarisEclipseLinkPersistenceUnit(Path path, String persistence
implements PolarisEclipseLinkPersistenceUnit {

@Override
public EntityManagerFactory createEntityManagerFactory(RealmContext realmContext)
throws IOException {
public EntityManagerFactory createEntityManagerFactory(RealmId realmId) throws IOException {
Map<String, String> properties =
loadProperties(path.toUri().toURL(), persistenceUnitName, realmContext);
loadProperties(path.toUri().toURL(), persistenceUnitName, realmId);
Path archiveDirectory = path.getParent();
String descriptorPath = archiveDirectory.getParent().relativize(path).toString();
properties.put(ECLIPSELINK_PERSISTENCE_XML, descriptorPath);
Expand All @@ -101,9 +99,8 @@ record JarFilePolarisEclipseLinkPersistenceUnit(
implements PolarisEclipseLinkPersistenceUnit {

@Override
public EntityManagerFactory createEntityManagerFactory(RealmContext realmContext)
throws IOException {
Map<String, String> properties = loadProperties(confUrl, persistenceUnitName, realmContext);
public EntityManagerFactory createEntityManagerFactory(RealmId realmId) throws IOException {
Map<String, String> properties = loadProperties(confUrl, persistenceUnitName, realmId);
properties.put(ECLIPSELINK_PERSISTENCE_XML, descriptorPath);
ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
try (URLClassLoader currentClassLoader =
Expand Down Expand Up @@ -183,9 +180,7 @@ private static URL classpathResource(String resourceName) throws IOException {

/** Load the persistence unit properties from a given configuration file */
private static Map<String, String> loadProperties(
@Nonnull URL confFile,
@Nonnull String persistenceUnitName,
@Nonnull RealmContext realmContext)
@Nonnull URL confFile, @Nonnull String persistenceUnitName, @Nonnull RealmId realmId)
throws IOException {
try (InputStream input = confFile.openStream()) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Expand All @@ -205,9 +200,7 @@ private static Map<String, String> loadProperties(
}
// Replace database name in JDBC URL with realm
if (properties.containsKey(JDBC_URL)) {
properties.put(
JDBC_URL,
properties.get(JDBC_URL).replace("{realm}", realmContext.getRealmIdentifier()));
properties.put(JDBC_URL, properties.get(JDBC_URL).replace("{realm}", realmId.id()));
}
return properties;
} catch (XPathExpressionException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import org.apache.polaris.core.PolarisConfigurationStore;
import org.apache.polaris.core.PolarisDefaultDiagServiceImpl;
import org.apache.polaris.core.PolarisDiagnostics;
import org.apache.polaris.core.context.RealmContext;
import org.apache.polaris.core.context.RealmId;
import org.apache.polaris.core.entity.PolarisPrincipalSecrets;
import org.apache.polaris.core.persistence.BasePolarisMetaStoreManagerTest;
import org.apache.polaris.core.persistence.PolarisMetaStoreManagerImpl;
Expand Down Expand Up @@ -101,13 +101,13 @@ static void deleteConfFiles() throws IOException {
protected PolarisTestMetaStoreManager createPolarisTestMetaStoreManager() {
PolarisDiagnostics diagServices = new PolarisDefaultDiagServiceImpl();
PolarisEclipseLinkStore store = new PolarisEclipseLinkStore(diagServices);
RealmContext realmContext = () -> "realm";
RealmId realmId = RealmId.newRealmId("realm");
PolarisMetaStoreSession session =
new PolarisEclipseLinkMetaStoreSessionImpl(
store, Mockito.mock(), realmContext, null, "polaris", RANDOM_SECRETS, diagServices);
store, Mockito.mock(), realmId, null, "polaris", RANDOM_SECRETS, diagServices);
return new PolarisTestMetaStoreManager(
new PolarisMetaStoreManagerImpl(
realmContext,
realmId,
diagServices,
new PolarisConfigurationStore() {},
timeSource.withZone(ZoneId.systemDefault())),
Expand All @@ -128,7 +128,7 @@ void testCreateStoreSession(String confFile, boolean success) {
new PolarisEclipseLinkMetaStoreSessionImpl(
store,
Mockito.mock(),
() -> "realm",
RealmId.newRealmId("realm"),
confFile,
"polaris",
RANDOM_SECRETS,
Expand Down
3 changes: 3 additions & 0 deletions polaris-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ dependencies {
compileOnly(libs.jetbrains.annotations)
compileOnly(libs.spotbugs.annotations)

compileOnly(project(":polaris-immutables"))
annotationProcessor(project(":polaris-immutables", configuration = "processor"))

constraints {
implementation("org.xerial.snappy:snappy-java:1.1.10.7") {
because("Vulnerability detected in 1.1.8.2")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import jakarta.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import org.apache.polaris.core.context.RealmContext;
import org.apache.polaris.core.context.RealmId;
import org.apache.polaris.core.entity.CatalogEntity;

/**
Expand All @@ -35,11 +35,11 @@ public interface PolarisConfigurationStore {
* Retrieve the current value for a configuration key. May be null if not set.
*
* @param <T> the type of the configuration value
* @param realmContext the realm context to check for overrides; may be null.
* @param realmId the realm context to check for overrides; may be null.
* @param configName the name of the configuration key to check
* @return the current value set for the configuration key or null if not set
*/
default <T> @Nullable T getConfiguration(@Nullable RealmContext realmContext, String configName) {
default <T> @Nullable T getConfiguration(@Nullable RealmId realmId, String configName) {
return null;
}

Expand All @@ -48,15 +48,15 @@ public interface PolarisConfigurationStore {
* value.
*
* @param <T> the type of the configuration value
* @param realmContext the realm context to check for overrides; may be null.
* @param realmId the realm context to check for overrides; may be null.
* @param configName the name of the configuration key to check
* @param defaultValue the default value if the configuration key has no value
* @return the current value or the supplied default value
*/
default <T> @Nonnull T getConfiguration(
@Nullable RealmContext realmContext, String configName, @Nonnull T defaultValue) {
@Nullable RealmId realmId, String configName, @Nonnull T defaultValue) {
Preconditions.checkNotNull(defaultValue, "Cannot pass null as a default value");
T configValue = getConfiguration(realmContext, configName);
T configValue = getConfiguration(realmId, configName);
return configValue != null ? configValue : defaultValue;
}

Expand Down Expand Up @@ -88,13 +88,13 @@ public interface PolarisConfigurationStore {
* Retrieve the current value for a configuration.
*
* @param <T> the type of the configuration value
* @param realmContext the realm context to check for overrides; may be null.
* @param realmId the realm context to check for overrides; may be null.
* @param config the configuration to load
* @return the current value set for the configuration key or null if not set
*/
default <T> @Nonnull T getConfiguration(
@Nullable RealmContext realmContext, PolarisConfiguration<T> config) {
T result = getConfiguration(realmContext, config.key, config.defaultValue);
@Nullable RealmId realmId, PolarisConfiguration<T> config) {
T result = getConfiguration(realmId, config.key, config.defaultValue);
return tryCast(config, result);
}

Expand All @@ -103,20 +103,20 @@ public interface PolarisConfigurationStore {
* present.
*
* @param <T> the type of the configuration value
* @param realmContext the realm context to check for overrides; may be null.
* @param realmId the realm context to check for overrides; may be null.
* @param catalogEntity the catalog to check for an override
* @param config the configuration to load
* @return the current value set for the configuration key or null if not set
*/
default <T> @Nonnull T getConfiguration(
@Nullable RealmContext realmContext,
@Nullable RealmId realmId,
@Nonnull CatalogEntity catalogEntity,
PolarisConfiguration<T> config) {
if (config.hasCatalogConfig()
&& catalogEntity.getPropertiesAsMap().containsKey(config.catalogConfig())) {
return tryCast(config, catalogEntity.getPropertiesAsMap().get(config.catalogConfig()));
} else {
return getConfiguration(realmContext, config);
return getConfiguration(realmId, config);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@
import jakarta.annotation.Nullable;
import java.util.List;
import java.util.Set;
import org.apache.polaris.core.context.RealmContext;
import org.apache.polaris.core.context.RealmId;
import org.apache.polaris.core.entity.PolarisBaseEntity;
import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;

/** Interface for invoking authorization checks. */
public interface PolarisAuthorizer {

void authorizeOrThrow(
@Nonnull RealmContext realmContext,
@Nonnull RealmId realmId,
@Nonnull AuthenticatedPolarisPrincipal authenticatedPrincipal,
@Nonnull Set<PolarisBaseEntity> activatedEntities,
@Nonnull PolarisAuthorizableOperation authzOp,
@Nullable PolarisResolvedPathWrapper target,
@Nullable PolarisResolvedPathWrapper secondary);

void authorizeOrThrow(
@Nonnull RealmContext realmContext,
@Nonnull RealmId realmId,
@Nonnull AuthenticatedPolarisPrincipal authenticatedPrincipal,
@Nonnull Set<PolarisBaseEntity> activatedEntities,
@Nonnull PolarisAuthorizableOperation authzOp,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
import org.apache.iceberg.exceptions.ForbiddenException;
import org.apache.polaris.core.PolarisConfiguration;
import org.apache.polaris.core.PolarisConfigurationStore;
import org.apache.polaris.core.context.RealmContext;
import org.apache.polaris.core.context.RealmId;
import org.apache.polaris.core.entity.PolarisBaseEntity;
import org.apache.polaris.core.entity.PolarisEntityConstants;
import org.apache.polaris.core.entity.PolarisEntityCore;
Expand Down Expand Up @@ -487,14 +487,14 @@ public boolean matchesOrIsSubsumedBy(

@Override
public void authorizeOrThrow(
@Nonnull RealmContext realmContext,
@Nonnull RealmId realmId,
@Nonnull AuthenticatedPolarisPrincipal authenticatedPrincipal,
@Nonnull Set<PolarisBaseEntity> activatedEntities,
@Nonnull PolarisAuthorizableOperation authzOp,
@Nullable PolarisResolvedPathWrapper target,
@Nullable PolarisResolvedPathWrapper secondary) {
authorizeOrThrow(
realmContext,
realmId,
authenticatedPrincipal,
activatedEntities,
authzOp,
Expand All @@ -504,16 +504,15 @@ public void authorizeOrThrow(

@Override
public void authorizeOrThrow(
@Nonnull RealmContext realmContext,
@Nonnull RealmId realmId,
@Nonnull AuthenticatedPolarisPrincipal authenticatedPrincipal,
@Nonnull Set<PolarisBaseEntity> activatedEntities,
@Nonnull PolarisAuthorizableOperation authzOp,
@Nullable List<PolarisResolvedPathWrapper> targets,
@Nullable List<PolarisResolvedPathWrapper> secondaries) {
boolean enforceCredentialRotationRequiredState =
featureConfig.getConfiguration(
realmContext,
PolarisConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
realmId, PolarisConfiguration.ENFORCE_PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_CHECKING);
if (enforceCredentialRotationRequiredState
&& authenticatedPrincipal
.getPrincipalEntity()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,26 @@
*/
package org.apache.polaris.core.context;

import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.apache.polaris.immutables.PolarisImmutable;
import org.immutables.value.Value;

/**
* Represents the elements of a REST request associated with routing to independent and isolated
* "universes". This may include properties such as region, deployment environment (e.g. dev, qa,
* prod), and/or account.
* Represents the ID of the realm used in a REST request associated with routing to independent and
* isolated "universes".
*/
public interface RealmContext {
@PolarisImmutable
@JsonSerialize(as = ImmutableRealmId.class)
@JsonDeserialize(as = ImmutableRealmId.class)
public interface RealmId {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we were making this change, why don't we call it Realm, instead of RealmId?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it's the ID of a realm - not the realm itself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The realmId used to be a simple string, but it has now been replaced by a RealmId type, which contains a field called id—essentially an id of an id. While this approach works, it feels cumbersome and lacks extensibility. For instance, if we want to add new fields like a description for a realm, we would have to either include it under this interface or create a separate interface, such as Realm or RealmContext.

Adding new fields directly under RealmId feels odd since these fields typically represent a concept that is part of a realm rather than the realmId. On the other hand, introducing a separate interface adds complexity by requiring an additional structure to be defined.

Additionally, I’m questioning whether the concepts of realm and realmId are truly distinct or interchangeable. If they are interchangeable, using the name realm instead of realmId might be a more concise and descriptive choice, simplifying the naming and making the code easier to understand.


static RealmContext copyOf(RealmContext original) {
String realmIdentifier = original.getRealmIdentifier();
return () -> realmIdentifier;
static RealmId newRealmId(String id) {
return ImmutableRealmId.of(id);
}

String getRealmIdentifier();
@Value.Parameter
@JsonValue
String id();
}
Loading
Loading