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

wuwen5 / hessian / 17190932491

24 Aug 2025 03:32PM UTC coverage: 68.598% (+0.2%) from 68.416%
17190932491

push

github

wuwen5
Bump actions/checkout from 4 to 5

Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

1793 of 2809 branches covered (63.83%)

Branch coverage included in aggregate %.

4173 of 5888 relevant lines covered (70.87%)

3.08 hits per line

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

73.5
hessian2-codec/src/main/java/io/github/wuwen5/hessian/io/JavaSerializer.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.HessianUnshared;
52
import java.io.IOException;
53
import java.lang.ref.SoftReference;
54
import java.lang.reflect.Field;
55
import java.lang.reflect.InvocationTargetException;
56
import java.lang.reflect.Method;
57
import java.lang.reflect.Modifier;
58
import java.util.ArrayList;
59
import java.util.WeakHashMap;
60
import java.util.logging.Level;
61
import java.util.logging.Logger;
62

63
/**
64
 * Serializing an object for known object types.
65
 */
66
public class JavaSerializer extends AbstractSerializer {
67
    private static final Logger log = Logger.getLogger(JavaSerializer.class.getName());
4✔
68

69
    private static final WeakHashMap<Class<?>, SoftReference<JavaSerializer>> SERIALIZER_MAP = new WeakHashMap<>();
5✔
70

71
    private Field[] fields;
72
    private FieldSerializer[] fieldSerializers;
73

74
    private Object writeReplaceFactory;
75
    private final Method writeReplace;
76

77
    public JavaSerializer(Class<?> cl) {
2✔
78
        introspect(cl);
3✔
79

80
        writeReplace = getWriteReplace(cl);
4✔
81

82
        if (writeReplace != null) {
3✔
83
            writeReplace.setAccessible(true);
4✔
84
        }
85
    }
1✔
86

87
    public static Serializer create(Class<?> cl) {
88
        synchronized (SERIALIZER_MAP) {
4✔
89
            SoftReference<JavaSerializer> baseRef = SERIALIZER_MAP.get(cl);
5✔
90

91
            JavaSerializer base = baseRef != null ? baseRef.get() : null;
4!
92

93
            if (base == null) {
2!
94
                if (cl.isAnnotationPresent(HessianUnshared.class)) {
4!
95
                    base = new JavaUnsharedSerializer(cl);
×
96
                } else {
97
                    base = new JavaSerializer(cl);
5✔
98
                }
99

100
                baseRef = new SoftReference<>(base);
5✔
101
                SERIALIZER_MAP.put(cl, baseRef);
5✔
102
            }
103

104
            return base;
4✔
105
        }
106
    }
107

108
    protected void introspect(Class<?> cl) {
109
        if (writeReplace != null) {
3!
110
            writeReplace.setAccessible(true);
×
111
        }
112

113
        ArrayList<Field> primitiveFields = new ArrayList<>();
4✔
114
        ArrayList<Field> compoundFields = new ArrayList<>();
4✔
115

116
        for (; cl != null; cl = cl.getSuperclass()) {
6✔
117
            for (Field field : cl.getDeclaredFields()) {
17✔
118
                if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) {
8✔
119
                    continue;
1✔
120
                }
121

122
                // XXX: could parameterize the handler to only deal with public
123
                field.setAccessible(true);
3✔
124

125
                if (field.getType().isPrimitive()
5✔
126
                        || (field.getType().getName().startsWith("java.lang.")
6✔
127
                                && !field.getType().equals(Object.class))) {
4✔
128
                    primitiveFields.add(field);
5✔
129
                } else {
130
                    compoundFields.add(field);
4✔
131
                }
132
            }
133
        }
134

135
        ArrayList<Field> fieldArrayList = new ArrayList<>();
4✔
136
        fieldArrayList.addAll(primitiveFields);
4✔
137
        fieldArrayList.addAll(compoundFields);
4✔
138

139
        this.fields = new Field[fieldArrayList.size()];
5✔
140
        fieldArrayList.toArray(this.fields);
5✔
141

142
        fieldSerializers = new FieldSerializer[this.fields.length];
6✔
143

144
        for (int i = 0; i < this.fields.length; i++) {
9✔
145
            fieldSerializers[i] = getFieldSerializer(this.fields[i].getType());
10✔
146
        }
147
    }
1✔
148

149
    /**
150
     * Returns the writeReplace method
151
     */
152
    protected static Method getWriteReplace(Class<?> cl) {
153
        for (; cl != null; cl = cl.getSuperclass()) {
6✔
154
            Method[] methods = cl.getDeclaredMethods();
3✔
155

156
            for (Method method : methods) {
16✔
157
                if ("writeReplace".equals(method.getName()) && method.getParameterTypes().length == 0) {
9!
158
                    return method;
2✔
159
                }
160
            }
161
        }
162

163
        return null;
2✔
164
    }
165

166
    /**
167
     * Returns the writeReplace method
168
     */
169
    protected Method getWriteReplace(Class<?> cl, Class<?> param) {
170
        for (; cl != null; cl = cl.getSuperclass()) {
×
171
            for (Method method : cl.getDeclaredMethods()) {
×
172
                if ("writeReplace".equals(method.getName())
×
173
                        && method.getParameterTypes().length == 1
×
174
                        && param.equals(method.getParameterTypes()[0])) {
×
175
                    return method;
×
176
                }
177
            }
178
        }
179

180
        return null;
×
181
    }
182

183
    @Override
184
    public void writeObject(Object obj, AbstractHessianEncoder out) throws IOException {
185
        if (out.addRef(obj)) {
4!
186
            return;
×
187
        }
188

189
        Class<?> cl = obj.getClass();
3✔
190

191
        try {
192
            if (writeReplace != null) {
3✔
193
                Object repl;
194

195
                if (writeReplaceFactory != null) {
3!
196
                    repl = writeReplace.invoke(writeReplaceFactory, obj);
×
197
                } else {
198
                    repl = writeReplace.invoke(obj);
7✔
199
                }
200

201
                // hessian/3a5a
202
                int ref = out.writeObjectBegin(cl.getName());
5✔
203

204
                if (ref < -1) {
3!
205
                    writeObject10(repl, out);
×
206
                } else {
207
                    if (ref == -1) {
3!
208
                        writeDefinition20(out);
3✔
209
                        out.writeObjectBegin(cl.getName());
5✔
210
                    }
211

212
                    writeInstance(repl, out);
4✔
213
                }
214

215
                return;
1✔
216
            }
217
        } catch (InvocationTargetException | IllegalAccessException e) {
×
218
            throw new IllegalStateException(e);
×
219
        }
1✔
220

221
        int ref = out.writeObjectBegin(cl.getName());
5✔
222

223
        if (ref < -1) {
3!
224
            writeObject10(obj, out);
×
225
        } else {
226
            if (ref == -1) {
3✔
227
                writeDefinition20(out);
3✔
228
                out.writeObjectBegin(cl.getName());
5✔
229
            }
230

231
            writeInstance(obj, out);
4✔
232
        }
233
    }
1✔
234

235
    @Override
236
    protected void writeObject10(Object obj, AbstractHessianEncoder out) throws IOException {
237
        for (int i = 0; i < fields.length; i++) {
×
238
            Field field = fields[i];
×
239

240
            out.writeString(field.getName());
×
241

242
            fieldSerializers[i].serialize(out, obj, field);
×
243
        }
244

245
        out.writeMapEnd();
×
246
    }
×
247

248
    private void writeDefinition20(AbstractHessianEncoder out) throws IOException {
249
        out.writeClassFieldLength(fields.length);
5✔
250

251
        for (Field field : fields) {
17✔
252
            out.writeString(field.getName());
4✔
253
        }
254
    }
1✔
255

256
    @Override
257
    public void writeInstance(Object obj, AbstractHessianEncoder out) throws IOException {
258
        try {
259
            for (int i = 0; i < fields.length; i++) {
9✔
260
                Field field = fields[i];
5✔
261

262
                fieldSerializers[i].serialize(out, obj, field);
8✔
263
            }
264
        } catch (RuntimeException e) {
×
265
            throw new IllegalStateException(
×
266
                    e.getMessage() + "\n class: " + obj.getClass().getName() + " (object=" + obj + ")", e);
×
267
        } catch (IOException e) {
×
268
            throw new IOExceptionWrapper(
×
269
                    e.getMessage() + "\n class: " + obj.getClass().getName() + " (object=" + obj + ")", e);
×
270
        }
1✔
271
    }
1✔
272

273
    private static FieldSerializer getFieldSerializer(Class<?> type) {
274
        if (int.class.equals(type) || byte.class.equals(type) || short.class.equals(type)) {
12✔
275
            return IntFieldSerializer.SER;
2✔
276
        } else if (long.class.equals(type)) {
4✔
277
            return LongFieldSerializer.SER;
2✔
278
        } else if (double.class.equals(type) || float.class.equals(type)) {
8✔
279
            return DoubleFieldSerializer.SER;
2✔
280
        } else if (boolean.class.equals(type)) {
4✔
281
            return BooleanFieldSerializer.SER;
2✔
282
        } else if (String.class.equals(type)) {
4✔
283
            return StringFieldSerializer.SER;
2✔
284
        } else if (java.util.Date.class.equals(type)
6✔
285
                || java.sql.Date.class.equals(type)
4✔
286
                || java.sql.Timestamp.class.equals(type)
4✔
287
                || java.sql.Time.class.equals(type)) {
2✔
288
            return DateFieldSerializer.SER;
2✔
289
        } else {
290
            return FieldSerializer.SER;
2✔
291
        }
292
    }
