[hibernate-issues] [Hibernate-JIRA] Created: (HHH-5094) PersistenceUtilHelper cannot access non-public fields/methods (it should be able to)

Philip Clay (JIRA) noreply at atlassian.com
Fri Apr 9 12:19:01 EDT 2010


PersistenceUtilHelper cannot access non-public fields/methods (it should be able to)
------------------------------------------------------------------------------------

                 Key: HHH-5094
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5094
             Project: Hibernate Core
          Issue Type: Bug
          Components: entity-manager
    Affects Versions: 3.5.0-Final
         Environment: 3.5.0-Final.  Any environment
            Reporter: Philip Clay
         Attachments: hibernate-entitymanager-bugreproduction.tgz

PersistenceUtilHelper is only able to access public fields and public methods.  As it is written, it cannot access non-public members.

Internally, it incorrectly uses Class.getField(...) and Class.getMethod(...).

It should use Class.getDeclaredField(...) and Class.getDeclaredMethod(...), so that it can see non-public members.


I believe the use of getField and getMethod is not indented, because setAccessibility is the next call after that.  Here is the code...

{code}
	private static Object get(Object proxy, String property) {
		final Class<?> clazz = proxy.getClass();
		try {
			try {
				final Field field = clazz.getField( property );  // only retrieves public fields!!!
				setAccessibility( field );                       // if you really only wanted public fields, this call is unnecessary!
				return field.get( proxy );
			}
			catch ( NoSuchFieldException e ) {
				final Method method = getMethod( clazz, property );
				if (method != null) {
					setAccessibility( method );              // if you really only wanted public methods, this call is unnecessary!
					return method.invoke( proxy );
				}
		...
	}

	private static Method getMethod(Class<?> clazz, String methodName) {
		try {
			char string[] = methodName.toCharArray();
			string[0] = Character.toUpperCase( string[0] );
			methodName = new String( string );
			try {
				return clazz.getMethod( "get" + methodName );  // only retrieves public methods!!!
			}
			catch ( NoSuchMethodException e ) {
				return clazz.getMethod( "is" + methodName );  // only retrieves public methods!!!
			}
		...
	}

	private static void setAccessibility(Member member) {
		if ( !Modifier.isPublic( member.getModifiers() ) ) {
			//Sun's ease of use, sigh...
			( ( AccessibleObject ) member ).setAccessible( true );  // This is dead code!  The input member will always be public
		}
	}
{code}

Notice the call to setAccessibility.  The call to setAccessibility shows that one assumes that the field retrieved from getField() (or method from getMethod()) could be non-public, which in fact it can't.  All fields returned from getField will always be public (same for getMethod()).  So, essentially the code inside the if statement in setAccessibility is dead code.


I have attached a tarball containing a failing testcase that shows the incorrect behavior.

Explode the tarball and run "mvn test" to reproduce the incorrect behavior.

Also, within the tarball, I have included an svn diff for a proposed patch.

See the README.txt file within the tarball for more info.



I first noticed this problem when using hibernate validator to validate some protected members, but I narrowed it down to a problem in PersistenceUtilHelper.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list