2424
2525import java .io .IOException ;
2626import java .util .HashMap ;
27+ import java .util .IdentityHashMap ;
2728import java .util .Map ;
2829
2930/**
@@ -39,6 +40,8 @@ public class EventDeserializer {
3940
4041 private final Map <Long , TableMapEventData > tableMapEventByTableId ;
4142
43+ private EventDataDeserializer tableMapEventDataDeserializer ;
44+
4245 public EventDeserializer () {
4346 this (new EventHeaderV4Deserializer (), new NullEventDataDeserializer ());
4447 }
@@ -55,9 +58,12 @@ public EventDeserializer(
5558 EventHeaderDeserializer eventHeaderDeserializer ,
5659 EventDataDeserializer defaultEventDataDeserializer
5760 ) {
58- this (eventHeaderDeserializer , defaultEventDataDeserializer ,
59- new HashMap <EventType , EventDataDeserializer >(), new HashMap <Long , TableMapEventData >());
61+ this .eventHeaderDeserializer = eventHeaderDeserializer ;
62+ this .defaultEventDataDeserializer = defaultEventDataDeserializer ;
63+ this .eventDataDeserializers = new IdentityHashMap <EventType , EventDataDeserializer >();
64+ this .tableMapEventByTableId = new HashMap <Long , TableMapEventData >();
6065 registerDefaultEventDataDeserializers ();
66+ afterEventDataDeserializerSet (null );
6167 }
6268
6369 public EventDeserializer (
@@ -70,14 +76,20 @@ public EventDeserializer(
7076 this .defaultEventDataDeserializer = defaultEventDataDeserializer ;
7177 this .eventDataDeserializers = eventDataDeserializers ;
7278 this .tableMapEventByTableId = tableMapEventByTableId ;
79+ afterEventDataDeserializerSet (null );
7380 }
7481
7582 private void registerDefaultEventDataDeserializers () {
76- eventDataDeserializers .put (EventType .FORMAT_DESCRIPTION , new FormatDescriptionEventDataDeserializer ());
77- eventDataDeserializers .put (EventType .ROTATE , new RotateEventDataDeserializer ());
78- eventDataDeserializers .put (EventType .QUERY , new QueryEventDataDeserializer ());
79- eventDataDeserializers .put (EventType .TABLE_MAP , new TableMapEventDataDeserializer ());
80- eventDataDeserializers .put (EventType .XID , new XidEventDataDeserializer ());
83+ eventDataDeserializers .put (EventType .FORMAT_DESCRIPTION ,
84+ new FormatDescriptionEventDataDeserializer ());
85+ eventDataDeserializers .put (EventType .ROTATE ,
86+ new RotateEventDataDeserializer ());
87+ eventDataDeserializers .put (EventType .QUERY ,
88+ new QueryEventDataDeserializer ());
89+ eventDataDeserializers .put (EventType .TABLE_MAP ,
90+ new TableMapEventDataDeserializer ());
91+ eventDataDeserializers .put (EventType .XID ,
92+ new XidEventDataDeserializer ());
8193 eventDataDeserializers .put (EventType .WRITE_ROWS ,
8294 new WriteRowsEventDataDeserializer (tableMapEventByTableId ));
8395 eventDataDeserializers .put (EventType .UPDATE_ROWS ,
@@ -93,12 +105,28 @@ private void registerDefaultEventDataDeserializers() {
93105 eventDataDeserializers .put (EventType .EXT_DELETE_ROWS ,
94106 new DeleteRowsEventDataDeserializer (tableMapEventByTableId ).
95107 setMayContainExtraInformation (true ));
96- eventDataDeserializers .put (EventType .ROWS_QUERY , new RowsQueryEventDataDeserializer ());
97- eventDataDeserializers .put (EventType .GTID , new GtidEventDataDeserializer ());
108+ eventDataDeserializers .put (EventType .ROWS_QUERY ,
109+ new RowsQueryEventDataDeserializer ());
110+ eventDataDeserializers .put (EventType .GTID ,
111+ new GtidEventDataDeserializer ());
98112 }
99113
100114 public void setEventDataDeserializer (EventType eventType , EventDataDeserializer eventDataDeserializer ) {
101115 eventDataDeserializers .put (eventType , eventDataDeserializer );
116+ afterEventDataDeserializerSet (eventType );
117+ }
118+
119+ private void afterEventDataDeserializerSet (EventType eventType ) {
120+ if (eventType == null || eventType == EventType .TABLE_MAP ) {
121+ EventDataDeserializer eventDataDeserializer = getEventDataDeserializer (EventType .TABLE_MAP );
122+ if (eventDataDeserializer .getClass () != TableMapEventDataDeserializer .class &&
123+ eventDataDeserializer .getClass () != EventDataWrapper .Deserializer .class ) {
124+ tableMapEventDataDeserializer = new EventDataWrapper .Deserializer (
125+ new TableMapEventDataDeserializer (), eventDataDeserializer );
126+ } else {
127+ tableMapEventDataDeserializer = null ;
128+ }
129+ }
102130 }
103131
104132 public void setChecksumType (ChecksumType checksumType ) {
@@ -113,17 +141,29 @@ public Event nextEvent(ByteArrayInputStream inputStream) throws IOException {
113141 return null ;
114142 }
115143 EventHeader eventHeader = eventHeaderDeserializer .deserialize (inputStream );
116- EventData eventData = deserializeEventData (inputStream , eventHeader );
144+ EventDataDeserializer eventDataDeserializer = getEventDataDeserializer (eventHeader .getEventType ());
145+ if (eventHeader .getEventType () == EventType .TABLE_MAP && tableMapEventDataDeserializer != null ) {
146+ eventDataDeserializer = tableMapEventDataDeserializer ;
147+ }
148+ EventData eventData = deserializeEventData (inputStream , eventHeader , eventDataDeserializer );
117149 if (eventHeader .getEventType () == EventType .TABLE_MAP ) {
118- TableMapEventData tableMapEvent = (TableMapEventData ) eventData ;
150+ TableMapEventData tableMapEvent ;
151+ if (eventData instanceof EventDataWrapper ) {
152+ EventDataWrapper eventDataWrapper = (EventDataWrapper ) eventData ;
153+ tableMapEvent = (TableMapEventData ) eventDataWrapper .getInternal ();
154+ if (tableMapEventDataDeserializer != null ) {
155+ eventData = eventDataWrapper .getExternal ();
156+ }
157+ } else {
158+ tableMapEvent = (TableMapEventData ) eventData ;
159+ }
119160 tableMapEventByTableId .put (tableMapEvent .getTableId (), tableMapEvent );
120161 }
121162 return new Event (eventHeader , eventData );
122163 }
123164
124- private EventData deserializeEventData (ByteArrayInputStream inputStream , EventHeader eventHeader )
125- throws EventDataDeserializationException {
126- EventDataDeserializer eventDataDeserializer = getEventDataDeserializer (eventHeader .getEventType ());
165+ private EventData deserializeEventData (ByteArrayInputStream inputStream , EventHeader eventHeader ,
166+ EventDataDeserializer eventDataDeserializer ) throws EventDataDeserializationException {
127167 // todo: use checksum algorithm descriptor from FormatDescriptionEvent
128168 // (as per http://dev.mysql.com/worklog/task/?id=2540)
129169 int eventBodyLength = (int ) eventHeader .getDataLength () - checksumLength ;
@@ -142,9 +182,64 @@ private EventData deserializeEventData(ByteArrayInputStream inputStream, EventHe
142182 return eventData ;
143183 }
144184
145- private EventDataDeserializer getEventDataDeserializer (EventType eventType ) {
185+ public EventDataDeserializer getEventDataDeserializer (EventType eventType ) {
146186 EventDataDeserializer eventDataDeserializer = eventDataDeserializers .get (eventType );
147187 return eventDataDeserializer != null ? eventDataDeserializer : defaultEventDataDeserializer ;
148188 }
149189
190+ /**
191+ * Enwraps internal {@link EventData} if custom {@link EventDataDeserializer} is provided (for internally used
192+ * events only).
193+ */
194+ public static class EventDataWrapper implements EventData {
195+
196+ private EventData internal ;
197+ private EventData external ;
198+
199+ public EventDataWrapper (EventData internal , EventData external ) {
200+ this .internal = internal ;
201+ this .external = external ;
202+ }
203+
204+ public EventData getInternal () {
205+ return internal ;
206+ }
207+
208+ public EventData getExternal () {
209+ return external ;
210+ }
211+
212+ @ Override
213+ public String toString () {
214+ final StringBuilder sb = new StringBuilder ("InternalEventData" );
215+ sb .append ("{internal=" ).append (internal );
216+ sb .append (", external=" ).append (external );
217+ sb .append ('}' );
218+ return sb .toString ();
219+ }
220+
221+ /**
222+ * {@link com.github.shyiko.mysql.binlog.event.deserialization.EventDeserializer.EventDataWrapper} deserializer.
223+ */
224+ public static class Deserializer implements EventDataDeserializer {
225+
226+ private EventDataDeserializer internal ;
227+ private EventDataDeserializer external ;
228+
229+ public Deserializer (EventDataDeserializer internal , EventDataDeserializer external ) {
230+ this .internal = internal ;
231+ this .external = external ;
232+ }
233+
234+ @ Override
235+ public EventData deserialize (ByteArrayInputStream inputStream ) throws IOException {
236+ byte [] bytes = inputStream .read (inputStream .available ());
237+ EventData internalEventData = internal .deserialize (new ByteArrayInputStream (bytes ));
238+ EventData externalEventData = external .deserialize (new ByteArrayInputStream (bytes ));
239+ return new EventDataWrapper (internalEventData , externalEventData );
240+ }
241+ }
242+
243+ }
244+
150245}
0 commit comments