293

294
    static class FieldSerializer {
3✔
295
        static final FieldSerializer SER = new FieldSerializer();
5✔
296

297
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
298
            Object value = null;
2✔
299

300
            try {
301
                value = field.get(obj);
4✔
302
            } catch (IllegalAccessException e) {
×
303
                log.log(Level.FINE, e.toString(), e);
×
304
            }
1✔
305

306
            try {
307
                out.writeObject(value);
3✔
308
            } catch (RuntimeException e) {
×
309
                throw new IllegalStateException(
×
310
                        e.getMessage() + "\n field: "
×
311
                                + field.getDeclaringClass().getName()
×
312
                                + '.' + field.getName(),
×
313
                        e);
314
            } catch (IOException e) {
×
315
                throw new IOExceptionWrapper(
×
316
                        e.getMessage() + "\n field: "
×
317
                                + field.getDeclaringClass().getName()
×
318
                                + '.' + field.getName(),
×
319
                        e);
320
            }
1✔
321
        }
1✔
322
    }
323

324
    static class BooleanFieldSerializer extends FieldSerializer {
3✔
325
        static final FieldSerializer SER = new BooleanFieldSerializer();
5✔
326

327
        @Override
328
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
329
            boolean value = false;
2✔
330

331
            try {
332
                value = field.getBoolean(obj);
4✔
333
            } catch (IllegalAccessException e) {
×
334
                log.log(Level.FINE, e.toString(), e);
×
335
            }
1✔
336

337
            out.writeBoolean(value);
3✔
338
        }
1✔
339
    }
340

341
    static class IntFieldSerializer extends FieldSerializer {
3✔
342
        static final FieldSerializer SER = new IntFieldSerializer();
5✔
343

344
        @Override
345
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
346
            int value = 0;
2✔
347

348
            try {
349
                value = field.getInt(obj);
4✔
350
            } catch (IllegalAccessException e) {
×
351
                log.log(Level.FINE, e.toString(), e);
×
352
            }
1✔
353

354
            out.writeInt(value);
3✔
355
        }
1✔
356
    }
357

358
    static class LongFieldSerializer extends FieldSerializer {
3✔
359
        static final FieldSerializer SER = new LongFieldSerializer();
5✔
360

361
        @Override
362
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
363
            long value = 0;
2✔
364

365
            try {
366
                value = field.getLong(obj);
4✔
367
            } catch (IllegalAccessException e) {
×
368
                log.log(Level.FINE, e.toString(), e);
×
369
            }
1✔
370

371
            out.writeLong(value);
3✔
372
        }
1✔
373
    }
374

375
    static class DoubleFieldSerializer extends FieldSerializer {
3✔
376
        static final FieldSerializer SER = new DoubleFieldSerializer();
5✔
377

378
        @Override
379
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
380
            double value = 0;
2✔
381

382
            try {
383
                value = field.getDouble(obj);
4✔
384
            } catch (IllegalAccessException e) {
×
385
                log.log(Level.FINE, e.toString(), e);
×
386
            }
1✔
387

388
            out.writeDouble(value);
3✔
389
        }
1✔
390
    }
391

392
    static class StringFieldSerializer extends FieldSerializer {
3✔
393
        static final FieldSerializer SER = new StringFieldSerializer();
5✔
394

395
        @Override
396
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
397
            String value = null;
2✔
398

399
            try {
400
                value = (String) field.get(obj);
5✔
401
            } catch (IllegalAccessException e) {
×
402
                log.log(Level.FINE, e.toString(), e);
×
403
            }
1✔
404

405
            out.writeString(value);
3✔
406
        }
1✔
407
    }
408

409
    static class DateFieldSerializer extends FieldSerializer {
3✔
410
        static final FieldSerializer SER = new DateFieldSerializer();
5✔
411

412
        @Override
413
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
414
            java.util.Date value = null;
2✔
415

416
            try {
417
                value = (java.util.Date) field.get(obj);
5✔
418
            } catch (IllegalAccessException e) {
×
419
                log.log(Level.FINE, e.toString(), e);
×
420
            }
1✔
421

422
            if (value == null) {
2!
423
                out.writeNull();
×
424
            } else {
425
                out.writeUTCDate(value.getTime());
4✔
426
            }
427
        }
1✔
428
    }
429
}
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