View Javadoc

1   /*
2    * Copyright 2006-2012 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.maven.plugin.buildmetadata.data;
17  
18  import java.lang.reflect.Field;
19  import java.util.Map;
20  
21  import org.apache.commons.beanutils.ConvertUtils;
22  import org.apache.maven.execution.MavenSession;
23  import org.apache.maven.execution.RuntimeInformation;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.project.MavenProject;
26  
27  import de.smartics.maven.plugin.buildmetadata.common.ScmInfo;
28  
29  /**
30   * Configuration instance to create instances of {@link MetaDataProvider}.
31   *
32   * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
33   * @version $Revision:591 $
34   */
35  public final class MetaDataProviderBuilder
36  {
37    // ********************************* Fields *********************************
38  
39    // --- constants ------------------------------------------------------------
40  
41    // --- members --------------------------------------------------------------
42  
43    /**
44     * The Maven project.
45     */
46    private final MavenProject project;
47  
48    /**
49     * The Maven session instance.
50     */
51    private final MavenSession session;
52  
53    /**
54     * The runtime information of the Maven instance being executed for the build.
55     */
56    private final RuntimeInformation runtime;
57  
58    /**
59     * The information for the SCM provided to the build plugin.
60     */
61    private final ScmInfo scmInfo;
62  
63    // ****************************** Initializer *******************************
64  
65    // ****************************** Constructors ******************************
66  
67    /**
68     * Default constructor.
69     *
70     * @param project the Maven project.
71     * @param session the Maven session instance.
72     * @param runtime the runtime information of the Maven instance being executed
73     *          for the build.
74     * @param scmInfo the information for the SCM provided to the build plugin.
75     */
76    public MetaDataProviderBuilder(final MavenProject project,
77        final MavenSession session, final RuntimeInformation runtime,
78        final ScmInfo scmInfo)
79    {
80      this.project = project;
81      this.session = session;
82      this.runtime = runtime;
83      this.scmInfo = scmInfo;
84    }
85  
86    // ****************************** Inner Classes *****************************
87  
88    // ********************************* Methods ********************************
89  
90    // --- init -----------------------------------------------------------------
91  
92    // --- get&set --------------------------------------------------------------
93  
94    // --- business -------------------------------------------------------------
95  
96    /**
97     * Creates a configured instance of the {@link MetaDataProvider} interface.
98     *
99     * @param config the configuration for the build.
100    * @return the created instance.
101    * @throws MojoExecutionException if the instance cannot be created.
102    */
103   public MetaDataProvider build(final Provider config)
104     throws MojoExecutionException
105   {
106     final MetaDataProvider instance = create(config.getType());
107     initialize(instance, config.getProperties());
108     return instance;
109   }
110 
111   @SuppressWarnings("unchecked")
112   private MetaDataProvider create(final String metaDataProviderClassName)
113     throws MojoExecutionException
114   {
115     try
116     {
117       final Class<? extends MetaDataProvider> metaDataProviderClass =
118           (Class<? extends MetaDataProvider>) Class
119               .forName(metaDataProviderClassName);
120       final MetaDataProvider instance = metaDataProviderClass.newInstance();
121       return instance;
122     }
123     catch (final Exception e)
124     {
125       throw new MojoExecutionException(
126           "Cannot create instance for meta data provider class '"
127               + metaDataProviderClassName + "'.", e);
128     }
129   }
130 
131   private void initialize(final MetaDataProvider instance,
132       final Map<String, String> properties) throws MojoExecutionException
133   {
134     setNonNullProperty(instance, "project", project, MavenProject.class);
135     setNonNullProperty(instance, "session", session, MavenSession.class);
136     setNonNullProperty(instance, "runtime", runtime, RuntimeInformation.class);
137     setNonNullProperty(instance, "scmInfo", scmInfo, ScmInfo.class);
138 
139     setProperties(instance, properties);
140   }
141 
142   private void setNonNullProperty(final MetaDataProvider instance,
143       final String propertyName, final Object propertyValue,
144       final Class<?> propertyType) throws MojoExecutionException
145   {
146     if (propertyValue != null)
147     {
148       final Class<? extends MetaDataProvider> metaDataProviderClass =
149           instance.getClass();
150       try
151       {
152         final Field field = findField(metaDataProviderClass, propertyName);
153         final Class<?> type = field.getType();
154         if (type.isAssignableFrom(propertyType))
155         {
156           field.setAccessible(true);
157           field.set(instance, propertyValue);
158         }
159       }
160       catch (final NoSuchFieldException e)
161       {
162         // OK, no such field, so we do not set it.
163       }
164       catch (final Exception e)
165       {
166         throw new MojoExecutionException("Cannot set property '" + propertyName
167                                          + "' for the instance of class '"
168                                          + metaDataProviderClass.getName()
169                                          + "'.", e);
170       }
171     }
172   }
173 
174   private Field findField(final Class<?> type, final String propertyName)
175     throws NoSuchFieldException
176   {
177     try
178     {
179       return type.getDeclaredField(propertyName);
180     }
181     catch (final NoSuchFieldException e)
182     {
183       if (type.getSuperclass().equals(Object.class))
184       {
185         throw e;
186       }
187     }
188     return findField(type.getSuperclass(), propertyName);
189   }
190 
191   private void setProperties(final MetaDataProvider instance,
192       final Map<String, String> properties) throws MojoExecutionException
193   {
194     if (properties != null && !properties.isEmpty())
195     {
196       for (final Map.Entry<String, String> entry : properties.entrySet())
197       {
198         final String propertyName = entry.getKey();
199         if (!Provider.RUN_AT_BUILD_POINT.equals(propertyName))
200         {
201           final String propertyValue = entry.getValue();
202           setProperty(instance, propertyName, propertyValue);
203         }
204       }
205     }
206   }
207 
208   private void setProperty(final MetaDataProvider instance,
209       final String propertyName, final String propertyValue)
210     throws MojoExecutionException
211   {
212     final Class<? extends MetaDataProvider> metaDataProviderClass =
213         instance.getClass();
214 
215     try
216     {
217       final Field field = findField(metaDataProviderClass, propertyName);
218       field.setAccessible(true);
219       final Class<?> type = field.getType();
220       final Object typedPropertyValue =
221           ConvertUtils.convert(propertyValue, type);
222       field.set(instance, typedPropertyValue);
223     }
224     catch (final Exception e)
225     {
226       throw new MojoExecutionException(
227           "Cannot set property '" + propertyName + "' to value '"
228               + propertyValue + "' for the instance of class '"
229               + metaDataProviderClass.getName() + "'.", e);
230     }
231   }
232 
233   // --- object basics --------------------------------------------------------
234 
235 }