001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.tools.patternengine;
051:
052: import java.lang.reflect.*;
053: import java.util.*;
054: import java.net.*;
055: import java.io.*;
056: import org.webmacro.*;
057: import org.jaffa.datatypes.DateTime;
058: import org.jaffa.util.URLHelper;
059: import org.jaffa.tools.common.SourceDecomposerUtils;
060: import org.jaffa.tools.common.SourceDecomposerException;
061: import org.jaffa.util.DefaultEntityResolver;
062: import org.jaffa.util.DefaultErrorHandler;
063: import org.jaffa.util.XmlHelper;
064: import javax.xml.parsers.DocumentBuilderFactory;
065: import javax.xml.parsers.DocumentBuilder;
066: import org.w3c.dom.Document;
067: import org.w3c.dom.Element;
068: import org.w3c.dom.Node;
069: import org.w3c.dom.NodeList;
070: import javax.xml.parsers.ParserConfigurationException;
071: import org.xml.sax.SAXException;
072:
073: /** Use this class to perform code generation based on the input pattern meta data file.
074: */
075: public class PatternGenerator {
076: // property files used
077: private static final String PATTERN_GENERATOR_PROPERTIES_FILE = "patterns/PatternGenerator.properties";
078: private static final String WEB_MACRO_PROPERTIES_FILE = "patterns/WebMacro.properties";
079:
080: // log files created
081: private static final String AUDIT_LOG_FILE = "audit.log";
082:
083: // PatternGenerator properties
084: private static final String PROPERTY_PROJECT_ROOT_DIRECTORY = "ProjectRootDirectory";
085: private static final String PROPERTY_TEMP_META_DIRECTORY = "TempMetaDataDirectory";
086: private static final String PROPERTY_LOG_DIRECTORY = "LogDirectory";
087:
088: // XML elements referenced
089: private static final String XML_PATTERN_TEMPLATE = "PatternTemplate";
090: private static final String XML_DATE_TIME = "DateTime";
091: private static final String XML_PREREQUESITES = "PreRequesites";
092: private static final String XML_COMPONENTS = "Components";
093: private static final String XML_FILE_NAME = "FileName";
094: private static final String XML_PACKAGE = "Package";
095: private static final String XML_TEMPLATE = "Template";
096: private static final String XML_OVERRIDE = "Override";
097: private static final String XML_GENERATE = "Generate";
098: private static final String XML_GENERATE_TYPE = "Type";
099: private static final String XML_GENERATE_WORKING_DIR = "WorkingDirectory";
100: private static final String XML_GENERATE_COMMAND_LINE = "CommandLine";
101: private static final String XML_GENERATE_CLASS_NAME = "ClassName";
102: private static final String XML_GENERATE_ARGUMENTS = "Arguments";
103: private static final String XML_SCRATCHPAD_FOR_WM = "ScratchPad";
104:
105: // fields
106: private URL m_patternMetaData = null;
107: private Properties m_pgProperties = null;
108: private String m_auditFile = null;
109: private WebMacro m_wm = null;
110:
111: /** Creates new PatternGenerator.
112: * @param patternMetaData the pattern meta data file to be used for code generation.
113: * @throws PatternGeneratorException if any error occurs.
114: */
115: public PatternGenerator(URL patternMetaData)
116: throws PatternGeneratorException {
117: try {
118: // initializations
119: doInit(patternMetaData);
120: } catch (PatternGeneratorException e) {
121: throw e;
122: } catch (Exception e) {
123: throw new PatternGeneratorException(e);
124: }
125: }
126:
127: /** This method is to be invoked, when done with the code generation. It will free up the resources.
128: */
129: public void destroy() {
130: if (m_wm != null) {
131: m_wm.destroy();
132: m_wm = null;
133: }
134:
135: if (m_pgProperties != null) {
136: m_pgProperties.clear();
137: m_pgProperties = null;
138: }
139: }
140:
141: private void doInit(URL patternMetaData)
142: throws PatternGeneratorException, IOException,
143: WebMacroException, ParserConfigurationException,
144: SAXException, MalformedURLException {
145: // set the field m_patternMetaData
146: m_patternMetaData = patternMetaData;
147:
148: // set the field - m_pgProperties
149: URL pgUrl = URLHelper
150: .newExtendedURL(PATTERN_GENERATOR_PROPERTIES_FILE);
151: m_pgProperties = getProperties(pgUrl);
152:
153: // set the field - m_auditFile
154: String logDir = m_pgProperties
155: .getProperty(PROPERTY_LOG_DIRECTORY);
156: if (logDir != null && !logDir.equals("")) {
157: m_auditFile = getAbsoluteFileName(logDir, AUDIT_LOG_FILE);
158: }
159:
160: // Startup WebMacro
161: m_wm = new WM(WEB_MACRO_PROPERTIES_FILE);
162: }
163:
164: private Properties getProperties(URL url) throws IOException,
165: PatternGeneratorException {
166: Properties properties = new Properties();
167: InputStream in = url.openStream();
168: properties.load(in);
169: in.close();
170: if (properties.isEmpty())
171: throw new PatternGeneratorException(
172: "Could not load properties: " + url);
173: return properties;
174: }
175:
176: private String getAbsoluteFileName(String dirName, String fileName) {
177: File file = new File(dirName, fileName);
178: return file.getAbsolutePath();
179: }
180:
181: /** This will invoke the Pattern Generation routine.
182: * @throws PatternGeneratorException if any error occurs.
183: */
184: public void processPattern() throws PatternGeneratorException {
185: try {
186: // Step 1 - Get the patternTemplate from m_patternMetaData
187: // Note: The XML should not be validated.. since it may contain WebMacro script variables
188: String patternTemplate = null;
189: DocumentBuilderFactory factory = DocumentBuilderFactory
190: .newInstance();
191: factory.setValidating(false);
192: DocumentBuilder parser = factory.newDocumentBuilder();
193: parser.setEntityResolver(new DefaultEntityResolver());
194: parser.setErrorHandler(new DefaultErrorHandler());
195: Document document = parser.parse(m_patternMetaData
196: .getFile());
197: NodeList nodes = document
198: .getElementsByTagName(XML_PATTERN_TEMPLATE);
199: if (nodes != null && nodes.getLength() > 0) {
200: Node node = nodes.item(0);
201: patternTemplate = XmlHelper.getTextTrim(node);
202: }
203: if (patternTemplate == null || patternTemplate.equals(""))
204: throw new PatternGeneratorException(
205: "The "
206: + XML_PATTERN_TEMPLATE
207: + " element is not supplied in the input Meta Data File");
208:
209: // Step2 - Generate the TemporaryMetaDataFile from patternTemplate + m_patternMetaData
210: Context context = getContextWithData();
211: String tempFileName = process1(patternTemplate, (new File(
212: m_patternMetaData.getFile())).getName(), context);
213:
214: // Step3 - Generate the source code files
215: process2(tempFileName, context);
216:
217: } catch (PatternGeneratorException e) {
218: throw e;
219: } catch (Exception e) {
220: throw new PatternGeneratorException(e);
221: } finally {
222: destroy();
223: }
224: }
225:
226: private Context getContextWithData()
227: throws ParserConfigurationException, SAXException,
228: IOException, PatternGeneratorException {
229: // parse the metaData.. Force XML validation
230: Map metaDataMap = DomParser.parse(m_patternMetaData.getFile(),
231: true);
232:
233: // strip off the root element from the metaDataMap
234: metaDataMap = stripRoot(metaDataMap);
235: if (metaDataMap == null)
236: throw new PatternGeneratorException("PatternMetaData file "
237: + m_patternMetaData.getFile()
238: + " is incorrectly formatted");
239:
240: // copy metaDataMap to context
241: Context context = m_wm.getContext();
242: for (Iterator itr = metaDataMap.entrySet().iterator(); itr
243: .hasNext();) {
244: Map.Entry me = (Map.Entry) itr.next();
245: context.put(me.getKey(), me.getValue());
246: }
247:
248: // Add some static data to the context
249: context.put(XML_DATE_TIME, new DateTime());
250: context.put(PROPERTY_PROJECT_ROOT_DIRECTORY, m_pgProperties
251: .getProperty(PROPERTY_PROJECT_ROOT_DIRECTORY));
252:
253: // This is used by the WM template to put temporary data in a scratchpad Map...
254: context.put(XML_SCRATCHPAD_FOR_WM, new HashMap());
255: return context;
256: }
257:
258: private Map stripRoot(Map input) {
259: Map output = null;
260: Iterator itr = input.values().iterator();
261: if (itr.hasNext()) {
262: Object obj = itr.next();
263: if (obj instanceof Map)
264: output = (Map) obj;
265: }
266: return output;
267: }
268:
269: // Generates tempFileName
270: // Modifies the input object context !!!
271: private String process1(String patternTemplate,
272: String patternMetaData, Context context)
273: throws IOException, WebMacroException {
274: // write the Output to the temp folder using WebMacro
275: String tempFileName = getAbsoluteFileName(m_pgProperties
276: .getProperty(PROPERTY_TEMP_META_DIRECTORY),
277: patternMetaData);
278: writeWm(patternTemplate, context, tempFileName);
279:
280: // append to the audit.log
281: String log = '\n' + new DateTime().toString()
282: + " - Processing PatternTemplate: " + patternTemplate
283: + " using PatternMetaData: " + patternMetaData + '\n'
284: + "Created temporary file: " + tempFileName;
285: write(m_auditFile, log, true);
286:
287: return tempFileName;
288: }
289:
290: private void process2(String tempFileName, Context context)
291: throws PatternGeneratorException,
292: ParserConfigurationException, SAXException, IOException,
293: WebMacroException, SourceDecomposerException {
294: // parse the tempFileName.. Force XML validation
295: DocumentBuilderFactory factory = DocumentBuilderFactory
296: .newInstance();
297: factory.setValidating(true);
298: DocumentBuilder parser = factory.newDocumentBuilder();
299: parser.setEntityResolver(new DefaultEntityResolver());
300: parser.setErrorHandler(new DefaultErrorHandler());
301: Document document = parser.parse(tempFileName);
302:
303: // check for Prerequisites
304: // @todo : this currently only supports java files.. Need to enhance this logic to support other files too !!
305: String preReqErrLog = null;
306: Node preReq = document.getElementsByTagName(XML_PREREQUESITES)
307: .item(0);
308: NodeList classes = preReq.getChildNodes();
309: if (classes != null) {
310: for (int i = 0; i < classes.getLength(); i++) {
311: Node clazz = classes.item(i);
312: if (clazz.getNodeType() == Node.ELEMENT_NODE) {
313: String requiredClassName = XmlHelper
314: .getTextTrim(clazz);
315: try {
316: Class.forName(requiredClassName);
317: } catch (ClassNotFoundException e) {
318: if (preReqErrLog == null)
319: preReqErrLog = "";
320: preReqErrLog += "Error: PreRequesite Class "
321: + requiredClassName + " not found\n";
322: }
323: }
324: }
325: }
326: if (preReqErrLog != null) {
327: write(m_auditFile, preReqErrLog, true);
328: throw new PatternGeneratorException(preReqErrLog);
329: }
330:
331: // loop through each Component
332: Node components = document.getElementsByTagName(XML_COMPONENTS)
333: .item(0);
334: NodeList buildNodes = components.getChildNodes();
335: for (int i = 0; i < buildNodes.getLength(); i++) {
336: Node buildNode = buildNodes.item(i);
337: if (buildNode.getNodeType() != Node.ELEMENT_NODE)
338: continue;
339: Element build = (Element) buildNode;
340: String fileName = XmlHelper.getTextTrim(build
341: .getElementsByTagName(XML_FILE_NAME).item(0));
342: String packageName = XmlHelper.getTextTrim(build
343: .getElementsByTagName(XML_PACKAGE).item(0));
344: String templateName = XmlHelper.getTextTrim(build
345: .getElementsByTagName(XML_TEMPLATE).item(0));
346: String override = XmlHelper.getTextTrim(build
347: .getElementsByTagName(XML_OVERRIDE).item(0));
348: boolean fileExists = false;
349: context.put(XML_FILE_NAME, fileName);
350: context.put(XML_PACKAGE, packageName);
351:
352: // rootDirectory + package
353: String dirName = getDirectoryName(m_pgProperties
354: .getProperty(PROPERTY_PROJECT_ROOT_DIRECTORY),
355: packageName);
356:
357: // create the file to be created
358: fileName = dirName + File.separatorChar + fileName;
359:
360: // check if it already exists
361: File f = new File(fileName);
362: if (f.exists() && f.isFile())
363: fileExists = true;
364:
365: if (!fileExists) {
366: createFile(templateName, context, fileName);
367: write(m_auditFile, "Created: " + fileName, true);
368: } else {
369: // ask the user what to do in case the file already exists
370: if (override.equalsIgnoreCase("ask"))
371: override = askUser(fileName);
372:
373: if (override.equalsIgnoreCase("no")
374: || override.equalsIgnoreCase("false")) {
375: write(m_auditFile, "Left untouched: " + fileName,
376: true);
377: } else if (override.equalsIgnoreCase("yes")
378: || override.equalsIgnoreCase("true")) {
379: createFile(templateName, context, fileName);
380: write(m_auditFile, "Recreated: " + fileName, true);
381: } else if (override.equalsIgnoreCase("merge")) {
382: mergeFile(templateName, context, fileName);
383: write(m_auditFile,
384: "Recreated with existing customizations: "
385: + fileName, true);
386: } else if (override
387: .equalsIgnoreCase("OverrideIfMarkerPresent")) {
388: if (SourceDecomposerUtils
389: .isJaffaOverwriteMarkerPresent(f)) {
390: // Override only if the marker is still present in the file.
391: // Absence of the marker indicates that the file has been customized
392: createFile(templateName, context, fileName);
393: write(m_auditFile, "Recreated: " + fileName,
394: true);
395: } else {
396: write(m_auditFile, "Left untouched: "
397: + fileName, true);
398: }
399: } else if (override
400: .equalsIgnoreCase("OverrideIfMarkerPresentOrCreateTempFileIfMarkerAbsent")) {
401: if (SourceDecomposerUtils
402: .isJaffaOverwriteMarkerPresent(f)) {
403: // Override only if the marker is still present in the file.
404: // Absence of the marker indicates that the file has been customized
405: createFile(templateName, context, fileName);
406: write(m_auditFile, "Recreated: " + fileName,
407: true);
408: } else {
409: // Leave the existing file as is, but create a temp file with a '.new' extension
410: String newFileName = fileName + ".new";
411: createFile(templateName, context, newFileName);
412: write(m_auditFile, "Created Temp File: "
413: + newFileName, true);
414: }
415: } else {
416: write(m_auditFile,
417: "ERROR: Unknown override option '"
418: + override + "' passed for file "
419: + fileName + ". Nothing done", true);
420: continue;
421: }
422: }
423:
424: // Execute the Generate Command if any...
425: processGenerate(build);
426: }
427: }
428:
429: private String askUser(String fileName) throws IOException {
430: System.out.println("File '" + fileName + "' already exists..");
431: System.out
432: .println("1 - Leave It Alone / 2 - Overwrite / 3 - Merge / 4 - OverrideIfMarkerPresent / 5 - OverrideIfMarkerPresentOrCreateTempFileIfMarkerAbsent ?");
433: System.out.flush();
434:
435: String s;
436: BufferedReader in = new BufferedReader(new InputStreamReader(
437: System.in));
438: while (true) {
439: s = in.readLine();
440: if (s.equals("1")) {
441: s = "false";
442: break;
443: } else if (s.equals("2")) {
444: s = "true";
445: break;
446: } else if (s.equals("3")) {
447: s = "merge";
448: break;
449: } else if (s.equals("4")) {
450: s = "OverrideIfMarkerPresent";
451: break;
452: } else if (s.equals("5")) {
453: s = "OverrideIfMarkerPresentOrCreateTempFileIfMarkerAbsent";
454: break;
455: } else {
456: System.out.println("Enter either 1, 2, 3, 4 or 5");
457: }
458: }
459: return s;
460: }
461:
462: private void createFile(String templateName, Context context,
463: String fileName) throws WebMacroException, IOException,
464: PatternGeneratorException {
465: // create the file
466: writeWm(templateName, context, fileName);
467: }
468:
469: private void mergeFile(String templateName, Context context,
470: String fileName) throws WebMacroException, IOException,
471: PatternGeneratorException, SourceDecomposerException {
472: // get the new contents
473: ByteArrayOutputStream bos = new ByteArrayOutputStream();
474: writeWm(templateName, context, bos);
475: String newContents = bos.toString();
476:
477: // merge the contents
478: String mergedContents = SourceMerge.performMerge(
479: new BufferedReader(new StringReader(newContents)),
480: new BufferedReader(new FileReader(fileName)));
481:
482: // write to the file
483: Writer writer = new BufferedWriter(new FileWriter(fileName));
484: writer.write(mergedContents);
485: writer.flush();
486: writer.close();
487: }
488:
489: private String getDirectoryName(String rootDir, String packageName) {
490: // Remove the '.' from the package
491: String packageNameToDir = packageName.replace('.',
492: File.separatorChar);
493:
494: // Append the new package to the rootDir
495: if (rootDir.endsWith(File.separator))
496: rootDir = rootDir + packageNameToDir;
497: else
498: rootDir = rootDir + File.separatorChar + packageNameToDir;
499:
500: // Create directoryName if it doesn't already exist
501: File dir = new File(rootDir);
502: if (!dir.isDirectory())
503: dir.mkdirs();
504:
505: return dir.getAbsolutePath();
506: }
507:
508: private void writeWm(String templateFileName, Context context,
509: String outputFileName) throws WebMacroException,
510: IOException {
511: writeWm(templateFileName, context, new FileOutputStream(
512: outputFileName));
513: }
514:
515: private void writeWm(String templateFileName, Context context,
516: OutputStream outputStream) throws WebMacroException,
517: IOException {
518: Template template = m_wm.getTemplate(templateFileName);
519: // FastWriter out = new FastWriter(new BufferedOutputStream( new FileOutputStream(outputFileName) ),
520: // FastWriter.SAFE_UNICODE_ENCODING);
521: FastWriter out = new FastWriter(m_wm.getBroker(),
522: new BufferedOutputStream(outputStream),
523: FastWriter.SAFE_UNICODE_ENCODING);
524: template.write(out, context);
525: out.close();
526: }
527:
528: private void write(String fileName, String message, boolean append)
529: throws IOException {
530: if (fileName != null && !fileName.equals("") && message != null
531: && !message.equals("")) {
532: PrintWriter out = null;
533: if (append)
534: out = new PrintWriter(new FileWriter(fileName, true));
535: else
536: out = new PrintWriter(new FileWriter(fileName));
537: out.println(message);
538: out.close();
539: }
540: }
541:
542: private void processGenerate(Element build) throws IOException {
543: NodeList list = build.getElementsByTagName(XML_GENERATE);
544: if (list != null && list.getLength() > 0) {
545: Element generate = (Element) list.item(0);
546: String type = XmlHelper.getTextTrim(generate
547: .getElementsByTagName(XML_GENERATE_TYPE).item(0));
548: if ("OS".equalsIgnoreCase(type)) {
549: String workingDir = XmlHelper.getTextTrim(generate
550: .getElementsByTagName(XML_GENERATE_WORKING_DIR)
551: .item(0));
552: String command = XmlHelper
553: .getTextTrim(generate.getElementsByTagName(
554: XML_GENERATE_COMMAND_LINE).item(0));
555: Process process = Runtime.getRuntime().exec(command,
556: null, new File(workingDir));
557:
558: // wait for the command to be completed
559: try {
560: process.waitFor();
561: } catch (InterruptedException e) {
562: // dont do anything
563: }
564: write(m_auditFile, "OS: Executed " + command
565: + " with the working dir " + workingDir, true);
566:
567: } else if ("JAVA".equalsIgnoreCase(type)) {
568: String className = XmlHelper.getTextTrim(generate
569: .getElementsByTagName(XML_GENERATE_CLASS_NAME)
570: .item(0));
571: String arguments = XmlHelper.getTextTrim(generate
572: .getElementsByTagName(XML_GENERATE_ARGUMENTS)
573: .item(0));
574: try {
575: // get a handle on the 'public static void main(String[])' method of the class
576: Class clazz = Class.forName(className);
577: Method main = clazz.getMethod("main",
578: new Class[] { String[].class });
579: int mod = main.getModifiers();
580: if (Modifier.isStatic(mod)) {
581: // convert the arguments into a string-array
582: StringTokenizer stz = new StringTokenizer(
583: arguments, " ");
584: String[] argumentArray = new String[stz
585: .countTokens()];
586: int i = -1;
587: while (stz.hasMoreTokens())
588: argumentArray[++i] = stz.nextToken();
589:
590: // execute the method
591: main.invoke(null,
592: new Object[] { argumentArray });
593: write(m_auditFile, "JAVA: Executed class "
594: + className + ", using the arguments "
595: + arguments, true);
596: } else {
597: write(
598: m_auditFile,
599: "JAVA Error: The 'public static void main(String[] args)' method not found for the class "
600: + className, true);
601: }
602: } catch (ClassNotFoundException e) {
603: write(m_auditFile, "JAVA Error: Class " + className
604: + " not found", true);
605: } catch (NoSuchMethodException e) {
606: write(
607: m_auditFile,
608: "JAVA Error: The 'public static void main(String[] args)' method not found for the class "
609: + className, true);
610: } catch (IllegalAccessException e) {
611: write(m_auditFile,
612: "JAVA Error: IllegalAccessException thrown while executing class "
613: + className, true);
614: } catch (InvocationTargetException e) {
615: write(m_auditFile,
616: "JAVA Error: InvocationTargetException thrown while executing class "
617: + className, true);
618: }
619:
620: } else {
621: write(m_auditFile, "Error: UnSupported Generate Type "
622: + type, true);
623: }
624: }
625: }
626:
627: /** This will create an instance of the PatternGenerator, passing the URL corresponding to the input argument.
628: * It will then invoke the 'processPattern()' method.
629: * If the argument is a directory, then the above process will be invoked for each file in the directory.
630: * If the '-r' argument is passed, then it will recursively scan the directory for files, and invoke the pattern generation for each file.
631: * @param args This expects at least one argument to be passed in. This should represent the patternMetaData file, relative to the classpath. If a directory of passed, then the optional second argument determines, if a recursive search is to be performed on the directory.
632: */
633: public static void main(String[] args) {
634: if (args.length < 1 || args.length > 2
635: || (args.length == 2 && !args[1].equals("-r")))
636: usage();
637:
638: // check if the input is a directory
639: File dir = new File(args[0]);
640: if (dir.exists() && dir.isDirectory()) {
641: // loop thru all the files of the directory.
642: executePatternGenerator(dir, args.length == 2 ? true
643: : false);
644: } else {
645: // try to get it off the classpath and check again if its a directory
646: try {
647: URL url = URLHelper.newExtendedURL(args[0]);
648: File f = new File(url.getFile());
649: if (f.exists() && f.isDirectory())
650: executePatternGenerator(f, args.length == 2 ? true
651: : false);
652: else
653: executePatternGenerator(args[0]);
654: } catch (MalformedURLException e) {
655: e.printStackTrace();
656: System.out
657: .println("The pattern meta data file not found: "
658: + args[0]);
659: }
660: }
661:
662: }
663:
664: private static void executePatternGenerator(File dir,
665: boolean recursive) {
666: File[] files = dir.listFiles();
667: for (int i = 0; i < files.length; i++) {
668: System.out.flush();
669: File file = files[i];
670: if (file.isFile())
671: executePatternGenerator(file.getAbsolutePath());
672: else if (file.isDirectory() && recursive)
673: executePatternGenerator(file, recursive);
674: }
675: }
676:
677: private static void executePatternGenerator(String resourceName) {
678: PatternGenerator pg = null;
679: try {
680: URL patternMetaData = URLHelper
681: .newExtendedURL(resourceName);
682: System.out
683: .println("Processing the pattern meta data file: "
684: + resourceName + '(' + patternMetaData
685: + ')');
686: pg = new PatternGenerator(patternMetaData);
687: pg.processPattern();
688: } catch (MalformedURLException e) {
689: System.out.println("The pattern meta data file not found: "
690: + resourceName);
691: e.printStackTrace();
692: } catch (Exception e) {
693: e.printStackTrace();
694: } finally {
695: if (pg != null)
696: pg.destroy();
697: }
698: }
699:
700: private static void usage() {
701: System.err
702: .println("Usage: PatternGenerator <PatternMetaDataFileName relative to ClassPath>");
703: System.out
704: .println("Alternately use: PatternGenerator <a directory with PatternMetaData files> [<-r>]");
705: System.exit(1);
706: }
707: }
|