Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fixed classpath issues with RoboGuice
Some classes of RoboGuice are referencing the android.support package.
This is problematic, since it is not always in the classpath. In that
case, generated code cannot be compiled if support classes are
indirectly referenced, also validation can go wrong.
This commit fixes that issue by removing all indirect reference to the
support package.
  • Loading branch information
WonderCsabo committed Sep 22, 2014
commit 574fd51661e10253d9c66fe8650b86dc9770d75a
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Export-Package: org.androidannotations.annotations,
org.androidannotations.api,
org.androidannotations.api.builder,
org.androidannotations.api.rest,
org.androidannotations.api.roboguice,
org.androidannotations.api.sharedpreferences,
org.androidannotations.api.view
Bundle-Vendor: androidannotations
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.androidannotations.api.roboguice;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* Reflection utils to call methods which are accessible in RoboGuice package
* but not from outside.
*/
public class RoboGuiceHelper {

public static void callInjectViews(Object activity) {
try {
Class<?> viewMembersInjectorClass = Class.forName("roboguice.inject.ViewListener$ViewMembersInjector");
Method injectViewsMethod = viewMembersInjectorClass.getDeclaredMethod("injectViews", Object.class);
injectViewsMethod.setAccessible(true);
injectViewsMethod.invoke(null, activity);
} catch (ClassNotFoundException e) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you catch any RuntimeException in a single catch ?
It would enable us to remove the method propagateRuntimeException.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like catching any exceptions, and it is a very bad design, since that means just consuming all RuntimeExceptions, for example NPE, too. The current code is ugly, but would be much nicer if we would use Java 7, because we could just catchReflectiveOperationException.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Java 6 Supported or are we building for 7? Then you could go with Multi catch.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use Java 6, see the newest issue.

propagateRuntimeException(e);
} catch (NoSuchMethodException e) {
propagateRuntimeException(e);
} catch (SecurityException e) {
propagateRuntimeException(e);
} catch (IllegalAccessException e) {
propagateRuntimeException(e);
} catch (IllegalArgumentException e) {
propagateRuntimeException(e);
} catch (InvocationTargetException e) {
propagateRuntimeException(e);
}
}

