View Javadoc

1   /*
2    * 
3    *  © Copyright 2005-2010, Mike Odling-Smee.  All rights reserved.
4    * 	
5    * 	Licensed under the Artistic License: 
6    * 	http://www.opensource.org/licenses/artistic-license.php
7    * 	
8    * Preamble
9    * 
10   *         The intent of this document is to state the conditions under which a 
11   *         Package may be copied, such that the Copyright Holder maintains some 
12   *         semblance of artistic control over the development of the package, while 
13   *         giving the users of the package the right to use and distribute the Package
14   * 	       in a more-or-less customary fashion, plus the right to make reasonable 
15   *         modifications.
16   * 
17   * Definitions:
18   * 
19   *         * "Package" refers to the collection of files distributed by the 
20   *         Copyright Holder, and derivatives of that collection of files created 
21   *         through textual modification. 
22   * 
23   *         * "Standard Version" refers to such a Package if it has not been modified, 
24   *         or has been modified in accordance with the wishes of the Copyright Holder.
25   * 
26   *         * "Copyright Holder" is whoever is named in the copyright or copyrights for
27   *         the package. 
28   * 
29   *         * "You" is you, if you're thinking about copying or distributing this Package.
30   * 
31   *         * "Reasonable copying fee" is whatever you can justify on the basis of 
32   *         media cost, duplication charges, time of people involved, and so on. 
33   *         (You will not be required to justify it to the Copyright Holder, but 
34   *         only to the computing community at large as a market that must bear the 
35   *         fee.) 
36   * 
37   *         * "Freely Available" means that no fee is charged for the item 
38   *         itself, though there may be fees involved in handling the item. It also 
39   *         means that recipients of the item may redistribute it under the same 
40   *         conditions they received it.
41   * 
42   * 	1. You may make and give away verbatim copies of the source form of the Standard 
43   * 	Version of this Package without restriction, provided that you duplicate all of 
44   * 	the original copyright notices and associated disclaimers.
45   * 	
46   * 	2. You may apply bug fixes, portability fixes and other modifications derived 
47   * 	from the Public Domain or from the Copyright Holder. A Package modified in such 
48   * 	a way shall still be considered the Standard Version.
49   * 	
50   * 	3. You may otherwise modify your copy of this Package in any way, provided that 
51   * 	you insert a prominent notice in each changed file stating how and when you 
52   * 	changed that file, and provided that you do at least ONE of the following:
53   * 	
54   * 		a) place your modifications in the Public Domain or otherwise make them 
55   * 		Freely Available, such as by posting said modifications to Usenet or an 
56   * 		equivalent medium, or placing the modifications on a major archive site such 
57   * 		as ftp.uu.net, or by allowing the Copyright Holder to include your modifications 
58   * 		in the Standard Version of the Package.
59   * 	
60   * 		b) use the modified Package only within your corporation or organization.
61   * 	
62   * 		c) rename any non-standard executables so the names do not conflict with 
63   * 		standard executables, which must also be provided, and provide a separate 
64   * 		manual page for each non-standard executable that clearly documents how it 
65   * 		differs from the Standard Version.
66   * 	
67   * 		d) make other distribution arrangements with the Copyright Holder.
68   * 	
69   * 	4. You may distribute the programs of this Package in object code or executable 
70   * 	form, provided that you do at least ONE of the following:
71   * 	
72   * 		a) distribute a Standard Version of the executables and library files, 
73   * 		together with instructions (in the manual page or equivalent) on where to 
74   * 		get the Standard Version.
75   * 	
76   * 		b) accompany the distribution with the machine-readable source of the 
77   * 		Package with your modifications.
78   * 	
79   * 		c) accompany any non-standard executables with their corresponding Standard 
80   * 		Version executables, giving the non-standard executables non-standard names, 
81   * 		and clearly documenting the differences in manual pages (or equivalent), 
82   * 		together with instructions on where to get the Standard Version.
83   * 	
84   * 		d) make other distribution arrangements with the Copyright Holder.
85   * 	
86   * 	5. You may charge a reasonable copying fee for any distribution of this Package. 
87   * 	You may charge any fee you choose for support of this Package. You may not 
88   * 	charge a fee for this Package itself. However, you may distribute this Package 
89   * 	in aggregate with other (possibly commercial) programs as part of a larger 
90   * 	(possibly commercial) software distribution provided that you do not advertise 
91   * 	this Package as a product of your own.
92   * 	
93   * 	6. The scripts and library files supplied as input to or produced as output from 
94   * 	the programs of this Package do not automatically fall under the copyright of 
95   * 	this Package, but belong to whomever generated them, and may be sold 
96   * 	commercially, and may be aggregated with this Package.
97   * 	
98   * 	7. C or perl subroutines supplied by you and linked into this Package shall not 
99   * 	be considered part of this Package.
100  * 	
101  * 	8. The name of the Copyright Holder may not be used to endorse or promote 
102  * 	products derived from this software without specific prior written permission.
103  * 	
104  * 	9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED 
105  * 	WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 
106  * 	MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
107  * 
108  * The End
109  */
110 package net.sourceforge.xuse;
111 
112 import java.io.BufferedReader;
113 import java.io.File;
114 import java.io.IOException;
115 import java.io.InputStreamReader;
116 import java.util.Arrays;
117 import java.util.List;
118 import java.util.Locale;
119 
120 import net.sourceforge.xuse.build.BuildException;
121 import net.sourceforge.xuse.build.StylesheetInvoker;
122 import net.sourceforge.xuse.build.XusePropertiesReader;
123 import net.sourceforge.xuse.log.Logger;
124 import net.sourceforge.xuse.tools.exporting.ExportFactory;
125 import net.sourceforge.xuse.tools.exporting.Exporter;
126 import net.sourceforge.xuse.tools.importing.ImportFactory;
127 import net.sourceforge.xuse.utils.CommandLineWrapper;
128 import net.sourceforge.xuse.utils.FileUtils;
129 import net.sourceforge.xuse.utils.XuseUtils;
130 
131 import com.xmlsolutions.annotation.Requirement;
132 import com.xmlsolutions.annotation.UseCase;
133 
134 @Requirement(traceTo="RQ61")
135 public class Xuse {
136 	
137 	private static final StylesheetInvoker XSL_INVOKER = StylesheetInvoker.getInstance();
138 	
139 	private static final String BUILD_ALL = "xuse";
140 	private static final String BUILD_HTML = "xuse:html";
141 	private static final String BUILD_HTML_DOCS = "xuse:documents-html";
142 	private static final String NEW_PROJECT = "xuse:new-project";
143 	private static final String UPGRADE = "xuse:upgrade";
144 	private static final String VALIDATE = "xuse:validate";
145 	private static final String PDF_USE_CASE = "xuse:pdf-use-case";
146 	private static final String PDF_USE_CASES = "xuse:pdf-use-cases";
147 	private static final String IMPORT_TRACE_REPORT = "xuse:import-trace-report";
148 	private static final String IMPORT_REQUIREMENTS = "xuse:import-requirements";
149 	private static final String EXPORT_REQUIREMENTS = "xuse:export-requirements";
150 	private static final String IMPORT_GLOSSARY = "xuse:import-glossary";
151 	private static final String HELP_1 = "-help";
152 	private static final String HELP_2 = "--help";
153 	private static final String HELP_3 = "-h";
154 	private static final String HELP_4 = "-man";
155 	private static final String HELP_5 = "man";
156 	private static final String HELP_6 = "help";
157 	private static final String[] ALL_HELP_COMMANDS = new String[] {HELP_1, HELP_2, HELP_3, HELP_4, HELP_5, HELP_6};
158 	private static final List<String> ALL_HELP_COMMANDS_LIST = Arrays.asList(ALL_HELP_COMMANDS);
159 	//private static final String GRAPH_REQUIREMENT = "xuse:graph-requirement";
160 	
161 	private static final String[] ALL_COMMANDS = new String[] {BUILD_ALL, BUILD_HTML, BUILD_HTML_DOCS, NEW_PROJECT, UPGRADE, VALIDATE, PDF_USE_CASE, PDF_USE_CASES, IMPORT_TRACE_REPORT, IMPORT_REQUIREMENTS, EXPORT_REQUIREMENTS,IMPORT_GLOSSARY, HELP_1};
162 	private static final List<String> ALL_COMMANDS_LIST = Arrays.asList(ALL_COMMANDS);
163 	
164 	public static void main(String[] args) {
165 		if (args != null && args.length > 0 && validArgZero(args[0])) {
166 			Xuse builder = new Xuse();
167 			builder.dispatchBuildRequest(args);
168 		} else {
169 			System.out.print("\n\nUsage: java net.sourceforge.xuse.Xuse | xuse.bat | xuse.sh | xuse");
170 			for (String command: ALL_COMMANDS) {
171 				System.out.print(" \n\t ");
172 				System.out.print(command);
173 			}
174 			System.out.println("\n\n\te.g. xuse xuse:new-project");
175 		}
176 	}
177 	
178 	private void dispatchBuildRequest(String args[]) throws BuildException {
179 		long startTime = System.currentTimeMillis();
180 		Locale locale = XusePropertiesReader.getLocaleOverride();
181 		if (locale != null) {
182 			Locale.setDefault(locale);
183 		}
184 		String goal = args[0];
185 		System.out.println("__  __              ");  
186 		System.out.println("// /// /_  _  ___ ___ ");  
187 		System.out.println(" >  <| || |(_-</ -_)");  
188 		System.out.println("/_///_////_,_|/__///___| v. " + net.sourceforge.xuse.build.Version.getFullVersion());  
189 		System.out.println();
190 		System.out.println();
191 		debugEnv(this);
192 		debugArgs(this, args);
193 		Logger.debug(this, XusePropertiesReader.debugProperties());
194 		if (ALL_HELP_COMMANDS_LIST.contains(goal)) {
195 			this.displayHelp();
196 		} else if (goal.equals(BUILD_ALL)) {
197 			this.xuse();
198 			this.displayExecutionTime(startTime);
199 		} else if (goal.equals(BUILD_HTML)) {
200 			this.xuseHtml();
201 			this.displayExecutionTime(startTime);
202 		}else if (goal.equals(BUILD_HTML_DOCS)) {
203 			this.xuseDocumentsHtml();
204 			this.displayExecutionTime(startTime);
205 		} else if (goal.equals(NEW_PROJECT)) {
206 			this.newProject();
207 			this.displayExecutionTime(startTime);
208 		} else if (goal.equals(VALIDATE)) {
209 			this.validateProject();
210 			this.displayExecutionTime(startTime);
211 		} else if (goal.equals(UPGRADE)) {
212 			this.upGrade();
213 			this.displayExecutionTime(startTime);
214 		} else if (goal.equals(PDF_USE_CASE)) {
215 			this.pdfUseCase(args[1]);
216 			this.displayExecutionTime(startTime);
217 		} else if (goal.equals(PDF_USE_CASES)) {
218 			this.pdfUseCases();
219 			this.displayExecutionTime(startTime);
220 		} else if (goal.equals(IMPORT_TRACE_REPORT)) {
221 			this.importTraceReport();
222 			this.displayExecutionTime(startTime);
223 		} else if (goal.equals(IMPORT_REQUIREMENTS)) {
224             this.importRequirements();
225             this.displayExecutionTime(startTime);
226         } else if (goal.equals(IMPORT_GLOSSARY)) {
227             this.importGlossary();
228             this.displayExecutionTime(startTime);
229         } else if (goal.equals(EXPORT_REQUIREMENTS)) {
230             this.exportRequirements();
231             this.displayExecutionTime(startTime);
232         }//else if (goal.equals(GRAPH_REQUIREMENT)) {
233 			//this.graphRequirement(args[1]);
234 		//} 
235         else {
236         	Logger.error(this, "Goal: " + goal + " was not recognised");
237         	System.exit(-1);
238         }		
239 		this.processPerformanceResults();
240 	}
241 	
242 	private void displayExecutionTime(long startTime) {
243 		long processingTime = (System.currentTimeMillis() - startTime) / 1000;
244 		int minutes = (int)Math.floor(processingTime / 60);
245 		int seconds = (int)Math.floor(processingTime - (60 * minutes));
246 		Logger.info(this, "Processing complete in " + minutes + " mins "+ seconds + " seconds");
247 	}
248 	
249 	public void displayHelp() {
250 	    System.out.println("Help: todo");
251 	}
252 	
253 	private void processPerformanceResults() {
254 		Logger.debug(this, "in processPerformanceResults()");
255 		XSL_INVOKER.processPerformanceResults();
256 	}
257 	
258 	public void xuse() throws BuildException {
259 		Logger.debug(this, "In xuse()");
260 		this.xuseHtml();
261 		this.xusePdf();
262 	}
263 	
264 	public void xusePdf() throws BuildException {
265 		Logger.debug(this, "In xusePdf()");
266 		this.pdfUseCases();
267 	}
268 	
269 	@Requirement(traceTo={"RQ19", "RQ60"})
270 	@UseCase(traceTo={"UC2"})
271 	public void xuseHtml() throws BuildException {
272 		Logger.debug(this, "In xuseHtml()");
273 		try {
274 			this.xuseDocumentsHtml();
275 			XSL_INVOKER.invokeBuildHTMLSite();
276 		} catch (Throwable t) {
277 			throw new BuildException("Error building site", t);
278 		}
279 	}
280 	
281 	@Requirement(traceTo={"RQ19", "RQ60"})
282 	public void xuseDocumentsHtml() throws BuildException {
283 		Logger.debug(this, "In xuseDocumentsHtml()");
284 		try {
285 			FileUtils.extractStyleSheets();
286 			FileUtils.extractResources();
287 			FileUtils.copyHTMLResources(XusePropertiesReader.getOutputDirectory());
288 			FileUtils.extractSchemas();
289 			XSL_INVOKER.invokeBuildHTMLDocuments();
290 		} catch (Throwable t) {
291 			throw new BuildException("Error building site", t);
292 		}
293 	}
294 	
295 	@Requirement(traceTo={"RQ40"})
296 	public void newProject() throws BuildException {
297 		Logger.debug(this, "In newProject()");
298 		try {
299 			FileUtils.extractTemplateProject();
300 		} catch (Throwable t) {
301 			throw new BuildException("Error copying resources", t);
302 		}
303 	}
304 	
305 	@Requirement(traceTo={"RQ48"})
306 	public void validateProject() throws BuildException {
307 		Logger.debug(this, "In validateProject()");
308 		try {
309 			FileUtils.extractStyleSheets();
310 			FileUtils.extractSchemas();
311 			XSL_INVOKER.invokeValidateProject();
312 		} catch (Throwable t) {
313 			throw new BuildException("Error validating project", t);
314 		}
315 	}
316 	
317 	@Requirement(traceTo={"RQ3", "RQ58"})
318 	public void pdfUseCases() throws BuildException {
319 		Logger.debug(this, "In pdfUseCases()");
320 		try {
321 			FileUtils.extractStyleSheets();
322 			FileUtils.extractResources();
323 			XSL_INVOKER.invokePDFUseCases();
324 		} catch (Throwable t) {
325 			throw new BuildException("Error creating pdf of use-case", t);
326 		} 
327 	}
328 	
329 	public void importTraceReport() throws BuildException {
330 		Logger.debug(this, "In importTraceReport()");
331 	    try {
332 			FileUtils.extractStyleSheets();
333 			FileUtils.extractResources();
334 			XSL_INVOKER.invokeImportTraceReport();
335 		} catch (Throwable t) {
336 			throw new BuildException("Error importing trace report", t);
337 		} 	        
338 	}
339 	
340 	public void importRequirements() throws BuildException {
341 		Logger.debug(this, "In importRequirements()");
342 		try {
343 			FileUtils.extractStyleSheets();
344 			ImportFactory.newRequirementsInstance().importContent();
345 	    } catch (Throwable t) {
346 	    	throw new BuildException("Error importing requirements", t);
347 	    } 
348 	}
349 	
350 	public void importGlossary() throws BuildException {
351 		Logger.debug(this, "In importGlossary()");
352 		try {
353 			FileUtils.extractStyleSheets();
354 			ImportFactory.newGlossaryInstance().importContent();
355 	    } catch (Throwable t) {
356 	    	throw new BuildException("Error importing requirements", t);
357 	    } 
358 	}
359 	
360 	public void exportRequirements() throws BuildException {
361 		Logger.debug(this, "In exportRequirements()");
362         try {
363         	FileUtils.extractStyleSheets();
364             Exporter exporter = ExportFactory.newInstance();
365             exporter.exportRequirements();
366         } catch (Throwable t) {
367             throw new BuildException("Error exporting requirements", t);
368         } 
369     }
370 	
371 	@Requirement(traceTo={"RQ3", "RQ58"})
372 	public void pdfUseCase(String useCaseId) throws BuildException {
373 		Logger.debug(this, "In pdfUseCase()");
374 		try {
375 			FileUtils.extractStyleSheets();
376 			FileUtils.extractResources();
377 			XSL_INVOKER.invokePDFSingleUseCase(useCaseId);
378 		} catch (Throwable t) {
379 			throw new BuildException("Error creating pdf of use-case", t);
380 		} 
381 	}
382 	
383 	public void graphRequirement(String requirementId) throws BuildException {
384 		Logger.debug(this, "In graphRequirement()");
385 		if (CommandLineWrapper.graphVizAvailable()) {
386 			try {
387 				FileUtils.extractStyleSheets();
388 				FileUtils.extractResources();
389 				XSL_INVOKER.invokeGraphRequirement(requirementId);
390 			} catch (Throwable t) {
391 				throw new BuildException("Error graphing requirement " + requirementId, t);
392 			}
393 		} else {
394 			throw new BuildException("Please install the graphics utility Graphiz - graphing the requirements depends on this layout engine.");
395 		}
396 	}
397 	
398 	@Requirement(traceTo={"RQ20"})
399 	public void upGrade() throws BuildException {
400 		Logger.debug(this, "In upGrade()");
401 		BufferedReader br = null;
402 		try {
403 			System.out.print("Upgrading your project - It is strongly recommended that you back up your files to a safe location before running this command: continue?(y,n)");
404 			br = new BufferedReader(new InputStreamReader(System.in));
405 			String line = br.readLine();
406 			if (line.equalsIgnoreCase("y")) {
407 				File baseDir = new File(System.getProperty("user.dir"));
408 				File stakeholderFile = new File(baseDir, XusePropertiesReader.getStakeholders());
409 				FileUtils.extractResourceFromJar(XusePropertiesReader.getTemplateProjectPath() + "/" + XusePropertiesReader.getRequirementsDir(), "stakeholders.xml", stakeholderFile);
410 				FileUtils.copyDirectory(XusePropertiesReader.getTemplateProjectPath() + "/src/resources", new File(baseDir, "src/resources"), false);
411 				FileUtils.extractStyleSheets();
412 				XSL_INVOKER.invokeUpgrade();
413 				//TODO: There seems to be an intermittent file lock on the repository file
414 				//Force garbage collection and wait a while
415 				System.gc();
416 				Thread.sleep(5000);
417 				//Archive existing files
418 				XuseUtils.archiveUseCases();
419 				XuseUtils.renameUpgradedCases();
420 				XuseUtils.archiveRequirements();
421 				XuseUtils.renameUpgradedRequirements();
422 			} else {
423 				System.out.println("Upgrade aborted by user....");
424 				System.exit(-1);
425 			}
426 		} catch (Throwable t) {
427 			throw new BuildException("Error upgrading", t);
428 		} finally {
429 			if (br != null) {
430 				try {
431 					br.close();
432 				} catch (IOException e) {
433 					throw new BuildException("Could not close buffered reader", e);
434 				}
435 			}
436 		}
437 	}
438 	
439 	private static boolean validArgZero(String arg) {
440 		return arg != null && (ALL_COMMANDS_LIST.contains(arg) || ALL_HELP_COMMANDS_LIST.contains(arg));
441 	}
442 	
443 	private static void debugArgs(Object clazzInstance, String[] args) {
444 		if (args != null) {
445 			int index = 0;
446 			for (String arg : args) {
447 				Logger.debug(clazzInstance, "[" + index + "] " + arg);
448 				index++;
449 			}
450 		}
451 	}
452 	
453 	private static void debugEnv(Object clazzInstance) {
454 		Logger.debug(clazzInstance, "Using " + net.sf.saxon.Version.getProductName() + " version: " + net.sf.saxon.Version.getProductVersion() + ", released: " + net.sf.saxon.Version.getReleaseDate());
455 		Logger.debug(clazzInstance, "Environment settings");
456 		Logger.debug(clazzInstance, "-------------------------------------------------------------");
457 		Logger.debug(clazzInstance, "File encoding\t\t" + System.getProperty("file.encoding"));
458 		Logger.debug(clazzInstance, "File encoding package\t\t" + System.getProperty("file.encoding.pkg"));
459 		Logger.debug(clazzInstance, "File separator\t\t" + System.getProperty("file.separator"));
460 		Logger.debug(clazzInstance, "Classpath\t\t" + System.getProperty("java.class.path"));
461 		//Logger.debug(clazzInstance, "Class version\t\t" + System.getProperty("java.class.version"));
462 		//Logger.debug(clazzInstance, "Java Compiler\t\t" + System.getProperty("java.compiler"));
463 		Logger.debug(clazzInstance, "JAVA_HOME\t\t" + System.getProperty("java.home"));
464 		//Logger.debug(clazzInstance, "Java IO tmp dir\t\t" + System.getProperty("java.io.tmpdir"));
465 		Logger.debug(clazzInstance, "Java version\t\t" + System.getProperty("java.version"));
466 		Logger.debug(clazzInstance, "Java Vendor\t\t" + System.getProperty("java.vendor"));
467 		Logger.debug(clazzInstance, "Java Vendor URL\t\t" + System.getProperty("java.vendor.url"));
468 		Logger.debug(clazzInstance, "Line Seperator\t\t" + System.getProperty("line.separator"));
469 		Logger.debug(clazzInstance, "OS Name\t\t" + System.getProperty("os.name"));
470 		Logger.debug(clazzInstance, "OS Arch\t\t" + System.getProperty("os.arch"));
471 		Logger.debug(clazzInstance, "OS Version\t\t" + System.getProperty("os.version"));
472 		Logger.debug(clazzInstance, "Path Separator\t\t" + System.getProperty("path.separator"));
473 		Logger.debug(clazzInstance, "User dir\t\t" + System.getProperty("user.dir"));
474 		//Logger.debug(clazzInstance, "User home\t\t" + System.getProperty("user.home"));
475 		//Logger.debug(clazzInstance, "User name\t\t" + System.getProperty("user.name"));
476 		Logger.debug(clazzInstance, "User region\t\t" + System.getProperty("user.region"));
477 		Logger.debug(clazzInstance, "User timezone\t\t" + System.getProperty("user.timezone"));
478 		Logger.debug(clazzInstance, "-------------------------------------------------------------");
479 	}
480 
481 }