Skip to content

Commit 971b882

Browse files
committed
Reviewing persistence implementations
1 parent e2739df commit 971b882

71 files changed

Lines changed: 955 additions & 552 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/crosschecks.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
fail-fast: false
3232
matrix:
3333
language: ['java']
34-
java: [ '25', '28-ea' ]
34+
java: [ '25', '27' ]
3535
os: [ubuntu-latest, windows-latest, macos-latest]
3636

3737
steps:

‎core/idrepo/logic/src/test/java/org/apache/syncope/core/logic/ReportLogicTest.java‎

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,6 @@ public static void unsetAuthContext() {
8989
@Autowired
9090
private ReportLogic logic;
9191

92-
private void checkExport(final String execKey) throws IOException {
93-
ByteArrayOutputStream os = new ByteArrayOutputStream();
94-
95-
logic.exportExecutionResult(os, execKey);
96-
97-
os.close();
98-
byte[] entity = os.toByteArray();
99-
assertTrue(entity.length > 0);
100-
}
101-
10292
@Test
10393
void executeAndExport() throws Exception {
10494
ReportTO report = logic.read("0062ea9c-924d-4ecf-9961-4492a8cc6d1b");
@@ -123,6 +113,12 @@ void executeAndExport() throws Exception {
123113

124114
String execKey = report.getExecutions().getFirst().getKey();
125115

126-
checkExport(execKey);
116+
ByteArrayOutputStream os = new ByteArrayOutputStream();
117+
118+
logic.exportExecutionResult(os, execKey);
119+
120+
os.close();
121+
byte[] entity = os.toByteArray();
122+
assertTrue(entity.length > 0);
127123
}
128124
}

‎core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupOutInterceptor.java‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import org.apache.cxf.message.Message;
2323
import org.apache.cxf.phase.AbstractPhaseInterceptor;
2424
import org.apache.cxf.phase.Phase;
25-
import org.apache.syncope.core.persistence.api.utils.FormatUtils;
2625
import org.identityconnectors.common.l10n.CurrentLocale;
2726
import org.identityconnectors.framework.impl.api.local.ThreadClassLoaderManager;
2827
import org.slf4j.MDC;
@@ -38,8 +37,6 @@ public ThreadLocalCleanupOutInterceptor() {
3837

3938
@Override
4039
public void handleMessage(final Message message) throws Fault {
41-
FormatUtils.clear();
42-
4340
ThreadClassLoaderManager.clearInstance();
4441
CurrentLocale.clear();
4542

‎core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SyncopeAbstractSearchCondVisitor.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
public abstract class SyncopeAbstractSearchCondVisitor
5151
extends AbstractSearchConditionVisitor<SearchBean, SearchCond> {
5252

53-
protected static final ThreadLocal<SearchCond> SEARCH_COND = new ThreadLocal<>();
53+
protected SearchCond searchCond;
5454

5555
protected static AttrCond createAttrCond(final String schema) {
5656
AttrCond attrCond = SearchableFields.contains(schema)
@@ -264,11 +264,11 @@ protected SearchCond visitCompound(final SearchCondition<SearchBean> sc) {
264264

265265
@Override
266266
public void visit(final SearchCondition<SearchBean> sc) {
267-
SEARCH_COND.set(sc.getStatement() == null ? visitCompound(sc) : visitPrimitive(sc));
267+
searchCond = sc.getStatement() == null ? visitCompound(sc) : visitPrimitive(sc);
268268
}
269269

270270
@Override
271271
public SearchCond getQuery() {
272-
return SEARCH_COND.get();
272+
return searchCond;
273273
}
274274
}

‎core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SyncopePage.java‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,15 @@ public int getTotalPages() {
4747

4848
@Override
4949
public boolean equals(final Object obj) {
50+
if (this == obj) {
51+
return true;
52+
}
53+
if (!(obj instanceof SyncopePage<?> other)) {
54+
return false;
55+
}
5056
return new EqualsBuilder().
5157
appendSuper(super.equals(obj)).
52-
append(total, total).
58+
append(total, other.total).
5359
build();
5460
}
5561

‎core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/utils/FormatUtils.java‎

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,6 @@ public final class FormatUtils {
4141

4242
private static final String NO_CONVERSION_PATTERN = "#,##0.###";
4343

44-
private static final ThreadLocal<DecimalFormat> DECIMAL_FORMAT = ThreadLocal.withInitial(() -> {
45-
DecimalFormat df = new DecimalFormat(NO_CONVERSION_PATTERN);
46-
df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
47-
return df;
48-
});
49-
5044
public static final ZoneOffset DEFAULT_OFFSET = OffsetDateTime.now().getOffset();
5145

5246
public static String format(final TemporalAccessor temporal) {
@@ -64,41 +58,19 @@ public static String format(final long number) {
6458
}
6559

6660
public static String format(final long number, final String conversionPattern) {
67-
DecimalFormat df = DECIMAL_FORMAT.get();
68-
69-
String previous = df.toPattern();
70-
if (!previous.equals(conversionPattern)) {
71-
df.applyPattern(conversionPattern);
72-
}
73-
74-
String formatted = df.format(number);
75-
76-
if (!previous.equals(conversionPattern)) {
77-
df.applyPattern(previous);
78-
}
79-
80-
return formatted;
61+
final DecimalFormat df = new DecimalFormat(conversionPattern);
62+
df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
63+
return df.format(number);
8164
}
8265

8366
public static String format(final double number) {
8467
return format(number, NO_CONVERSION_PATTERN);
8568
}
8669

8770
public static String format(final double number, final String conversionPattern) {
88-
DecimalFormat df = DECIMAL_FORMAT.get();
89-
90-
String previous = df.toPattern();
91-
if (!previous.equals(conversionPattern)) {
92-
df.applyPattern(conversionPattern);
93-
}
94-
95-
String formatted = df.format(number);
96-
97-
if (!previous.equals(conversionPattern)) {
98-
df.applyPattern(previous);
99-
}
100-
101-
return formatted;
71+
final DecimalFormat df = new DecimalFormat(conversionPattern);
72+
df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
73+
return df.format(number);
10274
}
10375

10476
public static OffsetDateTime parseDate(final String source)
@@ -141,15 +113,11 @@ public static OffsetDateTime parseDate(final String source, final String convers
141113
}
142114

143115
public static Number parseNumber(final String source, final String conversionPattern) throws ParseException {
144-
DecimalFormat df = DECIMAL_FORMAT.get();
145-
df.applyPattern(conversionPattern);
116+
final DecimalFormat df = new DecimalFormat(conversionPattern);
117+
df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
146118
return df.parse(source);
147119
}
148120

149-
public static void clear() {
150-
DECIMAL_FORMAT.remove();
151-
}
152-
153121
private FormatUtils() {
154122
// private empty constructor
155123
}

‎core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAnyMatchDAO.java‎

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
import jakarta.validation.constraints.Min;
2424
import java.beans.PropertyDescriptor;
2525
import java.lang.annotation.Annotation;
26+
import java.lang.reflect.Field;
2627
import java.lang.reflect.InvocationTargetException;
2728
import java.lang.reflect.Method;
2829
import java.time.OffsetDateTime;
2930
import java.util.ArrayList;
3031
import java.util.List;
32+
import java.util.Locale;
3133
import java.util.Optional;
3234
import java.util.Set;
3335
import java.util.regex.Pattern;
@@ -181,12 +183,6 @@ public <T extends Any> boolean matches(final T any, final SearchCond cond) {
181183
orElse(null));
182184
}
183185

184-
if (match == null) {
185-
match = cond.asLeaf(AttrCond.class).
186-
map(leaf -> matches(any, leaf, not)).
187-
orElse(null);
188-
}
189-
190186
return BooleanUtils.toBoolean(match);
191187
}
192188
case AND -> {
@@ -299,7 +295,7 @@ protected boolean matches(
299295
case LIKE, ILIKE -> {
300296
if (schema.getType().isStringClass()) {
301297
StringBuilder output = new StringBuilder();
302-
for (char c : cond.getExpression().toLowerCase().toCharArray()) {
298+
for (char c : cond.getExpression().toLowerCase(Locale.ROOT).toCharArray()) {
303299
if (c == '%') {
304300
output.append(".*");
305301
} else if (Character.isLetter(c)) {
@@ -428,11 +424,19 @@ protected boolean matches(final Any any, final AnyCond cond, final boolean not)
428424
boolean foundBooleanMin = false;
429425
boolean foundBooleanMax = false;
430426
if (Integer.class.equals(pd.getPropertyType())) {
431-
for (Annotation annotation : pd.getPropertyType().getAnnotations()) {
432-
if (Min.class.equals(annotation.annotationType())) {
433-
foundBooleanMin = ((Min) annotation).value() == 0;
434-
} else if (Max.class.equals(annotation.annotationType())) {
435-
foundBooleanMax = ((Max) annotation).value() == 1;
427+
for (Class<?> clazz = any.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
428+
try {
429+
final Field field = clazz.getDeclaredField(pd.getName());
430+
for (final Annotation annotation : field.getAnnotations()) {
431+
if (Min.class.equals(annotation.annotationType())) {
432+
foundBooleanMin = ((Min) annotation).value() == 0;
433+
} else if (Max.class.equals(annotation.annotationType())) {
434+
foundBooleanMax = ((Max) annotation).value() == 1;
435+
}
436+
}
437+
break;
438+
} catch (final NoSuchFieldException e) {
439+
// continue walking up the class hierarchy
436440
}
437441
}
438442
}

‎core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractAnySearchDAO.java‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020

2121
import java.util.ArrayList;
2222
import java.util.Comparator;
23+
import java.util.HashMap;
2324
import java.util.HashSet;
2425
import java.util.List;
26+
import java.util.Map;
2527
import java.util.Set;
2628
import java.util.function.Function;
2729
import java.util.stream.Collectors;
@@ -272,11 +274,17 @@ protected <T extends Any> List<T> buildResult(final List<Object> raw, final AnyT
272274
map(key -> key instanceof Object[] array ? (String) (array)[0] : ((String) key)).
273275
toList();
274276

277+
Map<String, Integer> keyPositions = new HashMap<>();
278+
for (int i = 0; i < keys.size(); i++) {
279+
keyPositions.put(keys.get(i), i);
280+
}
281+
275282
// sort anys according to keys' sorting, as their ordering is same as raw, e.g. the actual query results
276283
List<Any> anys = anyUtilsFactory.getInstance(kind).dao().findByKeys(keys).stream().
277-
sorted(Comparator.comparing(any -> keys.indexOf(any.getKey()))).toList();
284+
sorted(Comparator.comparingInt(any -> keyPositions.getOrDefault(any.getKey(), -1))).toList();
278285

279-
keys.stream().filter(key -> anys.stream().noneMatch(any -> key.equals(any.getKey()))).
286+
Set<String> foundKeys = anys.stream().map(Any::getKey).collect(Collectors.toSet());
287+
keys.stream().filter(key -> !foundKeys.contains(key)).
280288
forEach(key -> LOG.error("Could not find {} with id {}, even if returned by native query", kind, key));
281289

282290
return (List<T>) anys;

‎core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/dao/AbstractSearchDAO.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ protected List<SearchCond> buildDerAttrValueConditions(
197197
// Contains used identifiers in order to avoid replications
198198
Set<String> used = new HashSet<>();
199199

200-
// Create several clauses: one for eanch identifiers
200+
// Create several clauses: one for each identifier
201201
for (int i = 0; i < identifiers.size() && !used.contains(identifiers.get(i)); i++) {
202202
used.add(identifiers.get(i));
203203

@@ -251,7 +251,7 @@ protected CheckResult<AnyCond> check(final AnyCond cond, final Field field, fina
251251
PlainSchema schema = entityFactory.newEntity(PlainSchema.class);
252252
schema.setKey(field.getName());
253253
for (AttrSchemaType attrSchemaType : AttrSchemaType.values()) {
254-
if (field.getType().isAssignableFrom(attrSchemaType.getType())) {
254+
if (attrSchemaType.getType().isAssignableFrom(field.getType())) {
255255
schema.setType(attrSchemaType);
256256
}
257257
}

core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/openjpa/ImplementationManagerCacheEntryListener.java renamed to core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/ImplementationManagerCacheEntryListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19-
package org.apache.syncope.core.persistence.jpa.openjpa;
19+
package org.apache.syncope.core.persistence.jpa;
2020

2121
import jakarta.persistence.EntityManagerFactory;
2222
import java.io.Serializable;

0 commit comments

Comments
 (0)