1
2 package com.simpligility.maven.plugins.android.config;
3
4 import org.apache.maven.execution.MavenSession;
5 import org.apache.maven.plugin.MojoExecution;
6 import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
7
8 import java.lang.annotation.Annotation;
9 import java.lang.reflect.Field;
10 import java.lang.reflect.Method;
11 import java.util.ArrayList;
12 import java.util.Collection;
13
14
15
16
17
18
19
20
21
22
23
24 public class ConfigHandler
25 {
26
27 private Object mojo;
28 private Object configPojoInstance;
29 private String configPojoName;
30 private String configPojoPrefix;
31 private PluginParameterExpressionEvaluator evaluator;
32
33 public ConfigHandler( Object mojo, MavenSession session, MojoExecution execution )
34 {
35 this.mojo = mojo;
36
37 if ( session == null )
38 {
39 throw new IllegalArgumentException( "The argument session is required" );
40 }
41 if ( execution == null )
42 {
43 throw new IllegalArgumentException( "The argument execution is required" );
44 }
45
46 this.evaluator = new PluginParameterExpressionEvaluator( session, execution );
47
48 initConfigPojo();
49 }
50
51 private Collection< Field > findPropertiesByAnnotation( Class< ? extends Annotation > annotation )
52 {
53 Collection< Field > result = new ArrayList< Field >();
54 for ( Class< ? extends Object > cls = mojo.getClass(); cls != Object.class; cls = cls.getSuperclass() )
55 {
56 for ( Field field : cls.getDeclaredFields() )
57 {
58 if ( field.isAnnotationPresent( annotation ) )
59 {
60 field.setAccessible( true );
61 result.add( field );
62 }
63 }
64 }
65
66 return result;
67 }
68
69 public void parseConfiguration()
70 {
71 Collection< Field > parsedFields = findPropertiesByAnnotation( PullParameter.class );
72
73 for ( Field field : parsedFields )
74 {
75 Object value = null;
76 String fieldBaseName = getFieldNameWithoutParsedPrefix( field );
77
78 if ( configPojoInstance != null )
79 {
80 value = getValueFromPojo( fieldBaseName );
81 }
82
83
84 Object propertyValue = getValueFromMojo( fieldBaseName );
85 if ( propertyValue == null || propertyValue instanceof Object[]
86 && ( (Object[]) propertyValue ).length == 0 )
87 {
88
89 }
90 else
91 {
92 value = propertyValue;
93 }
94
95 if ( value == null )
96 {
97 value = getValueFromAnnotation( field );
98 }
99
100 try
101 {
102 field.set( mojo, value );
103 }
104 catch ( Exception e )
105 {
106 e.printStackTrace();
107 }
108 }
109 }
110
111 private Object getValueFromAnnotation( Field field )
112 {
113 PullParameter annotation = field.getAnnotation( PullParameter.class );
114 String[] defaultValue = annotation.defaultValue();
115 boolean required = annotation.required();
116 String currentParameterName = "android." + configPojoName + "." + getFieldNameWithoutParsedPrefix( field );
117
118 if ( defaultValue.length > 0 )
119 {
120 if ( defaultValue.length > 1 )
121 {
122 throw new RuntimeException( String.format( "Too many default values for field %s", field.getName() ) );
123 }
124
125 final Class< ? > fieldType = field.getType();
126
127 try
128 {
129 final Object defValue = evaluator.evaluate( defaultValue[0], fieldType );
130
131 if ( defValue == null || fieldType.isInstance( defValue ) )
132 {
133 return defValue;
134 }
135
136 return convertTo( fieldType, defValue );
137 }
138 catch ( RuntimeException e )
139 {
140 throw e;
141 }
142 catch ( Exception e )
143 {
144 throw new RuntimeException( String.format(
145 "Problem encountered converting default value for %s parameter to %s",
146 currentParameterName, fieldType ), e );
147 }
148 }
149 else
150 {
151 if ( !required )
152 {
153
154 if ( annotation.defaultValueGetterMethod().isEmpty() )
155 {
156 return null;
157 }
158
159 try
160 {
161 Method method = mojo.getClass().getDeclaredMethod( annotation.defaultValueGetterMethod() );
162
163 method.setAccessible( true );
164 return method.invoke( mojo );
165 }
166 catch ( Exception e )
167 {
168 throw new RuntimeException( String.format(
169 "Problem encountered accessing default value for %s parameter",
170 currentParameterName ), e );
171 }
172 }
173 else
174 {
175 throw new RuntimeException( String.format(
176 "Required parameter %1$ has no value. Please "
177 + "supply with -D%1$=value on the command line or as property or "
178 + "plugin configuration in your pom or settings file.",
179 currentParameterName ) );
180 }
181 }
182 }
183
184 private Object convertTo( Class< ? > javaType, Object defValue )
185 throws Exception
186 {
187
188 try
189 {
190 return javaType.getMethod( "valueOf", String.class ).invoke( null, defValue );
191 }
192 catch ( NoSuchMethodException e )
193 {
194 return javaType.getConstructor( String.class ).newInstance( defValue );
195 }
196 }
197
198 private Object getValueFromMojo( String fieldBaseName )
199 {
200 return getValueFromObject( mojo, configPojoName + toFirstLetterUppercase( fieldBaseName ) );
201 }
202
203 private Object getValueFromPojo( String fieldBaseName )
204 {
205 return getValueFromObject( configPojoInstance, fieldBaseName );
206 }
207
208 private Object getValueFromObject( Object object, String fieldBaseName )
209 {
210 Object value = null;
211 try
212 {
213 Field pojoField = findFieldByName( object, fieldBaseName );
214 if ( pojoField != null )
215 {
216 value = pojoField.get( object );
217 }
218 }
219 catch ( Exception e )
220 {
221
222 }
223 return value;
224 }
225
226 private Field findFieldByName( Object object, String name )
227 {
228 for ( Field field : object.getClass().getDeclaredFields() )
229 {
230 if ( field.getName().equals( name ) )
231 {
232 field.setAccessible( true );
233 return field;
234 }
235 }
236 return null;
237 }
238
239 private String getFieldNameWithoutPrefix( Field field, String prefix )
240 {
241 if ( field.getName().startsWith( prefix ) )
242 {
243 String fieldName = field.getName().substring( prefix.length() );
244 return fieldName.substring( 0, 1 ).toLowerCase() + fieldName.substring( 1 );
245 }
246 else
247 {
248 return field.getName();
249 }
250 }
251
252 private String toFirstLetterUppercase( String s )
253 {
254 return s.substring( 0, 1 ).toUpperCase() + s.substring( 1 );
255 }
256
257 private String getFieldNameWithoutParsedPrefix( Field field )
258 {
259 return getFieldNameWithoutPrefix( field, configPojoPrefix );
260 }
261
262 private void initConfigPojo()
263 {
264 try
265 {
266 Field configPojo = findPropertiesByAnnotation( ConfigPojo.class ).iterator().next();
267 configPojoName = configPojo.getName();
268 configPojoInstance = configPojo.get( mojo );
269 configPojoPrefix = configPojo.getAnnotation( ConfigPojo.class ).prefix();
270 }
271 catch ( Exception e )
272 {
273
274 }
275 }
276 }