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

wuwen5 / hessian / 18043144273

25 Sep 2025 12:46AM UTC coverage: 71.311% (+0.2%) from 71.118%
18043144273

push

github

web-flow
Refactor JavaSerializer, UnsafeSerializer, and BeanSerializer to eliminate code duplication (#57)

* Initial plan

* Refactor JavaSerializer and UnsafeSerializer to use FieldBasedSerializer base class

Co-authored-by: wuwen5 <5037807+wuwen5@users.noreply.github.com>

* Complete refactoring - consolidate writeReplace methods and fix module access

Co-authored-by: wuwen5 <5037807+wuwen5@users.noreply.github.com>

* Address code review feedback: move setAccessible to JavaSerializer only, remove writeObject10 from base classes

Co-authored-by: wuwen5 <5037807+wuwen5@users.noreply.github.com>

* Refactor JavaSerializer to reuse parent introspection and remove unused writeFieldValue method

Co-authored-by: wuwen5 <5037807+wuwen5@users.noreply.github.com>

* Remove unused writeObject10 methods and writeReplaceFactory field

Co-authored-by: wuwen5 <5037807+wuwen5@users.noreply.github.com>

* Rename writeReplace field to writeReplaceMethod to avoid confusion with superclass method

Co-authored-by: wuwen5 <5037807+wuwen5@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wuwen5 <5037807+wuwen5@users.noreply.github.com>

1724 of 2605 branches covered (66.18%)

Branch coverage included in aggregate %.

4152 of 5635 relevant lines covered (73.68%)

3.18 hits per line

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

80.77
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.util.WeakHashMap;
56
import java.util.logging.Level;
57
import java.util.logging.Logger;
58

59
/**
60
 * Serializing an object for known object types.
61
 */
62
public class JavaSerializer extends FieldBasedSerializer {
63
    private static final Logger log = Logger.getLogger(JavaSerializer.class.getName());
4✔
64

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

67
    private FieldSerializer[] fieldSerializers;
68

69
    public JavaSerializer(Class<?> cl) {
2✔
70
        introspectFields(cl);
3✔
71

72
        writeReplaceMethod = getWriteReplace(cl);
4✔
73

74
        if (writeReplaceMethod != null) {
3✔
75
            writeReplaceMethod.setAccessible(true);
4✔
76
        }
77

78
        fieldSerializers = new FieldSerializer[this.fields.length];
6✔
79

80
        for (int i = 0; i < this.fields.length; i++) {
9✔
81
            fieldSerializers[i] = getFieldSerializer(this.fields[i].getType());
10✔
82
        }
83
    }
1✔
84

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

89
            JavaSerializer base = baseRef != null ? baseRef.get() : null;
4!
90

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

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

102
            return base;
4✔
103
        }
104
    }
105

106
    /**
107
     * Implement abstract method from FieldBasedSerializer
108
     * JavaSerializer needs to call setAccessible(true) on fields for reflection access
109
     */
110
    @Override
111
    protected void writeInstanceFields(Object obj, AbstractHessianEncoder out) throws IOException {
112
        for (int i = 0; i < fields.length; i++) {
9✔
113
            Field field = fields[i];
5✔
114
            // XXX: could parameterize the handler to only deal with public
115
            field.setAccessible(true);
3✔
116
            fieldSerializers[i].serialize(out, obj, field);
8✔
117
        }
118
    }
1✔
119

120
    private static FieldSerializer getFieldSerializer(Class<?> type) {
121
        if (int.class.equals(type) || byte.class.equals(type) || short.class.equals(type)) {
12✔
122
            return IntFieldSerializer.SER;
2✔
123
        } else if (long.class.equals(type)) {
4✔
124
            return LongFieldSerializer.SER;
2✔
125
        } else if (double.class.equals(type) || float.class.equals(type)) {
8✔
126
            return DoubleFieldSerializer.SER;
2✔
127
        } else if (boolean.class.equals(type)) {
4✔
128
            return BooleanFieldSerializer.SER;
2✔
129
        } else if (String.class.equals(type)) {
4✔
130
            return StringFieldSerializer.SER;
2✔
131
        } else if (java.util.Date.class.equals(type)
6✔
132
                || java.sql.Date.class.equals(type)
4✔
133
                || java.sql.Timestamp.class.equals(type)
4✔
134
                || java.sql.Time.class.equals(type)) {
2✔
135
            return DateFieldSerializer.SER;
2✔
136
        } else {
137
            return FieldSerializer.SER;
2✔
138
        }
139
    }
