View Javadoc

1   /*
2    * Copyright 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.ci.config.load;
17  
18  import java.io.FileNotFoundException;
19  import java.io.IOException;
20  
21  import org.jdom.Document;
22  import org.jdom.Element;
23  import org.jdom.JDOMException;
24  import org.jdom.input.SAXBuilder;
25  import org.jdom.xpath.XPath;
26  import org.xml.sax.InputSource;
27  
28  import de.smartics.ci.config.hudson.AbstractHudsonConfigHelper;
29  import de.smartics.ci.config.utils.JDomUtils;
30  import de.smartics.util.lang.Arguments;
31  import de.smartics.util.lang.NullArgumentException;
32  
33  /**
34   * Loader of XML job configurations.
35   */
36  public final class HudsonJobConfigLoader
37  {
38    // ********************************* Fields *********************************
39  
40    // --- constants ------------------------------------------------------------
41  
42    // --- members --------------------------------------------------------------
43  
44    /**
45     * The location manager to load resources.
46     */
47    private final LocationManager locationManager;
48  
49    /**
50     * The loader configuration to control the loading and creation of Hudson job
51     * configuration files.
52     */
53    private final HudsonJobConfigurationLoaderConfig loaderConfig;
54  
55    /**
56     * Helper to merge Hudson XML config files.
57     */
58    private final DocumentMerger merger = new DocumentMerger();
59  
60    // ****************************** Initializer *******************************
61  
62    // ****************************** Constructors ******************************
63  
64    /**
65     * Default constructor.
66     *
67     * @param locationManager the location manager to load resources.
68     * @param loaderConfig the loader configuration to control the loading and
69     *          creation of Hudson job configuration files.
70     * @throws NullArgumentException if {@code locationManager} or
71     *           {@code loaderConfig} is <code>null</code>.
72     */
73    public HudsonJobConfigLoader(final LocationManager locationManager,
74        final HudsonJobConfigurationLoaderConfig loaderConfig)
75      throws NullArgumentException
76    {
77      Arguments.checkNotNull("locationManager", locationManager);
78      Arguments.checkNotNull("loaderConfig", loaderConfig);
79  
80      this.locationManager = locationManager;
81      this.loaderConfig = loaderConfig;
82    }
83  
84    // ****************************** Inner Classes *****************************
85  
86    // ********************************* Methods ********************************
87  
88    // --- init -----------------------------------------------------------------
89  
90    // --- get&set --------------------------------------------------------------
91  
92    // --- business -------------------------------------------------------------
93  
94    /**
95     * Loads the XML document from the given loader plan. The loader plan
96     * instructs the job config loader to load a number of Hudson job
97     * configuration files to merge their contents.
98     *
99     * @param plan the plan to load a number of job config files in a given order.
100    *          Later config files override values previously loaded.
101    * @return the document containing the merged information from the job config
102    *         files specified by the plan as an XML string.
103    * @throws NullArgumentException if {@code plan} is <code>null</code>.
104    * @throws IllegalArgumentException if {@code plan} is empty.
105    * @throws JDOMException on any XML parsing or generation problem.
106    */
107   public HudsonJobConfig loadHudsonConfig(final LoaderPlan plan)
108     throws NullArgumentException, IllegalArgumentException, JDOMException
109   {
110     final Document document = load(plan);
111     final String xmlString = JDomUtils.toString(document);
112     final String id = fetchId(document);
113     return new HudsonJobConfig(id, xmlString);
114   }
115 
116   private String fetchId(final Document document) throws JDOMException
117   {
118     final Element projectIdElement =
119         (Element) XPath.selectSingleNode(document,
120             "/maven2-moduleset/authToken");
121     final String projectId = projectIdElement.getTextNormalize();
122     return projectId;
123   }
124 
125   /**
126    * Loads the XML document from the given loader plan. The loader plan
127    * instructs the job config loader to load a number of Hudson job
128    * configuration files to merge their contents.
129    *
130    * @param plan the plan to load a number of job config files in a given order.
131    *          Later config files override values previously loaded.
132    * @return the document containing the merged information from the job config
133    *         files specified by the plan as an XML string.
134    * @throws NullArgumentException if {@code plan} is <code>null</code>.
135    * @throws IllegalArgumentException if {@code plan} is empty.
136    * @throws JDOMException on any XML parsing or generation problem.
137    */
138   public Document load(final LoaderPlan plan) throws NullArgumentException,
139     IllegalArgumentException, JDOMException
140   {
141     checkArguments(plan);
142 
143     Document document = createDocument(plan);
144 
145     String resource = null;
146     try
147     {
148       for (final String configName : plan)
149       {
150         resource = configName + ".xml";
151         final InputSource inputSource = locationManager.open(resource);
152         document = mergeDocument(document, inputSource);
153       }
154 
155       final HudsonJobDocumentFixer fixer =
156           new HudsonJobDocumentFixer(loaderConfig, document);
157       fixer.fix();
158 
159       return document;
160     }
161     catch (final FileNotFoundException e)
162     {
163       throw new IllegalArgumentException("Resource '" + resource // NOPMD
164                                          + "' cannot be found.", e);
165     }
166     catch (final JDOMException e)
167     {
168       throw new IllegalArgumentException("Resource '" + resource
169                                          + "' is not valid.", e);
170     }
171     catch (final IOException e)
172     {
173       throw new IllegalArgumentException("Resource '" + resource
174                                          + "' cannot be read.", e);
175     }
176   }
177 
178   private static void checkArguments(final LoaderPlan plan)
179     throws IllegalArgumentException, NullArgumentException
180   {
181     Arguments.checkNotNull("plan", plan);
182 
183     if (plan.isEmpty())
184     {
185       throw new IllegalArgumentException("The loader plan must not be empty.");
186     }
187   }
188 
189   private Document createDocument(final LoaderPlan plan) throws JDOMException
190   {
191     final Document hudsonConfigXml =
192         AbstractHudsonConfigHelper.createDocument();
193     final MavenInfoApplier maven = new MavenInfoApplier(loaderConfig, plan);
194     maven.addAllInfo(hudsonConfigXml);
195     return hudsonConfigXml;
196   }
197 
198   private Document mergeDocument(final Document document,
199       final InputSource inputSource) throws JDOMException, IOException
200   {
201     final SAXBuilder builder = new SAXBuilder();
202     final Document newDocument = builder.build(inputSource);
203     final Document mergedDocument = merger.merge(document, newDocument);
204 
205     return mergedDocument;
206   }
207 
208   // --- object basics --------------------------------------------------------
209 
210 }