1414import java .util .Map ;
1515
1616/* package */ class ParseObjectSubclassingController {
17- private static class ObjectSubclassInfo {
18- public final Class <? extends ParseObject > type ;
19- public final Constructor <? extends ParseObject > constructor ;
20-
21- public ObjectSubclassInfo (Class <? extends ParseObject > clazz ) throws NoSuchMethodException , IllegalAccessException {
22- type = clazz ;
23- constructor = getConstructor (clazz );
24- }
25-
26- private static Constructor <? extends ParseObject > getConstructor (Class <? extends ParseObject > clazz ) throws NoSuchMethodException , IllegalAccessException {
27- Constructor <? extends ParseObject > constructor = clazz .getDeclaredConstructor ();
28- if (constructor == null ) {
29- throw new NoSuchMethodException ();
30- }
31- int modifiers = constructor .getModifiers ();
32- if (Modifier .isPublic (modifiers ) || (clazz .getPackage ().getName ().equals ("com.parse" ) &&
33- !(Modifier .isProtected (modifiers ) || Modifier .isPrivate (modifiers )))) {
34- return constructor ;
35- }
36- throw new IllegalAccessException ();
37- }
38- }
39-
4017 private final Object mutex = new Object ();
41- private final Map <String , ObjectSubclassInfo > registeredSubclasses = new HashMap <>();
18+ private final Map <String , Constructor <? extends ParseObject > > registeredSubclasses = new HashMap <>();
4219
4320 /* package */ String getClassName (Class <? extends ParseObject > clazz ) {
4421 ParseClassName info = clazz .getAnnotation (ParseClassName .class );
@@ -49,15 +26,15 @@ private static Constructor<? extends ParseObject> getConstructor(Class<? extends
4926 }
5027
5128 /* package */ boolean isSubclassValid (String className , Class <? extends ParseObject > clazz ) {
52- ObjectSubclassInfo info = null ;
29+ Constructor <? extends ParseObject > constructor = null ;
5330
5431 synchronized (mutex ) {
55- info = registeredSubclasses .get (className );
32+ constructor = registeredSubclasses .get (className );
5633 }
5734
58- return info == null
35+ return constructor == null
5936 ? clazz == ParseObject .class
60- : info . type == clazz ;
37+ : constructor . getDeclaringClass () == clazz ;
6138 }
6239
6340 /* package */ void registerSubclass (Class <? extends ParseObject > clazz ) {
@@ -66,29 +43,30 @@ private static Constructor<? extends ParseObject> getConstructor(Class<? extends
6643 }
6744
6845 String className = getClassName (clazz );
69- ObjectSubclassInfo previousInfo = null ;
46+ Constructor <? extends ParseObject > previousConstructor = null ;
7047
7148 synchronized (mutex ) {
72- previousInfo = registeredSubclasses .get (className );
73- if (previousInfo != null ) {
74- if (clazz .isAssignableFrom (previousInfo .type )) {
49+ previousConstructor = registeredSubclasses .get (className );
50+ if (previousConstructor != null ) {
51+ Class <? extends ParseObject > previousClass = previousConstructor .getDeclaringClass ();
52+ if (clazz .isAssignableFrom (previousClass )) {
7553 // Previous subclass is more specific or equal to the current type, do nothing.
7654 return ;
77- } else if (previousInfo . type .isAssignableFrom (clazz )) {
55+ } else if (previousClass .isAssignableFrom (clazz )) {
7856 // Previous subclass is parent of new child subclass, fallthrough and actually
7957 // register this class.
8058 /* Do nothing */
8159 } else {
8260 throw new IllegalArgumentException (
83- "Tried to register both " + previousInfo . type . getName () + " and " +
84- clazz . getName () + " as the ParseObject subclass of " + className + ". " +
85- "Cannot determine the right class to use because netiher inherits from the other."
61+ "Tried to register both " + previousClass . getName () + " and " + clazz . getName () +
62+ " as the ParseObject subclass of " + className + ". " + "Cannot determine the right " +
63+ " class to use because neither inherits from the other."
8664 );
8765 }
8866 }
8967
9068 try {
91- registeredSubclasses .put (className , new ObjectSubclassInfo (clazz ));
69+ registeredSubclasses .put (className , getConstructor (clazz ));
9270 } catch (NoSuchMethodException ex ) {
9371 throw new IllegalArgumentException (
9472 "Cannot register a type that does not implement the default constructor!"
@@ -100,7 +78,7 @@ private static Constructor<? extends ParseObject> getConstructor(Class<? extends
10078 }
10179 }
10280
103- if (previousInfo != null ) {
81+ if (previousConstructor != null ) {
10482 // TODO: This is super tightly coupled. Let's remove it when automatic registration is in.
10583 // NOTE: Perform this outside of the mutex, to prevent any potential deadlocks.
10684 if (className .equals (getClassName (ParseUser .class ))) {
@@ -120,20 +98,33 @@ private static Constructor<? extends ParseObject> getConstructor(Class<? extends
12098 }
12199
122100 /* package */ ParseObject newInstance (String className ) {
123- ObjectSubclassInfo info = null ;
101+ Constructor <? extends ParseObject > constructor = null ;
124102
125103 synchronized (mutex ) {
126- info = registeredSubclasses .get (className );
104+ constructor = registeredSubclasses .get (className );
127105 }
128106
129107 try {
130- return info != null
131- ? info . constructor .newInstance ()
108+ return constructor != null
109+ ? constructor .newInstance ()
132110 : new ParseObject (className );
133111 } catch (RuntimeException e ) {
134112 throw e ;
135113 } catch (Exception e ) {
136114 throw new RuntimeException ("Failed to create instance of subclass." , e );
137115 }
138116 }
117+
118+ private static Constructor <? extends ParseObject > getConstructor (Class <? extends ParseObject > clazz ) throws NoSuchMethodException , IllegalAccessException {
119+ Constructor <? extends ParseObject > constructor = clazz .getDeclaredConstructor ();
120+ if (constructor == null ) {
121+ throw new NoSuchMethodException ();
122+ }
123+ int modifiers = constructor .getModifiers ();
124+ if (Modifier .isPublic (modifiers ) || (clazz .getPackage ().getName ().equals ("com.parse" ) &&
125+ !(Modifier .isProtected (modifiers ) || Modifier .isPrivate (modifiers )))) {
126+ return constructor ;
127+ }
128+ throw new IllegalAccessException ();
129+ }
139130}
0 commit comments