140

141
    static class FieldSerializer {
3✔
142
        static final FieldSerializer SER = new FieldSerializer();
5✔
143

144
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
145
            Object value = null;
2✔
146

147
            try {
148
                value = field.get(obj);
4✔
149
            } catch (IllegalAccessException e) {
×
150
                log.log(Level.FINE, e.toString(), e);
×
151
            }
1✔
152

153
            try {
154
                out.writeObject(value);
3✔
155
            } catch (RuntimeException e) {
×
156
                throw new IllegalStateException(
×
157
                        e.getMessage() + "\n field: "
×
158
                                + field.getDeclaringClass().getName()
×
159
                                + '.' + field.getName(),
×
160
                        e);
161
            } catch (IOException e) {
×
162
                throw new IOExceptionWrapper(
×
163
                        e.getMessage() + "\n field: "
×
164
                                + field.getDeclaringClass().getName()
×
165
                                + '.' + field.getName(),
×
166
                        e);
167
            }
1✔
168
        }
1✔
169
    }
170

171
    static class BooleanFieldSerializer extends FieldSerializer {
3✔
172
        static final FieldSerializer SER = new BooleanFieldSerializer();
5✔
173

174
        @Override
175
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
176
            boolean value = false;
2✔
177

178
            try {
179
                value = field.getBoolean(obj);
4✔
180
            } catch (IllegalAccessException e) {
×
181
                log.log(Level.FINE, e.toString(), e);
×
182
            }
1✔
183

184
            out.writeBoolean(value);
3✔
185
        }
1✔
186
    }
187

188
    static class IntFieldSerializer extends FieldSerializer {
3✔
189
        static final FieldSerializer SER = new IntFieldSerializer();
5✔
190

191
        @Override
192
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
193
            int value = 0;
2✔
194

195
            try {
196
                value = field.getInt(obj);
4✔
197
            } catch (IllegalAccessException e) {
×
198
                log.log(Level.FINE, e.toString(), e);
×
199
            }
1✔
200

201
            out.writeInt(value);
3✔
202
        }
1✔
203
    }
204

205
    static class LongFieldSerializer extends FieldSerializer {
3✔
206
        static final FieldSerializer SER = new LongFieldSerializer();
5✔
207

208
        @Override
209
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
210
            long value = 0;
2✔
211

212
            try {
213
                value = field.getLong(obj);
4✔
214
            } catch (IllegalAccessException e) {
×
215
                log.log(Level.FINE, e.toString(), e);
×
216
            }
1✔
217

218
            out.writeLong(value);
3✔
219
        }
1✔
220
    }
221

222
    static class DoubleFieldSerializer extends FieldSerializer {
3✔
223
        static final FieldSerializer SER = new DoubleFieldSerializer();
5✔
224

225
        @Override
226
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
227
            double value = 0;
2✔
228

229
            try {
230
                value = field.getDouble(obj);
4✔
231
            } catch (IllegalAccessException e) {
×
232
                log.log(Level.FINE, e.toString(), e);
×
233
            }
1✔
234

235
            out.writeDouble(value);
3✔
236
        }
1✔
237
    }
238

239
    static class StringFieldSerializer extends FieldSerializer {
3✔
240
        static final FieldSerializer SER = new StringFieldSerializer();
5✔
241

242
        @Override
243
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
244
            String value = null;
2✔
245

246
            try {
247
                value = (String) field.get(obj);
5✔
248
            } catch (IllegalAccessException e) {
×
249
                log.log(Level.FINE, e.toString(), e);
×
250
            }
1✔
251

252
            out.writeString(value);
3✔
253
        }
1✔
254
    }
255

256
    static class DateFieldSerializer extends FieldSerializer {
3✔
257
        static final FieldSerializer SER = new DateFieldSerializer();
5✔
258

259
        @Override
260
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
261
            java.util.Date value = null;
2✔
262

263
            try {
264
                value = (java.util.Date) field.get(obj);
5✔
265
            } catch (IllegalAccessException e) {
×
266
                log.log(Level.FINE, e.toString(), e);
×
267
            }
1✔
268

269
            if (value == null) {
2!
270
                out.writeNull();
×
271
            } else {
272
                out.writeUTCDate(value.getTime());
4✔
273
            }
274
        }
1✔
275
    }
276
}
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