• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ben-manes / caffeine / #5173

29 Dec 2025 05:27AM UTC coverage: 0.0% (-100.0%) from 100.0%
#5173

push

github

ben-manes
speed up development ci build

0 of 3838 branches covered (0.0%)

0 of 7869 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/jcache/src/main/java/com/github/benmanes/caffeine/jcache/copy/AbstractCopier.java
1
/*
2
 * Copyright 2015 Ben Manes. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.github.benmanes.caffeine.jcache.copy;
17

18
import static java.util.Objects.requireNonNull;
19

20
import java.lang.reflect.Array;
21
import java.math.BigDecimal;
22
import java.math.BigInteger;
23
import java.net.Inet4Address;
24
import java.net.Inet6Address;
25
import java.net.InetSocketAddress;
26
import java.net.URI;
27
import java.net.URL;
28
import java.time.Duration;
29
import java.time.Instant;
30
import java.time.LocalDate;
31
import java.time.LocalDateTime;
32
import java.time.LocalTime;
33
import java.util.Date;
34
import java.util.GregorianCalendar;
35
import java.util.Map;
36
import java.util.Set;
37
import java.util.UUID;
38
import java.util.function.Function;
39
import java.util.regex.Pattern;
40

41
import org.jspecify.annotations.NullMarked;
42

43
/**
44
 * A skeleton implementation where subclasses provide the serialization strategy. Serialization is
45
 * not performed if the type is a known immutable, an array of known immutable types, or specially
46
 * handled by a known cloning strategy.
47
 *
48
 * @author ben.manes@gmail.com (Ben Manes)
49
 */
50
@NullMarked
51
@SuppressWarnings({"ImmutableMemberCollection", "JavaUtilDate"})
52
public abstract class AbstractCopier<A> implements Copier {
53
  private static final Map<Class<?>, Function<Object, Object>> JAVA_DEEP_COPY = Map.of(Date.class,
×
54
      o -> ((Date) o).clone(), GregorianCalendar.class, o -> ((GregorianCalendar) o).clone());
×
55
  private static final Set<Class<?>> JAVA_IMMUTABLE = Set.of(Boolean.class, Byte.class,
×
56
      Character.class, Double.class, Float.class, Short.class, Integer.class, Long.class,
57
      BigInteger.class, BigDecimal.class, String.class, Class.class, UUID.class, URL.class,
58
      URI.class, Pattern.class, Inet4Address.class, Inet6Address.class, InetSocketAddress.class,
59
      LocalDate.class, LocalTime.class, LocalDateTime.class, Instant.class, Duration.class);
60

61
  private final Set<Class<?>> immutableClasses;
62
  private final Map<Class<?>, Function<Object, Object>> deepCopyStrategies;
63

64
  protected AbstractCopier() {
65
    this(javaImmutableClasses(), javaDeepCopyStrategies());
×
66
  }
×
67

68
  protected AbstractCopier(Set<Class<?>> immutableClasses,
69
      Map<Class<?>, Function<Object, Object>> deepCopyStrategies) {
×
70
    this.immutableClasses = requireNonNull(immutableClasses);
×
71
    this.deepCopyStrategies = requireNonNull(deepCopyStrategies);
×
72
  }
×
73

74
  /** Returns the set of Java native classes that are immutable. */
75
  public static Set<Class<?>> javaImmutableClasses() {
76
    return JAVA_IMMUTABLE;
×
77
  }
78

79
  /** Returns the set of Java native classes that are deeply copied. */
80
  public static Map<Class<?>, Function<Object, Object>> javaDeepCopyStrategies() {
81
    return JAVA_DEEP_COPY;
×
82
  }
83

84
  @Override
85
  public <T> T copy(T object, ClassLoader classLoader) {
86
    requireNonNull(object);
×
87
    requireNonNull(classLoader);
×
88

89
    if (isImmutable(object.getClass())) {
×
90
      return object;
×
91
    } else if (isArrayOfImmutableTypes(object.getClass())) {
×
92
      return arrayCopy(object);
×
93
    }
94

95
    var deeplyCopyStrategy = deepCopyStrategies.get(object.getClass());
×
96
    if (deeplyCopyStrategy != null) {
×
97
      @SuppressWarnings("unchecked")
98
      var copy = (T) deeplyCopyStrategy.apply(object);
×
99
      return copy;
×
100
    }
101

102
    return roundtrip(object, classLoader);
×
103
  }
104

105
  /**
106
   * Returns if the class is an immutable type and does not need to be copied.
107
   *
108
   * @param clazz the class of the object being copied
109
   * @return if the class is an immutable type and does not need to be copied
110
   */
111
  protected boolean isImmutable(Class<?> clazz) {
112
    return immutableClasses.contains(clazz) || clazz.isEnum();
×
113
  }
114

115
  /**
116
   * Returns if the class has a known deep copy strategy.
117
   *
118
   * @param clazz the class of the object being copied
119
   * @return if the class has a known deep copy strategy
120
   */
121
  protected boolean canDeeplyCopy(Class<?> clazz) {
122
    return deepCopyStrategies.containsKey(clazz);
×
123
  }
124

125
  /** @return if the class represents an array of immutable values. */
126
  private boolean isArrayOfImmutableTypes(Class<?> clazz) {
127
    if (!clazz.isArray()) {
×
128
      return false;
×
129
    }
130
    Class<?> component = clazz.getComponentType();
×
131
    return component.isPrimitive() || isImmutable(component);
×
132
  }
133

134
  /** @return a shallow copy of the array. */
135
  @SuppressWarnings("SuspiciousSystemArraycopy")
136
  private static <T> T arrayCopy(T object) {
137
    int length = Array.getLength(object);
×
138
    @SuppressWarnings("unchecked")
139
    var copy = (T) Array.newInstance(object.getClass().getComponentType(), length);
×
140
    System.arraycopy(object, 0, copy, 0, length);
×
141
    return copy;
×
142
  }
143

144
  /**
145
   * Performs the serialization and deserialization, returning the copied object.
146
   *
147
   * @param object the object to serialize
148
   * @param classLoader the classloader to create the instance with
149
   * @param <T> the type of object being copied
150
   * @return the deserialized object
151
   */
152
  protected <T> T roundtrip(T object, ClassLoader classLoader) {
153
    A data = serialize(object);
×
154
    @SuppressWarnings("unchecked")
155
    var copy = (T) deserialize(data, classLoader);
×
156
    return copy;
×
157
  }
158

159
  /**
160
   * Serializes the object.
161
   *
162
   * @param object the object to serialize
163
   * @return the serialized bytes
164
   */
165
  protected abstract A serialize(Object object);
166

167
  /**
168
   * Deserializes the data using the provided classloader.
169
   *
170
   * @param data the serialized bytes
171
   * @param classLoader the classloader to create the instance with
172
   * @return the deserialized object
173
   */
174
  protected abstract Object deserialize(A data, ClassLoader classLoader);
175
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc