source: release-kits/lirk3/bin/ant-installer/src/org/tp23/antinstaller/runtime/exe/LoadConfigFilter.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 17.0 KB
Line 
1/*
2 * Copyright 2005 Paul Hinds
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 */
16package org.tp23.antinstaller.runtime.exe;
17
18import java.io.File;
19import java.io.FileInputStream;
20import java.io.IOException;
21import java.io.InputStream;
22import java.lang.reflect.InvocationTargetException;
23import java.lang.reflect.Method;
24import java.util.ArrayList;
25
26import javax.xml.parsers.DocumentBuilder;
27import javax.xml.parsers.DocumentBuilderFactory;
28
29import org.tp23.antinstaller.InstallException;
30import org.tp23.antinstaller.Installer;
31import org.tp23.antinstaller.InstallerContext;
32import org.tp23.antinstaller.input.AppRootInput;
33import org.tp23.antinstaller.input.CheckboxInput;
34import org.tp23.antinstaller.input.CommentOutput;
35import org.tp23.antinstaller.input.ConditionalField;
36import org.tp23.antinstaller.input.ConfirmPasswordTextInput;
37import org.tp23.antinstaller.input.DateInput;
38import org.tp23.antinstaller.input.DirectoryInput;
39import org.tp23.antinstaller.input.ExtValidatedTextInput;
40import org.tp23.antinstaller.input.FileInput;
41import org.tp23.antinstaller.input.HiddenPropertyInput;
42import org.tp23.antinstaller.input.InputField;
43import org.tp23.antinstaller.input.LargeSelectInput;
44import org.tp23.antinstaller.input.OutputField;
45import org.tp23.antinstaller.input.PasswordTextInput;
46import org.tp23.antinstaller.input.SelectInput;
47import org.tp23.antinstaller.input.TargetInput;
48import org.tp23.antinstaller.input.TargetSelectInput;
49import org.tp23.antinstaller.input.UnvalidatedTextInput;
50import org.tp23.antinstaller.input.ValidatedTextInput;
51import org.tp23.antinstaller.page.LicensePage;
52import org.tp23.antinstaller.page.Page;
53import org.tp23.antinstaller.page.ProgressPage;
54import org.tp23.antinstaller.page.SimpleInputPage;
55import org.tp23.antinstaller.page.SplashPage;
56import org.tp23.antinstaller.page.TextPage;
57import org.tp23.antinstaller.runtime.ConfigurationException;
58import org.w3c.dom.Document;
59import org.w3c.dom.Element;
60import org.w3c.dom.NamedNodeMap;
61import org.w3c.dom.Node;
62import org.w3c.dom.NodeList;
63import org.xml.sax.EntityResolver;
64import org.xml.sax.InputSource;
65
66
67/**
68 * Loads the Ant Install configuration and sets the Installer object back
69 * into the context. A similar technique to the apache digester is used to
70 * populate object attributes in this class.
71 * N.B. The only types that can be set for object attributes are Strings, booleans
72 * or ints.
73 * @author Paul Hinds
74 * @version $Id: LoadConfigFilter.java,v 1.9 2007/01/28 08:44:39 teknopaul Exp $
75 */
76public class LoadConfigFilter implements ExecuteFilter {
77
78 //TODO move to InstallerContext
79 public static final String INSTALLER_CONFIG_FILE = "antinstall-config.xml";
80
81 protected Installer installer = new Installer();
82 protected InstallerContext ctx;
83
84 /**
85 * @see org.tp23.antinstaller.runtime.exe.ExecuteFilter#exec(org.tp23.antinstaller.InstallerContext)
86 */
87 public void exec(InstallerContext ctx) throws InstallException {
88 this.ctx = ctx;
89
90 try {
91 installer = readConfig(ctx.getFileRoot(), ctx.getInstallerConfigFile());
92 ctx.setInstaller(installer);
93 ctx.log("Config loaded");
94 }
95 catch (IOException e) {
96 throw new InstallException("Not able to load and read the AntInstaller config", e);
97 }
98 catch (ConfigurationException e) {
99 throw new InstallException("Not able to load and read the AntInstaller config", e);
100 }
101 }
102
103 /**
104 * Currently read the config using any available XML parser
105 * This method reads the config from the file system
106 * @param fileRoot The directory where the config file is stored
107 * @param the name of the configuration file (usually antinstall-config.xml)
108 * @return Installer
109 */
110 public Installer readConfig(File fileRoot, String fileName) throws IOException, ConfigurationException {
111
112 installer.getResultContainer().setInstallRoot(fileRoot);
113
114 File config = new File(fileRoot, fileName);
115 if(!config.exists()){ // passed in incorrectly on the command line or bad installer
116 throw new IOException();
117 }
118 InputSource xmlInp = new InputSource(new FileInputStream(config));
119 readConfig(xmlInp);
120
121 return installer;
122 }
123 /**
124 * This overloaded method reads from the provided input stream to facilitate
125 * reading configs directly from the Jar, the file root is still needed
126 * for Ant's basedir. Used by InputStreamLoadConfigFilter
127 * @return Installer
128 */
129 protected Installer readConfig(File fileRoot, InputStream configSource) throws IOException, ConfigurationException {
130
131 installer.getResultContainer().setInstallRoot(fileRoot);
132
133 InputSource xmlInp = new InputSource(configSource);
134 readConfig(xmlInp);
135
136 return installer;
137 }
138 /**
139 * Currently read the config using any available XML parser
140 * @todo read the installer with only xerces
141 * @return Installer
142 */
143 protected Installer readConfig(InputSource xmlInp) throws IOException, ConfigurationException {
144
145 Document doc = null;
146 int line=0;
147 try {
148 line=1;
149 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
150 line=2;
151 DocumentBuilder parser = docBuilderFactory.newDocumentBuilder();
152 line=3;
153 // RFE [ 1475361 ] Using a custom entity resolver
154 String entityResolverClass = System.getProperty("antinstaller.EntityResolverClass");
155
156 line=4;
157 EntityResolver er = null;
158
159 line=5;
160 if(entityResolverClass != null){
161 line=6;
162 try{
163 line=7;
164 er = (EntityResolver)Class.forName(entityResolverClass).newInstance();
165 }
166 catch(Exception e){
167 // Property error use default this is a very specific requirement
168 line=8;
169 er = new CustomEntityResolver();
170 }
171 line=9;
172 }
173 else{
174 line=10;
175 er = new CustomEntityResolver();
176 }
177 line=11;
178 parser.setEntityResolver(er);
179
180 line=12;
181 doc = parser.parse(xmlInp);
182 line=13;
183 Element root = doc.getDocumentElement();
184 line=14;
185 root.normalize();
186 line=15;
187 setProperties(installer, root.getAttributes());
188 line=16;
189 NodeList allPages = root.getElementsByTagName("page");
190 //TODO make this pluggable
191 line=17;
192 getPages(installer, allPages);
193 }
194 catch (Exception e) {
195 e.printStackTrace();
196 System.out.println( e.getMessage() );
197 throw new IOException("DomFactory error: caused by:" + e.getClass() + ":" + e.getMessage() + ". Line: " + line);
198 }
199 return installer;
200 }
201
202
203 /**
204 * Used when reading the config
205 * @param allPages NodeList
206 * @throws ConfigurationException
207 */
208 private void getPages(Installer installerConfig, NodeList allPages) throws ConfigurationException {
209 ArrayList pages = new ArrayList();
210 for (int i = 0; i < allPages.getLength(); i++) {
211 Element pageElem = (Element) allPages.item(i);
212 Page page = getPageType(pageElem.getAttribute("type"));
213 setProperties(page, pageElem.getAttributes());
214 pages.add(page);
215 getOutputFields(page, pageElem);
216 }
217 Page[] pageArr = new Page[pages.size()];
218 pages.toArray(pageArr);
219 installerConfig.setPages(pageArr);
220 }
221 /**
222 * Used when reading the config
223 * @param page Page
224 * @param pageElem Element
225 * @throws ConfigurationException
226 */
227 private void getOutputFields(Page page, Element pageElem) throws ConfigurationException {
228 page.setOutputField( getInnerOutputFields( pageElem ));
229 }
230
231 private OutputField[] getInnerOutputFields( Element elem) throws ConfigurationException {
232 NodeList allFields = elem.getChildNodes();
233 ArrayList fields = new ArrayList();
234 for (int i = 0; i < allFields.getLength(); i++) {
235 if(! (allFields.item(i) instanceof Element))continue;
236 Element fieldElem = (Element)allFields.item(i);
237 OutputField field = getOutputFieldType(fieldElem.getNodeName(), fieldElem);
238 if(field != null){
239 setProperties(field, fieldElem.getAttributes());
240 fields.add(field);
241 field.setResultContainer(installer.getResultContainer());
242 }
243 }
244 OutputField[] fieldArr = new OutputField[fields.size()];
245
246 return (OutputField[])fields.toArray(fieldArr);
247 }
248
249 /**
250 * Used when reading the config
251 * @param type String
252 * @throws ConfigurationException
253 * @return Page
254 */
255 private Page getPageType(String type) throws ConfigurationException {
256 if (type.equalsIgnoreCase("license")) {
257 return new LicensePage();
258 }
259 else if (type.equalsIgnoreCase("input")) {
260 return new SimpleInputPage();
261 }
262 else if (type.equalsIgnoreCase("progress")) {
263 return new ProgressPage();
264 }
265 else if (type.equalsIgnoreCase("splash")) {
266 return new SplashPage();
267 }
268 else if (type.equalsIgnoreCase("text")) {
269 return new TextPage();
270 }
271 throw new ConfigurationException("Unknown Page type:" + type);
272 }
273 /**
274 * Used when reading the config
275 * @param type String
276 * @param field Element
277 * @throws ConfigurationException
278 * @return InputField
279 */
280 private OutputField getOutputFieldType(String type, Element field) throws ConfigurationException {
281 if (type.equalsIgnoreCase("text")) {
282 return new UnvalidatedTextInput();
283 }
284 else if (type.equalsIgnoreCase("directory")) {
285 return new DirectoryInput();
286 }
287 else if (type.equalsIgnoreCase("target")) {
288 return new TargetInput();
289 }
290 else if (type.equalsIgnoreCase("file")) {
291 return new FileInput();
292 }
293 else if (type.equalsIgnoreCase("comment")) {
294 return new CommentOutput();
295 }
296 else if (type.equalsIgnoreCase("checkbox")) {
297 return new CheckboxInput();
298 }
299 else if (type.equalsIgnoreCase("validated")) {
300 return new ValidatedTextInput();
301 }
302 else if (type.equalsIgnoreCase("ext-validated")) {
303 return new ExtValidatedTextInput();
304 }
305 else if (type.equalsIgnoreCase("password")) {
306 return new PasswordTextInput();
307 }
308 else if (type.equalsIgnoreCase("password-confirm")) {
309 return new ConfirmPasswordTextInput();
310 }
311 else if (type.equalsIgnoreCase("hidden")) {
312 return new HiddenPropertyInput();
313 }
314 else if (type.equalsIgnoreCase("date")) {
315 return new DateInput();
316 }
317 else if (type.equalsIgnoreCase("app-root")) {
318 return new AppRootInput();
319 }
320 else if (type.equalsIgnoreCase("conditional")) {
321 ConditionalField conditionalField = new ConditionalField();
322 OutputField[] outFields = getInnerOutputFields( field );
323 InputField[] inFields = new InputField[ outFields.length ];
324 for( int i = 0; i < outFields.length; i++ ) {
325 inFields[i] = (InputField) outFields[i];
326 }
327 conditionalField.setFields( inFields );
328 return conditionalField;
329 }
330 else if (type.equalsIgnoreCase("select")) {
331 SelectInput sInput = new SelectInput();
332 NodeList allOptions = field.getElementsByTagName("option");
333 ArrayList options = new ArrayList();
334 for (int i = 0; i < allOptions.getLength(); i++) {
335 Element optionElem = (Element) allOptions.item(i);
336 SelectInput.Option option = sInput.getNewOption();
337 option.setText(optionElem.getAttribute("text"));
338 option.value = optionElem.getAttribute("value");
339 options.add(option);
340 }
341 SelectInput.Option[] optionArr = new SelectInput.Option[options.size()];
342 options.toArray(optionArr);
343 sInput.setOptions(optionArr);
344
345 return sInput;
346 }
347 else if (type.equalsIgnoreCase("target-select")) {
348 TargetSelectInput sInput = new TargetSelectInput();
349 NodeList allOptions = field.getElementsByTagName("option");
350 ArrayList options = new ArrayList();
351 for (int i = 0; i < allOptions.getLength(); i++) {
352 Element optionElem = (Element) allOptions.item(i);
353 SelectInput.Option option = sInput.getNewOption();
354 option.setText(optionElem.getAttribute("text"));
355 option.value = optionElem.getAttribute("value");
356 options.add(option);
357 }
358 SelectInput.Option[] optionArr = new SelectInput.Option[options.size()];
359 options.toArray(optionArr);
360 sInput.setOptions(optionArr);
361
362 return sInput;
363 }
364 else if (type.equalsIgnoreCase("large-select")) {
365 LargeSelectInput sInput = new LargeSelectInput();
366 NodeList allOptions = field.getElementsByTagName("option");
367 ArrayList options = new ArrayList();
368 for (int i = 0; i < allOptions.getLength(); i++) {
369 Element optionElem = (Element) allOptions.item(i);
370 LargeSelectInput.Option option = sInput.getNewOption();
371 option.setText(optionElem.getAttribute("text"));
372 option.value = optionElem.getAttribute("value");
373 options.add(option);
374 }
375 LargeSelectInput.Option[] optionArr = new LargeSelectInput.Option[options.size()];
376 options.toArray(optionArr);
377 sInput.setOptions(optionArr);
378
379 return sInput;
380 }
381 System.out.println("Unrecognised Input Element:"+type);
382 return null;
383 //throw new ConfigurationException("Unknown Input Field type:" + type);
384 }
385
386
387
388 /**
389 * Calls bean setter methods based on attribures found. Could use BeanUtils here
390 * but we want to stay clear of external dependencies.
391 * @param bean Object
392 * @param map NamedNodeMap
393 */
394 private void setProperties(Object bean, NamedNodeMap map) {
395 int numAtts = map.getLength();
396 for (int a = 0; a < numAtts; a++) {
397 Node attribute = map.item(a);
398 String name = attribute.getNodeName();
399 String value = attribute.getNodeValue();
400 String methodName = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
401 Method[] allMethods = bean.getClass().getMethods();
402 for (int m = 0; m < allMethods.length; m++) {
403 if (allMethods[m].getName().equals(methodName)) {
404 try {
405 Class[] parameters = allMethods[m].getParameterTypes();
406 Object[] paramValues;
407 if (parameters[0].equals(Boolean.class)) {
408 paramValues = new Boolean[1];
409 if ( OutputField.isTrue(value) ) {
410 paramValues[0] = Boolean.TRUE;
411 }
412 else {
413 paramValues[0] = Boolean.FALSE;
414 }
415 }
416 else
417 if (parameters[0].equals(Integer.class)) {
418 paramValues = new Integer[1];
419 paramValues[0] = new Integer(value);
420 }
421 else {
422 paramValues = new String[1];
423 paramValues[0] = value;
424 }
425 allMethods[m].invoke(bean, paramValues);
426 continue;
427 }
428 catch (IndexOutOfBoundsException ex) {
429 // not the setter we are looking for
430 // this is the wrong overloaded method
431 continue;
432 }
433 // Ignore reflection errors and continue
434 catch (IllegalArgumentException e) {
435 }
436 catch (IllegalAccessException e) {
437 }
438 catch (InvocationTargetException e) {
439 }
440 }
441 }
442 }
443 }
444
445 private static class CustomEntityResolver implements EntityResolver{
446 public InputSource resolveEntity(String publicId, String systemId) {
447
448 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
449 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.2.dtd")) {
450 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
451 "/org/tp23/antinstaller/antinstall-config-0.2.dtd"));
452 return localSrc;
453 }
454 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
455 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.3.dtd")) {
456 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
457 "/org/tp23/antinstaller/antinstall-config-0.3.dtd"));
458 return localSrc;
459 }
460 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
461 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.4.dtd")) {
462 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
463 "/org/tp23/antinstaller/antinstall-config-0.4.dtd"));
464 return localSrc;
465 }
466 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
467 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.5.dtd")) {
468 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
469 "/org/tp23/antinstaller/antinstall-config-0.5.dtd"));
470 return localSrc;
471 }
472 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
473 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.6.dtd")) {
474 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
475 "/org/tp23/antinstaller/antinstall-config-0.6.dtd"));
476 return localSrc;
477 }
478 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
479 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.7.dtd")) {
480 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
481 "/org/tp23/antinstaller/antinstall-config-0.7.dtd"));
482 return localSrc;
483 }
484 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
485 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.8.dtd")) {
486 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
487 "/org/tp23/antinstaller/antinstall-config-0.8.dtd"));
488 return localSrc;
489 }
490 else {
491 return null;
492 }
493 }
494 }
495}
Note: See TracBrowser for help on using the repository browser.