Permalink
Browse files

FACES-2605 Improve performance of com.liferay.faces.util.map.Abstract…

…PropertyMap by reducing calls to getPropertyNames()
  • Loading branch information...
1 parent 6230ccd commit d34c496927de6d45f4fc48c3e2250202d3dd1ed8 @ngriffin7a ngriffin7a committed Feb 11, 2017
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2000-2016 Liferay, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.liferay.faces.bridge.context.map.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.liferay.faces.util.map.AbstractPropertyMap;
+
+
+/**
+ * This class extends {@link AbstractPropertyMap} in order to provide a non-thread-safe performance optimization for the
+ * {@link #containsKey(Object)} and {@link #getPropertyNames()} methods. The {@link #removeProperty(String)} and {@link
+ * #setProperty(String, Object)} methods throw {@link UnsupportedOperationException} in order to enforce immutability.
+ *
+ * @author Neil Griffin
+ */
+public abstract class AbstractImmutablePropertyMap<V> extends AbstractPropertyMap<V> {
+
+ // Private Data Members
+ private Set<String> propertyNames;
+
+ @Override
+ public boolean containsKey(Object key) {
+
+ initPropertyNames();
+
+ return propertyNames.contains(key);
+ }
+
+ protected abstract Enumeration<String> getImmutablePropertyNames();
+
+ @Override
+ protected Enumeration<String> getPropertyNames() {
+
+ initPropertyNames();
+
+ return Collections.enumeration(propertyNames);
+ }
+
+ @Override
+ protected void removeProperty(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void setProperty(String name, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ private void initPropertyNames() {
+
+ if (propertyNames == null) {
+ Enumeration<String> attributeNames = getImmutablePropertyNames();
+ ArrayList<String> attributeNameList = Collections.list(attributeNames);
+ propertyNames = new LinkedHashSet<String>(attributeNameList);
+ }
+ }
+}
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2000-2016 Liferay, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.liferay.faces.bridge.context.map.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.liferay.faces.util.map.AbstractPropertyMap;
+
+
+/**
+ * This class extends {@link AbstractPropertyMap} in order to provide a non-thread-safe performance optimization for the
+ * {@link #containsKey(Object)} and {@link #getPropertyNames()} methods.
+ *
+ * @author Neil Griffin
+ */
+public abstract class AbstractMutablePropertyMap<V> extends AbstractPropertyMap<V> {
+
+ // Private Data Members
+ private Set<String> propertyNames;
+
+ @Override
+ public boolean containsKey(Object key) {
+
+ initPropertyNames();
+
+ return propertyNames.contains(key);
+ }
+
+ protected abstract V getMutableProperty(String name);
+
+ protected abstract Enumeration<String> getMutablePropertyNames();
+
+ protected abstract void removeMutableProperty(String name);
+
+ protected abstract void setMutableProperty(String name, V value);
+
+ @Override
+ protected V getProperty(String name) {
+ return getMutableProperty(name);
+ }
+
+ @Override
+ protected Enumeration<String> getPropertyNames() {
+
+ initPropertyNames();
+
+ return Collections.enumeration(propertyNames);
+ }
+
+ @Override
+ protected void removeProperty(String name) {
+
+ if (propertyNames != null) {
+ propertyNames.remove(name);
+ }
+
+ removeMutableProperty(name);
+ }
+
+ @Override
+ protected void setProperty(String name, V value) {
+
+ if (propertyNames != null) {
+
+ if (value == null) {
+
+ // Cause the set of property names to get re-initialized since setting a value to null might cause the
+ // property to be removed from the underlying enumeration.
+ propertyNames = null;
+ }
+ else {
+
+ if (!propertyNames.contains(name)) {
+ propertyNames.add(name);
+ }
+ }
+ }
+
+ setMutableProperty(name, value);
+ }
+
+ private void initPropertyNames() {
+
+ if (propertyNames == null) {
+ Enumeration<String> attributeNames = getMutablePropertyNames();
+ ArrayList<String> attributeNameList = Collections.list(attributeNames);
+ propertyNames = new LinkedHashSet<String>(attributeNameList);
+ }
+ }
+}
@@ -28,14 +28,16 @@
import com.liferay.faces.bridge.bean.internal.PreDestroyInvoker;
import com.liferay.faces.bridge.bean.internal.PreDestroyInvokerFactory;
import com.liferay.faces.util.config.ApplicationConfig;
-import com.liferay.faces.util.map.AbstractPropertyMap;
import com.liferay.faces.util.map.AbstractPropertyMapEntry;
/**
+ * This class provides a {@link Map<String,Object>} abstraction over the {@link PortletContext} attributes. Since it is
+ * designed to exist and be used within the scope of a request, it is not thread-safe.
+ *
* @author Neil Griffin
*/
-public class ApplicationScopeMap extends AbstractPropertyMap<Object> {
+public class ApplicationScopeMap extends AbstractMutablePropertyMap<Object> {
// Private Data Members
private BeanManager beanManager;
@@ -106,22 +108,22 @@ public Object remove(Object key) {
}
@Override
- protected Object getProperty(String name) {
+ protected Object getMutableProperty(String name) {
return portletContext.getAttribute(name);
}
@Override
- protected Enumeration<String> getPropertyNames() {
+ protected Enumeration<String> getMutablePropertyNames() {
return portletContext.getAttributeNames();
}
@Override
- protected void removeProperty(String name) {
+ protected void removeMutableProperty(String name) {
portletContext.removeAttribute(name);
}
@Override
- protected void setProperty(String name, Object value) {
+ protected void setMutableProperty(String name, Object value) {
portletContext.setAttribute(name, value);
}
}
@@ -19,15 +19,18 @@
import javax.portlet.PortletContext;
-import com.liferay.faces.util.map.AbstractPropertyMap;
import com.liferay.faces.util.map.AbstractPropertyMapEntry;
/**
+ * This class provides a {@link java.util.Map<String,String>} abstraction over the {@link PortletContext} init
+ * parameters. Since it is designed to exist and be used within the scope of a request, it is not thread-safe.
+ *
* @author Neil Griffin
*/
-public class InitParameterMap extends AbstractPropertyMap<String> {
+public class InitParameterMap extends AbstractImmutablePropertyMap<String> {
+ // Private Data Members
private PortletContext portletContext;
public InitParameterMap(PortletContext portletContext) {
@@ -40,22 +43,12 @@ public InitParameterMap(PortletContext portletContext) {
}
@Override
- protected String getProperty(String name) {
- return portletContext.getInitParameter(name);
- }
-
- @Override
- protected Enumeration<String> getPropertyNames() {
+ protected Enumeration<String> getImmutablePropertyNames() {
return portletContext.getInitParameterNames();
}
@Override
- protected void removeProperty(String name) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected void setProperty(String name, String value) {
- throw new UnsupportedOperationException();
+ protected String getProperty(String name) {
+ return portletContext.getInitParameter(name);
}
}
@@ -24,20 +24,26 @@
/**
+ * This class provides a {@link Map<String,Object>} abstraction over request cookies. Since it is designed to exist and
+ * be used within the scope of a request, it is not thread-safe.
+ *
* @author Neil Griffin
*/
public class RequestCookieMap implements Map<String, Object> {
+ // Private Data Members
private Cookie[] cookies;
public RequestCookieMap(Cookie[] cookies) {
this.cookies = cookies;
}
+ @Override
public void clear() {
throw new UnsupportedOperationException();
}
+ @Override
public boolean containsKey(Object key) {
boolean found = false;
@@ -59,6 +65,7 @@ public boolean containsKey(Object key) {
return found;
}
+ @Override
public boolean containsValue(Object value) {
boolean found = false;
@@ -76,6 +83,7 @@ public boolean containsValue(Object value) {
return found;
}
+ @Override
public Set<Map.Entry<String, Object>> entrySet() {
Set<Map.Entry<String, Object>> entrySet = null;
@@ -92,6 +100,7 @@ public boolean containsValue(Object value) {
return entrySet;
}
+ @Override
public Cookie get(Object key) {
Cookie value = null;
@@ -111,10 +120,12 @@ public Cookie get(Object key) {
return value;
}
+ @Override
public boolean isEmpty() {
return ((cookies == null) || (cookies.length == 0));
}
+ @Override
public Set<String> keySet() {
Set<String> keySet = null;
@@ -130,18 +141,22 @@ public boolean isEmpty() {
return keySet;
}
+ @Override
public Cookie put(String key, Object value) {
throw new UnsupportedOperationException();
}
+ @Override
public void putAll(Map<? extends String, ? extends Object> t) {
throw new UnsupportedOperationException();
}
+ @Override
public Cookie remove(Object key) {
throw new UnsupportedOperationException();
}
+ @Override
public int size() {
int size = 0;
@@ -152,6 +167,7 @@ public int size() {
return size;
}
+ @Override
public Collection<Object> values() {
Collection<Object> values = null;
@@ -23,6 +23,9 @@
/**
+ * This class provides a {@link Map<String,String>} abstraction over request headers. Since it is designed to exist and
+ * be used within the scope of a request, it is not thread-safe.
+ *
* @author Neil Griffin
*/
public class RequestHeaderMap extends CaseInsensitiveHashMap<String> {
@@ -31,6 +31,9 @@
/**
+ * This class provides a @link Map<String,String[]>} abstraction over request header values. Since it is designed to
+ * exist and be used within the scope of a request, it is not thread-safe.
+ *
* @author Neil Griffin
*/
public class RequestHeaderValuesMap extends RequestHeaderValuesMapCompat {
Oops, something went wrong.

0 comments on commit d34c496

Please sign in to comment.