source: release-kits/shared/ant-installer/src/org/tp23/antinstaller/runtime/exe/LoadConfigFilter.java@ 15210

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

Lots of changes to the installer. Now only look in LanguagePack resource bundle for strings.

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
282 if (type.equalsIgnoreCase("text")) {
283 return new UnvalidatedTextInput();
284 }
285 else if (type.equalsIgnoreCase("directory")) {
286 return new DirectoryInput();
287 }
288 else if (type.equalsIgnoreCase("target")) {
289 return new TargetInput();
290 }
291 else if (type.equalsIgnoreCase("file")) {
292 return new FileInput();
293 }
294 else if (type.equalsIgnoreCase("comment")) {
295 return new CommentOutput();
296 }
297 else if (type.equalsIgnoreCase("checkbox")) {
298 return new CheckboxInput();
299 }
300 else if (type.equalsIgnoreCase("validated")) {
301 return new ValidatedTextInput();
302 }
303 else if (type.equalsIgnoreCase("ext-validated")) {
304 return new ExtValidatedTextInput();
305 }
306 else if (type.equalsIgnoreCase("password")) {
307 return new PasswordTextInput();
308 }
309 else if (type.equalsIgnoreCase("password-confirm")) {
310 return new ConfirmPasswordTextInput();
311 }
312 else if (type.equalsIgnoreCase("hidden")) {
313 return new HiddenPropertyInput();
314 }
315 else if (type.equalsIgnoreCase("date")) {
316 return new DateInput();
317 }
318 else if (type.equalsIgnoreCase("app-root")) {
319 return new AppRootInput();
320 }
321 else if (type.equalsIgnoreCase("conditional")) {
322 ConditionalField conditionalField = new ConditionalField();
323 OutputField[] outFields = getInnerOutputFields( field );
324 InputField[] inFields = new InputField[ outFields.length ];
325 for( int i = 0; i < outFields.length; i++ ) {
326 inFields[i] = (InputField) outFields[i];
327 }
328 conditionalField.setFields( inFields );
329 return conditionalField;
330 }
331 else if (type.equalsIgnoreCase("select")) {
332 SelectInput sInput = new SelectInput();
333 NodeList allOptions = field.getElementsByTagName("option");
334 ArrayList options = new ArrayList();
335 for (int i = 0; i < allOptions.getLength(); i++) {
336 Element optionElem = (Element) allOptions.item(i);
337 SelectInput.Option option = sInput.getNewOption();
338 option.setText(optionElem.getAttribute("text"));
339 option.value = optionElem.getAttribute("value");
340 options.add(option);
341 }
342 SelectInput.Option[] optionArr = new SelectInput.Option[options.size()];
343 options.toArray(optionArr);
344 sInput.setOptions(optionArr);
345
346 return sInput;
347 }
348 else if (type.equalsIgnoreCase("target-select")) {
349 TargetSelectInput sInput = new TargetSelectInput();
350 NodeList allOptions = field.getElementsByTagName("option");
351 ArrayList options = new ArrayList();
352 for (int i = 0; i < allOptions.getLength(); i++) {
353 Element optionElem = (Element) allOptions.item(i);
354 SelectInput.Option option = sInput.getNewOption();
355 option.setText(optionElem.getAttribute("text"));
356 option.value = optionElem.getAttribute("value");
357 options.add(option);
358 }
359 SelectInput.Option[] optionArr = new SelectInput.Option[options.size()];
360 options.toArray(optionArr);
361 sInput.setOptions(optionArr);
362
363 return sInput;
364 }
365 else if (type.equalsIgnoreCase("large-select")) {
366 LargeSelectInput sInput = new LargeSelectInput();
367 NodeList allOptions = field.getElementsByTagName("option");
368 ArrayList options = new ArrayList();
369 for (int i = 0; i < allOptions.getLength(); i++) {
370 Element optionElem = (Element) allOptions.item(i);
371 LargeSelectInput.Option option = sInput.getNewOption();
372 option.setText(optionElem.getAttribute("text"));
373 option.value = optionElem.getAttribute("value");
374 options.add(option);
375 }
376 LargeSelectInput.Option[] optionArr = new LargeSelectInput.Option[options.size()];
377 options.toArray(optionArr);
378 sInput.setOptions(optionArr);
379
380 return sInput;
381 }
382 System.out.println("Unrecognised Input Element:"+type);
383 return null;
384 //throw new ConfigurationException("Unknown Input Field type:" + type);
385 }
386
387
388
389 /**
390 * Calls bean setter methods based on attribures found. Could use BeanUtils here
391 * but we want to stay clear of external dependencies.
392 * @param bean Object
393 * @param map NamedNodeMap
394 */
395 private void setProperties(Object bean, NamedNodeMap map) {
396 int numAtts = map.getLength();
397 for (int a = 0; a < numAtts; a++) {
398 Node attribute = map.item(a);
399 String name = attribute.getNodeName();
400 String value = attribute.getNodeValue();
401 String methodName = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
402 Method[] allMethods = bean.getClass().getMethods();
403 for (int m = 0; m < allMethods.length; m++) {
404 if (allMethods[m].getName().equals(methodName)) {
405 try {
406 Class[] parameters = allMethods[m].getParameterTypes();
407 Object[] paramValues;
408 if (parameters[0].equals(Boolean.class)) {
409 paramValues = new Boolean[1];
410 if ( OutputField.isTrue(value) ) {
411 paramValues[0] = Boolean.TRUE;
412 }
413 else {
414 paramValues[0] = Boolean.FALSE;
415 }
416 }
417 else
418 if (parameters[0].equals(Integer.class)) {
419 paramValues = new Integer[1];
420 paramValues[0] = new Integer(value);
421 }
422 else {
423 paramValues = new String[1];
424 paramValues[0] = value;
425 }
426 allMethods[m].invoke(bean, paramValues);
427 continue;
428 }
429 catch (IndexOutOfBoundsException ex) {
430 // not the setter we are looking for
431 // this is the wrong overloaded method
432 continue;
433 }
434 // Ignore reflection errors and continue
435 catch (IllegalArgumentException e) {
436 }
437 catch (IllegalAccessException e) {
438 }
439 catch (InvocationTargetException e) {
440 }
441 }
442 }
443 }
444 }
445
446 private static class CustomEntityResolver implements EntityResolver{
447 public InputSource resolveEntity(String publicId, String systemId) {
448
449 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
450 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.2.dtd")) {
451 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
452 "/org/tp23/antinstaller/antinstall-config-0.2.dtd"));
453 return localSrc;
454 }
455 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
456 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.3.dtd")) {
457 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
458 "/org/tp23/antinstaller/antinstall-config-0.3.dtd"));
459 return localSrc;
460 }
461 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
462 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.4.dtd")) {
463 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
464 "/org/tp23/antinstaller/antinstall-config-0.4.dtd"));
465 return localSrc;
466 }
467 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
468 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.5.dtd")) {
469 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
470 "/org/tp23/antinstaller/antinstall-config-0.5.dtd"));
471 return localSrc;
472 }
473 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
474 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.6.dtd")) {
475 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
476 "/org/tp23/antinstaller/antinstall-config-0.6.dtd"));
477 return localSrc;
478 }
479 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
480 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.7.dtd")) {
481 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
482 "/org/tp23/antinstaller/antinstall-config-0.7.dtd"));
483 return localSrc;
484 }
485 if (publicId.equals("-//tp23 //DTD Ant Installer Config//EN") &&
486 systemId.equals("http://antinstaller.sf.net/dtd/antinstall-config-0.8.dtd")) {
487 InputSource localSrc = new InputSource(this.getClass().getResourceAsStream(
488 "/org/tp23/antinstaller/antinstall-config-0.8.dtd"));
489 return localSrc;
490 }
491 else {
492 return null;
493 }
494 }
495 }
496}
Note: See TracBrowser for help on using the repository browser.