private static void propagateRuntimeException(Throwable t) {
throw new RuntimeException("Could not invoke RoboGuice method!", t);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,13 @@ public void process(Element element, EActivityHolder holder) {

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

JFieldVar scope = roboGuiceHolder.getScopeField();
JFieldVar scopedObjects = roboGuiceHolder.getScopedObjectsField();
JFieldVar eventManager = roboGuiceHolder.getEventManagerField();
roboGuiceHolder.getContentViewListenerField();
listenerFields(element, holder);

beforeCreateMethod(holder, scopedObjects, eventManager);
beforeCreateMethod(holder, scope, scopedObjects, eventManager);
onRestartMethod(roboGuiceHolder, eventManager);
onStartMethod(roboGuiceHolder, eventManager);
onResumeMethod(roboGuiceHolder, eventManager);
Expand All @@ -83,7 +84,7 @@ public void process(Element element, EActivityHolder holder) {
onStopMethod(roboGuiceHolder, eventManager);
onDestroyMethod(roboGuiceHolder, eventManager);
onConfigurationChangedMethod(roboGuiceHolder, eventManager);
onContentChangedMethod(roboGuiceHolder, eventManager);
onContentChangedMethod(roboGuiceHolder, holder, scope, eventManager);
onActivityResultMethod(roboGuiceHolder, eventManager);
getScopedObjectMap(holder, scopedObjects);
}
Expand Down Expand Up @@ -131,13 +132,14 @@ private List<String> extractListenerClasses(Element activityElement) {
return new ArrayList<String>(0);
}

private void beforeCreateMethod(EActivityHolder holder, JFieldVar scopedObjects, JFieldVar eventManager) {
private void beforeCreateMethod(EActivityHolder holder, JFieldVar scope, JFieldVar scopedObjects, JFieldVar eventManager) {
JBlock body = holder.getInitBody();
JClass keyWildCard = classes().KEY.narrow(codeModel().wildcard());
JClass scopedHashMap = classes().HASH_MAP.narrow(keyWildCard, classes().OBJECT);
body.assign(scopedObjects, JExpr._new(scopedHashMap));

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

private void onContentChangedMethod(RoboGuiceHolder holder, JFieldVar eventManager) {
private void onContentChangedMethod(RoboGuiceHolder holder, EActivityHolder eActivityHolder, JFieldVar scope, JFieldVar eventManager) {
JBlock onContentChangedAfterSuperBlock = holder.getOnContentChangedAfterSuperBlock();
onContentChangedAfterSuperBlock.add(classes().ROBO_GUICE.staticInvoke("getInjector").arg(_this()).invoke("injectViewMembers").arg(_this()));

// no synchronized in CodeModel
// https://java.net/jira/browse/CODEMODEL-6
onContentChangedAfterSuperBlock.directStatement("synchronized(" + classes().CONTEXT_SCOPE.name() + ".class" + ")");
JBlock synchronizedBlock = new JBlock(true, true);
synchronizedBlock.invoke(scope, "enter").arg(_this());
JTryBlock tryBlock = synchronizedBlock._try();
tryBlock.body().staticInvoke(eActivityHolder.refClass(org.androidannotations.api.roboguice.RoboGuiceHelper.class), "callInjectViews").arg(_this());
tryBlock._finally().invoke(scope, "exit").arg(_this());
onContentChangedAfterSuperBlock.add(synchronizedBlock);

fireEvent(eventManager, onContentChangedAfterSuperBlock, classes().ON_CONTENT_CHANGED_EVENT);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ public final class CanonicalNameConstants {
/*
* RoboGuice
*/
public static final String ROBO_APPLICATION = "roboguice.application.RoboApplication";
public static final String ROBO_CONTEXT = "roboguice.util.RoboContext";
public static final String ROBO_INJECTOR = "roboguice.inject.RoboInjector";
public static final String KEY = "com.google.inject.Key";
Expand All @@ -152,6 +153,7 @@ public final class CanonicalNameConstants {
public static final String ON_NEW_INTENT_EVENT = "roboguice.activity.event.OnNewIntentEvent";
public static final String EVENT_MANAGER = "roboguice.event.EventManager";
public static final String CONTEXT_SCOPE = "roboguice.inject.ContextScope";
public static final String VIEW_MEMBERS_INJECTOR = "roboguice.inject.ViewListener.ViewMembersInjector";
public static final String ROBO_GUICE = "roboguice.RoboGuice";
public static final String INJECT = "com.google.inject.Inject";
public static final String ON_STOP_EVENT = "roboguice.activity.event.OnStopEvent";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,14 +678,9 @@ public void hasRoboGuiceJars(Element element, IsValid valid) {
annotationHelper.printAnnotationError(element, "Could not find the RoboGuice framework in the classpath, the following class is missing: " + CanonicalNameConstants.ROBO_CONTEXT);
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@

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

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.";

private ActivityIntentBuilder intentBuilder;
private JMethod onCreate;
private JMethod setIntent;
Expand Down Expand Up @@ -230,6 +232,7 @@ protected void setOnConfigurationChanged() {
protected void setOnContentChanged() {
JMethod method = generatedClass.method(JMod.PUBLIC, codeModel().VOID, "onContentChanged");
method.annotate(Override.class);
method.javadoc().append(ON_CONTENT_CHANGED_JAVADOC);
JBlock body = method.body();
body.invoke(_super(), method);
getRoboGuiceHolder().onContentChangedAfterSuperBlock = body.block();
Expand Down Expand Up @@ -368,15 +371,15 @@ private void handleBackPressed() {

onKeyDownBody._if( //
sdkInt.lt(JExpr.lit(5)) //
.cand(keyCodeParam.eq(keyEventClass.staticRef("KEYCODE_BACK"))) //
.cand(eventParam.invoke("getRepeatCount").eq(JExpr.lit(0)))) //
.cand(keyCodeParam.eq(keyEventClass.staticRef("KEYCODE_BACK"))) //
.cand(eventParam.invoke("getRepeatCount").eq(JExpr.lit(0)))) //
._then() //
.invoke("onBackPressed");

onKeyDownBody._return( //
JExpr._super().invoke(onKeyDownMethod) //
.arg(keyCodeParam) //
.arg(eventParam));
.arg(keyCodeParam) //
.arg(eventParam));

}
}
Expand Down Expand Up @@ -406,7 +409,7 @@ private boolean isCustomOnBackPressedMethod(ExecutableElement method) {
&& method.getModifiers().contains(Modifier.PUBLIC) //
&& method.getReturnType().getKind().equals(TypeKind.VOID) //
&& method.getParameters().size() == 0 //
;
;
}

@Override
Expand Down Expand Up @@ -448,6 +451,11 @@ protected void setContentViewListenerField() {
getRoboGuiceHolder().contentViewListenerField.annotate(classes().INJECT);
}

protected void setScopeField() {
getRoboGuiceHolder().scope = getGeneratedClass().field(JMod.PRIVATE, classes().CONTEXT_SCOPE, "scope_");

}

@Override
public JMethod getInjectExtrasMethod() {
if (injectExtrasMethod == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class RoboGuiceHolder {

private EActivityHolder holder;
protected JFieldVar scopedObjects;
protected JFieldVar scope;
protected JFieldVar eventManager;
public JFieldVar contentViewListenerField;
protected JBlock onRestartBeforeSuperBlock;
Expand Down Expand Up @@ -57,6 +58,13 @@ public JFieldVar getScopedObjectsField() {
return scopedObjects;
}

public JFieldVar getScopeField() {
if (scope == null) {
holder.setScopeField();
}
return scope;
}

public JFieldVar getContentViewListenerField() {
if (contentViewListenerField == null) {
holder.setContentViewListenerField();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,27 @@
*/
package org.androidannotations.process;

import com.sun.codemodel.JClass;
import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import org.androidannotations.helper.CanonicalNameConstants;
import org.androidannotations.holder.GeneratedClassHolder;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;

import org.androidannotations.helper.CanonicalNameConstants;
import org.androidannotations.holder.GeneratedClassHolder;

import com.sun.codemodel.JClass;
import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;

public class ProcessHolder {

Expand Down Expand Up @@ -129,6 +136,8 @@ public class Classes {
public final JClass ON_PAUSE_EVENT = refClass(CanonicalNameConstants.ON_PAUSE_EVENT);
public final JClass ON_NEW_INTENT_EVENT = refClass(CanonicalNameConstants.ON_NEW_INTENT_EVENT);
public final JClass EVENT_MANAGER = refClass(CanonicalNameConstants.EVENT_MANAGER);
public final JClass CONTEXT_SCOPE = refClass(CanonicalNameConstants.CONTEXT_SCOPE);
public final JClass VIEW_MEMBERS_INJECTOR = refClass(CanonicalNameConstants.VIEW_MEMBERS_INJECTOR);
public final JClass ROBO_GUICE = refClass(CanonicalNameConstants.ROBO_GUICE);
public final JClass INJECT = refClass(CanonicalNameConstants.INJECT);
public final JClass ON_STOP_EVENT = refClass(CanonicalNameConstants.ON_STOP_EVENT);
Expand Down Expand Up @@ -212,7 +221,7 @@ public void put(Element element, GeneratedClassHolder generatedClassHolder) {

public GeneratedClassHolder getGeneratedClassHolder(Element element) {
for (Element key : generatedClassHolders.keySet()) {
if(key.asType().toString().equals(element.asType().toString())) {
if (key.asType().toString().equals(element.asType().toString())) {
return generatedClassHolders.get(key);
}
}
Expand Down