localSession = new ThreadLocal<>();
-
- private final PolarisEclipseLinkStore store;
- private final PolarisStorageIntegrationProvider storageIntegrationProvider;
- private final PrincipalSecretsGenerator secretsGenerator;
-
- /**
- * Create a meta store session against provided realm. Each realm has its own database.
- *
- * @param store Backing store of EclipseLink implementation
- * @param storageIntegrationProvider Storage integration provider
- * @param realmContext 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 PolarisDiagnostics diagnostics,
- @Nonnull PolarisEclipseLinkStore store,
- @Nonnull PolarisStorageIntegrationProvider storageIntegrationProvider,
- @Nonnull RealmContext realmContext,
- @Nullable String confFile,
- @Nullable String persistenceUnitName,
- @Nonnull PrincipalSecretsGenerator secretsGenerator) {
- super(diagnostics);
- LOGGER.debug(
- "Creating EclipseLink Meta Store Session for realm {}", realmContext.getRealmIdentifier());
- emf = createEntityManagerFactory(realmContext, confFile, persistenceUnitName);
-
- // init store
- this.store = store;
- try (EntityManager session = emf.createEntityManager()) {
- this.store.initialize(session);
- }
- this.storageIntegrationProvider = storageIntegrationProvider;
- this.secretsGenerator = secretsGenerator;
- }
-
- /**
- * Create EntityManagerFactory.
- *
- * The EntityManagerFactory creation is expensive, so we are caching and reusing it for each
- * realm.
- */
- private EntityManagerFactory createEntityManagerFactory(
- @Nonnull RealmContext realmContext,
- @Nullable String confFile,
- @Nullable String persistenceUnitName) {
- String realm = realmContext.getRealmIdentifier();
- return realmFactories.computeIfAbsent(
- realm,
- key -> {
- try {
- PolarisEclipseLinkPersistenceUnit persistenceUnit =
- PolarisEclipseLinkPersistenceUnit.locatePersistenceUnit(
- confFile, persistenceUnitName);
- return persistenceUnit.createEntityManagerFactory(realmContext);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- });
- }
-
- @VisibleForTesting
- static void clearEntityManagerFactories() {
- realmFactories.clear();
- }
-
- /** {@inheritDoc} */
- @Override
- public T runInTransaction(
- @Nonnull PolarisCallContext callCtx, @Nonnull Supplier transactionCode) {
- getDiagnostics().check(localSession.get() == null, "cannot nest transaction");
-
- try (EntityManager session = emf.createEntityManager()) {
- localSession.set(session);
- EntityTransaction tr = session.getTransaction();
- try {
- tr.begin();
-
- T result = transactionCode.get();
-
- // Commit when it's not rolled back by the client
- if (session.getTransaction().isActive()) {
- tr.commit();
- LOGGER.debug("transaction committed");
- }
-
- return result;
- } catch (Exception e) {
- // For some transaction conflict errors, the transaction will already no longer be active;
- // if it's still active, explicitly rollback.
- if (tr.isActive()) {
- tr.rollback();
- }
- LOGGER.debug("transaction rolled back", e);
-
- if (e instanceof OptimisticLockException
- || e.getCause() instanceof OptimisticLockException) {
- throw new RetryOnConcurrencyException(e);
- }
-
- throw e;
- } finally {
- localSession.remove();
- }
- } catch (PersistenceException e) {
- if (e.toString().toLowerCase(Locale.ROOT).contains("duplicate key")) {
- throw new AlreadyExistsException("Duplicate key error when persisting entity", e);
- } else {
- throw new RuntimeException("Error persisting entity", e);
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void runActionInTransaction(
- @Nonnull PolarisCallContext callCtx, @Nonnull Runnable transactionCode) {
- getDiagnostics().check(localSession.get() == null, "cannot nest transaction");
-
- try (EntityManager session = emf.createEntityManager()) {
- localSession.set(session);
- EntityTransaction tr = session.getTransaction();
- try {
- tr.begin();
-
- transactionCode.run();
-
- // Commit when it's not rolled back by the client
- if (session.getTransaction().isActive()) {
- tr.commit();
- LOGGER.debug("transaction committed");
- }
- } catch (Exception e) {
- LOGGER.debug("Rolling back transaction due to an error", e);
- // For some transaction conflict errors, the transaction will already no longer be active;
- // if it's still active, explicitly rollback.
- if (tr.isActive()) {
- tr.rollback();
- }
-
- if (e instanceof OptimisticLockException
- || e.getCause() instanceof OptimisticLockException) {
- throw new RetryOnConcurrencyException(e);
- }
-
- throw e;
- } finally {
- localSession.remove();
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public T runInReadTransaction(
- @Nonnull PolarisCallContext callCtx, @Nonnull Supplier transactionCode) {
- // EclipseLink doesn't support readOnly transaction
- return runInTransaction(callCtx, transactionCode);
- }
-
- /** {@inheritDoc} */
- @Override
- public void runActionInReadTransaction(
- @Nonnull PolarisCallContext callCtx, @Nonnull Runnable transactionCode) {
- // EclipseLink doesn't support readOnly transaction
- runActionInTransaction(callCtx, transactionCode);
- }
-
- /**
- * @return new unique entity identifier
- */
- @Override
- public long generateNewIdInCurrentTxn(@Nonnull PolarisCallContext callCtx) {
- // This function can be called within a transaction or out of transaction.
- // If called out of transaction, create a new transaction, otherwise run in current transaction
- return localSession.get() != null
- ? this.store.getNextSequence(localSession.get())
- : runInReadTransaction(callCtx, () -> generateNewIdInCurrentTxn(callCtx));
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeToEntitiesInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisBaseEntity entity) {
- this.store.writeToEntities(localSession.get(), entity);
- }
-
- /** {@inheritDoc} */
- @Override
- public
- void persistStorageIntegrationIfNeededInCurrentTxn(
- @Nonnull PolarisCallContext callContext,
- @Nonnull PolarisBaseEntity entity,
- @Nullable PolarisStorageIntegration storageIntegration) {
- // not implemented for eclipselink store
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeToEntitiesActiveInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisBaseEntity entity) {
- // write it
- this.store.writeToEntitiesActive(localSession.get(), entity);
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeToEntitiesChangeTrackingInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisBaseEntity entity) {
- // write it
- this.store.writeToEntitiesChangeTracking(localSession.get(), entity);
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeToGrantRecordsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisGrantRecord grantRec) {
- // write it
- this.store.writeToGrantRecords(localSession.get(), grantRec);
- }
-
- /** {@inheritDoc} */
- @Override
- public void deleteFromEntitiesInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisEntityCore entity) {
-
- // delete it
- this.store.deleteFromEntities(
- localSession.get(), entity.getCatalogId(), entity.getId(), entity.getTypeCode());
- }
-
- /** {@inheritDoc} */
- @Override
- public void deleteFromEntitiesActiveInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisEntityCore entity) {
- // delete it
- this.store.deleteFromEntitiesActive(localSession.get(), new PolarisEntitiesActiveKey(entity));
- }
-
- /**
- * {@inheritDoc}
- *
- * @param callCtx
- * @param entity entity record to delete
- */
- @Override
- public void deleteFromEntitiesChangeTrackingInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisEntityCore entity) {
- // delete it
- this.store.deleteFromEntitiesChangeTracking(localSession.get(), entity);
- }
-
- /** {@inheritDoc} */
- @Override
- public void deleteFromGrantRecordsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisGrantRecord grantRec) {
- this.store.deleteFromGrantRecords(localSession.get(), grantRec);
- }
-
- /** {@inheritDoc} */
- @Override
- public void deleteAllEntityGrantRecordsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- @Nonnull PolarisEntityCore entity,
- @Nonnull List grantsOnGrantee,
- @Nonnull List grantsOnSecurable) {
- this.store.deleteAllEntityGrantRecords(localSession.get(), entity);
- }
-
- /** {@inheritDoc} */
- @Override
- public void deleteAllInCurrentTxn(@Nonnull PolarisCallContext callCtx) {
- this.store.deleteAll(localSession.get());
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nullable PolarisBaseEntity lookupEntityInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, long catalogId, long entityId, int typeCode) {
- return ModelEntity.toEntity(
- this.store.lookupEntity(localSession.get(), catalogId, entityId, typeCode));
- }
-
- @Override
- public @Nonnull List lookupEntitiesInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, List entityIds) {
- return this.store.lookupEntities(localSession.get(), entityIds).stream()
- .map(ModelEntity::toEntity)
- .toList();
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nonnull List lookupEntityVersionsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, List entityIds) {
- Map idToEntityMap =
- this.store.lookupEntities(localSession.get(), entityIds).stream()
- .collect(
- Collectors.toMap(
- entry -> new PolarisEntityId(entry.getCatalogId(), entry.getId()),
- entry -> entry));
- return entityIds.stream()
- .map(
- entityId -> {
- ModelEntity entity = idToEntityMap.getOrDefault(entityId, null);
- return entity == null
- ? null
- : new PolarisChangeTrackingVersions(
- entity.getEntityVersion(), entity.getGrantRecordsVersion());
- })
- .collect(Collectors.toList());
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable
- public EntityNameLookupRecord lookupEntityActiveInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisEntitiesActiveKey entityActiveKey) {
- // lookup the active entity slice
- return ModelEntityActive.toEntityActive(
- this.store.lookupEntityActive(localSession.get(), entityActiveKey));
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull
- public List lookupEntityActiveBatchInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- @Nonnull List entityActiveKeys) {
- // now build a list to quickly verify that nothing has changed
- return entityActiveKeys.stream()
- .map(entityActiveKey -> this.lookupEntityActiveInCurrentTxn(callCtx, entityActiveKey))
- .collect(Collectors.toList());
- }
-
- @Override
- public @Nonnull Page loadEntitiesInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- long catalogId,
- long parentId,
- @Nonnull PolarisEntityType entityType,
- @Nonnull PolarisEntitySubType entitySubType,
- @Nonnull Predicate entityFilter,
- @Nonnull Function transformer,
- @Nonnull PageToken pageToken) {
- // full range scan under the parent for that type
- Stream data =
- this.store
- .lookupFullEntitiesActive(
- localSession.get(), catalogId, parentId, entityType, entitySubType, pageToken)
- .stream()
- .map(ModelEntity::toEntity)
- .filter(entityFilter);
-
- return Page.mapped(pageToken, data, transformer, EntityIdToken::fromEntity);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean hasChildrenInCurrentTxn(
- @Nonnull PolarisCallContext callContext,
- @Nullable PolarisEntityType entityType,
- long catalogId,
- long parentId) {
- // check if it has children
- return this.store.countActiveChildEntities(localSession.get(), catalogId, parentId, entityType)
- > 0;
- }
-
- /** {@inheritDoc} */
- @Override
- public int lookupEntityGrantRecordsVersionInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, long catalogId, long entityId) {
- ModelEntityChangeTracking entity =
- this.store.lookupEntityChangeTracking(localSession.get(), catalogId, entityId);
-
- // does not exist, 0
- return entity == null ? 0 : entity.getGrantRecordsVersion();
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nullable PolarisGrantRecord lookupGrantRecordInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- long securableCatalogId,
- long securableId,
- long granteeCatalogId,
- long granteeId,
- int privilegeCode) {
- // lookup the grants records slice to find the usage role
- return ModelGrantRecord.toGrantRecord(
- this.store.lookupGrantRecord(
- localSession.get(),
- securableCatalogId,
- securableId,
- granteeCatalogId,
- granteeId,
- privilegeCode));
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nonnull List loadAllGrantRecordsOnSecurableInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, long securableCatalogId, long securableId) {
- // now fetch all grants for this securable
- return this.store
- .lookupAllGrantRecordsOnSecurable(localSession.get(), securableCatalogId, securableId)
- .stream()
- .map(ModelGrantRecord::toGrantRecord)
- .toList();
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nonnull List loadAllGrantRecordsOnGranteeInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, long granteeCatalogId, long granteeId) {
- // now fetch all grants assigned to this grantee
- return this.store
- .lookupGrantRecordsOnGrantee(localSession.get(), granteeCatalogId, granteeId)
- .stream()
- .map(ModelGrantRecord::toGrantRecord)
- .toList();
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nullable PolarisPrincipalSecrets loadPrincipalSecretsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull String clientId) {
- return ModelPrincipalSecrets.toPrincipalSecrets(
- this.store.lookupPrincipalSecrets(localSession.get(), clientId));
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nonnull PolarisPrincipalSecrets generateNewPrincipalSecretsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull String principalName, long principalId) {
- // ensure principal client id is unique
- PolarisPrincipalSecrets principalSecrets;
- ModelPrincipalSecrets lookupPrincipalSecrets;
- do {
- // generate new random client id and secrets
- principalSecrets = secretsGenerator.produceSecrets(principalName, principalId);
-
- // load the existing secrets
- lookupPrincipalSecrets =
- this.store.lookupPrincipalSecrets(
- localSession.get(), principalSecrets.getPrincipalClientId());
- } while (lookupPrincipalSecrets != null);
-
- // write new principal secrets
- this.store.writePrincipalSecrets(localSession.get(), principalSecrets);
-
- // if not found, return null
- return principalSecrets;
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nonnull PolarisPrincipalSecrets rotatePrincipalSecretsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- @Nonnull String clientId,
- long principalId,
- boolean reset,
- @Nonnull String oldSecretHash) {
-
- // load the existing secrets
- PolarisPrincipalSecrets principalSecrets =
- ModelPrincipalSecrets.toPrincipalSecrets(
- this.store.lookupPrincipalSecrets(localSession.get(), clientId));
-
- // should be found
- getDiagnostics()
- .checkNotNull(
- principalSecrets,
- "cannot_find_secrets",
- "client_id={} principalId={}",
- clientId,
- principalId);
-
- // ensure principal id is matching
- getDiagnostics()
- .check(
- principalId == principalSecrets.getPrincipalId(),
- "principal_id_mismatch",
- "expectedId={} id={}",
- principalId,
- principalSecrets.getPrincipalId());
-
- // rotate the secrets
- principalSecrets.rotateSecrets(oldSecretHash);
- if (reset) {
- principalSecrets.rotateSecrets(principalSecrets.getMainSecretHash());
- }
-
- // write back new secrets
- this.store.writePrincipalSecrets(localSession.get(), principalSecrets);
-
- // return those
- return principalSecrets;
- }
-
- /** {@inheritDoc} */
- @Override
- public void deletePrincipalSecretsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull String clientId, long principalId) {
- // load the existing secrets
- ModelPrincipalSecrets principalSecrets =
- this.store.lookupPrincipalSecrets(localSession.get(), clientId);
-
- // should be found
- getDiagnostics()
- .checkNotNull(
- principalSecrets,
- "cannot_find_secrets",
- "client_id={} principalId={}",
- clientId,
- principalId);
-
- // ensure principal id is matching
- getDiagnostics()
- .check(
- principalId == principalSecrets.getPrincipalId(),
- "principal_id_mismatch",
- "expectedId={} id={}",
- principalId,
- principalSecrets.getPrincipalId());
-
- // delete these secrets
- this.store.deletePrincipalSecrets(localSession.get(), clientId);
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nullable
- PolarisStorageIntegration createStorageIntegrationInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- long catalogId,
- long entityId,
- PolarisStorageConfigurationInfo polarisStorageConfigurationInfo) {
- return storageIntegrationProvider.getStorageIntegrationForConfig(
- polarisStorageConfigurationInfo);
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nullable
- PolarisStorageIntegration loadPolarisStorageIntegrationInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisBaseEntity entity) {
- PolarisStorageConfigurationInfo storageConfig =
- BaseMetaStoreManager.extractStorageConfiguration(getDiagnostics(), entity);
- return storageIntegrationProvider.getStorageIntegrationForConfig(storageConfig);
- }
-
- /** {@inheritDoc} */
- @Override
- public void writeToPolicyMappingRecordsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisPolicyMappingRecord record) {
-
- this.store.writeToPolicyMappingRecords(localSession.get(), record);
- }
-
- /** {@inheritDoc} */
- @Override
- public void deleteFromPolicyMappingRecordsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, @Nonnull PolarisPolicyMappingRecord record) {
- this.store.deleteFromPolicyMappingRecords(localSession.get(), record);
- }
-
- /** {@inheritDoc} */
- @Override
- public void deleteAllEntityPolicyMappingRecordsInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- @Nonnull PolarisBaseEntity entity,
- @Nonnull List mappingOnTarget,
- @Nonnull List mappingOnPolicy) {
- this.store.deleteAllEntityPolicyMappingRecords(localSession.get(), entity);
- }
-
- /** {@inheritDoc} */
- @Nullable
- @Override
- public PolarisPolicyMappingRecord lookupPolicyMappingRecordInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- long targetCatalogId,
- long targetId,
- int policyTypeCode,
- long policyCatalogId,
- long policyId) {
- return ModelPolicyMappingRecord.toPolicyMappingRecord(
- this.store.lookupPolicyMappingRecord(
- localSession.get(),
- targetCatalogId,
- targetId,
- policyTypeCode,
- policyCatalogId,
- policyId));
- }
-
- /** {@inheritDoc} */
- @Nonnull
- @Override
- public List loadPoliciesOnTargetByTypeInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- long targetCatalogId,
- long targetId,
- int policyTypeCode) {
- return this.store
- .loadPoliciesOnTargetByType(localSession.get(), targetCatalogId, targetId, policyTypeCode)
- .stream()
- .map(ModelPolicyMappingRecord::toPolicyMappingRecord)
- .toList();
- }
-
- /** {@inheritDoc} */
- @Nonnull
- @Override
- public List loadAllPoliciesOnTargetInCurrentTxn(
- @Nonnull PolarisCallContext callCtx, long targetCatalogId, long targetId) {
- return this.store
- .loadAllPoliciesOnTarget(localSession.get(), targetCatalogId, targetId)
- .stream()
- .map(ModelPolicyMappingRecord::toPolicyMappingRecord)
- .toList();
- }
-
- /** {@inheritDoc} */
- @Nonnull
- @Override
- public List loadAllTargetsOnPolicyInCurrentTxn(
- @Nonnull PolarisCallContext callCtx,
- long policyCatalogId,
- long policyId,
- int policyTypeCode) {
- return this.store
- .loadAllTargetsOnPolicy(localSession.get(), policyCatalogId, policyId, policyTypeCode)
- .stream()
- .map(ModelPolicyMappingRecord::toPolicyMappingRecord)
- .toList();
- }
-
- @Override
- public void rollback() {
- EntityManager session = localSession.get();
- if (session != null) {
- session.getTransaction().rollback();
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public
- Optional> hasOverlappingSiblings(
- @Nonnull PolarisCallContext callContext, T entity) {
- return Optional.empty();
- }
-
- @Nullable
- @Override
- public PolarisPrincipalSecrets storePrincipalSecrets(
- @Nonnull PolarisCallContext callCtx,
- long principalId,
- @Nonnull String resolvedClientId,
- String customClientSecret) {
- throw new UnsupportedOperationException(
- "This method is not supported for EclipseLink as metastore");
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkPersistenceUnit.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkPersistenceUnit.java
deleted file mode 100644
index 89d9d0eb8c..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkPersistenceUnit.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink;
-
-import static org.eclipse.persistence.config.PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML;
-import static org.eclipse.persistence.config.PersistenceUnitProperties.JDBC_URL;
-
-import jakarta.annotation.Nonnull;
-import jakarta.annotation.Nullable;
-import jakarta.persistence.EntityManagerFactory;
-import jakarta.persistence.Persistence;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
-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.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;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-sealed interface PolarisEclipseLinkPersistenceUnit
- permits ClasspathResourcePolarisEclipseLinkPersistenceUnit,
- FileSystemPolarisEclipseLinkPersistenceUnit,
- JarFilePolarisEclipseLinkPersistenceUnit {
-
- Map loadProperties() throws IOException;
-
- EntityManagerFactory createEntityManagerFactory(@Nonnull RealmContext realmContext)
- throws IOException;
-
- record ClasspathResourcePolarisEclipseLinkPersistenceUnit(
- URL resource, String resourceName, String persistenceUnitName)
- implements PolarisEclipseLinkPersistenceUnit {
-
- @Override
- public Map loadProperties() throws IOException {
- var properties = internalLoadProperties(resource, persistenceUnitName);
- properties.put(ECLIPSELINK_PERSISTENCE_XML, resourceName);
- return properties;
- }
-
- @Override
- public EntityManagerFactory createEntityManagerFactory(@Nonnull RealmContext realmContext)
- throws IOException {
- var properties = transformJdbcUrl(loadProperties(), realmContext);
- return Persistence.createEntityManagerFactory(persistenceUnitName, properties);
- }
- }
-
- record FileSystemPolarisEclipseLinkPersistenceUnit(Path path, String persistenceUnitName)
- implements PolarisEclipseLinkPersistenceUnit {
-
- @Override
- public Map loadProperties() throws IOException {
- var properties = internalLoadProperties(path.toUri().toURL(), persistenceUnitName);
- Path archiveDirectory = path.getParent();
- String descriptorPath = archiveDirectory.getParent().relativize(path).toString();
- properties.put(ECLIPSELINK_PERSISTENCE_XML, descriptorPath);
- return properties;
- }
-
- @Override
- public EntityManagerFactory createEntityManagerFactory(@Nonnull RealmContext realmContext)
- throws IOException {
- var properties = transformJdbcUrl(loadProperties(), realmContext);
- Path archiveDirectory = path.getParent();
- ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
- try (URLClassLoader currentClassLoader =
- new URLClassLoader(
- new URL[] {archiveDirectory.getParent().toUri().toURL()},
- this.getClass().getClassLoader())) {
- Thread.currentThread().setContextClassLoader(currentClassLoader);
- return Persistence.createEntityManagerFactory(persistenceUnitName, properties);
- } finally {
- Thread.currentThread().setContextClassLoader(prevClassLoader);
- }
- }
- }
-
- record JarFilePolarisEclipseLinkPersistenceUnit(
- URL confUrl, URL jarUrl, String descriptorPath, String persistenceUnitName)
- implements PolarisEclipseLinkPersistenceUnit {
-
- @Override
- public Map loadProperties() throws IOException {
- var properties = internalLoadProperties(confUrl, persistenceUnitName);
- properties.put(ECLIPSELINK_PERSISTENCE_XML, descriptorPath);
- return properties;
- }
-
- @Override
- public EntityManagerFactory createEntityManagerFactory(@Nonnull RealmContext realmContext)
- throws IOException {
- var properties = transformJdbcUrl(loadProperties(), realmContext);
- ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
- try (URLClassLoader currentClassLoader =
- new URLClassLoader(new URL[] {jarUrl}, this.getClass().getClassLoader())) {
- Thread.currentThread().setContextClassLoader(currentClassLoader);
- return Persistence.createEntityManagerFactory(persistenceUnitName, properties);
- } finally {
- Thread.currentThread().setContextClassLoader(prevClassLoader);
- }
- }
- }
-
- static PolarisEclipseLinkPersistenceUnit locatePersistenceUnit(
- @Nullable String confFile, @Nullable String persistenceUnitName) throws IOException {
- if (persistenceUnitName == null) {
- persistenceUnitName = "polaris";
- }
- if (confFile == null) {
- confFile = "META-INF/persistence.xml";
- }
- // Try an embedded config file first
- int splitPosition = confFile.indexOf("!/");
- if (splitPosition != -1) {
- String jarPrefix = confFile.substring(0, splitPosition);
- String descriptorPath = confFile.substring(splitPosition + 2);
- URL jarUrl = classpathResource(jarPrefix);
- if (jarUrl != null) {
- // The JAR is in the classpath
- URL confUrl = URI.create("jar:" + jarUrl + "!/" + descriptorPath).toURL();
- return new ClasspathResourcePolarisEclipseLinkPersistenceUnit(
- confUrl, confFile, persistenceUnitName);
- } else {
- // The JAR is in the filesystem
- jarUrl = fileSystemPath(jarPrefix).toUri().toURL();
- URL confUrl = URI.create("jar:" + jarUrl + "!/" + descriptorPath).toURL();
- return new JarFilePolarisEclipseLinkPersistenceUnit(
- confUrl, jarUrl, descriptorPath, persistenceUnitName);
- }
- }
- // Try a classpath resource next
- URL resource = classpathResource(confFile);
- if (resource != null) {
- return new ClasspathResourcePolarisEclipseLinkPersistenceUnit(
- resource, confFile, persistenceUnitName);
- }
- // Try a filesystem path last
- try {
- return new FileSystemPolarisEclipseLinkPersistenceUnit(
- fileSystemPath(confFile), persistenceUnitName);
- } catch (Exception e) {
- throw new IllegalStateException("Cannot find classpath resource or file: " + confFile, e);
- }
- }
-
- private static Path fileSystemPath(String pathStr) {
- Path path = Paths.get(pathStr);
- if (!Files.exists(path) || !Files.isRegularFile(path)) {
- throw new IllegalStateException("Not a regular file: " + pathStr);
- }
- return path.normalize().toAbsolutePath();
- }
-
- @Nullable
- private static URL classpathResource(String resourceName) throws IOException {
- Enumeration resources =
- Thread.currentThread().getContextClassLoader().getResources(resourceName);
- if (resources.hasMoreElements()) {
- URL resource = resources.nextElement();
- if (resources.hasMoreElements()) {
- throw new IllegalStateException(
- "Multiple resources found in classpath for " + resourceName);
- }
- return resource;
- }
- return null;
- }
-
- /** Load the persistence unit properties from a given configuration file */
- private static Map internalLoadProperties(
- @Nonnull URL confFile, @Nonnull String persistenceUnitName) throws IOException {
- try (InputStream input = confFile.openStream()) {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder builder = factory.newDocumentBuilder();
- Document doc = builder.parse(input);
- XPath xPath = XPathFactory.newInstance().newXPath();
- String expression =
- "/persistence/persistence-unit[@name='" + persistenceUnitName + "']/properties/property";
- NodeList nodeList =
- (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);
- Map properties = new HashMap<>();
- for (int i = 0; i < nodeList.getLength(); i++) {
- NamedNodeMap nodeMap = nodeList.item(i).getAttributes();
- properties.put(
- nodeMap.getNamedItem("name").getNodeValue(),
- nodeMap.getNamedItem("value").getNodeValue());
- }
-
- return properties;
- } catch (XPathExpressionException
- | ParserConfigurationException
- | SAXException
- | IOException e) {
- String str =
- String.format(
- "Cannot find or parse the configuration file %s for persistence-unit %s",
- confFile, persistenceUnitName);
- throw new IOException(str, e);
- }
- }
-
- private static Map transformJdbcUrl(
- Map properties, RealmContext realmContext) {
- if (properties.containsKey(JDBC_URL)) {
- properties.put(
- JDBC_URL, properties.get(JDBC_URL).replace("{realm}", realmContext.getRealmIdentifier()));
- }
- return properties;
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkSessionCustomizer.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkSessionCustomizer.java
deleted file mode 100644
index e62c840498..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkSessionCustomizer.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink;
-
-import org.eclipse.persistence.sessions.DatabaseLogin;
-import org.eclipse.persistence.sessions.Session;
-import org.eclipse.persistence.sessions.SessionCustomizer;
-
-/**
- * This pattern of injecting a SessionCustomizer is taken from the EclipseLink guide documentation:
- *
- * https://eclipse.dev/eclipselink/documentation/4.0/dbws/dbws.html#performing-intermediate-customization
- */
-public class PolarisEclipseLinkSessionCustomizer implements SessionCustomizer {
- @Override
- public void customize(Session session) throws Exception {
- DatabaseLogin databaseLogin = (DatabaseLogin) session.getDatasourceLogin();
- databaseLogin.setTransactionIsolation(DatabaseLogin.TRANSACTION_SERIALIZABLE);
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkStore.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkStore.java
deleted file mode 100644
index 223567073a..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkStore.java
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink;
-
-import jakarta.annotation.Nonnull;
-import jakarta.annotation.Nullable;
-import jakarta.persistence.EntityManager;
-import jakarta.persistence.TypedQuery;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-import org.apache.polaris.core.PolarisDiagnostics;
-import org.apache.polaris.core.entity.EntityNameLookupRecord;
-import org.apache.polaris.core.entity.PolarisBaseEntity;
-import org.apache.polaris.core.entity.PolarisEntitiesActiveKey;
-import org.apache.polaris.core.entity.PolarisEntityCore;
-import org.apache.polaris.core.entity.PolarisEntityId;
-import org.apache.polaris.core.entity.PolarisEntitySubType;
-import org.apache.polaris.core.entity.PolarisEntityType;
-import org.apache.polaris.core.entity.PolarisGrantRecord;
-import org.apache.polaris.core.entity.PolarisPrincipalSecrets;
-import org.apache.polaris.core.persistence.pagination.EntityIdToken;
-import org.apache.polaris.core.persistence.pagination.PageToken;
-import org.apache.polaris.core.policy.PolarisPolicyMappingRecord;
-import org.apache.polaris.core.policy.PolicyEntity;
-import org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntity;
-import org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityActive;
-import org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityChangeTracking;
-import org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelGrantRecord;
-import org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelPolicyMappingRecord;
-import org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelPrincipalSecrets;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Implements an EclipseLink based metastore for Polaris which can be configured for any database
- * with EclipseLink support
- */
-public class PolarisEclipseLinkStore {
- private static final Logger LOGGER = LoggerFactory.getLogger(PolarisEclipseLinkStore.class);
-
- // diagnostic services
- private final PolarisDiagnostics diagnosticServices;
-
- // Used to track when the store is initialized
- private final AtomicBoolean initialized = new AtomicBoolean(false);
-
- /**
- * Constructor, allocate everything at once
- *
- * @param diagnostics diagnostic services
- */
- public PolarisEclipseLinkStore(@Nonnull PolarisDiagnostics diagnostics) {
- this.diagnosticServices = diagnostics;
- }
-
- /** Initialize the store. This should be called before other methods. */
- public void initialize(EntityManager session) {
- PolarisSequenceUtil.initialize(session);
- initialized.set(true);
- }
-
- long getNextSequence(EntityManager session) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return PolarisSequenceUtil.getNewId(session);
- }
-
- void writeToEntities(EntityManager session, PolarisBaseEntity entity) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelEntity model =
- lookupEntity(session, entity.getCatalogId(), entity.getId(), entity.getTypeCode());
- if (model != null) {
- // Update if the same entity already exists
- model.update(entity);
- } else {
- model = ModelEntity.fromEntity(entity);
- }
-
- session.persist(model);
- }
-
- void writeToEntitiesActive(EntityManager session, PolarisBaseEntity entity) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelEntityActive model = lookupEntityActive(session, new PolarisEntitiesActiveKey(entity));
- if (model == null) {
- session.persist(ModelEntityActive.fromEntityActive(new EntityNameLookupRecord(entity)));
- }
- }
-
- void writeToEntitiesChangeTracking(EntityManager session, PolarisBaseEntity entity) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- // Update the existing change tracking if a record with the same ids exists; otherwise, persist
- // a new one
- ModelEntityChangeTracking entityChangeTracking =
- lookupEntityChangeTracking(session, entity.getCatalogId(), entity.getId());
- if (entityChangeTracking != null) {
- entityChangeTracking.update(entity);
- } else {
- entityChangeTracking = new ModelEntityChangeTracking(entity);
- }
-
- session.persist(entityChangeTracking);
- }
-
- void writeToGrantRecords(EntityManager session, PolarisGrantRecord grantRec) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- session.persist(ModelGrantRecord.fromGrantRecord(grantRec));
- }
-
- void deleteFromEntities(EntityManager session, long catalogId, long entityId, int typeCode) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelEntity model = lookupEntity(session, catalogId, entityId, typeCode);
- diagnosticServices.check(model != null, "entity_not_found");
-
- session.remove(model);
- }
-
- void deleteFromEntitiesActive(EntityManager session, PolarisEntitiesActiveKey key) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelEntityActive entity = lookupEntityActive(session, key);
- diagnosticServices.check(entity != null, "active_entity_not_found");
- session.remove(entity);
- }
-
- void deleteFromEntitiesChangeTracking(EntityManager session, PolarisEntityCore entity) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelEntityChangeTracking entityChangeTracking =
- lookupEntityChangeTracking(session, entity.getCatalogId(), entity.getId());
- diagnosticServices.check(entityChangeTracking != null, "change_tracking_entity_not_found");
-
- session.remove(entityChangeTracking);
- }
-
- void deleteFromGrantRecords(EntityManager session, PolarisGrantRecord grantRec) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelGrantRecord lookupGrantRecord =
- lookupGrantRecord(
- session,
- grantRec.getSecurableCatalogId(),
- grantRec.getSecurableId(),
- grantRec.getGranteeCatalogId(),
- grantRec.getGranteeId(),
- grantRec.getPrivilegeCode());
-
- diagnosticServices.check(lookupGrantRecord != null, "grant_record_not_found");
-
- session.remove(lookupGrantRecord);
- }
-
- void deleteAllEntityGrantRecords(EntityManager session, PolarisEntityCore entity) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- // Delete grant records from grantRecords tables
- lookupAllGrantRecordsOnSecurable(session, entity.getCatalogId(), entity.getId())
- .forEach(session::remove);
-
- // Delete grantee records from grantRecords tables
- lookupGrantRecordsOnGrantee(session, entity.getCatalogId(), entity.getId())
- .forEach(session::remove);
- }
-
- void deleteAll(EntityManager session) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- session.createQuery("DELETE from ModelEntity").executeUpdate();
- session.createQuery("DELETE from ModelEntityActive").executeUpdate();
- session.createQuery("DELETE from ModelEntityChangeTracking").executeUpdate();
- session.createQuery("DELETE from ModelGrantRecord").executeUpdate();
- session.createQuery("DELETE from ModelPrincipalSecrets").executeUpdate();
-
- LOGGER.debug("All entities deleted.");
- }
-
- ModelEntity lookupEntity(EntityManager session, long catalogId, long entityId, long typeCode) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelEntity m where m.catalogId=:catalogId and m.id=:id and m.typeCode=:typeCode",
- ModelEntity.class)
- .setParameter("typeCode", typeCode)
- .setParameter("catalogId", catalogId)
- .setParameter("id", entityId)
- .getResultStream()
- .findFirst()
- .orElse(null);
- }
-
- @SuppressWarnings("unchecked")
- List lookupEntities(EntityManager session, List entityIds) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- if (entityIds == null || entityIds.isEmpty()) return new ArrayList<>();
-
- // TODO Support paging
- String inClause =
- entityIds.stream()
- .map(entityId -> "(" + entityId.getCatalogId() + "," + entityId.getId() + ")")
- .collect(Collectors.joining(","));
-
- String hql = "SELECT * from ENTITIES m where (m.catalogId, m.id) in (" + inClause + ")";
- return (List) session.createNativeQuery(hql, ModelEntity.class).getResultList();
- }
-
- ModelEntityActive lookupEntityActive(
- EntityManager session, PolarisEntitiesActiveKey entityActiveKey) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelEntityActive m where m.catalogId=:catalogId and m.parentId=:parentId and m.typeCode=:typeCode and m.name=:name",
- ModelEntityActive.class)
- .setParameter("catalogId", entityActiveKey.getCatalogId())
- .setParameter("parentId", entityActiveKey.getParentId())
- .setParameter("typeCode", entityActiveKey.getTypeCode())
- .setParameter("name", entityActiveKey.getName())
- .getResultStream()
- .findFirst()
- .orElse(null);
- }
-
- long countActiveChildEntities(
- EntityManager session,
- long catalogId,
- long parentId,
- @Nullable PolarisEntityType entityType) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- String hql =
- "SELECT COUNT(m) from ModelEntityActive m where m.catalogId=:catalogId and m.parentId=:parentId";
- if (entityType != null) {
- hql += " and m.typeCode=:typeCode";
- }
-
- TypedQuery query =
- session
- .createQuery(hql, Long.class)
- .setParameter("catalogId", catalogId)
- .setParameter("parentId", parentId);
- if (entityType != null) {
- query.setParameter("typeCode", entityType.getCode());
- }
-
- return query.getSingleResult();
- }
-
- List lookupFullEntitiesActive(
- EntityManager session,
- long catalogId,
- long parentId,
- @Nonnull PolarisEntityType entityType,
- @Nonnull PolarisEntitySubType entitySubType,
- @Nonnull PageToken pageToken) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- // Currently check against ENTITIES not joining with ENTITIES_ACTIVE
- String hql =
- "SELECT m from ModelEntity m where"
- + " m.catalogId=:catalogId and m.parentId=:parentId and m.typeCode=:typeCode";
-
- if (entitySubType != PolarisEntitySubType.ANY_SUBTYPE) {
- hql += " and m.subTypeCode=:subTypeCode";
- }
-
- var entityIdToken = pageToken.valueAs(EntityIdToken.class);
- if (entityIdToken.isPresent()) {
- hql += " and m.id > :tokenId";
- }
-
- if (pageToken.paginationRequested()) {
- hql += " order by m.id asc";
- }
-
- TypedQuery query =
- session
- .createQuery(hql, ModelEntity.class)
- .setParameter("catalogId", catalogId)
- .setParameter("parentId", parentId)
- .setParameter("typeCode", entityType.getCode());
-
- if (entitySubType != PolarisEntitySubType.ANY_SUBTYPE) {
- query.setParameter("subTypeCode", entitySubType.getCode());
- }
-
- if (entityIdToken.isPresent()) {
- long tokenId = entityIdToken.get().entityId();
- query = query.setParameter("tokenId", tokenId);
- }
-
- return query.getResultList();
- }
-
- ModelEntityChangeTracking lookupEntityChangeTracking(
- EntityManager session, long catalogId, long entityId) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelEntityChangeTracking m where m.catalogId=:catalogId and m.id=:id",
- ModelEntityChangeTracking.class)
- .setParameter("catalogId", catalogId)
- .setParameter("id", entityId)
- .getResultStream()
- .findFirst()
- .orElse(null);
- }
-
- ModelGrantRecord lookupGrantRecord(
- EntityManager session,
- long securableCatalogId,
- long securableId,
- long granteeCatalogId,
- long granteeId,
- int privilegeCode) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelGrantRecord m where m.securableCatalogId=:securableCatalogId "
- + "and m.securableId=:securableId "
- + "and m.granteeCatalogId=:granteeCatalogId "
- + "and m.granteeId=:granteeId "
- + "and m.privilegeCode=:privilegeCode",
- ModelGrantRecord.class)
- .setParameter("securableCatalogId", securableCatalogId)
- .setParameter("securableId", securableId)
- .setParameter("granteeCatalogId", granteeCatalogId)
- .setParameter("granteeId", granteeId)
- .setParameter("privilegeCode", privilegeCode)
- .getResultStream()
- .findFirst()
- .orElse(null);
- }
-
- List lookupAllGrantRecordsOnSecurable(
- EntityManager session, long securableCatalogId, long securableId) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelGrantRecord m "
- + "where m.securableCatalogId=:securableCatalogId "
- + "and m.securableId=:securableId",
- ModelGrantRecord.class)
- .setParameter("securableCatalogId", securableCatalogId)
- .setParameter("securableId", securableId)
- .getResultList();
- }
-
- List lookupGrantRecordsOnGrantee(
- EntityManager session, long granteeCatalogId, long granteeId) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelGrantRecord m "
- + "where m.granteeCatalogId=:granteeCatalogId "
- + "and m.granteeId=:granteeId",
- ModelGrantRecord.class)
- .setParameter("granteeCatalogId", granteeCatalogId)
- .setParameter("granteeId", granteeId)
- .getResultList();
- }
-
- ModelPrincipalSecrets lookupPrincipalSecrets(EntityManager session, String clientId) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelPrincipalSecrets m where m.principalClientId=:clientId",
- ModelPrincipalSecrets.class)
- .setParameter("clientId", clientId)
- .getResultStream()
- .findFirst()
- .orElse(null);
- }
-
- void writePrincipalSecrets(EntityManager session, PolarisPrincipalSecrets principalSecrets) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelPrincipalSecrets modelPrincipalSecrets =
- lookupPrincipalSecrets(session, principalSecrets.getPrincipalClientId());
- if (modelPrincipalSecrets != null) {
- modelPrincipalSecrets.update(principalSecrets);
- } else {
- modelPrincipalSecrets = ModelPrincipalSecrets.fromPrincipalSecrets(principalSecrets);
- }
-
- session.persist(modelPrincipalSecrets);
- }
-
- void deletePrincipalSecrets(EntityManager session, String clientId) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelPrincipalSecrets modelPrincipalSecrets = lookupPrincipalSecrets(session, clientId);
- diagnosticServices.check(modelPrincipalSecrets != null, "principal_secretes_not_found");
-
- session.remove(modelPrincipalSecrets);
- }
-
- void writeToPolicyMappingRecords(
- EntityManager session, PolarisPolicyMappingRecord mappingRecord) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- // TODO: combine existence check and write into one statement
- ModelPolicyMappingRecord model =
- lookupPolicyMappingRecord(
- session,
- mappingRecord.getTargetCatalogId(),
- mappingRecord.getTargetId(),
- mappingRecord.getPolicyTypeCode(),
- mappingRecord.getPolicyCatalogId(),
- mappingRecord.getPolicyId());
- if (model != null) {
- model.update(mappingRecord);
- } else {
- model = ModelPolicyMappingRecord.fromPolicyMappingRecord(mappingRecord);
- }
-
- session.persist(model);
- }
-
- void deleteFromPolicyMappingRecords(
- EntityManager session, PolarisPolicyMappingRecord mappingRecord) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- ModelPolicyMappingRecord lookupPolicyMappingRecord =
- lookupPolicyMappingRecord(
- session,
- mappingRecord.getTargetCatalogId(),
- mappingRecord.getTargetId(),
- mappingRecord.getPolicyTypeCode(),
- mappingRecord.getPolicyCatalogId(),
- mappingRecord.getPolicyId());
-
- diagnosticServices.check(lookupPolicyMappingRecord != null, "policy_mapping_record_not_found");
- session.remove(lookupPolicyMappingRecord);
- }
-
- void deleteAllEntityPolicyMappingRecords(EntityManager session, PolarisBaseEntity entity) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- if (entity.getType() == PolarisEntityType.POLICY) {
- PolicyEntity policyEntity = PolicyEntity.of(entity);
- loadAllTargetsOnPolicy(
- session,
- policyEntity.getCatalogId(),
- policyEntity.getId(),
- policyEntity.getPolicyTypeCode())
- .forEach(session::remove);
- } else {
- loadAllPoliciesOnTarget(session, entity.getCatalogId(), entity.getId())
- .forEach(session::remove);
- }
- }
-
- ModelPolicyMappingRecord lookupPolicyMappingRecord(
- EntityManager session,
- long targetCatalogId,
- long targetId,
- int policyTypeCode,
- long policyCatalogId,
- long policyId) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelPolicyMappingRecord m "
- + "where m.targetCatalogId=:targetCatalogId "
- + "and m.targetId=:targetId "
- + "and m.policyTypeCode=:policyTypeCode "
- + "and m.policyCatalogId=:policyCatalogId "
- + "and m.policyId=:policyId",
- ModelPolicyMappingRecord.class)
- .setParameter("targetCatalogId", targetCatalogId)
- .setParameter("targetId", targetId)
- .setParameter("policyTypeCode", policyTypeCode)
- .setParameter("policyCatalogId", policyCatalogId)
- .setParameter("policyId", policyId)
- .getResultStream()
- .findFirst()
- .orElse(null);
- }
-
- List loadPoliciesOnTargetByType(
- EntityManager session, long targetCatalogId, long targetId, int policyTypeCode) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelPolicyMappingRecord m "
- + "where m.targetCatalogId=:targetCatalogId "
- + "and m.targetId=:targetId "
- + "and m.policyTypeCode=:policyTypeCode",
- ModelPolicyMappingRecord.class)
- .setParameter("targetCatalogId", targetCatalogId)
- .setParameter("targetId", targetId)
- .setParameter("policyTypeCode", policyTypeCode)
- .getResultList();
- }
-
- List loadAllPoliciesOnTarget(
- EntityManager session, long targetCatalogId, long targetId) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelPolicyMappingRecord m "
- + " where m.targetCatalogId=:targetCatalogId "
- + "and m.targetId=:targetId",
- ModelPolicyMappingRecord.class)
- .setParameter("targetCatalogId", targetCatalogId)
- .setParameter("targetId", targetId)
- .getResultList();
- }
-
- List loadAllTargetsOnPolicy(
- EntityManager session, long policyCatalogId, long policyId, int policyTypeCode) {
- diagnosticServices.check(session != null, "session_is_null");
- checkInitialized();
-
- return session
- .createQuery(
- "SELECT m from ModelPolicyMappingRecord m "
- + "where m.policyTypeCode=:policyTypeCode "
- + "and m.policyCatalogId=:policyCatalogId "
- + "and m.policyId=:policyId",
- ModelPolicyMappingRecord.class)
- .setParameter("policyTypeCode", policyTypeCode)
- .setParameter("policyCatalogId", policyCatalogId)
- .setParameter("policyId", policyId)
- .getResultList();
- }
-
- private void checkInitialized() {
- diagnosticServices.check(this.initialized.get(), "store_not_initialized");
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisSequenceUtil.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisSequenceUtil.java
deleted file mode 100644
index ba1ec9f1f1..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisSequenceUtil.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink;
-
-import jakarta.persistence.EntityManager;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelSequenceId;
-import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
-import org.eclipse.persistence.platform.database.DatabasePlatform;
-import org.eclipse.persistence.platform.database.PostgreSQLPlatform;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Used to generate sequence IDs for Polaris entities. If the legacy `POLARIS_SEQ` generator is
- * available it will be used then cleaned up. In all other cases the `POLARIS_SEQUENCE` table is
- * used directly.
- */
-class PolarisSequenceUtil {
- private static final Logger LOGGER = LoggerFactory.getLogger(PolarisSequenceUtil.class);
-
- private static final AtomicBoolean initialized = new AtomicBoolean(false);
-
- private PolarisSequenceUtil() {}
-
- /* If `initialize` was never called, throw an exception */
- private static void throwIfNotInitialized() {
- if (!initialized.get()) {
- throw new IllegalStateException("Sequence util has not been initialized");
- }
- }
-
- /* Get the database platform associated with the `EntityManager` */
- private static DatabasePlatform getDatabasePlatform(EntityManager session) {
- EntityManagerImpl entityManagerImpl = session.unwrap(EntityManagerImpl.class);
- return entityManagerImpl.getDatabaseSession().getPlatform();
- }
-
- private static void removeSequence(EntityManager session) {
- LOGGER.info("Renaming legacy sequence `POLARIS_SEQ` to `POLARIS_SEQ_UNUSED`");
- String renameSequenceQuery = "ALTER SEQUENCE POLARIS_SEQ RENAME TO POLARIS_SEQ_UNUSED";
- session.createNativeQuery(renameSequenceQuery).executeUpdate();
- }
-
- /**
- * Prepare the `PolarisSequenceUtil` to generate IDs. This may run a failing query, so it should
- * be called for the first time outside the context of a transaction. This method should be called
- * before any other methods. TODO: after a sufficient this can eventually be removed or altered
- */
- public static void initialize(EntityManager session) {
- // Trigger cleanup of the POLARIS_SEQ if it is present
- DatabasePlatform databasePlatform = getDatabasePlatform(session);
- if (!initialized.get()) {
- if (databasePlatform instanceof PostgreSQLPlatform) {
- Optional result = Optional.empty();
- LOGGER.info("Checking if the sequence POLARIS_SEQ exists");
- String checkSequenceQuery =
- "SELECT COUNT(*) FROM information_schema.sequences WHERE sequence_name IN "
- + "('polaris_seq', 'POLARIS_SEQ')";
- int sequenceExists =
- ((Number) session.createNativeQuery(checkSequenceQuery).getSingleResult()).intValue();
-
- if (sequenceExists > 0) {
- LOGGER.info("POLARIS_SEQ exists, calling NEXTVAL");
- long queryResult =
- (long) session.createNativeQuery("SELECT NEXTVAL('POLARIS_SEQ')").getSingleResult();
- result = Optional.of(queryResult);
- } else {
- LOGGER.info("POLARIS_SEQ does not exist, skipping NEXTVAL");
- }
- result.ifPresent(
- r -> {
- ModelSequenceId modelSequenceId = new ModelSequenceId();
- modelSequenceId.setId(r);
-
- // Persist the new ID:
- session.persist(modelSequenceId);
- session.flush();
-
- // Clean the sequence:
- removeSequence(session);
- });
- }
- initialized.set(true);
- }
- }
-
- /**
- * Generates a new ID from `POLARIS_SEQUENCE` or `POLARIS_SEQ` depending on availability.
- * `initialize` should be called before this method.
- */
- public static Long getNewId(EntityManager session) {
- throwIfNotInitialized();
-
- ModelSequenceId modelSequenceId = new ModelSequenceId();
-
- // Persist the new ID:
- session.persist(modelSequenceId);
- session.flush();
-
- return modelSequenceId.getId();
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntity.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntity.java
deleted file mode 100644
index 2fed884579..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntity.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink.models;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import jakarta.persistence.Version;
-import org.apache.polaris.core.entity.PolarisBaseEntity;
-
-/**
- * Entity model representing all attributes of a Polaris Entity. This is used to exchange full
- * entity information with ENTITIES table
- */
-@Entity
-@Table(name = "ENTITIES")
-public class ModelEntity {
- // the id of the catalog associated to that entity. NULL_ID if this entity is top-level like
- // a catalog
- @Id private long catalogId;
-
- // the id of the entity which was resolved
- @Id private long id;
-
- // the id of the parent of this entity, use 0 for a top-level entity whose parent is the account
- private long parentId;
-
- // the type of the entity when it was resolved
- private int typeCode;
-
- // the name that this entity had when it was resolved
- private String name;
-
- // the version that this entity had when it was resolved
- private int entityVersion;
-
- public static final String EMPTY_MAP_STRING = "{}";
- // the type of the entity when it was resolved
- private int subTypeCode;
-
- // timestamp when this entity was created
- private long createTimestamp;
-
- // when this entity was dropped. Null if was never dropped
- private long dropTimestamp;
-
- // when did we start purging this entity. When not null, un-drop is no longer possible
- private long purgeTimestamp;
-
- // when should we start purging this entity
- private long toPurgeTimestamp;
-
- // last time this entity was updated, only for troubleshooting
- private long lastUpdateTimestamp;
-
- // properties, serialized as a JSON string
- @Column(columnDefinition = "TEXT")
- private String properties;
-
- // internal properties, serialized as a JSON string
- @Column(columnDefinition = "TEXT")
- private String internalProperties;
-
- // current version for that entity, will be monotonically incremented
- private int grantRecordsVersion;
-
- // Used for Optimistic Locking to handle concurrent reads and updates
- @Version private long version;
-
- public long getId() {
- return id;
- }
-
- public long getParentId() {
- return parentId;
- }
-
- public int getTypeCode() {
- return typeCode;
- }
-
- public String getName() {
- return name;
- }
-
- public int getEntityVersion() {
- return entityVersion;
- }
-
- public long getCatalogId() {
- return catalogId;
- }
-
- public int getSubTypeCode() {
- return subTypeCode;
- }
-
- public long getCreateTimestamp() {
- return createTimestamp;
- }
-
- public long getDropTimestamp() {
- return dropTimestamp;
- }
-
- public long getPurgeTimestamp() {
- return purgeTimestamp;
- }
-
- public long getToPurgeTimestamp() {
- return toPurgeTimestamp;
- }
-
- public long getLastUpdateTimestamp() {
- return lastUpdateTimestamp;
- }
-
- public String getProperties() {
- return properties != null ? properties : EMPTY_MAP_STRING;
- }
-
- public String getInternalProperties() {
- return internalProperties != null ? internalProperties : EMPTY_MAP_STRING;
- }
-
- public int getGrantRecordsVersion() {
- return grantRecordsVersion;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static final class Builder {
- private final ModelEntity entity;
-
- private Builder() {
- entity = new ModelEntity();
- }
-
- public Builder catalogId(long catalogId) {
- entity.catalogId = catalogId;
- return this;
- }
-
- public Builder id(long id) {
- entity.id = id;
- return this;
- }
-
- public Builder parentId(long parentId) {
- entity.parentId = parentId;
- return this;
- }
-
- public Builder typeCode(int typeCode) {
- entity.typeCode = typeCode;
- return this;
- }
-
- public Builder name(String name) {
- entity.name = name;
- return this;
- }
-
- public Builder entityVersion(int entityVersion) {
- entity.entityVersion = entityVersion;
- return this;
- }
-
- public Builder subTypeCode(int subTypeCode) {
- entity.subTypeCode = subTypeCode;
- return this;
- }
-
- public Builder createTimestamp(long createTimestamp) {
- entity.createTimestamp = createTimestamp;
- return this;
- }
-
- public Builder dropTimestamp(long dropTimestamp) {
- entity.dropTimestamp = dropTimestamp;
- return this;
- }
-
- public Builder purgeTimestamp(long purgeTimestamp) {
- entity.purgeTimestamp = purgeTimestamp;
- return this;
- }
-
- public Builder toPurgeTimestamp(long toPurgeTimestamp) {
- entity.toPurgeTimestamp = toPurgeTimestamp;
- return this;
- }
-
- public Builder lastUpdateTimestamp(long lastUpdateTimestamp) {
- entity.lastUpdateTimestamp = lastUpdateTimestamp;
- return this;
- }
-
- public Builder properties(String properties) {
- entity.properties = properties;
- return this;
- }
-
- public Builder internalProperties(String internalProperties) {
- entity.internalProperties = internalProperties;
- return this;
- }
-
- public Builder grantRecordsVersion(int grantRecordsVersion) {
- entity.grantRecordsVersion = grantRecordsVersion;
- return this;
- }
-
- public ModelEntity build() {
- return entity;
- }
- }
-
- public static ModelEntity fromEntity(PolarisBaseEntity entity) {
- return ModelEntity.builder()
- .catalogId(entity.getCatalogId())
- .id(entity.getId())
- .parentId(entity.getParentId())
- .typeCode(entity.getTypeCode())
- .name(entity.getName())
- .entityVersion(entity.getEntityVersion())
- .subTypeCode(entity.getSubTypeCode())
- .createTimestamp(entity.getCreateTimestamp())
- .dropTimestamp(entity.getDropTimestamp())
- .purgeTimestamp(entity.getPurgeTimestamp())
- .toPurgeTimestamp(entity.getToPurgeTimestamp())
- .lastUpdateTimestamp(entity.getLastUpdateTimestamp())
- .properties(entity.getProperties())
- .internalProperties(entity.getInternalProperties())
- .grantRecordsVersion(entity.getGrantRecordsVersion())
- .build();
- }
-
- public static PolarisBaseEntity toEntity(ModelEntity model) {
- if (model == null) {
- return null;
- }
-
- return new PolarisBaseEntity.Builder()
- .catalogId(model.getCatalogId())
- .id(model.getId())
- .typeCode(model.getTypeCode())
- .subTypeCode(model.getSubTypeCode())
- .parentId(model.getParentId())
- .name(model.getName())
- .entityVersion(model.getEntityVersion())
- .createTimestamp(model.getCreateTimestamp())
- .dropTimestamp(model.getDropTimestamp())
- .purgeTimestamp(model.getPurgeTimestamp())
- .toPurgeTimestamp(model.getToPurgeTimestamp())
- .lastUpdateTimestamp(model.getLastUpdateTimestamp())
- .properties(model.getProperties())
- .internalProperties(model.getInternalProperties())
- .grantRecordsVersion(model.getGrantRecordsVersion())
- .build();
- }
-
- public void update(PolarisBaseEntity entity) {
- if (entity == null) return;
-
- this.catalogId = entity.getCatalogId();
- this.id = entity.getId();
- this.parentId = entity.getParentId();
- this.typeCode = entity.getTypeCode();
- this.name = entity.getName();
- this.entityVersion = entity.getEntityVersion();
- this.subTypeCode = entity.getSubTypeCode();
- this.createTimestamp = entity.getCreateTimestamp();
- this.dropTimestamp = entity.getDropTimestamp();
- this.purgeTimestamp = entity.getPurgeTimestamp();
- this.toPurgeTimestamp = entity.getToPurgeTimestamp();
- this.lastUpdateTimestamp = entity.getLastUpdateTimestamp();
- this.properties = entity.getProperties();
- this.internalProperties = entity.getInternalProperties();
- this.grantRecordsVersion = entity.getGrantRecordsVersion();
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntityActive.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntityActive.java
deleted file mode 100644
index 8e9bd8c8b6..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntityActive.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink.models;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import org.apache.polaris.core.entity.EntityNameLookupRecord;
-import org.apache.polaris.core.entity.PolarisEntitySubType;
-import org.apache.polaris.core.entity.PolarisEntityType;
-
-/**
- * EntityActive model representing some attributes of a Polaris Entity. This is used to exchange
- * entity information with ENTITIES_ACTIVE table
- */
-@Entity
-@Table(name = "ENTITIES_ACTIVE")
-public class ModelEntityActive {
- // entity catalog id
- @Id private long catalogId;
-
- // id of the entity
- @Id private long id;
-
- // parent id of the entity
- @Id private long parentId;
-
- // name of the entity
- private String name;
-
- // code representing the type of that entity
- @Id private int typeCode;
-
- // code representing the subtype of that entity
- private int subTypeCode;
-
- public long getCatalogId() {
- return catalogId;
- }
-
- public long getId() {
- return id;
- }
-
- public long getParentId() {
- return parentId;
- }
-
- public String getName() {
- return name;
- }
-
- public int getTypeCode() {
- return typeCode;
- }
-
- public PolarisEntityType getType() {
- return PolarisEntityType.fromCode(this.typeCode);
- }
-
- public int getSubTypeCode() {
- return subTypeCode;
- }
-
- public PolarisEntitySubType getSubType() {
- return PolarisEntitySubType.fromCode(this.subTypeCode);
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static final class Builder {
- private final ModelEntityActive entity;
-
- private Builder() {
- entity = new ModelEntityActive();
- }
-
- public Builder catalogId(long catalogId) {
- entity.catalogId = catalogId;
- return this;
- }
-
- public Builder id(long id) {
- entity.id = id;
- return this;
- }
-
- public Builder parentId(long parentId) {
- entity.parentId = parentId;
- return this;
- }
-
- public Builder typeCode(int typeCode) {
- entity.typeCode = typeCode;
- return this;
- }
-
- public Builder name(String name) {
- entity.name = name;
- return this;
- }
-
- public Builder subTypeCode(int subTypeCode) {
- entity.subTypeCode = subTypeCode;
- return this;
- }
-
- public ModelEntityActive build() {
- return entity;
- }
- }
-
- public static ModelEntityActive fromEntityActive(EntityNameLookupRecord record) {
- return ModelEntityActive.builder()
- .catalogId(record.getCatalogId())
- .id(record.getId())
- .parentId(record.getParentId())
- .name(record.getName())
- .typeCode(record.getTypeCode())
- .subTypeCode(record.getSubTypeCode())
- .build();
- }
-
- public static EntityNameLookupRecord toEntityActive(ModelEntityActive model) {
- if (model == null) {
- return null;
- }
-
- return new EntityNameLookupRecord(
- model.catalogId, model.id, model.parentId, model.name, model.typeCode, model.subTypeCode);
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntityChangeTracking.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntityChangeTracking.java
deleted file mode 100644
index 0eb4e01f91..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelEntityChangeTracking.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink.models;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import jakarta.persistence.Version;
-import org.apache.polaris.core.entity.PolarisBaseEntity;
-
-/**
- * EntityChangeTracking model representing some attributes of a Polaris Entity. This is used to
- * exchange entity information with ENTITIES_CHANGE_TRACKING table
- */
-@Entity
-@Table(name = "ENTITIES_CHANGE_TRACKING")
-public class ModelEntityChangeTracking {
- // the id of the catalog associated to that entity. NULL_ID if this entity is top-level like
- // a catalog
- @Id private long catalogId;
-
- // the id of the entity which was resolved
- @Id private long id;
-
- // the version that this entity had when it was resolved
- private int entityVersion;
-
- // current version for that entity, will be monotonically incremented
- private int grantRecordsVersion;
-
- // Used for Optimistic Locking to handle concurrent reads and updates
- @Version private long version;
-
- public ModelEntityChangeTracking() {}
-
- public ModelEntityChangeTracking(PolarisBaseEntity entity) {
- this.catalogId = entity.getCatalogId();
- this.id = entity.getId();
- this.entityVersion = entity.getEntityVersion();
- this.grantRecordsVersion = entity.getGrantRecordsVersion();
- }
-
- public long getCatalogId() {
- return catalogId;
- }
-
- public long getId() {
- return id;
- }
-
- public int getEntityVersion() {
- return entityVersion;
- }
-
- public int getGrantRecordsVersion() {
- return grantRecordsVersion;
- }
-
- public void update(PolarisBaseEntity entity) {
- this.entityVersion = entity.getEntityVersion();
- this.grantRecordsVersion = entity.getGrantRecordsVersion();
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelGrantRecord.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelGrantRecord.java
deleted file mode 100644
index 262d77942d..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelGrantRecord.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink.models;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Index;
-import jakarta.persistence.Table;
-import jakarta.persistence.Version;
-import org.apache.polaris.core.entity.PolarisGrantRecord;
-
-/**
- * GrantRecord model representing a privilege record of a securable granted to grantee. This is used
- * to exchange the information with GRANT_RECORDS table
- */
-@Entity
-@Table(
- name = "GRANT_RECORDS",
- indexes = {
- @Index(
- name = "GRANT_RECORDS_BY_GRANTEE_INDEX",
- columnList = "granteeCatalogId,granteeId,securableCatalogId,securableId,privilegeCode")
- })
-public class ModelGrantRecord {
-
- // id of the catalog where the securable entity resides, NULL_ID if this entity is a top-level
- // account entity
- @Id private long securableCatalogId;
-
- // id of the securable
- @Id private long securableId;
-
- // id of the catalog where the grantee entity resides, NULL_ID if this entity is a top-level
- // account entity
- @Id private long granteeCatalogId;
-
- // id of the grantee
- @Id private long granteeId;
-
- // id associated to the privilege
- @Id private int privilegeCode;
-
- // Used for Optimistic Locking to handle concurrent reads and updates
- @Version private long version;
-
- public long getSecurableCatalogId() {
- return securableCatalogId;
- }
-
- public long getSecurableId() {
- return securableId;
- }
-
- public long getGranteeCatalogId() {
- return granteeCatalogId;
- }
-
- public long getGranteeId() {
- return granteeId;
- }
-
- public int getPrivilegeCode() {
- return privilegeCode;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static final class Builder {
- private final ModelGrantRecord grantRecord;
-
- private Builder() {
- grantRecord = new ModelGrantRecord();
- }
-
- public Builder securableCatalogId(long securableCatalogId) {
- grantRecord.securableCatalogId = securableCatalogId;
- return this;
- }
-
- public Builder securableId(long securableId) {
- grantRecord.securableId = securableId;
- return this;
- }
-
- public Builder granteeCatalogId(long granteeCatalogId) {
- grantRecord.granteeCatalogId = granteeCatalogId;
- return this;
- }
-
- public Builder granteeId(long granteeId) {
- grantRecord.granteeId = granteeId;
- return this;
- }
-
- public Builder privilegeCode(int privilegeCode) {
- grantRecord.privilegeCode = privilegeCode;
- return this;
- }
-
- public ModelGrantRecord build() {
- return grantRecord;
- }
- }
-
- public static ModelGrantRecord fromGrantRecord(PolarisGrantRecord record) {
- if (record == null) return null;
-
- return ModelGrantRecord.builder()
- .securableCatalogId(record.getSecurableCatalogId())
- .securableId(record.getSecurableId())
- .granteeCatalogId(record.getGranteeCatalogId())
- .granteeId(record.getGranteeId())
- .privilegeCode(record.getPrivilegeCode())
- .build();
- }
-
- public static PolarisGrantRecord toGrantRecord(ModelGrantRecord model) {
- if (model == null) return null;
-
- return new PolarisGrantRecord(
- model.getSecurableCatalogId(),
- model.getSecurableId(),
- model.getGranteeCatalogId(),
- model.getGranteeId(),
- model.getPrivilegeCode());
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelPolicyMappingRecord.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelPolicyMappingRecord.java
deleted file mode 100644
index b58199b0e4..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelPolicyMappingRecord.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink.models;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Index;
-import jakarta.persistence.Table;
-import jakarta.persistence.Version;
-import org.apache.polaris.core.policy.PolarisPolicyMappingRecord;
-import org.eclipse.persistence.annotations.PrimaryKey;
-
-@Entity
-@Table(
- name = "POLICY_MAPPING_RECORDS",
- indexes = {
- @Index(
- name = "POLICY_MAPPING_RECORDS_BY_POLICY_INDEX",
- columnList = "policyTypeCode,policyCatalogId,policyId,targetCatalogId,targetId")
- })
-@PrimaryKey(
- columns = {
- @Column(name = "targetCatalogId"),
- @Column(name = "targetId"),
- @Column(name = "policyTypeCode"),
- @Column(name = "policyCatalogId"),
- @Column(name = "policyId")
- })
-public class ModelPolicyMappingRecord {
- // id of the catalog where target entity resides
- @Id private long targetCatalogId;
-
- // id of the target entity
- @Id private long targetId;
-
- // id associated to the policy type
- @Id private int policyTypeCode;
-
- // id of the catalog where the policy entity resides
- @Id private long policyCatalogId;
-
- // id of the policy
- @Id private long policyId;
-
- // additional parameters of the mapping
- private String parameters;
-
- // Used for Optimistic Locking to handle concurrent reads and updates
- @Version private long version;
-
- public long getTargetCatalogId() {
- return targetCatalogId;
- }
-
- public long getTargetId() {
- return targetId;
- }
-
- public int getPolicyTypeCode() {
- return policyTypeCode;
- }
-
- public long getPolicyCatalogId() {
- return policyCatalogId;
- }
-
- public long getPolicyId() {
- return policyId;
- }
-
- public String getParameters() {
- return parameters;
- }
-
- public static ModelPolicyMappingRecord.Builder builder() {
- return new ModelPolicyMappingRecord.Builder();
- }
-
- public static final class Builder {
- private final ModelPolicyMappingRecord policyMappingRecord;
-
- private Builder() {
- policyMappingRecord = new ModelPolicyMappingRecord();
- }
-
- public Builder targetCatalogId(long targetCatalogId) {
- policyMappingRecord.targetCatalogId = targetCatalogId;
- return this;
- }
-
- public Builder targetId(long targetId) {
- policyMappingRecord.targetId = targetId;
- return this;
- }
-
- public Builder policyTypeCode(int policyTypeCode) {
- policyMappingRecord.policyTypeCode = policyTypeCode;
- return this;
- }
-
- public Builder policyCatalogId(long policyCatalogId) {
- policyMappingRecord.policyCatalogId = policyCatalogId;
- return this;
- }
-
- public Builder policyId(long policyId) {
- policyMappingRecord.policyId = policyId;
- return this;
- }
-
- public Builder parameters(String parameters) {
- policyMappingRecord.parameters = parameters;
- return this;
- }
-
- public ModelPolicyMappingRecord build() {
- return policyMappingRecord;
- }
- }
-
- public void update(PolarisPolicyMappingRecord record) {
- this.targetCatalogId = record.getTargetCatalogId();
- this.targetId = record.getTargetId();
- this.policyTypeCode = record.getPolicyTypeCode();
- this.policyCatalogId = record.getPolicyCatalogId();
- this.policyId = record.getPolicyId();
- this.parameters = record.getParameters();
- }
-
- public static ModelPolicyMappingRecord fromPolicyMappingRecord(
- PolarisPolicyMappingRecord record) {
- if (record == null) return null;
-
- return ModelPolicyMappingRecord.builder()
- .targetCatalogId(record.getTargetCatalogId())
- .targetId(record.getTargetId())
- .policyTypeCode(record.getPolicyTypeCode())
- .policyCatalogId(record.getPolicyCatalogId())
- .policyId(record.getPolicyId())
- .parameters(record.getParameters())
- .build();
- }
-
- public static PolarisPolicyMappingRecord toPolicyMappingRecord(ModelPolicyMappingRecord model) {
- if (model == null) return null;
-
- return new PolarisPolicyMappingRecord(
- model.getTargetCatalogId(),
- model.getTargetId(),
- model.getPolicyCatalogId(),
- model.getPolicyId(),
- model.getPolicyTypeCode(),
- model.getParameters());
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelPrincipalSecrets.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelPrincipalSecrets.java
deleted file mode 100644
index 61e0697b12..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelPrincipalSecrets.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink.models;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import jakarta.persistence.Version;
-import org.apache.polaris.core.entity.PolarisPrincipalSecrets;
-
-/**
- * PrincipalSecrets model representing the secrets used to authenticate a catalog principal. This is
- * used to exchange the information with PRINCIPAL_SECRETS table
- */
-@Entity
-@Table(name = "PRINCIPAL_SECRETS")
-public class ModelPrincipalSecrets {
- // the id of the principal
- private long principalId;
-
- // the client id for that principal
- @Id private String principalClientId;
-
- // Hash of mainSecret
- private String mainSecretHash;
-
- // Hash of secondarySecret
- private String secondarySecretHash;
-
- private String secretSalt;
-
- // Used for Optimistic Locking to handle concurrent reads and updates
- @Version private long version;
-
- public long getPrincipalId() {
- return principalId;
- }
-
- public String getPrincipalClientId() {
- return principalClientId;
- }
-
- public String getSecretSalt() {
- return secretSalt;
- }
-
- public String getMainSecretHash() {
- return mainSecretHash;
- }
-
- public String getSecondarySecretHash() {
- return secondarySecretHash;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static final class Builder {
- private final ModelPrincipalSecrets principalSecrets;
-
- private Builder() {
- principalSecrets = new ModelPrincipalSecrets();
- }
-
- public Builder principalId(long principalId) {
- principalSecrets.principalId = principalId;
- return this;
- }
-
- public Builder principalClientId(String principalClientId) {
- principalSecrets.principalClientId = principalClientId;
- return this;
- }
-
- public Builder secretSalt(String secretSalt) {
- principalSecrets.secretSalt = secretSalt;
- return this;
- }
-
- public Builder mainSecretHash(String mainSecretHash) {
- principalSecrets.mainSecretHash = mainSecretHash;
- return this;
- }
-
- public Builder secondarySecretHash(String secondarySecretHash) {
- principalSecrets.secondarySecretHash = secondarySecretHash;
- return this;
- }
-
- public ModelPrincipalSecrets build() {
- return principalSecrets;
- }
- }
-
- public static ModelPrincipalSecrets fromPrincipalSecrets(PolarisPrincipalSecrets record) {
- if (record == null) return null;
-
- return ModelPrincipalSecrets.builder()
- .principalId(record.getPrincipalId())
- .principalClientId(record.getPrincipalClientId())
- .secretSalt(record.getSecretSalt())
- .mainSecretHash(record.getMainSecretHash())
- .secondarySecretHash(record.getSecondarySecretHash())
- .build();
- }
-
- public static PolarisPrincipalSecrets toPrincipalSecrets(ModelPrincipalSecrets model) {
- if (model == null) return null;
-
- return new PolarisPrincipalSecrets(
- model.getPrincipalId(),
- model.getPrincipalClientId(),
- null,
- null,
- model.getSecretSalt(),
- model.getMainSecretHash(),
- model.getSecondarySecretHash());
- }
-
- public void update(PolarisPrincipalSecrets principalSecrets) {
- if (principalSecrets == null) return;
-
- this.principalId = principalSecrets.getPrincipalId();
- this.principalClientId = principalSecrets.getPrincipalClientId();
- this.secretSalt = principalSecrets.getSecretSalt();
- this.mainSecretHash = principalSecrets.getMainSecretHash();
- this.secondarySecretHash = principalSecrets.getSecondarySecretHash();
- }
-}
diff --git a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelSequenceId.java b/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelSequenceId.java
deleted file mode 100644
index 7a77b4fe23..0000000000
--- a/persistence/eclipselink/src/main/java/org/apache/polaris/extension/persistence/impl/eclipselink/models/ModelSequenceId.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink.models;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-
-/** Used to manage unique IDs in Polaris */
-@Entity
-@Table(name = "POLARIS_SEQUENCE")
-public class ModelSequenceId {
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- private Long id;
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public Long getId() {
- return id;
- }
-}
diff --git a/persistence/eclipselink/src/main/resources/META-INF/persistence.xml b/persistence/eclipselink/src/main/resources/META-INF/persistence.xml
deleted file mode 100644
index 329281463d..0000000000
--- a/persistence/eclipselink/src/main/resources/META-INF/persistence.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
- org.eclipse.persistence.jpa.PersistenceProvider
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntity
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityActive
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityChangeTracking
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelGrantRecord
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelPolicyMappingRecord
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelPrincipalSecrets
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelSequenceId
- NONE
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/persistence/eclipselink/src/test/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkMetaStoreManagerTest.java b/persistence/eclipselink/src/test/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkMetaStoreManagerTest.java
deleted file mode 100644
index bf358cca0d..0000000000
--- a/persistence/eclipselink/src/test/java/org/apache/polaris/extension/persistence/impl/eclipselink/PolarisEclipseLinkMetaStoreManagerTest.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.extension.persistence.impl.eclipselink;
-
-import static jakarta.persistence.Persistence.createEntityManagerFactory;
-import static org.apache.polaris.core.persistence.PrincipalSecretsGenerator.RANDOM_SECRETS;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Objects;
-import java.util.stream.Stream;
-import org.apache.polaris.core.PolarisCallContext;
-import org.apache.polaris.core.PolarisDefaultDiagServiceImpl;
-import org.apache.polaris.core.PolarisDiagnostics;
-import org.apache.polaris.core.context.RealmContext;
-import org.apache.polaris.core.entity.PolarisPrincipalSecrets;
-import org.apache.polaris.core.persistence.BasePolarisMetaStoreManagerTest;
-import org.apache.polaris.core.persistence.PolarisTestMetaStoreManager;
-import org.apache.polaris.core.persistence.transactional.TransactionalMetaStoreManagerImpl;
-import org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelPrincipalSecrets;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-import org.mockito.Mockito;
-
-/**
- * Integration test for EclipseLink based metastore implementation
- *
- * @author aixu
- */
-public class PolarisEclipseLinkMetaStoreManagerTest extends BasePolarisMetaStoreManagerTest {
-
- private static Path persistenceXml;
- private static Path confJar;
-
- @BeforeAll
- static void prepareConfFiles(@TempDir Path archiveDir) throws IOException {
- URL persistenceXmlSource =
- Objects.requireNonNull(
- PolarisEclipseLinkMetaStoreManagerTest.class.getResource("/META-INF/persistence.xml"));
- Files.createDirectories(archiveDir);
- persistenceXml = archiveDir.resolve("persistence.xml");
- try (InputStream is = persistenceXmlSource.openStream()) {
- Files.copy(is, persistenceXml);
- }
- URL confJarSource =
- Objects.requireNonNull(
- PolarisEclipseLinkMetaStoreManagerTest.class.getResource("/eclipselink/test-conf.jar"));
- confJar = archiveDir.resolve("test-conf.jar");
- try (InputStream is = confJarSource.openStream()) {
- Files.copy(is, confJar);
- }
- }
-
- @Override
- protected PolarisTestMetaStoreManager createPolarisTestMetaStoreManager() {
- PolarisDiagnostics diagServices = new PolarisDefaultDiagServiceImpl();
- PolarisEclipseLinkStore store = new PolarisEclipseLinkStore(diagServices);
- RealmContext realmContext = () -> "realm";
- PolarisEclipseLinkMetaStoreSessionImpl session =
- new PolarisEclipseLinkMetaStoreSessionImpl(
- diagServices, store, Mockito.mock(), realmContext, null, "polaris", RANDOM_SECRETS);
- TransactionalMetaStoreManagerImpl metaStoreManager =
- new TransactionalMetaStoreManagerImpl(clock, diagServices);
- PolarisCallContext callCtx = new PolarisCallContext(realmContext, session);
- return new PolarisTestMetaStoreManager(metaStoreManager, callCtx);
- }
-
- @ParameterizedTest
- @MethodSource
- void testCreateStoreSession(String confFile, boolean success) {
- // Clear cache to prevent reuse EntityManagerFactory
- PolarisEclipseLinkMetaStoreSessionImpl.clearEntityManagerFactories();
-
- PolarisDiagnostics diagServices = new PolarisDefaultDiagServiceImpl();
- PolarisEclipseLinkStore store = new PolarisEclipseLinkStore(diagServices);
- try {
- var session =
- new PolarisEclipseLinkMetaStoreSessionImpl(
- diagServices,
- store,
- Mockito.mock(),
- () -> "realm",
- confFile,
- "polaris",
- RANDOM_SECRETS);
- assertNotNull(session);
- assertTrue(success);
- } catch (Exception e) {
- assertFalse(success);
- }
- }
-
- public static Stream testCreateStoreSession() {
- return Stream.of(
- // conf file not provided
- Arguments.of(null, true),
- // classpath resource
- Arguments.of("META-INF/persistence.xml", true),
- Arguments.of("META-INF/dummy.xml", false),
- // classpath resource, embedded
- Arguments.of("eclipselink/test-conf.jar!/persistence.xml", true),
- Arguments.of("eclipselink/test-conf.jar!/dummy.xml", false),
- Arguments.of("dummy/test-conf.jar!/persistence.xml", false),
- // filesystem path
- Arguments.of(persistenceXml.toString(), true),
- Arguments.of("/dummy_path/conf/persistence.xml", false),
- // filesystem path, embedded
- Arguments.of(confJar + "!/persistence.xml", true),
- Arguments.of(confJar + "!/dummy.xml", false),
- Arguments.of("/dummy_path/test-conf.jar!/persistence.xml", false));
- }
-
- @Test
- void testRotateLegacyPrincipalSecret() {
-
- PolarisEclipseLinkMetaStoreSessionImpl.clearEntityManagerFactories();
-
- var newSecrets = new PolarisPrincipalSecrets(42L);
- assertThat(newSecrets)
- .extracting(
- PolarisPrincipalSecrets::getMainSecret,
- PolarisPrincipalSecrets::getSecondarySecret,
- PolarisPrincipalSecrets::getMainSecretHash,
- PolarisPrincipalSecrets::getSecondarySecretHash,
- PolarisPrincipalSecrets::getSecretSalt)
- .doesNotContainNull()
- .allMatch(x -> !x.toString().isEmpty());
-
- ModelPrincipalSecrets model = ModelPrincipalSecrets.fromPrincipalSecrets(newSecrets);
- var key = model.getPrincipalClientId();
-
- var fromModel = ModelPrincipalSecrets.toPrincipalSecrets(model);
-
- assertThat(fromModel)
- .extracting(
- PolarisPrincipalSecrets::getMainSecret, PolarisPrincipalSecrets::getSecondarySecret)
- .containsOnlyNulls();
-
- assertThat(model)
- .extracting(
- ModelPrincipalSecrets::getPrincipalId,
- ModelPrincipalSecrets::getPrincipalClientId,
- ModelPrincipalSecrets::getSecretSalt,
- ModelPrincipalSecrets::getMainSecretHash,
- ModelPrincipalSecrets::getSecondarySecretHash)
- .containsExactly(
- newSecrets.getPrincipalId(),
- newSecrets.getPrincipalClientId(),
- newSecrets.getSecretSalt(),
- newSecrets.getMainSecretHash(),
- newSecrets.getSecondarySecretHash());
-
- try (var emf = createEntityManagerFactory("polaris")) {
- var entityManager = emf.createEntityManager();
-
- // Persist the original model:
- entityManager.getTransaction().begin();
- entityManager.persist(model);
- entityManager.getTransaction().commit();
-
- // Retrieve the model
- entityManager.clear();
- ModelPrincipalSecrets retrievedModel = entityManager.find(ModelPrincipalSecrets.class, key);
-
- assertThat(retrievedModel)
- .extracting(
- ModelPrincipalSecrets::getPrincipalId,
- ModelPrincipalSecrets::getPrincipalClientId,
- ModelPrincipalSecrets::getSecretSalt,
- ModelPrincipalSecrets::getMainSecretHash,
- ModelPrincipalSecrets::getSecondarySecretHash)
- .containsExactly(
- model.getPrincipalId(),
- model.getPrincipalClientId(),
- model.getSecretSalt(),
- model.getMainSecretHash(),
- model.getSecondarySecretHash());
-
- // Now read using PolarisEclipseLinkStore
- var store = new PolarisEclipseLinkStore(new PolarisDefaultDiagServiceImpl());
- store.initialize(entityManager);
- PolarisPrincipalSecrets principalSecrets =
- ModelPrincipalSecrets.toPrincipalSecrets(
- store.lookupPrincipalSecrets(entityManager, key));
-
- assertThat(principalSecrets)
- .extracting(
- PolarisPrincipalSecrets::getPrincipalId,
- PolarisPrincipalSecrets::getPrincipalClientId,
- PolarisPrincipalSecrets::getSecretSalt,
- PolarisPrincipalSecrets::getMainSecret,
- PolarisPrincipalSecrets::getMainSecretHash,
- PolarisPrincipalSecrets::getSecondarySecret,
- PolarisPrincipalSecrets::getSecondarySecretHash)
- .containsExactly(
- fromModel.getPrincipalId(),
- fromModel.getPrincipalClientId(),
- fromModel.getSecretSalt(),
- null,
- fromModel.getMainSecretHash(),
- null,
- fromModel.getSecondarySecretHash());
-
- // Rotate:
- principalSecrets.rotateSecrets(principalSecrets.getMainSecretHash());
- assertThat(principalSecrets.getMainSecret()).isNotEqualTo(newSecrets.getMainSecret());
- assertThat(principalSecrets.getMainSecretHash()).isNotEqualTo(newSecrets.getMainSecretHash());
- assertThat(principalSecrets)
- .extracting(
- PolarisPrincipalSecrets::getSecondarySecret,
- PolarisPrincipalSecrets::getSecondarySecretHash)
- .containsExactly(null, newSecrets.getMainSecretHash());
-
- // Persist the rotated credential:
- store.deletePrincipalSecrets(entityManager, key);
- store.writePrincipalSecrets(entityManager, principalSecrets);
-
- // Reload the model:
- var reloadedModel = store.lookupPrincipalSecrets(entityManager, key);
-
- // Confirm the old secret still works via hash:
- var reloadedSecrets = ModelPrincipalSecrets.toPrincipalSecrets(reloadedModel);
- Assertions.assertTrue(reloadedSecrets.matchesSecret(newSecrets.getMainSecret()));
- Assertions.assertFalse(reloadedSecrets.matchesSecret(newSecrets.getSecondarySecret()));
- }
- }
-}
diff --git a/polaris-core/README.md b/polaris-core/README.md
index a6d32c3241..563c223f9c 100644
--- a/polaris-core/README.md
+++ b/polaris-core/README.md
@@ -48,4 +48,4 @@ Polaris supports multiple object storage providers. `PolarisStorageIntegration`
The `polaris-core` module is primarily consumed by:
- **API Services** - Management and catalog REST services
- **Runtime Components** - Server and admin tools
-- **Persistence Implementations** - Eclipselink, JDBC, etc.
+- **Persistence Implementations** - JDBC, etc.
diff --git a/runtime/admin/build.gradle.kts b/runtime/admin/build.gradle.kts
index a90aa7e331..103da5c79f 100644
--- a/runtime/admin/build.gradle.kts
+++ b/runtime/admin/build.gradle.kts
@@ -32,7 +32,6 @@ dependencies {
compileOnly("com.fasterxml.jackson.core:jackson-annotations")
- runtimeOnly(project(":polaris-eclipselink"))
runtimeOnly(project(":polaris-relational-jdbc"))
runtimeOnly("org.postgresql:postgresql")
@@ -54,7 +53,6 @@ dependencies {
testFixturesApi("org.testcontainers:testcontainers")
testFixturesApi("org.testcontainers:postgresql")
- testRuntimeOnly(project(":polaris-eclipselink"))
testRuntimeOnly("org.postgresql:postgresql")
}
diff --git a/runtime/admin/distribution/LICENSE b/runtime/admin/distribution/LICENSE
index b3449385b7..4d2b7d0e7b 100644
--- a/runtime/admin/distribution/LICENSE
+++ b/runtime/admin/distribution/LICENSE
@@ -1101,12 +1101,6 @@ License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2
--------------------------------------------------------------------------------
-Group: org.eclipse.persistence Name: eclipselink Version: 4.0.8
-Project URL: https://eclipse.dev/eclipselink/
-License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
-
---------------------------------------------------------------------------------
-
Group: org.hdrhistogram Name: HdrHistogram Version: 2.2.2
Project URL: http://hdrhistogram.github.io/HdrHistogram/
License: BSD 2-Clause
diff --git a/runtime/admin/src/main/java/org/apache/polaris/admintool/config/AdminToolProducers.java b/runtime/admin/src/main/java/org/apache/polaris/admintool/config/AdminToolProducers.java
index cd97696727..e6251b2c88 100644
--- a/runtime/admin/src/main/java/org/apache/polaris/admintool/config/AdminToolProducers.java
+++ b/runtime/admin/src/main/java/org/apache/polaris/admintool/config/AdminToolProducers.java
@@ -43,8 +43,6 @@ public MetaStoreManagerFactory metaStoreManagerFactory(
return metaStoreManagerFactories.select(Identifier.Literal.of(persistenceType)).get();
}
- // CDI dependencies of EclipseLink's MetaStoreManagerFactory:
-
@Produces
@ApplicationScoped
public Clock clock() {
diff --git a/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkBootstrapCommandTest.java b/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkBootstrapCommandTest.java
deleted file mode 100644
index 025f9ff920..0000000000
--- a/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkBootstrapCommandTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.admintool.el;
-
-import io.quarkus.test.junit.TestProfile;
-import org.apache.polaris.admintool.BootstrapCommandTestBase;
-
-@TestProfile(EclipselinkProfile.class)
-class EclipselinkBootstrapCommandTest extends BootstrapCommandTestBase {}
diff --git a/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkProfile.java b/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkProfile.java
deleted file mode 100644
index bb249b7ae6..0000000000
--- a/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkProfile.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.admintool.el;
-
-import static org.apache.polaris.admintool.PostgresEclipselinkTestResourceLifecycleManager.INIT_SCRIPT;
-
-import io.quarkus.test.junit.QuarkusTestProfile;
-import java.util.List;
-import java.util.Map;
-import org.apache.polaris.admintool.PostgresEclipselinkTestResourceLifecycleManager;
-
-public class EclipselinkProfile implements QuarkusTestProfile {
-
- @Override
- public Map getConfigOverrides() {
- return Map.of();
- }
-
- @Override
- public List testResources() {
- return List.of(
- new TestResourceEntry(
- PostgresEclipselinkTestResourceLifecycleManager.class,
- Map.of(INIT_SCRIPT, "org/apache/polaris/admintool/init.sql")));
- }
-}
diff --git a/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkPurgeCommandTest.java b/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkPurgeCommandTest.java
deleted file mode 100644
index 395d3211a0..0000000000
--- a/runtime/admin/src/test/java/org/apache/polaris/admintool/el/EclipselinkPurgeCommandTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.admintool.el;
-
-import com.google.common.collect.ImmutableMap;
-import io.quarkus.test.junit.TestProfile;
-import java.util.Map;
-import org.apache.polaris.admintool.PurgeCommandTestBase;
-
-@TestProfile(EclipselinkPurgeCommandTest.Profile.class)
-class EclipselinkPurgeCommandTest extends PurgeCommandTestBase {
-
- public static class Profile extends EclipselinkProfile {
- @Override
- public Map getConfigOverrides() {
- return ImmutableMap.builder()
- .putAll(super.getConfigOverrides())
- .put("pre-bootstrap", "true")
- .build();
- }
- }
-}
diff --git a/runtime/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java b/runtime/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java
index 48979fa4f1..07d2e29d36 100644
--- a/runtime/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java
+++ b/runtime/admin/src/test/java/org/apache/polaris/admintool/relational/jdbc/RelationalJdbcAdminProfile.java
@@ -18,8 +18,6 @@
*/
package org.apache.polaris.admintool.relational.jdbc;
-import static org.apache.polaris.admintool.PostgresEclipselinkTestResourceLifecycleManager.INIT_SCRIPT;
-
import java.util.List;
import java.util.Map;
import org.apache.polaris.test.commons.PostgresRelationalJdbcLifeCycleManagement;
@@ -42,8 +40,6 @@ public Map getConfigOverrides() {
@Override
public List testResources() {
return List.of(
- new TestResourceEntry(
- PostgresRelationalJdbcLifeCycleManagement.class,
- Map.of(INIT_SCRIPT, "org/apache/polaris/admintool/init.sql")));
+ new TestResourceEntry(PostgresRelationalJdbcLifeCycleManagement.class, Map.of()));
}
}
diff --git a/runtime/admin/src/testFixtures/java/org/apache/polaris/admintool/PostgresEclipselinkTestResourceLifecycleManager.java b/runtime/admin/src/testFixtures/java/org/apache/polaris/admintool/PostgresEclipselinkTestResourceLifecycleManager.java
deleted file mode 100644
index 4583273b14..0000000000
--- a/runtime/admin/src/testFixtures/java/org/apache/polaris/admintool/PostgresEclipselinkTestResourceLifecycleManager.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.admintool;
-
-import static org.apache.polaris.containerspec.ContainerSpecHelper.containerSpecHelper;
-
-import io.quarkus.test.common.DevServicesContext;
-import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Map;
-import org.apache.commons.io.FileUtils;
-import org.testcontainers.containers.PostgreSQLContainer;
-
-public class PostgresEclipselinkTestResourceLifecycleManager
- implements QuarkusTestResourceLifecycleManager, DevServicesContext.ContextAware {
-
- public static final String INIT_SCRIPT = "init-script";
-
- private PostgreSQLContainer> postgres;
- private String initScript;
- private DevServicesContext context;
- private Path rootDir;
-
- @Override
- public void init(Map initArgs) {
- initScript = initArgs.get(INIT_SCRIPT);
- }
-
- @Override
- public void setIntegrationTestContext(DevServicesContext context) {
- this.context = context;
- }
-
- @Override
- @SuppressWarnings("resource")
- public Map start() {
- postgres =
- new PostgreSQLContainer<>(
- containerSpecHelper(
- "postgres", PostgresEclipselinkTestResourceLifecycleManager.class)
- .dockerImageName(null)
- .asCompatibleSubstituteFor("postgres"))
- .withDatabaseName("polaris_realm1")
- .withUsername("polaris")
- .withPassword("polaris");
- if (initScript != null) {
- postgres.withInitScript(initScript);
- }
- context.containerNetworkId().ifPresent(postgres::withNetworkMode);
- postgres.start();
- return Map.of(
- "quarkus.datasource.postgresql.jdbc.url",
- postgres.getJdbcUrl(),
- "quarkus.datasource.username",
- postgres.getUsername(),
- "quarkus.datasource.password",
- postgres.getPassword(),
- "polaris.persistence.type",
- "eclipse-link",
- "polaris.persistence.eclipselink.configuration-file",
- createPersistenceXml().toString());
- }
-
- @Override
- public void stop() {
- if (postgres != null) {
- try {
- postgres.stop();
- } finally {
- postgres = null;
- }
- }
- if (rootDir != null) {
- try {
- FileUtils.deleteDirectory(rootDir.toFile());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } finally {
- rootDir = null;
- }
- }
- }
-
- private Path createPersistenceXml() {
- try {
- rootDir = Files.createTempDirectory("root");
- Path archiveDir = rootDir.resolve("archive");
- Files.createDirectory(archiveDir);
- String persistenceXmlContent =
- """
-
-
- org.eclipse.persistence.jpa.PersistenceProvider
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntity
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityActive
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityChangeTracking
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityDropped
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelGrantRecord
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelPrincipalSecrets
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelSequenceId
- NONE
-
-
-
-
-
-
-
-
-
-
-
- """
- .formatted(
- postgres.getJdbcUrl().replace("realm1", "{realm}"),
- postgres.getUsername(),
- postgres.getPassword());
- Path file = Files.createTempFile(archiveDir, "persistence", "xml");
- Files.writeString(file, persistenceXmlContent);
- return file;
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-}
diff --git a/runtime/admin/src/testFixtures/resources/org/apache/polaris/admintool/init.sql b/runtime/admin/src/testFixtures/resources/org/apache/polaris/admintool/init.sql
deleted file mode 100644
index c6d4e1644a..0000000000
--- a/runtime/admin/src/testFixtures/resources/org/apache/polaris/admintool/init.sql
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
--- Create two more databases for testing. The first database, polaris_realm1, is created
--- during container initialization. See PostgresTestResourceLifecycleManager.
-
--- Note: the database names must follow the pattern polaris_{realm}. That's the pattern
--- specified by the persistence.xml file used in tests.
-
-CREATE DATABASE polaris_realm2;
-GRANT ALL PRIVILEGES ON DATABASE polaris_realm2 TO polaris;
-
-CREATE DATABASE polaris_realm3;
-GRANT ALL PRIVILEGES ON DATABASE polaris_realm3 TO polaris;
diff --git a/runtime/defaults/src/main/resources/application.properties b/runtime/defaults/src/main/resources/application.properties
index bda31e9e70..91d41f9256 100644
--- a/runtime/defaults/src/main/resources/application.properties
+++ b/runtime/defaults/src/main/resources/application.properties
@@ -119,7 +119,6 @@ polaris.features."SUPPORTED_CATALOG_CONNECTION_TYPES"=["ICEBERG_REST"]
# realm overrides
# polaris.features.realm-overrides."my-realm"."SKIP_CREDENTIAL_SUBSCOPING_INDIRECTION"=true
-# polaris.persistence.type=eclipse-link
# polaris.persistence.type=in-memory-atomic
polaris.persistence.type=in-memory
# polaris.persistence.type=relational-jdbc
diff --git a/runtime/distribution/LICENSE b/runtime/distribution/LICENSE
index d01b00f64a..f9253efecb 100644
--- a/runtime/distribution/LICENSE
+++ b/runtime/distribution/LICENSE
@@ -1490,12 +1490,6 @@ License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2
--------------------------------------------------------------------------------
-Group: org.eclipse.persistence Name: eclipselink Version: 4.0.8
-Project URL: https://eclipse.dev/eclipselink/
-License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
-
---------------------------------------------------------------------------------
-
Group: org.glassfish.expressly Name: expressly Version: 6.0.0
Project URL: https://projects.eclipse.org/projects/ee4j
License: EPL 2.0 - https://www.eclipse.org/legal/epl-2.0
diff --git a/runtime/server/build.gradle.kts b/runtime/server/build.gradle.kts
index eba921a5d9..dc2119983e 100644
--- a/runtime/server/build.gradle.kts
+++ b/runtime/server/build.gradle.kts
@@ -40,7 +40,6 @@ val distributionElements by
dependencies {
implementation(project(":polaris-runtime-service"))
- runtimeOnly(project(":polaris-eclipselink"))
runtimeOnly("org.postgresql:postgresql")
runtimeOnly(project(":polaris-relational-jdbc"))
runtimeOnly("io.quarkus:quarkus-jdbc-postgresql")
diff --git a/runtime/server/distribution/LICENSE b/runtime/server/distribution/LICENSE
index 0e4b1a5b7c..cf9469ba30 100644
--- a/runtime/server/distribution/LICENSE
+++ b/runtime/server/distribution/LICENSE
@@ -1481,12 +1481,6 @@ License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
--------------------------------------------------------------------------------
-Group: org.eclipse.persistence Name: eclipselink Version: 4.0.8
-Project URL: https://eclipse.dev/eclipselink/
-License: Eclipse Public License 2.0 - https://projects.eclipse.org/license/epl-2.0
-
---------------------------------------------------------------------------------
-
Group: org.glassfish.expressly Name: expressly Version: 6.0.0
Project URL: https://projects.eclipse.org/projects/ee4j
License: EPL 2.0 - https://www.eclipse.org/legal/epl-2.0
@@ -1858,4 +1852,4 @@ Group: org.awaitility Name: awaitility Version: 4.3.0
Project URL: https://github.com/awaitility/awaitility
License: Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt
---------------------------------------------------------------------------------
\ No newline at end of file
+--------------------------------------------------------------------------------
diff --git a/site/content/in-dev/unreleased/configuration.md b/site/content/in-dev/unreleased/configuration.md
index 5728361ada..d27194edfa 100644
--- a/site/content/in-dev/unreleased/configuration.md
+++ b/site/content/in-dev/unreleased/configuration.md
@@ -83,12 +83,10 @@ read-only mode, as Polaris only reads the configuration file once, at startup.
| Configuration Property | Default Value | Description |
|----------------------------------------------------------------------------------------|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `polaris.persistence.type` | `relational-jdbc` | Define the persistence backend used by Polaris (`in-memory`, `relational-jdbc`, `eclipse-link` (deprecated)). See [Configuring Apache Polaris for Production)[{{% ref "configuring-polaris-for-production.md" %}}) |
+| `polaris.persistence.type` | `relational-jdbc` | Define the persistence backend used by Polaris (`in-memory`, `relational-jdbc`). See [Configuring Apache Polaris for Production)[{{% ref "configuring-polaris-for-production.md" %}}) |
| `polaris.persistence.relational.jdbc.max-retries` | `1` | Total number of retries JDBC persistence will attempt on connection resets or serialization failures before giving up. |
| `polaris.persistence.relational.jdbc.max_duaration_in_ms` | `5000 ms` | Max time interval (ms) since the start of a transaction when retries can be attempted. |
| `polaris.persistence.relational.jdbc.initial_delay_in_ms` | `100 ms` | Initial delay before retrying. The delay is doubled after each retry. |
-| `polaris.persistence.eclipselink.configurationFile` | | Define the location of the `persistence.xml`. By default, it's the built-in `persistence.xml` in use. |
-| `polaris.persistence.eclipselink.persistenceUnit` | `polaris` | Define the name of the persistence unit to use, as defined in the `persistence.xml`. |
| `polaris.realm-context.type` | `default` | Define the type of the Polaris realm to use. |
| `polaris.realm-context.realms` | `POLARIS` | Define the list of realms to use. |
| `polaris.realm-context.header-name` | `Polaris-Realm` | Define the header name defining the realm context. |
diff --git a/site/content/in-dev/unreleased/evolution.md b/site/content/in-dev/unreleased/evolution.md
index b3a57c7525..0462d37339 100644
--- a/site/content/in-dev/unreleased/evolution.md
+++ b/site/content/in-dev/unreleased/evolution.md
@@ -58,15 +58,14 @@ Polaris stores its data in a database, which is sometimes referred to as "Metast
"Persistence" in other docs.
Each Polaris release may support multiple Persistence [implementations](../metastores),
-for example, "EclipseLink" (deprecated) and "JDBC" (current).
+for example "JDBC".
Each type of Persistence evolves individually. Within each Persistence type, Polaris
attempts to support rolling upgrades (both version X and X + 1 servers running at the
same time).
However, migrating between different Persistence types is not supported in a rolling
-upgrade manner (for example, migrating from "EclipseLink" to "JDBC"). Polaris provides
-[tools](https://github.com/apache/polaris-tools/) for migrating between different
+upgrade manner. Polaris provides [tools](https://github.com/apache/polaris-tools/) for migrating between different
catalogs and those tools may be used to migrate between different Persistence types
as well. Service interruption (downtime) should be expected in those cases.
diff --git a/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-aws.md b/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-aws.md
index 485365d59b..452deb2f51 100644
--- a/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-aws.md
+++ b/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-aws.md
@@ -53,7 +53,7 @@ To shut down the Polaris server, run the following commands:
```shell
export ASSETS_PATH=$(pwd)/getting-started/assets/
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml down
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml down
```
To deploy Polaris in a production setting, please review further recommendations at the [Configuring Polaris for Production]({{% relref "../../../configuring-polaris-for-production" %}}) page.
diff --git a/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-azure.md b/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-azure.md
index ce265391fd..ddb401168a 100644
--- a/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-azure.md
+++ b/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-azure.md
@@ -48,7 +48,7 @@ To shut down the Polaris server, run the following commands:
```shell
export ASSETS_PATH=$(pwd)/getting-started/assets/
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml down
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml down
```
To deploy Polaris in a production setting, please review further recommendations at the [Configuring Polaris for Production]({{% relref "../../../configuring-polaris-for-production" %}}) page.
diff --git a/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-gcp.md b/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-gcp.md
index dfb47bc78d..ca40a15441 100644
--- a/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-gcp.md
+++ b/site/content/in-dev/unreleased/getting-started/deploying-polaris/cloud-deploy/deploy-gcp.md
@@ -48,7 +48,7 @@ To shut down the Polaris server, run the following commands:
```shell
export ASSETS_PATH=$(pwd)/getting-started/assets/
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml down
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml down
```
To deploy Polaris in a production setting, please review further recommendations at the [Configuring Polaris for Production]({{% relref "../../../configuring-polaris-for-production" %}}) page.
diff --git a/site/content/in-dev/unreleased/getting-started/using-polaris/_index.md b/site/content/in-dev/unreleased/getting-started/using-polaris/_index.md
index 752a846f5c..7be1ab218a 100644
--- a/site/content/in-dev/unreleased/getting-started/using-polaris/_index.md
+++ b/site/content/in-dev/unreleased/getting-started/using-polaris/_index.md
@@ -163,9 +163,9 @@ Finally, note that we include the `iceberg-aws-bundle` package here. If your tab
Refresh the Docker container with the user's credentials:
```shell
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml stop spark-sql
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml rm -f spark-sql
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml up -d --no-deps spark-sql
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml stop spark-sql
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml rm -f spark-sql
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml up -d --no-deps spark-sql
```
Attach to the running spark-sql container:
@@ -226,9 +226,9 @@ org.apache.iceberg.exceptions.ForbiddenException: Forbidden: Principal 'quicksta
Refresh the Docker container with the user's credentials:
```shell
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml stop trino
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml rm -f trino
-docker compose -p polaris -f getting-started/eclipselink/docker-compose.yml up -d --no-deps trino
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml stop trino
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml rm -f trino
+docker compose -p polaris -f getting-started/jdbc/docker-compose.yml up -d --no-deps trino
```
Attach to the running Trino container:
diff --git a/site/content/in-dev/unreleased/helm.md b/site/content/in-dev/unreleased/helm.md
index ef82e8e675..f30e195da4 100644
--- a/site/content/in-dev/unreleased/helm.md
+++ b/site/content/in-dev/unreleased/helm.md
@@ -232,7 +232,7 @@ ct install --namespace polaris --charts ./helm/polaris
| features.realmOverrides | object | `{}` | Features to enable or disable per realm. This field is a map of maps. The realm name is the key, and the value is a map of feature names to values. If a feature is not present in the map, the default value from the 'defaults' field is used. |
| fileIo | object | `{"type":"default"}` | Polaris FileIO configuration. |
| fileIo.type | string | `"default"` | The type of file IO to use. Two built-in types are supported: default and wasb. The wasb one translates WASB paths to ABFS ones. |
-| image.configDir | string | `"/deployments/config"` | The path to the directory where the application.properties file, and other configuration files, if any, should be mounted. Note: if you are using EclipseLink, then this value must be at least two folders down to the root folder, e.g. `/deployments/config` is OK, whereas `/deployments` is not. |
+| image.configDir | string | `"/deployments/config"` | The path to the directory where the application.properties file, and other configuration files, if any, should be mounted. |
| image.pullPolicy | string | `"IfNotPresent"` | The image pull policy. |
| image.repository | string | `"apache/polaris"` | The image repository to pull from. |
| image.tag | string | `"latest"` | The image tag. |
@@ -310,7 +310,7 @@ ct install --namespace polaris --charts ./helm/polaris
| persistence.relationalJdbc.secret.name | string | `nil` | The secret name to pull database connection properties from |
| persistence.relationalJdbc.secret.password | string | `"password"` | The secret key holding the database password for authentication |
| persistence.relationalJdbc.secret.username | string | `"username"` | The secret key holding the database username for authentication |
-| persistence.type | string | `"in-memory"` | The type of persistence to use. Two built-in types are supported: in-memory and relational-jdbc. The eclipse-link type is also supported but is deprecated. |
+| persistence.type | string | `"in-memory"` | The type of persistence to use. Two built-in types are supported: in-memory and relational-jdbc. |
| podAnnotations | object | `{}` | Annotations to apply to polaris pods. |
| podLabels | object | `{}` | Additional Labels to apply to polaris pods. |
| podSecurityContext | object | `{"fsGroup":10001,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for the polaris pod. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/. |
diff --git a/site/content/in-dev/unreleased/metastores.md b/site/content/in-dev/unreleased/metastores.md
index c22bbdd907..6013db68bd 100644
--- a/site/content/in-dev/unreleased/metastores.md
+++ b/site/content/in-dev/unreleased/metastores.md
@@ -22,8 +22,7 @@ type: docs
weight: 700
---
-This page explains how to configure and use Polaris metastores with either the recommended Relational JDBC or the
-deprecated EclipseLink persistence backends.
+This page explains how to configure and use Polaris metastores with the recommended Relational JDBC backend.
## Relational JDBC
This implementation leverages Quarkus for datasource management and supports configuration through
@@ -69,120 +68,8 @@ quarkus.rds.credentials-provider.aws.port=6160
```
This is the basic configuration. For more details, please refer to the [Quarkus plugin documentation](https://docs.quarkiverse.io/quarkus-amazon-services/dev/amazon-rds.html#_configuration_reference)
-The Relational JDBC metastore currently relies on a Quarkus-managed datasource and supports only PostgresSQL and H2 databases. This limitation is similar to that of EclipseLink, primarily due to underlying schema differences. At this time, official documentation is provided exclusively for usage with PostgreSQL.
+The Relational JDBC metastore currently relies on a Quarkus-managed datasource and supports only PostgresSQL and H2 databases. At this time, official documentation is provided exclusively for usage with PostgreSQL.
Please refer to the documentation here:
[Configure data sources in Quarkus](https://quarkus.io/guides/datasource)
Additionally, the retries can be configured via `polaris.persistence.relational.jdbc.*` properties please ref [configuration]({{% ref "configuration" %}})
-
-## EclipseLink (Deprecated)
-{{< alert important >}}
-EclipseLink persistence will be completely removed from Polaris in 1.3.0 or in 2.0.0 (whichever happens earlier).
-{{< /alert >}}
-
-Polaris includes EclipseLink plugin by default with PostgresSQL driver.
-
-Configure the `polaris.persistence` section in your Polaris configuration file
-(`application.properties`) as follows:
-
-```
-polaris.persistence.type=eclipse-link
-polaris.persistence.eclipselink.configuration-file=/path/to/persistence.xml
-polaris.persistence.eclipselink.persistence-unit=polaris
-```
-
-Alternatively, configuration can also be done with environment variables or system properties. Refer
-to the [Quarkus Configuration Reference] for more information.
-
-The `configuration-file` option must point to an [EclipseLink configuration file]. This file, named
-`persistence.xml`, is used to set up the database connection properties, which can differ depending
-on the type of database and its configuration.
-
-{{< alert note >}}
-You have to locate the `persistence.xml` at least two folders down to the root folder, e.g. `/deployments/config/persistence.xml` is OK, whereas `/deployments/persistence.xml` will cause an infinity loop.
-{{< /alert >}}
-[Quarkus Configuration Reference]: https://quarkus.io/guides/config-reference
-[EclipseLink configuration file]: https://eclipse.dev/eclipselink/documentation/4.0/solutions/solutions.html#TESTINGJPA002
-
-Polaris creates and connects to a separate database for each realm. Specifically, the `{realm}` placeholder in `jakarta.persistence.jdbc.url` is substituted with the actual realm name, allowing the Polaris server to connect to different databases based on the realm.
-
-{{< alert note >}}
-Some database systems such as Postgres don't create databases automatically. Database admins need to create them manually before running Polaris server.
-{{< /alert >}}
-
-A single `persistence.xml` can describe multiple [persistence units](https://eclipse.dev/eclipselink/documentation/4.0/concepts/concepts.html#APPDEV001). For example, with both a `polaris-dev` and `polaris` persistence unit defined, you could use a single `persistence.xml` to easily switch between development and production databases. Use the `persistence-unit` option in the Polaris server configuration to easily switch between persistence units.
-
-### Using H2
-
-{{< alert important >}}
-H2 is an in-memory database and is not suitable for production!
-{{< /alert >}}
-
-The default [persistence.xml] in Polaris is already configured for H2, but you can easily customize
-your H2 configuration using the persistence unit template below:
-
-[persistence.xml]: https://github.com/apache/polaris/blob/main/persistence/eclipselink/src/main/resources/META-INF/persistence.xml
-
-```xml
-
- org.eclipse.persistence.jpa.PersistenceProvider
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntity
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityActive
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityChangeTracking
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityDropped
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelGrantRecord
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelPrincipalSecrets
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelSequenceId
- NONE
-
-
-
-
-
-
-
-```
-
-To build Polaris with the necessary H2 dependency and start the Polaris service, run the following:
-
-```shell
-./gradlew \
- :polaris-server:assemble \
- :polaris-server:quarkusAppPartsBuild --rerun \
- -PeclipseLinkDeps=com.h2database:h2:2.3.232
-java -Dpolaris.persistence.type=eclipse-link \
- -Dpolaris.persistence.eclipselink.configuration-file=/path/to/persistence.xml \
- -Dpolaris.persistence.eclipselink.persistence-unit=polaris \
- -jar runtime/server/build/quarkus-app/quarkus-run.jar
-```
-
-### Using Postgres
-
-PostgreSQL is included by default in the Polaris server distribution.
-
-The following shows a sample configuration for integrating Polaris with Postgres.
-
-```xml
-
- org.eclipse.persistence.jpa.PersistenceProvider
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntity
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityActive
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityChangeTracking
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelEntityDropped
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelGrantRecord
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelPrincipalSecrets
- org.apache.polaris.extension.persistence.impl.eclipselink.models.ModelSequenceId
- NONE
-
-
-
-
-
-
-
-
-
-
-```
diff --git a/site/content/in-dev/unreleased/realm.md b/site/content/in-dev/unreleased/realm.md
index 4e0cc1ce25..57e007b25b 100644
--- a/site/content/in-dev/unreleased/realm.md
+++ b/site/content/in-dev/unreleased/realm.md
@@ -49,5 +49,4 @@ This ensures that each realm's data is stored separately.
**Authentication and Authorization:** For example, in `DefaultAuthenticator`, `RealmContext` is used to provide context about the current security domain, which is used to retrieve the correct `PolarisMetastoreManager` that manages all Polaris entities and associated grant records metadata for
authorization.
-**Isolation:** In methods like `createEntityManagerFactory(@Nonnull RealmContext realmContext)` from `PolarisEclipseLinkPersistenceUnit` interface, the realm context influence how resources are created or managed based on the security policies of that realm.
-An example of this is the way a realm name can be used to create a database connection url so that you have one database instance per realm, when applicable. Or it can be more granular and applied at primary key level (within the same database instance).
+**Isolation:** In classes like `JdbcBasePersistenceImpl`, the realm id from the realm context is part of the primary key to manage entities of realms in isolation (within the same database instance).
diff --git a/tools/config-docs/site/build.gradle.kts b/tools/config-docs/site/build.gradle.kts
index 93817963f3..6439a4b1e2 100644
--- a/tools/config-docs/site/build.gradle.kts
+++ b/tools/config-docs/site/build.gradle.kts
@@ -27,7 +27,6 @@ description = "Polaris site - reference docs"
val genProjectPaths = listOf(
":polaris-async-api",
":polaris-runtime-service",
- ":polaris-eclipselink",
)
val genProjects by configurations.creating