Skip to content

Commit 45c0413

Browse files
committed
Merge pull request androidannotations#1158 from WonderCsabo/1116_fixRoboGuiceSupportV4Problem
Fixed classpath issues with RoboGuice
2 parents f71fb28 + 574fd51 commit 45c0413

8 files changed

Lines changed: 94 additions & 23 deletions

File tree

‎AndroidAnnotations/androidannotations-api/META-INF/MANIFEST.MF‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Export-Package: org.androidannotations.annotations,
1010
org.androidannotations.api,
1111
org.androidannotations.api.builder,
1212
org.androidannotations.api.rest,
13+
org.androidannotations.api.roboguice,
1314
org.androidannotations.api.sharedpreferences,
1415
org.androidannotations.api.view
1516
Bundle-Vendor: androidannotations
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.androidannotations.api.roboguice;
2+
3+
import java.lang.reflect.InvocationTargetException;
4+
import java.lang.reflect.Method;
5+
6+
/**
7+
* Reflection utils to call methods which are accessible in RoboGuice package
8+
* but not from outside.
9+
*/
10+
public class RoboGuiceHelper {
11+
12+
public static void callInjectViews(Object activity) {
13+
try {
14+
Class<?> viewMembersInjectorClass = Class.forName("roboguice.inject.ViewListener$ViewMembersInjector");
15+
Method injectViewsMethod = viewMembersInjectorClass.getDeclaredMethod("injectViews", Object.class);
16+
injectViewsMethod.setAccessible(true);
17+
injectViewsMethod.invoke(null, activity);
18+
} catch (ClassNotFoundException e) {
19+
propagateRuntimeException(e);
20+
} catch (NoSuchMethodException e) {
21+
propagateRuntimeException(e);
22+
} catch (SecurityException e) {
23+
propagateRuntimeException(e);
24+
} catch (IllegalAccessException e) {
25+
propagateRuntimeException(e);
26+
} catch (IllegalArgumentException e) {
27+
propagateRuntimeException(e);
28+
} catch (InvocationTargetException e) {
29+
propagateRuntimeException(e);
30+
}
31+
}
32+
33+
private static void propagateRuntimeException(Throwable t) {
34+
throw new RuntimeException("Could not invoke RoboGuice method!", t);
35+
}
36+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/RoboGuiceHandler.java‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,13 @@ public void process(Element element, EActivityHolder holder) {
6969

7070
holder.getGeneratedClass()._implements(classes().ROBO_CONTEXT);
7171

72+
JFieldVar scope = roboGuiceHolder.getScopeField();
7273
JFieldVar scopedObjects = roboGuiceHolder.getScopedObjectsField();
7374
JFieldVar eventManager = roboGuiceHolder.getEventManagerField();
7475
roboGuiceHolder.getContentViewListenerField();
7576
listenerFields(element, holder);
7677

77-
beforeCreateMethod(holder, scopedObjects, eventManager);
78+
beforeCreateMethod(holder, scope, scopedObjects, eventManager);
7879
onRestartMethod(roboGuiceHolder, eventManager);
7980
onStartMethod(roboGuiceHolder, eventManager);
8081
onResumeMethod(roboGuiceHolder, eventManager);
@@ -83,7 +84,7 @@ public void process(Element element, EActivityHolder holder) {
8384
onStopMethod(roboGuiceHolder, eventManager);
8485
onDestroyMethod(roboGuiceHolder, eventManager);
8586
onConfigurationChangedMethod(roboGuiceHolder, eventManager);
86-
onContentChangedMethod(roboGuiceHolder, eventManager);
87+
onContentChangedMethod(roboGuiceHolder, holder, scope, eventManager);
8788
onActivityResultMethod(roboGuiceHolder, eventManager);
8889
getScopedObjectMap(holder, scopedObjects);
8990
}
@@ -131,13 +132,14 @@ private List<String> extractListenerClasses(Element activityElement) {
131132
return new ArrayList<String>(0);
132133
}
133134

134-
private void beforeCreateMethod(EActivityHolder holder, JFieldVar scopedObjects, JFieldVar eventManager) {
135+
private void beforeCreateMethod(EActivityHolder holder, JFieldVar scope, JFieldVar scopedObjects, JFieldVar eventManager) {
135136
JBlock body = holder.getInitBody();
136137
JClass keyWildCard = classes().KEY.narrow(codeModel().wildcard());
137138
JClass scopedHashMap = classes().HASH_MAP.narrow(keyWildCard, classes().OBJECT);
138139
body.assign(scopedObjects, JExpr._new(scopedHashMap));
139140

140141
JVar injector = body.decl(classes().ROBO_INJECTOR, "injector_", classes().ROBO_GUICE.staticInvoke("getInjector").arg(_this()));
142+
body.assign(scope, invoke(injector, "getInstance").arg(classes().CONTEXT_SCOPE.dotclass()));
141143
body.assign(eventManager, invoke(injector, "getInstance").arg(classes().EVENT_MANAGER.dotclass()));
142144
body.add(injector.invoke("injectMembersWithoutViews").arg(_this()));
143145
fireEvent(eventManager, body, classes().ON_CREATE_EVENT, holder.getInitSavedInstanceParam());
@@ -203,9 +205,19 @@ private void onConfigurationChangedMethod(RoboGuiceHolder holder, JFieldVar even
203205
fireEvent(eventManager, onConfigurationChangedAfterSuperBlock, classes().ON_CONFIGURATION_CHANGED_EVENT, currentConfig, newConfig);
204206
}
205207

206-
private void onContentChangedMethod(RoboGuiceHolder holder, JFieldVar eventManager) {
208+
private void onContentChangedMethod(RoboGuiceHolder holder, EActivityHolder eActivityHolder, JFieldVar scope, JFieldVar eventManager) {
207209
JBlock onContentChangedAfterSuperBlock = holder.getOnContentChangedAfterSuperBlock();
208-
onContentChangedAfterSuperBlock.add(classes().ROBO_GUICE.staticInvoke("getInjector").arg(_this()).invoke("injectViewMembers").arg(_this()));
210+
211+
// no synchronized in CodeModel
212+
// https://java.net/jira/browse/CODEMODEL-6
213+
onContentChangedAfterSuperBlock.directStatement("synchronized(" + classes().CONTEXT_SCOPE.name() + ".class" + ")");
214+
JBlock synchronizedBlock = new JBlock(true, true);
215+
synchronizedBlock.invoke(scope, "enter").arg(_this());
216+
JTryBlock tryBlock = synchronizedBlock._try();
217+
tryBlock.body().staticInvoke(eActivityHolder.refClass(org.androidannotations.api.roboguice.RoboGuiceHelper.class), "callInjectViews").arg(_this());
218+
tryBlock._finally().invoke(scope, "exit").arg(_this());
219+
onContentChangedAfterSuperBlock.add(synchronizedBlock);
220+
209221
fireEvent(eventManager, onContentChangedAfterSuperBlock, classes().ON_CONTENT_CHANGED_EVENT);
210222
}
211223

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ public final class CanonicalNameConstants {
141141
/*
142142
* RoboGuice
143143
*/
144+
public static final String ROBO_APPLICATION = "roboguice.application.RoboApplication";
144145
public static final String ROBO_CONTEXT = "roboguice.util.RoboContext";
145146
public static final String ROBO_INJECTOR = "roboguice.inject.RoboInjector";
146147
public static final String KEY = "com.google.inject.Key";
@@ -152,6 +153,7 @@ public final class CanonicalNameConstants {
152153
public static final String ON_NEW_INTENT_EVENT = "roboguice.activity.event.OnNewIntentEvent";
153154
public static final String EVENT_MANAGER = "roboguice.event.EventManager";
154155
public static final String CONTEXT_SCOPE = "roboguice.inject.ContextScope";
156+
public static final String VIEW_MEMBERS_INJECTOR = "roboguice.inject.ViewListener.ViewMembersInjector";
155157
public static final String ROBO_GUICE = "roboguice.RoboGuice";
156158
public static final String INJECT = "com.google.inject.Inject";
157159
public static final String ON_STOP_EVENT = "roboguice.activity.event.OnStopEvent";

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/ValidatorHelper.java‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -689,14 +689,9 @@ public void hasRoboGuiceJars(Element element, IsValid valid) {
689689
annotationHelper.printAnnotationError(element, "Could not find the RoboGuice framework in the classpath, the following class is missing: " + CanonicalNameConstants.ROBO_CONTEXT);
690690
}
691691

692-
try {
693-
if (elementUtils.getTypeElement(CanonicalNameConstants.ROBO_INJECTOR) == null) {
694-
valid.invalidate();
695-
annotationHelper.printAnnotationError(element, "Could not find the Guice framework in the classpath, the following class is missing: " + CanonicalNameConstants.ROBO_INJECTOR);
696-
}
697-
} catch (RuntimeException e) {
692+
if (elementUtils.getTypeElement(CanonicalNameConstants.ROBO_APPLICATION) != null) {
698693
valid.invalidate();
699-
annotationHelper.printAnnotationError(element, "Could not find the Guice framework in the classpath, the following class is missing: " + CanonicalNameConstants.ROBO_INJECTOR);
694+
annotationHelper.printAnnotationError(element, "It seems you are using an old version of RoboGuice. Be sure to use version 2.0!");
700695
}
701696
}
702697

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EActivityHolder.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959

6060
public class EActivityHolder extends EComponentWithViewSupportHolder implements HasIntentBuilder, HasExtras, HasInstanceState, HasOptionsMenu, HasOnActivityResult, HasReceiverRegistration {
6161

62+
private static final String ON_CONTENT_CHANGED_JAVADOC = "We cannot simply copy the " + "code from RoboActivity, because that can cause classpath issues. " + "For further details see issue #1116.";
63+
6264
private ActivityIntentBuilder intentBuilder;
6365
private JMethod onCreate;
6466
private JMethod setIntent;
@@ -230,6 +232,7 @@ protected void setOnConfigurationChanged() {
230232
protected void setOnContentChanged() {
231233
JMethod method = generatedClass.method(JMod.PUBLIC, codeModel().VOID, "onContentChanged");
232234
method.annotate(Override.class);
235+
method.javadoc().append(ON_CONTENT_CHANGED_JAVADOC);
233236
JBlock body = method.body();
234237
body.invoke(_super(), method);
235238
getRoboGuiceHolder().onContentChangedAfterSuperBlock = body.block();
@@ -448,6 +451,11 @@ protected void setContentViewListenerField() {
448451
getRoboGuiceHolder().contentViewListenerField.annotate(classes().INJECT);
449452
}
450453

454+
protected void setScopeField() {
455+
getRoboGuiceHolder().scope = getGeneratedClass().field(JMod.PRIVATE, classes().CONTEXT_SCOPE, "scope_");
456+
457+
}
458+
451459
@Override
452460
public JMethod getInjectExtrasMethod() {
453461
if (injectExtrasMethod == null) {

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/RoboGuiceHolder.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class RoboGuiceHolder {
2424

2525
private EActivityHolder holder;
2626
protected JFieldVar scopedObjects;
27+
protected JFieldVar scope;
2728
protected JFieldVar eventManager;
2829
public JFieldVar contentViewListenerField;
2930
protected JBlock onRestartBeforeSuperBlock;
@@ -57,6 +58,13 @@ public JFieldVar getScopedObjectsField() {
5758
return scopedObjects;
5859
}
5960

61+
public JFieldVar getScopeField() {
62+
if (scope == null) {
63+
holder.setScopeField();
64+
}
65+
return scope;
66+
}
67+
6068
public JFieldVar getContentViewListenerField() {
6169
if (contentViewListenerField == null) {
6270
holder.setContentViewListenerField();

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ProcessHolder.java‎

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,27 @@
1515
*/
1616
package org.androidannotations.process;
1717

18-
import com.sun.codemodel.JClass;
19-
import com.sun.codemodel.JClassAlreadyExistsException;
20-
import com.sun.codemodel.JCodeModel;
21-
import com.sun.codemodel.JDefinedClass;
22-
import org.androidannotations.helper.CanonicalNameConstants;
23-
import org.androidannotations.holder.GeneratedClassHolder;
24-
25-
import javax.annotation.processing.ProcessingEnvironment;
26-
import javax.lang.model.element.Element;
2718
import java.io.FileInputStream;
2819
import java.io.InputStream;
2920
import java.io.Serializable;
3021
import java.sql.SQLException;
31-
import java.util.*;
22+
import java.util.Collections;
23+
import java.util.HashMap;
24+
import java.util.HashSet;
25+
import java.util.List;
26+
import java.util.Map;
27+
import java.util.Set;
28+
29+
import javax.annotation.processing.ProcessingEnvironment;
30+
import javax.lang.model.element.Element;
31+
32+
import org.androidannotations.helper.CanonicalNameConstants;
33+
import org.androidannotations.holder.GeneratedClassHolder;
34+
35+
import com.sun.codemodel.JClass;
36+
import com.sun.codemodel.JClassAlreadyExistsException;
37+
import com.sun.codemodel.JCodeModel;
38+
import com.sun.codemodel.JDefinedClass;
3239

3340
public class ProcessHolder {
3441

@@ -129,6 +136,8 @@ public class Classes {
129136
public final JClass ON_PAUSE_EVENT = refClass(CanonicalNameConstants.ON_PAUSE_EVENT);
130137
public final JClass ON_NEW_INTENT_EVENT = refClass(CanonicalNameConstants.ON_NEW_INTENT_EVENT);
131138
public final JClass EVENT_MANAGER = refClass(CanonicalNameConstants.EVENT_MANAGER);
139+
public final JClass CONTEXT_SCOPE = refClass(CanonicalNameConstants.CONTEXT_SCOPE);
140+
public final JClass VIEW_MEMBERS_INJECTOR = refClass(CanonicalNameConstants.VIEW_MEMBERS_INJECTOR);
132141
public final JClass ROBO_GUICE = refClass(CanonicalNameConstants.ROBO_GUICE);
133142
public final JClass INJECT = refClass(CanonicalNameConstants.INJECT);
134143
public final JClass ON_STOP_EVENT = refClass(CanonicalNameConstants.ON_STOP_EVENT);
@@ -212,7 +221,7 @@ public void put(Element element, GeneratedClassHolder generatedClassHolder) {
212221

213222
public GeneratedClassHolder getGeneratedClassHolder(Element element) {
214223
for (Element key : generatedClassHolders.keySet()) {
215-
if(key.asType().toString().equals(element.asType().toString())) {
224+
if (key.asType().toString().equals(element.asType().toString())) {
216225
return generatedClassHolders.get(key);
217226
}
218227
}

0 commit comments

Comments
 (0)