Skip to content

Commit a4ac24a

Browse files
committed
v1.4.4: unmarshalInit Object and XML reader and writer hashmaps
1 parent bb337c9 commit a4ac24a

File tree

11 files changed

+270
-207
lines changed

11 files changed

+270
-207
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ EasyML
99
(http://sourceforge.net/projects/kxml/files/kxml2/2.3.0/kxml2-min-2.3.0.jar/download)
1010

1111

12+
!Release 1.4.4
13+
- refactor: made n.s.e.m.CompositeStrategy.unmarshalInit return type more
14+
loose to better support readResolve in n.s.e.m.j.i.ExternalizableStrategy.
15+
- refactor: n.s.e.XMLReader and n.s.e.XMLWriter use HashMap instead of
16+
ConcurrentHashMap if not in shared mode (i.e. if in standalone mode).
17+
18+
1219
!Release 1.4.3
1320
- feature: new n.s.e.m.j.i.ExternalizableStrategy offers support for the
1421
Java Externalizable protocol.

easyml/src/net/sourceforge/easyml/EasyML.java

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import net.sourceforge.easyml.marshalling.java.util.UUIDStrategy;
6767
import net.sourceforge.easyml.marshalling.java.util.VectorStrategy;
6868
import net.sourceforge.easyml.marshalling.java.util.regex.PatternStrategy;
69+
import net.sourceforge.easyml.util.Caching;
6970
import org.w3c.dom.Document;
7071
import org.xmlpull.v1.XmlPullParser;
7172

@@ -106,7 +107,7 @@
106107
* objects.<br/>
107108
*
108109
* @author Victor Cordis ( cordis.victor at gmail.com)
109-
* @version 1.4.0
110+
* @version 1.4.4
110111
* @since 1.0
111112
*
112113
* @see XMLReader
@@ -460,8 +461,10 @@ public interface XmlPullParserProvider {
460461

461462
private EasyML(Profile profile) {
462463
final ConcurrentHashMap<Class, Object> commonCtorCache = new ConcurrentHashMap<>();
463-
this.writerPrototype = new XMLWriter(commonCtorCache);
464-
this.readerPrototype = new XMLReader(commonCtorCache);
464+
final ConcurrentHashMap<String, Object> readerFieldCache = new ConcurrentHashMap<>();
465+
466+
this.writerPrototype = new XMLWriter(commonCtorCache, Caching.STRATEGY_PUT_IF_ABSENT);
467+
this.readerPrototype = new XMLReader(commonCtorCache, readerFieldCache, Caching.STRATEGY_PUT_IF_ABSENT);
465468
profile.configure(this.writerPrototype);
466469
profile.configure(this.readerPrototype);
467470
this.perThreadWriter = new ThreadLocal<XMLWriter>() {
@@ -633,7 +636,9 @@ public CompositeStrategy lookupCompositeStrategyBy(String name) {
633636
* @return a new shared-configuration writer
634637
*/
635638
public XMLWriter newWriter(Writer out) {
636-
return new XMLWriter(out, this.writerPrototype);
639+
final XMLWriter ret = new XMLWriter(writerPrototype);
640+
ret.reset(out);
641+
return ret;
637642
}
638643

639644
/**
@@ -649,7 +654,9 @@ public XMLWriter newWriter(Writer out) {
649654
* @return a new shared-configuration writer
650655
*/
651656
public XMLWriter newWriter(OutputStream out) {
652-
return new XMLWriter(out, this.writerPrototype);
657+
final XMLWriter ret = new XMLWriter(writerPrototype);
658+
ret.reset(out);
659+
return ret;
653660
}
654661

655662
/**
@@ -668,7 +675,9 @@ public XMLWriter newWriter(OutputStream out) {
668675
* @return a new shared-configuration writer
669676
*/
670677
public XMLWriter newWriter(Document out) {
671-
return new XMLWriter(out, this.writerPrototype);
678+
final XMLWriter ret = new XMLWriter(writerPrototype);
679+
ret.reset(out);
680+
return ret;
672681
}
673682

674683
/**
@@ -683,9 +692,9 @@ public XMLWriter newWriter(Document out) {
683692
* @return a new shared-configuration reader
684693
*/
685694
public XMLReader newReader(Reader in) {
686-
return this.xmlPullParserProvider != null
687-
? new XMLReader(in, this.xmlPullParserProvider.newXmlPullParser(), this.readerPrototype)
688-
: new XMLReader(in, this.readerPrototype);
695+
final XMLReader ret = new XMLReader(readerPrototype);
696+
ret.reset(in, maybeProvidedXmlPullParser());
697+
return ret;
689698
}
690699

691700
/**
@@ -718,7 +727,9 @@ public XMLReader newReader(InputStream in) {
718727
* @return a new shared-configuration reader
719728
*/
720729
public XMLReader newReader(Document in) {
721-
return new XMLReader(in, this.readerPrototype);
730+
final XMLReader ret = new XMLReader(readerPrototype);
731+
ret.reset(in);
732+
return ret;
722733
}
723734

724735
/**
@@ -790,13 +801,16 @@ public void serialize(Object o, Document out) {
790801
*/
791802
public Object deserialize(Reader in) {
792803
final XMLReader reader = this.perThreadReader.get();
793-
reader.reset(in, this.xmlPullParserProvider != null
794-
? this.xmlPullParserProvider.newXmlPullParser()
795-
: null
796-
);
804+
reader.reset(in, maybeProvidedXmlPullParser());
797805
return reader.read();
798806
}
799807

808+
private XmlPullParser maybeProvidedXmlPullParser() {
809+
return this.xmlPullParserProvider != null
810+
? this.xmlPullParserProvider.newXmlPullParser()
811+
: null;
812+
}
813+
800814
/**
801815
* De-serializes from the given input stream.
802816
* <br>

easyml/src/net/sourceforge/easyml/XMLReader.java

Lines changed: 21 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.util.List;
3939
import java.util.Map;
4040
import java.util.Set;
41-
import java.util.concurrent.ConcurrentHashMap;
4241
import net.sourceforge.easyml.marshalling.CompositeReader;
4342
import net.sourceforge.easyml.marshalling.CompositeStrategy;
4443
import net.sourceforge.easyml.marshalling.SimpleStrategy;
@@ -80,7 +79,7 @@
8079
*
8180
* @author Victor Cordis ( cordis.victor at gmail.com)
8281
* @since 1.0
83-
* @version 1.4.3
82+
* @version 1.4.4
8483
*/
8584
public class XMLReader implements Closeable {
8685

@@ -430,26 +429,26 @@ public S put(String key, S value) {
430429
private Map<String, Object> decoded;
431430
private boolean sharedConfiguration;
432431
private UnmarshalContextImpl context;
433-
/* default*/ ConcurrentHashMap<String, Object> cachedAliasingReflection;
434-
/* default*/ ConcurrentHashMap<Class, Object> cachedDefCtors;
432+
/* default*/ Map<String, Object> cachedAliasingReflection;
433+
/* default*/ Map<Class, Object> cachedDefCtors;
434+
private Caching.CachePutStrategy cachesPut;
435435
private Map<String, SimpleStrategy> simpleStrategies;
436436
private Map<String, CompositeStrategy> compositeStrategies;
437437
/* default*/ SimpleDateFormat dateFormat;
438438
/* default*/ SecurityPolicy securityPolicy;
439439

440440
/**
441-
* Creates a new instance. To be used by {@linkplain EasyML} only.
441+
* Creates a new configuration prototype instance, to be used by
442+
* {@linkplain EasyML} only.
442443
*/
443-
/* default*/ XMLReader(ConcurrentHashMap<Class, Object> commonCtorCache) {
444+
/* default*/ XMLReader(Map<Class, Object> ctorCache, Map<String, Object> aliasFieldCache, Caching.CachePutStrategy cachesPut) {
444445
this.driver = null;
445-
this.cachedDefCtors = commonCtorCache;
446-
this.init();
446+
this.init(ctorCache, aliasFieldCache, cachesPut);
447447
}
448448

449449
/**
450-
* Creates a new instance. To be used by {@linkplain EasyML} only.
451-
*
452-
* @param configured reader prototype
450+
* Creates a new shared-configuration instance, to be used by
451+
* {@linkplain EasyML} only.
453452
*/
454453
/* default*/ XMLReader(XMLReader configured) {
455454
this.driver = null;
@@ -468,19 +467,6 @@ public XMLReader(Reader reader) {
468467
this.init();
469468
}
470469

471-
/**
472-
* Creates a new shared-configuration instance with the given
473-
* <code>reader</code> to use and the <code>kXML2</code> parser as default.
474-
* The parser is set to the given reader.
475-
*
476-
* @param reader to read input with
477-
* @param configured xml reader prototype
478-
*/
479-
public XMLReader(Reader reader, XMLReader configured) {
480-
this.driver = new XMLReaderTextDriver(this, reader);
481-
this.initIdentically(configured);
482-
}
483-
484470
/**
485471
* Creates a new instance with the given <code>in</code> stream to read from
486472
* and the <code>kXML2</code> parser as default. The parser is set to the
@@ -493,19 +479,6 @@ public XMLReader(InputStream in) {
493479
this.init();
494480
}
495481

496-
/**
497-
* Creates a new shared-configuration instance with the given
498-
* <code>in</code> stream to read from and the <code>kXML2</code> parser as
499-
* default. The parser is set to the given stream.
500-
*
501-
* @param in stream from which to read
502-
* @param configured xml reader prototype
503-
*/
504-
public XMLReader(InputStream in, XMLReader configured) {
505-
this.driver = new XMLReaderTextDriver(this, new InputStreamReader(in));
506-
this.initIdentically(configured);
507-
}
508-
509482
/**
510483
* Creates a new instance with the given <code>reader</code> to use and the
511484
* <code>parser</code> to process XML with. The parser is set (or reset) to
@@ -519,20 +492,6 @@ public XMLReader(Reader reader, XmlPullParser parser) {
519492
this.init();
520493
}
521494

522-
/**
523-
* Creates a new shared-configuration instance with the given
524-
* <code>reader</code> to use and the <code>parser</code> to process XML
525-
* with. The parser is set (or reset) to the given reader.
526-
*
527-
* @param reader to read input with
528-
* @param parser to process the in XML with
529-
* @param configured xml reader prototype
530-
*/
531-
public XMLReader(Reader reader, XmlPullParser parser, XMLReader configured) {
532-
this.driver = new XMLReaderTextDriver(this, reader, parser);
533-
this.initIdentically(configured);
534-
}
535-
536495
/**
537496
* Creates a new instance with the given <code>in</code> stream to read from
538497
* and the <code>parser</code> to process XML with. The parser is set to the
@@ -546,20 +505,6 @@ public XMLReader(InputStream in, XmlPullParser parser) {
546505
this.init();
547506
}
548507

549-
/**
550-
* Creates a new shared-configuration instance with the given
551-
* <code>in</code> stream to read from and the <code>parser</code> to
552-
* process XML with. The parser is set to the given stream.
553-
*
554-
* @param in stream from which to read
555-
* @param parser to process the in XML with
556-
* @param configured xml reader prototype
557-
*/
558-
public XMLReader(InputStream in, XmlPullParser parser, XMLReader configured) {
559-
this.driver = new XMLReaderTextDriver(this, new InputStreamReader(in), parser);
560-
this.initIdentically(configured);
561-
}
562-
563508
/**
564509
* Creates a new instance with the given <code>in</code> DOM document to
565510
* read from.
@@ -571,29 +516,19 @@ public XMLReader(Document in) {
571516
this.init();
572517
}
573518

574-
/**
575-
* Creates a new shared-configuration instance with the given
576-
* <code>in</code> DOM document to read from.
577-
*
578-
* @param in stream from which to read
579-
* @param configured xml reader prototype
580-
*/
581-
public XMLReader(Document in, XMLReader configured) {
582-
this.driver = new XMLReaderDOMDriver(this, in);
583-
this.initIdentically(configured);
519+
private void init() {
520+
this.init(new HashMap<Class, Object>(), new HashMap<String, Object>(), Caching.STRATEGY_PUT);
584521
}
585522

586-
private void init() {
523+
private void init(Map<Class, Object> ctorCache, Map<String, Object> aliasFieldCache, Caching.CachePutStrategy cachesPut) {
587524
this.beforeRoot = true;
588525
this.rootTag = DTD.ELEMENT_EASYML;
589526
this.decoded = new HashMap<>();
590527
this.sharedConfiguration = false;
591528
this.context = new UnmarshalContextImpl();
592-
// The caches must be concurrent in case this instance will be used as a prototype:
593-
this.cachedAliasingReflection = new ConcurrentHashMap<>();
594-
if (this.cachedDefCtors == null) {
595-
this.cachedDefCtors = new ConcurrentHashMap<>();
596-
}
529+
this.cachedDefCtors = ctorCache;
530+
this.cachedAliasingReflection = aliasFieldCache;
531+
this.cachesPut = cachesPut;
597532
this.simpleStrategies = new StrategyHashMap<>();
598533
this.compositeStrategies = new StrategyHashMap<>();
599534
this.dateFormat = new SimpleDateFormat(DTD.FORMAT_DATE);
@@ -621,6 +556,7 @@ private void initIdentically(XMLReader other) {
621556
this.context = new UnmarshalContextImpl();
622557
this.cachedAliasingReflection = other.cachedAliasingReflection;
623558
this.cachedDefCtors = other.cachedDefCtors;
559+
this.cachesPut = other.cachesPut;
624560
this.simpleStrategies = other.simpleStrategies;
625561
this.compositeStrategies = other.compositeStrategies;
626562
this.dateFormat = new SimpleDateFormat(other.dateFormat.toPattern());
@@ -1250,10 +1186,10 @@ public <T> Constructor<T> defaultConstructorFor(Class<T> c)
12501186
}
12511187
try {
12521188
final Constructor<T> ctor = ReflectionUtil.defaultConstructor(c);
1253-
cachedDefCtors.putIfAbsent(c, ctor);
1189+
cachesPut.put(cachedDefCtors, c, ctor);
12541190
return ctor;
12551191
} catch (NoSuchMethodException noDefCtorX) {
1256-
cachedDefCtors.putIfAbsent(c, noDefCtorX);
1192+
cachesPut.put(cachedDefCtors, c, noDefCtorX);
12571193
throw noDefCtorX;
12581194
}
12591195
}
@@ -1291,7 +1227,7 @@ public Class classFor(String aliasOrName) throws ClassNotFoundException {
12911227
}
12921228
// else cache class:
12931229
final Class ret = ReflectionUtil.classForName(aliasOrName);
1294-
cachedAliasingReflection.putIfAbsent(aliasOrName, ret);
1230+
cachesPut.put(cachedAliasingReflection, aliasOrName, ret);
12951231
return ret;
12961232
}
12971233

@@ -1304,7 +1240,7 @@ public Field fieldFor(Class declaring, String aliasOrName) throws NoSuchFieldExc
13041240
}
13051241
// else cache field:
13061242
final Field ret = declaring.getDeclaredField(aliasOrName);
1307-
cachedAliasingReflection.putIfAbsent(fieldFQN, ret);
1243+
cachesPut.put(cachedAliasingReflection, fieldFQN, ret);
13081244
return ret;
13091245
}
13101246

0 commit comments

Comments
 (0)