Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance fixes #16

Open
wants to merge 14 commits into
base: JXPATH_1_3_RC4
Choose a base branch
from
42 changes: 25 additions & 17 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ under the License.
<parent>
<groupId>org.apache.commons</groupId>
<artifactId>commons-parent</artifactId>
<version>10</version>
<version>11</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>commons-jxpath</groupId>
<artifactId>commons-jxpath</artifactId>
<name>Commons JXPath</name>
<version>1.3-SNAPSHOT</version>
<!-- when cutting a release, be sure to modify the commons.release.version property,
found at /project/properties/commons.release.version in this document -->
<version>1.3</version>
<description>A Java-based implementation of XPath 1.0 that, in addition to XML processing, can inspect/modify Java object graphs (the library's explicit purpose) and even mixed Java/XML structures.</description>
<url>http://commons.apache.org/jxpath/</url>
<issueManagement>
Expand Down Expand Up @@ -62,7 +64,8 @@ under the License.

<properties>
<commons.componentid>jxpath</commons.componentid>
<commons.release.version>1.2</commons.release.version>
<!-- should agree with project.version for releases: -->
<commons.release.version>1.3</commons.release.version>
<commons.binary.suffix />
<commons.jira.id>JXPATH</commons.jira.id>
<commons.jira.pid>12310480</commons.jira.pid>
Expand Down Expand Up @@ -98,20 +101,32 @@ under the License.
<tarLongFileMode>gnu</tarLongFileMode>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<optional>true</optional>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.4.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
Expand Down Expand Up @@ -153,13 +168,6 @@ under the License.
<version>1.7.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2</version>
<optional>true</optional>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.mockrunner</groupId>
<artifactId>mockrunner-jdk1.3-j2ee1.3</artifactId>
Expand Down
3 changes: 3 additions & 0 deletions src/assembly/src.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,8 @@
<fileSet>
<directory>xdocs</directory>
</fileSet>
<fileSet>
<directory>conf</directory>
</fileSet>
</fileSets>
</assembly>
260 changes: 136 additions & 124 deletions src/java/org/apache/commons/jxpath/JXPathBasicBeanInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,153 +23,165 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

/**
* An implementation of JXPathBeanInfo based on JavaBeans' BeanInfo. Properties
* advertised by JXPathBasicBeanInfo are the same as those advertised by
* BeanInfo for the corresponding class.
*
* @see java.beans.BeanInfo
* @see java.beans.Introspector
*
* @author Dmitri Plotnikov
* @version $Revision$ $Date$
* @see java.beans.BeanInfo
* @see java.beans.Introspector
*/
@SuppressWarnings({"unchecked", "WeakerAccess"})
public class JXPathBasicBeanInfo implements JXPathBeanInfo {
private static final long serialVersionUID = -3863803443111484155L;

private static final Comparator PROPERTY_DESCRIPTOR_COMPARATOR = new Comparator() {
public int compare(Object left, Object right) {
return ((PropertyDescriptor) left).getName().compareTo(
((PropertyDescriptor) right).getName());
}
};

private boolean atomic = false;
private Class clazz;
private Class dynamicPropertyHandlerClass;
private transient PropertyDescriptor[] propertyDescriptors;
private transient HashMap propertyDescriptorMap;

/**
* Create a new JXPathBasicBeanInfo.
* @param clazz bean class
*/
public JXPathBasicBeanInfo(Class clazz) {
this.clazz = clazz;
}
private static final long serialVersionUID = -3863803443111484155L;

/**
* Create a new JXPathBasicBeanInfo.
* @param clazz bean class
* @param atomic whether objects of this class are treated as atomic
* objects which have no properties of their own.
*/
public JXPathBasicBeanInfo(Class clazz, boolean atomic) {
this.clazz = clazz;
this.atomic = atomic;
}
private static final Comparator PROPERTY_DESCRIPTOR_COMPARATOR =
Comparator.comparing(left -> ((PropertyDescriptor) left).getName());

/**
* Create a new JXPathBasicBeanInfo.
* @param clazz bean class
* @param dynamicPropertyHandlerClass dynamic property handler class
*/
public JXPathBasicBeanInfo(Class clazz, Class dynamicPropertyHandlerClass) {
this.clazz = clazz;
this.atomic = false;
this.dynamicPropertyHandlerClass = dynamicPropertyHandlerClass;
}
private boolean atomic = false;
private Class clazz;
private Class dynamicPropertyHandlerClass;
private transient volatile PropertyDescriptor[] propertyDescriptors;
private transient volatile Map propertyDescriptorMap;

/**
* Returns true if objects of this class are treated as atomic
* objects which have no properties of their own.
* @return boolean
*/
public boolean isAtomic() {
return atomic;
}
/**
* Create a new JXPathBasicBeanInfo.
*
* @param clazz bean class
*/
public JXPathBasicBeanInfo(Class clazz) {
this.clazz = clazz;
this.propertyDescriptors = descriptors();
}

/**
* Create a new JXPathBasicBeanInfo.
*
* @param clazz bean class
* @param atomic whether objects of this class are treated as atomic
* objects which have no properties of their own.
*/
public JXPathBasicBeanInfo(Class clazz, boolean atomic) {
this.clazz = clazz;
this.atomic = atomic;
this.propertyDescriptors = descriptors();
}

/**
* Create a new JXPathBasicBeanInfo.
*
* @param clazz bean class
* @param dynamicPropertyHandlerClass dynamic property handler class
*/
public JXPathBasicBeanInfo(Class clazz, Class dynamicPropertyHandlerClass) {
this.clazz = clazz;
this.atomic = false;
this.dynamicPropertyHandlerClass = dynamicPropertyHandlerClass;
this.propertyDescriptors = descriptors();
}

/**
* Returns true if objects of this class are treated as atomic
* objects which have no properties of their own.
*
* @return boolean
*/
public boolean isAtomic() {
return atomic;
}

/**
* Return true if the corresponding objects have dynamic properties.
* @return boolean
*/
public boolean isDynamic() {
return dynamicPropertyHandlerClass != null;
/**
* Return true if the corresponding objects have dynamic properties.
*
* @return boolean
*/
public boolean isDynamic() {
return dynamicPropertyHandlerClass != null;
}

public PropertyDescriptor[] getPropertyDescriptors() {
if (this.propertyDescriptors == null) {
this.propertyDescriptors = descriptors();
}
return this.propertyDescriptors;
}

public synchronized PropertyDescriptor[] getPropertyDescriptors() {
if (propertyDescriptors == null) {
if (clazz == Object.class) {
propertyDescriptors = new PropertyDescriptor[0];
}
else {
try {
BeanInfo bi = null;
if (clazz.isInterface()) {
bi = Introspector.getBeanInfo(clazz);
}
else {
bi = Introspector.getBeanInfo(clazz, Object.class);
}
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
PropertyDescriptor[] descriptors = new PropertyDescriptor[pds.length];
System.arraycopy(pds, 0, descriptors, 0, pds.length);
Arrays.sort(descriptors, PROPERTY_DESCRIPTOR_COMPARATOR);
propertyDescriptors = descriptors;
}
catch (IntrospectionException ex) {
ex.printStackTrace();
}
}
}
if (propertyDescriptors.length == 0) {
return propertyDescriptors;
}
PropertyDescriptor[] result = new PropertyDescriptor[propertyDescriptors.length];
System.arraycopy(propertyDescriptors, 0, result, 0, propertyDescriptors.length);
return result;
public PropertyDescriptor getPropertyDescriptor(String propertyName) {
if (this.propertyDescriptorMap == null) {
this.propertyDescriptorMap = descriptorsMap();
}
return (PropertyDescriptor) propertyDescriptorMap.get(propertyName);
}

public synchronized PropertyDescriptor getPropertyDescriptor(String propertyName) {
if (propertyDescriptorMap == null) {
propertyDescriptorMap = new HashMap();
PropertyDescriptor[] pds = getPropertyDescriptors();
for (int i = 0; i < pds.length; i++) {
propertyDescriptorMap.put(pds[i].getName(), pds[i]);
}
/**
* For a dynamic class, returns the corresponding DynamicPropertyHandler
* class.
*
* @return Class
*/
public Class getDynamicPropertyHandlerClass() {
return dynamicPropertyHandlerClass;
}

private PropertyDescriptor[] descriptors() {
if (clazz == Object.class) {
return new PropertyDescriptor[0];
} else {
try {
BeanInfo bi;
if (clazz.isInterface()) {
bi = Introspector.getBeanInfo(clazz);
} else {
bi = Introspector.getBeanInfo(clazz, Object.class);
}
return (PropertyDescriptor) propertyDescriptorMap.get(propertyName);
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
PropertyDescriptor[] descriptors = new PropertyDescriptor[pds.length];
System.arraycopy(pds, 0, descriptors, 0, pds.length);
Arrays.sort(descriptors, PROPERTY_DESCRIPTOR_COMPARATOR);
return descriptors;
} catch (IntrospectionException ex) {
ex.printStackTrace();
}
}
return new PropertyDescriptor[0];
}

/**
* For a dynamic class, returns the corresponding DynamicPropertyHandler
* class.
* @return Class
*/
public Class getDynamicPropertyHandlerClass() {
return dynamicPropertyHandlerClass;
private Map descriptorsMap() {
Map propertyDescriptorMap = new HashMap();
PropertyDescriptor[] pds = getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
propertyDescriptorMap.put(pd.getName(), pd);
}
return propertyDescriptorMap;
}

public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("BeanInfo [class = ");
buffer.append(clazz.getName());
if (isDynamic()) {
buffer.append(", dynamic");
}
if (isAtomic()) {
buffer.append(", atomic");
}
buffer.append(", properties = ");
PropertyDescriptor[] jpds = getPropertyDescriptors();
for (int i = 0; i < jpds.length; i++) {
buffer.append("\n ");
buffer.append(jpds[i].getPropertyType());
buffer.append(": ");
buffer.append(jpds[i].getName());
}
buffer.append("]");
return buffer.toString();

public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("BeanInfo [class = ");
buffer.append(clazz.getName());
if (isDynamic()) {
buffer.append(", dynamic");
}
if (isAtomic()) {
buffer.append(", atomic");
}
buffer.append(", properties = ");
PropertyDescriptor[] jpds = getPropertyDescriptors();
for (PropertyDescriptor jpd : jpds) {
buffer.append("\n ");
buffer.append(jpd.getPropertyType());
buffer.append(": ");
buffer.append(jpd.getName());
}
buffer.append("]");
return buffer.toString();
}


}
Loading