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

wuwen5 / hessian / 18062024814

27 Sep 2025 03:33AM UTC coverage: 71.737% (+0.4%) from 71.311%
18062024814

push

github

web-flow
feat: add InetSocketAddress serialization and deserialization support (#61)

* feat: add InetSocketAddress serialization and deserialization support

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

1764 of 2651 branches covered (66.54%)

Branch coverage included in aggregate %.

4244 of 5724 relevant lines covered (74.14%)

3.2 hits per line

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

83.15
hessian2-codec/src/main/java/io/github/wuwen5/hessian/io/ContextSerializerFactory.java
1
/*
2
 * Copyright (c) 2001-2008 Caucho Technology, Inc.  All rights reserved.
3
 *
4
 * The Apache Software License, Version 1.1
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 *
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in
15
 *    the documentation and/or other materials provided with the
16
 *    distribution.
17
 *
18
 * 3. The end-user documentation included with the redistribution, if
19
 *    any, must include the following acknowlegement:
20
 *       "This product includes software developed by the
21
 *        Caucho Technology (http://www.caucho.com/)."
22
 *    Alternately, this acknowlegement may appear in the software itself,
23
 *    if and wherever such third-party acknowlegements normally appear.
24
 *
25
 * 4. The names "Burlap", "Resin", and "Caucho" must not be used to
26
 *    endorse or promote products derived from this software without prior
27
 *    written permission. For written permission, please contact
28
 *    info@caucho.com.
29
 *
30
 * 5. Products derived from this software may not be called "Resin"
31
 *    nor may "Resin" appear in their names without prior written
32
 *    permission of Caucho Technology.
33
 *
34
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
35
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37
 * DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
38
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
39
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
44
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
 *
46
 * @author Scott Ferguson
47
 */
48

49
package io.github.wuwen5.hessian.io;
50

51
import io.github.wuwen5.hessian.HessianException;
52
import io.github.wuwen5.hessian.io.net.InetAddressDeserializer;
53
import io.github.wuwen5.hessian.io.net.InetAddressSerializer;
54
import io.github.wuwen5.hessian.io.net.InetSocketAddressDeserializer;
55
import io.github.wuwen5.hessian.io.net.InetSocketAddressSerializer;
56
import java.io.InputStream;
57
import java.lang.ref.SoftReference;
58
import java.lang.ref.WeakReference;
59
import java.net.Inet4Address;
60
import java.net.Inet6Address;
61
import java.net.InetSocketAddress;
62
import java.net.URL;
63
import java.util.Enumeration;
64
import java.util.HashMap;
65
import java.util.HashSet;
66
import java.util.Map;
67
import java.util.Properties;
68
import java.util.Set;
69
import java.util.WeakHashMap;
70
import java.util.concurrent.ConcurrentHashMap;
71
import java.util.concurrent.ConcurrentMap;
72
import java.util.logging.Level;
73
import java.util.logging.Logger;
74

75
/**
76
 * The classloader-specific Factory for returning serialization
77
 */
78
public class ContextSerializerFactory {
79
    private static final Logger log = Logger.getLogger(ContextSerializerFactory.class.getName());
4✔
80

81
    private static final WeakHashMap<ClassLoader, SoftReference<ContextSerializerFactory>> CONTEXT_REF_MAP =
4✔
82
            new WeakHashMap<>();
83

84
    private static final ClassLoader SYSTEM_CLASS_LOADER;
85

86
    private static Map<String, HessianSerializer> staticSerializerMap;
87
    private static Map<String, HessianDeserializer> staticDeserializerMap;
88
    private static Map<String, HessianDeserializer> staticClassNameMap;
89

90
    private ContextSerializerFactory parent;
91
    private final WeakReference<ClassLoader> loaderRef;
92

93
    private final Set<String> serializerFiles = new HashSet<>();
5✔
94
    private final Set<String> deserializerFiles = new HashSet<>();
5✔
95

96
    private final Map<String, HessianSerializer> serializerClassMap = new HashMap<>();
5✔
97

98
    private final ConcurrentMap<String, HessianSerializer> customSerializerMap = new ConcurrentHashMap<>();
5✔
99

100
    private final Map<Class<?>, HessianSerializer> serializerInterfaceMap = new HashMap<>();
5✔
101

102
    private final Map<String, HessianDeserializer> deserializerClassMap = new HashMap<>();
5✔
103

104
    private final Map<String, HessianDeserializer> deserializerClassNameMap = new HashMap<>();
5✔
105

106
    private final ConcurrentMap<String, HessianDeserializer> customDeserializerMap = new ConcurrentHashMap<>();
5✔
107

108
    private final Map<String, HessianDeserializer> deserializerInterfaceMap = new HashMap<>();
5✔
109

110
    public ContextSerializerFactory(ContextSerializerFactory parent, ClassLoader loader) {
2✔
111
        if (loader == null) {
2✔
112
            loader = SYSTEM_CLASS_LOADER;
2✔
113
        }
114

115
        loaderRef = new WeakReference<>(loader);
6✔
116

117
        init();
2✔
118
    }
1✔
119

120
    public static ContextSerializerFactory create() {
121
        return create(Thread.currentThread().getContextClassLoader());
4✔
122
    }
123

124
    public static ContextSerializerFactory create(ClassLoader loader) {
125
        synchronized (CONTEXT_REF_MAP) {
4✔
126
            SoftReference<ContextSerializerFactory> factoryRef = CONTEXT_REF_MAP.get(loader);
5✔
127

128
            ContextSerializerFactory factory = null;
2✔
129

130
            if (factoryRef != null) {
2✔
131
                factory = factoryRef.get();
4✔
132
            }
133

134
            if (factory == null) {
2✔
135
                ContextSerializerFactory parent = null;
2✔
136

137
                if (loader != null) {
2✔
138
                    parent = create(loader.getParent());
4✔
139
                }
140

141
                factory = new ContextSerializerFactory(parent, loader);
6✔
142
                factoryRef = new SoftReference<>(factory);
5✔
143

144
                CONTEXT_REF_MAP.put(loader, factoryRef);
5✔
145
            }
146

147
            return factory;
4✔
148
        }
149
    }
150

151
    public ClassLoader getClassLoader() {
152

153
        if (this.loaderRef != null) {
3!
154
            return this.loaderRef.get();
5✔
155
        } else {
156
            return null;
×
157
        }
158
    }
159

160
    /**
161
     * Returns the serializer for a given class.
162
     */
163
    public HessianSerializer getSerializer(String className) {
164
        HessianSerializer serializer = serializerClassMap.get(className);
6✔
165

166
        if (serializer == AbstractSerializer.NULL) {
3!
167
            return null;
×
168
        } else {
169
            return serializer;
2✔
170
        }
171
    }
172

173
    /**
174
     * Returns a custom serializer the class
175
     *
176
     * @param cl the class of the object that needs to be serialized.
177
     *
178
     * @return a serializer object for the serialization.
179
     */
180
    public HessianSerializer getCustomSerializer(Class<?> cl) {
181
        HessianSerializer serializer = customSerializerMap.get(cl.getName());
7✔
182

183
        if (serializer == AbstractSerializer.NULL) {
3✔
184
            return null;
2✔
185
        } else if (serializer != null) {
2!
186
            return serializer;
×
187
        }
188

189
        try {
190
            Class<?> serClass = Class.forName(cl.getName() + "HessianSerializer", false, cl.getClassLoader());
8✔
191

192
            HessianSerializer ser =
3✔
193
                    (HessianSerializer) serClass.getDeclaredConstructor().newInstance();
6✔
194

195
            customSerializerMap.put(cl.getName(), ser);
7✔
196

197
            return ser;
2✔
198
        } catch (ClassNotFoundException e) {
1✔
199
            log.log(Level.ALL, e.toString(), e);
6✔
200
        } catch (Exception e) {
×
201
            throw new HessianException(e);
×
202
        }
1✔
203

204
        customSerializerMap.put(cl.getName(), AbstractSerializer.NULL);
7✔
205

206
        return null;
2✔
207
    }
208

209
    /**
210
     * Returns the deserializer for a given class.
211
     */
212
    public HessianDeserializer getDeserializer(String className) {
213
        HessianDeserializer deserializer = deserializerClassMap.get(className);
6✔
214

215
        if (deserializer != null && deserializer != BaseDeserializer.NULL) {
5!
216
            return deserializer;
2✔
217
        }
218

219
        deserializer = deserializerInterfaceMap.get(className);
6✔
220

221
        if (deserializer != null && deserializer != BaseDeserializer.NULL) {
2!
222
            return deserializer;
×
223
        }
224

225
        return null;
2✔
226
    }
227

228
    /**
229
     * Returns a custom deserializer the class
230
     *
231
     * @param cl the class of the object that needs to be deserialized.
232
     *
233
     * @return a deserializer object for the deserialization.
234
     */
235
    public HessianDeserializer getCustomDeserializer(Class<?> cl) {
236
        HessianDeserializer deserializer = customDeserializerMap.get(cl.getName());
7✔
237

238
        if (deserializer == BaseDeserializer.NULL) {
3✔
239
            return null;
2✔
240
        } else if (deserializer != null) {
2!
241
            return deserializer;
×
242
        }
243

244
        try {
245
            Class<?> serClass = Class.forName(cl.getName() + "HessianDeserializer", false, cl.getClassLoader());
8✔
246

247
            HessianDeserializer ser =
3✔
248
                    (HessianDeserializer) serClass.getDeclaredConstructor().newInstance();
6✔
249

250
            customDeserializerMap.put(cl.getName(), ser);
7✔
251

252
            return ser;
2✔
253
        } catch (ClassNotFoundException e) {
1✔
254
            log.log(Level.ALL, e.toString(), e);
6✔
255
        } catch (Exception e) {
×
256
            throw new HessianException(e);
×
257
        }
1✔
258

259
        customDeserializerMap.put(cl.getName(), BaseDeserializer.NULL);
7✔
260

261
        return null;
2✔
262
    }
263

264
    /**
265
     * Initialize the factory
266
     */
267
    private void init() {
268
        if (parent != null) {
3!
269
            serializerFiles.addAll(parent.serializerFiles);
×
270
            deserializerFiles.addAll(parent.deserializerFiles);
×
271

272
            serializerClassMap.putAll(parent.serializerClassMap);
×
273
            deserializerClassMap.putAll(parent.deserializerClassMap);
×
274
        }
275

276
        if (parent == null) {
3!
277
            serializerClassMap.putAll(staticSerializerMap);
4✔
278
            deserializerClassMap.putAll(staticDeserializerMap);
4✔
279
            deserializerClassNameMap.putAll(staticClassNameMap);
4✔
280
        }
281

282
        Map<Class<?>, Class<?>> classMap = new HashMap<>();
4✔
283
        initSerializerFiles("META-INF/hessian/serializers", serializerFiles, classMap, HessianSerializer.class);
7✔
284

285
        for (Map.Entry<Class<?>, Class<?>> entry : classMap.entrySet()) {
11✔
286
            try {
287
                HessianSerializer ser = (HessianSerializer)
1✔
288
                        entry.getValue().getDeclaredConstructor().newInstance();
10✔
289

290
                if (entry.getKey().isInterface()) {
5✔
291
                    serializerInterfaceMap.put(entry.getKey(), ser);
9✔
292
                } else {
293
                    serializerClassMap.put(entry.getKey().getName(), ser);
9✔
294
                }
295
            } catch (Exception e) {
×
296
                throw new HessianException(e);
×
297
            }
1✔
298
        }
1✔
299

300
        classMap = new HashMap<>();
4✔
301
        initSerializerFiles("META-INF/hessian/deserializers", deserializerFiles, classMap, HessianDeserializer.class);
7✔
302

303
        for (Map.Entry<Class<?>, Class<?>> entry : classMap.entrySet()) {
11✔
304
            try {
305
                HessianDeserializer ser = (HessianDeserializer)
1✔
306
                        entry.getValue().getDeclaredConstructor().newInstance();
10✔
307

308
                if (entry.getKey().isInterface()) {
5!
309
                    deserializerInterfaceMap.put(entry.getKey().getName(), ser);
×
310
                } else {
311
                    deserializerClassMap.put(entry.getKey().getName(), ser);
9✔
312
                }
313
            } catch (Exception e) {
×
314
                throw new HessianException(e);
×
315
            }
1✔
316
        }
1✔
317
    }
1✔
318

319
    private void initSerializerFiles(
320
            String fileName, Set<String> fileList, Map<Class<?>, Class<?>> classMap, Class<?> type) {
321
        try {
322
            ClassLoader classLoader = getClassLoader();
3✔
323

324
            // on systems with the security manager enabled, the system classloader
325
            // is null
326
            if (classLoader == null) {
2!
327
                return;
×
328
            }
329

330
            Enumeration<?> iter;
331

332
            iter = classLoader.getResources(fileName);
4✔
333
            while (iter.hasMoreElements()) {
3✔
334
                URL url = (URL) iter.nextElement();
4✔
335

336
                if (fileList.contains(url.toString())) {
5!
337
                    continue;
×
338
                }
339

340
                fileList.add(url.toString());
5✔
341

342
                try (InputStream is = url.openStream()) {
3✔
343

344
                    Properties props = new Properties();
4✔
345
                    props.load(is);
3✔
346

347
                    for (Map.Entry<Object, Object> entry : props.entrySet()) {
11✔
348
                        String apiName = (String) entry.getKey();
4✔
349
                        String serializerName = (String) entry.getValue();
4✔
350

351
                        Class<?> apiClass;
352
                        Class<?> serializerClass;
353

354
                        try {
355
                            apiClass = Class.forName(apiName, false, classLoader);
5✔
356
                        } catch (ClassNotFoundException e) {
1✔
357
                            log.fine(url + ": " + apiName + " is not available in this context: " + getClassLoader());
9✔
358
                            continue;
1✔
359
                        }
1✔
360

361
                        try {
362
                            serializerClass = Class.forName(serializerName, false, classLoader);
5✔
363
                        } catch (ClassNotFoundException e) {
×
364
                            log.fine(url + ": " + serializerName + " is not available in this context: "
×
365
                                    + getClassLoader());
×
366
                            continue;
×
367
                        }
1✔
368

369
                        if (!type.isAssignableFrom(serializerClass)) {
4!
370
                            throw new HessianException(url + ": " + serializerClass.getName()
×
371
                                    + " is invalid because it does not implement " + type.getName());
×
372
                        }
373

374
                        classMap.put(apiClass, serializerClass);
5✔
375
                    }
1✔
376
                }
377
            }
1✔
378
        } catch (RuntimeException e) {
×
379
            throw e;
×
380
        } catch (Exception e) {
×
381
            throw new HessianException(e);
×
382
        }
1✔
383
    }
1✔
384

385
    private static void addBasic(Class<?> cl, String typeName, int type) {
386
        staticSerializerMap.put(cl.getName(), new BasicSerializer(type));
9✔
387

388
        HessianDeserializer deserializer = new BasicDeserializer(type);
5✔
389
        staticDeserializerMap.put(cl.getName(), deserializer);
6✔
390
        staticClassNameMap.put(typeName, deserializer);
5✔
391
    }
1✔
392

393
    static {
394
        staticSerializerMap = new HashMap<>();
4✔
395
        staticDeserializerMap = new HashMap<>();
4✔
396
        staticClassNameMap = new HashMap<>();
4✔
397

398
        FieldDeserializer2Factory fieldFactory = FieldDeserializer2Factory.create();
2✔
399

400
        addBasic(void.class, "void", BasicSerializer.NULL);
4✔
401

402
        addBasic(Boolean.class, "boolean", BasicSerializer.BOOLEAN);
4✔
403
        addBasic(Byte.class, "byte", BasicSerializer.BYTE);
4✔
404
        addBasic(Short.class, "short", BasicSerializer.SHORT);
4✔
405
        addBasic(Integer.class, "int", BasicSerializer.INTEGER);
4✔
406
        addBasic(Long.class, "long", BasicSerializer.LONG);
4✔
407
        addBasic(Float.class, "float", BasicSerializer.FLOAT);
4✔
408
        addBasic(Double.class, "double", BasicSerializer.DOUBLE);
4✔
409
        addBasic(Character.class, "char", BasicSerializer.CHARACTER_OBJECT);
4✔
410
        addBasic(String.class, "string", BasicSerializer.STRING);
4✔
411
        addBasic(Object.class, "object", BasicSerializer.OBJECT);
4✔
412
        addBasic(java.util.Date.class, "date", BasicSerializer.DATE);
4✔
413

414
        addBasic(boolean.class, "boolean", BasicSerializer.BOOLEAN);
4✔
415
        addBasic(byte.class, "byte", BasicSerializer.BYTE);
4✔
416
        addBasic(short.class, "short", BasicSerializer.SHORT);
4✔
417
        addBasic(int.class, "int", BasicSerializer.INTEGER);
4✔
418
        addBasic(long.class, "long", BasicSerializer.LONG);
4✔
419
        addBasic(float.class, "float", BasicSerializer.FLOAT);
4✔
420
        addBasic(double.class, "double", BasicSerializer.DOUBLE);
4✔
421
        addBasic(char.class, "char", BasicSerializer.CHARACTER);
4✔
422

423
        addBasic(boolean[].class, "[boolean", BasicSerializer.BOOLEAN_ARRAY);
4✔
424
        addBasic(byte[].class, "[byte", BasicSerializer.BYTE_ARRAY);
4✔
425
        staticSerializerMap.put(byte[].class.getName(), ByteArraySerializer.SER);
6✔
426
        addBasic(short[].class, "[short", BasicSerializer.SHORT_ARRAY);
4✔
427
        addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY);
4✔
428
        addBasic(long[].class, "[long", BasicSerializer.LONG_ARRAY);
4✔
429
        addBasic(float[].class, "[float", BasicSerializer.FLOAT_ARRAY);
4✔
430
        addBasic(double[].class, "[double", BasicSerializer.DOUBLE_ARRAY);
4✔
431
        addBasic(char[].class, "[char", BasicSerializer.CHARACTER_ARRAY);
4✔
432
        addBasic(String[].class, "[string", BasicSerializer.STRING_ARRAY);
4✔
433
        addBasic(Object[].class, "[object", BasicSerializer.OBJECT_ARRAY);
4✔
434

435
        HessianDeserializer objectDeserializer = new JavaDeserializer(Object.class, fieldFactory);
6✔
436
        staticDeserializerMap.put("object", objectDeserializer);
5✔
437
        staticClassNameMap.put("object", objectDeserializer);
5✔
438

439
        staticSerializerMap.put(Class.class.getName(), new ClassSerializer());
8✔
440

441
        staticDeserializerMap.put(Number.class.getName(), new BasicDeserializer(BasicSerializer.NUMBER));
9✔
442

443
        staticSerializerMap.put(Inet4Address.class.getName(), InetAddressSerializer.create());
6✔
444
        staticSerializerMap.put(Inet6Address.class.getName(), InetAddressSerializer.create());
6✔
445
        staticSerializerMap.put(InetSocketAddress.class.getName(), new InetSocketAddressSerializer());
8✔
446

447
        SqlDateSerializer sqlDateSerializer = new SqlDateSerializer();
4✔
448
        staticSerializerMap.put(java.sql.Date.class.getName(), sqlDateSerializer);
6✔
449
        staticSerializerMap.put(java.sql.Time.class.getName(), sqlDateSerializer);
6✔
450
        staticSerializerMap.put(java.sql.Timestamp.class.getName(), sqlDateSerializer);
6✔
451

452
        staticDeserializerMap.put(java.sql.Date.class.getName(), new SqlDateDeserializer(java.sql.Date.class));
9✔
453
        staticDeserializerMap.put(java.sql.Time.class.getName(), new SqlDateDeserializer(java.sql.Time.class));
9✔
454
        staticDeserializerMap.put(
4✔
455
                java.sql.Timestamp.class.getName(), new SqlDateDeserializer(java.sql.Timestamp.class));
5✔
456

457
        // hessian/3bb5
458
        staticDeserializerMap.put(StackTraceElement.class.getName(), new StackTraceElementDeserializer(fieldFactory));
9✔
459

460
        staticDeserializerMap.put(Inet4Address.class.getName(), new InetAddressDeserializer(Inet4Address.class));
9✔
461
        staticDeserializerMap.put(Inet6Address.class.getName(), new InetAddressDeserializer(Inet6Address.class));
9✔
462
        staticDeserializerMap.put(InetSocketAddress.class.getName(), new InetSocketAddressDeserializer());
8✔
463

464
        ClassLoader systemClassLoader = null;
2✔
465
        try {
466
            systemClassLoader = ClassLoader.getSystemClassLoader();
2✔
467
        } catch (Exception ignored) {
×
468
        }
1✔
469

470
        SYSTEM_CLASS_LOADER = systemClassLoader;
2✔
471
    }
1✔
472
}
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