private OrderedMap<String, Field> getStaticFields(Class type) { if (staticFields.containsKey(type)) return staticFields.get(type); Field[] fields = ClassReflection.getDeclaredFields(type); OrderedMap<String, Field> nameToField = new OrderedMap(fields.length); for (Field field : fields) { if (!field.isStatic()) continue; if (!field.isAccessible()) { try { field.setAccessible(true); } catch (AccessControlException ex) { continue; } } nameToField.put(field.getName(), field); } staticFields.put(type, nameToField); return nameToField; }
private Metadata findMetadata (Class<?> clazz) { Metadata metadata = metadataCache.get(clazz); if (metadata == null) { Annotation tca = ClassReflection.getAnnotation(clazz, TaskConstraint.class); if (tca != null) { TaskConstraint taskConstraint = tca.getAnnotation(TaskConstraint.class); ObjectMap<String, AttrInfo> taskAttributes = new ObjectMap<String, AttrInfo>(); Field[] fields = ClassReflection.getFields(clazz); for (Field f : fields) { Annotation a = f.getDeclaredAnnotation(TaskAttribute.class); if (a != null) { AttrInfo ai = new AttrInfo(f.getName(), a.getAnnotation(TaskAttribute.class)); taskAttributes.put(ai.name, ai); } } metadata = new Metadata(taskConstraint.minChildren(), taskConstraint.maxChildren(), taskAttributes); metadataCache.put(clazz, metadata); } } return metadata; }
/** Does the actual processing of found fields. * * @param component owner of the fields. * @param fields present in one of superclasses of the component. * @param context used to resolve dependencies. * @param contextDestroyer used to register destruction callbacks. */ @SuppressWarnings({ "rawtypes", "unchecked" }) // Using correct types, but wildcards fail to see that. private void processFields(final Object component, final Field[] fields, final Context context, final ContextDestroyer contextDestroyer) { for (final Field field : fields) { final com.badlogic.gdx.utils.reflect.Annotation[] annotations = getAnnotations(field); if (annotations == null || annotations.length == 0) { continue; } for (final com.badlogic.gdx.utils.reflect.Annotation annotation : annotations) { if (fieldProcessors.containsKey(annotation.getAnnotationType())) { for (final AnnotationProcessor processor : fieldProcessors.get(annotation.getAnnotationType())) { processor.processField(field, annotation.getAnnotation(annotation.getAnnotationType()), component, context, this, contextDestroyer); } } } } }
@Override public void processField(final Field field, final LmlMacro annotation, final Object component, final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) { try { final Object macroData = Reflection.getFieldValue(field, component); final LmlParser parser = interfaceService.get().getParser(); final FileType fileType = annotation.fileType(); if (macroData instanceof String) { parser.parseTemplate(Gdx.files.getFileHandle((String) macroData, fileType)); } else if (macroData instanceof String[]) { for (final String macroPath : (String[]) macroData) { parser.parseTemplate(Gdx.files.getFileHandle(macroPath, fileType)); } } else { throw new GdxRuntimeException("Invalid type of LML macro definition in component: " + component + ". String or String[] expected, received: " + macroData + "."); } } catch (final ReflectionException exception) { throw new GdxRuntimeException( "Unable to extract macro paths from field: " + field + " of component: " + component + ".", exception); } }
private void handleLazyAssetInjection(final Object component, final Field field, final Asset assetData) { if (Annotations.isNotVoid(assetData.lazyCollection())) { handleLazyAssetCollectionInjection(component, field, assetData); return; } else if (assetData.value().length != 1) { throw new GdxRuntimeException( "Lazy wrapper can contain only one asset if lazy collection type is not provided. Found multiple assets in field: " + field + " of component: " + component); } final String assetPath = assetData.value()[0]; if (!assetData.loadOnDemand()) { load(assetPath, assetData.type()); } try { Reflection.setFieldValue(field, component, Lazy.providedBy(new AssetProvider(this, assetPath, assetData.type(), assetData.loadOnDemand()))); } catch (final ReflectionException exception) { throw new GdxRuntimeException("Unable to inject lazy asset.", exception); } }
@Override public void processField(final Field field, final LmlParserSyntax annotation, final Object component, final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) { try { final Object syntax = Reflection.getFieldValue(field, component); if (syntax instanceof LmlSyntax) { interfaceService.getParser().setSyntax((LmlSyntax) syntax); } else { throw new ContextInitiationException( "LmlParserSyntax-annotated fields need to contain an instance of LmlSyntax. Found: " + syntax + " in field: " + field + " of component: " + component); } } catch (final ReflectionException exception) { throw new ContextInitiationException( "Unable to extract LML syntax from field: " + field + " of component: " + component, exception); } }
@Override public void processField(final Field field, final AvailableLocales annotation, final Object component, final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) { try { final Object locales = Reflection.getFieldValue(field, component); if (locales instanceof String[]) { final String[] availableLocales = (String[]) locales; final LmlParser parser = interfaceService.getParser(); parser.getData().addArgument(annotation.viewArgumentName(), availableLocales); for (final String locale : availableLocales) { parser.getData().addActorConsumer(annotation.localeChangeMethodPrefix() + locale, new LocaleChangingAction(localeService, LocaleService.toLocale(locale))); } return; } throw new GdxRuntimeException("Invalid field annotated with @AvailableLocales in component " + component + ". Expected String[], received: " + locales + "."); } catch (final ReflectionException exception) { throw new GdxRuntimeException( "Unable to read available locales from field: " + field + " of component: " + component + ".", exception); } }
@Override public void processField(final Field field, final Asset annotation, final Object component, final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) { validateAssetData(component, field, annotation); if (field.getType().equals(Lazy.class)) { handleLazyAssetInjection(component, field, annotation); } else if (field.getType().equals(Array.class)) { handleArrayInjection(component, field, annotation); } else if (field.getType().equals(ObjectSet.class)) { handleSetInjection(component, field, annotation); } else if (field.getType().equals(ObjectMap.class)) { handleMapInjection(component, field, annotation); } else { handleRegularAssetInjection(component, field, annotation); } }
protected <View> void processLmlActorAnnotation(final View view, final Field field) { if (Reflection.isAnnotationPresent(field, LmlActor.class)) { final LmlActor actorData = Reflection.getAnnotation(field, LmlActor.class); String[] actorIds = actorData.value(); if (actorIds.length == 0) { actorIds = new String[] { field.getName() }; } if (Reflection.isExtending(field.getType(), Array.class)) { injectArrayOfActors(view, field, actorIds); } else if (Reflection.isExtending(field.getType(), ObjectSet.class)) { injectSetOfActors(view, field, actorIds); } else if (Reflection.isExtending(field.getType(), ObjectMap.class)) { injectMapOfActors(view, field, actorIds); } else { injectSingleActor(view, field, actorIds); } } }
/** @param actionContainer action container that might contain the referenced method. * @param actionId name of the requested action. * @param forActor will be used as potential action argument. * @return actor consumer constructed with container's method (or field) or null if action not found. */ protected ActorConsumer<?, ?> extractActionFromContainer(final ActionContainerWrapper actionContainer, final String actionId, final Object forActor) { Method method = actionContainer.getNamedMethod(actionId); if (method == null && Lml.EXTRACT_UNANNOTATED_METHODS) { method = findUnnamedMethod(actionContainer, actionId, forActor); } if (method != null) { return new MethodActorConsumer(method, actionContainer.getActionContainer()); } else if (Lml.EXTRACT_FIELDS_AS_METHODS) { Field field = actionContainer.getNamedField(actionId); if (field == null && Lml.EXTRACT_UNANNOTATED_METHODS) { field = actionContainer.getField(actionId); } if (field != null) { return new FieldActorConsumer(field, actionContainer.getActionContainer()); } } return null; }
private void mapClassFields(final Class<?> containerClass) { if (!Lml.EXTRACT_FIELDS_AS_METHODS) { return; } for (final Field field : ClassReflection.getDeclaredFields(containerClass)) { final LmlAction actionData = Reflection.getAnnotation(field, LmlAction.class); if (actionData != null) { final String[] ids = actionData.value(); if (ids.length > 0) { for (final String actionId : ids) { annotatedFields.put(actionId, field); } } else { annotatedFields.put(field.getName(), field); } } } }
@Override public void processField(final Field field, final LmlMacro annotation, final Object component, final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) { try { final Object macroData = Reflection.getFieldValue(field, component); final FileType fileType = annotation.fileType(); if (macroData instanceof String) { macros.add(Gdx.files.getFileHandle((String) macroData, fileType)); } else if (macroData instanceof String[]) { for (final String macroPath : (String[]) macroData) { macros.add(Gdx.files.getFileHandle(macroPath, fileType)); } } else { throw new GdxRuntimeException("Invalid type of LML macro definition in component: " + component + ". String or String[] expected, received: " + macroData + "."); } } catch (final ReflectionException exception) { throw new GdxRuntimeException( "Unable to extract macro paths from field: " + field + " of component: " + component + ".", exception); } }
/** @param field reflected field data. * @param component owner of the field. * @return true if the field is empty, accepted by the modifier filter, does not match modifier signature, not * primitive and - if strings are ignored - not a string. * @throws Exception due to reflection issues. */ protected boolean isInjectable(final Field field, final Object component) throws Exception { try { if (field.isSynthetic() || field.getType().isPrimitive() || isIgnoreStrings() && field.getType() == String.class) { return false; } } catch (final Exception exception) { Exceptions.ignore(exception); // GWT compatibility. Gdx.app.debug("UEDI", "Unable to access field of component: " + component, exception); return false; } final int modifier = Modifier.getModifiers(field); if ((modifier & getFieldsIgnoreFilter()) != 0 || modifier == getFieldsIgnoreSignature()) { return false; } field.setAccessible(true); return field.get(component) == null; }
private void handleRegularAssetInjection(final Object component, final Field field, final Asset assetData) { if (assetData.value().length != 1) { throw new GdxRuntimeException( "Regular fields can store only 1 asset. If the field is a collection, its type is not currently supported: only LibGDX Array, ObjectSet and ObjectMap are permitted. Regular arrays will not be supported. Found multiple assets in field: " + field + " of component: " + component); } final String assetPath = assetData.value()[0]; if (assetData.loadOnDemand()) { // Loaded immediately. @SuppressWarnings("unchecked") final Object asset = finishLoading(assetPath, field.getType()); try { Reflection.setFieldValue(field, component, asset); } catch (final ReflectionException exception) { throw new GdxRuntimeException("Unable to inject asset loaded on demand.", exception); } } else { load(assetPath, field.getType()); // Scheduled to be loaded, delayed injection. assetInjections.add(new StandardAssetInjection(field, assetPath, component)); } }
private static int getPixmapColor (Pixmap pixmap){ int color = 0; try { Field colorField = ClassReflection.getDeclaredField(Pixmap.class, "color"); colorField.setAccessible(true); color = (Integer)colorField.get(pixmap); } catch (ReflectionException e) { Log.error("Color field of pixmap could not be read. Using transparent black.", e); } return color; }
public <T> T getStaticFieldValue(Class<T> type, String fieldName) { OrderedMap<String, Field> fields = getStaticFields(type); Field field = fields.get(fieldName, null); Throwable throwable = null; if (field != null) { try { return (T) field.get(null); } catch (ReflectionException e) { throwable = e; } } error(String.format("Could not retrieve static field value %s from class %s.", fieldName, type.getName()), throwable); return null; }
@Override public synchronized boolean update () { boolean done = super.update(); if (done) { // assign references to Asset fields of queuedContainers for (Object assetContainer : queuedContainers) { ObjectMap<Field, AssetDescriptor<?>> fieldsToAssets = containersFieldsToAssets.get(assetContainer); for (ObjectMap.Entry<Field, AssetDescriptor<?>> fieldEntry : fieldsToAssets) { Field field = fieldEntry.key; makeAccessible(field); try { field.set(assetContainer, get(fieldEntry.value)); } catch (ReflectionException e) { throw new GdxRuntimeException("Failed to assign loaded asset " + field.getName(), e); } } ObjectMap<Object[], AssetDescriptor<?>[]> fieldsToAssetArrays = containersFieldsToAssetArrays.get(assetContainer); for (ObjectMap.Entry<Object[], AssetDescriptor<?>[]> arrayEntry : fieldsToAssetArrays) { Object[] destinationArray = arrayEntry.key; AssetDescriptor<?>[] descriptors = arrayEntry.value; for (int i = 0; i < descriptors.length; i++) { destinationArray[i] = get(descriptors[i]); } } if (assetContainer instanceof AssetContainer) ((AssetContainer) assetContainer).onAssetsLoaded(); } loadedContainers.addAll(queuedContainers); queuedContainers.clear(); } return done; }
private void makeAccessible (Field field) { if (!field.isAccessible()) { try { field.setAccessible(true); } catch (AccessControlException ex) { throw new GdxRuntimeException(String.format("Field %s cannot be made accessible", field.getName())); } } }
/** * Check if exist a MapWayPointItemStyle for all CacheTypes and WayPointTypes */ @Override public void runValidation() { checkCacheTypes(); //Check changes of MapWayPointItemStyle.class Field[] fields = ClassReflection.getFields(MapWayPointItemStyle.class); String classChanged = ""; if (fields.length > 3) { classChanged = "MapWayPointItemStyle is changed, maybe you must add new Validation " + "on de.longri.cachebox3.develop.tools.skin_editor.validation.Validate_MapWayPointItemStyle.java"; } //set result if (missingBitmaps.length > 0 || missingSyles.length > 0) { errorMsg = "Missing Styles:\n\n" + missingSyles.toString() + "\n\nMissing Bitmaps:\n\n" + missingBitmaps.toString(); } if (!classChanged.isEmpty()) { warnMsg = classChanged + "\n\n Wrong Sizes:\n\n" + wrongBitmapsSize.toString(); } else if (wrongBitmapsSize.length > 0) { warnMsg = "Wrong Sizes:\n\n" + wrongBitmapsSize.toString(); } }
/** * Is font is already in use somewhere else? */ public boolean isFontInUse(BitmapFont font) { try { // Check if it is already in use somewhere! for (String widget : SkinEditorGame.widgets) { String widgetStyle = "com.badlogic.gdx.scenes.scene2d.ui." + widget + "$" + widget + "Style"; Class<?> style = Class.forName(widgetStyle); ObjectMap<String, ?> styles = game.skinProject.getAll(style); Iterator<String> it = styles.keys().iterator(); while (it.hasNext()) { Object item = styles.get((String) it.next()); Field[] fields = ClassReflection.getFields(item.getClass()); for (Field field : fields) { if (field.getType() == BitmapFont.class) { BitmapFont f = (BitmapFont) field.get(item); if (font.equals(f)) { return true; } } } } } } catch (Exception e) { e.printStackTrace(); } return false; }
public DrawablePickerDialog(final SkinEditorGame game, final Field field, int arrayIndex, boolean disableNinePatch, Stage stage) { super("Drawable Picker", game.skin); this.game = game; this.field = field; this.disableNinePatch = disableNinePatch; this.stage = stage; this.callSelectedSvg = false; this.arrayIndex = arrayIndex; initializeSelf(); }
@Override protected <E> boolean attribute (DefaultBehaviorTreeReader<E> reader, String name, Object value) { StackedTask<E> stackedTask = reader.getCurrentTask(); AttrInfo ai = stackedTask.metadata.attributes.get(name); if (ai == null) return false; boolean isNew = reader.encounteredAttributes.add(name); if (!isNew) throw reader.stackedTaskException(stackedTask, "attribute '" + name + "' specified more than once"); Field attributeField = reader.getField(stackedTask.task.getClass(), ai.fieldName); reader.setField(attributeField, stackedTask.task, value); return true; }
private Field getField (Class<?> clazz, String name) { try { return ClassReflection.getField(clazz, name); } catch (ReflectionException e) { throw new GdxRuntimeException(e); } }
private void setField (Field field, Task<E> task, Object value) { field.setAccessible(true); Object valueObject = castValue(field, value); try { field.set(task, valueObject); } catch (ReflectionException e) { throw new GdxRuntimeException(e); } }
public int getAxisAmount () { try { switch (Gdx.app.getType()) { case Android: Field androidAxes = ClassReflection .getDeclaredField(ClassReflection.forName("com.badlogic.gdx.controllers.android.AndroidController"), "axes"); androidAxes.setAccessible(true); return ((float[])androidAxes.get(gamePad)).length; case Desktop: Field desktopAxes = ClassReflection .getDeclaredField(ClassReflection.forName("com.badlogic.gdx.controllers.lwjgl3.Lwjgl3Controller"), "axisState"); desktopAxes.setAccessible(true); return ((float[])desktopAxes.get(gamePad)).length; case HeadlessDesktop: return 0; case WebGL: Field gwtAxes = ClassReflection .getDeclaredField(ClassReflection.forName("com.badlogic.gdx.controllers.gwt.GwtController"), "axes"); gwtAxes.setAccessible(true); return ((float[])gwtAxes.get(gamePad)).length; case iOS: return 0; default: break; } } catch (Exception ex) { ex.printStackTrace(); } return 0; }
public int getButtonAmount () { try { switch (Gdx.app.getType()) { case Android: Field androidButtons = ClassReflection .getDeclaredField(ClassReflection.forName("com.badlogic.gdx.controllers.android.AndroidController"), "buttons"); androidButtons.setAccessible(true); return ((IntIntMap)androidButtons.get(gamePad)).size; case Desktop: Field desktopButtons = ClassReflection.getDeclaredField( ClassReflection.forName("com.badlogic.gdx.controllers.lwjgl3.Lwjgl3Controller"), "buttonState"); desktopButtons.setAccessible(true); return ((boolean[])desktopButtons.get(gamePad)).length; case HeadlessDesktop: return 0; case WebGL: Field gwtButtons = ClassReflection .getDeclaredField(ClassReflection.forName("com.badlogic.gdx.controllers.gwt.GwtController"), "buttons"); gwtButtons.setAccessible(true); return ((IntFloatMap)gwtButtons.get(gamePad)).size; case iOS: return 0; default: break; } } catch (Exception ex) { ex.printStackTrace(); } return 0; }
/** Injects actors from group into target's fields annotated with {@link InjectActor} using reflection. */ public static void injectActorFields(Object target, Group group) { Class<?> handledClass = target.getClass(); while (handledClass != null && !handledClass.equals(Object.class)) { for (final Field field : ClassReflection.getDeclaredFields(handledClass)) { if (field != null && field.isAnnotationPresent(InjectActor.class)) { try { InjectActor annotation = field.getDeclaredAnnotation(InjectActor.class).getAnnotation(InjectActor.class); String actorName = annotation.value(); if (actorName.length() == 0) { actorName = field.getName(); } Actor actor = group.findActor(actorName); if (actor == null && actorName.equals(group.getName())) { actor = group; } if (actor == null) { Gdx.app.error(TAG_INJECT_FIELDS, "Can't find actor with name: " + actorName + " in group: " + group + " to inject into: " + target); } else { field.setAccessible(true); field.set(target, actor); } } catch (final ReflectionException exception) { Gdx.app.error(TAG_INJECT_FIELDS, "Unable to set value into field: " + field + " of object: " + target, exception); } } } handledClass = handledClass.getSuperclass(); } }
@SuppressWarnings("static-access") @Before public void setup() { Gdx.app = Mockito.mock(HeadlessApplication.class); when(Gdx.app.getPreferences(anyString())).thenReturn(new PreferencesStub()); config = new TwitterConfig(); PowerMockito.mockStatic(ClassReflection.class); classReflectionMock = Mockito.mock(ClassReflection.class); PowerMockito.mockStatic(Field.class); fieldMock = Mockito.mock(Field.class); PowerMockito.mockStatic(Constructor.class); constructorMock = Mockito.mock(Constructor.class); PowerMockito.mockStatic(Method.class); methodMock = Mockito.mock(Method.class); activityStub = new ActivityStub(); twitterAPIStub = new TwitterAPIStub(config); gdxStub = new GdxStub(); supportFragmentStub = new SupportFragmentStub(); fragmentStub = new FragmentStub(); gdxLifecycleListenerStub = new GdxLifecycleListenerStub(); try { Mockito.when(classReflectionMock.forName("com.badlogic.gdx.Gdx")).thenReturn(gdxStub.getClass()); Mockito.when(classReflectionMock.getField(gdxStub.getClass(), "app")).thenReturn(fieldMock); Mockito.when(fieldMock.get(null)).thenReturn(Gdx.app); } catch (ReflectionException e) { } }
@Override public void processField(final Field field, final I18nLocale annotation, final Object component, final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) { try { final Object locale = Reflection.getFieldValue(field, component); if (locale instanceof Locale) { currentLocale.set((Locale) locale); } else if (locale instanceof String) { extractLocaleFromAnnotatedString(annotation, (String) locale); } } catch (final ReflectionException exception) { throw new GdxRuntimeException("Unable to extract application's locale.", exception); } }
/** Utility method that allows to extract actual annotation from field, bypassing LibGDX annotation wrapper. Returns * null if annotation is not present. * * @param field might be annotated. * @param annotationType class of the annotation. * @return an instance of the annotation if the field is annotated or null if not. */ public static <Type extends Annotation> Type getAnnotation(final Field field, final Class<Type> annotationType) { if (isAnnotationPresent(field, annotationType)) { return field.getDeclaredAnnotation(annotationType).getAnnotation(annotationType); } return null; }
/** @param field will be set accessible and extracted. * @param fieldOwner instance of class that contains the field. * @param fieldType class of the field. Will be used to cast the field object. * @return current field value. * @throws ReflectionException if unable to extract. */ @SuppressWarnings("unchecked") public static <FieldType> FieldType getFieldValue(final Field field, final Object fieldOwner, final Class<FieldType> fieldType) throws ReflectionException { field.setAccessible(true); return (FieldType) field.get(fieldOwner); }
/** Scans class tree of component to process all its fields. * * @param component all fields of its class tree will be processed. * @param context used to resolve dependencies. * @param contextDestroyer used to register destruction callbacks. */ private void processFields(final Object component, final Context context, final ContextDestroyer contextDestroyer) { Class<?> componentClass = component.getClass(); while (componentClass != null && !componentClass.equals(Object.class)) { final Field[] fields = ClassReflection.getDeclaredFields(componentClass); if (fields != null && fields.length > 0) { processFields(component, fields, context, contextDestroyer); } componentClass = componentClass.getSuperclass(); } }
/** @param field will return an array of its annotations. * @return array of annotations or null. GWT utility. */ private static com.badlogic.gdx.utils.reflect.Annotation[] getAnnotations(final Field field) { try { return field.getDeclaredAnnotations(); } catch (final Exception exception) { Exceptions.ignore(exception); return null; } }
@Override public void processField(final Field field, final Inject annotation, final Object component, final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) { if (Annotations.isNotVoid(annotation.lazy())) { processLazyInjection(field, annotation, component, context); } else { processRegularInjection(field, annotation, component, context); } }
/** @param field will have its value injected. * @param annotation used to determine dependency type. * @param component owner of the field. * @param context used to resolve dependencies. */ protected void processRegularInjection(final Field field, final Inject annotation, final Object component, final Context context) { final Class<?> dependencyClass = Annotations.isNotVoid(annotation.value()) ? annotation.value() : field.getType(); setFieldValue(field, component, context.provide(dependencyClass)); }