001: /*
002: * Project: AMODA - Abstract Modeled Application
003: * Class: de.gulden.framework.amoda.generic.core.GenericApplicationEnvironment
004: * Version: snapshot-beautyj-1.1
005: *
006: * Date: 2004-09-29
007: *
008: * This is a snapshot version of the AMODA 0.2 development branch,
009: * it is not released as a seperate version.
010: * For AMODA, see http://amoda.berlios.de/.
011: *
012: * This is licensed under the GNU Lesser General Public License (LGPL)
013: * and comes with NO WARRANTY.
014: *
015: * Author: Jens Gulden
016: * Email: amoda@jensgulden.de
017: */
018:
019: package de.gulden.framework.amoda.generic.core;
020:
021: import de.gulden.framework.amoda.generic.metadata.*;
022: import de.gulden.framework.amoda.generic.option.*;
023: import de.gulden.framework.amoda.model.core.*;
024: import de.gulden.framework.amoda.model.core.ApplicationEnvironment;
025: import de.gulden.framework.amoda.model.core.Feature;
026: import de.gulden.framework.amoda.model.data.*;
027: import de.gulden.framework.amoda.model.data.Value;
028: import de.gulden.framework.amoda.model.interaction.*;
029: import de.gulden.framework.amoda.model.metadata.*;
030: import de.gulden.framework.amoda.model.option.*;
031: import de.gulden.util.Toolbox;
032: import de.gulden.util.xml.*;
033: import de.gulden.util.xml.serializer.*;
034: import de.gulden.util.xml.serializer.XMLSerializable;
035: import java.lang.*;
036: import java.net.*;
037: import java.util.*;
038: import javax.xml.parsers.*;
039: import org.w3c.dom.*;
040:
041: /**
042: * Class GenericApplicationEnvironment.
043: *
044: * @author Jens Gulden
045: * @version snapshot-beautyj-1.1
046: */
047: public abstract class GenericApplicationEnvironment implements
048: ApplicationEnvironment, XMLSerializable {
049:
050: // ------------------------------------------------------------------------
051: // --- fields ---
052: // ------------------------------------------------------------------------
053:
054: public static final Object[][] XML_COLLECTION_ELEMENTS = { {
055: "features", GenericFeature.FEATURE_MEMBERS } };
056:
057: public static final String VERSION = "0.2";
058:
059: public static String DEFAULT_LOGFILE = "./application.log";
060:
061: public static String DEFAULT_PROPERTIES = "./application.properties";
062:
063: public static String NL = System.getProperty("line.separator");
064:
065: public static String CONFIGURATION_PERSISTENT_OPTIONS = "persistent-options";
066:
067: public static String CONFIGURATION_BATCH_MODE = "batch-mode";
068:
069: public static String CONFIGURATION_INTERACTION_MODE = "interaction-mode";
070:
071: public Metadata metadata;
072:
073: public Map features;
074:
075: public Options options;
076:
077: protected ArgsParser argsParser;
078:
079: protected Collection batchCommands;
080:
081: protected Value[] inputValues;
082:
083: protected Workspace workspace;
084:
085: protected GenericApplicationEnvironmentFactory factory;
086:
087: protected GenericApplication genericApplication;
088:
089: protected LogFile logFile;
090:
091: // ------------------------------------------------------------------------
092: // --- constructor ---
093: // ------------------------------------------------------------------------
094:
095: public GenericApplicationEnvironment() {
096: options = new GenericOptions();
097: }
098:
099: // ------------------------------------------------------------------------
100: // --- methods ---
101: // ------------------------------------------------------------------------
102:
103: public GenericApplicationEnvironmentFactory getFactory() {
104: return factory;
105: }
106:
107: public void setFactory(
108: GenericApplicationEnvironmentFactory genericApplicationEnvironmentFactory) {
109: this .factory = genericApplicationEnvironmentFactory;
110: }
111:
112: public GenericApplication getGenericApplication() {
113: return genericApplication;
114: }
115:
116: public void setGenericApplication(
117: GenericApplication genericApplication) {
118: if (this .genericApplication != genericApplication) {
119: this .genericApplication = genericApplication;
120: if (genericApplication != null)
121: genericApplication
122: .setGenericApplicationEnvironment(this );
123: }
124: }
125:
126: public LogFile getLogFile() {
127: return logFile;
128: }
129:
130: public void setLogFile(LogFile logFile) {
131: this .logFile = logFile;
132: }
133:
134: public void launch(Application application) {
135: GenericApplication genericApplication = (GenericApplication) application; // application must be of type GenericApplication
136: setGenericApplication(genericApplication);
137: try {
138: setArgsParser(genericApplication.createArgsParser()); // user may overwtie factory methods to implement own features
139: setWorkspace(genericApplication.createWorkspace());
140:
141: genericApplication.init(this ); // will invoke XML initialization of application
142: launchAfterInit(genericApplication);
143: } catch (Throwable t) {
144: getGenericApplication().fatalError(t);
145: }
146: }
147:
148: public Message createDefaultMessage(String title, String text,
149: int type, Metadata metadata) {
150: de.gulden.framework.amoda.generic.interaction.GenericMessage m = new de.gulden.framework.amoda.generic.interaction.GenericMessage();
151: m.setParent(getGenericApplication());
152: m.setTitle(title);
153: m.setText(text);
154: m.setType(type);
155: return m;
156: }
157:
158: public ErrorMessage createDefaultErrorMessage(String text,
159: Throwable throwable, boolean exitApplication,
160: Metadata metadata) {
161: de.gulden.framework.amoda.generic.interaction.GenericErrorMessage m = new de.gulden.framework.amoda.generic.interaction.GenericErrorMessage();
162: m.setParent(getGenericApplication());
163: m.setTitle("Error");
164: m.setText(text);
165: m.setCause(throwable);
166: m.setExitApplication(exitApplication);
167: return m;
168: }
169:
170: public Question createDefaultQuestion(String title, String text,
171: String answerOptionsIds, Metadata metadata) {
172: de.gulden.framework.amoda.generic.interaction.GenericQuestion m = new de.gulden.framework.amoda.generic.interaction.GenericQuestion();
173: m.setParent(getGenericApplication());
174: m.setTitle(title);
175: m.setText(text);
176: m.setAnswers(answerOptionsIds);
177: return m;
178: }
179:
180: public Dialog createDefaultDialog(String title, String text,
181: Options options, Metadata metadata) {
182: de.gulden.framework.amoda.generic.interaction.GenericDialog m = new de.gulden.framework.amoda.generic.interaction.GenericDialog();
183: m.setParent(getGenericApplication());
184: m.setTitle(title);
185: m.setText(text);
186: m.setOptions(options);
187: return m;
188: }
189:
190: public Wizard createDefaultWizard(String title, Collection dialogs,
191: Metadata metadata) {
192: de.gulden.framework.amoda.generic.interaction.GenericWizard m = new de.gulden.framework.amoda.generic.interaction.GenericWizard();
193: m.setParent(getGenericApplication());
194: m.setTitle(title);
195: m.getDialogs().addAll(dialogs); // ****** ? ok so?
196: return m;
197: }
198:
199: public LogMessage createDefaultLogMessage(String text,
200: Object source, int type, Metadata metadata) {
201: de.gulden.framework.amoda.generic.interaction.GenericLogMessage m = new de.gulden.framework.amoda.generic.interaction.GenericLogMessage();
202: m.setParent(getGenericApplication());
203: m.setText(text);
204: m.setSource(source);
205: m.setType(type);
206: return m;
207: }
208:
209: public abstract void doMessage(Message message);
210:
211: public void doLogMessage(LogMessage logMessage) {
212: LogMessagePerformer log = getLogMessagePerformer();
213: if (log != null) {
214: log.doLogMessage(logMessage);
215: }
216: try {
217: if (logMessage.getApplication().getOptions().getBoolean(
218: "show-log-messages")) {
219: doMessage(logMessage);
220: return;
221: }
222: } catch (IllegalOptionError ioe) {
223: //fallthrough
224: }
225: if (logMessage.getApplication().isVerbose()) {
226: System.out.println("[log] " + logMessage.getText());
227: }
228: }
229:
230: public abstract void doErrorMessage(ErrorMessage errorMessage);
231:
232: public abstract void doQuestion(Question question);
233:
234: public abstract void doDialog(Dialog dialog);
235:
236: public abstract void doWizard(Wizard wizard);
237:
238: public OptionEntry createDefaultOption(String id,
239: Object initialValue, Metadata metadata) {
240: de.gulden.framework.amoda.generic.option.GenericOptionEntry o = new de.gulden.framework.amoda.generic.option.GenericOptionEntry();
241: o.setParent(getGenericApplication());
242: o.setId(id);
243: Class initialType;
244: if (initialValue != null) {
245: initialType = initialValue.getClass();
246: } else {
247: initialType = String.class;
248: }
249: o.setType(initialType);
250: ((de.gulden.framework.amoda.generic.data.GenericValue) o
251: .getValue(OptionEntry.STATE_DEFAULT)).set(initialValue);
252: o.setMetadata(metadata);
253: return o;
254: }
255:
256: public OptionChoice createDefaultOptionsChoice(String id,
257: Option[] options, Metadata metadata) {
258: de.gulden.framework.amoda.generic.option.GenericOptionChoice o = new de.gulden.framework.amoda.generic.option.GenericOptionChoice();
259: o.setParent(getGenericApplication());
260: o.setId(id);
261: for (int i = 0; i < options.length; i++) {
262: o.getEntries().put(options[i].getId(), options[i]);
263: }
264: o.setMetadata(metadata);
265: return o;
266: }
267:
268: public Options createDefaultOptions() {
269: de.gulden.framework.amoda.generic.option.GenericOptions o = new de.gulden.framework.amoda.generic.option.GenericOptions();
270: o.setParent(getGenericApplication());
271: return o;
272: }
273:
274: public Metadata createDefaultMetadata(String name, String title,
275: String description, String author, String copyright,
276: String email, String web) {
277: de.gulden.framework.amoda.generic.metadata.GenericMetadata m = new de.gulden.framework.amoda.generic.metadata.GenericMetadata();
278: if (name != null)
279: m.set("name", name);
280: if (name != null)
281: m.set("longname", name);
282: if (title != null)
283: m.set("title", title);
284: if (description != null)
285: m.set("description", description);
286: if (author != null)
287: m.set("author", author);
288: if (copyright != null)
289: m.set("copyright", copyright);
290: if (email != null)
291: m.set("email", email);
292: if (web != null)
293: m.set("web", web);
294: return m;
295: }
296:
297: public Metadata createDefaultMetadata(String name, String title,
298: String description) {
299: return createDefaultMetadata(name, title, description, null,
300: null, null, null);
301: }
302:
303: public Metadata createDefaultMetadata(String title,
304: String description) {
305: return createDefaultMetadata(null, title, description);
306: }
307:
308: public Metadata createDefaultMetadata(String description) {
309: return createDefaultMetadata(null, description);
310: }
311:
312: public DocumentBuilder getDefaultDocumentBuilder() {
313: return ((GenericApplicationEnvironmentFactory) getFactory())
314: .getDocumentBuilder();
315: }
316:
317: public Metadata parseXMLMetadata(Element element,
318: XMLSerializer serializer) throws XMLException {
319: Element metadataTag = de.gulden.util.xml.XMLToolbox.getChild(
320: element, "metadata");
321: if (metadataTag != null) {
322: de.gulden.framework.amoda.generic.metadata.GenericMetadata metadata = new de.gulden.framework.amoda.generic.metadata.GenericMetadata();
323: serializer.xmlDeserialize(metadata, metadataTag);
324: return metadata;
325: } else {
326: return new de.gulden.framework.amoda.generic.metadata.GenericMetadata(); // dummy rather than null
327: }
328: }
329:
330: public Options parseXMLOptions(Element element,
331: XMLSerializer serializer) throws XMLException {
332: Element optionsTag = de.gulden.util.xml.XMLToolbox.getChild(
333: element, "options");
334: if (optionsTag != null) {
335: de.gulden.framework.amoda.generic.option.GenericOptions options = new de.gulden.framework.amoda.generic.option.GenericOptions();
336: options.setParent(getGenericApplication());
337: serializer.xmlDeserialize(options, optionsTag);
338: return options;
339: } else {
340: return null;
341: }
342: }
343:
344: public LogMessagePerformer getLogMessagePerformer() {
345: return getLogFile();
346: }
347:
348: public Metadata getMetadata() {
349: return metadata;
350: }
351:
352: public void setMetadata(Metadata _metadata) {
353: metadata = _metadata;
354: }
355:
356: public ArgsParser getArgsParser() {
357: return argsParser;
358: }
359:
360: public void setArgsParser(ArgsParser _argsParser) {
361: argsParser = _argsParser;
362: }
363:
364: public Collection getBatchCommands() {
365: return batchCommands;
366: }
367:
368: public void setBatchCommands(Collection _batchCommands) {
369: batchCommands = _batchCommands;
370: }
371:
372: public Workspace getWorkspace() {
373: return workspace;
374: }
375:
376: public void setWorkspace(Workspace _workspace) {
377: workspace = _workspace;
378: }
379:
380: public Map getFeatures() {
381: return features;
382: }
383:
384: public void setFeatures(Map _features) {
385: features = _features;
386: }
387:
388: public abstract void doExit(GenericApplication application, int code);
389:
390: public Workspace createDefaultWorkspace() {
391: // your code here
392: return null;
393: }
394:
395: public Value[] getInputValues() {
396: return inputValues;
397: }
398:
399: public void setInputValues(Value[] _inputValues) {
400: inputValues = _inputValues;
401: }
402:
403: public void exit(int exitCode) {
404: System.exit(exitCode);
405: }
406:
407: public void exit() {
408: exit(0);
409: }
410:
411: public void doAbout() {
412: getGenericApplication().createAboutMessage().perform();
413: }
414:
415: public void doUsage(boolean exitApplication) {
416: de.gulden.framework.amoda.model.interaction.Message m = getGenericApplication()
417: .createUsageMessage();
418: if (m != null) {
419: String t = m.getText();
420: t += "Use option '-help' to see the list of options." + NL;
421: ((de.gulden.framework.amoda.generic.interaction.GenericMessage) m)
422: .setText(t);
423: m.perform();
424: }
425: if (exitApplication) {
426: getGenericApplication().exit();
427: }
428: }
429:
430: public void doHelp() {
431: de.gulden.framework.amoda.model.interaction.Message m = getGenericApplication()
432: .createHelpMessage();
433: if (m != null) {
434: m.perform();
435: }
436: }
437:
438: protected void launchAfterInit(GenericApplication genericApplication) {
439: prepareApplicationWelcome();
440: if (!genericApplication.isQuiet()) {
441: genericApplication.welcome();
442: }
443: if (genericApplication.getOptions().getBoolean("help")) {
444: genericApplication.help();
445: } else {
446: if (genericApplication.getOptions().getBoolean(
447: "use-logging")) {
448: setLogFile(createLogFile());
449: }
450: prepareApplicationStart();
451: //if (genericApplication.getOptions().getBolean("batch-mode"))
452: launchStart(genericApplication);
453: // wait until application returns
454: }
455: }
456:
457: protected LogFile createLogFile() {
458: java.io.File f = new java.io.File(getLogFilename());
459: LogFile logFile = new LogFile();
460: logFile.setFile(f);
461: logFile.open();
462: return logFile;
463: }
464:
465: protected String getLogFilename() {
466: String n = null;
467: n = getGenericApplication().getOptions().getString("logfile");
468: if (n == null) {
469: n = getDefaultLogFilename();
470: }
471: return n;
472: }
473:
474: protected String getDefaultLogFilename() {
475: String n = System.getProperties().getProperty(
476: "amoda.default.logfile", DEFAULT_LOGFILE);
477: return n;
478: }
479:
480: protected void initApplicationOptions(GenericApplication application) {
481: // add all system-options and features to the application, if not already specified explicitly
482: for (Iterator it = this .features.values().iterator(); it
483: .hasNext();) {
484: Feature f = (Feature) it.next();
485: Object alreadyExisting = application.get(f.getId(), false); //.getFeature(f.getId());
486: if (alreadyExisting == null) {
487: application.add(f); // genericApplication is subclass of CompositeGroup
488: }
489: }
490: for (Iterator it = this .options.getAll().values().iterator(); it
491: .hasNext();) {
492: Option o = (Option) it.next();
493: Object alreadyExisting = application.getOptions().get(
494: o.getId(), false);
495: if (alreadyExisting == null) {
496: ((GenericOptions) application.getOptions()).add(o);
497: }
498: }
499: setBatchCommands(Collections.singletonList(application
500: .getFeature("default"))); // maybe replace below
501: ArgsParser argsParser = getArgsParser();
502: if (argsParser != null) {
503: if (options.getBoolean("batch-mode")) { // TODO: will not work when running in GUIApplicationEnvironment, default value false will be used
504: Collection features = application
505: .getAvailableFeatures(); //new ArrayList();
506: /*for (Iterator it = application.getFeatures().iterator(); it.hasNext(); ) {
507: GenericFeature f = (GenericFeature)it.next();
508: if (!f.isSystem()) {
509: features.add(f);
510: }
511: }*/
512: Collection c = argsParser.parseBatchCommands(features); // Genericfeature also implements Command, so this makes sence
513: if (!c.isEmpty()) {
514: setBatchCommands(c);
515: }
516: }
517: GenericOptions options = (GenericOptions) application
518: .getOptions();
519: argsParser.parseOptions(options);
520: setInputValues(argsParser.parseInputValues());
521: }
522: // now, maybe an explicit -properties option is set
523: java.io.File file = application.getOptions().getFile(
524: "properties");
525: if ((file == null)
526: && (application.getOptions()
527: .getBoolean(CONFIGURATION_PERSISTENT_OPTIONS))) { // force to load if persistent-options=true
528: String filename = "./" + application.getId()
529: + ".properties";
530: file = new java.io.File(filename);
531: application
532: .getOptions()
533: .getOptionEntry("properties")
534: .getValue(
535: de.gulden.framework.amoda.model.option.Option.STATE_CURRENT)
536: .set(file);
537: }
538: if (file != null) {
539: ((GenericOptions) application.getOptions())
540: .loadFromProperties(file);
541: }
542: // re-run args parser to overwrite value with command line options
543: if (argsParser != null) {
544: argsParser.parseOptions((GenericOptions) application
545: .getOptions());
546: }
547: }
548:
549: protected String getPropertiesFilename() {
550: String n = null;
551: n = getGenericApplication().getOptions()
552: .getString("properties"); // ***** ??? already loaded ?!?
553: if (n == null) {
554: n = getDefaultPropertiesFilename();
555: }
556: return n;
557: }
558:
559: protected String getDefaultPropertiesFilename() {
560: String n = System.getProperties().getProperty(
561: "amoda.properties", DEFAULT_PROPERTIES);
562: return n;
563: }
564:
565: protected void prepareApplicationWelcome() {
566: // your code here
567: }
568:
569: protected void prepareApplicationStart() {
570: // your code here
571: }
572:
573: protected void launchStart(GenericApplication application) {
574: application.start();
575: }
576:
577: // ------------------------------------------------------------------------
578: // --- static methods ---
579: // ------------------------------------------------------------------------
580:
581: public static void main(String[] args) throws Exception {
582: String applicationClassname = System
583: .getProperty("application",
584: "de.gulden.framework.amoda.generic.GenericApplicationDummy");
585: String environmentFactoryClassname = System
586: .getProperty(
587: "application.environment.factory",
588: "de.gulden.framework.amoda.environment.commandline.CommandLineApplicationEnvironmentFactory");
589: invoke(applicationClassname, args, environmentFactoryClassname);
590: }
591:
592: public static void invoke(String applicationClassname,
593: String[] args, String environmentFactoryClassname)
594: throws Exception {
595: Application application = (Application) Toolbox
596: .instantiateClass(applicationClassname,
597: Application.class);
598: ApplicationEnvironmentFactory factory = (ApplicationEnvironmentFactory) Toolbox
599: .instantiateClass(environmentFactoryClassname,
600: ApplicationEnvironmentFactory.class);
601: invoke(application, args, factory);
602: }
603:
604: public static void invoke(Class applicationClass, String[] args,
605: Class environmentFactoryClass) throws Exception {
606: invoke((Application) applicationClass.newInstance(), args,
607: (ApplicationEnvironmentFactory) environmentFactoryClass
608: .newInstance());
609: }
610:
611: public static void invoke(Application application, String[] args,
612: ApplicationEnvironmentFactory environmentFactory) {
613: environmentFactory.setArgs(args);
614: environmentFactory.createApplicationEnvironment().launch(
615: application);
616: }
617:
618: public static URL getXMLResourceForClass(Class cls) {
619: String resName = cls.getName();
620: resName = resName.replace('.', '/');
621: resName += ".xml";
622: URL res = Toolbox.findResource(resName, cls.getClassLoader());
623: return res;
624: }
625:
626: } // end GenericApplicationEnvironment
|