import org.apache.fop.fo.PropertyListMaker;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.Property;
+import org.apache.fop.fo.properties.PropertyCache;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_marker">
}
/** Convenience inner class */
- private static final class MarkerAttribute {
+ public static final class MarkerAttribute {
- private static Map attributeCache =
- Collections.synchronizedMap(new java.util.WeakHashMap());
+ private static PropertyCache attributeCache =
+ new PropertyCache(MarkerAttribute.class);
protected String namespace;
protected String qname;
private static MarkerAttribute getInstance(
String namespace, String qname,
String name, String value) {
- MarkerAttribute newInstance =
- new MarkerAttribute(namespace, qname, name, value);
- if (attributeCache.containsKey(newInstance)) {
- return (MarkerAttribute) attributeCache.get(newInstance);
- } else {
- attributeCache.put(newInstance, newInstance);
- return newInstance;
- }
+ return attributeCache.fetch(
+ new MarkerAttribute(namespace, qname, name, value));
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ int hash = 17;
+ hash = (37 * hash) + (this.namespace == null ? 0 : this.namespace.hashCode());
+ hash = (37 * hash) + (this.qname == null ? 0 : this.qname.hashCode());
+ hash = (37 * hash) + (this.name == null ? 0 : this.name.hashCode());
+ hash = (37 * hash) + (this.value == null ? 0 : this.value.hashCode());
+ return hash;
}
/** {@inheritDoc} */
public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
if (o instanceof MarkerAttribute) {
MarkerAttribute attr = (MarkerAttribute) o;
return ((attr.namespace == this.namespace)
package org.apache.fop.fo.properties;
+import org.apache.fop.fo.flow.Marker;
+
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
private Class runtimeType;
- private boolean[] votesForRehash = new boolean[SEGMENT_COUNT];
+ private final boolean[] votesForRehash = new boolean[SEGMENT_COUNT];
/* same hash function as used by java.util.HashMap */
private static int hash(Object x) {
return (CommonBorderPaddingBackground.BorderInfo) fetch((Object) bi);
}
+ /**
+ * Checks if the given {@link Marker.MarkerAttribute} is present
+ * in the cache - if so, returns a reference to the cached instance.
+ * Otherwise the given object is added to the cache and returned.
+ *
+ * @param ma the MarkerAttribute instance to check for
+ * @return the cached instance
+ */
+ public Marker.MarkerAttribute fetch(
+ Marker.MarkerAttribute ma) {
+ return (Marker.MarkerAttribute) fetch((Object) ma);
+ }
+
/** {@inheritDoc} */
public String toString() {
return super.toString() + "[runtimeType=" + this.runtimeType + "]";
<changes>
<release version="FOP Trunk" date="TBD">
+ <action context="Code" dev="AD" type="fix" fixes-bug="46319">
+ Fixed a memory-leak in Marker.MarkerAttribute, where an instance was used both as key and value in
+ a WeakHashMap, effectively neutralizing the benefit of using WeakReferences. Solved by extending
+ PropertyCache to work for MarkerAttributes as well.
+ </action>
<action context="Renderers" dev="JM" type="fix" fixed-bug="46360">
Fixed a multi-threading issue when rendering SVG.
</action>