11/*
2- * Copyright (c) 2009-2021 jMonkeyEngine
2+ * Copyright (c) 2009-2025 jMonkeyEngine
33 * All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
3838import com .jme3 .export .Savable ;
3939import com .jme3 .export .SavableClassUtil ;
4040import com .jme3 .math .FastMath ;
41- import java .io .*;
41+
42+ import java .io .BufferedOutputStream ;
43+ import java .io .ByteArrayOutputStream ;
44+ import java .io .File ;
45+ import java .io .FileOutputStream ;
46+ import java .io .IOException ;
47+ import java .io .OutputStream ;
4248import java .util .ArrayList ;
4349import java .util .HashMap ;
4450import java .util .IdentityHashMap ;
116122 *
117123 * @author Joshua Slack
118124 */
119-
120125public class BinaryExporter implements JmeExporter {
121- private static final Logger logger = Logger . getLogger ( BinaryExporter . class
122- .getName ());
126+
127+ private static final Logger logger = Logger . getLogger ( BinaryExporter . class .getName ());
123128
124129 protected int aliasCount = 1 ;
125130 protected int idCount = 1 ;
126131
127- private final IdentityHashMap <Savable , BinaryIdContentPair > contentTable
128- = new IdentityHashMap <>();
129-
130- protected HashMap <Integer , Integer > locationTable
131- = new HashMap <>();
132+ private final IdentityHashMap <Savable , BinaryIdContentPair > contentTable = new IdentityHashMap <>();
133+ protected HashMap <Integer , Integer > locationTable = new HashMap <>();
132134
133135 // key - class name, value = bco
134- private final HashMap <String , BinaryClassObject > classes
135- = new HashMap <>();
136-
136+ private final HashMap <String , BinaryClassObject > classes = new HashMap <>();
137137 private final ArrayList <Savable > contentKeys = new ArrayList <>();
138138
139139 public static boolean debug = false ;
140140 public static boolean useFastBufs = true ;
141141
142+ /**
143+ * Constructs a new {@code BinaryExporter}.
144+ */
142145 public BinaryExporter () {
143146 }
144147
148+ /**
149+ * Returns a new instance of {@code BinaryExporter}.
150+ *
151+ * @return A new {@code BinaryExporter} instance.
152+ */
145153 public static BinaryExporter getInstance () {
146154 return new BinaryExporter ();
147155 }
148156
149157 /**
150158 * Saves the object into memory then loads it from memory.
151- *
152159 * Used by tests to check if the persistence system is working.
153160 *
154161 * @param <T> The type of savable.
@@ -163,9 +170,11 @@ public static <T extends Savable> T saveAndLoad(AssetManager assetManager, T obj
163170 try {
164171 BinaryExporter exporter = new BinaryExporter ();
165172 exporter .save (object , baos );
173+
166174 BinaryImporter importer = new BinaryImporter ();
167175 importer .setAssetManager (assetManager );
168176 return (T ) importer .load (baos .toByteArray ());
177+
169178 } catch (IOException ex ) {
170179 // Should never happen.
171180 throw new AssertionError (ex );
@@ -191,28 +200,25 @@ public void save(Savable object, OutputStream os) throws IOException {
191200 // write out tag table
192201 int classTableSize = 0 ;
193202 int classNum = classes .keySet ().size ();
194- int aliasSize = ((int ) FastMath .log (classNum , 256 ) + 1 ); // make all
195- // aliases a
196- // fixed width
203+ int aliasSize = ((int ) FastMath .log (classNum , 256 ) + 1 ); // make all aliases a fixed width
197204
198205 os .write (ByteUtils .convertToBytes (classNum )); // 3. "number of classes"
199206 for (String key : classes .keySet ()) {
200207 BinaryClassObject bco = classes .get (key );
201208
202209 // write alias
203- byte [] aliasBytes = fixClassAlias (bco .alias ,
204- aliasSize );
210+ byte [] aliasBytes = fixClassAlias (bco .alias , aliasSize );
205211 os .write (aliasBytes ); // 4. "class alias"
206212 classTableSize += aliasSize ;
207213
208214 // jME3 NEW: Write class hierarchy version numbers
209- os .write ( bco .classHierarchyVersions .length );
210- for (int version : bco .classHierarchyVersions ){
215+ os .write (bco .classHierarchyVersions .length );
216+ for (int version : bco .classHierarchyVersions ) {
211217 os .write (ByteUtils .convertToBytes (version ));
212218 }
213219 classTableSize += 1 + bco .classHierarchyVersions .length * 4 ;
214220
215- // write classname size & classname
221+ // write class name size & class name
216222 byte [] classBytes = key .getBytes ();
217223 os .write (ByteUtils .convertToBytes (classBytes .length )); // 5. "full class-name size"
218224 os .write (classBytes ); // 6. "full class name"
@@ -236,14 +242,12 @@ public void save(Savable object, OutputStream os) throws IOException {
236242 // write out data to a separate stream
237243 int location = 0 ;
238244 // keep track of location for each piece
239- HashMap <String , ArrayList <BinaryIdContentPair >> alreadySaved = new HashMap <>(
240- contentTable .size ());
245+ HashMap <String , ArrayList <BinaryIdContentPair >> alreadySaved = new HashMap <>(contentTable .size ());
241246 for (Savable savable : contentKeys ) {
242247 // look back at previous written data for matches
243248 String savableName = savable .getClass ().getName ();
244249 BinaryIdContentPair pair = contentTable .get (savable );
245- ArrayList <BinaryIdContentPair > bucket = alreadySaved
246- .get (savableName + getChunk (pair ));
250+ ArrayList <BinaryIdContentPair > bucket = alreadySaved .get (savableName + getChunk (pair ));
247251 int prevLoc = findPrevMatch (pair , bucket );
248252 if (prevLoc != -1 ) {
249253 locationTable .put (pair .getId (), prevLoc );
@@ -286,17 +290,14 @@ public void save(Savable object, OutputStream os) throws IOException {
286290 // append stream to the output stream
287291 out .writeTo (os );
288292
289-
290- out = null ;
291- os = null ;
292-
293293 if (debug ) {
294- logger .fine ("Stats:" );
295- logger .log (Level .FINE , "classes: {0}" , classNum );
296- logger .log (Level .FINE , "class table: {0} bytes" , classTableSize );
297- logger .log (Level .FINE , "objects: {0}" , numLocations );
298- logger .log (Level .FINE , "location table: {0} bytes" , locationTableSize );
299- logger .log (Level .FINE , "data: {0} bytes" , location );
294+ logger .log (Level .INFO , "BinaryExporter Stats:"
295+ + "\n * Classes: {0}"
296+ + "\n * Class Table: {1} bytes"
297+ + "\n * Objects: {2}"
298+ + "\n * Location Table: {3} bytes"
299+ + "\n * Data: {4} bytes" ,
300+ new Object [] {classNum , classTableSize , numLocations , locationTableSize , location });
300301 }
301302 }
302303
@@ -305,14 +306,15 @@ private String getChunk(BinaryIdContentPair pair) {
305306 .getContent ().bytes .length ));
306307 }
307308
308- private int findPrevMatch (BinaryIdContentPair oldPair ,
309- ArrayList <BinaryIdContentPair > bucket ) {
310- if (bucket == null )
309+ private int findPrevMatch (BinaryIdContentPair oldPair , ArrayList <BinaryIdContentPair > bucket ) {
310+ if (bucket == null ) {
311311 return -1 ;
312+ }
312313 for (int x = bucket .size (); --x >= 0 ;) {
313314 BinaryIdContentPair pair = bucket .get (x );
314- if (pair .getContent ().equals (oldPair .getContent ()))
315+ if (pair .getContent ().equals (oldPair .getContent ())) {
315316 return locationTable .get (pair .getId ());
317+ }
316318 }
317319 return -1 ;
318320 }
@@ -345,7 +347,7 @@ public OutputCapsule getCapsule(Savable object) {
345347 return contentTable .get (object ).getContent ();
346348 }
347349
348- private BinaryClassObject createClassObject (Class <? extends Savable > clazz ) throws IOException {
350+ private BinaryClassObject createClassObject (Class <? extends Savable > clazz ) throws IOException {
349351 BinaryClassObject bco = new BinaryClassObject ();
350352 bco .alias = generateTag ();
351353 bco .nameFields = new HashMap <>();
@@ -361,10 +363,10 @@ public int processBinarySavable(Savable object) throws IOException {
361363 return -1 ;
362364 }
363365 Class <? extends Savable > clazz = object .getClass ();
364- BinaryClassObject bco = classes .get (object . getClass () .getName ());
366+ BinaryClassObject bco = classes .get (clazz .getName ());
365367 // is this class been looked at before? in tagTable?
366368 if (bco == null ) {
367- bco = createClassObject (object . getClass () );
369+ bco = createClassObject (clazz );
368370 }
369371
370372 // is object in contentTable?
@@ -379,7 +381,6 @@ public int processBinarySavable(Savable object) throws IOException {
379381 object .write (this );
380382 newPair .getContent ().finish ();
381383 return newPair .getId ();
382-
383384 }
384385
385386 protected byte [] generateTag () {
@@ -401,4 +402,4 @@ private BinaryIdContentPair generateIdContentPair(BinaryClassObject bco) {
401402 new BinaryOutputCapsule (this , bco ));
402403 return pair ;
403404 }
404- }
405+ }
0 commit comments