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

wuwen5 / hessian / 17882005206

20 Sep 2025 01:06PM UTC coverage: 70.892% (+1.5%) from 69.377%
17882005206

push

github

web-flow
refactor: code clean (#50)

* refactor: code clean

* refactor: code clean,remove hessian1 code

* refactor: fix HessianDebugState

1780 of 2691 branches covered (66.15%)

Branch coverage included in aggregate %.

4226 of 5781 relevant lines covered (73.1%)

3.17 hits per line

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

74.28
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.Collections;
60
import java.util.WeakHashMap;
61
import java.util.logging.Level;
62
import java.util.logging.Logger;
63

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

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

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

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

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

81
        writeReplace = getWriteReplace(cl);
4✔
82

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

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

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

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

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

105
            return base;
4✔
106
        }
107
    }
108

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

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

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

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

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

136
        ArrayList<Field> fieldArrayList = new ArrayList<>();
4✔
137
        fieldArrayList.addAll(primitiveFields);
4✔
138
        fieldArrayList.addAll(compoundFields);
4✔
139
        Collections.reverse(fieldArrayList);
2✔
140

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

144
        fieldSerializers = new FieldSerializer[this.fields.length];
6✔
145

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

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

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

165
        return null;
2✔
166
    }
167

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

182
        return null;
×
183
    }
184

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

191
        Class<?> cl = obj.getClass();
3✔
192

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

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

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

206
                if (ref == -1) {
3!
207
                    writeDefinition20(out);
3✔
208
                    out.writeObjectBegin(cl.getName());
5✔
209
                }
210

211
                writeInstance(repl, out);
4✔
212

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

219
        int ref = out.writeObjectBegin(cl.getName());
5✔
220

221
        if (ref == -1) {
3✔
222
            writeDefinition20(out);
3✔
223
            out.writeObjectBegin(cl.getName());
5✔
224
        }
225

226
        writeInstance(obj, out);
4✔
227
    }
1✔
228

229
    @Override
230
    protected void writeObject10(Object obj, AbstractHessianEncoder out) throws IOException {
231
        for (int i = 0; i < fields.length; i++) {
×
232
            Field field = fields[i];
×
233

234
            out.writeString(field.getName());
×
235

236
            fieldSerializers[i].serialize(out, obj, field);
×
237
        }
238

239
        out.writeMapEnd();
×
240
    }
×
241

242
    private void writeDefinition20(AbstractHessianEncoder out) throws IOException {
243
        out.writeClassFieldLength(fields.length);
5✔
244

245
        for (Field field : fields) {
17✔
246
            out.writeString(field.getName());
4✔
247
        }
248
    }
1✔
249

250
    @Override
251
    public void writeInstance(Object obj, AbstractHessianEncoder out) throws IOException {
252
        try {
253
            for (int i = 0; i < fields.length; i++) {
9✔
254
                Field field = fields[i];
5✔
255

256
                fieldSerializers[i].serialize(out, obj, field);
8✔
257
            }
258
        } catch (RuntimeException e) {
×
259
            throw new IllegalStateException(
×
260
                    e.getMessage() + "\n class: " + obj.getClass().getName() + " (object=" + obj + ")", e);
×
261
        } catch (IOException e) {
×
262
            throw new IOExceptionWrapper(
×
263
                    e.getMessage() + "\n class: " + obj.getClass().getName() + " (object=" + obj + ")", e);
×
264
        }
1✔
265
    }
1✔
266

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

