Skip to content
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