1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.ldap.model.ldif;
21
22
23 import java.io.Externalizable;
24 import java.io.IOException;
25 import java.io.ObjectInput;
26 import java.io.ObjectOutput;
27 import java.util.HashMap;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.concurrent.ConcurrentHashMap;
32
33 import org.apache.directory.api.i18n.I18n;
34 import org.apache.directory.api.ldap.model.entry.Attribute;
35 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
36 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
37 import org.apache.directory.api.ldap.model.entry.DefaultModification;
38 import org.apache.directory.api.ldap.model.entry.Entry;
39 import org.apache.directory.api.ldap.model.entry.Modification;
40 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
41 import org.apache.directory.api.ldap.model.entry.StringValue;
42 import org.apache.directory.api.ldap.model.entry.Value;
43 import org.apache.directory.api.ldap.model.exception.LdapException;
44 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
45 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
46 import org.apache.directory.api.ldap.model.message.Control;
47 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
48 import org.apache.directory.api.ldap.model.name.Dn;
49 import org.apache.directory.api.ldap.model.name.Rdn;
50 import org.apache.directory.api.util.Base64;
51 import org.apache.directory.api.util.Strings;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public class LdifEntry implements Cloneable, Externalizable
69 {
70
71 public static final Modification[] EMPTY_MODS = new Modification[0];
72
73
74 private ChangeType changeType;
75
76
77 private List<Modification> modificationList;
78
79
80 private Map<String, Modification> modifications;
81
82
83 private String newSuperior;
84
85
86 private String newRdn;
87
88
89 private boolean deleteOldRdn;
90
91
92 private Entry entry;
93
94
95 private Dn entryDn;
96
97
98 private Map<String, LdifControl> controls;
99
100
101
102
103
104
105 private int lengthBeforeParsing = 0;
106
107
108 private long offset = 0;
109
110
111
112
113 public LdifEntry()
114 {
115 changeType = ChangeType.None;
116 modificationList = new LinkedList<Modification>();
117 modifications = new HashMap<String, Modification>();
118 entry = new DefaultEntry( ( Dn ) null );
119 entryDn = null;
120 controls = null;
121 }
122
123
124
125
126
127 public LdifEntry( Entry entry )
128 {
129 changeType = ChangeType.None;
130 modificationList = new LinkedList<Modification>();
131 modifications = new HashMap<String, Modification>();
132 this.entry = entry;
133 entryDn = entry.getDn();
134 controls = null;
135 }
136
137
138
139
140
141
142
143
144
145
146
147 public LdifEntry( Dn dn, Object... avas ) throws LdapInvalidAttributeValueException, LdapLdifException
148 {
149
150 StringBuilder sb = new StringBuilder();
151 int pos = 0;
152 boolean valueExpected = false;
153 String dnStr = null;
154
155 if ( dn == null )
156 {
157 dnStr = "";
158 }
159 else
160 {
161 dnStr = dn.getName();
162 }
163
164 if ( LdifUtils.isLDIFSafe( dnStr ) )
165 {
166 sb.append( "dn: " ).append( dnStr ).append( '\n' );
167 }
168 else
169 {
170 sb.append( "dn:: " ).append( Base64.encode( Strings.getBytesUtf8( dnStr ) ) ).append( '\n' );
171 }
172
173 for ( Object ava : avas )
174 {
175 if ( !valueExpected )
176 {
177 if ( !( ava instanceof String ) )
178 {
179 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
180 I18n.ERR_12085, ( pos + 1 ) ) );
181 }
182
183 String attribute = ( String ) ava;
184 sb.append( attribute );
185
186 if ( attribute.indexOf( ':' ) != -1 )
187 {
188 sb.append( '\n' );
189 }
190 else
191 {
192 valueExpected = true;
193 }
194 }
195 else
196 {
197 if ( ava instanceof String )
198 {
199 sb.append( ": " ).append( ( String ) ava ).append( '\n' );
200 }
201 else if ( ava instanceof byte[] )
202 {
203 sb.append( ":: " );
204 sb.append( new String( Base64.encode( ( byte[] ) ava ) ) );
205 sb.append( '\n' );
206 }
207 else
208 {
209 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
210 I18n.ERR_12086, ( pos + 1 ) ) );
211 }
212
213 valueExpected = false;
214 }
215 }
216
217 if ( valueExpected )
218 {
219 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n
220 .err( I18n.ERR_12087 ) );
221 }
222
223
224 LdifReader reader = new LdifReader();
225 List<LdifEntry> ldifEntries = reader.parseLdif( sb.toString() );
226
227 try
228 {
229 reader.close();
230 }
231 catch ( IOException e )
232 {
233 e.printStackTrace();
234 }
235
236 if ( ( ldifEntries != null ) && ( ldifEntries.size() == 1 ) )
237 {
238 LdifEntry ldifEntry = ldifEntries.get( 0 );
239
240 changeType = ldifEntry.getChangeType();
241 controls = ldifEntry.getControls();
242 entryDn = ldifEntry.getDn();
243
244 switch ( ldifEntry.getChangeType() )
245 {
246 case Add:
247
248 case None:
249 entry = ldifEntry.getEntry();
250 break;
251
252 case Delete:
253 break;
254
255 case ModDn:
256 case ModRdn:
257 newRdn = ldifEntry.getNewRdn();
258 newSuperior = ldifEntry.getNewSuperior();
259 deleteOldRdn = ldifEntry.isDeleteOldRdn();
260 break;
261
262 case Modify:
263 modificationList = ldifEntry.getModifications();
264 modifications = new HashMap<String, Modification>();
265
266 for ( Modification modification : modificationList )
267 {
268 modifications.put( modification.getAttribute().getId(), modification );
269 }
270
271 break;
272 }
273 }
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287 public LdifEntry( String dn, Object... strings )
288 throws LdapInvalidAttributeValueException, LdapLdifException, LdapInvalidDnException
289 {
290 this( new Dn( dn ), strings );
291 }
292
293
294
295
296
297
298
299 public void setDn( Dn dn )
300 {
301 entryDn = dn;
302 entry.setDn( dn );
303 }
304
305
306
307
308
309
310
311
312 public void setDn( String dn ) throws LdapInvalidDnException
313 {
314 entryDn = new Dn( dn );
315 entry.setDn( entryDn );
316 }
317
318
319
320
321
322
323
324
325 public void setChangeType( ChangeType changeType )
326 {
327 this.changeType = changeType;
328 }
329
330
331
332
333
334
335
336 public void setChangeType( String changeType )
337 {
338 if ( "add".equals( changeType ) )
339 {
340 this.changeType = ChangeType.Add;
341 }
342 else if ( "modify".equals( changeType ) )
343 {
344 this.changeType = ChangeType.Modify;
345 }
346 else if ( "moddn".equals( changeType ) )
347 {
348 this.changeType = ChangeType.ModDn;
349 }
350 else if ( "modrdn".equals( changeType ) )
351 {
352 this.changeType = ChangeType.ModRdn;
353 }
354 else if ( "delete".equals( changeType ) )
355 {
356 this.changeType = ChangeType.Delete;
357 }
358 }
359
360
361
362
363
364
365
366 public void addModification( Modification modification )
367 {
368 if ( changeType == ChangeType.Modify )
369 {
370 modificationList.add( modification );
371 modifications.put( modification.getAttribute().getId(), modification );
372 }
373 }
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388 public void addModification( ModificationOperation modOp, Attribute attr )
389 {
390 if ( changeType == ChangeType.Modify )
391 {
392 Modification item = new DefaultModification( modOp, attr );
393 modificationList.add( item );
394 modifications.put( attr.getId(), item );
395 }
396 }
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412 public void addModification( ModificationOperation modOp, String id, Object value )
413 {
414 if ( changeType == ChangeType.Modify )
415 {
416 Attribute attr;
417
418 if ( value == null )
419 {
420 value = new StringValue( ( String ) null );
421 attr = new DefaultAttribute( id, ( Value<?> ) value );
422 }
423 else
424 {
425 attr = ( Attribute ) value;
426 }
427
428 Modification item = new DefaultModification( modOp, attr );
429 modificationList.add( item );
430 modifications.put( id, item );
431 }
432 }
433
434
435
436
437
438
439
440
441 public void addAttribute( Attribute attr ) throws LdapException
442 {
443 entry.put( attr );
444 }
445
446
447
448
449
450
451
452
453
454
455 public void addAttribute( String id, Object... values ) throws LdapException
456 {
457 if ( values != null )
458 {
459 for ( Object value : values )
460 {
461 if ( value instanceof String )
462 {
463 entry.add( id, ( String ) value );
464 }
465 else
466 {
467 entry.add( id, ( byte[] ) value );
468 }
469 }
470 }
471 else
472 {
473 entry.add( id, ( Value<?> ) null );
474 }
475 }
476
477
478
479
480
481
482
483
484 public void removeAttribute( String... ids )
485 {
486 if ( entry.containsAttribute( ids ) )
487 {
488 entry.removeAttributes( ids );
489 }
490 }
491
492
493
494
495
496
497
498
499
500
501 public void putAttribute( String id, Object value ) throws LdapException
502 {
503 if ( value instanceof String )
504 {
505 entry.add( id, ( String ) value );
506 }
507 else
508 {
509 entry.add( id, ( byte[] ) value );
510 }
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527 public ChangeType getChangeType()
528 {
529 return changeType;
530 }
531
532
533
534
535
536 public List<Modification> getModifications()
537 {
538 return modificationList;
539 }
540
541
542
543
544
545
546
547 public Modification[] getModificationArray()
548 {
549 return modificationList.toArray( EMPTY_MODS );
550 }
551
552
553
554
555
556 public Dn getDn()
557 {
558 return entryDn;
559 }
560
561
562
563
564
565 public int size()
566 {
567 return modificationList.size();
568 }
569
570
571
572
573
574
575
576
577 public Attribute get( String attributeId )
578 {
579 if ( "dn".equalsIgnoreCase( attributeId ) )
580 {
581 return new DefaultAttribute( "dn", entry.getDn().getName() );
582 }
583
584 return entry.get( attributeId );
585 }
586
587
588
589
590
591
592
593 public Entry getEntry()
594 {
595 if ( isEntry() )
596 {
597 return entry;
598 }
599 else
600 {
601 return null;
602 }
603 }
604
605
606
607
608
609 public boolean isDeleteOldRdn()
610 {
611 return deleteOldRdn;
612 }
613
614
615
616
617
618
619
620 public void setDeleteOldRdn( boolean deleteOldRdn )
621 {
622 this.deleteOldRdn = deleteOldRdn;
623 }
624
625
626
627
628
629 public String getNewRdn()
630 {
631 return newRdn;
632 }
633
634
635
636
637
638
639
640 public void setNewRdn( String newRdn )
641 {
642 this.newRdn = newRdn;
643 }
644
645
646
647
648
649 public String getNewSuperior()
650 {
651 return newSuperior;
652 }
653
654
655
656
657
658
659
660 public void setNewSuperior( String newSuperior )
661 {
662 this.newSuperior = newSuperior;
663 }
664
665
666
667
668
669 public boolean isLdifContent()
670 {
671 return changeType == ChangeType.None;
672 }
673
674
675
676
677
678 public boolean isLdifChange()
679 {
680 return changeType != ChangeType.None;
681 }
682
683
684
685
686
687 public boolean isChangeAdd()
688 {
689 return changeType == ChangeType.Add;
690 }
691
692
693
694
695
696 public boolean isChangeDelete()
697 {
698 return changeType == ChangeType.Delete;
699 }
700
701
702
703
704
705 public boolean isChangeModDn()
706 {
707 return changeType == ChangeType.ModDn;
708 }
709
710
711
712
713
714 public boolean isChangeModRdn()
715 {
716 return changeType == ChangeType.ModRdn;
717 }
718
719
720
721
722
723 public boolean isChangeModify()
724 {
725 return changeType == ChangeType.Modify;
726 }
727
728
729
730
731
732
733
734 public boolean isEntry()
735 {
736 return ( changeType == ChangeType.None ) || ( changeType == ChangeType.Add );
737 }
738
739
740
741
742
743 public boolean hasControls()
744 {
745 return controls != null;
746 }
747
748
749
750
751
752 public Map<String, LdifControl> getControls()
753 {
754 return controls;
755 }
756
757
758
759
760
761
762 public LdifControl getControl( String oid )
763 {
764 if ( controls != null )
765 {
766 return controls.get( oid );
767 }
768
769 return null;
770 }
771
772
773
774
775
776
777
778 public void addControl( Control... controls )
779 {
780 if ( controls == null )
781 {
782 throw new IllegalArgumentException( "The added control must not be null" );
783 }
784
785 for ( Control control : controls )
786 {
787 if ( changeType == ChangeType.None )
788 {
789 changeType = ChangeType.Add;
790 }
791
792 if ( this.controls == null )
793 {
794 this.controls = new ConcurrentHashMap<String, LdifControl>();
795 }
796
797 if ( control instanceof LdifControl )
798 {
799 this.controls.put( control.getOid(), ( LdifControl ) control );
800 }
801 else
802 {
803 LdifControl ldifControl = new LdifControl( control.getOid() );
804 ldifControl.setCritical( control.isCritical() );
805 this.controls.put( control.getOid(), new LdifControl( control.getOid() ) );
806 }
807 }
808 }
809
810
811
812
813
814
815
816 public LdifEntry clone() throws CloneNotSupportedException
817 {
818 LdifEntry clone = ( LdifEntry ) super.clone();
819
820 if ( modificationList != null )
821 {
822 for ( Modification modif : modificationList )
823 {
824 Modification modifClone = new DefaultModification( modif.getOperation(),
825 modif.getAttribute().clone() );
826 clone.modificationList.add( modifClone );
827 }
828 }
829
830 if ( modifications != null )
831 {
832 for ( String key : modifications.keySet() )
833 {
834 Modification modif = modifications.get( key );
835 Modification modifClone = new DefaultModification( modif.getOperation(),
836 modif.getAttribute().clone() );
837 clone.modifications.put( key, modifClone );
838 }
839
840 }
841
842 if ( entry != null )
843 {
844 clone.entry = entry.clone();
845 }
846
847 return clone;
848 }
849
850
851
852
853
854
855
856
857 public int getLengthBeforeParsing()
858 {
859 return lengthBeforeParsing;
860 }
861
862
863
864
865
866 void setLengthBeforeParsing( int length )
867 {
868 this.lengthBeforeParsing = length;
869 }
870
871
872
873
874
875 public long getOffset()
876 {
877 return offset;
878 }
879
880
881
882
883
884 void setOffset( long offset )
885 {
886 this.offset = offset;
887 }
888
889
890
891
892
893 public String toString()
894 {
895 try
896 {
897 return LdifUtils.convertToLdif( this );
898 }
899 catch ( LdapException ne )
900 {
901 return "";
902 }
903 }
904
905
906
907
908
909
910
911 public int hashCode()
912 {
913 int result = 37;
914
915 if ( entry != null && entry.getDn() != null )
916 {
917 result = result * 17 + entry.getDn().hashCode();
918 }
919
920 if ( changeType != null )
921 {
922 result = result * 17 + changeType.hashCode();
923
924
925 switch ( changeType )
926 {
927 case None:
928
929 case Add:
930
931 if ( entry != null )
932 {
933 result = result * 17 + entry.hashCode();
934 }
935
936 break;
937
938 case Delete:
939
940 break;
941
942 case Modify:
943 if ( modificationList != null )
944 {
945 result = result * 17 + modificationList.hashCode();
946
947 for ( Modification modification : modificationList )
948 {
949 result = result * 17 + modification.hashCode();
950 }
951 }
952
953 break;
954
955 case ModDn:
956 case ModRdn:
957 result = result * 17;
958
959 if ( deleteOldRdn )
960 {
961 result++;
962 }
963 else
964 {
965 result--;
966 }
967
968 if ( newRdn != null )
969 {
970 result = result * 17 + newRdn.hashCode();
971 }
972
973 if ( newSuperior != null )
974 {
975 result = result * 17 + newSuperior.hashCode();
976 }
977
978 break;
979
980 default:
981 break;
982 }
983 }
984
985 if ( controls != null )
986 {
987 for ( String control : controls.keySet() )
988 {
989 result = result * 17 + control.hashCode();
990 }
991 }
992
993 return result;
994 }
995
996
997
998
999
1000 public boolean equals( Object o )
1001 {
1002
1003 if ( this == o )
1004 {
1005 return true;
1006 }
1007
1008 if ( o == null )
1009 {
1010 return false;
1011 }
1012
1013 if ( !( o instanceof LdifEntry ) )
1014 {
1015 return false;
1016 }
1017
1018 LdifEntry otherEntry = ( LdifEntry ) o;
1019
1020
1021 Dn thisDn = entryDn;
1022 Dn dnEntry = otherEntry.getDn();
1023
1024 if ( !thisDn.equals( dnEntry ) )
1025 {
1026 return false;
1027 }
1028
1029
1030 if ( changeType != otherEntry.changeType )
1031 {
1032 return false;
1033 }
1034
1035
1036 switch ( changeType )
1037 {
1038 case None:
1039
1040 case Add:
1041
1042 if ( entry.size() != otherEntry.entry.size() )
1043 {
1044 return false;
1045 }
1046
1047 if ( !entry.equals( otherEntry.entry ) )
1048 {
1049 return false;
1050 }
1051
1052 break;
1053
1054 case Delete:
1055
1056 break;
1057
1058 case Modify:
1059
1060
1061
1062 if ( modificationList == null )
1063 {
1064 if ( otherEntry.modificationList != null )
1065 {
1066 return false;
1067 }
1068 else
1069 {
1070 break;
1071 }
1072 }
1073
1074 if ( otherEntry.modificationList == null )
1075 {
1076 return false;
1077 }
1078
1079 if ( modificationList.size() != otherEntry.modificationList.size() )
1080 {
1081 return false;
1082 }
1083
1084
1085 int i = 0;
1086
1087 for ( Modification modification : modificationList )
1088 {
1089 if ( !modification.equals( otherEntry.modificationList.get( i ) ) )
1090 {
1091 return false;
1092 }
1093
1094 i++;
1095 }
1096
1097 break;
1098
1099 case ModDn:
1100 case ModRdn:
1101
1102 if ( deleteOldRdn != otherEntry.deleteOldRdn )
1103 {
1104 return false;
1105 }
1106
1107
1108 try
1109 {
1110 Rdn thisNewRdn = new Rdn( newRdn );
1111 Rdn entryNewRdn = new Rdn( otherEntry.newRdn );
1112
1113 if ( !thisNewRdn.equals( entryNewRdn ) )
1114 {
1115 return false;
1116 }
1117 }
1118 catch ( LdapInvalidDnException ine )
1119 {
1120 return false;
1121 }
1122
1123
1124 try
1125 {
1126 Dn thisNewSuperior = new Dn( newSuperior );
1127 Dn entryNewSuperior = new Dn( otherEntry.newSuperior );
1128
1129 if ( !thisNewSuperior.equals( entryNewSuperior ) )
1130 {
1131 return false;
1132 }
1133 }
1134 catch ( LdapInvalidDnException ine )
1135 {
1136 return false;
1137 }
1138
1139 break;
1140
1141 default:
1142 break;
1143 }
1144
1145 if ( controls != null )
1146 {
1147 Map<String, LdifControl> otherControls = otherEntry.controls;
1148
1149 if ( otherControls == null )
1150 {
1151 return false;
1152 }
1153
1154 if ( controls.size() != otherControls.size() )
1155 {
1156 return false;
1157 }
1158
1159 for ( String controlOid : controls.keySet() )
1160 {
1161 if ( !otherControls.containsKey( controlOid ) )
1162 {
1163 return false;
1164 }
1165
1166 Control thisControl = controls.get( controlOid );
1167 Control otherControl = otherControls.get( controlOid );
1168
1169 if ( thisControl == null )
1170 {
1171 if ( otherControl != null )
1172 {
1173 return false;
1174 }
1175 }
1176 else
1177 {
1178 if ( !thisControl.equals( otherControl ) )
1179 {
1180 return false;
1181 }
1182 }
1183 }
1184
1185 return true;
1186 }
1187 else
1188 {
1189 return otherEntry.controls == null;
1190 }
1191 }
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
1202 {
1203
1204 int type = in.readInt();
1205 changeType = ChangeType.getChangeType( type );
1206
1207
1208 switch ( changeType )
1209 {
1210 case Add:
1211 case None:
1212
1213 entry.readExternal( in );
1214 entryDn = entry.getDn();
1215
1216 break;
1217
1218 case Delete:
1219
1220 entryDn = new Dn();
1221 entryDn.readExternal( in );
1222
1223 break;
1224
1225 case ModDn:
1226
1227 case ModRdn:
1228
1229 entryDn = new Dn();
1230 entryDn.readExternal( in );
1231
1232 deleteOldRdn = in.readBoolean();
1233
1234 if ( in.readBoolean() )
1235 {
1236 newRdn = in.readUTF();
1237 }
1238
1239 if ( in.readBoolean() )
1240 {
1241 newSuperior = in.readUTF();
1242 }
1243
1244 break;
1245
1246 case Modify:
1247
1248 entryDn = new Dn();
1249 entryDn.readExternal( in );
1250
1251
1252 int nbModifs = in.readInt();
1253
1254 for ( int i = 0; i < nbModifs; i++ )
1255 {
1256 Modification modification = new DefaultModification();
1257 modification.readExternal( in );
1258
1259 addModification( modification );
1260 }
1261
1262 break;
1263 }
1264
1265 int nbControls = in.readInt();
1266
1267
1268 if ( nbControls > 0 )
1269 {
1270 controls = new ConcurrentHashMap<String, LdifControl>( nbControls );
1271
1272 for ( int i = 0; i < nbControls; i++ )
1273 {
1274 LdifControl control = new LdifControl();
1275
1276 control.readExternal( in );
1277
1278 controls.put( control.getOid(), control );
1279 }
1280 }
1281 }
1282
1283
1284
1285
1286
1287
1288
1289 public void writeExternal( ObjectOutput out ) throws IOException
1290 {
1291
1292 out.writeInt( changeType.getChangeType() );
1293
1294
1295 switch ( changeType )
1296 {
1297 case Add:
1298 case None:
1299 entry.writeExternal( out );
1300 break;
1301
1302
1303 case Delete:
1304
1305 entryDn.writeExternal( out );
1306 break;
1307
1308 case ModDn:
1309
1310 case ModRdn:
1311
1312 entryDn.writeExternal( out );
1313
1314 out.writeBoolean( deleteOldRdn );
1315
1316 if ( newRdn == null )
1317 {
1318 out.writeBoolean( false );
1319 }
1320 else
1321 {
1322 out.writeBoolean( true );
1323 out.writeUTF( newRdn );
1324 }
1325
1326 if ( newSuperior != null )
1327 {
1328 out.writeBoolean( true );
1329 out.writeUTF( newSuperior );
1330 }
1331 else
1332 {
1333 out.writeBoolean( false );
1334 }
1335 break;
1336
1337 case Modify:
1338
1339 entryDn.writeExternal( out );
1340
1341
1342 out.writeInt( modificationList.size() );
1343
1344 for ( Modification modification : modificationList )
1345 {
1346 modification.writeExternal( out );
1347 }
1348
1349 break;
1350 }
1351
1352
1353 if ( controls != null )
1354 {
1355
1356 out.writeInt( controls.size() );
1357
1358 for ( LdifControl control : controls.values() )
1359 {
1360 control.writeExternal( out );
1361 }
1362 }
1363 else
1364 {
1365
1366 out.writeInt( -1 );
1367 }
1368
1369
1370 out.flush();
1371 }
1372 }