288
    static class FieldSerializer {
3✔
289
        static final FieldSerializer SER = new FieldSerializer();
5✔
290

291
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
292
            Object value = null;
2✔
293

294
            try {
295
                value = field.get(obj);
4✔
296
            } catch (IllegalAccessException e) {
×
297
                log.log(Level.FINE, e.toString(), e);
×
298
            }
1✔
299

300
            try {
301
                out.writeObject(value);
3✔
302
            } catch (RuntimeException e) {
×
303
                throw new IllegalStateException(
×
304
                        e.getMessage() + "\n field: "
×
305
                                + field.getDeclaringClass().getName()
×
306
                                + '.' + field.getName(),
×
307
                        e);
308
            } catch (IOException e) {
×
309
                throw new IOExceptionWrapper(
×
310
                        e.getMessage() + "\n field: "
×
311
                                + field.getDeclaringClass().getName()
×
312
                                + '.' + field.getName(),
×
313
                        e);
314
            }
1✔
315
        }
1✔
316
    }
317

318
    static class BooleanFieldSerializer extends FieldSerializer {
3✔
319
        static final FieldSerializer SER = new BooleanFieldSerializer();
5✔
320

321
        @Override
322
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
323
            boolean value = false;
2✔
324

325
            try {
326
                value = field.getBoolean(obj);
4✔
327
            } catch (IllegalAccessException e) {
×
328
                log.log(Level.FINE, e.toString(), e);
×
329
            }
1✔
330

331
            out.writeBoolean(value);
3✔
332
        }
1✔
333
    }
334

335
    static class IntFieldSerializer extends FieldSerializer {
3✔
336
        static final FieldSerializer SER = new IntFieldSerializer();
5✔
337

338
        @Override
339
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
340
            int value = 0;
2✔
341

342
            try {
343
                value = field.getInt(obj);
4✔
344
            } catch (IllegalAccessException e) {
×
345
                log.log(Level.FINE, e.toString(), e);
×
346
            }
1✔
347

348
            out.writeInt(value);
3✔
349
        }
1✔
350
    }
351

352
    static class LongFieldSerializer extends FieldSerializer {
3✔
353
        static final FieldSerializer SER = new LongFieldSerializer();
5✔
354

355
        @Override
356
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
357
            long value = 0;
2✔
358

359
            try {
360
                value = field.getLong(obj);
4✔
361
            } catch (IllegalAccessException e) {
×
362
                log.log(Level.FINE, e.toString(), e);
×
363
            }
1✔
364

365
            out.writeLong(value);
3✔
366
        }
1✔
367
    }
368

369
    static class DoubleFieldSerializer extends FieldSerializer {
3✔
370
        static final FieldSerializer SER = new DoubleFieldSerializer();
5✔
371

372
        @Override
373
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
374
            double value = 0;
2✔
375

376
            try {
377
                value = field.getDouble(obj);
4✔
378
            } catch (IllegalAccessException e) {
×
379
                log.log(Level.FINE, e.toString(), e);
×
380
            }
1✔
381

382
            out.writeDouble(value);
3✔
383
        }
1✔
384
    }
385

386
    static class StringFieldSerializer extends FieldSerializer {
3✔
387
        static final FieldSerializer SER = new StringFieldSerializer();
5✔
388

389
        @Override
390
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
391
            String value = null;
2✔
392

393
            try {
394
                value = (String) field.get(obj);
5✔
395
            } catch (IllegalAccessException e) {
×
396
                log.log(Level.FINE, e.toString(), e);
×
397
            }
1✔
398

399
            out.writeString(value);
3✔
400
        }
1✔
401
    }
402

403
    static class DateFieldSerializer extends FieldSerializer {
3✔
404
        static final FieldSerializer SER = new DateFieldSerializer();
5✔
405

406
        @Override
407
        void serialize(AbstractHessianEncoder out, Object obj, Field field) throws IOException {
408
            java.util.Date value = null;
2✔
409

410
            try {
411
                value = (java.util.Date) field.get(obj);
5✔
412
            } catch (IllegalAccessException e) {
×
413
                log.log(Level.FINE, e.toString(), e);
×
414
            }
1✔
415

416
            if (value == null) {
2!
417
                out.writeNull();
×
418
            } else {
419
                out.writeUTCDate(value.getTime());
4✔
420
            }
421
        }
1✔
422
    }
423
}
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