Skip to content

Commit fd7d1b2

Browse files
committed
warn unregistered classes option
1 parent 732fba4 commit fd7d1b2

File tree

2 files changed

+188
-2
lines changed

2 files changed

+188
-2
lines changed

src/com/esotericsoftware/kryo/Kryo.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public class Kryo {
123123
private ClassLoader classLoader = getClass().getClassLoader();
124124
private InstantiatorStrategy strategy = new DefaultInstantiatorStrategy();
125125
private boolean registrationRequired;
126+
private boolean warnUnregisteredClasses;
126127

127128
private int depth, maxDepth = Integer.MAX_VALUE;
128129
private boolean autoReset = true;
@@ -481,15 +482,22 @@ public Registration getRegistration (Class type) {
481482
}
482483
if (registration == null) {
483484
if (registrationRequired) {
484-
throw new IllegalArgumentException("Class is not registered: " + className(type)
485-
+ "\nNote: To register this class use: kryo.register(" + className(type) + ".class);");
485+
throw new IllegalArgumentException(unregisteredClassMessage(type));
486+
}
487+
if(warnUnregisteredClasses) {
488+
warn(unregisteredClassMessage(type));
486489
}
487490
registration = classResolver.registerImplicit(type);
488491
}
489492
}
490493
return registration;
491494
}
492495

