AbstractResourcesInjector.java
001 /*
002  * Copyright 2010-2013 the original author or authors.
003  *
004  * Licensed under the Apache License, Version 2.0 (the "License");
005  * you may not use this file except in compliance with the License.
006  * You may obtain a copy of the License at
007  *
008  *      http://www.apache.org/licenses/LICENSE-2.0
009  *
010  * Unless required by applicable law or agreed to in writing, software
011  * distributed under the License is distributed on an "AS IS" BASIS,
012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013  * See the License for the specific language governing permissions and
014  * limitations under the License.
015  */
016 
017 package org.codehaus.griffon.runtime.core.resources;
018 
019 import griffon.core.GriffonApplication;
020 import griffon.core.resources.InjectedResource;
021 import griffon.core.resources.ResourcesInjector;
022 import org.slf4j.Logger;
023 import org.slf4j.LoggerFactory;
024 
025 import java.beans.PropertyEditor;
026 import java.beans.PropertyEditorManager;
027 import java.lang.reflect.Field;
028 import java.util.Arrays;
029 
030 import static griffon.util.GriffonExceptionHandler.sanitize;
031 import static griffon.util.GriffonNameUtils.isBlank;
032 
033 /**
034  @author Andres Almiray
035  @since 1.2.0
036  */
037 public abstract class AbstractResourcesInjector implements ResourcesInjector {
038     private static final Logger LOG = LoggerFactory.getLogger(AbstractResourcesInjector.class);
039     private final GriffonApplication app;
040 
041     public AbstractResourcesInjector(GriffonApplication app) {
042         this.app = app;
043     }
044 
045     public GriffonApplication getApp() {
046         return app;
047     }
048 
049     @Override
050     public void injectResources(Object instance) {
051         if (null == instancereturn;
052         Class klass = instance.getClass();
053         do {
054             doResourceInjection(klass, instance);
055             klass = klass.getSuperclass();
056         while (null != klass);
057     }
058 
059     protected boolean doResourceInjection(Class klass, Object instance) {
060         boolean injected = false;
061         for (Field field : klass.getDeclaredFields()) {
062             if (field.isSynthetic()) continue;
063             final InjectedResource annotation = field.getAnnotation(InjectedResource.class);
064             if (null == annotationcontinue;
065 
066             String fqFieldName = field.getDeclaringClass().getName().replace('$''.'"." + field.getName();
067             String key = annotation.key();
068             String[] args = annotation.args();
069             String defaultValue = annotation.defaultValue();
070             if (isBlank(key)) key = fqFieldName;
071 
072             if (LOG.isDebugEnabled()) {
073                 LOG.debug("Field " + fqFieldName +
074                     " of instance " + instance +
075                     " [key='" + key +
076                     "', args='" + Arrays.toString(args+
077                     "', defaultValue='" + defaultValue +
078                     "'] is marked for resource injection.");
079             }
080 
081             Object value = null;
082             if (isBlank(defaultValue)) {
083                 value = resolveResource(key, args);
084             else {
085                 value = resolveResource(key, args, defaultValue);
086             }
087 
088             if (null != value) {
089                 if (!field.getType().isAssignableFrom(value.getClass())) {
090                     value = convertValue(field.getType(), value);
091                 }
092                 setFieldValue(instance, field, value, fqFieldName);
093             }
094             injected = true;
095         }
096         return injected;
097     }
098 
099     protected abstract Object resolveResource(String key, String[] args);
100 
101     protected abstract Object resolveResource(String key, String[] args, String defaultValue);
102 
103     protected Object convertValue(Class<?> type, Object value) {
104         final PropertyEditor propertyEditor = PropertyEditorManager.findEditor(type);
105         if (null == propertyEditorreturn value;
106         if (value instanceof CharSequence) {
107             propertyEditor.setAsText(String.valueOf(value));
108         else {
109             propertyEditor.setValue(value);
110         }
111         return propertyEditor.getValue();
112     }
113 
114     protected void setFieldValue(Object instance, Field field, Object value, String fqFieldName) {
115         try {
116             field.setAccessible(true);
117             field.set(instance, value);
118         catch (IllegalAccessException e) {
119             if (LOG.isWarnEnabled()) {
120                 LOG.warn("Cannot set value on field " + fqFieldName + " of instance " + instance, sanitize(e));
121             }
122         }
123     }
124 }