1 package org.xmlfield.core;
2
3 import java.util.Map;
4
5 /**
6 * Factory used to create XmlField instances.
7 * <p>
8 * This factory is thread safe and can be configured to use ThreadLocal to reuse
9 * XmlField instances for performance reasons.
10 * <p>
11 * When using ThreadLocal, configuration ( parserConfiguration and getter cache)
12 * is unique (static) across all XmlFieldFactory instances.
13 *
14 *
15 * @see CleanThreadLocalFilter
16 *
17 * @author Nicolas Richeton
18 *
19 */
20 public class XmlFieldFactory {
21
22 private static Boolean staticGetterCache = null;
23 private static Map<String, String> staticParserConfiguration = null;
24 /**
25 * XmlFiled instances associated to threads. Used only if useThreadLocal is
26 * true.
27 */
28 private static final ThreadLocal<XmlField> xmlFieldInstances = new ThreadLocal<XmlField>() {
29 @Override
30 protected XmlField initialValue() {
31 XmlField xf = new XmlField(staticParserConfiguration);
32 if (staticGetterCache != null) {
33 xf.setGetterCache(staticGetterCache);
34 }
35 return xf;
36 }
37 };
38
39 private Boolean getterCache = null;
40 private Map<String, String> parserConfiguration = null;
41
42 private final boolean useThreadLocal;
43
44 public XmlFieldFactory() {
45 this(false);
46 }
47
48 /**
49 * @param useThreadLocal
50 * When enabled, the factory will create only one XmlField object
51 * per thread and reuse it each time {@link #getXmlField()} is
52 * called.
53 * <p>
54 * This improves performance if {@link #getXmlField()} is called
55 * several times in the same thread. But it is still better to
56 * keep the XmlField object and reuse it because it it not
57 * subject to synchronization.
58 *
59 * <p>
60 * When used in a web application, it is recommended to use a
61 * servlet filter which clears the context after each call to
62 * prevent leaks in application servers.
63 *
64 * @see CleanThreadLocalFilter
65 */
66 public XmlFieldFactory(boolean useThreadLocal) {
67 this.useThreadLocal = useThreadLocal;
68 }
69
70 /**
71 * Clean the XmlField instance of the current thread.
72 */
73 public void cleanThreadLocal() {
74 if (useThreadLocal) {
75 xmlFieldInstances.remove();
76 }
77 }
78
79 /**
80 * Get a new XmlField instance, or the instance associated with the current
81 * thread if {@link #setUseThreadLocal(boolean)} is enabled.
82 *
83 * @return
84 */
85 public XmlField getXmlField() {
86 if (useThreadLocal) {
87 return xmlFieldInstances.get();
88 }
89
90 XmlField xf = new XmlField(parserConfiguration);
91 if (getterCache != null) {
92 xf.setGetterCache(getterCache);
93 }
94
95 return xf;
96 }
97
98 /**
99 * Enable Getter cache.
100 *
101 * @see XmlField#setGetterCache(boolean)
102 * @param enabled
103 */
104 public void setGetterCache(boolean enabled) {
105 if (useThreadLocal) {
106 staticGetterCache = enabled;
107 } else {
108 this.getterCache = enabled;
109 }
110 }
111
112 /**
113 * Set parser configuration. All XmlField instances will use this
114 * configuration.
115 *
116 * @param configuration
117 */
118 public void setParserConfiguration(Map<String, String> configuration) {
119 if (useThreadLocal) {
120 staticParserConfiguration = configuration;
121 } else {
122 parserConfiguration = configuration;
123 }
124 }
125
126 }