diff --git a/jans-bom/pom.xml b/jans-bom/pom.xml index d1f6e8b2742..14227c63384 100644 --- a/jans-bom/pom.xml +++ b/jans-bom/pom.xml @@ -710,7 +710,7 @@ com.couchbase.client java-client - 2.7.22 + 3.3.2 @@ -744,7 +744,7 @@ com.github.jsqlparser jsqlparser - 4.2 + 4.3 diff --git a/jans-core/script/src/main/java/io/jans/model/custom/script/type/persistence/PersistenceType.java b/jans-core/script/src/main/java/io/jans/model/custom/script/type/persistence/PersistenceType.java index 83d4887bf48..92086941e81 100644 --- a/jans-core/script/src/main/java/io/jans/model/custom/script/type/persistence/PersistenceType.java +++ b/jans-core/script/src/main/java/io/jans/model/custom/script/type/persistence/PersistenceType.java @@ -10,7 +10,7 @@ import io.jans.model.SimpleCustomProperty; import io.jans.model.custom.script.type.BaseExternalType; -import io.jans.orm.exception.extension.PersistenceExtension; +import io.jans.orm.extension.PersistenceExtension; /** * Base interface for persistence script diff --git a/jans-core/service/src/main/java/io/jans/service/external/ExternalPersistenceExtensionService.java b/jans-core/service/src/main/java/io/jans/service/external/ExternalPersistenceExtensionService.java index 94fd7b9ad1f..578ef3fffa8 100644 --- a/jans-core/service/src/main/java/io/jans/service/external/ExternalPersistenceExtensionService.java +++ b/jans-core/service/src/main/java/io/jans/service/external/ExternalPersistenceExtensionService.java @@ -21,7 +21,7 @@ import io.jans.model.custom.script.conf.CustomScriptConfiguration; import io.jans.model.custom.script.type.persistence.PersistenceType; import io.jans.orm.PersistenceEntryManager; -import io.jans.orm.exception.extension.PersistenceExtension; +import io.jans.orm.extension.PersistenceExtension; import io.jans.service.custom.script.ExternalScriptService; /** diff --git a/jans-orm/.gitignore b/jans-orm/.gitignore index 56bbf5c9641..431771766f6 100644 --- a/jans-orm/.gitignore +++ b/jans-orm/.gitignore @@ -1,4 +1,5 @@ # Eclipse project files +.dbeaver .settings .project .classpath diff --git a/jans-orm/core/src/main/java/io/jans/orm/PersistenceEntryManager.java b/jans-orm/core/src/main/java/io/jans/orm/PersistenceEntryManager.java index ba5896296f2..06d611c4fda 100644 --- a/jans-orm/core/src/main/java/io/jans/orm/PersistenceEntryManager.java +++ b/jans-orm/core/src/main/java/io/jans/orm/PersistenceEntryManager.java @@ -25,8 +25,9 @@ import jakarta.persistence.criteria.CriteriaUpdate; import jakarta.persistence.metamodel.Metamodel; import io.jans.orm.event.DeleteNotifier; -import io.jans.orm.exception.extension.PersistenceExtension; +import io.jans.orm.extension.PersistenceExtension; import io.jans.orm.model.AttributeData; +import io.jans.orm.model.AttributeType; import io.jans.orm.model.BatchOperation; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; @@ -94,6 +95,7 @@ PagedResult findPagedEntries(String primaryKey, Class entryClass, Filt @Deprecated void remove(String dn); + void removeByDn(String dn, String[] objectClasses); void remove(String primaryKey, Class entryClass); int remove(String primaryKey, Class entryClass, Filter filter, int count); @@ -102,6 +104,7 @@ PagedResult findPagedEntries(String primaryKey, Class entryClass, Filt void removeRecursively(String primaryKey); void removeRecursively(String primaryKey, Class entryClass); + void removeRecursivelyFromDn(String primaryKey, String[] objectClasses); boolean hasBranchesSupport(String primaryKey); boolean hasExpirationSupport(String primaryKey); @@ -126,7 +129,7 @@ Map> groupListByProperties(Class entryClass, List entries, @Deprecated List exportEntry(String dn); - List exportEntry(String dn, String objectClass); + List exportEntry(String dn, String objectClass); void importEntry(String dn, Class entryClass, List data); @@ -135,6 +138,8 @@ Map> groupListByProperties(Class entryClass, List entries, void setPersistenceExtension(PersistenceExtension persistenceExtension); + AttributeType getAttributeType(String primaryKey, Class entryClass, String propertyName); + boolean destroy(); default void clear() { diff --git a/jans-orm/core/src/main/java/io/jans/orm/exception/extension/PersistenceExtension.java b/jans-orm/core/src/main/java/io/jans/orm/extension/PersistenceExtension.java similarity index 91% rename from jans-orm/core/src/main/java/io/jans/orm/exception/extension/PersistenceExtension.java rename to jans-orm/core/src/main/java/io/jans/orm/extension/PersistenceExtension.java index cfa9305fe69..ccc77e93cd3 100644 --- a/jans-orm/core/src/main/java/io/jans/orm/exception/extension/PersistenceExtension.java +++ b/jans-orm/core/src/main/java/io/jans/orm/extension/PersistenceExtension.java @@ -4,7 +4,7 @@ * Copyright (c) 2020, Janssen Project */ -package io.jans.orm.exception.extension; +package io.jans.orm.extension; /** * Base interface for persistence script diff --git a/jans-orm/core/src/main/java/io/jans/orm/impl/BaseEntryManager.java b/jans-orm/core/src/main/java/io/jans/orm/impl/BaseEntryManager.java index 4e487e7f985..fd998889204 100644 --- a/jans-orm/core/src/main/java/io/jans/orm/impl/BaseEntryManager.java +++ b/jans-orm/core/src/main/java/io/jans/orm/impl/BaseEntryManager.java @@ -6,18 +6,52 @@ package io.jans.orm.impl; +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.codec.binary.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.fasterxml.jackson.databind.ObjectMapper; + import io.jans.orm.PersistenceEntryManager; -import io.jans.orm.annotation.*; +import io.jans.orm.annotation.AttributeEnum; +import io.jans.orm.annotation.AttributeName; +import io.jans.orm.annotation.AttributesList; +import io.jans.orm.annotation.CustomObjectClass; +import io.jans.orm.annotation.DN; +import io.jans.orm.annotation.DataEntry; +import io.jans.orm.annotation.Expiration; +import io.jans.orm.annotation.JsonObject; +import io.jans.orm.annotation.LanguageTag; +import io.jans.orm.annotation.ObjectClass; +import io.jans.orm.annotation.SchemaEntry; import io.jans.orm.exception.EntryPersistenceException; import io.jans.orm.exception.InvalidArgumentException; import io.jans.orm.exception.MappingException; -import io.jans.orm.exception.extension.PersistenceExtension; +import io.jans.orm.extension.PersistenceExtension; import io.jans.orm.model.AttributeData; import io.jans.orm.model.AttributeDataModification; -import io.jans.orm.model.AttributeDataModification.AttributeModificationType; +import io.jans.orm.model.AttributeType; import io.jans.orm.model.SearchScope; import io.jans.orm.model.base.LocalizedString; +import io.jans.orm.model.AttributeDataModification.AttributeModificationType; import io.jans.orm.operation.PersistenceOperationService; import io.jans.orm.reflect.property.Getter; import io.jans.orm.reflect.property.PropertyAnnotation; @@ -26,24 +60,13 @@ import io.jans.orm.search.filter.Filter; import io.jans.orm.util.ArrayHelper; import io.jans.orm.util.StringHelper; -import org.apache.commons.codec.binary.Base64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.*; -import java.util.Map.Entry; -import java.util.stream.Collectors; /** * Abstract Entry Manager * - * @author Yuriy Movchan - * @version April 25, 2022 + * @author Yuriy Movchan Date: 10.07.2010 */ -public abstract class BaseEntryManager implements PersistenceEntryManager { +public abstract class BaseEntryManager implements PersistenceEntryManager { private static final Logger LOG = LoggerFactory.getLogger(BaseEntryManager.class); @@ -80,7 +103,7 @@ public abstract class BaseEntryManager implements PersistenceEntryManager { protected static final int DEFAULT_PAGINATION_SIZE = 100; - protected PersistenceOperationService operationService = null; + protected O operationService = null; protected PersistenceExtension persistenceExtension = null; @Override @@ -447,7 +470,7 @@ protected boolean isEmptyAttributeValues(AttributeData attributeData) { protected abstract void merge(String dn, String[] objectClasses, List attributeDataModifications, Integer expiration); - protected abstract void removeByDn(String dn, String[] objectClasses); + public abstract void removeByDn(String dn, String[] objectClasses); @Deprecated public void remove(String primaryKey) { @@ -467,7 +490,7 @@ public void remove(String primaryKey, Class entryClass) { removeByDn(primaryKey, objectClasses); } - protected abstract void removeRecursivelyFromDn(String primaryKey, String[] objectClasses); + public abstract void removeRecursivelyFromDn(String primaryKey, String[] objectClasses); @Deprecated public void removeRecursively(String primaryKey) { @@ -2226,6 +2249,11 @@ public void setPersistenceExtension(PersistenceExtension persistenceExtension) { } } + @Override + public AttributeType getAttributeType(String primaryKey, Class entryClass, String propertyName) { + throw new UnsupportedOperationException("Method not implemented."); + } + protected static final class PropertyComparator implements Comparator, Serializable { private static final long serialVersionUID = 574848841116711467L; diff --git a/jans-orm/core/src/main/java/io/jans/orm/model/AttributeType.java b/jans-orm/core/src/main/java/io/jans/orm/model/AttributeType.java new file mode 100644 index 00000000000..6b567f6bf04 --- /dev/null +++ b/jans-orm/core/src/main/java/io/jans/orm/model/AttributeType.java @@ -0,0 +1,46 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.orm.model; + +/** + * DB Attribute Type + * + * @author Yuriy Movchan Date: 07/04/2022 + */ +public class AttributeType { + private final String name; + private final String type; + private final Boolean multiValued; + + public AttributeType(String name, String type) { + this(name, type, null); + } + + public AttributeType(String name, String type, Boolean multiValued) { + this.name = name; + this.type = type; + this.multiValued = multiValued; + } + + public Boolean getMultiValued() { + return multiValued; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + @Override + public String toString() { + return "AttributeType [name=" + name + ", type=" + type + ", multiValued=" + multiValued + "]"; + } + +} diff --git a/jans-orm/core/src/main/java/io/jans/orm/model/Sort.java b/jans-orm/core/src/main/java/io/jans/orm/model/Sort.java index 2e43d1494ca..47085ae47f9 100644 --- a/jans-orm/core/src/main/java/io/jans/orm/model/Sort.java +++ b/jans-orm/core/src/main/java/io/jans/orm/model/Sort.java @@ -33,6 +33,18 @@ public SortOrder getSortOrder() { return sortOrder; } + public static Sort desc(String name) { + return new Sort(name, SortOrder.DESCENDING); + } + + public static Sort asc(String name) { + return new Sort(name, SortOrder.ASCENDING); + } + + public static Sort def(String name) { + return new Sort(name, SortOrder.DEFAULT); + } + @Override public int hashCode() { final int prime = 31; diff --git a/jans-orm/core/src/main/java/io/jans/orm/model/SortOrder.java b/jans-orm/core/src/main/java/io/jans/orm/model/SortOrder.java index 4532c7b9618..c60ace029bb 100644 --- a/jans-orm/core/src/main/java/io/jans/orm/model/SortOrder.java +++ b/jans-orm/core/src/main/java/io/jans/orm/model/SortOrder.java @@ -12,14 +12,18 @@ import io.jans.orm.annotation.AttributeEnum; /** - * @author Val Pecaoco + * Sort order + * + * @author Yuriy Movchan Date: 04/22/2021 */ public enum SortOrder implements AttributeEnum { - ASCENDING("ascending"), - DESCENDING("descending"); + ASCENDING("ascending", "asc"), + DESCENDING("descending", "desc"), + DEFAULT("default", "def"); private String value; + private String shortValue; private static Map MAP_BY_VALUES = new HashMap(); @@ -29,8 +33,9 @@ public enum SortOrder implements AttributeEnum { } } - SortOrder(String value) { + SortOrder(String value, String shortValue) { this.value = value; + this.shortValue = shortValue; } @Override @@ -38,6 +43,10 @@ public String getValue() { return value; } + public String getShortValue() { + return shortValue; + } + public static SortOrder getByValue(String value) { return MAP_BY_VALUES.get(value); } diff --git a/jans-orm/core/src/main/java/io/jans/orm/operation/PersistenceOperationService.java b/jans-orm/core/src/main/java/io/jans/orm/operation/PersistenceOperationService.java index 6558185780b..508a14231e8 100644 --- a/jans-orm/core/src/main/java/io/jans/orm/operation/PersistenceOperationService.java +++ b/jans-orm/core/src/main/java/io/jans/orm/operation/PersistenceOperationService.java @@ -7,10 +7,10 @@ package io.jans.orm.operation; import io.jans.orm.exception.AuthenticationException; -import io.jans.orm.exception.extension.PersistenceExtension; import io.jans.orm.exception.operation.ConnectionException; import io.jans.orm.exception.operation.EntryConvertationException; import io.jans.orm.exception.operation.SearchException; +import io.jans.orm.extension.PersistenceExtension; /** * Base interface for Operation Service diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseAddBulkUserSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseAddBulkUserSample.java new file mode 100644 index 00000000000..b5d98839b3f --- /dev/null +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseAddBulkUserSample.java @@ -0,0 +1,144 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.orm.couchbase; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.log4j.Logger; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.status.StatusLogger; + +import io.jans.orm.couchbase.impl.CouchbaseEntryManager; +import io.jans.orm.couchbase.model.GluuStatus; +import io.jans.orm.couchbase.model.SimpleUser; +import io.jans.orm.model.base.CustomAttribute; +import io.jans.orm.model.base.CustomObjectAttribute; +import io.jans.orm.search.filter.Filter; +import io.jans.orm.util.StringHelper; + +/** + * @author Yuriy Movchan Date: 06/16/2022 + */ +public final class CouchbaseAddBulkUserSample { + + private static final Logger LOG; + + static { + StatusLogger.getLogger().setLevel(Level.OFF); + LoggingHelper.configureConsoleAppender(); + LOG = Logger.getLogger(CouchbaseAddBulkUserSample.class); + } + + private static AtomicLong successResult = new AtomicLong(0) ; + private static AtomicLong errorResult = new AtomicLong(0) ; + private static AtomicLong totalTime = new AtomicLong(0) ; + private static AtomicLong activeCount = new AtomicLong(0) ; + + private CouchbaseAddBulkUserSample() { + } + + public static void main(String[] args) throws InterruptedException { + // Prepare sample connection details + CouchbaseEntryManagerSample couchbaseEntryManagerSample = new CouchbaseEntryManagerSample(); + final CouchbaseEntryManager couchbaseEntryManager = couchbaseEntryManagerSample.createCouchbaseEntryManager(); + + int countUsers = 1000000; + int threadCount = 200; + int threadIterationCount = countUsers / threadCount; + + long totalStart = System.currentTimeMillis(); + try { + ExecutorService executorService = Executors.newFixedThreadPool(threadCount, daemonThreadFactory()); + for (int i = 0; i < threadCount; i++) { + activeCount.incrementAndGet(); + final int count = i; + executorService.execute(new AddUserRunnable(i * threadIterationCount, (i + 1) * threadIterationCount - 1) { + @Override + public void run() { + long start = System.currentTimeMillis(); + for (int j = startRange; j <= endRange; j++) { + long userUid = j; + String name = String.format("user%06d", userUid); + String sn = String.format("lastname%06d", userUid); + String cn = String.format("%s %s", name, sn); + String mail = String.format("%s@gluu.org", name); + + String dn = String.format("inum=%06d,ou=people,o=jans", userUid); + + SimpleUser newUser = new SimpleUser(); + newUser.setDn(dn); + newUser.setUserId(name); + newUser.setUserPassword("topsecret" + j); + newUser.setDisplayName(cn); + newUser.setMail(mail); + newUser.setStatus(GluuStatus.ACTIVE); + + CustomObjectAttribute customAttribute = new CustomObjectAttribute("givenName", name); + newUser.getCustomAttributes().add(customAttribute); + + newUser.setAttributeValue("sn", sn); + newUser.setAttributeValue("cn", cn); + + try { + couchbaseEntryManager.persist(newUser); + successResult.incrementAndGet(); + } catch (Throwable e) { + errorResult.incrementAndGet(); + System.out.println("ERROR !!!, thread: " + count + ", uid: " + name + ", error:" + e.getMessage()); + e.printStackTrace(); + } + } + + long end = System.currentTimeMillis(); + long duration = end - start; + LOG.info("Thread " + count + " execution time: " + duration); + totalTime.addAndGet(duration); + activeCount.decrementAndGet(); + } + }); + } + + while (activeCount.get() != 0) { + Thread.sleep(1000L); + } + } finally { + couchbaseEntryManager.destroy(); + } + long totalEnd = System.currentTimeMillis(); + long duration = totalEnd - totalStart; + + LOG.info("Total execution time: " + duration + " after execution: " + (threadCount * threadIterationCount)); + + System.out.println(String.format("successResult: '%d', errorResult: '%d'", successResult.get(), errorResult.get())); + } + + public static ThreadFactory daemonThreadFactory() { + return new ThreadFactory() { + public Thread newThread(Runnable runnable) { + Thread thread = new Thread(runnable); + thread.setDaemon(true); + return thread; + } + }; + } + + public static abstract class AddUserRunnable implements Runnable { + + protected int startRange; + protected int endRange; + + public AddUserRunnable(int startRange, int endRange) { + this.startRange = startRange; + this.endRange = endRange; + } + } + +} diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseBatchJobSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseBatchJobSample.java index ab4c61a51ed..91b8bcd5f66 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseBatchJobSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseBatchJobSample.java @@ -11,9 +11,10 @@ import org.apache.logging.log4j.status.StatusLogger; import io.jans.orm.couchbase.impl.CouchbaseEntryManager; +import io.jans.orm.couchbase.model.SimpleCache; import io.jans.orm.couchbase.model.SimpleClient; import io.jans.orm.couchbase.model.SimpleSession; -import io.jans.orm.couchbase.model.SimpleTokenCouchbase; +import io.jans.orm.couchbase.model.SimpleToken; import io.jans.orm.exception.EntryPersistenceException; import io.jans.orm.model.BatchOperation; import io.jans.orm.model.DefaultBatchOperation; @@ -48,12 +49,12 @@ public static void main(String[] args) { // Create Couchbase entry manager final CouchbaseEntryManager couchbaseEntryManager = couchbaseEntryManagerSample.createCouchbaseEntryManager(); - BatchOperation tokenCouchbaseBatchOperation = new ProcessBatchOperation() { + BatchOperation tokenCouchbaseBatchOperation = new ProcessBatchOperation() { private int processedCount = 0; @Override - public void performAction(List objects) { - for (SimpleTokenCouchbase simpleTokenCouchbase : objects) { + public void performAction(List objects) { + for (SimpleToken simpleTokenCouchbase : objects) { try { CustomAttribute customAttribute = getUpdatedAttribute(couchbaseEntryManager, simpleTokenCouchbase.getDn(), "exp", simpleTokenCouchbase.getAttribute("exp")); @@ -70,7 +71,7 @@ public void performAction(List objects) { }; final Filter filter1 = Filter.createPresenceFilter("exp"); - couchbaseEntryManager.findEntries("o=jans", SimpleTokenCouchbase.class, filter1, SearchScope.SUB, new String[] {"exp"}, + couchbaseEntryManager.findEntries("ou=tokens,o=jans", SimpleToken.class, filter1, SearchScope.SUB, new String[] {"exp"}, tokenCouchbaseBatchOperation, 0, 0, 100); BatchOperation sessionBatchOperation = new ProcessBatchOperation() { @@ -95,34 +96,59 @@ public void performAction(List objects) { }; final Filter filter2 = Filter.createPresenceFilter("jansLastAccessTime"); - couchbaseEntryManager.findEntries("o=jans", SimpleSession.class, filter2, SearchScope.SUB, new String[] {"jansLastAccessTime"}, + couchbaseEntryManager.findEntries("ou=sessions,o=jans", SimpleSession.class, filter2, SearchScope.SUB, new String[] {"jansLastAccessTime"}, sessionBatchOperation, 0, 0, 100); - BatchOperation clientBatchOperation = new ProcessBatchOperation() { + if (false) { + Calendar calendar = Calendar.getInstance(); + Date jansLastAccessTimeDate = new Date(); + calendar.setTime(jansLastAccessTimeDate); + calendar.add(Calendar.SECOND, 60); + Date date = calendar.getTime(); + + for (int i = 0; i < 1111; i++) { + String id = String.format("cache_%06d", i); + String dn = String.format("id=%s,ou=cache,o=jans", id); + + SimpleCache newCache = new SimpleCache(); + newCache.setDn(dn); + newCache.setId(id); + newCache.setData("{'sample_data': 'sample_data_value'}"); + newCache.setExpirationDate(date); + newCache.setDeletable(true); + + try { + couchbaseEntryManager.persist(newCache); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + + BatchOperation clientBatchOperation = new ProcessBatchOperation() { private int processedCount = 0; @Override - public void performAction(List objects) { - for (SimpleClient simpleClient : objects) { + public void performAction(List objects) { + for (SimpleCache simpleCache : objects) { processedCount++; } LOG.info("Total processed: " + processedCount); } }; - final Filter filter3 = Filter.createPresenceFilter("exp"); - List result3 = couchbaseEntryManager.findEntries("o=jans", SimpleClient.class, filter3, SearchScope.SUB, - new String[] {"exp"}, clientBatchOperation, 0, 0, 1000); + List result3 = couchbaseEntryManager.findEntries("ou=cache,o=jans", SimpleCache.class, filter3, SearchScope.SUB, + new String[] {"exp"}, clientBatchOperation, 0, 0, 333); LOG.info("Result count (without collecting results): " + result3.size()); - BatchOperation clientBatchOperation2 = new DefaultBatchOperation() { + BatchOperation clientBatchOperation2 = new DefaultBatchOperation() { private int processedCount = 0; @Override - public void performAction(List objects) { - for (SimpleClient simpleClient : objects) { + public void performAction(List objects) { + for (SimpleCache simpleCache : objects) { processedCount++; } @@ -131,8 +157,8 @@ public void performAction(List objects) { }; final Filter filter4 = Filter.createPresenceFilter("exp"); - List result4 = couchbaseEntryManager.findEntries("o=jans", SimpleClient.class, filter4, SearchScope.SUB, - new String[] {"exp"}, clientBatchOperation2, 0, 0, 1000); + List result4 = couchbaseEntryManager.findEntries("ou=cache,o=jans", SimpleCache.class, filter4, SearchScope.SUB, + new String[] {"exp"}, clientBatchOperation2, 0, 0, 333); LOG.info("Result count (with collecting results): " + result4.size()); } diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseConcurentSessionUpdateSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseConcurentSessionUpdateSample.java index d4120026a02..eeab54a6e48 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseConcurentSessionUpdateSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseConcurentSessionUpdateSample.java @@ -44,7 +44,7 @@ public static void main(String[] args) throws InterruptedException { String sessionId = "xyzcyzxy-a41a-45ad-8a83-61485dbad561"; final String sessionDn = "uniqueIdentifier=" + sessionId + ",ou=session,o=jans"; final String userDn = - "inum=@!E8F2.853B.1E7B.ACE2!0001!39A4.C163!0000!A8F2.DE1E.D7FB,ou=people,o=jans"; + "inum=sample_concurrent_user_1,ou=people,o=jans"; final SimpleSessionState simpleSessionState = new SimpleSessionState(); simpleSessionState.setDn(sessionDn); diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseCustomMultiValuedTypesSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseCustomMultiValuedTypesSample.java index 848a5202ed6..7a6d517e82f 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseCustomMultiValuedTypesSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseCustomMultiValuedTypesSample.java @@ -9,14 +9,15 @@ import java.util.Arrays; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.jans.orm.couchbase.impl.CouchbaseEntryManager; import io.jans.orm.couchbase.model.SimpleUser; import io.jans.orm.couchbase.operation.impl.CouchbaseConnectionProvider; import io.jans.orm.model.base.CustomObjectAttribute; import io.jans.orm.search.filter.Filter; import io.jans.orm.util.StringHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * @author Yuriy Movchan Date: 09/16/2019 @@ -75,8 +76,8 @@ public static void main(String[] args) { LOG.info("Cusom attributes '{}'", foundUpdatedUser.getCustomAttributes()); - Filter filter = Filter.createEqualityFilter(Filter.createLowercaseFilter("givenName"), StringHelper.toLowerCase("jon")); - List foundUpdatedUsers = couchbaseEntryManager.findEntries("o=jans", SimpleUser.class, filter); + Filter filter = Filter.createEqualityFilter(Filter.createLowercaseFilter("givenName"), StringHelper.toLowerCase("john")); + List foundUpdatedUsers = couchbaseEntryManager.findEntries("ou=people,o=jans", SimpleUser.class, filter); System.out.println(foundUpdatedUsers); } diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseCustomStringAttributesSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseCustomStringAttributesSample.java index c499de4b638..e3c935548e9 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseCustomStringAttributesSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseCustomStringAttributesSample.java @@ -9,6 +9,9 @@ import java.util.Arrays; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.jans.orm.couchbase.impl.CouchbaseEntryManager; import io.jans.orm.couchbase.model.SimpleCustomStringUser; import io.jans.orm.couchbase.model.UserRole; @@ -16,9 +19,6 @@ import io.jans.orm.model.base.CustomAttribute; import io.jans.orm.search.filter.Filter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * @author Yuriy Movchan Date: 09/27/2019 */ @@ -43,7 +43,7 @@ public static void main(String[] args) { newUser.setDn(String.format("inum=%s,ou=people,o=jans", System.currentTimeMillis())); newUser.setUserId("sample_user_" + System.currentTimeMillis()); newUser.setUserPassword("test"); - newUser.getCustomAttributes().add(new CustomAttribute("streetAddress", Arrays.asList("London", "Texas", "Kiev"))); + newUser.getCustomAttributes().add(new CustomAttribute("streetAddress", Arrays.asList("London", "Texas", "Kiev")).setMultiValued(false)); newUser.getCustomAttributes().add((new CustomAttribute("jansExternalUid", randomExternalUid)).setMultiValued(true)); newUser.setUserRole(UserRole.ADMIN); @@ -59,14 +59,29 @@ public static void main(String[] args) { LOG.info("Custom attributes '{}'", foundUser.getCustomAttributes()); for (CustomAttribute customAttribute : foundUser.getCustomAttributes()) { - LOG.info("Found custom attribute '{}' with value '{}'", customAttribute.getName(), customAttribute.getValue()); + LOG.info("Found custom attribute '{}' with value '{}'", customAttribute.getName(), customAttribute.getValues()); + } + + // Persist as multivalued + foundUser.setAttributeValues("streetAddress", Arrays.asList("London", "Texas", "Kiev")); + couchbaseEntryManager.merge(foundUser); + + LOG.info("Updated User '{}' with uid '{}' and key '{}'", foundUser, foundUser.getUserId(), foundUser.getDn()); + + // Find added dummy user but use custom class with String values + SimpleCustomStringUser foundUser2 = couchbaseEntryManager.find(SimpleCustomStringUser.class, foundUser.getDn()); + LOG.info("Found User '{}' with uid '{}' and key '{}'", foundUser, foundUser.getUserId(), foundUser.getDn()); + + LOG.info("Custom attributes '{}'", foundUser2.getCustomAttributes()); + for (CustomAttribute customAttribute : foundUser2.getCustomAttributes()) { + LOG.info("Found custom attribute '{}' with value '{}'", customAttribute.getName(), customAttribute.getValues()); } // Find by jsExternalUid Filter jsExternalUidFilter = Filter.createEqualityFilter("jansExternalUid", randomExternalUid).multiValued(); List foundUsers = couchbaseEntryManager.findEntries("ou=people,o=jans", SimpleCustomStringUser.class, jsExternalUidFilter); - for (SimpleCustomStringUser foundUser2 : foundUsers) { - LOG.info("Found User '{}' by jsExternalUid with uid '{}' and key '{}'", foundUser2, foundUser2.getUserId(), foundUser2.getDn()); + for (SimpleCustomStringUser foundUser3 : foundUsers) { + LOG.info("Found User '{}' by jsExternalUid with uid '{}' and key '{}'", foundUser3, foundUser3.getUserId(), foundUser3.getDn()); } } diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseDeleteSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseDeleteSample.java index 2e46151757e..f18ee200be6 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseDeleteSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseDeleteSample.java @@ -6,15 +6,22 @@ package io.jans.orm.couchbase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.jans.orm.couchbase.impl.CouchbaseEntryManager; +import io.jans.orm.couchbase.model.GluuStatus; +import io.jans.orm.couchbase.model.SimpleCache; +import io.jans.orm.couchbase.model.SimpleUser; import io.jans.orm.couchbase.operation.impl.CouchbaseConnectionProvider; +import io.jans.orm.model.base.CustomObjectAttribute; import io.jans.orm.model.base.DeletableEntity; import io.jans.orm.search.filter.Filter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; /** * @author Yuriy Movchan Date: 11/03/2016 @@ -33,13 +40,38 @@ public static void main(String[] args) { // Create Couchbase entry manager CouchbaseEntryManager couchbaseEntryManager = couchbaseEntryManagerSample.createCouchbaseEntryManager(); + Date now = new GregorianCalendar(TimeZone.getTimeZone("UTC")).getTime(); + Calendar pastCalendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); + pastCalendar.add(Calendar.SECOND, -60); + Date past = pastCalendar.getTime(); + + if (true) { + for (int i = 0; i < 1000; i++) { + String id = String.format("cache_%06d", i); + String dn = String.format("id=%s,ou=cache,o=jans", id); + + SimpleCache newCache = new SimpleCache(); + newCache.setDn(dn); + newCache.setId(id); + newCache.setData("{'sample_data': 'sample_data_value'}"); + newCache.setExpirationDate(past); + newCache.setDeletable(true); + + try { + couchbaseEntryManager.persist(newCache); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + String baseDn = "ou=cache,o=jans"; Filter filter = Filter.createANDFilter( Filter.createEqualityFilter("del", true), - Filter.createLessOrEqualFilter("exp", couchbaseEntryManager.encodeTime(baseDn, new Date())) + Filter.createLessOrEqualFilter("exp", couchbaseEntryManager.encodeTime(baseDn, now)) ); - int result = couchbaseEntryManager.remove(baseDn, DeletableEntity.class, filter, 100); + int result = couchbaseEntryManager.remove(baseDn, SimpleCache.class, filter, 2000); System.out.println(result); } diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseEntryManagerSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseEntryManagerSample.java index 5a0d87fef5c..d4b00f78d5a 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseEntryManagerSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseEntryManagerSample.java @@ -9,6 +9,7 @@ import java.util.Properties; import org.apache.log4j.Logger; + import io.jans.orm.couchbase.impl.CouchbaseEntryManager; import io.jans.orm.couchbase.impl.CouchbaseEntryManagerFactory; @@ -26,14 +27,19 @@ private Properties getSampleConnectionProperties() { connectionProperties.put("couchbase#servers", "localhost"); connectionProperties.put("couchbase#auth.userName", "admin"); connectionProperties.put("couchbase#auth.userPassword", "secret"); -// connectionProperties.put("couchbase#buckets", "jans"); - connectionProperties.put("couchbase#buckets", "jans, jans_user, jans_token"); + + connectionProperties.put("couchbase#connection.dns.use-lookup", "false"); + + connectionProperties.put("couchbase#buckets", "jans, jans_user, jans_site, jans_cache, jans_token, jans_session"); connectionProperties.put("couchbase#bucket.default", "jans"); - connectionProperties.put("couchbase#bucket.jans_user.mapping", "people, groups"); - connectionProperties.put("couchbase#bucket.jans_token.mapping", "sessions"); + connectionProperties.put("couchbase#bucket.jans_user.mapping", "people, groups, authorizations"); + connectionProperties.put("couchbase#bucket.jans_site.mapping", "cache-refresh"); + connectionProperties.put("couchbase#bucket.jans_cache.mapping", "cache"); + connectionProperties.put("couchbase#bucket.jans_token.mapping", "tokens"); + connectionProperties.put("couchbase#bucket.jans_session.mapping", "sessions"); - connectionProperties.put("couchbase#password.encryption.method", "CRYPT-SHA-256"); + connectionProperties.put("couchbase#password.encryption.method", "SSHA-256"); return connectionProperties; } diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseSample.java index e7dab969c93..f0fd71fff0f 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseSample.java @@ -9,10 +9,13 @@ import java.util.Arrays; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.jans.orm.couchbase.impl.CouchbaseEntryManager; import io.jans.orm.couchbase.model.SimpleAttribute; -import io.jans.orm.couchbase.model.SimpleGrant; import io.jans.orm.couchbase.model.SimpleSession; +import io.jans.orm.couchbase.model.SimpleToken; import io.jans.orm.couchbase.model.SimpleUser; import io.jans.orm.couchbase.operation.impl.CouchbaseConnectionProvider; import io.jans.orm.model.PagedResult; @@ -21,9 +24,6 @@ import io.jans.orm.model.base.CustomObjectAttribute; import io.jans.orm.search.filter.Filter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * @author Yuriy Movchan Date: 11/03/2016 */ @@ -49,11 +49,8 @@ public static void main(String[] args) { newUser.getCustomAttributes().add(new CustomObjectAttribute("test", "test_value")); couchbaseEntryManager.persist(newUser); -// SimpleUser dummyUser = couchbaseEntryManager.find(SimpleUser.class, "inum=test,o=test,o=jans"); -// LOG.info("Dummy User '{}'", dummyUser); - // Find all users which have specified object classes defined in SimpleUser - List users = couchbaseEntryManager.findEntries("o=@!5304.5F36.0E64.E1AC!0001!179C.62D7,o=jans", SimpleUser.class, null); + List users = couchbaseEntryManager.findEntries("ou=people,o=jans", SimpleUser.class, null); for (SimpleUser user : users) { LOG.info("User with uid: '{}' with DN: '{}'", user.getUserId(), user.getDn()); } @@ -77,26 +74,28 @@ public static void main(String[] args) { for (SimpleUser user : users) { boolean result1 = couchbaseEntryManager.authenticate(user.getDn(), "test"); boolean result2 = couchbaseEntryManager.authenticate("ou=people,o=jans", SimpleUser.class, user.getUserId(), "test"); - System.out.println("authetication result: " + result1 + ", " + result2); + System.out.println("authetication result: " + result1 + ", " + result2 + ", user: " + user.getDn()); } - Filter filter = Filter.createEqualityFilter("status", "active"); - List attributes = couchbaseEntryManager.findEntries("o=jans", SimpleAttribute.class, filter, SearchScope.SUB, null, null, 10, + Filter filterAttributes = Filter.createEqualityFilter("jansStatus", "active"); + List attributes = couchbaseEntryManager.findEntries("ou=attributes,o=jans", SimpleAttribute.class, filterAttributes, SearchScope.SUB, null, null, 10, 0, 0); + LOG.info("Found attributes: " + attributes.size()); for (SimpleAttribute attribute : attributes) { LOG.info("Attribute with displayName: " + attribute.getCustomAttributes().get(1)); } - List sessions = couchbaseEntryManager.findEntries("o=jans", SimpleSession.class, filter, SearchScope.SUB, null, null, 10, 0, + Filter filterSessions = Filter.createEqualityFilter("jansState", "authenticated"); + List sessions = couchbaseEntryManager.findEntries("ou=sessions,o=jans", SimpleSession.class, filterSessions, SearchScope.SUB, null, null, 0, 1, 0); LOG.info("Found sessions: " + sessions.size()); - List grants = couchbaseEntryManager.findEntries("o=jans", SimpleGrant.class, null, SearchScope.SUB, - new String[] { "grtId" }, null, 1, 0, 0); - LOG.info("Found grants: " + grants.size()); + List tokens = couchbaseEntryManager.findEntries("ou=tokens,o=jans", SimpleToken.class, null, SearchScope.SUB, + new String[] { "code" }, null, 1, 0, 0); + LOG.info("Found tokens: " + tokens.size()); try { - PagedResult listViewResponse = couchbaseEntryManager.findPagedEntries("o=jans", SimpleUser.class, null, + PagedResult listViewResponse = couchbaseEntryManager.findPagedEntries("ou=people,o=jans", SimpleUser.class, null, new String[] { "uid", "displayName", "status" }, "uid", SortOrder.ASCENDING, 0, 6, 4); LOG.info("Found persons: " + listViewResponse.getEntriesCount() + ", total persons: " + listViewResponse.getTotalEntriesCount()); @@ -108,7 +107,7 @@ public static void main(String[] args) { } try { - PagedResult listViewResponse = couchbaseEntryManager.findPagedEntries("o=jans", SimpleUser.class, null, + PagedResult listViewResponse = couchbaseEntryManager.findPagedEntries("ou=people,o=jans", SimpleUser.class, null, new String[] { "uid", "displayName", "status" }, "uid", SortOrder.DESCENDING, 0, 6, 4); LOG.info("Found persons: " + listViewResponse.getEntriesCount() + ", total persons: " + listViewResponse.getTotalEntriesCount()); diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUpateMissingEntrySample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUpateMissingEntrySample.java index 138bcff9d77..1a7dd612ec9 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUpateMissingEntrySample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUpateMissingEntrySample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -47,6 +47,7 @@ public static void main(String[] args) { System.out.println("Updated"); } catch (EntryPersistenceException ex) { LOG.info("Failed to update, root case exception: {}", ex.getCause().getClass(), ex); + LOG.info("Test Passed :) It's right behaviour."); } } diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUpdateAttributeSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUpdateAttributeSample.java index 3e1d33c4b08..a2bc38c4584 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUpdateAttributeSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUpdateAttributeSample.java @@ -61,6 +61,7 @@ public static void main(String[] args) { SimpleUser userAfterUpdate = couchbaseEntryManager.find(SimpleUser.class, dn); LOG.info("Found user after update '{}'", userAfterUpdate); + LOG.info("jansLastLogonTime after update '{}'", userAfterUpdate.getAttribute("jansLastLogonTime")); } } diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUserSearchSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUserSearchSample.java index d771831977b..7f8d0dce17f 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUserSearchSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/CouchbaseUserSearchSample.java @@ -50,7 +50,7 @@ public static void main(String[] args) throws InterruptedException { int countUsers = 1000000; int threadCount = 200; - int threadIterationCount = 10; + int threadIterationCount = 50; long totalStart = System.currentTimeMillis(); try { diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/UmaResourceSample.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/UmaResourceSample.java index 82b122539e3..bbc20000168 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/UmaResourceSample.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/UmaResourceSample.java @@ -1,7 +1,7 @@ /* * oxCore is available under the MIT License (2014). See http://opensource.org/licenses/MIT for full text. * - * Copyright (c) 2014, Gluu + * Copyright (c) 2020, Janssen Project */ package io.jans.orm.couchbase; diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/GluuStatus.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/GluuStatus.java new file mode 100644 index 00000000000..4e77f90b20a --- /dev/null +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/GluuStatus.java @@ -0,0 +1,60 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.orm.couchbase.model; + +import java.util.HashMap; +import java.util.Map; + +import io.jans.orm.annotation.AttributeEnum; + +/** + * Status + * + * @author Yuriy Movchan Date: 10.07.2010 + */ +public enum GluuStatus implements AttributeEnum { + + ACTIVE("active", "Active"), INACTIVE("inactive", "Inactive"), EXPIRED("expired", "Expired"), REGISTER("register", "Register"); + + private String value; + private String displayName; + + private static Map MAP_BY_VALUES = new HashMap(); + + static { + for (GluuStatus enumType : values()) { + MAP_BY_VALUES.put(enumType.getValue(), enumType); + } + } + + GluuStatus(String value, String displayName) { + this.value = value; + this.displayName = displayName; + } + + public String getValue() { + return value; + } + + public String getDisplayName() { + return displayName; + } + + public static GluuStatus getByValue(String value) { + return MAP_BY_VALUES.get(value); + } + + public Enum resolveByValue(String value) { + return getByValue(value); + } + + @Override + public String toString() { + return value; + } + +} diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleAttribute.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleAttribute.java index c6552756aa1..a1c10ec682f 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleAttribute.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleAttribute.java @@ -10,12 +10,12 @@ import java.util.ArrayList; import java.util.List; -import io.jans.orm.model.base.CustomAttribute; import io.jans.orm.annotation.AttributesList; import io.jans.orm.annotation.CustomObjectClass; import io.jans.orm.annotation.DN; import io.jans.orm.annotation.DataEntry; import io.jans.orm.annotation.ObjectClass; +import io.jans.orm.model.base.CustomAttribute; import io.jans.orm.util.StringHelper; /** diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleCache.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleCache.java new file mode 100644 index 00000000000..1a11777c6b5 --- /dev/null +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleCache.java @@ -0,0 +1,82 @@ +package io.jans.orm.couchbase.model; + +import java.util.Date; + +import io.jans.orm.annotation.AttributeName; +import io.jans.orm.annotation.DataEntry; +import io.jans.orm.annotation.Expiration; +import io.jans.orm.annotation.ObjectClass; +import io.jans.orm.model.base.BaseEntry; + +@DataEntry +@ObjectClass(value = "cache") +public class SimpleCache extends BaseEntry { + + @Expiration + private Integer ttl; + @AttributeName(name = "uuid") + private String id; + @AttributeName(name = "iat") + private Date creationDate; + @AttributeName(name = "dat") + private String data; + + @AttributeName(name = "exp", consistency = true) + private Date expirationDate; + @AttributeName(name = "del") + private Boolean deletable; + + public Integer getTtl() { + return ttl; + } + + public void setTtl(Integer ttl) { + this.ttl = ttl; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public Date getExpirationDate() { + return expirationDate; + } + + public void setExpirationDate(Date expirationDate) { + this.expirationDate = expirationDate; + } + + public Boolean getDeletable() { + return deletable; + } + + public void setDeletable(Boolean deletable) { + this.deletable = deletable; + } + + @Override + public String toString() { + return "SimpleCache [ttl=" + ttl + ", id=" + id + ", creationDate=" + creationDate + ", data=" + data + + ", expirationDate=" + expirationDate + ", deletable=" + deletable + "]"; + } +} diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleSessionState.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleSessionState.java index 56bb82c6ad5..0c3cf8c544c 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleSessionState.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleSessionState.java @@ -45,7 +45,7 @@ public class SimpleSessionState implements Serializable { @AttributeName(name = "authnTime") private Date authenticationTime; - @AttributeName(name = "oxAuthSessionState") + @AttributeName(name = "jansAuthSessionState") private Boolean permissionGranted; @AttributeName(name = "jansAsJwt") diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleToken.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleToken.java new file mode 100644 index 00000000000..1d8bae10634 --- /dev/null +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleToken.java @@ -0,0 +1,132 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.orm.couchbase.model; + +import io.jans.orm.annotation.*; +import io.jans.orm.model.base.CustomAttribute; +import io.jans.orm.util.StringHelper; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Created by eugeniuparvan on 1/12/17. + */ +@DataEntry +@ObjectClass(value = "token") +public class SimpleToken implements Serializable { + + private static final long serialVersionUID = 6726419630327625172L; + + @AttributeName(name = "tknCde", consistency = true) + private String code; + + @AttributeName(name = "iat") + private Date creationDate; + + @AttributeName(name = "exp") + private Date expirationDate; + + @AttributeName(name = "del") + private boolean deletable = true; + + @AttributesList(name = "name", value = "values", sortByName = true) + private List customAttributes = new ArrayList(); + + @DN + private String dn; + + @CustomObjectClass + private String[] customObjectClasses; + + public String getDn() { + return dn; + } + + public void setDn(String dn) { + this.dn = dn; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + + public Date getExpirationDate() { + return expirationDate; + } + + public void setExpirationDate(Date expirationDate) { + this.expirationDate = expirationDate; + } + + public boolean isDeletable() { + return deletable; + } + + public void setDeletable(boolean deletable) { + this.deletable = deletable; + } + + public List getCustomAttributes() { + return customAttributes; + } + + public void setCustomAttributes(List customAttributes) { + this.customAttributes = customAttributes; + } + + public String getAttribute(String ldapAttribute) { + String attribute = null; + if (ldapAttribute != null && !ldapAttribute.isEmpty()) { + for (CustomAttribute customAttribute : customAttributes) { + if (customAttribute.getName().equals(ldapAttribute)) { + attribute = customAttribute.getValue(); + break; + } + } + } + + return attribute; + } + + public List getAttributeValues(String ldapAttribute) { + List values = null; + if (ldapAttribute != null && !ldapAttribute.isEmpty()) { + for (CustomAttribute customAttribute : customAttributes) { + if (StringHelper.equalsIgnoreCase(customAttribute.getName(), ldapAttribute)) { + values = customAttribute.getValues(); + break; + } + } + } + + return values; + } + + public String[] getCustomObjectClasses() { + return customObjectClasses; + } + + public void setCustomObjectClasses(String[] customObjectClasses) { + this.customObjectClasses = customObjectClasses; + } + +} diff --git a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleUser.java b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleUser.java index f88b0f49954..b2e5cff215f 100644 --- a/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleUser.java +++ b/jans-orm/couchbase-sample/src/main/java/io/jans/orm/couchbase/model/SimpleUser.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -37,6 +37,15 @@ public class SimpleUser implements Serializable { @AttributeName(name = "userPassword") private String userPassword; + @AttributeName(name = "displayName") + private String displayName; + + @AttributeName(name = "mail") + private String mail; + + @AttributeName(name = "jansStatus") + private GluuStatus status; + @AttributeName(name = "role") private UserRole userRole; @@ -73,6 +82,30 @@ public void setUserPassword(String userPassword) { this.userPassword = userPassword; } + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getMail() { + return mail; + } + + public void setMail(String mail) { + this.mail = mail; + } + + public GluuStatus getStatus() { + return status; + } + + public void setStatus(GluuStatus status) { + this.status = status; + } + public UserRole getUserRole() { return userRole; } diff --git a/jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/ManualCouchbaseEntryManagerTest.java b/jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/ManualCouchbaseEntryManagerTest.java similarity index 57% rename from jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/ManualCouchbaseEntryManagerTest.java rename to jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/ManualCouchbaseEntryManagerTest.java index e56b2063fd3..a8120fb6fb6 100644 --- a/jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/ManualCouchbaseEntryManagerTest.java +++ b/jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/ManualCouchbaseEntryManagerTest.java @@ -4,20 +4,23 @@ * Copyright (c) 2020, Janssen Project */ -package io.jans.couchbase.test; +package io.jans.orm.couchbase.test; + +import org.testng.annotations.Test; -import com.couchbase.client.core.message.kv.subdoc.multi.Lookup; import com.couchbase.client.java.Bucket; -import com.couchbase.client.java.document.JsonDocument; -import com.couchbase.client.java.subdoc.DocumentFragment; -import com.couchbase.client.java.subdoc.SubdocOptionsBuilder; +import com.couchbase.client.java.json.JsonObject; +import com.couchbase.client.java.kv.GetOptions; +import com.couchbase.client.java.kv.GetResult; +import com.couchbase.client.java.kv.LookupInMacro; +import com.couchbase.client.java.kv.LookupInResult; +import com.couchbase.client.java.kv.LookupInSpec; import io.jans.orm.couchbase.impl.CouchbaseEntryManager; import io.jans.orm.couchbase.impl.CouchbaseEntryManagerFactory; import io.jans.orm.couchbase.model.SimpleClient; import io.jans.orm.exception.operation.SearchException; import io.jans.orm.util.Pair; -import org.testng.annotations.Test; import java.io.IOException; import java.io.InputStream; @@ -33,8 +36,8 @@ public void sample() throws IOException { CouchbaseEntryManager manager = createCouchbaseEntryManager(); try { - List attributeList = manager.findEntries("o=jans", SimpleClient.class, null); - System.out.println(attributeList); + List resultList = manager.findEntries("ou=clietns,o=jans", SimpleClient.class, null); + System.out.println(resultList); } finally { manager.destroy(); } @@ -52,17 +55,20 @@ public void sampleSessionId() throws IOException, SearchException { System.out.println("Key: " + key + ", ttl:" + sessionId.getTtl()); Bucket sessionBucket = manager.getOperationService().getConnectionProvider().getBucketMapping("sessions").getBucket(); - final JsonDocument lookup = sessionBucket.get(key); - System.out.println("expiry: " + lookup.expiry()); + GetOptions getOptions1 = GetOptions.getOptions().withExpiry(true); + final GetResult lookup = sessionBucket.defaultCollection().get(key, getOptions1); + System.out.println("expiry: " + lookup.expiryTime()); - DocumentFragment ttl = sessionBucket.lookupIn(key).get("$document.exptime", new SubdocOptionsBuilder().xattr(true)).execute(); - System.out.println("ttl: " + ttl.content("$document.exptime")); + final LookupInResult ttl = sessionBucket.defaultCollection().lookupIn(key, Collections.singletonList( + LookupInSpec.get(LookupInMacro.EXPIRY_TIME).xattr())); + System.out.println("ttl: " + ttl.contentAs(0, Long.class)); updateSession(sessionId); manager.merge(sessionId); - final JsonDocument lookup2 = manager.getOperationService().getConnectionProvider().getBucketMapping("sessions").getBucket().get(key); - System.out.println("expiry after update: " + lookup2.expiry()); + GetOptions getOptions3 = GetOptions.getOptions().withExpiry(true); + final GetResult lookup2 = manager.getOperationService().getConnectionProvider().getBucketMapping("sessions").getBucket().defaultCollection().get(key, getOptions3); + System.out.println("expiry after update: " + lookup2.expiryTime()); } finally { manager.destroy(); @@ -95,7 +101,7 @@ private Pair expirationDate(Date creationDate) { } // MODIFY ACCORDING TO YOUR SERVER - public static Properties loadProperties() throws IOException { + private static Properties loadProperties() throws IOException { Properties properties = new Properties(); properties.put("couchbase.auth.userPassword", "secret"); @@ -105,11 +111,30 @@ public static Properties loadProperties() throws IOException { } } + private static Properties getSampleConnectionProperties() { + Properties connectionProperties = new Properties(); + + connectionProperties.put("couchbase#servers", "localhost"); + connectionProperties.put("couchbase#auth.userName", "admin"); + connectionProperties.put("couchbase#auth.userPassword", "secret"); + connectionProperties.put("couchbase#buckets", "jans, jans_user, jans_site, jans_cache, jans_token, jans_session"); + + connectionProperties.put("couchbase#bucket.default", "jans"); + connectionProperties.put("couchbase#bucket.jans_user.mapping", "people, groups, authorizations"); + connectionProperties.put("couchbase#bucket.jans_site.mapping", "cache-refresh"); + connectionProperties.put("couchbase#bucket.jans_cache.mapping", "cache"); + connectionProperties.put("couchbase#bucket.jans_token.mapping", "tokens"); + connectionProperties.put("couchbase#bucket.jans_session.mapping", "sessions"); + + connectionProperties.put("couchbase#password.encryption.method", "SSHA-256"); + + return connectionProperties; + } public static CouchbaseEntryManager createCouchbaseEntryManager() throws IOException { CouchbaseEntryManagerFactory couchbaseEntryManagerFactory = new CouchbaseEntryManagerFactory(); couchbaseEntryManagerFactory.create(); - CouchbaseEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(loadProperties()); + CouchbaseEntryManager couchbaseEntryManager = couchbaseEntryManagerFactory.createEntryManager(getSampleConnectionProperties() /* loadProperties() */); System.out.println("Created CouchbaseEntryManager: " + couchbaseEntryManager); return couchbaseEntryManager; diff --git a/jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/SessionId.java b/jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/SessionId.java similarity index 95% rename from jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/SessionId.java rename to jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/SessionId.java index 8e99165d4ee..4c032369476 100644 --- a/jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/SessionId.java +++ b/jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/SessionId.java @@ -4,19 +4,23 @@ * Copyright (c) 2020, Janssen Project */ -package io.jans.couchbase.test; +package io.jans.orm.couchbase.test; -import com.couchbase.client.java.cluster.User; -import com.google.common.collect.Maps; -import io.jans.orm.annotation.*; -import io.jans.orm.model.base.Deletable; - -import jakarta.inject.Named; -import jakarta.persistence.Transient; import java.io.Serializable; import java.util.Date; import java.util.Map; +import com.google.common.collect.Maps; + +import io.jans.orm.annotation.AttributeName; +import io.jans.orm.annotation.DN; +import io.jans.orm.annotation.DataEntry; +import io.jans.orm.annotation.Expiration; +import io.jans.orm.annotation.JsonObject; +import io.jans.orm.annotation.ObjectClass; +import io.jans.orm.model.base.Deletable; +import jakarta.persistence.Transient; + /** * @author Yuriy Zabrovarnyy * @author Javier Rojas Blum @@ -74,9 +78,6 @@ public class SessionId implements Deletable, Serializable { @Transient private transient boolean persisted; - @Transient - private User user; - @Expiration private int ttl; @@ -155,14 +156,6 @@ public void setUserDn(String p_userDn) { userDn = p_userDn != null ? p_userDn : ""; } - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - public Date getAuthenticationTime() { return authenticationTime; } diff --git a/jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/SessionIdState.java b/jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/SessionIdState.java similarity index 96% rename from jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/SessionIdState.java rename to jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/SessionIdState.java index 4460e1ec408..29974dd42bd 100644 --- a/jans-orm/couchbase-sample/src/test/java/io/jans/couchbase/test/SessionIdState.java +++ b/jans-orm/couchbase-sample/src/test/java/io/jans/orm/couchbase/test/SessionIdState.java @@ -4,7 +4,7 @@ * Copyright (c) 2020, Janssen Project */ -package io.jans.couchbase.test; +package io.jans.orm.couchbase.test; import io.jans.orm.annotation.AttributeEnum; diff --git a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseBatchOperationWraper.java b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseBatchOperationWraper.java index 9b38f691d26..7cba72e3c55 100644 --- a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseBatchOperationWraper.java +++ b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseBatchOperationWraper.java @@ -6,13 +6,13 @@ package io.jans.orm.couchbase.impl; -import com.couchbase.client.java.document.json.JsonObject; -import com.couchbase.client.java.query.N1qlQueryRow; +import java.util.ArrayList; +import java.util.List; + import io.jans.orm.model.BatchOperation; import io.jans.orm.reflect.property.PropertyAnnotation; -import java.util.ArrayList; -import java.util.List; +import com.couchbase.client.java.json.JsonObject; /** * Couchbase batch operation wrapper @@ -43,19 +43,12 @@ public final BatchOperation getBatchOperation() { return batchOperation; } - public List createEntities(List searchResult) { + public List createEntities(List searchResult) { if (couchbaseEntryManager == null) { return new ArrayList(0); } - JsonObject[] resultObjects = new JsonObject[searchResult.size()]; - - int index = 0; - for (N1qlQueryRow row : searchResult) { - resultObjects[index++] = row.value(); - } - - return couchbaseEntryManager.createEntities(entryClass, propertiesAnnotations, null, resultObjects); + return couchbaseEntryManager.createEntities(entryClass, propertiesAnnotations, null, searchResult.toArray(new JsonObject[0])); } } diff --git a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseEntryManager.java b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseEntryManager.java index 43ece668734..24550f48fe9 100644 --- a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseEntryManager.java +++ b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseEntryManager.java @@ -6,24 +6,27 @@ package io.jans.orm.couchbase.impl; -import com.couchbase.client.core.message.kv.subdoc.multi.Mutation; -import com.couchbase.client.java.document.json.JsonArray; -import com.couchbase.client.java.document.json.JsonObject; -import com.couchbase.client.java.query.consistency.ScanConsistency; -import com.couchbase.client.java.query.dsl.Expression; -import com.couchbase.client.java.query.dsl.Sort; -import com.couchbase.client.java.subdoc.MutationSpec; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import io.jans.orm.util.ArrayHelper; +import io.jans.orm.util.StringHelper; +import jakarta.inject.Inject; import io.jans.orm.PersistenceEntryManager; import io.jans.orm.annotation.AttributeName; -import io.jans.orm.couchbase.model.ConvertedExpression; -import io.jans.orm.couchbase.model.SearchReturnDataType; -import io.jans.orm.couchbase.operation.CouchbaseOperationService; -import io.jans.orm.couchbase.operation.impl.CouchbaseConnectionProvider; import io.jans.orm.event.DeleteNotifier; import io.jans.orm.exception.AuthenticationException; import io.jans.orm.exception.EntryDeleteException; import io.jans.orm.exception.EntryPersistenceException; import io.jans.orm.exception.MappingException; +import io.jans.orm.exception.UnsupportedOperationException; import io.jans.orm.exception.operation.SearchException; import io.jans.orm.impl.BaseEntryManager; import io.jans.orm.impl.GenericKeyConverter; @@ -35,37 +38,31 @@ import io.jans.orm.model.DefaultBatchOperation; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; +import io.jans.orm.model.Sort; import io.jans.orm.model.SortOrder; import io.jans.orm.reflect.property.PropertyAnnotation; import io.jans.orm.reflect.util.ReflectHelper; import io.jans.orm.search.filter.Filter; -import io.jans.orm.util.ArrayHelper; -import io.jans.orm.util.StringHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import jakarta.inject.Inject; -import java.io.Serializable; -import java.time.DateTimeException; -import java.time.Instant; -import java.time.format.DateTimeParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; +import com.couchbase.client.core.msg.kv.SubdocCommandType; +import com.couchbase.client.java.json.JsonArray; +import com.couchbase.client.java.json.JsonObject; +import com.couchbase.client.java.kv.MutateInSpec; +import com.couchbase.client.java.query.QueryScanConsistency; -import static java.time.format.DateTimeFormatter.ISO_INSTANT; +import io.jans.orm.couchbase.model.ConvertedExpression; +import io.jans.orm.couchbase.model.SearchReturnDataType; +import io.jans.orm.couchbase.operation.CouchbaseOperationService; +import io.jans.orm.couchbase.operation.impl.CouchbaseConnectionProvider; /** * Couchbase Entry Manager * * @author Yuriy Movchan Date: 05/14/2018 */ -public class CouchbaseEntryManager extends BaseEntryManager implements Serializable { +public class CouchbaseEntryManager extends BaseEntryManager implements Serializable { public static final int EXPIRATION_30_DAYS = 30 * 86400; @@ -83,7 +80,7 @@ public class CouchbaseEntryManager extends BaseEntryManager implements Serializa protected CouchbaseEntryManager(CouchbaseOperationService operationService) { this.operationService = operationService; - this.FILTER_CONVERTER = new CouchbaseFilterConverter(this); + this.FILTER_CONVERTER = new CouchbaseFilterConverter(operationService); subscribers = new LinkedList(); } @@ -106,11 +103,11 @@ public boolean destroy() { return true; } - return ((CouchbaseOperationService) this.operationService).destroy(); + return this.operationService.destroy(); } public CouchbaseOperationService getOperationService() { - return (CouchbaseOperationService) operationService; + return operationService; } @Override @@ -174,7 +171,7 @@ public void remove(Object entry) { LOG.debug("LDAP entry to remove: '{}'", dnValue.toString()); - remove(dnValue.toString()); + remove(dnValue.toString(), entryClass); } @Override @@ -228,7 +225,7 @@ protected void persist(String dn, String[] objectClasses, List at public void merge(String dn, String[] objectClasses, List attributeDataModifications, Integer expirationValue) { // Update entry try { - List modifications = new ArrayList(attributeDataModifications.size()); + List modifications = new ArrayList(attributeDataModifications.size()); for (AttributeDataModification attributeDataModification : attributeDataModifications) { AttributeData attribute = attributeDataModification.getAttribute(); AttributeData oldAttribute = attributeDataModification.getOldAttribute(); @@ -249,14 +246,14 @@ public void merge(String dn, String[] objectClasses, List void removeByDn(String dn, String[] objectClasses) { + public void removeByDn(String dn, String[] objectClasses) { // Remove entry try { for (DeleteNotifier subscriber : subscribers) { @@ -351,7 +348,7 @@ protected int removeImpl(String dn, Class entryClass, Filter filter, int } try { - int processed = getOperationService().delete(keyWithInum.getKey(), getScanConsistency(convertedExpression), convertedExpression.expression(), count); + int processed = getOperationService().delete(keyWithInum.getKey(), getQueryScanConsistency(convertedExpression), convertedExpression, count); return processed; } catch (Exception ex) { @@ -364,8 +361,7 @@ protected List find(String dn, String[] objectClasses, Map result = getAttributeDataList(entry); if (result != null) { return result; @@ -478,7 +474,7 @@ protected PagedResult findEntriesImpl(String baseDN, Class en if (batchOperation != null) { batchOperationWraper = new CouchbaseBatchOperationWraper(batchOperation, this, entryClass, propertiesAnnotations); } - searchResult = searchImpl(keyWithInum.getKey(), getScanConsistency(convertedExpression), convertedExpression.expression(), scope, currentLdapReturnAttributes, + searchResult = searchImpl(keyWithInum.getKey(), getQueryScanConsistency(convertedExpression), convertedExpression, scope, currentLdapReturnAttributes, defaultSort, batchOperationWraper, returnDataType, start, count, chunkSize); if (searchResult == null) { @@ -518,7 +514,7 @@ protected boolean contains(String baseDN, String[] objectClasses, Class e PagedResult searchResult = null; try { ParsedKey keyWithInum = toCouchbaseKey(baseDN); - searchResult = searchImpl(keyWithInum.getKey(), getScanConsistency(convertedExpression), convertedExpression.expression(), SearchScope.SUB, ldapReturnAttributes, null, + searchResult = searchImpl(keyWithInum.getKey(), getQueryScanConsistency(convertedExpression), convertedExpression, SearchScope.SUB, ldapReturnAttributes, null, null, SearchReturnDataType.SEARCH, 1, 1, 0); if (searchResult == null) { throw new EntryPersistenceException(String.format("Failed to find entry with baseDN: %s, filter: %s", baseDN, searchFilter)); @@ -530,7 +526,7 @@ protected boolean contains(String baseDN, String[] objectClasses, Class e return (searchResult != null) && (searchResult.getEntriesCount() > 0); } - private PagedResult searchImpl(String key, ScanConsistency scanConsistency, Expression expression, SearchScope scope, String[] attributes, Sort[] orderBy, + private PagedResult searchImpl(String key, QueryScanConsistency scanConsistency, ConvertedExpression expression, SearchScope scope, String[] attributes, Sort[] orderBy, CouchbaseBatchOperationWraper batchOperationWraper, SearchReturnDataType returnDataType, int start, int count, int pageSize) throws SearchException { return getOperationService().search(key, scanConsistency, expression, scope, toInternalAttributes(attributes), orderBy, batchOperationWraper, returnDataType, start, count, pageSize); } @@ -606,7 +602,7 @@ private List getAttributeDataList(JsonObject entry) { attributeValueObjects = new Object[] { attributeObject }; } else if (attributeObject instanceof String) { // If it looks like date, treat as Date - Object valueAsDate = decodeTime(null, attributeObject.toString(), true); + Object valueAsDate = decodeTime(null, attributeObject.toString(), true); Object value = valueAsDate == null ? attributeObject.toString() : valueAsDate; attributeValueObjects = new Object[] { value }; @@ -656,7 +652,7 @@ public boolean authenticate(String baseDN, Class entryClass, String userN } try { - PagedResult searchResult = searchImpl(toCouchbaseKey(baseDN).getKey(), getScanConsistency(convertedExpression), convertedExpression.expression(), + PagedResult searchResult = searchImpl(toCouchbaseKey(baseDN).getKey(), getQueryScanConsistency(convertedExpression), convertedExpression, SearchScope.SUB, CouchbaseOperationService.UID_ARRAY, null, null, SearchReturnDataType.SEARCH, 0, 1, 1); if ((searchResult == null) || (searchResult.getEntriesCount() != 1)) { return false; @@ -723,7 +719,7 @@ public int countEntries(String baseDN, Class entryClass, Filter filter, S PagedResult searchResult; try { - searchResult = searchImpl(toCouchbaseKey(baseDN).getKey(), getScanConsistency(convertedExpression), convertedExpression.expression(), scope, null, null, + searchResult = searchImpl(toCouchbaseKey(baseDN).getKey(), getQueryScanConsistency(convertedExpression), convertedExpression, scope, null, null, null, SearchReturnDataType.COUNT, 0, 0, 0); } catch (Exception ex) { throw new EntryPersistenceException( @@ -733,7 +729,7 @@ public int countEntries(String baseDN, Class entryClass, Filter filter, S return searchResult.getTotalEntriesCount(); } - private MutationSpec createModification(final Mutation type, final String attributeName, final Boolean multiValued, final Object... attributeValues) { + private MutateInSpec createModification(final SubdocCommandType type, final String attributeName, final Boolean multiValued, final Object... attributeValues) { String realAttributeName = attributeName; Object[] realValues = attributeValues; @@ -743,21 +739,41 @@ private MutationSpec createModification(final Mutation type, final String attrib escapeValues(realValues); - if ((multiValued == null) || !multiValued) { - return new MutationSpec(type, realAttributeName, realValues[0]); + MutateInSpec result = null; + if (SubdocCommandType.DELETE == type) { + result = MutateInSpec.remove(realAttributeName); } else { - return new MutationSpec(type, realAttributeName, realValues); + if ((multiValued == null) || !multiValued) { + if (SubdocCommandType.DICT_ADD == type) { + result = MutateInSpec.insert(realAttributeName, realValues[0]); + } else if (SubdocCommandType.REPLACE == type) { + result = MutateInSpec.replace(realAttributeName, realValues[0]); + } + } else { + // TODO: Check if we can use array here + if (SubdocCommandType.DICT_ADD == type) { + result = MutateInSpec.insert(realAttributeName, realValues); + } else if (SubdocCommandType.REPLACE == type) { + result = MutateInSpec.replace(realAttributeName, realValues); + } + } } + + if (result == null) { + throw new UnsupportedOperationException(String.format("Operation with type '%s' isn't supported", type)); + } + + return result; } protected Sort buildSort(String sortBy, SortOrder sortOrder) { Sort requestedSort = null; if (SortOrder.DESCENDING == sortOrder) { - requestedSort = Sort.desc(Expression.path(sortBy)); + requestedSort = Sort.desc(sortBy); } else if (SortOrder.ASCENDING == sortOrder) { - requestedSort = Sort.asc(Expression.path(sortBy)); + requestedSort = Sort.asc(sortBy); } else { - requestedSort = Sort.def(Expression.path(sortBy)); + requestedSort = Sort.def(sortBy); } return requestedSort; } @@ -775,7 +791,7 @@ protected Sort[] getDefaultSort(Class entryClass) { Sort[] sort = new Sort[sortByProperties.length]; for (int i = 0; i < sortByProperties.length; i++) { - sort[i] = Sort.def(Expression.path(sortByProperties[i])); + sort[i] = Sort.def(sortByProperties[i]); } return sort; @@ -799,11 +815,12 @@ public List exportEntry(String dn) { } } - public List exportEntry(String dn, String objectClass) { + @Override + public List exportEntry(String dn, String objectClass) { return exportEntry(dn); } - private ConvertedExpression toCouchbaseFilter(Filter genericFilter, Map propertiesAnnotationsMap) throws SearchException { + private ConvertedExpression toCouchbaseFilter(Filter genericFilter, Map propertiesAnnotationsMap) throws SearchException { return FILTER_CONVERTER.convertToCouchbaseFilter(genericFilter, propertiesAnnotationsMap); } @@ -851,19 +868,7 @@ public int getCountEntries() { @Override public String encodeTime(String baseDN, Date date) { - if (date == null) { - return null; - } - - try { - String utcDate = ISO_INSTANT.format(Instant.ofEpochMilli(date.getTime())); - // Drop UTC zone identifier to comply with format employed in CB: yyyy-MM-dd'T'HH:mm:ss.SSS - return utcDate.substring(0, utcDate.length() - 1); - } catch (DateTimeException ex) { - LOG.error("Cannot format date '{}' as ISO", date, ex); - return null; - } - + return operationService.encodeTime(date); } @Override @@ -877,21 +882,7 @@ public Date decodeTime(String baseDN, String date) { } protected Date decodeTime(String baseDN, String date, boolean silent) { - if (StringHelper.isEmpty(date)) { - return null; - } - - // Add ending Z if necessary - String dateZ = date.endsWith("Z") ? date : date + "Z"; - try { - return new Date(Instant.parse(dateZ).toEpochMilli()); - } catch (DateTimeParseException ex) { - if (!silent) { - LOG.error("Failed to decode generalized time '{}'", date, ex); - } - - return null; - } + return operationService.decodeTime(date, silent); } @Override @@ -950,15 +941,15 @@ protected Object getNativeDateAttributeValue(Date dateValue) { return encodeTime(dateValue); } - private ScanConsistency getScanConsistency(ConvertedExpression convertedExpression) { + private QueryScanConsistency getQueryScanConsistency(ConvertedExpression convertedExpression) { if (convertedExpression.consistency()) { - return ScanConsistency.REQUEST_PLUS; + return QueryScanConsistency.REQUEST_PLUS; } return null; } - private ScanConsistency getScanConsistency(String attributeName, Map propertiesAnnotationsMap) { + private QueryScanConsistency getQueryScanConsistency(String attributeName, Map propertiesAnnotationsMap) { if (StringHelper.isEmpty(attributeName)) { return null; } @@ -971,7 +962,7 @@ private ScanConsistency getScanConsistency(String attributeName, Map sslTrustStoreType = Optional.ofNullable(couchbaseConnectionProperties.getProperty("ssl.trustStore.type")); - builder.sslEnabled(true).sslTruststoreFile(sslTrustStoreFile).sslTruststorePassword(sslTrustStorePin); + clusterEnvironmentBuilder.securityConfig().enableTls(true).trustStore(FileSystems.getDefault().getPath(sslTrustStoreFile), sslTrustStorePin, sslTrustStoreType); LOG.info("Configuring builder to enable SSL support"); } else { - builder.sslEnabled(false); + clusterEnvironmentBuilder.securityConfig().enableTls(false); LOG.info("Configuring builder to disable SSL support"); } - + String connectTimeoutString = couchbaseConnectionProperties.getProperty("connection.connect-timeout"); if (StringHelper.isNotEmpty(connectTimeoutString)) { int connectTimeout = Integer.valueOf(connectTimeoutString); - builder.connectTimeout(connectTimeout); + clusterEnvironmentBuilder.timeoutConfig().connectTimeout(Duration.ofMillis(connectTimeout)); LOG.info("Configuring builder to override connectTimeout from properties"); } - String operationTracingEnabledString = couchbaseConnectionProperties.getProperty("connection.operation-tracing-enabled"); - if (StringHelper.isNotEmpty(operationTracingEnabledString)) { - boolean operationTracingEnabled = Boolean.valueOf(operationTracingEnabledString); - builder.operationTracingEnabled(operationTracingEnabled); - LOG.info("Configuring builder to override operationTracingEnabled from properties"); - } - - String mutationTokensEnabledString = couchbaseConnectionProperties.getProperty("connection.mutation-tokens-enabled"); - if (StringHelper.isNotEmpty(mutationTokensEnabledString)) { - boolean mutationTokensEnabled = Boolean.valueOf(mutationTokensEnabledString); - builder.mutationTokensEnabled(mutationTokensEnabled); - LOG.info("Configuring builder to override mutationTokensEnabled from properties"); + String connectDnsUseLookupString = couchbaseConnectionProperties.getProperty("connection.dns.use-lookup"); + if (StringHelper.isNotEmpty(connectDnsUseLookupString)) { + boolean connectDnsUseLookup = Boolean.valueOf(connectDnsUseLookupString); + clusterEnvironmentBuilder.ioConfig().enableDnsSrv(connectDnsUseLookup); + LOG.info("Configuring builder to override enableDnsSrv from properties"); } - String computationPoolSizeString = couchbaseConnectionProperties.getProperty("connection.computation-pool-size"); - if (StringHelper.isNotEmpty(computationPoolSizeString)) { - int computationPoolSize = Integer.valueOf(computationPoolSizeString); - builder.computationPoolSize(computationPoolSize); - LOG.info("Configuring builder to override computationPoolSize from properties"); + String kvTimeoutString = couchbaseConnectionProperties.getProperty("connection.kv-timeout"); + if (StringHelper.isNotEmpty(kvTimeoutString)) { + int kvTimeout = Integer.valueOf(kvTimeoutString); + clusterEnvironmentBuilder.timeoutConfig().kvTimeout(Duration.ofMillis(kvTimeout)); + LOG.info("Configuring builder to override kvTimeout from properties"); } - String keepAliveTimeoutString = couchbaseConnectionProperties.getProperty("connection.keep-alive-timeout"); - if (StringHelper.isNotEmpty(keepAliveTimeoutString)) { - long keepAliveTimeout = Integer.valueOf(keepAliveTimeoutString); - builder.keepAliveTimeout(keepAliveTimeout); - LOG.info("Configuring builder to override keepAliveTimeout from properties"); + String queryTimeoutString = couchbaseConnectionProperties.getProperty("connection.query-timeout"); + if (StringHelper.isNotEmpty(queryTimeoutString)) { + int queryTimeout = Integer.valueOf(queryTimeoutString); + clusterEnvironmentBuilder.timeoutConfig().queryTimeout(Duration.ofMillis(queryTimeout)); + LOG.info("Configuring builder to override queryTimeout from properties"); } - String keepAliveIntervalString = couchbaseConnectionProperties.getProperty("connection.keep-alive-interval"); - if (StringHelper.isNotEmpty(keepAliveIntervalString)) { - long keepAliveInterval = Integer.valueOf(keepAliveIntervalString); - builder.keepAliveInterval(keepAliveInterval); - LOG.info("Configuring builder to override keepAliveInterval from properties"); + String mutationTokensEnabledString = couchbaseConnectionProperties.getProperty("connection.mutation-tokens-enabled"); + if (StringHelper.isNotEmpty(mutationTokensEnabledString)) { + boolean mutationTokensEnabled = Boolean.valueOf(mutationTokensEnabledString); + clusterEnvironmentBuilder.ioConfig().enableMutationTokens(mutationTokensEnabled); + LOG.info("Configuring builder to override mutationTokensEnabled from properties"); } - this.couchbaseEnvironment = builder.build(); - - this.builder = null; + this.clusterEnvironment = clusterEnvironmentBuilder.build(); } @Override @@ -136,8 +130,8 @@ public HashMap getConfigurationFileNames(String alias) { return confs; } - public CouchbaseEnvironment getCouchbaseEnvironment() { - return couchbaseEnvironment; + public ClusterEnvironment getClusterEnvironment() { + return clusterEnvironment; } @Override @@ -155,7 +149,7 @@ public CouchbaseEntryManager createEntryManager(Properties conf) { throw new ConfigurationException("Failed to create Couchbase environment!"); } - CouchbaseConnectionProvider connectionProvider = new CouchbaseConnectionProvider(entryManagerConf, couchbaseEnvironment); + CouchbaseConnectionProvider connectionProvider = new CouchbaseConnectionProvider(entryManagerConf, clusterEnvironment); connectionProvider.create(); if (!connectionProvider.isCreated()) { throw new ConfigurationException( @@ -171,22 +165,10 @@ public CouchbaseEntryManager createEntryManager(Properties conf) { @Override public void initStandalone(BaseFactoryService persistanceFactoryService) { - this.builder = DefaultCouchbaseEnvironment.builder().mutationTokensEnabled(true).computationPoolSize(5); - } + ClusterEnvironment.Builder clusterEnvironmentBuilder = ClusterEnvironment.builder(); + clusterEnvironmentBuilder.ioConfig().enableMutationTokens(true).build(); - -/* - public static void main(String[] args) throws FileNotFoundException, IOException { - Properties prop = new Properties(); - prop.load(new FileInputStream(new File("D:/Temp/jans-couchbase.properties"))); - - CouchbaseEntryManagerFactory cemf = new CouchbaseEntryManagerFactory(); - cemf.create(); - - CouchbaseEntryManager cem = cemf.createEntryManager(prop); - - System.out.println(cem.getOperationService().getConnectionProvider().isCreated()); - + this.clusterEnvironment = clusterEnvironmentBuilder.build(); } -*/ + } diff --git a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseFilterConverter.java b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseFilterConverter.java index f504380ff83..7aaf8b9af8d 100644 --- a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseFilterConverter.java +++ b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/impl/CouchbaseFilterConverter.java @@ -7,47 +7,48 @@ package io.jans.orm.couchbase.impl; import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Function; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.couchbase.client.java.document.json.JsonArray; -import com.couchbase.client.java.query.dsl.Expression; -import com.couchbase.client.java.query.dsl.functions.Collections; -import com.couchbase.client.java.query.dsl.functions.Collections.SatisfiesBuilder; -import com.couchbase.client.java.query.dsl.functions.StringFunctions; - +import io.jans.orm.util.ArrayHelper; +import io.jans.orm.util.StringHelper; import io.jans.orm.annotation.AttributeEnum; import io.jans.orm.annotation.AttributeName; -import io.jans.orm.couchbase.model.ConvertedExpression; import io.jans.orm.exception.operation.SearchException; import io.jans.orm.ldap.impl.LdapFilterConverter; import io.jans.orm.reflect.property.PropertyAnnotation; import io.jans.orm.reflect.util.ReflectHelper; import io.jans.orm.search.filter.Filter; import io.jans.orm.search.filter.FilterType; -import io.jans.orm.util.ArrayHelper; -import io.jans.orm.util.Pair; -import io.jans.orm.util.StringHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.couchbase.client.java.json.JsonObject; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.jans.orm.couchbase.model.ConvertedExpression; +import io.jans.orm.couchbase.operation.CouchbaseOperationService; /** - * Filter to Couchbase expressions convert + * Filter to N1QL parameterized Couchbase query converter * - * @author Yuriy Movchan Date: 05/15/2018 + * @author Yuriy Movchan Date: 05/26/2022 */ public class CouchbaseFilterConverter { private static final Logger LOG = LoggerFactory.getLogger(CouchbaseFilterConverter.class); private LdapFilterConverter ldapFilterConverter = new LdapFilterConverter(); + private static final ObjectMapper JSON_OBJECT_MAPPER = new ObjectMapper(); - private CouchbaseEntryManager couchbaseEntryManager; + private CouchbaseOperationService operationService; - public CouchbaseFilterConverter(CouchbaseEntryManager couchbaseEntryManager) { - this.couchbaseEntryManager = couchbaseEntryManager; + public CouchbaseFilterConverter(CouchbaseOperationService operationService) { + this.operationService = operationService; } public ConvertedExpression convertToCouchbaseFilter(Filter genericFilter, Map propertiesAnnotationsMap) throws SearchException { @@ -55,12 +56,22 @@ public ConvertedExpression convertToCouchbaseFilter(Filter genericFilter, Map propertiesAnnotationsMap, Function processor) throws SearchException { - Filter currentGenericFilter = genericFilter; + JsonObject queryParameters = JsonObject.create(); + return convertToCouchbaseFilter(genericFilter, propertiesAnnotationsMap, queryParameters, processor); + } + + public ConvertedExpression convertToCouchbaseFilter(Filter genericFilter, Map propertiesAnnotationsMap, JsonObject queryParameters, Function processor) throws SearchException { + if (genericFilter == null) { + return null; + } + + Filter currentGenericFilter = genericFilter; FilterType type = currentGenericFilter.getType(); if (FilterType.RAW == type) { - LOG.warn("RAW Ldap filter to Couchbase convertion will be removed in new version!!!"); + LOG.warn("RAW Ldap filter to N1QL convertion will be removed in new version!!!"); currentGenericFilter = ldapFilterConverter.convertRawLdapFilterToFilter(currentGenericFilter.getFilterString()); + LOG.debug(String.format("Converted RAW filter: %s", currentGenericFilter)); type = currentGenericFilter.getType(); } @@ -80,7 +91,7 @@ public ConvertedExpression convertToCouchbaseFilter(Filter genericFilter, Map assertionValues = new ArrayList(); + for (ConvertedExpression eqFilter : expFilters) { + assertionValues.addAll(eqFilter.getSingleLevelParameters()); } - Expression exp = Expression - .par(buildPath(lastEqFilter, propertiesAnnotationsMap, processor).getFirst().in(jsonArrayValues)); - return ConvertedExpression.build(exp, requiredConsistency); + StringBuilder result = new StringBuilder(buildLeftExpressionPart(genericFilters[0], false, propertiesAnnotationsMap, queryParameters, processor)) + .append(" IN [ $").append(assertionValues.get(0)); + + for (int i = 1; i < assertionValues.size(); i++) { + Object assertionValue = assertionValues.get(i); + result.append(", $").append(assertionValue); + } + result.append(" ]"); + + return ConvertedExpression.build(result.toString(), queryParameters, requiredConsistency); } else { - Expression result = expFilters[0].expression(); + StringBuilder result = new StringBuilder("( ").append(expFilters[0].expression()); for (int i = 1; i < expFilters.length; i++) { - result = result.or(expFilters[i].expression()); + result = result.append(" OR ").append(expFilters[i].expression()); } + result.append(" )"); - return ConvertedExpression.build(Expression.par(result), requiredConsistency); + return ConvertedExpression.build(result.toString(), queryParameters, requiredConsistency); } } } } - if (FilterType.EQUALITY == type) { - boolean hasSubFilters = ArrayHelper.isNotEmpty(currentGenericFilter.getFilters()); - Boolean isMultiValuedDetected = determineMultiValuedByType(currentGenericFilter.getAttributeName(), propertiesAnnotationsMap); - - String internalAttribute = toInternalAttribute(currentGenericFilter); - Pair pairExpression = buildPath(currentGenericFilter, propertiesAnnotationsMap, processor); - if (Boolean.TRUE.equals(currentGenericFilter.getMultiValued()) || Boolean.TRUE.equals(isMultiValuedDetected)) { - return ConvertedExpression.build( - Collections.anyIn(internalAttribute + "_", pairExpression.getFirst()). - satisfies(pairExpression.getSecond().eq(buildTypedExpression(currentGenericFilter))), - requiredConsistency); - } else if (Boolean.FALSE.equals(currentGenericFilter.getMultiValued()) || Boolean.FALSE.equals(isMultiValuedDetected) || - (hasSubFilters && (isMultiValuedDetected == null))) { - return ConvertedExpression.build(pairExpression.getSecond().eq(buildTypedExpression(currentGenericFilter)), requiredConsistency); - } else { - Expression nameExpression = pairExpression.getSecond(); - Expression exp1 = Expression - .par(Expression.path(nameExpression).eq(buildTypedExpression(currentGenericFilter))); - Expression exp2 = Expression - .par(Expression.path(buildTypedExpression(currentGenericFilter)).in(nameExpression)); - return ConvertedExpression.build(Expression.par(exp1.or(exp2)), requiredConsistency); - } - } + // Generic part for rest of expression types + Boolean multiValuedWithUnknown = isMultiValue(currentGenericFilter, propertiesAnnotationsMap); + boolean multiValued = Boolean.TRUE.equals(multiValuedWithUnknown); - if (FilterType.LESS_OR_EQUAL == type) { - String internalAttribute = toInternalAttribute(currentGenericFilter); - Pair pairExpression = buildPath(currentGenericFilter, propertiesAnnotationsMap, processor); - if (isMultiValue(currentGenericFilter, propertiesAnnotationsMap)) { - return ConvertedExpression.build( - Collections.anyIn(internalAttribute + "_", pairExpression.getFirst()). - satisfies(pairExpression.getSecond().lte(buildTypedExpression(currentGenericFilter))), - requiredConsistency); - } else { - return ConvertedExpression.build(pairExpression.getSecond().lte(buildTypedExpression(currentGenericFilter)), requiredConsistency); - } - } + String internalAttribute = toInternalAttribute(currentGenericFilter); - if (FilterType.GREATER_OR_EQUAL == type) { - String internalAttribute = toInternalAttribute(currentGenericFilter); - Pair pairExpression = buildPath(currentGenericFilter, propertiesAnnotationsMap, processor); - if (isMultiValue(currentGenericFilter, propertiesAnnotationsMap)) { - return ConvertedExpression.build( - Collections.anyIn(internalAttribute + "_", pairExpression.getFirst()). - satisfies(pairExpression.getSecond().gte(buildTypedExpression(currentGenericFilter))), - requiredConsistency); - } else { - return ConvertedExpression.build(pairExpression.getSecond().gte(buildTypedExpression(currentGenericFilter)), requiredConsistency); + if ((FilterType.EQUALITY == type) || (FilterType.LESS_OR_EQUAL == type) || (FilterType.GREATER_OR_EQUAL == type)) { + String variableExpression = buildVariableExpression(internalAttribute, multiValued, currentGenericFilter.getAssertionValue(), queryParameters); + String leftExpressionPart = buildLeftExpressionPart(currentGenericFilter, multiValued, propertiesAnnotationsMap, queryParameters, processor); + + if (multiValued) { + // ANY mail_ IN mail SATISFIES mail_ = "test@gluu.org" END + String result = String.format("ANY %s_ IN %s SATISFIES %s %s $%s END", + internalAttribute, internalAttribute, leftExpressionPart, type.getSign(), variableExpression); + + return ConvertedExpression.build(result, queryParameters, variableExpression, requiredConsistency); } + + boolean hasSubFilters = ArrayHelper.isNotEmpty(genericFilter.getFilters()); + if (FilterType.EQUALITY == type) { + if ((Boolean.FALSE.equals(multiValuedWithUnknown)) || (hasSubFilters && (multiValuedWithUnknown == null))) { + String result = String.format("%s %s $%s", leftExpressionPart, type.getSign(), variableExpression); + return ConvertedExpression.build(result, queryParameters, variableExpression, requiredConsistency); + } else { + // uid == "test" OR "test" in uid + String result = String.format("( ( %s = $%s ) OR ( $%s IN %s ) )", + leftExpressionPart, variableExpression, variableExpression, internalAttribute); + + return ConvertedExpression.build(result, queryParameters, variableExpression, requiredConsistency); + } + } + + String result = String.format("%s %s $%s", leftExpressionPart, type.getSign(), variableExpression); + return ConvertedExpression.build(result, queryParameters, variableExpression, requiredConsistency); } if (FilterType.PRESENCE == type) { - String internalAttribute = toInternalAttribute(currentGenericFilter); - Pair pairExpression = buildPath(currentGenericFilter, propertiesAnnotationsMap, processor); - if (isMultiValue(currentGenericFilter, propertiesAnnotationsMap)) { - return ConvertedExpression.build( - Collections.anyIn(internalAttribute + "_", pairExpression.getFirst()). - satisfies(pairExpression.getSecond().isNotMissing()), - requiredConsistency); - } else { - return ConvertedExpression.build(pairExpression.getSecond().isNotMissing(), requiredConsistency); + String leftExpressionPart = buildLeftExpressionPart(currentGenericFilter, multiValued, propertiesAnnotationsMap, queryParameters, processor); + + if (multiValued) { + // ANY mail_ IN mail SATISFIES mail_ = "test@gluu.org" END + String result = String.format("ANY %s_ IN %s SATISFIES %s IS NOT MISSING END", + internalAttribute, internalAttribute, leftExpressionPart); + + return ConvertedExpression.build(result, queryParameters, requiredConsistency); } + + String result = String.format("%s IS NOT MISSING", leftExpressionPart); + return ConvertedExpression.build(result, queryParameters, requiredConsistency); } if (FilterType.APPROXIMATE_MATCH == type) { @@ -224,37 +232,53 @@ public ConvertedExpression convertToCouchbaseFilter(Filter genericFilter, Map filterParameters = new HashSet(); + + StringBuilder like = new StringBuilder(); if (currentGenericFilter.getSubInitial() != null) { - like.append(currentGenericFilter.getSubInitial()); + String variableExpressionInitial = buildVariableExpression(internalAttribute + "_i", multiValued, currentGenericFilter.getSubInitial(), queryParameters); + filterParameters.add(variableExpressionInitial); + like.append("$" + variableExpressionInitial); } like.append("%"); String[] subAny = currentGenericFilter.getSubAny(); if ((subAny != null) && (subAny.length > 0)) { for (String any : subAny) { - like.append(any); + String variableExpressionAny = buildVariableExpression(internalAttribute + "_any", multiValued, any, queryParameters); + filterParameters.add(variableExpressionAny); + like.append("$" + variableExpressionAny); like.append("%"); } } if (currentGenericFilter.getSubFinal() != null) { - like.append(currentGenericFilter.getSubFinal()); + String variableExpressionFinal = buildVariableExpression(internalAttribute + "_f", multiValued, currentGenericFilter.getSubFinal(), queryParameters); + filterParameters.add(variableExpressionFinal); + like.append("$" + variableExpressionFinal); } - String internalAttribute = toInternalAttribute(currentGenericFilter); - Pair pairExpression = buildPath(currentGenericFilter, propertiesAnnotationsMap, processor); - if (isMultiValue(currentGenericFilter, propertiesAnnotationsMap)) { - return ConvertedExpression.build( - Collections.anyIn(internalAttribute + "_", pairExpression.getFirst()). - satisfies(pairExpression.getSecond().like(Expression.s(escapeValue(like.toString())))), - requiredConsistency); - } else { - return ConvertedExpression.build(pairExpression.getSecond().like(Expression.s(escapeValue(like.toString()))), requiredConsistency); + + if (multiValued) { + // ANY mail_ IN mail SATISFIES mail_ LIKE "%test%" END + String result = String.format("ANY %s_ IN %s SATISFIES %s LIKE %s END", + internalAttribute, internalAttribute, leftExpressionPart, like.toString()); + + ConvertedExpression convertedExpression = ConvertedExpression.build(result, queryParameters, requiredConsistency); + convertedExpression.getSingleLevelParameters().addAll(filterParameters); + + return convertedExpression; } + + String result = String.format("%s LIKE %s", leftExpressionPart, like.toString()); + return ConvertedExpression.build(result, queryParameters, requiredConsistency); } if (FilterType.LOWERCASE == type) { - return ConvertedExpression.build(StringFunctions.lower(currentGenericFilter.getAttributeName()), requiredConsistency); + String leftExpressionPart = buildLeftExpressionPart(currentGenericFilter, multiValued, propertiesAnnotationsMap, queryParameters, processor); + + String result = String.format("LOWER( %s )", leftExpressionPart); + return ConvertedExpression.build(result, queryParameters, requiredConsistency); } throw new SearchException(String.format("Unknown filter type '%s'", type)); @@ -264,9 +288,11 @@ protected Boolean isMultiValue(Filter currentGenericFilter, Map buildPath(Filter genericFilter, Map propertiesAnnotationsMap, Function processor) throws SearchException { + private String buildLeftExpressionPart(Filter genericFilter, boolean multiValued, Map propertiesAnnotationsMap, JsonObject queryParameters, Function processor) throws SearchException { boolean hasSubFilters = ArrayHelper.isNotEmpty(genericFilter.getFilters()); - boolean isMultiValue = isMultiValue(genericFilter, propertiesAnnotationsMap); String internalAttribute = toInternalAttribute(genericFilter); - Expression expression = Expression.path(Expression.path(internalAttribute)); - Expression innerExpression = null; - if (isMultiValue) { - expression = Expression.path(Expression.path(internalAttribute)); - innerExpression = null; + String innerExpression = null; + if (multiValued) { if (hasSubFilters) { - Filter clonedFilter = genericFilter.getFilters()[0].clone(); - clonedFilter.setAttributeName(internalAttribute + "_"); + Filter subFilter = genericFilter.getFilters()[0].clone(); + subFilter.setAttributeName(internalAttribute + "_"); - innerExpression = convertToCouchbaseFilter(clonedFilter, propertiesAnnotationsMap, processor).expression(); + innerExpression = convertToCouchbaseFilter(subFilter, propertiesAnnotationsMap, queryParameters, processor).expression(); } else { - innerExpression = Expression.path(Expression.path(internalAttribute + "_")); + innerExpression = internalAttribute + "_"; } } else { if (hasSubFilters) { - innerExpression = convertToCouchbaseFilter(genericFilter.getFilters()[0], propertiesAnnotationsMap, processor).expression(); + Filter subFilter = genericFilter.getFilters()[0]; + innerExpression = convertToCouchbaseFilter(subFilter, propertiesAnnotationsMap, queryParameters, processor).expression(); } else { - innerExpression = Expression.path(Expression.path(internalAttribute)); + innerExpression = internalAttribute; } } - return new Pair<>(expression, innerExpression); + return innerExpression; } private Boolean determineMultiValuedByType(String attributeName, Map propertiesAnnotationsMap) { @@ -375,13 +418,15 @@ private boolean isRequiredConsistency(Filter filter, Map singleLevelParameters; - private ConvertedExpression(Expression expression) { + private ConvertedExpression(String expression, JsonObject queryParameters) { this.expression = expression; + this.queryParameters = queryParameters; + this.singleLevelParameters = new HashSet(); } - private ConvertedExpression(Expression expression, boolean consistency) { - this.expression = expression; + private ConvertedExpression(String expression, JsonObject queryParameters, boolean consistency) { + this(expression, queryParameters); this.consistency = consistency; } - public static ConvertedExpression build(Expression expression, boolean consistency) { - return new ConvertedExpression(expression, consistency); + public static ConvertedExpression build(String expression, JsonObject queryParameters, boolean consistency) { + return new ConvertedExpression(expression, queryParameters, consistency); + } + + public static ConvertedExpression build(String expression, JsonObject queryParameters, String queryParameter, boolean consistency) { + ConvertedExpression convertedExpression = new ConvertedExpression(expression, queryParameters, consistency); + convertedExpression.getSingleLevelParameters().add(queryParameter); + + return convertedExpression; } - public Expression expression() { + public String expression() { return expression; } + public JsonObject getQueryParameters() { + return queryParameters; + } + public boolean consistency() { return consistency; } @@ -43,9 +61,14 @@ public void consistency(boolean consistency) { this.consistency = consistency; } + public Set getSingleLevelParameters() { + return singleLevelParameters; + } + @Override public String toString() { - return "ConvertedExpression [expression=" + expression + ", consistency=" + consistency + "]"; + return "ConvertedExpression [expression=" + expression + ", queryParameters=" + queryParameters + + ", consistency=" + consistency + ", singleLevelParameters=" + singleLevelParameters + "]"; } } diff --git a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/model/CouchbaseConnectionConfiguration.java b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/model/CouchbaseConnectionConfiguration.java index f504d208d3f..cfc059f3a78 100644 --- a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/model/CouchbaseConnectionConfiguration.java +++ b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/model/CouchbaseConnectionConfiguration.java @@ -6,10 +6,10 @@ package io.jans.orm.couchbase.model; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + /** * @author Yuriy Zabrovarnyy */ @@ -19,18 +19,24 @@ public class CouchbaseConnectionConfiguration { private String configId; private String userName; private String userPassword; + private List servers; private String defaultBucket; private List buckets; + private String passwordEncryptionMethod; - private Boolean operationTracingEnabled; - private Boolean mutationTokensEnabled; + private int connectTimeout; - private int computationPoolSize; + + private Boolean mutationTokensEnabled; + private int kvTimeout; + private int queryTimeout; + private Boolean useSSL; private String sslTrustStoreFile; private String sslTrustStorePin; - private String sslTrustStoreFormat; + private String sslTrustStoreType; + private List binaryAttributes; private List certificateAttributes; @@ -90,14 +96,6 @@ public void setPasswordEncryptionMethod(String passwordEncryptionMethod) { this.passwordEncryptionMethod = passwordEncryptionMethod; } - public Boolean getOperationTracingEnabled() { - return operationTracingEnabled; - } - - public void setOperationTracingEnabled(Boolean operationTracingEnabled) { - this.operationTracingEnabled = operationTracingEnabled; - } - public Boolean getMutationTokensEnabled() { return mutationTokensEnabled; } @@ -114,15 +112,23 @@ public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } - public int getComputationPoolSize() { - return computationPoolSize; - } + public int getKvTimeout() { + return kvTimeout; + } - public void setComputationPoolSize(int computationPoolSize) { - this.computationPoolSize = computationPoolSize; - } + public void setKvTimeout(int kvTimeout) { + this.kvTimeout = kvTimeout; + } - public Boolean getUseSSL() { + public int getQueryTimeout() { + return queryTimeout; + } + + public void setQueryTimeout(int queryTimeout) { + this.queryTimeout = queryTimeout; + } + + public Boolean getUseSSL() { return useSSL; } @@ -146,15 +152,15 @@ public void setSslTrustStorePin(String sslTrustStorePin) { this.sslTrustStorePin = sslTrustStorePin; } - public String getSslTrustStoreFormat() { - return sslTrustStoreFormat; - } + public String getSslTrustStoreType() { + return sslTrustStoreType; + } - public void setSslTrustStoreFormat(String sslTrustStoreFormat) { - this.sslTrustStoreFormat = sslTrustStoreFormat; - } + public void setSslTrustStoreType(String sslTrustStoreType) { + this.sslTrustStoreType = sslTrustStoreType; + } - public List getBinaryAttributes() { + public List getBinaryAttributes() { return binaryAttributes; } diff --git a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/CouchbaseOperationService.java b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/CouchbaseOperationService.java index 01c2ecfb9b2..cf75a539260 100644 --- a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/CouchbaseOperationService.java +++ b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/CouchbaseOperationService.java @@ -6,12 +6,9 @@ package io.jans.orm.couchbase.operation; +import java.util.Date; import java.util.List; -import io.jans.orm.operation.PersistenceOperationService; -import io.jans.orm.couchbase.impl.CouchbaseBatchOperationWraper; -import io.jans.orm.couchbase.model.SearchReturnDataType; -import io.jans.orm.couchbase.operation.impl.CouchbaseConnectionProvider; import io.jans.orm.exception.operation.DeleteException; import io.jans.orm.exception.operation.DuplicateEntryException; import io.jans.orm.exception.operation.EntryNotFoundException; @@ -19,12 +16,17 @@ import io.jans.orm.exception.operation.SearchException; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; +import io.jans.orm.model.Sort; +import io.jans.orm.operation.PersistenceOperationService; + +import com.couchbase.client.java.json.JsonObject; +import com.couchbase.client.java.kv.MutateInSpec; +import com.couchbase.client.java.query.QueryScanConsistency; -import com.couchbase.client.java.document.json.JsonObject; -import com.couchbase.client.java.query.consistency.ScanConsistency; -import com.couchbase.client.java.query.dsl.Expression; -import com.couchbase.client.java.query.dsl.Sort; -import com.couchbase.client.java.subdoc.MutationSpec; +import io.jans.orm.couchbase.impl.CouchbaseBatchOperationWraper; +import io.jans.orm.couchbase.model.ConvertedExpression; +import io.jans.orm.couchbase.model.SearchReturnDataType; +import io.jans.orm.couchbase.operation.impl.CouchbaseConnectionProvider; /** * Couchbase operation service interface @@ -46,15 +48,15 @@ public interface CouchbaseOperationService extends PersistenceOperationService { boolean addEntry(String key, JsonObject atts) throws DuplicateEntryException, PersistenceException; boolean addEntry(String key, JsonObject jsonObject, Integer expiration) throws DuplicateEntryException, PersistenceException; - boolean updateEntry(String key, List mods, Integer expiration) throws UnsupportedOperationException, PersistenceException; + boolean updateEntry(String key, List mods, Integer expiration) throws UnsupportedOperationException, PersistenceException; boolean delete(String key) throws EntryNotFoundException; - int delete(String key, ScanConsistency scanConsistency, Expression expression, int count) throws DeleteException; - boolean deleteRecursively(String key) throws EntryNotFoundException, SearchException; + int delete(String key, QueryScanConsistency scanConsistency, ConvertedExpression expression, int count) throws DeleteException; + boolean deleteRecursively(String key) throws EntryNotFoundException, DeleteException; - JsonObject lookup(String key, ScanConsistency scanConsistency, String... attributes) throws SearchException; + JsonObject lookup(String key, String... attributes) throws SearchException; - PagedResult search(String key, ScanConsistency scanConsistency, Expression expression, SearchScope scope, + PagedResult search(String key, QueryScanConsistency scanConsistency, ConvertedExpression expression, SearchScope scope, String[] attributes, Sort[] orderBy, CouchbaseBatchOperationWraper batchOperationWraper, SearchReturnDataType returnDataType, int start, int count, int pageSize) throws SearchException; @@ -63,6 +65,15 @@ PagedResult search(String key, ScanConsistency scanConsistency, boolean isBinaryAttribute(String attribute); boolean isCertificateAttribute(String attribute); + String toInternalAttribute(String attributeName); + String[] toInternalAttributes(String[] attributeNames); + + String fromInternalAttribute(String internalAttributeName); + String[] fromInternalAttributes(String[] internalAttributeNames); + boolean destroy(); + String encodeTime(Date date); + Date decodeTime(String date, boolean silent); + } diff --git a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/impl/CouchbaseConnectionProvider.java b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/impl/CouchbaseConnectionProvider.java index 94fa4629175..0b32384bf3c 100644 --- a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/impl/CouchbaseConnectionProvider.java +++ b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/impl/CouchbaseConnectionProvider.java @@ -9,32 +9,36 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; import java.util.Properties; -import java.util.concurrent.TimeUnit; -import io.jans.orm.couchbase.model.BucketMapping; -import io.jans.orm.couchbase.model.ResultCode; +import io.jans.orm.util.ArrayHelper; +import io.jans.orm.util.StringHelper; import io.jans.orm.exception.KeyConversionException; import io.jans.orm.exception.operation.ConfigurationException; import io.jans.orm.operation.auth.PasswordEncryptionMethod; -import io.jans.orm.util.ArrayHelper; -import io.jans.orm.util.StringHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.couchbase.client.core.CouchbaseException; -import com.couchbase.client.core.message.internal.PingReport; -import com.couchbase.client.core.message.internal.PingServiceHealth; -import com.couchbase.client.core.message.internal.PingServiceHealth.PingState; +import com.couchbase.client.core.diagnostics.EndpointPingReport; +import com.couchbase.client.core.diagnostics.PingResult; +import com.couchbase.client.core.diagnostics.PingState; +import com.couchbase.client.core.error.CouchbaseException; +import com.couchbase.client.core.service.ServiceType; import com.couchbase.client.java.Bucket; -import com.couchbase.client.java.CouchbaseCluster; -import com.couchbase.client.java.bucket.BucketInfo; -import com.couchbase.client.java.bucket.BucketManager; -import com.couchbase.client.java.env.CouchbaseEnvironment; -import com.couchbase.client.java.query.N1qlQueryResult; -import com.couchbase.client.java.query.Select; -import com.couchbase.client.java.query.Statement; -import com.couchbase.client.java.query.dsl.Expression; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.ClusterOptions; +import com.couchbase.client.java.env.ClusterEnvironment; +import com.couchbase.client.java.json.JsonArray; +import com.couchbase.client.java.manager.bucket.BucketManager; +import com.couchbase.client.java.manager.bucket.BucketSettings; +import com.couchbase.client.java.query.QueryOptions; +import com.couchbase.client.java.query.QueryResult; +import com.couchbase.client.java.query.QueryStatus; + +import io.jans.orm.couchbase.model.BucketMapping; +import io.jans.orm.couchbase.model.ResultCode; /** * Perform cluster initialization and open required buckets @@ -47,15 +51,15 @@ public class CouchbaseConnectionProvider { private Properties props; - private String[] servers; + private String connectionString; private String[] buckets; private String defaultBucket; private String userName; private String userPassword; - private CouchbaseEnvironment couchbaseEnvironment; - private CouchbaseCluster cluster; + private ClusterEnvironment clusterEnvironment; + private Cluster cluster; private int creationResultCode; private HashMap bucketToBaseNameMapping; @@ -69,9 +73,9 @@ public class CouchbaseConnectionProvider { protected CouchbaseConnectionProvider() { } - public CouchbaseConnectionProvider(Properties props, CouchbaseEnvironment couchbaseEnvironment) { + public CouchbaseConnectionProvider(Properties props, ClusterEnvironment clusterEnvironment) { this.props = props; - this.couchbaseEnvironment = couchbaseEnvironment; + this.clusterEnvironment = clusterEnvironment; } public void create() { @@ -91,7 +95,7 @@ public void create() { } protected void init() { - this.servers = StringHelper.split(props.getProperty("servers"), ","); + this.connectionString = props.getProperty("servers"); this.userName = props.getProperty("auth.userName"); this.userPassword = props.getProperty("auth.userPassword"); @@ -182,15 +186,19 @@ private void open() { this.bucketToBaseNameMapping = new HashMap(); this.baseNameToBucketMapping = new HashMap(); - this.cluster = CouchbaseCluster.create(couchbaseEnvironment, servers); - cluster.authenticate(userName, userPassword); + ClusterOptions clusterOptions = ClusterOptions.clusterOptions(userName, userPassword); + if (clusterEnvironment != null) { + clusterOptions.environment(clusterEnvironment); + } + + this.cluster = Cluster.connect(connectionString, clusterOptions); // Open required buckets for (String bucketName : buckets) { String baseNamesProp = props.getProperty(String.format("bucket.%s.mapping", bucketName), ""); String[] baseNames = StringHelper.split(baseNamesProp, ","); - Bucket bucket = cluster.openBucket(bucketName); + Bucket bucket = this.cluster.bucket(bucketName); BucketMapping bucketMapping = new BucketMapping(bucketName, bucket); @@ -207,23 +215,11 @@ private void open() { } public boolean destroy() { - boolean result = true; - if (bucketToBaseNameMapping != null) { - for (BucketMapping bucketMapping : bucketToBaseNameMapping.values()) { - try { - bucketMapping.getBucket().close(); - } catch (CouchbaseException ex) { - LOG.error("Failed to close bucket '{}'", bucketMapping.getBucketName(), ex); - result = false; - } - } - } - - if (cluster != null) { - result &= cluster.disconnect(); + if (this.cluster != null) { + this.cluster.disconnect(); } - return result; + return true; } public boolean isConnected() { @@ -234,12 +230,7 @@ public boolean isConnected() { boolean isConnected = true; try { for (BucketMapping bucketMapping : bucketToBaseNameMapping.values()) { - Bucket bucket = bucketMapping.getBucket(); - if (bucket.isClosed() || !isConnected(bucketMapping)) { - if (bucket.isClosed()) { - LOG.debug("Bucket '{}' is closed", bucketMapping.getBucketName()); - } - + if (!isConnected(bucketMapping)) { LOG.error("Bucket '{}' is in invalid state", bucketMapping.getBucketName()); isConnected = false; break; @@ -256,22 +247,21 @@ public boolean isConnected() { private boolean isConnected(BucketMapping bucketMapping) { Bucket bucket = bucketMapping.getBucket(); - BucketManager bucketManager = bucket.bucketManager(); - BucketInfo bucketInfo = bucketManager.info(30, TimeUnit.SECONDS); + BucketManager bucketManager = this.cluster.buckets(); + BucketSettings bucketSettings = bucketManager.getBucket(bucket.name()); boolean result = true; - if (com.couchbase.client.java.bucket.BucketType.COUCHBASE == bucketInfo.type()) { + if (com.couchbase.client.java.manager.bucket.BucketType.COUCHBASE == bucketSettings.bucketType()) { // Check indexes state - Statement query = Select.select("state").from("system:indexes").where(Expression.path("state").eq(Expression.s("online")).not()); - N1qlQueryResult queryResult = bucket.query(query); - result = queryResult.finalSuccess(); + QueryResult queryResult = cluster.query("SELECT state FROM system:indexes WHERE state != $1 AND keyspace_id = $2", QueryOptions.queryOptions().parameters(JsonArray.from("online", bucket.name()))); - if (result) { - result = queryResult.info().resultCount() == 0; + if (QueryStatus.SUCCESS == queryResult.metaData().status()) { + result = queryResult.rowsAsObject().size() == 0; if (LOG.isDebugEnabled()) { LOG.debug("There are indexes which not online"); } } else { + result = false; if (LOG.isDebugEnabled()) { LOG.debug("Faield to check indexes status"); } @@ -279,12 +269,14 @@ private boolean isConnected(BucketMapping bucketMapping) { } if (result) { - PingReport pingReport = bucket.ping(); - for (PingServiceHealth pingServiceHealth : pingReport.services()) { - if (PingState.OK != pingServiceHealth.state()) { - LOG.debug("Ping returns that service typ {} is not online", pingServiceHealth.type()); - result = false; - break; + PingResult pingResult = bucket.ping(); + for (Entry> pingResultEntry : pingResult.endpoints().entrySet()) { + for (EndpointPingReport endpointPingReport : pingResultEntry.getValue()) { + if (PingState.OK != endpointPingReport.state()) { + LOG.debug("Ping returns that service type {} is not online", endpointPingReport.type()); + result = false; + break; + } } } } @@ -292,6 +284,10 @@ private boolean isConnected(BucketMapping bucketMapping) { return result; } + public Cluster getCluster() { + return cluster; + } + public BucketMapping getBucketMapping(String baseName) { BucketMapping bucketMapping = baseNameToBucketMapping.get(baseName); if (bucketMapping == null) { @@ -327,8 +323,8 @@ public boolean isCreated() { return ResultCode.SUCCESS_INT_VALUE == creationResultCode; } - public String[] getServers() { - return servers; + public String getServers() { + return connectionString; } public ArrayList getBinaryAttributes() { diff --git a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/impl/CouchbaseOperationServiceImpl.java b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/impl/CouchbaseOperationServiceImpl.java index 1b597fd84db..9ca6b1d5a97 100644 --- a/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/impl/CouchbaseOperationServiceImpl.java +++ b/jans-orm/couchbase/src/main/java/io/jans/orm/couchbase/operation/impl/CouchbaseOperationServiceImpl.java @@ -6,10 +6,15 @@ package io.jans.orm.couchbase.operation.impl; +import static java.time.format.DateTimeFormatter.ISO_INSTANT; + +import java.time.DateTimeException; import java.time.Duration; import java.time.Instant; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -17,53 +22,47 @@ import java.util.Properties; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.couchbase.client.core.CouchbaseException; -import com.couchbase.client.core.message.kv.subdoc.multi.Mutation; -import com.couchbase.client.java.Bucket; -import com.couchbase.client.java.document.JsonDocument; -import com.couchbase.client.java.document.json.JsonArray; -import com.couchbase.client.java.document.json.JsonObject; -import com.couchbase.client.java.query.Delete; -import com.couchbase.client.java.query.N1qlParams; -import com.couchbase.client.java.query.N1qlQuery; -import com.couchbase.client.java.query.N1qlQueryResult; -import com.couchbase.client.java.query.N1qlQueryRow; -import com.couchbase.client.java.query.Select; -import com.couchbase.client.java.query.Statement; -import com.couchbase.client.java.query.consistency.ScanConsistency; -import com.couchbase.client.java.query.dsl.Expression; -import com.couchbase.client.java.query.dsl.Sort; -import com.couchbase.client.java.query.dsl.path.GroupByPath; -import com.couchbase.client.java.query.dsl.path.LimitPath; -import com.couchbase.client.java.query.dsl.path.MutateLimitPath; -import com.couchbase.client.java.query.dsl.path.OffsetPath; -import com.couchbase.client.java.query.dsl.path.ReturningPath; -import com.couchbase.client.java.subdoc.DocumentFragment; -import com.couchbase.client.java.subdoc.MutateInBuilder; -import com.couchbase.client.java.subdoc.MutationSpec; - -import io.jans.orm.couchbase.impl.CouchbaseBatchOperationWraper; -import io.jans.orm.couchbase.model.BucketMapping; -import io.jans.orm.couchbase.model.SearchReturnDataType; -import io.jans.orm.couchbase.operation.CouchbaseOperationService; -import io.jans.orm.couchbase.operation.watch.OperationDurationUtil; +import io.jans.orm.util.ArrayHelper; +import io.jans.orm.util.StringHelper; import io.jans.orm.exception.AuthenticationException; -import io.jans.orm.exception.extension.PersistenceExtension; import io.jans.orm.exception.operation.ConnectionException; import io.jans.orm.exception.operation.DeleteException; import io.jans.orm.exception.operation.DuplicateEntryException; import io.jans.orm.exception.operation.EntryNotFoundException; import io.jans.orm.exception.operation.PersistenceException; import io.jans.orm.exception.operation.SearchException; +import io.jans.orm.extension.PersistenceExtension; import io.jans.orm.model.BatchOperation; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; +import io.jans.orm.model.Sort; +import io.jans.orm.model.SortOrder; import io.jans.orm.operation.auth.PasswordEncryptionHelper; -import io.jans.orm.util.ArrayHelper; -import io.jans.orm.util.StringHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.couchbase.client.core.error.CouchbaseException; +import com.couchbase.client.core.msg.ResponseStatus; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.json.JsonArray; +import com.couchbase.client.java.json.JsonObject; +import com.couchbase.client.java.kv.GetOptions; +import com.couchbase.client.java.kv.MutateInOptions; +import com.couchbase.client.java.kv.MutateInResult; +import com.couchbase.client.java.kv.MutateInSpec; +import com.couchbase.client.java.kv.MutationResult; +import com.couchbase.client.java.kv.UpsertOptions; +import com.couchbase.client.java.query.QueryOptions; +import com.couchbase.client.java.query.QueryResult; +import com.couchbase.client.java.query.QueryScanConsistency; +import com.couchbase.client.java.query.QueryStatus; + +import io.jans.orm.couchbase.impl.CouchbaseBatchOperationWraper; +import io.jans.orm.couchbase.model.BucketMapping; +import io.jans.orm.couchbase.model.ConvertedExpression; +import io.jans.orm.couchbase.model.SearchReturnDataType; +import io.jans.orm.couchbase.operation.CouchbaseOperationService; +import io.jans.orm.couchbase.operation.watch.OperationDurationUtil; /** * Base service which performs all supported Couchbase operations @@ -77,18 +76,16 @@ public class CouchbaseOperationServiceImpl implements CouchbaseOperationService private Properties props; private CouchbaseConnectionProvider connectionProvider; - private ScanConsistency scanConsistency = ScanConsistency.NOT_BOUNDED; + private QueryScanConsistency queryScanConsistency = QueryScanConsistency.NOT_BOUNDED; - private boolean ignoreAttributeScanConsistency = false; - private boolean attemptWithoutAttributeScanConsistency = true; + private boolean ignoreAttributeQueryScanConsistency = false; + private boolean attemptWithoutAttributeQueryScanConsistency = true; private boolean enableScopeSupport = false; private boolean disableAttributeMapping = false; private PersistenceExtension persistenceExtension; - - @SuppressWarnings("unused") - private CouchbaseOperationServiceImpl() { + public CouchbaseOperationServiceImpl() { } public CouchbaseOperationServiceImpl(Properties props, CouchbaseConnectionProvider connectionProvider) { @@ -99,16 +96,16 @@ public CouchbaseOperationServiceImpl(Properties props, CouchbaseConnectionProvid private void init() { if (props.containsKey("connection.scan-consistency")) { - String scanConsistencyString = StringHelper.toUpperCase(props.get("connection.scan-consistency").toString()); - this.scanConsistency = ScanConsistency.valueOf(scanConsistencyString); + String queryScanConsistencyString = StringHelper.toUpperCase(props.get("connection.scan-consistency").toString()); + this.queryScanConsistency = QueryScanConsistency.valueOf(queryScanConsistencyString); } if (props.containsKey("connection.ignore-attribute-scan-consistency")) { - this.ignoreAttributeScanConsistency = StringHelper.toBoolean(props.get("connection.ignore-attribute-scan-consistency").toString(), this.ignoreAttributeScanConsistency); + this.ignoreAttributeQueryScanConsistency = StringHelper.toBoolean(props.get("connection.ignore-attribute-scan-consistency").toString(), this.ignoreAttributeQueryScanConsistency); } if (props.containsKey("connection.attempt-without-attribute-scan-consistency")) { - this.attemptWithoutAttributeScanConsistency = StringHelper.toBoolean(props.get("attempt-without-attribute-scan-consistency").toString(), this.attemptWithoutAttributeScanConsistency); + this.attemptWithoutAttributeQueryScanConsistency = StringHelper.toBoolean(props.get("attempt-without-attribute-scan-consistency").toString(), this.attemptWithoutAttributeQueryScanConsistency); } if (props.containsKey("connection.enable-scope-support")) { @@ -119,8 +116,8 @@ private void init() { this.disableAttributeMapping = StringHelper.toBoolean(props.get("connection.disable-attribute-mapping").toString(), this.disableAttributeMapping); } - LOG.info("Option scanConsistency: " + scanConsistency); - LOG.info("Option ignoreAttributeScanConsistency: " + ignoreAttributeScanConsistency); + LOG.info("Option queryScanConsistency: " + queryScanConsistency); + LOG.info("Option ignoreAttributeQueryScanConsistency: " + ignoreAttributeQueryScanConsistency); LOG.info("Option enableScopeSupport: " + enableScopeSupport); LOG.info("Option disableAttributeMapping: " + disableAttributeMapping); } @@ -140,7 +137,7 @@ private boolean authenticateImpl(final String key, final String password) throws boolean result = false; if (password != null) { - JsonObject entry = lookup(key, null, USER_PASSWORD); + JsonObject entry = lookup(key, USER_PASSWORD); Object userPasswordObj = entry.get(USER_PASSWORD); String userPassword = null; @@ -187,20 +184,18 @@ public boolean addEntry(String key, JsonObject jsonObject, Integer expiration) t private boolean addEntryImpl(BucketMapping bucketMapping, String key, JsonObject jsonObject, Integer expiration) throws PersistenceException { try { - JsonDocument jsonDocument; - if (expiration == null) { - jsonDocument = JsonDocument.create(key, jsonObject); - } else { - jsonDocument = JsonDocument.create(key, expiration, jsonObject); + UpsertOptions upsertOptions = UpsertOptions.upsertOptions(); + if (expiration != null) { + upsertOptions = upsertOptions.expiry(Duration.ofSeconds(expiration)); } - JsonDocument result = bucketMapping.getBucket().upsert(jsonDocument); + MutationResult result = bucketMapping.getBucket().defaultCollection().upsert(key, jsonObject, upsertOptions); if (result != null) { return true; } } catch (CouchbaseException ex) { - throw new PersistenceException("Failed to add entry", ex); + throw new PersistenceException(String.format("Failed to add entry with key '%s'", key), ex); } return false; @@ -208,7 +203,7 @@ private boolean addEntryImpl(BucketMapping bucketMapping, String key, JsonObject @Deprecated protected boolean updateEntry(String key, JsonObject attrs) throws UnsupportedOperationException, PersistenceException { - List mods = new ArrayList(); + List mods = new ArrayList(); for (Entry attrEntry : attrs.toMap().entrySet()) { String attributeName = attrEntry.getKey(); @@ -218,7 +213,7 @@ protected boolean updateEntry(String key, JsonObject attrs) throws UnsupportedOp continue; } else { if (attributeValue != null) { - mods.add(new MutationSpec(Mutation.REPLACE, attributeName, attributeValue)); + mods.add(MutateInSpec.replace(attributeName, attributeValue)); } } } @@ -227,7 +222,7 @@ protected boolean updateEntry(String key, JsonObject attrs) throws UnsupportedOp } @Override - public boolean updateEntry(String key, List mods, Integer expiration) throws UnsupportedOperationException, PersistenceException { + public boolean updateEntry(String key, List mods, Integer expiration) throws PersistenceException { Instant startTime = OperationDurationUtil.instance().now(); BucketMapping bucketMapping = connectionProvider.getBucketMappingByKey(key); @@ -239,44 +234,20 @@ public boolean updateEntry(String key, List mods, Integer expirati return result; } - private boolean updateEntryImpl(BucketMapping bucketMapping, String key, List mods, Integer expiration) throws PersistenceException { + private boolean updateEntryImpl(BucketMapping bucketMapping, String key, List mods, Integer expiration) throws PersistenceException { try { - MutateInBuilder builder = bucketMapping.getBucket().mutateIn(key); + MutateInOptions options = MutateInOptions.mutateInOptions(); if (expiration != null) { - builder = builder.withExpiry(expiration); - } - - return modifyEntry(builder, mods); - } catch (final CouchbaseException ex) { - throw new PersistenceException("Failed to update entry", ex); - } - } - - protected boolean modifyEntry(MutateInBuilder builder, List mods) throws UnsupportedOperationException, PersistenceException { - try { - for (MutationSpec mod : mods) { - Mutation type = mod.type(); - if (Mutation.DICT_ADD == type) { - builder.insert(mod.path(), mod.fragment()); - } else if (Mutation.REPLACE == type) { - builder.replace(mod.path(), mod.fragment()); - } else if (Mutation.DELETE == type) { - builder.remove(mod.path()); - } else { - throw new UnsupportedOperationException("Operation type '" + type + "' is not implemented"); - } - } + options.expiry(Duration.ofSeconds(expiration)); + } - DocumentFragment result = builder.execute(); - if (result.size() > 0) { - return result.status(0).isSuccess(); - } + MutateInResult result = bucketMapping.getBucket().defaultCollection().mutateIn(key, mods, options); - return false; + return result != null; } catch (final CouchbaseException ex) { throw new PersistenceException("Failed to update entry", ex); } - } + } @Override public boolean delete(String key) throws EntryNotFoundException { @@ -293,55 +264,51 @@ public boolean delete(String key) throws EntryNotFoundException { private boolean deleteImpl(BucketMapping bucketMapping, String key) throws EntryNotFoundException { try { - JsonDocument result = bucketMapping.getBucket().remove(key); + MutationResult result = bucketMapping.getBucket().defaultCollection().remove(key); - return (result != null) && (result.id() != null); + return result != null; } catch (CouchbaseException ex) { - throw new EntryNotFoundException("Failed to delete entry", ex); + throw new EntryNotFoundException(String.format("Failed to delete entry by key '%s'", key), ex); } } @Override - public int delete(String key, ScanConsistency scanConsistency, Expression expression, int count) throws DeleteException { + public int delete(String key, QueryScanConsistency queryScanConsistency, ConvertedExpression expression, int count) throws DeleteException { Instant startTime = OperationDurationUtil.instance().now(); BucketMapping bucketMapping = connectionProvider.getBucketMappingByKey(key); - ScanConsistency useScanConsistency = getScanConsistency(scanConsistency, false); + QueryScanConsistency useQueryScanConsistency = getQueryScanConsistency(queryScanConsistency, false); - int result = deleteImpl(bucketMapping, key, useScanConsistency, expression, count); + int result = deleteImpl(bucketMapping, key, useQueryScanConsistency, expression, count); - String attemptInfo = getScanAttemptLogInfo(scanConsistency, useScanConsistency, false); + String attemptInfo = getScanAttemptLogInfo(queryScanConsistency, useQueryScanConsistency, false); Duration duration = OperationDurationUtil.instance().duration(startTime); - OperationDurationUtil.instance().logDebug("Couchbase operation: delete_search, duration: {}, bucket: {}, key: {}, expression: {}, count: {}, consistency: {}{}", duration, bucketMapping.getBucketName(), key, expression, count, useScanConsistency, attemptInfo); + OperationDurationUtil.instance().logDebug("Couchbase operation: delete_search, duration: {}, bucket: {}, key: {}, expression: {}, count: {}, consistency: {}{}", duration, bucketMapping.getBucketName(), key, expression, count, useQueryScanConsistency, attemptInfo); return result; } - private int deleteImpl(BucketMapping bucketMapping, String key, ScanConsistency scanConsistency, Expression expression, int count) throws DeleteException { - Bucket bucket = bucketMapping.getBucket(); - - Expression finalExpression = expression; + private int deleteImpl(BucketMapping bucketMapping, String key, QueryScanConsistency queryScanConsistency, ConvertedExpression expression, int count) throws DeleteException { + StringBuilder query = new StringBuilder("DELETE FROM `").append(bucketMapping.getBucketName()).append("` WHERE ").append(expression.expression()); if (enableScopeSupport) { - Expression scopeExpression = Expression.path("META().id").like(Expression.s(key + "%")); - finalExpression = scopeExpression.and(expression); + query.append("AND META().id LIKE ").append(key).append("%"); } - MutateLimitPath deleteQuery = Delete.deleteFrom(Expression.i(bucketMapping.getBucketName())).where(finalExpression); - ReturningPath query = deleteQuery.limit(count); + query.append(" LIMIT ").append(count).append(" RETURNING default.*"); LOG.debug("Execution query: '" + query + "'"); - N1qlQueryResult result = bucket.query(N1qlQuery.simple(query, N1qlParams.build().consistency(scanConsistency))); - if (!result.finalSuccess()) { - throw new DeleteException(String.format("Failed to delete entries. Query: '%s'. Error: '%s', Error count: '%d'", query, result.errors(), - result.info().errorCount()), result.errors().get(0).getInt("code")); + QueryOptions queryOptions = QueryOptions.queryOptions().scanConsistency(queryScanConsistency).parameters(expression.getQueryParameters()); + QueryResult result = connectionProvider.getCluster().query(query.toString(), queryOptions); + if (QueryStatus.SUCCESS != result.metaData().status()) { + throw new DeleteException(String.format("Failed to delete entries. Query: '%s'. Warnings: '%s'", query, result.metaData().warnings())); } - return result.info().mutationCount(); + return result.rowsAsObject().size(); } @Override - public boolean deleteRecursively(String key) throws EntryNotFoundException, SearchException { + public boolean deleteRecursively(String key) throws EntryNotFoundException, DeleteException { Instant startTime = OperationDurationUtil.instance().now(); BucketMapping bucketMapping = connectionProvider.getBucketMappingByKey(key); @@ -353,17 +320,21 @@ public boolean deleteRecursively(String key) throws EntryNotFoundException, Sear return result; } - private boolean deleteRecursivelyImpl(BucketMapping bucketMapping, String key) throws SearchException, EntryNotFoundException { + private boolean deleteRecursivelyImpl(BucketMapping bucketMapping, String key) throws EntryNotFoundException, DeleteException { try { if (enableScopeSupport) { - MutateLimitPath deleteQuery = Delete.deleteFrom(Expression.i(bucketMapping.getBucketName())) - .where(Expression.path("META().id").like(Expression.s(key + "%"))); + StringBuilder query = new StringBuilder("DELETE FROM `").append(bucketMapping.getBucketName()).append("` WHERE "). + append("META().id LIKE $1%"); - N1qlQueryResult result = bucketMapping.getBucket().query(deleteQuery); - if (!result.finalSuccess()) { - throw new SearchException(String.format("Failed to delete entries. Query: '%s'. Error: '%s', Error count: '%d'", deleteQuery, result.errors(), - result.info().errorCount()), result.errors().get(0).getInt("code")); + LOG.debug("Execution query: '" + query + "'"); + + QueryOptions queryOptions = QueryOptions.queryOptions().scanConsistency(queryScanConsistency).parameters(JsonArray.from(key)); + QueryResult result = connectionProvider.getCluster().query(query.toString(), queryOptions); + if (QueryStatus.SUCCESS != result.metaData().status()) { + throw new DeleteException(String.format("Failed to delete entries. Query: '%s'. Warnings: '%s'", query, result.metaData().warnings())); } + + return true; } else { LOG.warn("Removing only base key without sub-tree: " + key); delete(key); @@ -371,108 +342,85 @@ private boolean deleteRecursivelyImpl(BucketMapping bucketMapping, String key) t return true; } catch (CouchbaseException ex) { - throw new EntryNotFoundException("Failed to delete entry", ex); + throw new DeleteException("Failed to delete entry", ex); } } @Override - public JsonObject lookup(String key, ScanConsistency scanConsistency, String... attributes) throws SearchException { + public JsonObject lookup(String key, String... attributes) throws SearchException { Instant startTime = OperationDurationUtil.instance().now(); BucketMapping bucketMapping = connectionProvider.getBucketMappingByKey(key); - - boolean secondTry = false; - ScanConsistency useScanConsistency = getScanConsistency(scanConsistency, attemptWithoutAttributeScanConsistency); - JsonObject result = null; - SearchException lastException = null; - try { - result = lookupImpl(bucketMapping, key, useScanConsistency, attributes); - } catch (SearchException ex) { - lastException = ex; - } - if ((result == null) || result.isEmpty()) { - ScanConsistency useScanConsistency2 = getScanConsistency(scanConsistency, false); - if (!useScanConsistency2.equals(useScanConsistency)) { - useScanConsistency = useScanConsistency2; - secondTry = true; - result = lookupImpl(bucketMapping, key, useScanConsistency, attributes); - } else { - if (lastException != null) { - throw lastException; - } - } - } - - String attemptInfo = getScanAttemptLogInfo(scanConsistency, useScanConsistency, secondTry); + JsonObject result = lookupImpl(bucketMapping, key, attributes); Duration duration = OperationDurationUtil.instance().duration(startTime); - OperationDurationUtil.instance().logDebug("Couchbase operation: lookup, duration: {}, bucket: {}, key: {}, attributes: {}, consistency: {}{}", duration, bucketMapping.getBucketName(), key, attributes, useScanConsistency, attemptInfo); + OperationDurationUtil.instance().logDebug("Couchbase operation: lookup, duration: {}, bucket: {}, key: {}, attributes: {}", duration, bucketMapping.getBucketName(), key, attributes); return result; } - private JsonObject lookupImpl(BucketMapping bucketMapping, String key, ScanConsistency scanConsistency, String... attributes) throws SearchException { + private JsonObject lookupImpl(BucketMapping bucketMapping, String key, String... attributes) throws SearchException { try { Bucket bucket = bucketMapping.getBucket(); if (ArrayHelper.isEmpty(attributes)) { - JsonDocument doc = bucket.get(key); + JsonObject doc = bucket.defaultCollection().get(key).contentAsObject(); if (doc != null) { - return doc.content(); + return doc; } - } else { - JsonDocument doc = bucket.get(key); - if (doc != null) { - Set docAtributesKeep = new HashSet(Arrays.asList(attributes)); + // Server allows to request only max 16 fields + if (attributes.length > 16) { + JsonObject doc = bucket.defaultCollection().get(key).contentAsObject(); + + Set docAtributesKeep = new HashSet(Arrays.asList(attributes)); // docAtributesKeep.add(CouchbaseOperationService.DN); - for (Iterator it = doc.content().getNames().iterator(); it.hasNext();) { + for (Iterator it = doc.getNames().iterator(); it.hasNext();) { String docAtribute = (String) it.next(); if (!docAtributesKeep.contains(docAtribute)) { it.remove(); } } - return doc.content(); - } - -// N1qlParams params = N1qlParams.build().consistency(scanConsistency); -// OffsetPath select = Select.select(attributes).from(Expression.i(bucketMapping.getBucketName())).useKeys(Expression.s(key)).limit(1); -// N1qlQueryResult result = bucket.query(N1qlQuery.simple(select, params)); -// if (!result.finalSuccess()) { -// throw new SearchException(String.format("Failed to lookup entry. Errors: %s", result.errors()), result.info().errorCount()); -// } -// -// if (result.allRows().size() == 1) { -// return result.allRows().get(0).value(); -// } - + return doc; + } else { + GetOptions options = GetOptions.getOptions().project(Arrays.asList(attributes)); + JsonObject doc = bucket.defaultCollection().get(key, options).contentAsObject(); + if (doc != null) { + return doc; + } + } } } catch (CouchbaseException ex) { - throw new SearchException("Failed to lookup entry", ex); + if (ResponseStatus.SUBDOC_FAILURE == ex.context().responseStatus()) { + // No fields for return + return JsonObject.create(); + } + throw new SearchException(String.format("Failed to lookup entry by key '%s'", key), ex); } - throw new SearchException("Failed to lookup entry"); + throw new SearchException(String.format("Failed to lookup entry by key '%s'", key)); } @Override - public PagedResult search(String key, ScanConsistency scanConsistency, Expression expression, SearchScope scope, String[] attributes, Sort[] orderBy, + public PagedResult search(String key, QueryScanConsistency queryScanConsistency, ConvertedExpression expression, SearchScope scope, String[] attributes, Sort[] orderBy, CouchbaseBatchOperationWraper batchOperationWraper, SearchReturnDataType returnDataType, int start, int count, int pageSize) throws SearchException { Instant startTime = OperationDurationUtil.instance().now(); BucketMapping bucketMapping = connectionProvider.getBucketMappingByKey(key); boolean secondTry = false; - ScanConsistency useScanConsistency = getScanConsistency(scanConsistency, attemptWithoutAttributeScanConsistency); + QueryScanConsistency useQueryScanConsistency = getQueryScanConsistency(queryScanConsistency, attemptWithoutAttributeQueryScanConsistency); PagedResult result = null; int attemps = 20; do { attemps--; try { - result = searchImpl(bucketMapping, key, useScanConsistency, expression, scope, attributes, orderBy, batchOperationWraper, + result = searchImpl(bucketMapping, key, useQueryScanConsistency, expression, scope, attributes, orderBy, batchOperationWraper, returnDataType, start, count, pageSize); break; } catch (SearchException ex) { + // TODO: Check if it's not needed in CB 7.x and SDK 3.x if (ex.getErrorCode() != 5000) { throw ex; } @@ -483,27 +431,25 @@ public PagedResult search(String key, ScanConsistency scanConsis } catch (InterruptedException ex2) {} } } while (attemps > 0); - if ((result == null) || (result.getEntriesCount() == 0)) { - ScanConsistency useScanConsistency2 = getScanConsistency(scanConsistency, false); - if (!useScanConsistency2.equals(useScanConsistency)) { - useScanConsistency = useScanConsistency2; - result = searchImpl(bucketMapping, key, useScanConsistency, expression, scope, attributes, orderBy, batchOperationWraper, returnDataType, start, count, pageSize); + if ((result == null) || (result.getTotalEntriesCount() == 0)) { + QueryScanConsistency useQueryScanConsistency2 = getQueryScanConsistency(queryScanConsistency, false); + if (!useQueryScanConsistency2.equals(useQueryScanConsistency)) { + useQueryScanConsistency = useQueryScanConsistency2; + result = searchImpl(bucketMapping, key, useQueryScanConsistency, expression, scope, attributes, orderBy, batchOperationWraper, returnDataType, start, count, pageSize); secondTry = true; } } - String attemptInfo = getScanAttemptLogInfo(scanConsistency, useScanConsistency, secondTry); + String attemptInfo = getScanAttemptLogInfo(queryScanConsistency, useQueryScanConsistency, secondTry); Duration duration = OperationDurationUtil.instance().duration(startTime); - OperationDurationUtil.instance().logDebug("Couchbase operation: search, duration: {}, bucket: {}, key: {}, expression: {}, scope: {}, attributes: {}, orderBy: {}, batchOperationWraper: {}, returnDataType: {}, start: {}, count: {}, pageSize: {}, consistency: {}{}", duration, bucketMapping.getBucketName(), key, expression, scope, attributes, orderBy, batchOperationWraper, returnDataType, start, count, pageSize, useScanConsistency, attemptInfo); + OperationDurationUtil.instance().logDebug("Couchbase operation: search, duration: {}, bucket: {}, key: {}, expression: {}, scope: {}, attributes: {}, orderBy: {}, batchOperationWraper: {}, returnDataType: {}, start: {}, count: {}, pageSize: {}, consistency: {}{}", duration, bucketMapping.getBucketName(), key, expression, scope, attributes, orderBy, batchOperationWraper, returnDataType, start, count, pageSize, useQueryScanConsistency, attemptInfo); return result; } - private PagedResult searchImpl(BucketMapping bucketMapping, String key, ScanConsistency scanConsistency, Expression expression, SearchScope scope, String[] attributes, Sort[] orderBy, + private PagedResult searchImpl(BucketMapping bucketMapping, String key, QueryScanConsistency queryScanConsistency, ConvertedExpression expression, SearchScope scope, String[] attributes, Sort[] orderBy, CouchbaseBatchOperationWraper batchOperationWraper, SearchReturnDataType returnDataType, int start, int count, int pageSize) throws SearchException { - Bucket bucket = bucketMapping.getBucket(); - BatchOperation batchOperation = null; if (batchOperationWraper != null) { batchOperation = (BatchOperation) batchOperationWraper.getBatchOperation(); @@ -516,20 +462,12 @@ private PagedResult searchImpl(BucketMapping bucketMapping, Stri } } - Expression finalExpression = expression; + StringBuilder finalExpression = new StringBuilder(expression.expression()); if (enableScopeSupport) { - Expression scopeExpression; - if (scope == null) { - scopeExpression = null; - } else if (SearchScope.BASE == scope) { - scopeExpression = Expression.path("META().id").like(Expression.s(key + "%")) - .and(Expression.path("META().id").notLike(Expression.s(key + "\\\\_%\\\\_"))); + if (SearchScope.BASE == scope) { + finalExpression.append(" AND META().id NOT LIKE ").append(key).append("\\\\_%\\\\_"); } else { - scopeExpression = Expression.path("META().id").like(Expression.s(key + "%")); - } - - if (scopeExpression != null) { - finalExpression = scopeExpression.and(expression); + finalExpression.append(" AND META().id LIKE ").append(key).append("%"); } } else { if (scope != null) { @@ -549,82 +487,99 @@ private PagedResult searchImpl(BucketMapping bucketMapping, Stri select = ArrayHelper.arrayMerge(select, new String[] { CouchbaseOperationService.DN }); } } - GroupByPath selectQuery = Select.select(select).from(Expression.i(bucketMapping.getBucketName())).as("jans_doc").where(finalExpression); - LimitPath baseQuery = selectQuery; - if (orderBy != null) { - baseQuery = selectQuery.orderBy(orderBy); + StringBuilder baseQuery = new StringBuilder("SELECT ").append(StringHelper.toString(select)).append(" FROM `").append(bucketMapping.getBucketName()).append("` AS gluu_doc "). + append("WHERE ").append(finalExpression); + + StringBuilder baseQueryWithOrder = new StringBuilder(baseQuery); + if (ArrayHelper.isNotEmpty(orderBy)) { + baseQueryWithOrder.append(" ORDER BY "); + for (int i = 0; i < orderBy.length; i++) { + if (i > 0) { + baseQueryWithOrder.append(", "); + } + Sort order = orderBy[i]; + baseQueryWithOrder.append(order.getName()); + if ((order.getSortOrder() != null) && (SortOrder.DEFAULT != order.getSortOrder())) { + baseQueryWithOrder.append(" ").append(order.getSortOrder().getShortValue()); + } + } } - List searchResultList = new ArrayList(); + QueryOptions queryOptions = QueryOptions.queryOptions().scanConsistency(queryScanConsistency).parameters(expression.getQueryParameters()); + List searchResultList = new ArrayList(); + + int totalEntriesCount = 0; if ((SearchReturnDataType.SEARCH == returnDataType) || (SearchReturnDataType.SEARCH_COUNT == returnDataType)) { - N1qlQueryResult lastResult = null; + QueryResult lastResult = null; if (pageSize > 0) { boolean collectSearchResult; - Statement query = null; + StringBuilder query = null; int currentLimit; + int lastResultCount = 0; try { - List lastSearchResultList; - int resultCount = 0; - do { + List lastSearchResultList; + do { collectSearchResult = true; currentLimit = pageSize; if (count > 0) { - currentLimit = Math.min(pageSize, count - resultCount); + currentLimit = Math.min(pageSize, count - totalEntriesCount); } - query = baseQuery.limit(currentLimit).offset(start + resultCount); + query = new StringBuilder(baseQueryWithOrder).append(" LIMIT ").append(currentLimit).append(" OFFSET ").append(start + totalEntriesCount); + LOG.debug("Execution query: '" + query + "'"); - lastResult = bucket.query(N1qlQuery.simple(query, N1qlParams.build().consistency(scanConsistency))); - if (!lastResult.finalSuccess()) { - throw new SearchException(String.format("Failed to search entries. Query: '%s'. Error: '%s', Error count: '%d'", query, lastResult.errors(), - lastResult.info().errorCount()), lastResult.errors().get(0).getInt("code")); - } - - lastSearchResultList = lastResult.allRows(); + + lastResult = connectionProvider.getCluster().query(query.toString(), queryOptions); + if (QueryStatus.SUCCESS != lastResult.metaData().status()) { + throw new SearchException(String.format("Failed to search entries. Query: '%s'. Warnings: '%s'", query, lastResult.metaData().warnings())); + } + lastSearchResultList = lastResult.rowsAsObject(); + lastResultCount = lastSearchResultList.size(); + if (batchOperation != null) { - collectSearchResult = batchOperation.collectSearchResult(lastSearchResultList.size()); + collectSearchResult = batchOperation.collectSearchResult(lastResultCount); } if (collectSearchResult) { searchResultList.addAll(lastSearchResultList); } - if (batchOperation != null) { + if ((batchOperation != null) && (lastResultCount > 0)) { List entries = batchOperationWraper.createEntities(lastSearchResultList); batchOperation.performAction(entries); } - resultCount += lastSearchResultList.size(); + totalEntriesCount += lastResultCount; - if ((count > 0) && (resultCount >= count)) { + if ((count > 0) && (totalEntriesCount >= count)) { break; } - } while (lastSearchResultList.size() > 0); + } while (lastResultCount > 0); } catch (CouchbaseException ex) { throw new SearchException("Failed to search entries. Query: '" + query + "'", ex); } } else { try { - Statement query = baseQuery; + StringBuilder query = new StringBuilder(baseQueryWithOrder); if (count > 0) { - query = ((LimitPath) query).limit(count); + query.append(" LIMIT ").append(count); } if (start > 0) { - query = ((OffsetPath) query).offset(start); + query.append(" OFFSET ").append(start); } LOG.debug("Execution query: '" + query + "'"); - lastResult = bucket.query(N1qlQuery.simple(query, N1qlParams.build().consistency(scanConsistency))); - if (!lastResult.finalSuccess()) { - throw new SearchException(String.format("Failed to search entries. Query: '%s'. Error: '%s', Error count: '%d'", baseQuery, lastResult.errors(), - lastResult.info().errorCount()), lastResult.errors().get(0).getInt("code")); - } + + lastResult = connectionProvider.getCluster().query(query.toString(), queryOptions); + if (QueryStatus.SUCCESS != lastResult.metaData().status()) { + throw new SearchException(String.format("Failed to search entries. Query: '%s'. Warnings: '%s'", query, lastResult.metaData().warnings())); + } - searchResultList.addAll(lastResult.allRows()); + searchResultList.addAll(lastResult.rowsAsObject()); } catch (CouchbaseException ex) { throw new SearchException("Failed to search entries. Query: '" + baseQuery.toString() + "'", ex); } @@ -632,8 +587,8 @@ private PagedResult searchImpl(BucketMapping bucketMapping, Stri } List resultRows = new ArrayList(searchResultList.size()); - for (N1qlQueryRow row : searchResultList) { - resultRows.add(row.value()); + for (JsonObject row : searchResultList) { + resultRows.add(row); } PagedResult result = new PagedResult(); @@ -642,19 +597,21 @@ private PagedResult searchImpl(BucketMapping bucketMapping, Stri result.setStart(start); if ((SearchReturnDataType.COUNT == returnDataType) || (SearchReturnDataType.SEARCH_COUNT == returnDataType)) { - GroupByPath selectCountQuery = Select.select("COUNT(*) as TOTAL").from(Expression.i(bucketMapping.getBucketName())) - .where(finalExpression); + StringBuilder selectCountQuery = new StringBuilder("SELECT COUNT(*) as TOTAL").append(" FROM `").append(bucketMapping.getBucketName()).append("` AS gluu_doc "). + append("WHERE ").append(finalExpression); try { LOG.debug("Calculating count. Execution query: '" + selectCountQuery + "'"); - N1qlQueryResult countResult = bucket.query(N1qlQuery.simple(selectCountQuery, N1qlParams.build().consistency(scanConsistency))); - if (!countResult.finalSuccess() || (countResult.info().resultCount() != 1)) { - throw new SearchException(String.format("Failed to calculate count entries. Query: '%s'. Error: '%s', Error count: '%d'", selectCountQuery, countResult.errors(), - countResult.info().errorCount()), countResult.errors().get(0).getInt("code")); - } - result.setTotalEntriesCount(countResult.allRows().get(0).value().getInt("TOTAL")); + + QueryResult countResult = connectionProvider.getCluster().query(selectCountQuery.toString(), queryOptions); + if ((QueryStatus.SUCCESS != countResult.metaData().status()) && (countResult.rowsAsObject().size() != 1)) { + throw new SearchException(String.format("Failed to calculate count entries. Query: '%s'. Warnings: '%s'", selectCountQuery, countResult.metaData().warnings())); + } + result.setTotalEntriesCount(countResult.rowsAsObject().get(0).getInt("TOTAL")); } catch (CouchbaseException ex) { throw new SearchException("Failed to calculate count entries. Query: '" + selectCountQuery.toString() + "'", ex); } + } else { + result.setTotalEntriesCount(totalEntriesCount); } return result; @@ -687,24 +644,24 @@ public boolean isCertificateAttribute(String attribute) { return this.connectionProvider.isCertificateAttribute(attribute); } - private ScanConsistency getScanConsistency(ScanConsistency operationScanConsistency, boolean ignore) { + private QueryScanConsistency getQueryScanConsistency(QueryScanConsistency operationQueryScanConsistency, boolean ignore) { if (ignore) { - return scanConsistency; + return queryScanConsistency; } - if (ignoreAttributeScanConsistency) { - return scanConsistency; + if (ignoreAttributeQueryScanConsistency) { + return queryScanConsistency; } - if (operationScanConsistency != null) { - return operationScanConsistency; + if (operationQueryScanConsistency != null) { + return operationQueryScanConsistency; } - return scanConsistency; + return queryScanConsistency; } - public ScanConsistency getScanConsistency() { - return scanConsistency; + public QueryScanConsistency getQueryScanConsistency() { + return queryScanConsistency; } public boolean isDisableAttributeMapping() { @@ -732,13 +689,13 @@ public boolean isConnected() { return connectionProvider.isConnected(); } - protected String getScanAttemptLogInfo(ScanConsistency scanConsistency, ScanConsistency usedScanConsistency, boolean secondTry) { + protected String getScanAttemptLogInfo(QueryScanConsistency queryScanConsistency, QueryScanConsistency usedQueryScanConsistency, boolean secondTry) { String attemptInfo = ""; if (secondTry) { attemptInfo = ", attempt: second"; } else { - ScanConsistency useScanConsistency2 = getScanConsistency(scanConsistency, false); - if (!useScanConsistency2.equals(usedScanConsistency)) { + QueryScanConsistency useQueryScanConsistency2 = getQueryScanConsistency(queryScanConsistency, false); + if (!useQueryScanConsistency2.equals(usedQueryScanConsistency)) { attemptInfo = ", attempt: first"; } } @@ -756,4 +713,92 @@ public boolean isSupportObjectClass(String objectClass) { return true; } + @Override + public String toInternalAttribute(String attributeName) { + return attributeName; +// if (getOperationService().isDisableAttributeMapping()) { +// return attributeName; +// } +// +// return KeyShortcuter.shortcut(attributeName); + } + + @Override + public String[] toInternalAttributes(String[] attributeNames) { + return attributeNames; +// if (getOperationService().isDisableAttributeMapping() || ArrayHelper.isEmpty(attributeNames)) { +// return attributeNames; +// } +// +// String[] resultAttributeNames = new String[attributeNames.length]; +// +// for (int i = 0; i < attributeNames.length; i++) { +// resultAttributeNames[i] = KeyShortcuter.shortcut(attributeNames[i]); +// } +// +// return resultAttributeNames; + } + + @Override + public String fromInternalAttribute(String internalAttributeName) { + return internalAttributeName; +// if (getOperationService().isDisableAttributeMapping()) { +// return internalAttributeName; +// } +// +// return KeyShortcuter.fromShortcut(internalAttributeName); + } + + @Override + public String[] fromInternalAttributes(String[] internalAttributeNames) { + return internalAttributeNames; +// if (getOperationService().isDisableAttributeMapping() || ArrayHelper.isEmpty(internalAttributeNames)) { +// return internalAttributeNames; +// } +// +// String[] resultAttributeNames = new String[internalAttributeNames.length]; +// +// for (int i = 0; i < internalAttributeNames.length; i++) { +// resultAttributeNames[i] = KeyShortcuter.fromShortcut(internalAttributeNames[i]); +// } +// +// return resultAttributeNames; + } + + @Override + public String encodeTime(Date date) { + if (date == null) { + return null; + } + + try { + String utcDate = ISO_INSTANT.format(Instant.ofEpochMilli(date.getTime())); + // Drop UTC zone identifier to comply with format employed in CB: yyyy-MM-dd'T'HH:mm:ss.SSS +// return utcDate.substring(0, utcDate.length() - 1); + return utcDate; + } catch (DateTimeException ex) { + LOG.error("Cannot format date '{}' as ISO", date, ex); + return null; + } + } + + @Override + public Date decodeTime(String date, boolean silent) { + if (StringHelper.isEmpty(date)) { + return null; + } + + // Add ending Z if necessary + String dateZ = date.endsWith("Z") ? date : date + "Z"; + try { + return new Date(Instant.parse(dateZ).toEpochMilli()); + } catch (DateTimeParseException ex) { + if (!silent) { + LOG.error("Failed to decode generalized time '{}'", date, ex); + } + + return null; + } + } + } diff --git a/jans-orm/couchbase/src/test/java/io/jans/orm/couchbase/impl/test/CouchbaseFilterConverterCheckExcludeFilterTest.java b/jans-orm/couchbase/src/test/java/io/jans/orm/couchbase/impl/test/CouchbaseFilterConverterCheckExcludeFilterTest.java index 30a09963206..23c1314559f 100644 --- a/jans-orm/couchbase/src/test/java/io/jans/orm/couchbase/impl/test/CouchbaseFilterConverterCheckExcludeFilterTest.java +++ b/jans-orm/couchbase/src/test/java/io/jans/orm/couchbase/impl/test/CouchbaseFilterConverterCheckExcludeFilterTest.java @@ -6,27 +6,29 @@ import java.util.Date; import java.util.TimeZone; +import io.jans.orm.exception.operation.SearchException; +import io.jans.orm.search.filter.Filter; +import io.jans.orm.search.filter.FilterProcessor; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import com.couchbase.client.java.query.Select; -import com.couchbase.client.java.query.dsl.Expression; -import com.couchbase.client.java.query.dsl.path.GroupByPath; +import com.couchbase.client.java.json.JsonObject; import io.jans.orm.couchbase.impl.CouchbaseFilterConverter; import io.jans.orm.couchbase.model.ConvertedExpression; -import io.jans.orm.exception.operation.SearchException; -import io.jans.orm.search.filter.Filter; -import io.jans.orm.search.filter.FilterProcessor; +import io.jans.orm.couchbase.operation.CouchbaseOperationService; +import io.jans.orm.couchbase.operation.impl.CouchbaseOperationServiceImpl; public class CouchbaseFilterConverterCheckExcludeFilterTest { + private CouchbaseOperationService couchbaseOperationService; private CouchbaseFilterConverter simpleConverter; private FilterProcessor filterProcessor; @BeforeClass public void init() { - this.simpleConverter = new CouchbaseFilterConverter(null); + this.couchbaseOperationService = new CouchbaseOperationServiceImpl(); + this.simpleConverter = new CouchbaseFilterConverter(couchbaseOperationService); this.filterProcessor = new FilterProcessor(); } @@ -44,27 +46,48 @@ public void checkObjectClassExcludeFilter() throws SearchException { ConvertedExpression expression1 = simpleConverter.convertToCouchbaseFilter(filter1, null, null); String query1 = toSelectSQL(expression1); - assertEquals(query1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( ( objectClass = \"jansPerson\" ) OR ( \"jansPerson\" IN objectClass ) ) AND ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER(uid) = \"test\" AND ( ( objectClass = \"jansPerson\" ) OR ( \"jansPerson\" IN objectClass ) ) AND ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER(uid) = \"test\" AND ( ( objectClass = \"jansPerson\" ) OR ( \"jansPerson\" IN objectClass ) ) AND ANY added_ IN added SATISFIES added_ = \"Wed Dec 16 14:58:18 UTC 2020\" END ) AND ANY added_ IN added SATISFIES added_ = \"Wed Dec 16 14:58:18 UTC 2020\" END ) )"); + assertEquals(query1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( ( objectClass = \"jansPerson\" ) OR ( \"jansPerson\" IN objectClass ) ) AND ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER( uid ) = \"test\" AND ( ( objectClass = \"jansPerson\" ) OR ( \"jansPerson\" IN objectClass ) ) AND ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER( uid ) = \"test\" AND ( ( objectClass = \"jansPerson\" ) OR ( \"jansPerson\" IN objectClass ) ) AND ANY added_ IN added SATISFIES added_ = \"2020-12-16T14:58:18.398Z\" END ) AND ANY added_ IN added SATISFIES added_ = \"2020-12-16T14:58:18.398Z\" END ) )"); Filter filter2 = filterProcessor.excludeFilter(filter1, filterEq3); ConvertedExpression expression2 = simpleConverter.convertToCouchbaseFilter(filter2, null, null); String query2 = toSelectSQL(expression2); - assertEquals(query2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER(uid) = \"test\" AND ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER(uid) = \"test\" AND ANY added_ IN added SATISFIES added_ = \"Wed Dec 16 14:58:18 UTC 2020\" END ) AND ANY added_ IN added SATISFIES added_ = \"Wed Dec 16 14:58:18 UTC 2020\" END ) )"); + assertEquals(query2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER( uid ) = \"test\" AND ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER( uid ) = \"test\" AND ANY added_ IN added SATISFIES added_ = \"2020-12-16T14:58:18.398Z\" END ) AND ANY added_ IN added SATISFIES added_ = \"2020-12-16T14:58:18.398Z\" END ) )"); Filter filter3 = filterProcessor.excludeFilter(filter1, Filter.createEqualityFilter("objectClass", null)); ConvertedExpression expression3 = simpleConverter.convertToCouchbaseFilter(filter3, null, null); String query3 = toSelectSQL(expression3); - assertEquals(query3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER(uid) = \"test\" AND ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER(uid) = \"test\" AND ANY added_ IN added SATISFIES added_ = \"Wed Dec 16 14:58:18 UTC 2020\" END ) AND ANY added_ IN added SATISFIES added_ = \"Wed Dec 16 14:58:18 UTC 2020\" END ) )"); + assertEquals(query3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER( uid ) = \"test\" AND ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND LOWER( uid ) = \"test\" AND ANY added_ IN added SATISFIES added_ = \"2020-12-16T14:58:18.398Z\" END ) AND ANY added_ IN added SATISFIES added_ = \"2020-12-16T14:58:18.398Z\" END ) )"); } private String toSelectSQL(ConvertedExpression convertedExpression) { - GroupByPath select = Select.select("jans_doc.*").from(Expression.i("jans")).as("jans_doc").where(convertedExpression.expression()); + String select = String.format("SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE %s", convertedExpression.expression()); + + // Substitute parameters for test + JsonObject params = convertedExpression.getQueryParameters(); + for (String name : params.getNames()) { + Object value = params.get(name); + + Object replaceValue = value; + if (value instanceof String) { + replaceValue = "\"" + value + "\""; + } + + String searchName = "\\$" + name; + int subIndex = select.indexOf("%$" + name + "%"); + if (subIndex != -1) { + searchName = "%" + searchName + "%"; + replaceValue = "\"%" + value + "%\""; + } + select = select.replaceAll(searchName, replaceValue.toString()); + } + + select = select.replaceAll("\"\"%", "%").replaceAll("%\"\"", "%"); - return select.toString(); + return select; } private static Date getUtcDateFromMillis(long millis) { diff --git a/jans-orm/couchbase/src/test/java/io/jans/orm/couchbase/impl/test/CouchbaseFilterConverterTest.java b/jans-orm/couchbase/src/test/java/io/jans/orm/couchbase/impl/test/CouchbaseFilterConverterTest.java index d2ce00ec825..89aa3d6aeaa 100644 --- a/jans-orm/couchbase/src/test/java/io/jans/orm/couchbase/impl/test/CouchbaseFilterConverterTest.java +++ b/jans-orm/couchbase/src/test/java/io/jans/orm/couchbase/impl/test/CouchbaseFilterConverterTest.java @@ -6,25 +6,27 @@ import java.util.Date; import java.util.TimeZone; +import io.jans.orm.exception.operation.SearchException; +import io.jans.orm.search.filter.Filter; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import com.couchbase.client.java.query.Select; -import com.couchbase.client.java.query.dsl.Expression; -import com.couchbase.client.java.query.dsl.path.GroupByPath; +import com.couchbase.client.java.json.JsonObject; import io.jans.orm.couchbase.impl.CouchbaseFilterConverter; import io.jans.orm.couchbase.model.ConvertedExpression; -import io.jans.orm.exception.operation.SearchException; -import io.jans.orm.search.filter.Filter; +import io.jans.orm.couchbase.operation.CouchbaseOperationService; +import io.jans.orm.couchbase.operation.impl.CouchbaseOperationServiceImpl; public class CouchbaseFilterConverterTest { private CouchbaseFilterConverter simpleConverter; + private CouchbaseOperationService couchbaseOperationService; @BeforeClass public void init() { - this.simpleConverter = new CouchbaseFilterConverter(null); + this.couchbaseOperationService = new CouchbaseOperationServiceImpl(); + this.simpleConverter = new CouchbaseFilterConverter(couchbaseOperationService); } @Test @@ -34,28 +36,32 @@ public void checkEqFilters() throws SearchException { ConvertedExpression expressionEq1 = simpleConverter.convertToCouchbaseFilter(filterEq1, null, null); String queryEq1 = toSelectSQL(expressionEq1); - assertEquals(queryEq1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( uid = \"test\" ) OR ( \"test\" IN uid ) )"); + assertEquals(expressionEq1.expression(), "( ( uid = $uid ) OR ( $uid IN uid ) )"); + assertEquals(queryEq1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( uid = \"test\" ) OR ( \"test\" IN uid ) )"); // EQ -- Integer Filter filterEq2 = Filter.createEqualityFilter("age", 23); ConvertedExpression expressionEq2 = simpleConverter.convertToCouchbaseFilter(filterEq2, null, null); String queryEq2 = toSelectSQL(expressionEq2); - assertEquals(queryEq2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( age = 23 ) OR ( 23 IN age ) )"); + assertEquals(expressionEq2.expression(), "( ( age = $age ) OR ( $age IN age ) )"); + assertEquals(queryEq2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( age = 23 ) OR ( 23 IN age ) )"); // EQ -- Long Filter filterEq3 = Filter.createEqualityFilter("age", 23L); ConvertedExpression expressionEq3 = simpleConverter.convertToCouchbaseFilter(filterEq3, null, null); String queryEq3 = toSelectSQL(expressionEq3); - assertEquals(queryEq3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( age = 23 ) OR ( 23 IN age ) )"); + assertEquals(expressionEq3.expression(), "( ( age = $age ) OR ( $age IN age ) )"); + assertEquals(queryEq3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( age = 23 ) OR ( 23 IN age ) )"); // EQ -- Date Filter filterEq4 = Filter.createEqualityFilter("added", getUtcDateFromMillis(1608130698398L)); ConvertedExpression expressionEq4 = simpleConverter.convertToCouchbaseFilter(filterEq4, null, null); String queryEq4 = toSelectSQL(expressionEq4); - assertEquals(queryEq4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( added = \"Wed Dec 16 14:58:18 UTC 2020\" ) OR ( \"Wed Dec 16 14:58:18 UTC 2020\" IN added ) )"); + assertEquals(expressionEq4.expression(), "( ( added = $added ) OR ( $added IN added ) )"); + assertEquals(queryEq4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( added = \"2020-12-16T14:58:18.398Z\" ) OR ( \"2020-12-16T14:58:18.398Z\" IN added ) )"); } @Test @@ -65,28 +71,32 @@ public void checkMultivaluedEqFilters() throws SearchException { ConvertedExpression expressionEq1 = simpleConverter.convertToCouchbaseFilter(filterEq1, null, null); String queryEq1 = toSelectSQL(expressionEq1); - assertEquals(queryEq1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ = \"test\" END"); + assertEquals(expressionEq1.expression(), "ANY uid_ IN uid SATISFIES uid_ = $uid END"); + assertEquals(queryEq1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ = \"test\" END"); // EQ -- Integer Filter filterEq2 = Filter.createEqualityFilter("age", 23).multiValued(); ConvertedExpression expressionEq2 = simpleConverter.convertToCouchbaseFilter(filterEq2, null, null); String queryEq2 = toSelectSQL(expressionEq2); - assertEquals(queryEq2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY age_ IN age SATISFIES age_ = 23 END"); + assertEquals(expressionEq2.expression(), "ANY age_ IN age SATISFIES age_ = $age END"); + assertEquals(queryEq2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY age_ IN age SATISFIES age_ = 23 END"); // EQ -- Long Filter filterEq3 = Filter.createEqualityFilter("age", 23L).multiValued(); ConvertedExpression expressionEq3 = simpleConverter.convertToCouchbaseFilter(filterEq3, null, null); String queryEq3 = toSelectSQL(expressionEq3); - assertEquals(queryEq3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY age_ IN age SATISFIES age_ = 23 END"); + assertEquals(expressionEq3.expression(), "ANY age_ IN age SATISFIES age_ = $age END"); + assertEquals(queryEq3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY age_ IN age SATISFIES age_ = 23 END"); // EQ -- Date Filter filterEq4 = Filter.createEqualityFilter("added", getUtcDateFromMillis(1608130698398L)).multiValued(); ConvertedExpression expressionEq4 = simpleConverter.convertToCouchbaseFilter(filterEq4, null, null); String queryEq4 = toSelectSQL(expressionEq4); - assertEquals(queryEq4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY added_ IN added SATISFIES added_ = \"Wed Dec 16 14:58:18 UTC 2020\" END"); + assertEquals(expressionEq4.expression(), "ANY added_ IN added SATISFIES added_ = $added END"); + assertEquals(queryEq4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY added_ IN added SATISFIES added_ = \"2020-12-16T14:58:18.398Z\" END"); } @Test @@ -96,28 +106,32 @@ public void checkSinglevaluedEqFilters() throws SearchException { ConvertedExpression expressionEq1 = simpleConverter.convertToCouchbaseFilter(filterEq1, null, null); String queryEq1 = toSelectSQL(expressionEq1); - assertEquals(queryEq1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE uid = \"test\""); + assertEquals(expressionEq1.expression(), "uid = $uid"); + assertEquals(queryEq1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE uid = \"test\""); // EQ -- Integer Filter filterEq2 = Filter.createEqualityFilter("age", 23).multiValued(false); ConvertedExpression expressionEq2 = simpleConverter.convertToCouchbaseFilter(filterEq2, null, null); String queryEq2 = toSelectSQL(expressionEq2); - assertEquals(queryEq2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE age = 23"); + assertEquals(expressionEq2.expression(), "age = $age"); + assertEquals(queryEq2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE age = 23"); // EQ -- Long Filter filterEq3 = Filter.createEqualityFilter("age", 23L).multiValued(false); ConvertedExpression expressionEq3 = simpleConverter.convertToCouchbaseFilter(filterEq3, null, null); String queryEq3 = toSelectSQL(expressionEq3); - assertEquals(queryEq3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE age = 23"); + assertEquals(expressionEq3.expression(), "age = $age"); + assertEquals(queryEq3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE age = 23"); // EQ -- Date Filter filterEq4 = Filter.createEqualityFilter("added", getUtcDateFromMillis(1608130698398L)).multiValued(false); ConvertedExpression expressionEq4 = simpleConverter.convertToCouchbaseFilter(filterEq4, null, null); String queryEq4 = toSelectSQL(expressionEq4); - assertEquals(queryEq4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE added = \"Wed Dec 16 14:58:18 UTC 2020\""); + assertEquals(expressionEq4.expression(), "added = $added"); + assertEquals(queryEq4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE added = \"2020-12-16T14:58:18.398Z\""); } @Test @@ -127,28 +141,32 @@ public void checkLeFilters() throws SearchException { ConvertedExpression expressionLe1 = simpleConverter.convertToCouchbaseFilter(filterLe1, null, null); String queryLe1 = toSelectSQL(expressionLe1); - assertEquals(queryLe1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE uid <= \"test\""); + assertEquals(expressionLe1.expression(), "uid <= $uid"); + assertEquals(queryLe1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE uid <= \"test\""); // LE -- Integer Filter filterLe2 = Filter.createLessOrEqualFilter("age", 23); ConvertedExpression expressionLe2 = simpleConverter.convertToCouchbaseFilter(filterLe2, null, null); String queryLe2 = toSelectSQL(expressionLe2); - assertEquals(queryLe2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE age <= 23"); + assertEquals(expressionLe2.expression(), "age <= $age"); + assertEquals(queryLe2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE age <= 23"); // LE -- Long Filter filterLe3 = Filter.createLessOrEqualFilter("age", 23L); ConvertedExpression expressionLe3 = simpleConverter.convertToCouchbaseFilter(filterLe3, null, null); String queryLe3 = toSelectSQL(expressionLe3); - assertEquals(queryLe3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE age <= 23"); + assertEquals(expressionLe3.expression(), "age <= $age"); + assertEquals(queryLe3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE age <= 23"); // LE -- Date Filter filterLe4 = Filter.createLessOrEqualFilter("added", getUtcDateFromMillis(1608130698398L)); ConvertedExpression expressionLe4 = simpleConverter.convertToCouchbaseFilter(filterLe4, null, null); String queryLe4 = toSelectSQL(expressionLe4); - assertEquals(queryLe4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE added <= \"Wed Dec 16 14:58:18 UTC 2020\""); + assertEquals(expressionLe4.expression(), "added <= $added"); + assertEquals(queryLe4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE added <= \"2020-12-16T14:58:18.398Z\""); } @Test @@ -158,35 +176,40 @@ public void checkMultivaluedLeFilters() throws SearchException { ConvertedExpression expressionLe1 = simpleConverter.convertToCouchbaseFilter(filterLe1, null, null); String queryLe1 = toSelectSQL(expressionLe1); - assertEquals(queryLe1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ <= \"test\" END"); + assertEquals(expressionLe1.expression(), "ANY uid_ IN uid SATISFIES uid_ <= $uid END"); + assertEquals(queryLe1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ <= \"test\" END"); // LE -- Integer Filter filterLe2 = Filter.createLessOrEqualFilter("age", 23).multiValued(); ConvertedExpression expressionLe2 = simpleConverter.convertToCouchbaseFilter(filterLe2, null, null); String queryLe2 = toSelectSQL(expressionLe2); - assertEquals(queryLe2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY age_ IN age SATISFIES age_ <= 23 END"); + assertEquals(expressionLe2.expression(), "ANY age_ IN age SATISFIES age_ <= $age END"); + assertEquals(queryLe2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY age_ IN age SATISFIES age_ <= 23 END"); // LE -- Long Filter filterLe3 = Filter.createLessOrEqualFilter("age", 23L).multiValued(); ConvertedExpression expressionLe3 = simpleConverter.convertToCouchbaseFilter(filterLe3, null, null); String queryLe3 = toSelectSQL(expressionLe3); - assertEquals(queryLe3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY age_ IN age SATISFIES age_ <= 23 END"); + assertEquals(expressionLe3.expression(), "ANY age_ IN age SATISFIES age_ <= $age END"); + assertEquals(queryLe3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY age_ IN age SATISFIES age_ <= 23 END"); // LE -- Date Filter filterLe4 = Filter.createLessOrEqualFilter("added", getUtcDateFromMillis(1608130698398L)).multiValued(); ConvertedExpression expressionLe4 = simpleConverter.convertToCouchbaseFilter(filterLe4, null, null); String queryLe4 = toSelectSQL(expressionLe4); - assertEquals(queryLe4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY added_ IN added SATISFIES added_ <= \"Wed Dec 16 14:58:18 UTC 2020\" END"); + assertEquals(expressionLe4.expression(), "ANY added_ IN added SATISFIES added_ <= $added END"); + assertEquals(queryLe4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY added_ IN added SATISFIES added_ <= \"2020-12-16T14:58:18.398Z\" END"); // LE -- Date Filter filterLe5 = Filter.createLessOrEqualFilter("added", getUtcDateFromMillis(1608130698398L)).multiValued(3); ConvertedExpression expressionLe5 = simpleConverter.convertToCouchbaseFilter(filterLe5, null, null); String queryLe5 = toSelectSQL(expressionLe5); - assertEquals(queryLe5, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY added_ IN added SATISFIES added_ <= \"Wed Dec 16 14:58:18 UTC 2020\" END"); + assertEquals(expressionLe5.expression(), "ANY added_ IN added SATISFIES added_ <= $added END"); + assertEquals(queryLe5, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY added_ IN added SATISFIES added_ <= \"2020-12-16T14:58:18.398Z\" END"); } @Test @@ -196,28 +219,32 @@ public void checkGeFilters() throws SearchException { ConvertedExpression expressionGe1 = simpleConverter.convertToCouchbaseFilter(filterGe1, null, null); String queryGe1 = toSelectSQL(expressionGe1); - assertEquals(queryGe1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE uid >= \"test\""); + assertEquals(expressionGe1.expression(), "uid >= $uid"); + assertEquals(queryGe1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE uid >= \"test\""); // LE -- Integer Filter filterGe2 = Filter.createGreaterOrEqualFilter("age", 23); ConvertedExpression expressionGe2 = simpleConverter.convertToCouchbaseFilter(filterGe2, null, null); String queryGe2 = toSelectSQL(expressionGe2); - assertEquals(queryGe2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE age >= 23"); + assertEquals(expressionGe2.expression(), "age >= $age"); + assertEquals(queryGe2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE age >= 23"); // LE -- Long Filter filterGe3 = Filter.createGreaterOrEqualFilter("age", 23L); ConvertedExpression expressionGe3 = simpleConverter.convertToCouchbaseFilter(filterGe3, null, null); String queryGe3 = toSelectSQL(expressionGe3); - assertEquals(queryGe3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE age >= 23"); + assertEquals(expressionGe3.expression(), "age >= $age"); + assertEquals(queryGe3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE age >= 23"); // LE -- Date Filter filterGe4 = Filter.createGreaterOrEqualFilter("added", getUtcDateFromMillis(1608130698398L)); ConvertedExpression expressionGe4 = simpleConverter.convertToCouchbaseFilter(filterGe4, null, null); String queryGe4 = toSelectSQL(expressionGe4); - assertEquals(queryGe4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE added >= \"Wed Dec 16 14:58:18 UTC 2020\""); + assertEquals(expressionGe4.expression(), "added >= $added"); + assertEquals(queryGe4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE added >= \"2020-12-16T14:58:18.398Z\""); } @Test @@ -227,35 +254,40 @@ public void checkMultivaluedGeFilters() throws SearchException { ConvertedExpression expressionGe1 = simpleConverter.convertToCouchbaseFilter(filterGe1, null, null); String queryGe1 = toSelectSQL(expressionGe1); - assertEquals(queryGe1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ >= \"test\" END"); + assertEquals(expressionGe1.expression(), "ANY uid_ IN uid SATISFIES uid_ >= $uid END"); + assertEquals(queryGe1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ >= \"test\" END"); // GE -- Integer Filter filterGe2 = Filter.createGreaterOrEqualFilter("age", 23).multiValued(); ConvertedExpression expressionGe2 = simpleConverter.convertToCouchbaseFilter(filterGe2, null, null); String queryGe2 = toSelectSQL(expressionGe2); - assertEquals(queryGe2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY age_ IN age SATISFIES age_ >= 23 END"); + assertEquals(expressionGe2.expression(), "ANY age_ IN age SATISFIES age_ >= $age END"); + assertEquals(queryGe2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY age_ IN age SATISFIES age_ >= 23 END"); // GE -- Long Filter filterGe3 = Filter.createGreaterOrEqualFilter("age", 23L).multiValued(); ConvertedExpression expressionGe3 = simpleConverter.convertToCouchbaseFilter(filterGe3, null, null); String queryGe3 = toSelectSQL(expressionGe3); - assertEquals(queryGe3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY age_ IN age SATISFIES age_ >= 23 END"); + assertEquals(expressionGe3.expression(), "ANY age_ IN age SATISFIES age_ >= $age END"); + assertEquals(queryGe3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY age_ IN age SATISFIES age_ >= 23 END"); // GE -- Date Filter filterGe4 = Filter.createGreaterOrEqualFilter("added", getUtcDateFromMillis(1608130698398L)).multiValued(); ConvertedExpression expressionGe4 = simpleConverter.convertToCouchbaseFilter(filterGe4, null, null); String queryGe4 = toSelectSQL(expressionGe4); - assertEquals(queryGe4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY added_ IN added SATISFIES added_ >= \"Wed Dec 16 14:58:18 UTC 2020\" END"); + assertEquals(expressionGe4.expression(), "ANY added_ IN added SATISFIES added_ >= $added END"); + assertEquals(queryGe4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY added_ IN added SATISFIES added_ >= \"2020-12-16T14:58:18.398Z\" END"); // GE -- Date Filter filterGe5 = Filter.createGreaterOrEqualFilter("added", getUtcDateFromMillis(1608130698398L)).multiValued(3); ConvertedExpression expressionGe5 = simpleConverter.convertToCouchbaseFilter(filterGe5, null, null); String queryGe5 = toSelectSQL(expressionGe5); - assertEquals(queryGe5, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY added_ IN added SATISFIES added_ >= \"Wed Dec 16 14:58:18 UTC 2020\" END"); + assertEquals(expressionGe5.expression(), "ANY added_ IN added SATISFIES added_ >= $added END"); + assertEquals(queryGe5, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY added_ IN added SATISFIES added_ >= \"2020-12-16T14:58:18.398Z\" END"); } @Test @@ -265,7 +297,8 @@ public void checkPresenceFilters() throws SearchException { ConvertedExpression expressionPresence = simpleConverter.convertToCouchbaseFilter(filterPresence, null, null); String queryPresence = toSelectSQL(expressionPresence); - assertEquals(queryPresence, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE uid IS NOT MISSING"); + assertEquals(expressionPresence.expression(), "uid IS NOT MISSING"); + assertEquals(queryPresence, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE uid IS NOT MISSING"); } @Test @@ -275,14 +308,16 @@ public void checkMultivaluedPresenceFilters() throws SearchException { ConvertedExpression expressionPresence1 = simpleConverter.convertToCouchbaseFilter(filterPresence1, null, null); String queryPresence1 = toSelectSQL(expressionPresence1); - assertEquals(queryPresence1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ IS NOT MISSING END"); + assertEquals(expressionPresence1.expression(), "ANY uid_ IN uid SATISFIES uid_ IS NOT MISSING END"); + assertEquals(queryPresence1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ IS NOT MISSING END"); // Presence -- String -- Multivalued = 3 Filter filterPresence2 = Filter.createPresenceFilter("uid").multiValued(3); ConvertedExpression expressionPresence2 = simpleConverter.convertToCouchbaseFilter(filterPresence2, null, null); String queryPresence2 = toSelectSQL(expressionPresence2); - assertEquals(queryPresence2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ IS NOT MISSING END"); + assertEquals(expressionPresence2.expression(), "ANY uid_ IN uid SATISFIES uid_ IS NOT MISSING END"); + assertEquals(queryPresence2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ IS NOT MISSING END"); } @Test @@ -291,19 +326,22 @@ public void checkSubFilters() throws SearchException { ConvertedExpression expressionSub1 = simpleConverter.convertToCouchbaseFilter(filterSub1, null, null); String querySub1 = toSelectSQL(expressionSub1); - assertEquals(querySub1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE uid LIKE \"%test%\""); + assertEquals(expressionSub1.expression(), "uid LIKE %$uid_any%"); + assertEquals(querySub1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE uid LIKE \"%test%\""); Filter filterSub2 = Filter.createSubstringFilter("uid", "a", new String[] { "test" }, null); ConvertedExpression expressionSub2 = simpleConverter.convertToCouchbaseFilter(filterSub2, null, null); String querySub2 = toSelectSQL(expressionSub2); - assertEquals(querySub2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE uid LIKE \"a%test%\""); + assertEquals(expressionSub2.expression(), "uid LIKE $uid_i%$uid_any%"); + assertEquals(querySub2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE uid LIKE \"a%test%\""); Filter filterSub3 = Filter.createSubstringFilter("uid", null, new String[] { "test" }, "z"); ConvertedExpression expressionSub3 = simpleConverter.convertToCouchbaseFilter(filterSub3, null, null); String querySub3 = toSelectSQL(expressionSub3); - assertEquals(querySub3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE uid LIKE \"%test%z\""); + assertEquals(expressionSub3.expression(), "uid LIKE %$uid_any%$uid_f"); + assertEquals(querySub3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE uid LIKE \"%test%z\""); } @Test @@ -312,25 +350,29 @@ public void checkMultivaluedSubFilters() throws SearchException { ConvertedExpression expressionSub1 = simpleConverter.convertToCouchbaseFilter(filterSub1, null, null); String querySub1 = toSelectSQL(expressionSub1); - assertEquals(querySub1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ LIKE \"%test%\" END"); + assertEquals(expressionSub1.expression(), "ANY uid_ IN uid SATISFIES uid_ LIKE %$uid_any% END"); + assertEquals(querySub1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ LIKE \"%test%\" END"); Filter filterSub2 = Filter.createSubstringFilter("uid", "a", new String[] { "test" }, null).multiValued(); ConvertedExpression expressionSub2 = simpleConverter.convertToCouchbaseFilter(filterSub2, null, null); String querySub2 = toSelectSQL(expressionSub2); - assertEquals(querySub2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ LIKE \"a%test%\" END"); + assertEquals(expressionSub2.expression(), "ANY uid_ IN uid SATISFIES uid_ LIKE $uid_i%$uid_any% END"); + assertEquals(querySub2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ LIKE \"a%test%\" END"); Filter filterSub3 = Filter.createSubstringFilter("uid", null, new String[] { "test" }, "z").multiValued(); ConvertedExpression expressionSub3 = simpleConverter.convertToCouchbaseFilter(filterSub3, null, null); String querySub3 = toSelectSQL(expressionSub3); - assertEquals(querySub3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ LIKE \"%test%z\" END"); + assertEquals(expressionSub3.expression(), "ANY uid_ IN uid SATISFIES uid_ LIKE %$uid_any%$uid_f END"); + assertEquals(querySub3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ LIKE \"%test%z\" END"); Filter filterSub4 = Filter.createSubstringFilter("uid", null, new String[] { "test" }, "z").multiValued(3); ConvertedExpression expressionSub4 = simpleConverter.convertToCouchbaseFilter(filterSub4, null, null); String querySub4 = toSelectSQL(expressionSub4); - assertEquals(querySub4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES uid_ LIKE \"%test%z\" END"); + assertEquals(expressionSub4.expression(), "ANY uid_ IN uid SATISFIES uid_ LIKE %$uid_any%$uid_f END"); + assertEquals(querySub4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES uid_ LIKE \"%test%z\" END"); } @Test @@ -339,25 +381,29 @@ public void checkMultivaluedSubWithLowerFilters() throws SearchException { ConvertedExpression expressionSub1 = simpleConverter.convertToCouchbaseFilter(filterSub1, null, null); String querySub1 = toSelectSQL(expressionSub1); - assertEquals(querySub1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES LOWER(uid_) LIKE \"%test%\" END"); + assertEquals(expressionSub1.expression(), "ANY uid_ IN uid SATISFIES LOWER( uid_ ) LIKE %$uid_any% END"); + assertEquals(querySub1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES LOWER( uid_ ) LIKE \"%test%\" END"); Filter filterSub2 = Filter.createSubstringFilter(Filter.createLowercaseFilter("uid"), "a", new String[] { "test" }, null).multiValued(); ConvertedExpression expressionSub2 = simpleConverter.convertToCouchbaseFilter(filterSub2, null, null); String querySub2 = toSelectSQL(expressionSub2); - assertEquals(querySub2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES LOWER(uid_) LIKE \"a%test%\" END"); + assertEquals(expressionSub1.expression(), "ANY uid_ IN uid SATISFIES LOWER( uid_ ) LIKE %$uid_any% END"); + assertEquals(querySub2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES LOWER( uid_ ) LIKE \"a%test%\" END"); Filter filterSub3 = Filter.createSubstringFilter(Filter.createLowercaseFilter("uid"), null, new String[] { "test" }, "z").multiValued(); ConvertedExpression expressionSub3 = simpleConverter.convertToCouchbaseFilter(filterSub3, null, null); String querySub3 = toSelectSQL(expressionSub3); - assertEquals(querySub3, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES LOWER(uid_) LIKE \"%test%z\" END"); + assertEquals(expressionSub1.expression(), "ANY uid_ IN uid SATISFIES LOWER( uid_ ) LIKE %$uid_any% END"); + assertEquals(querySub3, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES LOWER( uid_ ) LIKE \"%test%z\" END"); Filter filterSub4 = Filter.createSubstringFilter(Filter.createLowercaseFilter("uid"), null, new String[] { "test" }, "z").multiValued(3); ConvertedExpression expressionSub4 = simpleConverter.convertToCouchbaseFilter(filterSub4, null, null); String querySub4 = toSelectSQL(expressionSub4); - assertEquals(querySub4, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES LOWER(uid_) LIKE \"%test%z\" END"); + assertEquals(expressionSub1.expression(), "ANY uid_ IN uid SATISFIES LOWER( uid_ ) LIKE %$uid_any% END"); + assertEquals(querySub4, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES LOWER( uid_ ) LIKE \"%test%z\" END"); } @Test @@ -367,7 +413,8 @@ public void checkLowerFilters() throws SearchException { ConvertedExpression expressionUserUid1 = simpleConverter.convertToCouchbaseFilter(userUidFilter1, null, null); String queryUserUid1 = toSelectSQL(expressionUserUid1); - assertEquals(queryUserUid1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE LOWER(uid) = \"test\""); + assertEquals(expressionUserUid1.expression(), "LOWER( uid ) = $uid"); + assertEquals(queryUserUid1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE LOWER( uid ) = \"test\""); } @Test @@ -377,8 +424,10 @@ public void checkMultivaluedLowerFilters() throws SearchException { ConvertedExpression expressionUserUid = simpleConverter.convertToCouchbaseFilter(userUidFilter, null, null); String queryUserUid = toSelectSQL(expressionUserUid); - assertEquals(queryUserUid, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ANY uid_ IN uid SATISFIES LOWER(uid_) = \"test\" END"); + assertEquals(expressionUserUid.expression(), "ANY uid_ IN uid SATISFIES LOWER( uid_ ) = $uid END"); + assertEquals(queryUserUid, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ANY uid_ IN uid SATISFIES LOWER( uid_ ) = \"test\" END"); } + @Test public void checkSinglevaluedLowerFilters() throws SearchException { Filter userUidFilter = Filter.createEqualityFilter(Filter.createLowercaseFilter("uid"), "test").multiValued(false); @@ -386,7 +435,8 @@ public void checkSinglevaluedLowerFilters() throws SearchException { ConvertedExpression expressionUserUid = simpleConverter.convertToCouchbaseFilter(userUidFilter, null, null); String queryUserUid = toSelectSQL(expressionUserUid); - assertEquals(queryUserUid, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE LOWER(uid) = \"test\""); + assertEquals(expressionUserUid.expression(), "LOWER( uid ) = $uid"); + assertEquals(queryUserUid, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE LOWER( uid ) = \"test\""); } @Test @@ -396,14 +446,16 @@ public void checkNotFilters() throws SearchException { ConvertedExpression expressionNot1 = simpleConverter.convertToCouchbaseFilter(notFilter1, null, null); String queryUserUid1 = toSelectSQL(expressionNot1); - assertEquals(queryUserUid1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( NOT age <= 23 )"); + assertEquals(expressionNot1.expression(), "NOT ( age <= $age )"); + assertEquals(queryUserUid1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE NOT ( age <= 23 )"); Filter notFilter2 = Filter.createNOTFilter(Filter.createANDFilter(Filter.createLessOrEqualFilter("age", 23), Filter.createGreaterOrEqualFilter("age", 25))); ConvertedExpression expressionNot2 = simpleConverter.convertToCouchbaseFilter(notFilter2, null, null); String queryUserUid2 = toSelectSQL(expressionNot2); - assertEquals(queryUserUid2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( NOT ( age <= 23 AND age >= 25 ) )"); + assertEquals(expressionNot2.expression(), "NOT ( ( age <= $age AND age >= $_age_0 ) )"); + assertEquals(queryUserUid2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE NOT ( ( age <= 23 AND age >= 25 ) )"); } @Test @@ -415,7 +467,8 @@ public void checkAndFilters() throws SearchException { ConvertedExpression expressionAnd1 = simpleConverter.convertToCouchbaseFilter(filterAnd1, null, null); String queryAnd1 = toSelectSQL(expressionAnd1); - assertEquals(queryAnd1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( mail IS NOT MISSING AND ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND age <= 23 )"); + assertEquals(expressionAnd1.expression(), "( mail IS NOT MISSING AND ( ( uid = $uid ) OR ( $uid IN uid ) ) AND age <= $age )"); + assertEquals(queryAnd1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( mail IS NOT MISSING AND ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) AND age <= 23 )"); } @Test @@ -427,7 +480,8 @@ public void checkOrFilters() throws SearchException { ConvertedExpression expressionAnd1 = simpleConverter.convertToCouchbaseFilter(filterOr1, null, null); String queryAnd1 = toSelectSQL(expressionAnd1); - assertEquals(queryAnd1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( mail IS NOT MISSING OR ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) OR age <= 23 )"); + assertEquals(expressionAnd1.expression(), "( mail IS NOT MISSING OR ( ( uid = $uid ) OR ( $uid IN uid ) ) OR age <= $age )"); + assertEquals(queryAnd1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( mail IS NOT MISSING OR ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) OR age <= 23 )"); } @Test @@ -440,13 +494,15 @@ public void checkOrJoinFilters() throws SearchException { ConvertedExpression expressionOr1 = simpleConverter.convertToCouchbaseFilter(filterOr1, null, null); String queryOr1 = toSelectSQL(expressionOr1); - assertEquals(queryOr1, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( uid IN [\"test\",\"test2\",\"test3\"] )"); + assertEquals(expressionOr1.expression(), "uid IN [ $uid, $_uid_0, $_uid_1 ]"); + assertEquals(queryOr1, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE uid IN [ \"test\", \"test2\", \"test3\" ]"); Filter filterOr2 = Filter.createORFilter(filterEq1, filterEq2, filterEq3); ConvertedExpression expressionOr2 = simpleConverter.convertToCouchbaseFilter(filterOr2, null, null); String queryOr2 = toSelectSQL(expressionOr2); - assertEquals(queryOr2, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) OR ( ( uid = \"test2\" ) OR ( \"test2\" IN uid ) ) OR ( ( uid = \"test3\" ) OR ( \"test3\" IN uid ) ) )"); + assertEquals(expressionOr2.expression(), "( ( ( uid = $uid ) OR ( $uid IN uid ) ) OR ( ( uid = $_uid_0 ) OR ( $_uid_0 IN uid ) ) OR ( ( uid = $_uid_1 ) OR ( $_uid_1 IN uid ) ) )"); + assertEquals(queryOr2, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( ( uid = \"test\" ) OR ( \"test\" IN uid ) ) OR ( ( uid = \"test2\" ) OR ( \"test2\" IN uid ) ) OR ( ( uid = \"test3\" ) OR ( \"test3\" IN uid ) ) )"); } @Test @@ -470,13 +526,35 @@ public void checkOrWithLowerCaseFilter() throws SearchException { ConvertedExpression expression = simpleConverter.convertToCouchbaseFilter(filter, null, null); String query = toSelectSQL(expression); - assertEquals(query, "SELECT jans_doc.* FROM `jans` AS jans_doc WHERE ( ( LOWER(description) LIKE \"%test_value%\" OR LOWER(displayName) LIKE \"%test_value%\" ) AND ( ( jansScrTyp = \"person_authentication\" ) OR ( \"person_authentication\" IN jansScrTyp ) ) )"); + assertEquals(expression.expression(), "( ( LOWER( description ) LIKE %$description_any% OR LOWER( displayName ) LIKE %$displayName_any% ) AND ( ( gluuScrTyp = $gluuScrTyp ) OR ( $gluuScrTyp IN gluuScrTyp ) ) )"); + assertEquals(query, "SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE ( ( LOWER( description ) LIKE \"%test_value%\" OR LOWER( displayName ) LIKE \"%test_value%\" ) AND ( ( gluuScrTyp = \"person_authentication\" ) OR ( \"person_authentication\" IN gluuScrTyp ) ) )"); } private String toSelectSQL(ConvertedExpression convertedExpression) { - GroupByPath select = Select.select("jans_doc.*").from(Expression.i("jans")).as("jans_doc").where(convertedExpression.expression()); + String select = String.format("SELECT gluu_doc.* FROM `gluu` AS gluu_doc WHERE %s", convertedExpression.expression()); + + // Substitute parameters for test + JsonObject params = convertedExpression.getQueryParameters(); + for (String name : params.getNames()) { + Object value = params.get(name); + + Object replaceValue = value; + if (value instanceof String) { + replaceValue = "\"" + value + "\""; + } + + String searchName = "\\$" + name; + int subIndex = select.indexOf("%$" + name + "%"); + if (subIndex != -1) { + searchName = "%" + searchName + "%"; + replaceValue = "\"%" + value + "%\""; + } + select = select.replaceAll(searchName, replaceValue.toString()); + } + + select = select.replaceAll("\"\"%", "%").replaceAll("%\"\"", "%"); - return select.toString(); + return select; } private static Date getUtcDateFromMillis(long millis) { diff --git a/jans-orm/filter/src/main/java/io/jans/orm/search/filter/FilterProcessor.java b/jans-orm/filter/src/main/java/io/jans/orm/search/filter/FilterProcessor.java index ee172020130..1c6d8a9b752 100644 --- a/jans-orm/filter/src/main/java/io/jans/orm/search/filter/FilterProcessor.java +++ b/jans-orm/filter/src/main/java/io/jans/orm/search/filter/FilterProcessor.java @@ -1,6 +1,6 @@ package io.jans.orm.search.filter; /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2021, Janssen Project */ diff --git a/jans-orm/hybrid/src/main/java/io/jans/orm/hybrid/impl/HybridEntryManager.java b/jans-orm/hybrid/src/main/java/io/jans/orm/hybrid/impl/HybridEntryManager.java index b5b9c180233..f0ea5bb1034 100644 --- a/jans-orm/hybrid/src/main/java/io/jans/orm/hybrid/impl/HybridEntryManager.java +++ b/jans-orm/hybrid/src/main/java/io/jans/orm/hybrid/impl/HybridEntryManager.java @@ -14,6 +14,9 @@ import java.util.Map.Entry; import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.jans.orm.PersistenceEntryManager; import io.jans.orm.event.DeleteNotifier; import io.jans.orm.exception.KeyConversionException; @@ -32,15 +35,13 @@ import io.jans.orm.search.filter.Filter; import io.jans.orm.util.ArrayHelper; import io.jans.orm.util.StringHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Hybrid Entry Manager * * @author Yuriy Movchan Date: 07/10/2019 */ -public class HybridEntryManager extends BaseEntryManager implements Serializable { +public class HybridEntryManager extends BaseEntryManager implements Serializable { private static final long serialVersionUID = -1544664410881103105L; @@ -190,7 +191,7 @@ public List exportEntry(String dn) { } @Override - public List exportEntry(String dn, String objectClass) { + public List exportEntry(String dn, String objectClass) { PersistenceEntryManager persistenceEntryManager = getEntryManagerForDn(dn); return persistenceEntryManager.exportEntry(dn, objectClass); } @@ -383,7 +384,7 @@ public void remove(Object entry) { @Override public void removeByDn(String primaryKey, String[] objectClasses) { PersistenceEntryManager persistenceEntryManager = getEntryManagerForDn(primaryKey); - persistenceEntryManager.remove(primaryKey); + persistenceEntryManager.removeByDn(primaryKey, objectClasses); } @Override @@ -406,7 +407,7 @@ public void removeDeleteSubscriber(DeleteNotifier subscriber) { @Override public void removeRecursivelyFromDn(String dn, String[] objectClasses) { PersistenceEntryManager persistenceEntryManager = getEntryManagerForDn(dn); - persistenceEntryManager.removeRecursively(dn); + persistenceEntryManager.removeRecursivelyFromDn(dn, objectClasses); } //************************************************************************* @@ -454,4 +455,5 @@ protected Object getNativeDateAttributeValue(Date dateValue) { throw new UnsupportedOperationException("Method not implemented."); } + } diff --git a/jans-orm/hybrid/src/main/java/io/jans/orm/hybrid/impl/HybridPersistenceOperationService.java b/jans-orm/hybrid/src/main/java/io/jans/orm/hybrid/impl/HybridPersistenceOperationService.java index e281ca205d0..30ea3cf991b 100644 --- a/jans-orm/hybrid/src/main/java/io/jans/orm/hybrid/impl/HybridPersistenceOperationService.java +++ b/jans-orm/hybrid/src/main/java/io/jans/orm/hybrid/impl/HybridPersistenceOperationService.java @@ -9,9 +9,9 @@ import java.util.List; import io.jans.orm.exception.AuthenticationException; -import io.jans.orm.exception.extension.PersistenceExtension; import io.jans.orm.exception.operation.ConnectionException; import io.jans.orm.exception.operation.SearchException; +import io.jans.orm.extension.PersistenceExtension; import io.jans.orm.operation.PersistenceOperationService; /** diff --git a/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/LdapUpateMissingEntrySample.java b/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/LdapUpateMissingEntrySample.java index 0d1fcfcb6c6..e195bf6673a 100644 --- a/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/LdapUpateMissingEntrySample.java +++ b/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/LdapUpateMissingEntrySample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/LdapUserFieldRemove.java b/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/LdapUserFieldRemove.java index c5b28226d11..f96f5a5bb91 100644 --- a/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/LdapUserFieldRemove.java +++ b/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/LdapUserFieldRemove.java @@ -35,7 +35,7 @@ public static void main(String[] args) { // Find all users which have specified object classes defined in SimpleUser Filter filter = Filter.createEqualityFilter("uid", "admin"); - List users = ldapEntryManager.findEntries("o=gluu", SimpleUser.class, filter); + List users = ldapEntryManager.findEntries("o=jans", SimpleUser.class, filter); if (users.size() == 0) { LOG.error("Failed to find user by filter: " + filter); return; @@ -45,7 +45,7 @@ public static void main(String[] args) { // Add dummy oxEnrollmentCode attribute SimpleUser user = users.get(0); - user.setAttribute("oxEnrollmentCode", "test-enrollment-code", false); + user.setAttribute("jansEnrollmentCode", "test-enrollment-code", false); ldapEntryManager.merge(user); // Reload user by DN @@ -56,7 +56,7 @@ public static void main(String[] args) { } // Clean dummy oxEnrollmentCode attribute - userWithEnrollment.setAttribute("oxEnrollmentCode", "", false); + userWithEnrollment.setAttribute("jansEnrollmentCode", "", false); ldapEntryManager.merge(userWithEnrollment); // Reload user by DN @@ -66,8 +66,8 @@ public static void main(String[] args) { return; } - String enrollmentCode = userWithoutEnrollment.getAttribute("oxEnrollmentCode"); - LOG.debug("oxEnrollmentCode: " + enrollmentCode); + String enrollmentCode = userWithoutEnrollment.getAttribute("jansEnrollmentCode"); + LOG.debug("jansEnrollmentCode: " + enrollmentCode); } } diff --git a/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/model/SimpleSessionState.java b/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/model/SimpleSessionState.java index 481fd32c04a..41301e68eae 100644 --- a/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/model/SimpleSessionState.java +++ b/jans-orm/ldap-sample/src/main/java/io/jans/orm/ldap/model/SimpleSessionState.java @@ -45,7 +45,7 @@ public class SimpleSessionState implements Serializable { @AttributeName(name = "authnTime") private Date authenticationTime; - @AttributeName(name = "oxAuthSessionState") + @AttributeName(name = "jansAuthSessionState") private Boolean permissionGranted; @AttributeName(name = "jansAsJwt") diff --git a/jans-orm/ldap/src/main/java/io/jans/orm/ldap/impl/LdapEntryManager.java b/jans-orm/ldap/src/main/java/io/jans/orm/ldap/impl/LdapEntryManager.java index 4b17465395e..45ebd5196ea 100644 --- a/jans-orm/ldap/src/main/java/io/jans/orm/ldap/impl/LdapEntryManager.java +++ b/jans-orm/ldap/src/main/java/io/jans/orm/ldap/impl/LdapEntryManager.java @@ -6,8 +6,35 @@ package io.jans.orm.ldap.impl; -import com.unboundid.ldap.sdk.*; +import java.io.Serializable; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.codec.binary.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.unboundid.ldap.sdk.Attribute; +import com.unboundid.ldap.sdk.LDAPConnection; +import com.unboundid.ldap.sdk.Modification; +import com.unboundid.ldap.sdk.ModificationType; +import com.unboundid.ldap.sdk.ResultCode; +import com.unboundid.ldap.sdk.SearchResult; +import com.unboundid.ldap.sdk.SearchResultEntry; import com.unboundid.util.StaticUtils; + import io.jans.orm.PersistenceEntryManager; import io.jans.orm.event.DeleteNotifier; import io.jans.orm.exception.AuthenticationException; @@ -20,31 +47,28 @@ import io.jans.orm.impl.BaseEntryManager; import io.jans.orm.ldap.operation.LdapOperationService; import io.jans.orm.ldap.operation.impl.LdapOperationServiceImpl; -import io.jans.orm.model.*; +import io.jans.orm.model.AttributeData; +import io.jans.orm.model.AttributeDataModification; +import io.jans.orm.model.BatchOperation; +import io.jans.orm.model.DefaultBatchOperation; +import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; -import io.jans.orm.model.AttributeDataModification.AttributeModificationType; +import io.jans.orm.model.SortOrder; import io.jans.orm.model.base.LocalizedString; +import io.jans.orm.model.AttributeDataModification.AttributeModificationType; import io.jans.orm.reflect.property.PropertyAnnotation; import io.jans.orm.search.filter.Filter; import io.jans.orm.util.ArrayHelper; import io.jans.orm.util.StringHelper; -import org.apache.commons.codec.binary.Base64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Serializable; -import java.text.ParseException; -import java.util.*; import static io.jans.orm.model.base.LocalizedString.*; /** * LDAP Entry Manager * - * @author Yuriy Movchan - * @version April 25, 2022 + * @author Yuriy Movchan Date: 10.07.2010 */ -public class LdapEntryManager extends BaseEntryManager implements Serializable { +public class LdapEntryManager extends BaseEntryManager implements Serializable { private static final long serialVersionUID = -2544614410981223105L; @@ -136,7 +160,7 @@ public void remove(Object entry) { LOG.debug(String.format("LDAP entry to remove: %s", dnValue.toString())); - remove(dnValue.toString()); + remove(dnValue.toString(), entryClass); } @Override @@ -339,14 +363,14 @@ public void removeRecursivelyFromDn(String dn, String[] objectClasses) { subscriber.onAfterRemove(dn, objectClasses); } } else { - removeSubtreeThroughIteration(dn); + removeSubtreeThroughIteration(dn, objectClasses); } } catch (Exception ex) { throw new EntryDeleteException(String.format("Failed to remove entry: %s", dn), ex); } } - private void removeSubtreeThroughIteration(String dn) { + private void removeSubtreeThroughIteration(String dn, String[] objectClasses) { SearchScope scope = SearchScope.SUB; SearchResult searchResult = null; @@ -369,7 +393,7 @@ private void removeSubtreeThroughIteration(String dn) { Collections.sort(removeEntriesDn, LINE_LENGHT_COMPARATOR); for (String removeEntryDn : removeEntriesDn) { - remove(removeEntryDn); + removeByDn(removeEntryDn, objectClasses); } } @@ -895,7 +919,7 @@ public List exportEntry(String dn) { } @Override - public List exportEntry(String dn, String objectClass) { + public List exportEntry(String dn, String objectClass) { return exportEntry(dn); } @@ -1001,11 +1025,13 @@ public DeleteBatchOperation(LdapEntryManager ldapEntryManager) { public void performAction(List entries) { for (T entity : entries) { try { - String dnValue = ldapEntryManager.getDNValue(entity).toString(); + Class entryClass = entity.getClass(); + + String dnValue = ldapEntryManager.getDNValue(entity, entryClass).toString(); if (ldapEntryManager.hasBranchesSupport(dnValue)) { - ldapEntryManager.removeRecursively(dnValue); + ldapEntryManager.removeRecursively(dnValue, entryClass); } else { - ldapEntryManager.remove(dnValue); + ldapEntryManager.remove(dnValue, entryClass); } LOG.trace("Removed {}", dnValue); } catch (Exception e) { diff --git a/jans-orm/ldap/src/main/java/io/jans/orm/ldap/model/MailUniquenessConfiguration.java b/jans-orm/ldap/src/main/java/io/jans/orm/ldap/model/MailUniquenessConfiguration.java new file mode 100644 index 00000000000..bb92e21d9d1 --- /dev/null +++ b/jans-orm/ldap/src/main/java/io/jans/orm/ldap/model/MailUniquenessConfiguration.java @@ -0,0 +1,48 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.orm.ldap.model; + +import java.io.Serializable; + +import io.jans.orm.annotation.AttributeName; +import io.jans.orm.annotation.DN; +import io.jans.orm.annotation.DataEntry; +import io.jans.orm.annotation.ObjectClass; + +/** + * @author Yuriy Movchan + * Date: 12/17/2019 + */ +@DataEntry(configurationDefinition = true) +@ObjectClass(value = "ds-cfg-plugin") +public class MailUniquenessConfiguration implements Serializable { + + private static final long serialVersionUID = -1634191420188575733L; + + @DN + private String dn; + + @AttributeName(name = "ds-cfg-enabled") + private boolean enabled; + + public String getDn() { + return dn; + } + + public void setDn(String dn) { + this.dn = dn; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + +} diff --git a/jans-orm/ldap/src/main/java/io/jans/orm/ldap/operation/impl/LdapConnectionProvider.java b/jans-orm/ldap/src/main/java/io/jans/orm/ldap/operation/impl/LdapConnectionProvider.java index f86ccf7e704..b60f7a259f4 100644 --- a/jans-orm/ldap/src/main/java/io/jans/orm/ldap/operation/impl/LdapConnectionProvider.java +++ b/jans-orm/ldap/src/main/java/io/jans/orm/ldap/operation/impl/LdapConnectionProvider.java @@ -11,10 +11,6 @@ import java.util.Arrays; import java.util.Properties; -import io.jans.orm.exception.operation.ConfigurationException; -import io.jans.orm.operation.auth.PasswordEncryptionMethod; -import io.jans.orm.util.ArrayHelper; -import io.jans.orm.util.StringHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +27,12 @@ import com.unboundid.util.ssl.TrustAllTrustManager; import com.unboundid.util.ssl.TrustStoreTrustManager; +import io.jans.orm.exception.operation.ConfigurationException; +import io.jans.orm.operation.auth.PasswordEncryptionMethod; +import io.jans.orm.util.ArrayHelper; +import io.jans.orm.util.CertUtils; +import io.jans.orm.util.StringHelper; + /** * @author Yuriy Movchan */ @@ -79,18 +81,17 @@ public void create(Properties props) { public void create() { try { init(props); - } catch (LDAPException ex) { - creationResultCode = ex.getResultCode(); + } catch (Exception ex) { + if (ex instanceof LDAPException) { + creationResultCode = ((LDAPException) ex).getResultCode(); + } Properties clonedProperties = (Properties) props.clone(); if (clonedProperties.getProperty("bindPassword") != null) { clonedProperties.setProperty("bindPassword", "REDACTED"); } - LOG.error("Failed to create connection pool with properties: " + clonedProperties, ex); - } catch (Exception ex) { - Properties clonedProperties = (Properties) props.clone(); - if (clonedProperties.getProperty("bindPassword") != null) { - clonedProperties.setProperty("bindPassword", "REDACTED"); + if (clonedProperties.getProperty("ssl.trustStorePin") != null) { + clonedProperties.setProperty("ssl.trustStorePin", "REDACTED"); } LOG.error("Failed to create connection pool with properties: " + clonedProperties, ex); } @@ -133,24 +134,28 @@ protected void init(Properties props) throws NumberFormatException, LDAPExceptio LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions(); connectionOptions.setConnectTimeoutMillis(100 * 1000); - connectionOptions.setAutoReconnect(true); + //connectionOptions.setAutoReconnect(true); this.useSSL = Boolean.valueOf(props.getProperty("useSSL")).booleanValue(); SSLUtil sslUtil = null; FailoverServerSet failoverSet; if (this.useSSL) { - String sslTrustStoreFile = props.getProperty("ssl.trustStoreFile"); - String sslTrustStorePin = props.getProperty("ssl.trustStorePin"); - String sslTrustStoreFormat = props.getProperty("ssl.trustStoreFormat"); + String trustStoreFile = props.getProperty("ssl.trustStoreFile"); + String trustStorePin = props.getProperty("ssl.trustStorePin"); + String trustStoreType = props.getProperty("ssl.trustStoreFormat"); - if (StringHelper.isEmpty(sslTrustStoreFile) && StringHelper.isEmpty(sslTrustStorePin)) { + if (CertUtils.isFips()) { + sslUtil = new SSLUtil(CertUtils.getTrustManagers(trustStoreFile, trustStorePin, trustStoreType)); + } else { + if (StringHelper.isEmpty(trustStoreFile) && StringHelper.isEmpty(trustStorePin)) { sslUtil = new SSLUtil(new TrustAllTrustManager()); } else { - TrustStoreTrustManager trustStoreTrustManager = new TrustStoreTrustManager(sslTrustStoreFile, sslTrustStorePin.toCharArray(), - sslTrustStoreFormat, true); + TrustStoreTrustManager trustStoreTrustManager = new TrustStoreTrustManager(trustStoreFile, trustStorePin.toCharArray(), + trustStoreType, true); sslUtil = new SSLUtil(trustStoreTrustManager); } + } failoverSet = new FailoverServerSet(this.addresses, this.ports, sslUtil.createSSLSocketFactory(SSL_PROTOCOLS[0]), connectionOptions); } else { diff --git a/jans-orm/ldap/src/main/java/io/jans/orm/ldap/operation/impl/LdapOperationServiceImpl.java b/jans-orm/ldap/src/main/java/io/jans/orm/ldap/operation/impl/LdapOperationServiceImpl.java index 4a585a07f68..9b6c1bbd6cc 100644 --- a/jans-orm/ldap/src/main/java/io/jans/orm/ldap/operation/impl/LdapOperationServiceImpl.java +++ b/jans-orm/ldap/src/main/java/io/jans/orm/ldap/operation/impl/LdapOperationServiceImpl.java @@ -26,10 +26,10 @@ import io.jans.orm.exception.AuthenticationException; import io.jans.orm.exception.MappingException; -import io.jans.orm.exception.extension.PersistenceExtension; import io.jans.orm.exception.operation.ConnectionException; import io.jans.orm.exception.operation.DuplicateEntryException; import io.jans.orm.exception.operation.SearchException; +import io.jans.orm.extension.PersistenceExtension; import io.jans.orm.ldap.operation.LdapOperationService; import io.jans.orm.model.BatchOperation; import io.jans.orm.model.PagedResult; diff --git a/jans-orm/model/pom.xml b/jans-orm/model/pom.xml index 7d8b94168f3..63629b1e969 100644 --- a/jans-orm/model/pom.xml +++ b/jans-orm/model/pom.xml @@ -33,6 +33,6 @@ testng test - + \ No newline at end of file diff --git a/jans-orm/model/src/main/java/io/jans/orm/model/base/CustomObjectAttribute.java b/jans-orm/model/src/main/java/io/jans/orm/model/base/CustomObjectAttribute.java index 1baaf3fd2fa..f3f13484786 100644 --- a/jans-orm/model/src/main/java/io/jans/orm/model/base/CustomObjectAttribute.java +++ b/jans-orm/model/src/main/java/io/jans/orm/model/base/CustomObjectAttribute.java @@ -92,12 +92,9 @@ public String getDisplayValue() { return values.get(0).toString(); } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < values.size(); i++) { - if (i > 0) { - sb.append(", "); - } - sb.append(values.get(i).toString()); + StringBuilder sb = new StringBuilder(values.get(0).toString()); + for (int i = 1; i < values.size(); i++) { + sb.append(", ").append(values.get(i).toString()); } return sb.toString(); diff --git a/jans-orm/model/src/main/java/io/jans/orm/model/base/LocalizedString.java b/jans-orm/model/src/main/java/io/jans/orm/model/base/LocalizedString.java index 795682fcdc3..f392f1f0c2e 100644 --- a/jans-orm/model/src/main/java/io/jans/orm/model/base/LocalizedString.java +++ b/jans-orm/model/src/main/java/io/jans/orm/model/base/LocalizedString.java @@ -6,9 +6,11 @@ package io.jans.orm.model.base; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; +import io.jans.orm.util.StringHelper; + import java.io.Serializable; import java.util.*; import java.util.function.BiFunction; diff --git a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2Data.java b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2Data.java index a3a6a4057f4..cd27990b29e 100644 --- a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2Data.java +++ b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2Data.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2Entry.java b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2Entry.java index 95e7a72ced2..2c289298693 100644 --- a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2Entry.java +++ b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2Entry.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationData.java b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationData.java index 7258bb43e91..11b0a55edaf 100644 --- a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationData.java +++ b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationData.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationEntry.java b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationEntry.java index 5f7e0b22eb7..c1a91cc056c 100644 --- a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationEntry.java +++ b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationEntry.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationStatus.java b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationStatus.java index 5464e4240ba..a78268dd460 100644 --- a/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationStatus.java +++ b/jans-orm/model/src/main/java/io/jans/orm/model/fido2/Fido2RegistrationStatus.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/LoggingHelper.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/LoggingHelper.java index 69ec9dbcd93..1709729fd6e 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/LoggingHelper.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/LoggingHelper.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerBatchJobSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerBatchJobSample.java index 54cdb20ce2a..1afc5dab5bb 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerBatchJobSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerBatchJobSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerConcurentSessionUpdateSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerConcurentSessionUpdateSample.java index 076090b8556..7704523bfad 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerConcurentSessionUpdateSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerConcurentSessionUpdateSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomMultiValuedTypesSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomMultiValuedTypesSample.java index 2cd18b176d3..92b57231294 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomMultiValuedTypesSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomMultiValuedTypesSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomObjectAttributesSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomObjectAttributesSample.java index 980aab58638..2af1b45a252 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomObjectAttributesSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomObjectAttributesSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomStringAttributesSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomStringAttributesSample.java index c298344aac2..7ac484b5645 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomStringAttributesSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerCustomStringAttributesSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerDeleteSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerDeleteSample.java index 969f0bf4d78..031e63a49f2 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerDeleteSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerDeleteSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerIdpAuthConfSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerIdpAuthConfSample.java index 9d41a38007f..eafb655b955 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerIdpAuthConfSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerIdpAuthConfSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerSample.java index 6440b116aa2..f17d47014b6 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUmaResourceSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUmaResourceSample.java index 0e59c417afd..eec58eb0969 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUmaResourceSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUmaResourceSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -34,7 +34,7 @@ public static void main(String[] args) { // Create SQL entry manager SpannerEntryManager sqlEntryManager = sqlEntryManagerSample.createSpannerEntryManager(); - final Filter filter = Filter.createEqualityFilter("jansAssociatedClnt", "inum=AB77-1A2B,ou=clients,o=jans"); + final Filter filter = Filter.createEqualityFilter("jansAssociatedClnt", "inum=AB77-1A2B,ou=clients,o=jans").multiValued(); List umaResource = sqlEntryManager.findEntries("ou=resources,ou=uma,o=jans", UmaResource.class, filter); LOG.info("Found umaResources: " + umaResource); diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUpateCacheEntrySample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUpateCacheEntrySample.java index a2d82760be5..4f94cd2c561 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUpateCacheEntrySample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUpateCacheEntrySample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -36,7 +36,7 @@ public static void main(String[] args) { SpannerEntryManager sqlEntryManager = sqlEntryManagerSample.createSpannerEntryManager(); String key = UUID.randomUUID().toString(); - final String cacheDn = String.format("uuid=%s,%s", key, "ou=cache,o=gluu"); + final String cacheDn = String.format("uuid=%s,%s", key, "ou=cache,o=jans"); int expirationInSeconds = 60; Calendar expirationDate = Calendar.getInstance(); diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUpateMissingEntrySample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUpateMissingEntrySample.java index 5d475bccd1f..255964a9b97 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUpateMissingEntrySample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUpateMissingEntrySample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUserSearchSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUserSearchSample.java index 6bda08fc40a..3d4dbe4ec2a 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUserSearchSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/SpannerUserSearchSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleAttribute.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleAttribute.java index b58542da929..ead5046c825 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleAttribute.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleAttribute.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleCacheEntry.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleCacheEntry.java index b9f781a6f7c..fa2cf108f5e 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleCacheEntry.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleCacheEntry.java @@ -1,14 +1,15 @@ -package io.jans.orm.cloud.spanner.model; - -import java.io.Serializable; -import java.util.Date; - /* * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ +package io.jans.orm.cloud.spanner.model; + +import java.io.Serializable; +import java.util.Date; + import io.jans.orm.annotation.AttributeName; +import io.jans.orm.annotation.DN; import io.jans.orm.annotation.DataEntry; import io.jans.orm.annotation.Expiration; import io.jans.orm.annotation.ObjectClass; @@ -21,6 +22,8 @@ public class SimpleCacheEntry extends DeletableEntity implements Serializable, D private static final long serialVersionUID = 3360900373193184522L; + @DN + private String dn; @Expiration private Integer ttl; @AttributeName(name = "uuid") @@ -30,6 +33,14 @@ public class SimpleCacheEntry extends DeletableEntity implements Serializable, D @AttributeName(name = "dat") private String data; + public String getDn() { + return dn; + } + + public void setDn(String dn) { + this.dn = dn; + } + public Integer getTtl() { return ttl; } @@ -64,7 +75,7 @@ public void setData(String data) { @Override public String toString() { - return "NativePersistenceCacheEntity [dn=" + getDn() + ", ttl=" + ttl + ", id=" + id + ", creationDate=" + creationDate + ", data=" + return "NativePersistenceCacheEntity [dn=" + dn + ", ttl=" + ttl + ", id=" + id + ", creationDate=" + creationDate + ", data=" + data + "]"; } } diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleClient.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleClient.java index 72b64371ca3..533ae9cf7ac 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleClient.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleClient.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleCustomStringUser.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleCustomStringUser.java index e5c275bc6b7..f24098223ec 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleCustomStringUser.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleCustomStringUser.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleGrant.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleGrant.java index 913b572d8de..ec3577ffa22 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleGrant.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleGrant.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleSession.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleSession.java index 7916a9b7b58..f4057f8472a 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleSession.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleSession.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleSessionState.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleSessionState.java index 1dbfcfbe187..631a9e262cb 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleSessionState.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleSessionState.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleToken.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleToken.java index a6592a72dca..ee97b4db7b2 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleToken.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleToken.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleUser.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleUser.java index 9aec95c77e8..11999dd1d5f 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleUser.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/SimpleUser.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/UmaResource.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/UmaResource.java index 80275972a80..24d84169ab4 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/UmaResource.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/UmaResource.java @@ -12,6 +12,7 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.common.collect.Lists; import io.jans.orm.annotation.AttributeName; import io.jans.orm.annotation.DN; @@ -137,7 +138,7 @@ public void setId(String id) { public List getClients() { if (clients == null) { - clients = new ArrayList<>(); + clients = new ArrayList(); } return clients; } @@ -171,7 +172,7 @@ public void setIconUri(String iconUri) { } public List getScopes() { - if (scopes == null) scopes = new ArrayList<>(); + if (scopes == null) scopes = Lists.newArrayList(); return scopes; } diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/UserRole.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/UserRole.java index cfd953e60b2..f27823d6314 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/UserRole.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/model/UserRole.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/persistence/SpannerEntryManagerSample.java b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/persistence/SpannerEntryManagerSample.java index b279a18e111..9dce22ff645 100644 --- a/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/persistence/SpannerEntryManagerSample.java +++ b/jans-orm/spanner-sample/src/main/java/io/jans/orm/cloud/spanner/persistence/SpannerEntryManagerSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/operation/impl/test/SpannerMultiValuedDataPopulatorTest.java b/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/operation/impl/test/SpannerMultiValuedDataPopulatorTest.java index eb58ed25018..3d7d518ffe0 100644 --- a/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/operation/impl/test/SpannerMultiValuedDataPopulatorTest.java +++ b/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/operation/impl/test/SpannerMultiValuedDataPopulatorTest.java @@ -16,7 +16,7 @@ public class SpannerMultiValuedDataPopulatorTest { public static void main(String[] args) { Properties props = new Properties(); - props.setProperty("connection.project", "gluu-server-184620"); + props.setProperty("connection.project", "jans-server-184620"); props.setProperty("connection.instance", "movchan"); props.setProperty("connection.database", "test_interleave"); props.setProperty("connection.client.create-max-wait-time-millis", "15"); diff --git a/jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/ManualSpannerEntryManagerTest.java b/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/ManualSpannerEntryManagerTest.java similarity index 98% rename from jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/ManualSpannerEntryManagerTest.java rename to jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/ManualSpannerEntryManagerTest.java index 641e71ad4d4..07fcbdab5b2 100644 --- a/jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/ManualSpannerEntryManagerTest.java +++ b/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/ManualSpannerEntryManagerTest.java @@ -1,10 +1,10 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ -package io.jans.cloud.spanner.test; +package io.jans.orm.cloud.spanner.test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; diff --git a/jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/SessionId.java b/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/SessionId.java similarity index 97% rename from jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/SessionId.java rename to jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/SessionId.java index a32c05916cd..a41792e79c6 100644 --- a/jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/SessionId.java +++ b/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/SessionId.java @@ -1,10 +1,10 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ -package io.jans.cloud.spanner.test; +package io.jans.orm.cloud.spanner.test; import java.io.Serializable; import java.util.ArrayList; diff --git a/jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/SessionIdState.java b/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/SessionIdState.java similarity index 86% rename from jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/SessionIdState.java rename to jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/SessionIdState.java index 5b59e8f86fe..e9cafc1876f 100644 --- a/jans-orm/spanner-sample/src/test/java/io/jans/cloud/spanner/test/SessionIdState.java +++ b/jans-orm/spanner-sample/src/test/java/io/jans/orm/cloud/spanner/test/SessionIdState.java @@ -1,10 +1,10 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ -package io.jans.cloud.spanner.test; +package io.jans.orm.cloud.spanner.test; import java.util.HashMap; import java.util.Map; diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerBatchOperationWraper.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerBatchOperationWraper.java index 7f6ddd3aee9..4fec736dbfa 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerBatchOperationWraper.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerBatchOperationWraper.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerEntryManager.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerEntryManager.java index ac67a5fff23..3af1532dd9c 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerEntryManager.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerEntryManager.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -16,8 +16,6 @@ import java.util.Map; import java.util.Set; -import jakarta.inject.Inject; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,25 +35,26 @@ import io.jans.orm.impl.model.ParsedKey; import io.jans.orm.model.AttributeData; import io.jans.orm.model.AttributeDataModification; -import io.jans.orm.model.AttributeDataModification.AttributeModificationType; import io.jans.orm.model.BatchOperation; import io.jans.orm.model.EntryData; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; import io.jans.orm.model.Sort; import io.jans.orm.model.SortOrder; +import io.jans.orm.model.AttributeDataModification.AttributeModificationType; import io.jans.orm.reflect.property.PropertyAnnotation; import io.jans.orm.search.filter.Filter; import io.jans.orm.search.filter.FilterProcessor; import io.jans.orm.util.ArrayHelper; import io.jans.orm.util.StringHelper; +import jakarta.inject.Inject; /** * SQL Entry Manager * * @author Yuriy Movchan Date: 01/12/2020 */ -public class SpannerEntryManager extends BaseEntryManager implements Serializable { +public class SpannerEntryManager extends BaseEntryManager implements Serializable { private static final long serialVersionUID = 2127241817126412574L; @@ -117,7 +116,7 @@ public Void merge(Object entry) { @Override protected List buildAttributesListForUpdate(Object entry, String[] objectClasses, List propertiesAnnotations) { List attributesList = getAttributesList(entry, propertiesAnnotations, false); - Set childAttributes = getOperationService().getTabeChildAttributes(objectClasses[0]); + Set childAttributes = getOperationService().getTabeChildAttributes(getBaseObjectClass(objectClasses)); if (childAttributes != null) { attributesList.addAll(childAttributes); } @@ -151,7 +150,7 @@ protected void updateMergeChanges(String baseDn, T entry, boolean isConfigur } // We need to check only first element of each array because objectCLass in SQL is single value attribute - if (!StringHelper.equals(objectClassesFromDb[0], objectClasses[0])) { + if (!StringHelper.equals(getBaseObjectClass(entryClass, objectClassesFromDb), getBaseObjectClass(entryClass, objectClasses))) { throw new UnsupportedOperationException(String.format("It's not possible to change objectClasses of already persisted entry! Entry is invalid: '%s'", entry)); } } @@ -215,7 +214,7 @@ protected void persist(String dn, String[] objectClasses, List at resultAttributes.add(new AttributeData(SpannerOperationService.DN, dn)); resultAttributes.add(new AttributeData(SpannerOperationService.DOC_ID, parsedKey.getKey())); - boolean result = getOperationService().addEntry(parsedKey.getKey(), objectClasses[0], resultAttributes); + boolean result = getOperationService().addEntry(parsedKey.getKey(), getBaseObjectClass(objectClasses), resultAttributes); if (!result) { throw new EntryPersistenceException(String.format("Failed to persist entry: '%s'", dn)); } @@ -272,7 +271,7 @@ public void merge(String dn, String[] objectClasses, List 0) { - boolean result = getOperationService().updateEntry(toSQLKey(dn).getKey(), objectClasses[0], modifications); + boolean result = getOperationService().updateEntry(toSQLKey(dn).getKey(), getBaseObjectClass(objectClasses), modifications); if (!result) { throw new EntryPersistenceException(String.format("Failed to update entry: '%s'", dn)); } @@ -283,7 +282,7 @@ public void merge(String dn, String[] objectClasses, List void removeByDn(String dn, String[] objectClasses) { + public void removeByDn(String dn, String[] objectClasses) { if (ArrayHelper.isEmpty(objectClasses)) { throw new UnsupportedOperationException("Entry class is manadatory for remove operation!"); } @@ -293,7 +292,7 @@ protected void removeByDn(String dn, String[] objectClasses) { for (DeleteNotifier subscriber : subscribers) { subscriber.onBeforeRemove(dn, objectClasses); } - getOperationService().delete(toSQLKey(dn).getKey(), objectClasses[0]); + getOperationService().delete(toSQLKey(dn).getKey(), getBaseObjectClass(objectClasses)); for (DeleteNotifier subscriber : subscribers) { subscriber.onAfterRemove(dn, objectClasses); } @@ -303,7 +302,7 @@ protected void removeByDn(String dn, String[] objectClasses) { } @Override - protected void removeRecursivelyFromDn(String dn, String[] objectClasses) { + public void removeRecursivelyFromDn(String dn, String[] objectClasses) { if (ArrayHelper.isEmpty(objectClasses)) { throw new UnsupportedOperationException("Entry class is manadatory for recursive remove operation!"); } @@ -312,7 +311,7 @@ protected void removeRecursivelyFromDn(String dn, String[] objectClasses) { for (DeleteNotifier subscriber : subscribers) { subscriber.onBeforeRemove(dn, objectClasses); } - getOperationService().deleteRecursively(toSQLKey(dn).getKey(), objectClasses[0]); + getOperationService().deleteRecursively(toSQLKey(dn).getKey(), getBaseObjectClass(objectClasses)); for (DeleteNotifier subscriber : subscribers) { subscriber.onAfterRemove(dn, objectClasses); } @@ -358,13 +357,13 @@ protected int removeImpl(String dn, Class entryClass, Filter filter, int String key = toSQLKey(dn).getKey(); ConvertedExpression convertedExpression; try { - convertedExpression = toSqlFilterWithEmptyAlias(key, objectClasses[0], searchFilter, propertiesAnnotationsMap); + convertedExpression = toSqlFilterWithEmptyAlias(key, getBaseObjectClass(entryClass, objectClasses), searchFilter, propertiesAnnotationsMap); } catch (SearchException ex) { throw new EntryDeleteException(String.format("Failed to convert filter '%s' to expression", searchFilter)); } try { - int processed = (int) getOperationService().delete(key, objectClasses[0], convertedExpression, count); + int processed = (int) getOperationService().delete(key, getBaseObjectClass(entryClass, objectClasses), convertedExpression, count); return processed; } catch (Exception ex) { @@ -377,7 +376,7 @@ protected List find(String dn, String[] objectClasses, Map result = getOperationService().lookup(keyWithInum.getKey(), objectClasses[0], toInternalAttributes(ldapReturnAttributes)); + List result = getOperationService().lookup(keyWithInum.getKey(), getBaseObjectClass(objectClasses), toInternalAttributes(ldapReturnAttributes)); if (result != null) { return result; } @@ -478,7 +477,7 @@ protected PagedResult findEntriesImpl(String baseDN, Class ent String key = toSQLKey(baseDN).getKey(); ConvertedExpression convertedExpression; try { - convertedExpression = toSqlFilter(key, objectClasses[0], searchFilter, propertiesAnnotationsMap); + convertedExpression = toSqlFilter(key, getBaseObjectClass(entryClass, objectClasses), searchFilter, propertiesAnnotationsMap); } catch (SearchException ex) { throw new EntryPersistenceException(String.format("Failed to convert filter '%s' to expression", searchFilter), ex); } @@ -489,7 +488,7 @@ protected PagedResult findEntriesImpl(String baseDN, Class ent if (batchOperation != null) { batchOperationWraper = new SpannerBatchOperationWraper(batchOperation, this, entryClass, propertiesAnnotations); } - searchResult = searchImpl(key, objectClasses[0], convertedExpression, scope, currentLdapReturnAttributes, + searchResult = searchImpl(key, getBaseObjectClass(entryClass, objectClasses), convertedExpression, scope, currentLdapReturnAttributes, defaultSort, batchOperationWraper, returnDataType, start, count, chunkSize); if (searchResult == null) { @@ -525,14 +524,14 @@ protected boolean contains(String baseDN, String[] objectClasses, Class e ConvertedExpression convertedExpression; try { - convertedExpression = toSqlFilter(key, objectClasses[0], searchFilter, propertiesAnnotationsMap); + convertedExpression = toSqlFilter(key, getBaseObjectClass(entryClass, objectClasses), searchFilter, propertiesAnnotationsMap); } catch (SearchException ex) { throw new EntryPersistenceException(String.format("Failed to convert filter '%s' to expression", searchFilter)); } PagedResult searchResult = null; try { - searchResult = searchImpl(key, objectClasses[0], convertedExpression, SearchScope.SUB, ldapReturnAttributes, null, + searchResult = searchImpl(key, getBaseObjectClass(entryClass, objectClasses), convertedExpression, SearchScope.SUB, ldapReturnAttributes, null, null, SearchReturnDataType.SEARCH, 0, 1, 0); if (searchResult == null) { throw new EntryPersistenceException(String.format("Failed to find entry with baseDN: '%s', filter: '%s'", baseDN, searchFilter)); @@ -620,13 +619,13 @@ public boolean authenticate(String baseDN, Class entryClass, String userN ConvertedExpression convertedExpression; try { - convertedExpression = toSqlFilter(key, objectClasses[0], searchFilter, propertiesAnnotationsMap); + convertedExpression = toSqlFilter(key, getBaseObjectClass(entryClass, objectClasses), searchFilter, propertiesAnnotationsMap); } catch (SearchException ex) { throw new EntryPersistenceException(String.format("Failed to convert filter '%s' to expression", searchFilter)); } try { - PagedResult searchResult = searchImpl(key, objectClasses[0], convertedExpression, + PagedResult searchResult = searchImpl(key, getBaseObjectClass(entryClass, objectClasses), convertedExpression, SearchScope.SUB, SpannerOperationService.UID_ARRAY, null, null, SearchReturnDataType.SEARCH, 0, 1, 1); if ((searchResult == null) || (searchResult.getEntriesCount() != 1)) { return false; @@ -664,7 +663,7 @@ public boolean authenticate(String bindDn, Class entryClass, String passw String[] objectClasses = getTypeObjectClasses(entryClass); try { - return getOperationService().authenticate(toSQLKey(bindDn).getKey(), escapeValue(password), objectClasses[0]); + return getOperationService().authenticate(toSQLKey(bindDn).getKey(), escapeValue(password), getBaseObjectClass(entryClass, objectClasses)); } catch (Exception ex) { throw new AuthenticationException(String.format("Failed to authenticate DN: '%s'", bindDn), ex); } @@ -701,14 +700,14 @@ public int countEntries(String baseDN, Class entryClass, Filter filter, S ConvertedExpression convertedExpression; try { - convertedExpression = toSqlFilter(key, objectClasses[0], searchFilter, propertiesAnnotationsMap); + convertedExpression = toSqlFilter(key, getBaseObjectClass(entryClass, objectClasses), searchFilter, propertiesAnnotationsMap); } catch (SearchException ex) { throw new EntryPersistenceException(String.format("Failed to convert filter '%s' to expression", searchFilter)); } PagedResult searchResult; try { - searchResult = searchImpl(toSQLKey(baseDN).getKey(), objectClasses[0], convertedExpression, scope, null, null, + searchResult = searchImpl(toSQLKey(baseDN).getKey(), getBaseObjectClass(entryClass, objectClasses), convertedExpression, scope, null, null, null, SearchReturnDataType.COUNT, 0, 0, 0); } catch (Exception ex) { throw new EntryPersistenceException( @@ -774,7 +773,7 @@ public List exportEntry(String dn) { } @Override - public List exportEntry(String dn, String objectClass) { + public List exportEntry(String dn, String objectClass) { if (StringHelper.isEmpty(objectClass)) { throw new MappingException("Object class isn't defined!"); } @@ -953,4 +952,20 @@ protected boolean isSupportForceUpdate() { return true; } + private String getBaseObjectClass(String[] objectClasses) { + if (ArrayHelper.isEmpty(objectClasses)) { + throw new MappingException("Object class isn't defined!"); + } + + return objectClasses[0]; + } + + private String getBaseObjectClass(Class entryClass, String[] objectClasses) { + if (ArrayHelper.isEmpty(objectClasses)) { + throw new MappingException(String.format("Object class isn't defined in bean '%s'!", entryClass)); + } + + return objectClasses[0]; + } + } diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerEntryManagerFactory.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerEntryManagerFactory.java index d6b44f4d291..8763b48782f 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerEntryManagerFactory.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerEntryManagerFactory.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerFilterConverter.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerFilterConverter.java index 1bc99c204d3..b69519efe1b 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerFilterConverter.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/impl/SpannerFilterConverter.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/ConvertedExpression.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/ConvertedExpression.java index 8f44efd7a30..f5685227bcd 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/ConvertedExpression.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/ConvertedExpression.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/ResultCode.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/ResultCode.java index a8a21e10e2d..f881493d04f 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/ResultCode.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/ResultCode.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/SearchReturnDataType.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/SearchReturnDataType.java index 3d56f307922..c752a46deb0 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/SearchReturnDataType.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/model/SearchReturnDataType.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/SpannerOperationService.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/SpannerOperationService.java index cf3cf9dc435..3b0c9c3c8f9 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/SpannerOperationService.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/SpannerOperationService.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/impl/SpannerConnectionProvider.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/impl/SpannerConnectionProvider.java index e80cb1224b8..16b2a6306d5 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/impl/SpannerConnectionProvider.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/impl/SpannerConnectionProvider.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -40,6 +40,7 @@ import io.jans.orm.exception.MappingException; import io.jans.orm.exception.operation.ConfigurationException; import io.jans.orm.exception.operation.ConnectionException; +import io.jans.orm.exception.operation.PersistenceException; import io.jans.orm.operation.auth.PasswordEncryptionMethod; import io.jans.orm.util.ArrayHelper; import io.jans.orm.util.PropertiesHelper; @@ -431,11 +432,12 @@ public PasswordEncryptionMethod getPasswordEncryptionMethod() { } public TableMapping getTableMappingByKey(String key, String objectClass, String tableName) { - Map columTypes = tableColumnsMap.get(tableName); if (!tableColumnsMap.containsKey(tableName)) { - throw new MappingException(String.format("Table '%s' metadata is not exists '", tableName)); + throw new MappingException(String.format("Table '%s' is not exists in metadata'", tableName)); } + Map columTypes = tableColumnsMap.get(tableName); + if ("_".equals(key)) { return new TableMapping("", tableName, objectClass, columTypes); } @@ -456,7 +458,13 @@ public TableMapping getTableMappingByKey(String key, String objectClass) { public TableMapping getChildTableMappingByKey(String key, TableMapping tableMapping, String columnName) { String childTableName = tableMapping.getTableName() + "_" + columnName; + + if (!tableColumnsMap.containsKey(childTableName)) { + return null; + } + TableMapping childTableMapping = getTableMappingByKey(key, tableMapping.getObjectClass(), childTableName); + return childTableMapping; } @@ -473,6 +481,10 @@ public Map getChildTablesMapping(String key, TableMapping Map childTableMapping = new HashMap<>(); for (String childAttribute : childAttributes) { TableMapping childColumTypes = getChildTableMappingByKey(key, tableMapping, childAttribute); + if (childColumTypes == null) { + String childTableName = tableMapping.getTableName() + "_" + childAttribute; + throw new MappingException(String.format("Table '%s' is not exists in metadata'", childTableName)); + } childTableMapping.put(childAttribute.toLowerCase(), childColumTypes); } diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/impl/SpannerOperationServiceImpl.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/impl/SpannerOperationServiceImpl.java index 97f74a89eda..0877ba0e0cc 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/impl/SpannerOperationServiceImpl.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/impl/SpannerOperationServiceImpl.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -42,7 +42,6 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; import com.google.cloud.spanner.Type.StructField; -import com.google.cloud.spanner.ValueBinder; import io.jans.orm.cloud.spanner.impl.SpannerBatchOperationWraper; import io.jans.orm.cloud.spanner.model.ConvertedExpression; @@ -52,7 +51,6 @@ import io.jans.orm.cloud.spanner.operation.SpannerOperationService; import io.jans.orm.cloud.spanner.operation.watch.OperationDurationUtil; import io.jans.orm.cloud.spanner.util.SpannerValueHelper; -import io.jans.orm.exception.extension.PersistenceExtension; import io.jans.orm.exception.operation.DeleteException; import io.jans.orm.exception.operation.DuplicateEntryException; import io.jans.orm.exception.operation.EntryConvertationException; @@ -60,18 +58,22 @@ import io.jans.orm.exception.operation.IncompatibleTypeException; import io.jans.orm.exception.operation.PersistenceException; import io.jans.orm.exception.operation.SearchException; +import io.jans.orm.extension.PersistenceExtension; import io.jans.orm.model.AttributeData; import io.jans.orm.model.AttributeDataModification; -import io.jans.orm.model.AttributeDataModification.AttributeModificationType; import io.jans.orm.model.BatchOperation; import io.jans.orm.model.EntryData; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; import io.jans.orm.model.Sort; import io.jans.orm.model.SortOrder; +import io.jans.orm.model.AttributeDataModification.AttributeModificationType; import io.jans.orm.operation.auth.PasswordEncryptionHelper; import io.jans.orm.util.ArrayHelper; import io.jans.orm.util.StringHelper; + +import com.google.cloud.spanner.ValueBinder; + import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.Function; @@ -623,7 +625,7 @@ private PagedResult searchImpl(TableMapping tableMapping, String // Change limit and offset limit.setRowCount(new LongValue(currentLimit)); - offset.setOffset(start + resultCount); + offset.setOffset(new LongValue(start + resultCount)); Statement.Builder statementBuilder = Statement.newBuilder(sqlSelectQuery.toString()); applyParametersBinding(statementBuilder, expression); @@ -672,7 +674,7 @@ private PagedResult searchImpl(TableMapping tableMapping, String if (start > 0) { Offset offset = new Offset(); - offset.setOffset(start); + offset.setOffset(new LongValue(start)); sqlSelectQuery.setOffset(offset); } diff --git a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/watch/OperationDurationUtil.java b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/watch/OperationDurationUtil.java index 46e0fba4485..e1ea4abbf4f 100644 --- a/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/watch/OperationDurationUtil.java +++ b/jans-orm/spanner/src/main/java/io/jans/orm/cloud/spanner/operation/watch/OperationDurationUtil.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/LoggingHelper.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/LoggingHelper.java index cdc2b54c740..e6e5f968d6c 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/LoggingHelper.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/LoggingHelper.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlBatchJobSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlBatchJobSample.java index 389474426c3..4dd6924aa8c 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlBatchJobSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlBatchJobSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCacheRefreshSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCacheRefreshSample.java new file mode 100644 index 00000000000..ea962d67dd5 --- /dev/null +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCacheRefreshSample.java @@ -0,0 +1,52 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.orm.sql; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.jans.orm.model.SearchScope; +import io.jans.orm.search.filter.Filter; +import io.jans.orm.sql.impl.SqlEntryManager; +import io.jans.orm.sql.model.SimleInumMap; +import io.jans.orm.sql.model.Status; +import io.jans.orm.sql.operation.impl.SqlConnectionProvider; +import io.jans.orm.sql.persistence.SqlEntryManagerSample; + +/** + * @author Yuriy Movchan Date: 01/15/2020 + */ +public final class SqlCacheRefreshSample { + + private static final Logger LOG = LoggerFactory.getLogger(SqlConnectionProvider.class); + + private SqlCacheRefreshSample() { + } + + public static void main(String[] args) { + // Prepare sample connection details + SqlEntryManagerSample sqlEntryManagerSample = new SqlEntryManagerSample(); + + // Create SQL entry manager + SqlEntryManager sqlEntryManager = sqlEntryManagerSample.createSqlEntryManager(); + + String inumbaseDn = "ou=cache-refresh,o=site"; + + Filter filterObjectClass = Filter.createEqualityFilter("objectClass", + "jansInumMap"); + Filter filterStatus = Filter.createNOTFilter( + Filter.createEqualityFilter("jansStatus", Status.INACTIVE.getValue())); + Filter filter = Filter.createANDFilter(filterObjectClass, filterStatus); + + List result = sqlEntryManager.findEntries(inumbaseDn, SimleInumMap.class, filter, SearchScope.SUB, null, + null, 0, 0, 1000); + System.out.println(result); + } + +} diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlConcurentSessionUpdateSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlConcurentSessionUpdateSample.java index 51b70cacbaa..e8ad4bf387f 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlConcurentSessionUpdateSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlConcurentSessionUpdateSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomMultiValuedTypesSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomMultiValuedTypesSample.java index 75b14ae5e12..0872940479b 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomMultiValuedTypesSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomMultiValuedTypesSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomObjectAttributesSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomObjectAttributesSample.java index 33fae9f7290..036c4bc079d 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomObjectAttributesSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomObjectAttributesSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomStringAttributesSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomStringAttributesSample.java index d2d92bd13f1..438653727d9 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomStringAttributesSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlCustomStringAttributesSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlDeleteSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlDeleteSample.java index 5ebbece3aa6..74e4b090d98 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlDeleteSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlDeleteSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlIdpAuthConfSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlIdpAuthConfSample.java index 0b016882a13..4dc845eae4c 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlIdpAuthConfSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlIdpAuthConfSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSample.java index 40a1557ce49..37a9810814e 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleClientSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleClientSample.java index 8b172173c28..c7df07dacc3 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleClientSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleClientSample.java @@ -1,3 +1,9 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + package io.jans.orm.sql; import java.util.Arrays; @@ -16,7 +22,7 @@ /** * @author Yuriy Movchan Date: 05/26/2021 */ -public class SqlSimpleClientSample { +public final class SqlSimpleClientSample { private static final Logger LOG = LoggerFactory.getLogger(SqlConnectionProvider.class); @@ -31,15 +37,14 @@ public static void main(String[] args) { SqlEntryManager sqlEntryManager = sqlEntryManagerSample.createSqlEntryManager(); SimpleClient newClient = new SimpleClient(); - newClient.setDn("inum=test_clnt2,ou=client,o=gluu"); - newClient.setDefaultAcrValues(new String[] { "test_clnt2_acr" }); - newClient.setClientName("test_clnt2"); + newClient.setDn("inum=test_acr2,ou=client,o=jans"); + newClient.setDefaultAcrValues(new String[] {"test_acr2"}); + newClient.setClientName("test_acr2"); sqlEntryManager.persist(newClient); - Filter presenceFilter = Filter.createEqualityFilter("displayName", "test_clnt2"); - List results = sqlEntryManager.findEntries("ou=test_clnt2,o=gluu", SimpleClient.class, - presenceFilter); + Filter presenceFilter = Filter.createEqualityFilter("displayName", "test_acr2"); + List results = sqlEntryManager.findEntries("ou=client,o=jans", SimpleClient.class, presenceFilter); for (SimpleClient client : results) { String[] acrs = client.getDefaultAcrValues(); if (ArrayHelper.isNotEmpty(acrs)) { diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleClientWithDeleteNotifierSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleClientWithDeleteNotifierSample.java index bf67330f5b1..a552efe7c33 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleClientWithDeleteNotifierSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleClientWithDeleteNotifierSample.java @@ -1,3 +1,9 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + package io.jans.orm.sql; import java.util.Arrays; @@ -17,7 +23,7 @@ /** * @author Yuriy Movchan Date: 05/26/2021 */ -public class SqlSimpleClientWithDeleteNotifierSample { +public final class SqlSimpleClientWithDeleteNotifierSample { private static final Logger LOG = LoggerFactory.getLogger(SqlConnectionProvider.class); @@ -45,15 +51,14 @@ public void onAfterRemove(String dn, String[] objectClasses) { }); SimpleClient newClient = new SimpleClient(); - newClient.setDn("inum=test_clnt3,ou=client,o=gluu"); - newClient.setDefaultAcrValues(new String[] { "test_clnt3_acr" }); - newClient.setClientName("test_clnt3"); + newClient.setDn("inum=test_acr4,ou=client,o=jans"); + newClient.setDefaultAcrValues(new String[] {"test_acr4"}); + newClient.setClientName("test_acr4"); sqlEntryManager.persist(newClient); - Filter presenceFilter = Filter.createEqualityFilter("displayName", "test_clnt3"); - List results = sqlEntryManager.findEntries("ou=test_clnt3,o=gluu", SimpleClient.class, - presenceFilter); + Filter presenceFilter = Filter.createEqualityFilter("displayName", "test_acr4"); + List results = sqlEntryManager.findEntries("ou=client,o=jans", SimpleClient.class, presenceFilter); for (SimpleClient client : results) { String[] acrs = client.getDefaultAcrValues(); if (ArrayHelper.isNotEmpty(acrs)) { @@ -61,7 +66,7 @@ public void onAfterRemove(String dn, String[] objectClasses) { } } - sqlEntryManager.remove(newClient.getDn(), SimpleClient.class); + sqlEntryManager.removeRecursively(newClient.getDn(), SimpleClient.class); } } diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleGroupSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleGroupSample.java index 5596e62b5a6..3cbc2da3242 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleGroupSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlSimpleGroupSample.java @@ -1,7 +1,7 @@ /* * oxCore is available under the MIT License (2014). See http://opensource.org/licenses/MIT for full text. * - * Copyright (c) 2014, Gluu + * Copyright (c) 2020, Janssen Project */ package io.jans.orm.sql; @@ -33,12 +33,12 @@ public static void main(String[] args) { // Create SQL entry manager SqlEntryManager sqlEntryManager = sqlEntryManagerSample.createSqlEntryManager(); - String personDN = "inum=ae8c7ff9-def7-4b42-8147-de8380617a37,ou=people,o=gluu"; + String personDN = "inum=ae8c7ff9-def7-4b42-8147-de8380617a37,ou=people,o=jans"; Filter ownerFilter = Filter.createEqualityFilter("owner", personDN); Filter memberFilter = Filter.createEqualityFilter("member", personDN); Filter searchFilter = Filter.createORFilter(ownerFilter, memberFilter); - List result = sqlEntryManager.findEntries("ou=groups,o=gluu", SimpleGroup.class, searchFilter, 1); + List result = sqlEntryManager.findEntries("ou=groups,o=jans", SimpleGroup.class, searchFilter, 1); System.out.println(result); } diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUmaResourceSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUmaResourceSample.java new file mode 100644 index 00000000000..b5e17c1e2f4 --- /dev/null +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUmaResourceSample.java @@ -0,0 +1,43 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.orm.sql; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.jans.orm.search.filter.Filter; +import io.jans.orm.sql.impl.SqlEntryManager; +import io.jans.orm.sql.model.UmaResource; +import io.jans.orm.sql.operation.impl.SqlConnectionProvider; +import io.jans.orm.sql.persistence.SqlEntryManagerSample; + +/** + * @author Yuriy Movchan Date: 01/15/2020 + */ +public final class SqlUmaResourceSample { + + private static final Logger LOG = LoggerFactory.getLogger(SqlConnectionProvider.class); + + private SqlUmaResourceSample() { + } + + public static void main(String[] args) { + // Prepare sample connection details + SqlEntryManagerSample sqlEntryManagerSample = new SqlEntryManagerSample(); + + // Create SQL entry manager + SqlEntryManager sqlEntryManager = sqlEntryManagerSample.createSqlEntryManager(); + + final Filter filter = Filter.createEqualityFilter("jansAssociatedClnt", "inum=AB77-1A2B,ou=clients,o=jans").multiValued(); + List umaResource = sqlEntryManager.findEntries("ou=resources,ou=uma,o=jans", UmaResource.class, filter); + + LOG.info("Found umaResources: " + umaResource); + } + +} diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUpateCacheEntrySample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUpateCacheEntrySample.java index 43714ad4dec..d1365fec9bc 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUpateCacheEntrySample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUpateCacheEntrySample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -36,7 +36,7 @@ public static void main(String[] args) { SqlEntryManager sqlEntryManager = sqlEntryManagerSample.createSqlEntryManager(); String key = UUID.randomUUID().toString(); - final String cacheDn = String.format("uuid=%s,%s", key, "ou=cache,o=gluu"); + final String cacheDn = String.format("uuid=%s,%s", key, "ou=cache,o=jans"); int expirationInSeconds = 60; Calendar expirationDate = Calendar.getInstance(); diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUpateMissingEntrySample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUpateMissingEntrySample.java index b6b61c3dc9c..f6438939e31 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUpateMissingEntrySample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUpateMissingEntrySample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUserSearchSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUserSearchSample.java index caa6bd2f267..77afc334ebd 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUserSearchSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/SqlUserSearchSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/UmaResourceSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/UmaResourceSample.java index 1f046b7397b..5f8c343ab32 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/UmaResourceSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/UmaResourceSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimleInumMap.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimleInumMap.java new file mode 100644 index 00000000000..88694c1dfb8 --- /dev/null +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimleInumMap.java @@ -0,0 +1,121 @@ +package io.jans.orm.sql.model; + +import java.io.Serializable; +import java.util.Arrays; + +import io.jans.orm.annotation.AttributeName; +import io.jans.orm.annotation.DataEntry; +import io.jans.orm.annotation.ObjectClass; +import io.jans.orm.model.base.Entry; + +/** +* GluuInumMap +* +* @author Yuriy Movchan Date: 04/20/2022 +*/ +@DataEntry(sortBy = { "inum" }) +@ObjectClass(value = "jansInumMap") +public class SimleInumMap extends Entry implements Serializable { + + private static final long serialVersionUID = -2190480357430436503L; + + @AttributeName(ignoreDuringUpdate = true) + private String inum; + + @AttributeName + private String primaryKeyAttrName; + + @AttributeName(name = "primaryKeyValue") + private String[] primaryKeyValues; + + @AttributeName + private String secondaryKeyAttrName; + + @AttributeName(name = "secondaryKeyValue") + private String[] secondaryKeyValues; + + @AttributeName + private String tertiaryKeyAttrName; + + @AttributeName(name = "tertiaryKeyValue") + private String[] tertiaryKeyValues; + + @AttributeName(name = "jansStatus") + private Status status; + + public String getInum() { + return inum; + } + + public void setInum(String inum) { + this.inum = inum; + } + + public String getPrimaryKeyAttrName() { + return primaryKeyAttrName; + } + + public void setPrimaryKeyAttrName(String primaryKeyAttrName) { + this.primaryKeyAttrName = primaryKeyAttrName; + } + + public String[] getPrimaryKeyValues() { + return primaryKeyValues; + } + + public void setPrimaryKeyValues(String[] primaryKeyValues) { + this.primaryKeyValues = primaryKeyValues; + } + + public String getSecondaryKeyAttrName() { + return secondaryKeyAttrName; + } + + public void setSecondaryKeyAttrName(String secondaryKeyAttrName) { + this.secondaryKeyAttrName = secondaryKeyAttrName; + } + + public String[] getSecondaryKeyValues() { + return secondaryKeyValues; + } + + public void setSecondaryKeyValues(String[] secondaryKeyValues) { + this.secondaryKeyValues = secondaryKeyValues; + } + + public String getTertiaryKeyAttrName() { + return tertiaryKeyAttrName; + } + + public void setTertiaryKeyAttrName(String tertiaryKeyAttrName) { + this.tertiaryKeyAttrName = tertiaryKeyAttrName; + } + + public String[] getTertiaryKeyValues() { + return tertiaryKeyValues; + } + + public void setTertiaryKeyValues(String[] tertiaryKeyValues) { + this.tertiaryKeyValues = tertiaryKeyValues; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GluuInumMap [inum=").append(inum).append(", primaryKeyAttrName=").append(primaryKeyAttrName) + .append(", primaryKeyValues=").append(Arrays.toString(primaryKeyValues)).append(", secondaryKeyAttrName=") + .append(secondaryKeyAttrName).append(", secondaryKeyValues=").append(Arrays.toString(secondaryKeyValues)) + .append(", tertiaryKeyAttrName=").append(tertiaryKeyAttrName).append(", tertiaryKeyValues=") + .append(Arrays.toString(tertiaryKeyValues)).append(", status=").append(status).append("]"); + return builder.toString(); + } + +} diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleAttribute.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleAttribute.java index 8a240598099..e66df08dc51 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleAttribute.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleAttribute.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleCacheEntry.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleCacheEntry.java index 11757620464..093b71230c6 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleCacheEntry.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleCacheEntry.java @@ -3,12 +3,8 @@ import java.io.Serializable; import java.util.Date; -/* - * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. - * - * Copyright (c) 2020, Janssen Project - */ import io.jans.orm.annotation.AttributeName; +import io.jans.orm.annotation.DN; import io.jans.orm.annotation.DataEntry; import io.jans.orm.annotation.Expiration; import io.jans.orm.annotation.ObjectClass; @@ -21,6 +17,8 @@ public class SimpleCacheEntry extends DeletableEntity implements Serializable, D private static final long serialVersionUID = 3360900373193184522L; + @DN + private String dn; @Expiration private Integer ttl; @AttributeName(name = "uuid") @@ -30,6 +28,14 @@ public class SimpleCacheEntry extends DeletableEntity implements Serializable, D @AttributeName(name = "dat") private String data; + public String getDn() { + return dn; + } + + public void setDn(String dn) { + this.dn = dn; + } + public Integer getTtl() { return ttl; } @@ -64,7 +70,7 @@ public void setData(String data) { @Override public String toString() { - return "NativePersistenceCacheEntity [dn=" + getDn() + ", ttl=" + ttl + ", id=" + id + ", creationDate=" + creationDate + ", data=" + return "NativePersistenceCacheEntity [dn=" + dn + ", ttl=" + ttl + ", id=" + id + ", creationDate=" + creationDate + ", data=" + data + "]"; } } diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleClient.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleClient.java index c870fd4811b..a18f2ebe460 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleClient.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleClient.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -51,12 +51,8 @@ public void setDn(String dn) { this.dn = dn; } - public String getClientName() { - return clientName; - } - - public void setClientName(String clientName) { - this.clientName = clientName; + public List getCustomAttributes() { + return customAttributes; } public String[] getDefaultAcrValues() { @@ -67,8 +63,12 @@ public void setDefaultAcrValues(String[] defaultAcrValues) { this.defaultAcrValues = defaultAcrValues; } - public List getCustomAttributes() { - return customAttributes; + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + this.clientName = clientName; } public void setCustomAttributes(List customAttributes) { diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleCustomStringUser.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleCustomStringUser.java index b5f5cb5a4ad..d091bb13867 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleCustomStringUser.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleCustomStringUser.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleGrant.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleGrant.java index 2b579387108..e11b933db30 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleGrant.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleGrant.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleGroup.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleGroup.java index cf3871888dd..cf0bbb496e8 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleGroup.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleGroup.java @@ -21,7 +21,7 @@ * @author Yuriy Movchan Date: 11.02.2010 */ @DataEntry(sortBy = { "displayName" }) -@ObjectClass(value = "gluuGroup") +@ObjectClass(value = "jansGroup") @JsonInclude(Include.NON_NULL) public class SimpleGroup extends Entry implements Serializable { diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleSession.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleSession.java index a5b07ee2ccf..389e2c43aa5 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleSession.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleSession.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleSessionState.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleSessionState.java index d52ae4bff52..cd5a608a823 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleSessionState.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleSessionState.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleToken.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleToken.java index 0ce8ca78030..2293c67d021 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleToken.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleToken.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleUser.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleUser.java index 90bcd5fea04..476301d6456 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleUser.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/SimpleUser.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/Status.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/Status.java new file mode 100644 index 00000000000..5d1c6e8987b --- /dev/null +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/Status.java @@ -0,0 +1,54 @@ +package io.jans.orm.sql.model; + +import java.util.HashMap; +import java.util.Map; + +import io.jans.orm.annotation.AttributeEnum; + +/** +* Status +* +* @author Yuriy Movchan Date: 04/22/2022 +*/ +public enum Status implements AttributeEnum { + + ACTIVE("active", "Active"), INACTIVE("inactive", "Inactive"), EXPIRED("expired", "Expired"), REGISTER("register", "Register"); + + private String value; + private String displayName; + + private static Map MAP_BY_VALUES = new HashMap(); + + static { + for (Status enumType : values()) { + MAP_BY_VALUES.put(enumType.getValue(), enumType); + } + } + + Status(String value, String displayName) { + this.value = value; + this.displayName = displayName; + } + + public String getValue() { + return value; + } + + public String getDisplayName() { + return displayName; + } + + public static Status getByValue(String value) { + return MAP_BY_VALUES.get(value); + } + + public Enum resolveByValue(String value) { + return getByValue(value); + } + + @Override + public String toString() { + return value; + } + +} diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/UmaResource.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/UmaResource.java index b12773cec36..3cce3b1d2e5 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/UmaResource.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/UmaResource.java @@ -12,6 +12,7 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.common.collect.Lists; import io.jans.orm.annotation.AttributeName; import io.jans.orm.annotation.DN; @@ -137,7 +138,7 @@ public void setId(String id) { public List getClients() { if (clients == null) { - clients = new ArrayList<>(); + clients = new ArrayList(); } return clients; } @@ -171,7 +172,7 @@ public void setIconUri(String iconUri) { } public List getScopes() { - if (scopes == null) scopes = new ArrayList<>(); + if (scopes == null) scopes = Lists.newArrayList(); return scopes; } diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/UserRole.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/UserRole.java index c5bbec0748a..ddee0874a6e 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/UserRole.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/model/UserRole.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/persistence/SqlEntryManagerSample.java b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/persistence/SqlEntryManagerSample.java index d791d6d60de..ef9c6986bfb 100644 --- a/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/persistence/SqlEntryManagerSample.java +++ b/jans-orm/sql-sample/src/main/java/io/jans/orm/sql/persistence/SqlEntryManagerSample.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql-sample/src/test/java/io/jans/sql/test/ManualSqlEntryManagerTest.java b/jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/ManualSqlEntryManagerTest.java similarity index 98% rename from jans-orm/sql-sample/src/test/java/io/jans/sql/test/ManualSqlEntryManagerTest.java rename to jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/ManualSqlEntryManagerTest.java index 3928338d535..e1334103851 100644 --- a/jans-orm/sql-sample/src/test/java/io/jans/sql/test/ManualSqlEntryManagerTest.java +++ b/jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/ManualSqlEntryManagerTest.java @@ -1,10 +1,10 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ -package io.jans.sql.test; +package io.jans.orm.sql.test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; diff --git a/jans-orm/sql-sample/src/test/java/io/jans/sql/test/SessionId.java b/jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/SessionId.java similarity index 98% rename from jans-orm/sql-sample/src/test/java/io/jans/sql/test/SessionId.java rename to jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/SessionId.java index 560a8aeeff3..b8a4ce0be07 100644 --- a/jans-orm/sql-sample/src/test/java/io/jans/sql/test/SessionId.java +++ b/jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/SessionId.java @@ -1,10 +1,10 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ -package io.jans.sql.test; +package io.jans.orm.sql.test; import java.io.Serializable; import java.util.ArrayList; @@ -14,7 +14,6 @@ import java.util.UUID; import javax.annotation.Nonnull; -import jakarta.persistence.Transient; import org.apache.commons.lang.StringUtils; @@ -30,6 +29,7 @@ import io.jans.orm.model.base.CustomAttribute; import io.jans.orm.model.base.Deletable; import io.jans.orm.util.StringHelper; +import jakarta.persistence.Transient; /** * diff --git a/jans-orm/sql-sample/src/test/java/io/jans/sql/test/SessionIdState.java b/jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/SessionIdState.java similarity index 86% rename from jans-orm/sql-sample/src/test/java/io/jans/sql/test/SessionIdState.java rename to jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/SessionIdState.java index db5af2982d8..b0b8474cbf9 100644 --- a/jans-orm/sql-sample/src/test/java/io/jans/sql/test/SessionIdState.java +++ b/jans-orm/sql-sample/src/test/java/io/jans/orm/sql/test/SessionIdState.java @@ -1,10 +1,10 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ -package io.jans.sql.test; +package io.jans.orm.sql.test; import java.util.HashMap; import java.util.Map; diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlBatchOperationWraper.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlBatchOperationWraper.java index 7eaae5d0262..22600cdf489 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlBatchOperationWraper.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlBatchOperationWraper.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlEntryManager.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlEntryManager.java index 001e44fac9e..5a5879b5f01 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlEntryManager.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlEntryManager.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -18,8 +18,7 @@ import java.util.Map; import java.util.function.Function; -import io.jans.orm.model.base.LocalizedString; -import jakarta.inject.Inject; +import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,17 +40,21 @@ import io.jans.orm.model.AttributeData; import io.jans.orm.model.AttributeDataModification; import io.jans.orm.model.AttributeDataModification.AttributeModificationType; +import io.jans.orm.model.AttributeType; import io.jans.orm.model.BatchOperation; import io.jans.orm.model.EntryData; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; import io.jans.orm.model.SortOrder; +import io.jans.orm.model.base.LocalizedString; import io.jans.orm.reflect.property.PropertyAnnotation; import io.jans.orm.search.filter.Filter; import io.jans.orm.search.filter.FilterProcessor; import io.jans.orm.sql.model.ConvertedExpression; import io.jans.orm.sql.model.SearchReturnDataType; +import io.jans.orm.sql.model.TableMapping; import io.jans.orm.sql.operation.SqlOperationService; +import io.jans.orm.sql.operation.impl.SqlConnectionProvider; import io.jans.orm.util.ArrayHelper; import io.jans.orm.util.StringHelper; @@ -60,7 +63,7 @@ * * @author Yuriy Movchan Date: 01/12/2020 */ -public class SqlEntryManager extends BaseEntryManager implements Serializable { +public class SqlEntryManager extends BaseEntryManager implements Serializable { private static final long serialVersionUID = 2127241817126412574L; @@ -145,7 +148,7 @@ protected void updateMergeChanges(String baseDn, T entry, boolean isConfigur } // We need to check only first element of each array because objectCLass in SQL is single value attribute - if (!StringHelper.equals(objectClassesFromDb[0], objectClasses[0])) { + if (!StringHelper.equals(getBaseObjectClass(entryClass, objectClassesFromDb), getBaseObjectClass(entryClass, objectClasses))) { throw new UnsupportedOperationException(String.format("It's not possible to change objectClasses of already persisted entry! Entry is invalid: '%s'", entry)); } } @@ -209,7 +212,7 @@ protected void persist(String dn, String[] objectClasses, List at resultAttributes.add(new AttributeData(SqlOperationService.DN, dn)); resultAttributes.add(new AttributeData(SqlOperationService.DOC_ID, parsedKey.getKey())); - boolean result = getOperationService().addEntry(parsedKey.getKey(), objectClasses[0], resultAttributes); + boolean result = getOperationService().addEntry(parsedKey.getKey(), getBaseObjectClass(objectClasses), resultAttributes); if (!result) { throw new EntryPersistenceException(String.format("Failed to persist entry: '%s'", dn)); } @@ -266,7 +269,7 @@ public void merge(String dn, String[] objectClasses, List 0) { - boolean result = getOperationService().updateEntry(toSQLKey(dn).getKey(), objectClasses[0], modifications); + boolean result = getOperationService().updateEntry(toSQLKey(dn).getKey(), getBaseObjectClass(objectClasses), modifications); if (!result) { throw new EntryPersistenceException(String.format("Failed to update entry: '%s'", dn)); } @@ -277,7 +280,7 @@ public void merge(String dn, String[] objectClasses, List void removeByDn(String dn, String[] objectClasses) { + public void removeByDn(String dn, String[] objectClasses) { if (ArrayHelper.isEmpty(objectClasses)) { throw new UnsupportedOperationException("Entry class is manadatory for remove operation!"); } @@ -287,7 +290,7 @@ protected void removeByDn(String dn, String[] objectClasses) { for (DeleteNotifier subscriber : subscribers) { subscriber.onBeforeRemove(dn, objectClasses); } - getOperationService().delete(toSQLKey(dn).getKey(), objectClasses[0]); + getOperationService().delete(toSQLKey(dn).getKey(), getBaseObjectClass(objectClasses)); for (DeleteNotifier subscriber : subscribers) { subscriber.onAfterRemove(dn, objectClasses); } @@ -297,7 +300,7 @@ protected void removeByDn(String dn, String[] objectClasses) { } @Override - protected void removeRecursivelyFromDn(String dn, String[] objectClasses) { + public void removeRecursivelyFromDn(String dn, String[] objectClasses) { if (ArrayHelper.isEmpty(objectClasses)) { throw new UnsupportedOperationException("Entry class is manadatory for recursive remove operation!"); } @@ -306,7 +309,7 @@ protected void removeRecursivelyFromDn(String dn, String[] objectClasses) { for (DeleteNotifier subscriber : subscribers) { subscriber.onBeforeRemove(dn, objectClasses); } - getOperationService().deleteRecursively(toSQLKey(dn).getKey(), objectClasses[0]); + getOperationService().deleteRecursively(toSQLKey(dn).getKey(), getBaseObjectClass(objectClasses)); for (DeleteNotifier subscriber : subscribers) { subscriber.onAfterRemove(dn, objectClasses); } @@ -358,7 +361,7 @@ protected int removeImpl(String dn, Class entryClass, Filter filter, int } try { - int processed = (int) getOperationService().delete(keyWithInum.getKey(), objectClasses[0], convertedExpression, count); + int processed = (int) getOperationService().delete(keyWithInum.getKey(), getBaseObjectClass(entryClass, objectClasses), convertedExpression, count); return processed; } catch (Exception ex) { @@ -371,7 +374,7 @@ protected List find(String dn, String[] objectClasses, Map result = getOperationService().lookup(keyWithInum.getKey(), objectClasses[0], toInternalAttributes(ldapReturnAttributes)); + List result = getOperationService().lookup(keyWithInum.getKey(), getBaseObjectClass(objectClasses), toInternalAttributes(ldapReturnAttributes)); if (result != null) { return result; } @@ -483,7 +486,7 @@ protected PagedResult findEntriesImpl(String baseDN, Class ent if (batchOperation != null) { batchOperationWraper = new SqlBatchOperationWraper(batchOperation, this, entryClass, propertiesAnnotations); } - searchResult = searchImpl(keyWithInum.getKey(), objectClasses[0], convertedExpression, scope, currentLdapReturnAttributes, + searchResult = searchImpl(keyWithInum.getKey(), getBaseObjectClass(entryClass, objectClasses), convertedExpression, scope, currentLdapReturnAttributes, defaultSort, batchOperationWraper, returnDataType, start, count, chunkSize); if (searchResult == null) { @@ -525,7 +528,7 @@ protected boolean contains(String baseDN, String[] objectClasses, Class e PagedResult searchResult = null; try { ParsedKey keyWithInum = toSQLKey(baseDN); - searchResult = searchImpl(keyWithInum.getKey(), objectClasses[0], convertedExpression, SearchScope.SUB, ldapReturnAttributes, null, + searchResult = searchImpl(keyWithInum.getKey(), getBaseObjectClass(entryClass, objectClasses), convertedExpression, SearchScope.SUB, ldapReturnAttributes, null, null, SearchReturnDataType.SEARCH, 0, 1, 0); if (searchResult == null) { throw new EntryPersistenceException(String.format("Failed to find entry with baseDN: '%s', filter: '%s'", baseDN, searchFilter)); @@ -615,7 +618,7 @@ public boolean authenticate(String baseDN, Class entryClass, String userN } try { - PagedResult searchResult = searchImpl(toSQLKey(baseDN).getKey(), objectClasses[0], convertedExpression, + PagedResult searchResult = searchImpl(toSQLKey(baseDN).getKey(), getBaseObjectClass(entryClass, objectClasses), convertedExpression, SearchScope.SUB, SqlOperationService.UID_ARRAY, null, null, SearchReturnDataType.SEARCH, 0, 1, 1); if ((searchResult == null) || (searchResult.getEntriesCount() != 1)) { return false; @@ -653,7 +656,7 @@ public boolean authenticate(String bindDn, Class entryClass, String passw String[] objectClasses = getTypeObjectClasses(entryClass); try { - return getOperationService().authenticate(toSQLKey(bindDn).getKey(), escapeValue(password), objectClasses[0]); + return getOperationService().authenticate(toSQLKey(bindDn).getKey(), escapeValue(password), getBaseObjectClass(entryClass, objectClasses)); } catch (Exception ex) { throw new AuthenticationException(String.format("Failed to authenticate DN: '%s'", bindDn), ex); } @@ -695,7 +698,7 @@ public int countEntries(String baseDN, Class entryClass, Filter filter, S PagedResult searchResult; try { - searchResult = searchImpl(toSQLKey(baseDN).getKey(), objectClasses[0], convertedExpression, scope, null, null, + searchResult = searchImpl(toSQLKey(baseDN).getKey(), getBaseObjectClass(entryClass, objectClasses), convertedExpression, scope, null, null, null, SearchReturnDataType.COUNT, 0, 0, 0); } catch (Exception ex) { throw new EntryPersistenceException( @@ -762,7 +765,7 @@ public List exportEntry(String dn) { } @Override - public List exportEntry(String dn, String objectClass) { + public List exportEntry(String dn, String objectClass) { if (StringHelper.isEmpty(objectClass)) { throw new MappingException("Object class isn't defined!"); } @@ -948,6 +951,20 @@ public String[] fromInternalAttributes(String[] internalAttributeNames) { return ((SqlOperationService) operationService).fromInternalAttributes(internalAttributeNames); } + @Override + public AttributeType getAttributeType(String primaryKey, Class entryClass, String propertyName) { + // Check entry class + checkEntryClass(entryClass, false); + String[] objectClasses = getTypeObjectClasses(entryClass); + + SqlConnectionProvider sqlConnectionProvider = getOperationService().getConnectionProvider(); + TableMapping tableMapping = sqlConnectionProvider.getTableMappingByKey(primaryKey, getBaseObjectClass(objectClasses)); + Map columTypes = tableMapping.getColumTypes(); + AttributeType attributeType = columTypes.get(propertyName.toLowerCase()); + + return attributeType; + } + protected boolean isSupportForceUpdate() { return true; } @@ -967,4 +984,24 @@ protected List getAttributeDataFromLocalizedString(String ldapAtt return listAttributes; } + private String getBaseObjectClass(String[] objectClasses) { + if (ArrayHelper.isEmpty(objectClasses)) { + throw new MappingException("Object class isn't defined!"); + } + + if (StringHelper.isEmpty(objectClasses[0])) { + throw new MappingException("First object class is invalid!"); + } + + return objectClasses[0]; + } + + private String getBaseObjectClass(Class entryClass, String[] objectClasses) { + if (ArrayHelper.isEmpty(objectClasses)) { + throw new MappingException(String.format("Object class isn't defined in bean '%s'!", entryClass)); + } + + return objectClasses[0]; + } + } diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlEntryManagerFactory.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlEntryManagerFactory.java index 5da08acdeb7..3411186f113 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlEntryManagerFactory.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlEntryManagerFactory.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlFilterConverter.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlFilterConverter.java index a115c113043..ee513740a3c 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlFilterConverter.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/impl/SqlFilterConverter.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -29,7 +29,6 @@ import com.querydsl.core.types.dsl.Expressions; import io.jans.orm.annotation.AttributeEnum; -import io.jans.orm.annotation.AttributeName; import io.jans.orm.exception.operation.SearchException; import io.jans.orm.ldap.impl.LdapFilterConverter; import io.jans.orm.reflect.property.PropertyAnnotation; @@ -178,24 +177,21 @@ private ConvertedExpression convertToSqlFilterImpl(Filter genericFilter, Map operation = ExpressionUtils.predicate(SqlOps.JSON_CONTAINS, expression, buildTypedExpression(currentGenericFilter, true), Expressions.constant("$.v")); return ConvertedExpression.build(operation, jsonAttributes); - } else { - Filter usedFilter = currentGenericFilter; - Expression expression = buildTypedPath(currentGenericFilter, propertiesAnnotationsMap, jsonAttributes, processor, skipAlias); - - return ConvertedExpression.build(ExpressionUtils.eq(expression, buildTypedExpression(usedFilter)), jsonAttributes); } + return ConvertedExpression.build(ExpressionUtils.eq(expression, buildTypedExpression(currentGenericFilter)), jsonAttributes); } if (FilterType.LESS_OR_EQUAL == type) { - if (isMultiValue(currentGenericFilter, propertiesAnnotationsMap)) { + if (multiValued) { if (currentGenericFilter.getMultiValuedCount() > 1) { Collection expressions = new ArrayList<>(currentGenericFilter.getMultiValuedCount()); for (int i = 0; i < currentGenericFilter.getMultiValuedCount(); i++) { @@ -222,7 +218,7 @@ private ConvertedExpression convertToSqlFilterImpl(Filter genericFilter, Map 1) { Collection expressions = new ArrayList<>(currentGenericFilter.getMultiValuedCount()); for (int i = 0; i < currentGenericFilter.getMultiValuedCount(); i++) { @@ -249,7 +245,7 @@ private ConvertedExpression convertToSqlFilterImpl(Filter genericFilter, Map 1) { Collection expressions = new ArrayList<>(currentGenericFilter.getMultiValuedCount()); for (int i = 0; i < currentGenericFilter.getMultiValuedCount(); i++) { @@ -295,7 +291,7 @@ private ConvertedExpression convertToSqlFilterImpl(Filter genericFilter, Map 1) { Collection expressions = new ArrayList<>(currentGenericFilter.getMultiValuedCount()); for (int i = 0; i < currentGenericFilter.getMultiValuedCount(); i++) { diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/model/ConvertedExpression.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/model/ConvertedExpression.java index cf97469520e..c912dc2e0f5 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/model/ConvertedExpression.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/model/ConvertedExpression.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/model/ResultCode.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/model/ResultCode.java index ffe1128b663..7a8b92c92c5 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/model/ResultCode.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/model/ResultCode.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/model/SearchReturnDataType.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/model/SearchReturnDataType.java index 60ccd519ec8..1e1cecd6d1e 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/model/SearchReturnDataType.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/model/SearchReturnDataType.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/model/TableMapping.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/model/TableMapping.java index 1289aa32252..11e8443bec7 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/model/TableMapping.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/model/TableMapping.java @@ -8,6 +8,8 @@ import java.util.Map; +import io.jans.orm.model.AttributeType; + /** * Mapping to DB table * @@ -18,9 +20,9 @@ public class TableMapping { private final String baseKeyName; private final String tableName; private final String objectClass; - private final Map columTypes; + private final Map columTypes; - public TableMapping(final String baseKeyName, final String tableName, final String objectClass, Map columTypes) { + public TableMapping(final String baseKeyName, final String tableName, final String objectClass, Map columTypes) { this.baseKeyName = baseKeyName; this.tableName = tableName; this.objectClass = objectClass; @@ -39,7 +41,7 @@ public String getObjectClass() { return objectClass; } - public Map getColumTypes() { + public Map getColumTypes() { return columTypes; } diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/SqlOperationService.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/SqlOperationService.java index 933d26b8050..47bf6211d34 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/SqlOperationService.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/SqlOperationService.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -90,4 +90,6 @@ PagedResult search(String key, String objectClass, ConvertedExpre DatabaseMetaData getMetadata(); + boolean isJsonColumn(String tableName, String attributeType); + } diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlConnectionProvider.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlConnectionProvider.java index f9e91f9dfa1..c084ed19713 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlConnectionProvider.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlConnectionProvider.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -38,6 +38,7 @@ import io.jans.orm.exception.KeyConversionException; import io.jans.orm.exception.operation.ConfigurationException; import io.jans.orm.exception.operation.ConnectionException; +import io.jans.orm.model.AttributeType; import io.jans.orm.operation.auth.PasswordEncryptionMethod; import io.jans.orm.sql.dsl.template.SqlJsonMySQLTemplates; import io.jans.orm.sql.model.ResultCode; @@ -53,7 +54,8 @@ */ public class SqlConnectionProvider { - private static final String JSON_TYPE_NAME = "json"; + protected static final String JSON_TYPE_NAME = "json"; + protected static final String LONGTEXT_TYPE_NAME = "longtext"; private static final Logger LOG = LoggerFactory.getLogger(SqlConnectionProvider.class); @@ -87,7 +89,7 @@ public class SqlConnectionProvider { private SQLQueryFactory sqlQueryFactory; - private Map> tableColumnsMap; + private Map> tableColumnsMap; private Map tableEnginesMap = new HashMap<>(); @@ -112,7 +114,6 @@ public void create() { } LOG.error("Failed to create connection pool with properties: '{}'. Exception: {}", clonedProperties, ex); - ex.printStackTrace(); } } @@ -227,7 +228,7 @@ private void loadTableMetaData(DatabaseMetaData databaseMetaData, Connection con ResultSet tableResultSet = databaseMetaData.getTables(null, schemaName, null, new String[]{"TABLE"}); while (tableResultSet.next()) { String tableName = tableResultSet.getString("TABLE_NAME"); - Map tableColumns = new HashMap<>(); + Map tableColumns = new HashMap<>(); String engineType = tableEnginesMap.get(tableName); @@ -235,13 +236,17 @@ private void loadTableMetaData(DatabaseMetaData databaseMetaData, Connection con ResultSet columnResultSet = databaseMetaData.getColumns(null, schemaName, tableName, null); while (columnResultSet.next()) { String columnName = columnResultSet.getString("COLUMN_NAME").toLowerCase(); - String columTypeName = columnResultSet.getString("TYPE_NAME").toLowerCase(); + String columnTypeName = columnResultSet.getString("TYPE_NAME").toLowerCase(); String remark = columnResultSet.getString("REMARKS"); - if (mariaDb && "longtext".equalsIgnoreCase(columTypeName) && "json".equalsIgnoreCase(remark)) { - columTypeName = JSON_TYPE_NAME; + if (mariaDb && LONGTEXT_TYPE_NAME.equalsIgnoreCase(columnTypeName) && JSON_TYPE_NAME.equalsIgnoreCase(remark)) { + columnTypeName = JSON_TYPE_NAME; } - tableColumns.put(columnName, columTypeName); + + boolean multiValued = SqlConnectionProvider.JSON_TYPE_NAME.equals(columnTypeName); + + AttributeType attributeType = new AttributeType(columnName, columnTypeName, multiValued); + tableColumns.put(columnName, attributeType); } tableColumnsMap.put(StringHelper.toLowerCase(tableName), tableColumns); @@ -396,7 +401,7 @@ public SQLQueryFactory getSqlQueryFactory() { public TableMapping getTableMappingByKey(String key, String objectClass) { String tableName = objectClass; - Map columTypes = tableColumnsMap.get(StringHelper.toLowerCase(tableName)); + Map columTypes = tableColumnsMap.get(StringHelper.toLowerCase(tableName)); if ("_".equals(key)) { return new TableMapping("", tableName, objectClass, columTypes); } diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlOperationServiceImpl.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlOperationServiceImpl.java index b36146f64b0..c3482f169b6 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlOperationServiceImpl.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlOperationServiceImpl.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ @@ -42,20 +42,21 @@ import com.querydsl.sql.dml.SQLUpdateClause; import io.jans.orm.exception.MappingException; -import io.jans.orm.exception.extension.PersistenceExtension; import io.jans.orm.exception.operation.DeleteException; import io.jans.orm.exception.operation.DuplicateEntryException; import io.jans.orm.exception.operation.EntryConvertationException; import io.jans.orm.exception.operation.EntryNotFoundException; import io.jans.orm.exception.operation.PersistenceException; import io.jans.orm.exception.operation.SearchException; +import io.jans.orm.extension.PersistenceExtension; import io.jans.orm.model.AttributeData; import io.jans.orm.model.AttributeDataModification; -import io.jans.orm.model.AttributeDataModification.AttributeModificationType; +import io.jans.orm.model.AttributeType; import io.jans.orm.model.BatchOperation; import io.jans.orm.model.EntryData; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SearchScope; +import io.jans.orm.model.AttributeDataModification.AttributeModificationType; import io.jans.orm.operation.auth.PasswordEncryptionHelper; import io.jans.orm.sql.impl.SqlBatchOperationWraper; import io.jans.orm.sql.model.ConvertedExpression; @@ -175,13 +176,13 @@ public boolean addEntry(String key, String objectClass, Collection attributes) throws PersistenceException { try { - Map columTypes = tableMapping.getColumTypes(); + Map columTypes = tableMapping.getColumTypes(); RelationalPathBase tableRelationalPath = buildTableRelationalPath(tableMapping); SQLInsertClause sqlInsertQuery = this.sqlQueryFactory.insert(tableRelationalPath); for (AttributeData attribute : attributes) { - String attributeType = columTypes.get(attribute.getName().toLowerCase()); + String attributeType = columTypes.get(attribute.getName().toLowerCase()).getType(); boolean multiValued = (attributeType != null) && isJsonColumn(tableMapping.getTableName(), attributeType); sqlInsertQuery.columns(Expressions.stringPath(attribute.getName())); @@ -215,7 +216,7 @@ public boolean updateEntry(String key, String objectClass, List mods) throws PersistenceException { try { - Map columTypes = tableMapping.getColumTypes(); + Map columTypes = tableMapping.getColumTypes(); RelationalPathBase tableRelationalPath = buildTableRelationalPath(tableMapping); SQLUpdateClause sqlUpdateQuery = this.sqlQueryFactory.update(tableRelationalPath); @@ -224,7 +225,7 @@ private boolean updateEntryImpl(TableMapping tableMapping, String key, List PagedResult searchImpl(TableMapping tableMapping, String boolean collectSearchResult; SQLQuery query; + ResultSet resultSet = null; int currentLimit; try { int resultCount = 0; @@ -443,9 +445,8 @@ private PagedResult searchImpl(TableMapping tableMapping, String queryStr = query.getSQL().getSQL(); LOG.debug("Executing query: '" + queryStr + "'"); - try (ResultSet resultSet = query.getResults()) { - lastResult = getEntryDataList(tableMapping, resultSet); - } + resultSet = query.getResults(); + lastResult = getEntryDataList(tableMapping, resultSet); lastCountRows = lastResult.size(); @@ -471,6 +472,14 @@ private PagedResult searchImpl(TableMapping tableMapping, String throw new SearchException(String.format("Failed to build search entries query. Key: '%s', expression: '%s'", key, expression.expression()), ex); } catch (SQLException | EntryConvertationException ex) { throw new SearchException(String.format("Failed to execute query '%s' with key: '%s'", queryStr, key), ex); + } finally { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException ex) { + throw new SearchException(String.format("Failed to close query after paged result collection. Query '%s' with key: '%s'", queryStr, key), ex); + } + } } } else { try { @@ -872,12 +881,12 @@ private Object[] convertDbJsonToValue(String jsonValue) { } } - private boolean isJsonColumn(String tableName, String columnTypeName) { + public boolean isJsonColumn(String tableName, String columnTypeName) { if (columnTypeName == null) { return false; } - - if (mariaDb && "longtext".equals(columnTypeName)) { + + if (mariaDb && SqlConnectionProvider.LONGTEXT_TYPE_NAME.equals(columnTypeName)) { return true; } @@ -886,7 +895,7 @@ private boolean isJsonColumn(String tableName, String columnTypeName) { // return "longtext".equals(columnTypeName); // } - return "json".equals(columnTypeName); + return SqlConnectionProvider.JSON_TYPE_NAME.equals(columnTypeName); } diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/watch/OperationDurationUtil.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/watch/OperationDurationUtil.java index 0643d063487..9b729d638e9 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/watch/OperationDurationUtil.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/watch/OperationDurationUtil.java @@ -1,5 +1,5 @@ /* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. * * Copyright (c) 2020, Janssen Project */ diff --git a/jans-orm/sql/src/test/java/io/jans/orm/sql/impl/test/SqlFilterConverterTest.java b/jans-orm/sql/src/test/java/io/jans/orm/sql/impl/test/SqlFilterConverterTest.java index b4e4f21c1a5..a008f1da773 100644 --- a/jans-orm/sql/src/test/java/io/jans/orm/sql/impl/test/SqlFilterConverterTest.java +++ b/jans-orm/sql/src/test/java/io/jans/orm/sql/impl/test/SqlFilterConverterTest.java @@ -454,7 +454,7 @@ public void checkOrWithLowerCaseFilter() throws SearchException { ConvertedExpression expression = simpleConverter.convertToSqlFilter(filter, null, null); String query = toSelectSQL(expression); - assertEquals(query, "select doc.`*` from `table` as doc where (lower(doc.description) like '%test_value%' or lower(doc.displayName) like '%test_value%') and doc.jansScrTyp = 'person_authentication'"); + assertEquals(query, "select doc.`*` from `table` as doc where (lower(doc.description) like '%test_value%' or lower(doc.displayName) like '%test_value%') and doc.gluuScrTyp = 'person_authentication'"); } private String toSelectSQL(ConvertedExpression convertedExpression) { diff --git a/jans-orm/util/src/main/java/io/jans/orm/util/CertUtils.java b/jans-orm/util/src/main/java/io/jans/orm/util/CertUtils.java new file mode 100644 index 00000000000..fec043639d8 --- /dev/null +++ b/jans-orm/util/src/main/java/io/jans/orm/util/CertUtils.java @@ -0,0 +1,70 @@ +package io.jans.orm.util; + +import java.io.File; +import java.io.FileInputStream; +import java.security.KeyStore; +import java.security.cert.CertificateException; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; + +/** + * Utility methods to help work with certs + * + * @author Yuriy Movchan Date: 07/07/2021 + */ +public class CertUtils { + + public static boolean isFips() { + java.security.Provider[] providers = java.security.Security.getProviders(); + for (int i = 0; i < providers.length; i++) { + if (providers[i].getName().toLowerCase().contains("fips")) + return true; + } + + return false; + } + + public static TrustManager[] getTrustManagers(String trustStoreFile, String trustStorePin, String trustStoreType) + throws CertificateException { + String useTrustStoreType = trustStoreType; + if (useTrustStoreType == null) { + useTrustStoreType = KeyStore.getDefaultType(); + } + + char[] useTrustStorePin = null; + if (StringHelper.isNotEmpty(trustStorePin)) { + useTrustStorePin = trustStorePin.toCharArray(); + } + + KeyStore keyStore; + try { + keyStore = KeyStore.getInstance(useTrustStoreType); + if ("pkcs11".equalsIgnoreCase(useTrustStoreType)) { + keyStore.load(null, useTrustStorePin); + } else { + final File f = new File(trustStoreFile); + if (!f.exists()) { + throw new CertificateException(String.format("Trustore file '%s' is not exists", trustStoreFile)); + } + try (FileInputStream inputStream = new FileInputStream(f)) { + keyStore.load(inputStream, useTrustStorePin); + } + } + } catch (Exception ex) { + throw new CertificateException("Failed to load truststore", ex); + } + + try { + String trustManagerAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(trustManagerAlgorithm); + trustManagerFactory.init(keyStore); + TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); + + return trustManagers; + } catch (Exception ex) { + throw new CertificateException("Failed to prepare truststore", ex); + } + } + +} diff --git a/jans-orm/util/src/main/java/io/jans/orm/util/StringHelper.java b/jans-orm/util/src/main/java/io/jans/orm/util/StringHelper.java index dbfd6342fd8..7397bfa1d4d 100644 --- a/jans-orm/util/src/main/java/io/jans/orm/util/StringHelper.java +++ b/jans-orm/util/src/main/java/io/jans/orm/util/StringHelper.java @@ -349,10 +349,18 @@ public static boolean toBoolean(Boolean value, boolean defaultValue) { } public static boolean isEmptyString(Object string) { + if (string == null) { + return false; + } + return !(string instanceof String) || isEmpty((String) string); } public static boolean isNotEmptyString(Object string) { + if (string == null) { + return false; + } + return !(string instanceof String) || isNotEmpty((String) string); }