496+
protected String unregisteredClassMessage (Class type) {
497+
return "Class is not registered: " + className(type)
498+
+ "\nNote: To register this class use: kryo.register(" + className(type) + ".class);";
499+
}
500+
493501
/** @see ClassResolver#getRegistration(int) */
494502
public Registration getRegistration (int classID) {
495503
return classResolver.getRegistration(classID);
@@ -1022,6 +1030,21 @@ public void setRegistrationRequired (boolean registrationRequired) {
10221030
public boolean isRegistrationRequired () {
10231031
return registrationRequired;
10241032
}
1033+
1034+
/**
1035+
* If true, kryo writes a warn log telling about the classes unregistered. Default is false.
1036+
* <p>
1037+
* If false, no log are written when unregistered classes are encountered.
1038+
* </p>
1039+
*/
1040+
public void setWarnUnregisteredClasses (boolean warnUnregisteredClasses) {
1041+
this.warnUnregisteredClasses = warnUnregisteredClasses;
1042+
if (TRACE) trace("kryo", "Warn unregistered classes: " + warnUnregisteredClasses);
1043+
}
1044+
1045+
public boolean isWarnUnregisteredClasses () {
1046+
return warnUnregisteredClasses;
1047+
}
10251048

10261049
/** If true, each appearance of an object in the graph after the first is stored as an integer ordinal. When set to true,
10271050
* {@link MapReferenceResolver} is used. This enables references to the same object and cyclic graphs to be serialized, but
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/* Copyright (c) 2008, Nathan Sweet
2+
* All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
5+
* conditions are met:
6+
*
7+
* - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8+
* - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
9+
* disclaimer in the documentation and/or other materials provided with the distribution.
10+
* - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
11+
* from this software without specific prior written permission.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
14+
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
15+
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
17+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
18+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
19+
20+
package com.esotericsoftware.kryo;
21+
22+
import java.io.ByteArrayOutputStream;
23+
import java.io.InputStream;
24+
import java.io.OutputStream;
25+
import java.math.BigDecimal;
26+
import java.math.BigInteger;
27+
import java.util.ArrayList;
28+
import java.util.Calendar;
29+
import java.util.Collections;
30+
import java.util.Date;
31+
import java.util.EnumSet;
32+
import java.util.List;
33+
import java.util.TimeZone;
34+
35+
import com.esotericsoftware.kryo.KryoTestCase.StreamFactory;
36+
import com.esotericsoftware.kryo.io.Input;
37+
import com.esotericsoftware.kryo.io.Output;
38+
import com.esotericsoftware.kryo.io.UnsafeMemoryInput;
39+
import com.esotericsoftware.kryo.io.UnsafeMemoryOutput;
40+
import com.esotericsoftware.minlog.Log;
41+
42+
import static com.esotericsoftware.minlog.Log.Logger;
43+
44+
import java.util.Locale;
45+
46+
import junit.framework.TestCase;
47+
48+
/** @author Tiago Albineli Motta <[email protected]> */
49+
public class WarnUnregisteredClassesTest extends TestCase {
50+
51+
LoggerStub log;
52+
53+
@Override
54+
protected void setUp() throws Exception {
55+
super.setUp();
56+
log = new LoggerStub();
57+
Log.setLogger(log);
58+
}
59+
60+
public void testLogOnlyOneTimePerClass () {
61+
Kryo kryo = new Kryo();
62+
kryo.setRegistrationRequired(false);
63+
kryo.setWarnUnregisteredClasses(true);
64+
65+
write(kryo, new UnregisteredClass());
66+
assertEquals(1, log.messages.size());
67+
68+
write(kryo, new UnregisteredClass());
69+
assertEquals(1, log.messages.size());
70+
71+
write(kryo, new UnregisteredClass2());
72+
assertEquals(2, log.messages.size());
73+
74+
write(kryo, new UnregisteredClass2());
75+
assertEquals(2, log.messages.size());
76+
}
77+
78+
public void testDontLogIfNotRequired () {
79+
Kryo kryo = new Kryo();
80+
kryo.setRegistrationRequired(false);
81+
kryo.setWarnUnregisteredClasses(false);
82+
83+
write(kryo, new UnregisteredClass());
84+
assertEquals(0, log.messages.size());
85+
86+
write(kryo, new UnregisteredClass2());
87+
assertEquals(0, log.messages.size());
88+
}
89+
90+
public void testDontLogClassIsRegistered () {
91+
Kryo kryo = new Kryo();
92+
kryo.setRegistrationRequired(false);
93+
kryo.setWarnUnregisteredClasses(true);
94+
kryo.register(RegisteredClass.class);
95+
96+
write(kryo, new RegisteredClass());
97+
assertEquals(0, log.messages.size());
98+
}
99+
100+
public void testLogShouldBeWarn () {
101+
Kryo kryo = new Kryo();
102+
kryo.setRegistrationRequired(false);
103+
kryo.setWarnUnregisteredClasses(true);
104+
105+
write(kryo, new UnregisteredClass());
106+
assertEquals(Log.LEVEL_WARN, log.levels.get(0).intValue());
107+
}
108+
109+
public void testLogMessageShouldContainsClassName () {
110+
Kryo kryo = new Kryo();
111+
kryo.setRegistrationRequired(false);
112+
kryo.setWarnUnregisteredClasses(true);
113+
114+
write(kryo, new UnregisteredClass());
115+
assertTrue(log.messages.get(0).contains(UnregisteredClass.class.getName()));
116+
}
117+
118+
public void write(Kryo kryo, Object object) {
119+
StreamFactory sf = new StreamFactory() {
120+
public Output createOutput(OutputStream os) {
121+
return new UnsafeMemoryOutput(os);
122+
}
123+
public Output createOutput(OutputStream os, int size) {
124+
return new UnsafeMemoryOutput(os, size);
125+
}
126+
public Output createOutput(int size, int limit) {
127+
return new UnsafeMemoryOutput(size, limit);
128+
}
129+
public Input createInput(InputStream os, int size) {
130+
return new UnsafeMemoryInput(os, size);
131+
}
132+
public Input createInput(byte[] buffer) {
133+
return new UnsafeMemoryInput(buffer);
134+
}
135+
};
136+
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
137+
Output output = sf.createOutput(outStream, 4096);
138+
kryo.writeClassAndObject(output, object);
139+
output.flush();
140+
}
141+
142+
class LoggerStub extends Logger {
143+
144+
public List<Integer> levels = new ArrayList();
145+
public List<String> messages = new ArrayList();
146+
147+
@Override
148+
public void log (int level, String category, String message, Throwable ex) {
149+
levels.add(level);
150+
messages.add(message);
151+
}
152+
}
153+
}
154+
155+
class UnregisteredClass {
156+
public UnregisteredClass() {}
157+
}
158+
class UnregisteredClass2 {
159+
public UnregisteredClass2() {}
160+
}
161+
class RegisteredClass {
162+
public RegisteredClass() {}
163+
}

0 commit comments

Comments
 (0)