1 /*
2 * Copyright 2012 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty.handler.codec.serialization;
17
18 import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
19
20 import io.netty.buffer.ByteBuf;
21 import io.netty.buffer.ByteBufOutputStream;
22 import io.netty.channel.ChannelHandlerContext;
23 import io.netty.handler.codec.MessageToByteEncoder;
24
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.io.OutputStream;
28 import java.io.Serializable;
29
30 /**
31 * An encoder which serializes a Java object into a {@link ByteBuf}
32 * (interoperability version).
33 * <p>
34 * This encoder is interoperable with the standard Java object streams such as
35 * {@link ObjectInputStream} and {@link ObjectOutputStream}.
36 * <p>
37 * <strong>Security:</strong> serialization can be a security liability,
38 * and should not be used without defining a list of classes that are
39 * allowed to be desirialized. Such a list can be specified with the
40 * <tt>jdk.serialFilter</tt> system property, for instance.
41 * See the <a href="https://docs.oracle.com/en/java/javase/17/core/serialization-filtering1.html">
42 * serialization filtering</a> article for more information.
43 *
44 * @deprecated This class has been deprecated with no replacement,
45 * because serialization can be a security liability
46 */
47 @Deprecated
48 public class CompatibleObjectEncoder extends MessageToByteEncoder<Serializable> {
49 private final int resetInterval;
50 private int writtenObjects;
51
52 /**
53 * Creates a new instance with the reset interval of {@code 16}.
54 */
55 public CompatibleObjectEncoder() {
56 this(16); // Reset at every sixteen writes
57 }
58
59 /**
60 * Creates a new instance.
61 *
62 * @param resetInterval
63 * the number of objects between {@link ObjectOutputStream#reset()}.
64 * {@code 0} will disable resetting the stream, but the remote
65 * peer will be at the risk of getting {@link OutOfMemoryError} in
66 * the long term.
67 */
68 public CompatibleObjectEncoder(int resetInterval) {
69 this.resetInterval = checkPositiveOrZero(resetInterval, "resetInterval");
70 }
71
72 /**
73 * Creates a new {@link ObjectOutputStream} which wraps the specified
74 * {@link OutputStream}. Override this method to use a subclass of the
75 * {@link ObjectOutputStream}.
76 */
77 protected ObjectOutputStream newObjectOutputStream(OutputStream out) throws Exception {
78 return new ObjectOutputStream(out);
79 }
80
81 @Override
82 protected void encode(ChannelHandlerContext ctx, Serializable msg, ByteBuf out) throws Exception {
83 // Suppress a warning about resource leak since oss is closed below
84 ObjectOutputStream oos = newObjectOutputStream(
85 new ByteBufOutputStream(out));
86 try {
87 if (resetInterval != 0) {
88 // Resetting will prevent OOM on the receiving side.
89 writtenObjects ++;
90 if (writtenObjects % resetInterval == 0) {
91 oos.reset();
92 }
93 }
94
95 oos.writeObject(msg);
96 oos.flush();
97 } finally {
98 oos.close();
99 }
100 }
101 }