Author: mrdon Date: Tue Apr 12 23:55:50 2005 New Revision: 161161 URL: http://svn.apache.org/viewcvs?view=rev&rev=161161 Log: * Adding javadocs comments for javascript functions * Adding script to generate javadoc files from javascript source * Adding several more extensions to File along with unit tests * Adding test driver to call scripts in SugarWrapFactory
Added: struts/flow/trunk/src/doc/jsdoc.js (with props) Modified: struts/flow/trunk/build.xml struts/flow/trunk/src/doc/extensions.xdt struts/flow/trunk/src/java/org/apache/struts/flow/sugar/FileExtensions.java struts/flow/trunk/src/java/org/apache/struts/flow/sugar/SugarWrapFactory.java struts/flow/trunk/src/java/system.js struts/flow/trunk/src/test/fileTest.js Modified: struts/flow/trunk/build.xml URL: http://svn.apache.org/viewcvs/struts/flow/trunk/build.xml?view=diff&r1=161160&r2=161161 ============================================================================== --- struts/flow/trunk/build.xml (original) +++ struts/flow/trunk/build.xml Tue Apr 12 23:55:50 2005 @@ -146,8 +146,23 @@ <doclet destdir="${build.doc}" verbose="true"> <fileset dir="${src.java}" includes="**/*Extensions.java"/> - <template templateFile="${src.doc}/extensions.xdt" destinationFile="extensions.html"/> + <template templateFile="${src.doc}/extensions.xdt" destinationFile="extensions.xml"/> </doclet> + </target> + + <target name="doc.jsdoc" depends="prepare"> + <taskdef name="doclet" + classname="xdoclet.DocletTask" + classpathref="base.classpath"/> + + <java classname="org.apache.struts.flow.sugar.SugarWrapFactory"> + <arg value="${src.doc}/jsdoc.js" /> + <arg value="-d" /> + <arg value="${build.doc}"/> + <arg value="-i" /> + <arg value="${src.java}"/> + <classpath refid="base.classpath" /> + </java> </target> <!-- Modified: struts/flow/trunk/src/doc/extensions.xdt URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/doc/extensions.xdt?view=diff&r1=161160&r2=161161 ============================================================================== --- struts/flow/trunk/src/doc/extensions.xdt (original) +++ struts/flow/trunk/src/doc/extensions.xdt Tue Apr 12 23:55:50 2005 @@ -1,89 +1,32 @@ -<html> -<head> - <title>Java API Extensions</title> -</head> -<body> -<h2>Java API Extensions</h2> -<p> -The following are methods that are added to Java API classes to -make developing with Struts Flow easier. -</p> +<extensions> <XDtClass:forAllClasses> <XDtClass:ifHasClassTag tagName="targetClass"> - <h3><XDtClass:classTagValue tagName="targetClass" /></h3> - <table width="100%" border="1"> + <class> + <name><XDtClass:classTagValue tagName="targetClass" /></name> <XDtMethod:forAllMethods> <XDtMethod:ifIsPublic> <XDtMethod:ifHasMethodTag tagName="propReturn"> - <tr> - <td><small><XDtMethod:methodTagValue tagName="propReturn" /></small></td> - <td><a href="#<XDtClass:className />_<XDtMethod:methodName />"><XDtMethod:methodName /></a> - <XDtMethod:firstSentenceDescriptionOfCurrentMethod /></td> - </tr> - </XDtMethod:ifHasMethodTag> - </XDtMethod:ifIsPublic> - </XDtMethod:forAllMethods> - </table> - <br /> - <table width="100%" border="1"> - <XDtMethod:forAllMethods> - <XDtMethod:ifIsPublic> + <property> + <type><XDtMethod:methodTagValue tagName="propReturn" /></type> + <name><XDtMethod:methodName /></name> + <firstSentence><XDtMethod:firstSentenceDescriptionOfCurrentMethod /></firstSentence> + <comment><XDtMethod:methodComment no-comment-signs="true"/></comment> + <example><XDtMethod:methodTagValue tagName="example" /></example> + </property> + </XDtMethod:ifHasMethodTag> <XDtMethod:ifHasMethodTag tagName="funcReturn"> - <tr> - <td><small><XDtMethod:methodTagValue tagName="funcReturn" /></small></td> - <td><a href="#<XDtClass:className />_<XDtMethod:methodName />"><XDtMethod:methodName />(<XDtMethod:methodTagValue tagName="funcParams" />)</a> - <XDtMethod:firstSentenceDescriptionOfCurrentMethod /></td> - </tr> - </XDtMethod:ifHasMethodTag> - </XDtMethod:ifIsPublic> - </XDtMethod:forAllMethods> - </table> - </XDtClass:ifHasClassTag> -</XDtClass:forAllClasses> -<hr /> -<XDtClass:forAllClasses> - <XDtClass:ifHasClassTag tagName="targetClass"> - <h3><XDtClass:classTagValue tagName="targetClass" /></h3> - <XDtMethod:forAllMethods> - <XDtMethod:ifIsPublic> - <XDtMethod:ifHasMethodTag tagName="propReturn"> - <hr /> - <a name="<XDtClass:className />_<XDtMethod:methodName />" /> - <h4><XDtMethod:methodName /></h4> - <code><XDtMethod:methodTagValue tagName="funcReturn" /> <XDtMethod:methodName /></code> - <blockquote> - <p> - <XDtMethod:methodComment no-comment-signs="true"/> - </p> - <p> - <strong>Example(s):</strong><br /> - <code><XDtMethod:methodTagValue tagName="example" /></code> - </p> - </blockquote> - </XDtMethod:ifHasMethodTag> - </XDtMethod:ifIsPublic> - </XDtMethod:forAllMethods> - <XDtMethod:forAllMethods> - <XDtMethod:ifIsPublic> - <XDtMethod:ifHasMethodTag tagName="funcReturn"> - <hr /> - <a name="<XDtClass:className />_<XDtMethod:methodName />" /> - <h4><XDtMethod:methodName /></h4> - - <code><XDtMethod:methodTagValue tagName="funcReturn" /> <XDtMethod:methodName />(<XDtMethod:methodTagValue tagName="funcParams" />)</code> - <blockquote> - <p> - <XDtMethod:methodComment no-comment-signs="true"/> - </p> - <p> - <strong>Example(s):</strong><br /> - <code><XDtMethod:methodTagValue tagName="example" /></code> - </p> - </blockquote> - </XDtMethod:ifHasMethodTag> + <method> + <type><XDtMethod:methodTagValue tagName="funcReturn" /></type> + <name><XDtMethod:methodName /></name> + <params><XDtMethod:methodTagValue tagName="funcParams" /></params> + <firstSentence><XDtMethod:firstSentenceDescriptionOfCurrentMethod /></firstSentence> + <comment><XDtMethod:methodComment no-comment-signs="true"/></comment> + <example><XDtMethod:methodTagValue tagName="example" /></example> + </method> + </XDtMethod:ifHasMethodTag> </XDtMethod:ifIsPublic> </XDtMethod:forAllMethods> - </XDtClass:ifHasClassTag> + </XDtClass:ifHasClassTag> + </class> </XDtClass:forAllClasses> - - -</body> -</html> +</extensions> Added: struts/flow/trunk/src/doc/jsdoc.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/doc/jsdoc.js?view=auto&rev=161161 ============================================================================== --- struts/flow/trunk/src/doc/jsdoc.js (added) +++ struts/flow/trunk/src/doc/jsdoc.js Tue Apr 12 23:55:50 2005 @@ -0,0 +1,563 @@ +/** + * Process a JavaScript source file and process special comments + * to produce an HTML file of documentation, similar to javadoc. + * @author Norris Boyd + * @see rhinotip.jar + * @lastmodified xx + * @version 1.2 Roland Pennings: Allow multiple files for a function. + * @version 1.3 Roland Pennings: Removes ../.. from the input directory name + */ + +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1997-1999 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Norris Boyd + * Roland Pennings + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License (the "GPL"), in which case the + * provisions of the GPL are applicable instead of those above. + * If you wish to allow use of your version of this file only + * under the terms of the GPL and not to allow others to use your + * version of this file under the NPL, indicate your decision by + * deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the NPL or the GPL. + */ + + + +var functionDocArray = []; +var inputDirName = ""; +var indexFileArray = []; +var indexFile = ""; +var indexFileName = "index_files"; +var indexFunctionArray = []; +var indexFunction = ""; +var indexFunctionName = "index_functions"; +var FileList = []; +var DirList = []; +var outputdir = null; +var debug = 0; + + + +/** + * Process JavaScript source file <code>f</code>, writing jsdoc to + * file <code>out</code>. + * @param f input file + * @param fname name of the input file (without the path) + * @param inputdir directory of the input file + * @param out output file + */ +function processFile(f, fname, inputdir, out) { + var s; + var firstLine = true; + indexFileArray[fname] = ""; + + // write the header of the output file + out.append('<HTML><HEADER><TITLE>' + fname + '</TITLE><BODY>'); + if (inputdir != null) { + outstr = '<a name=\"_top_\"></a><pre><a href=\"' + indexFile + '\">Index Files</a> '; + outstr += '<a href=\"' + indexFunction + '\">Index Functions</a></pre><hr>'; + out.append(outstr); + } + + // process the input file + var lines = f.getLines(); + var comment = ""; + var x = 0; + while ((s = lines[x++]) != null) { + var m = s.match(/\/\*\*(.*)/); + if (m != null) { + // Found a comment start. + s = "*" + m[1]; + do { + m = s.match(/(.*)\*\//); + if (m != null) { + // Found end of comment. + comment += m[1]; + break; + } + // Strip leading whitespace and "*". + comment += s.replace(/^\s*\*/, ""); + s = lines[x++]; + } while (s != null); + + if (debug) + print("Found comment " + comment); + + if (firstLine) { + // We have a comment for the whole file. + out.append('<H1>File ' + fname + '</H1>'); + out.append(processComment(comment,firstLine,fname)); + out.append('<HR>'); + firstLine = false; + comment = ""; + continue; + } + } + // match the beginning of the function + // NB we also match functions without a comment! + // if we have two comments one after another only the last one will be taken + m = s.match(/^\s*function\s+((\w+)|(\w+)(\s+))\(([^)]*)\)/); + if (m != null) + { + // Found a function start + var htmlText = processFunction(m[1], m[5], comment); // sjm changed from 2nd to 5th arg + + // Save the text in a global variable, so we + // can write out a table of contents first. + functionDocArray[functionDocArray.length] = {name:m[1], text:htmlText}; + + // Store the function also in the indexFunctionArray + // so we can have a seperate file with the function table of contents + if (indexFunctionArray[m[1]]) { + // print("ERROR: function: " + m[1] + " is defined more than once!"); + // Allow multiple files for a function + with (indexFunctionArray[m[1]]) { + filename = filename + "|" + fname; + // print("filename = " + filename); + } + } + else { + indexFunctionArray[m[1]] = {filename:fname}; + } + //reset comment + comment = ""; + } + // match a method being bound to a prototype + m = s.match(/^\s*(\w*)\.prototype\.(\w*)\s*=\s*function\s*\(([^)]*)\)/); + if (m != null) + { + // Found a method being bound to a prototype. + var htmlText = processPrototypeMethod(m[1], m[2], m[3], comment); + + // Save the text in a global variable, so we + // can write out a table of contents first. + functionDocArray[functionDocArray.length] = {name:m[1]+".prototype."+m[2], text:htmlText}; + + // Store the function also in the indexFunctionArray + // so we can have a seperate file with the function table of contents + if (indexFunctionArray[m[1]]) { + // print("ERROR: function: " + m[1] + " is defined more than once!"); + // Allow multiple files for a function + with (indexFunctionArray[m[1]]) { + filename = filename + "|" + fname; + // print("filename = " + filename); + } + } + else { + indexFunctionArray[m[1]] = {filename:fname}; + } + //reset comment + comment = ""; + } + + + firstLine = false; + } + + // Write table of contents. + for (var i=0; i < functionDocArray.length; i++) { + with (functionDocArray[i]) { + out.append('function <A HREF=#' + name + + '>' + name + '</A><BR>'); + } + } + out.append('<HR>'); + + // Now write the saved function documentation. + for (i=0; i < functionDocArray.length; i++) { + with (functionDocArray[i]) { + out.append('<A NAME=' + name + '>'); + out.append(text); + } + } + out.append('</BODY></HTML>'); + + // Now clean up the doc array + functionDocArray = []; +} + + +/** + * Process function and associated comment. + * @param name the name of the function + * @param args the args of the function as a single string + * @param comment the text of the comment + * @return a string for the HTML text of the documentation + */ +function processFunction(name, args, comment) { + if (debug) + print("Processing " + name + " " + args + " " + comment); + return "<H2>Function " + name + "</H2>" + + "<PRE>" + + "function " + name + "(" + args + ")" + + "</PRE>" + + processComment(comment,0,name) + + "<P><BR><BR>"; +} + +/** + * Process a method being bound to a prototype. + * @param proto the name of the prototype + * @param name the name of the function + * @param args the args of the function as a single string + * @param comment the text of the comment + * @return a string for the HTML text of the documentation + */ +function processPrototypeMethod(proto, name, args, comment) { + if (debug) + print("Processing " + proto + ".prototype." + name + " " + args + " " + comment); + return "<H2> Method " + proto + ".prototype." + name + "</H2>" + + "<PRE>" + + proto + ".prototype." + name + " = function(" + args + ")" + + "</PRE>" + + processComment(comment,0,name) + + "<P><BR><BR>"; +} + + +/** + * Process comment. + * @param comment the text of the comment + * @param firstLine shows if comment is at the beginning of the file + * @param fname name of the file (without path) + * @return a string for the HTML text of the documentation + */ +function processComment(comment,firstLine,fname) { + var tags = {}; + // Use the "lambda" form of regular expression replace, + // where the replacement object is a function rather + // than a string. The function is called with the + // matched text and any parenthetical matches as + // arguments, and the result of the function used as the + // replacement text. + // Here we use the function to build up the "tags" object, + // which has a property for each "@" tag that is the name + // of the tag, and whose value is an array of the + // text following that tag. + comment = comment.replace(/@(\w+)\s+([EMAIL PROTECTED])/g, + function (s, name, text) { + var a = tags[name] || []; + a.push(text); + tags[name] = a; + return ""; + }); + + // if we have a comment at the beginning of a file + // store the comment for the index file + if (firstLine) { + indexFileArray[fname] = comment; + } + + var out = comment + '<P>'; + if (tags["param"]) { + // Create a table of parameters and their descriptions. + var array = tags["param"]; + var params = ""; + for (var i=0; i < array.length; i++) { + var m = array[i].match(/(\w+)\s+(.*)/); + params += '<TR><TD><I>'+m[1]+'</I></TD>' + + '<TD>'+m[2]+'</TD></TR>'; + } + out += '<TABLE WIDTH="90%" BORDER=1>'; + out += '<TR BGCOLOR=0xdddddddd>'; + out += '<TD><B>Parameter</B></TD>'; + out += '<TD><B>Description</B></TD></TR>'; + out += params; + out += '</TABLE><P>'; + } + if (tags["return"]) { + out += "<DT><B>Returns:</B><DD>"; + out += tags["return"][0] + "</DL><P>"; + } + if (tags["author"]) { + // List the authors together, separated by commas. + out += '<DT><B>Author:</B><DD>'; + var array = tags["author"]; + for (var i=0; i < array.length; i++) { + out += array[i]; + if (i+1 < array.length) + out += ", "; + } + out += '</DL><P>'; + } + if (tags["version"]) { + // Show the version. + out += '<DT><B>Version:</B><DD>'; + var array = tags["version"]; + for (var i=0; i < array.length; i++) { + out += array[i]; + if (i+1 < array.length) + out += "<BR><DD>"; + } + out += '</DL><P>'; + } + if (tags["see"]) { + // List the see modules together, separated by <BR>. + out += '<DT><B>Dependencies:</B><DD>'; + var array = tags["see"]; + for (var i=0; i < array.length; i++) { + out += array[i]; + if (i+1 < array.length) + out += "<BR><DD>"; + } + out += '</DL><P>'; + } + if (tags["lastmodified"]) { + // Shows a last modified description with client-side js. + out += '<DT><B>Last modified:</B><DD>'; + out += '<script><!--\n'; + out += 'document.writeln(document.lastModified);\n'; + out += '// ---></script>\n'; + out += '</DL><P>'; + } + + // additional tags can be added here (i.e., "if (tags["see"])...") + return out; +} + +/** + * Create an html output file + * @param outputdir directory to put the file + * @param htmlfile name of the file +*/ +function CreateOutputFile(outputdir,htmlfile) +{ + if (outputdir==null) + { + var outname = htmlfile; + } + else + { + var separator = Packages.java.io.File.separator; + var outname = outputdir + separator + htmlfile.substring(htmlfile.lastIndexOf(separator),htmlfile.length); + } + print("output file: " + outname); + f = new java.io.File(outname); + f.remove(); + f.getParentFile().mkdirs(); + return f; +} + +/** + * Process a javascript file. Puts the generated HTML file in the outdir + * @param filename name of the javascript file + * @inputdir input directory of the file (default null) + */ +function processJSFile(filename,inputdir) +{ + if (debug) print("filename = " + filename + " inputdir = " + inputdir); + + if (!filename.match(/\.js$/)) { + print("Expected filename to end in '.js'; had instead " + + filename + ". I don't treat the file."); + } else { + if (inputdir==null) + { + var inname = filename; + } + else + { + var separator = Packages.java.io.File.separator; + var inname = inputdir + separator + filename; + } + print("Processing file " + inname); + + var f = new java.io.File(inname); + + // create the output file + var htmlfile = filename.replace(/\.js$/, ".html"); + + var out = CreateOutputFile(outputdir,htmlfile); + + processFile(f, filename, inputdir, out); + } +} + +/** + * Generate index files containing links to the processed javascript files + * and the generated functions + */ +function GenerateIndex(dirname) +{ + // construct the files index file + var out = CreateOutputFile(outputdir,indexFile); + + // write the beginning of the file + out.append('<HTML><HEADER><TITLE>File Index - directory: ' + dirname + '</TITLE><BODY>'); + out.append('<H1>File Index - directory: ' + dirname + '</H1>\n'); + out.append('<TABLE WIDTH="90%" BORDER=1>'); + out.append('<TR BGCOLOR=0xdddddddd>'); + out.append('<TD><B>File</B></TD>'); + out.append('<TD><B>Description</B></TD></TR>'); + + var separator = Packages.java.io.File.separator; + + // sort the index file array + var SortedFileArray = []; + for (var fname in indexFileArray) + SortedFileArray.push(fname); + SortedFileArray.sort(); + + for (var i=0; i < SortedFileArray.length; i++) { + var fname = SortedFileArray[i]; + var htmlfile = fname.replace(/\.js$/, ".html"); + out.append('<TR><TD><A HREF=\"' + htmlfile + '\">' + fname + '</A></TD></TD><TD>'); + if (indexFileArray[fname]) + out.append(indexFileArray[fname]); + else + out.append('No comments'); + out.append('</TD></TR>\n'); + } + out.append('</TABLE></BODY></HTML>'); + + // construct the functions index file + var out = CreateOutputFile(outputdir,indexFunction); + + // write the beginning of the file + out.append('<HTML><HEADER><TITLE>Function Index - directory: ' + dirname + '</TITLE><BODY>'); + out.append('<H1>Function Index - directory: ' + dirname + '</H1>\n'); + out.append('<TABLE WIDTH="90%" BORDER=1>'); + out.append('<TR BGCOLOR=0xdddddddd>'); + out.append('<TD><B>Function</B></TD>'); + out.append('<TD><B>Files</B></TD></TR>'); + + // sort the function array + var SortedFunctionArray = []; + for (var functionname in indexFunctionArray) + SortedFunctionArray.push(functionname); + SortedFunctionArray.sort(); + + for (var j=0; j < SortedFunctionArray.length; j++) { + var funcname = SortedFunctionArray[j]; + with (indexFunctionArray[funcname]) { + var outstr = '<TR><TD>' + funcname + '</TD><TD>'; + var filelst = filename.split("|"); + for (var i in filelst) { + var htmlfile = filelst[i].replace(/\.js$/, ".html"); + outstr += '<A HREF=\"' + htmlfile + '#' + funcname + '\">' + filelst[i] + '</A> '; + } + outstr += '</TD></TR>'; + out.append(outstr); + } + } + out.append('</TABLE></BODY></HTML>'); +} + + +/** + * prints the options for JSDoc +*/ +function PrintOptions() +{ + print("You can use the following options:\n"); + print("-d: specify an output directory for the generated html files\n"); + print("-i: processes all files in an input directory (you can specify several directories)\n"); + quit(); +} + +function print(val) { + java.lang.System.out.println((val == null ? "null" : val)); +} + + +// Main Script +// first read the arguments +if (! arguments) + PrintOptions(); + +for (var i=0; i < arguments.length; i++) { + if (debug) print("argument: + \'" + arguments[i] + "\'"); + if (arguments[i].match(/^\-/)) { + if (String(arguments[i])=="-d"){ + // output directory for the generated html files + + outputdir = String(arguments[i+1]); + if (debug) print("outputdir: + \'" + outputdir + "\'"); + //if (outputdir.match(/.*\/|\\$/)) { + // outputdir = outputdir.substring(0, outputdir.length); + //} + i++; + } + else if (String(arguments[i])=="-i"){ + // process all files in an input directory + + DirList.push(String(arguments[i+1])); +if (debug) print("inputdir: + \'" + arguments[i+1] + "\'"); + i++; + } + else { + print("Unknown option: " + arguments[i] + "\n"); + PrintOptions(); + } + } + else + { + // we have a single file + if (debug) print("file: + \'" + arguments[i] + "\'"); + + FileList.push(String(arguments[i])); + } +} + +// first handle the single files +for (var i in FileList) + processJSFile(FileList[i],null); + +// then handle the input directories +for (var j in DirList) { + var inputdir = String(DirList[j]); + + print("Process input directory: " + inputdir); + + // clean up index arrays + var indexFileArray = []; + var indexFunctionArray = []; + + // for the directory name get rid of ../../ or ..\..\ + inputDirName = inputdir.replace(/\.\.\/|\.\.\\/g,""); + + indexFile = indexFileName + "_" + inputDirName + ".html"; + indexFunction = indexFunctionName + "_" + inputDirName + ".html"; + +print("indexFile = " + indexFile); +print("indexFunction = " + indexFunction); + + // read the files in the directory + var DirFile = new java.io.File(inputdir); + var lst = DirFile.list(); + var separator = Packages.java.io.File.separator; + + for (var i=0; i < lst.length; i++) + { + processJSFile(String(lst[i]),inputdir); + } + + // generate the index files for the input directory + GenerateIndex(inputDirName); +} + + + Propchange: struts/flow/trunk/src/doc/jsdoc.js ------------------------------------------------------------------------------ svn:executable = * Modified: struts/flow/trunk/src/java/org/apache/struts/flow/sugar/FileExtensions.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/sugar/FileExtensions.java?view=diff&r1=161160&r2=161161 ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/sugar/FileExtensions.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/sugar/FileExtensions.java Tue Apr 12 23:55:50 2005 @@ -102,4 +102,52 @@ }; } + /** + * Collects the contents of the file as an array of lines. The file is opened, and + * interpreted as a text file using the default encoding. + * + * @funcParams + * @funcReturn String[] + * @example linesArray = file.getLines() + */ + public static ExtensionFunction getLines(final File file) { + return new ExtensionFunction() { + public Object execute(Context cx, Scriptable scope, Scriptable thisObj, java.lang.Object[] args) + throws IOException { + + BufferedReader reader = new BufferedReader(new FileReader(file)); + ArrayList list = new ArrayList(); + String line = null; + + while ((line = reader.readLine()) != null) { + list.add(line); + } + reader.close(); + + Object[] lines = new Object[list.size()]; + for (int x=0; x<lines.length; x++) { + lines[x] = cx.javaToJS(list.get(x), scope); + } + return cx.newArray(scope, lines); + } + }; + } + + /** + * Removes a file. Used to get around the problem of the reserved word 'delete'. + * + * @funcParams + * @funcReturn boolean + * @example isRemoved = file.remove() + */ + public static ExtensionFunction remove(final File file) { + return new ExtensionFunction() { + public Object execute(Context cx, Scriptable scope, Scriptable thisObj, java.lang.Object[] args) + throws IOException { + + return new Boolean(file.delete()); + } + }; + } + } Modified: struts/flow/trunk/src/java/org/apache/struts/flow/sugar/SugarWrapFactory.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/sugar/SugarWrapFactory.java?view=diff&r1=161160&r2=161161 ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/sugar/SugarWrapFactory.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/sugar/SugarWrapFactory.java Tue Apr 12 23:55:50 2005 @@ -112,6 +112,40 @@ return map; } + /** + * Test driver. Also used for generating javascript javadocs. + */ + public static final void main(String[] args) throws Exception { + Context cx = Context.enter(); + try { + cx.setWrapFactory(new SugarWrapFactory()); + // Initialize the standard objects (Object, Function, etc.) + // This must be done before scripts can be executed. Returns + // a scope object that we use in later calls. + Scriptable scope = cx.initStandardObjects(); + + FileReader reader = new FileReader(args[0]); + + // Set up "arguments" in the global scope to contain the command + // line arguments after the name of the script to execute + Object[] array = args; + if (args.length > 0) { + int length = args.length - 1; + array = new Object[length]; + System.arraycopy(args, 1, array, 0, length); + } + Scriptable argsObj = cx.newArray(scope, array); + scope.put("arguments", scope, argsObj); + Object result = cx.evaluateReader(scope, reader, args[0], 1, null); + + // Convert the result to a string and print it. + System.err.println(cx.toString(result)); + } finally { + // Exit from the context. + Context.exit(); + } + } + class ExtensionEntry { public Class clazz; public String name; Modified: struts/flow/trunk/src/java/system.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/system.js?view=diff&r1=161160&r2=161161 ============================================================================== --- struts/flow/trunk/src/java/system.js (original) +++ struts/flow/trunk/src/java/system.js Tue Apr 12 23:55:50 2005 @@ -1,7 +1,15 @@ +/** + * System methods to simplify interactions with the flow engine. + */ + var suicide; var lastContinuation = null; -// starts a continuation +/** + * Starts a continuation, linking it with the last continuation. + * @param lastWebCont The last web continuation to link this continuation to + * @return The created continuation + */ function startContinuation(lastWebCont) { var k = new Continuation(); @@ -14,15 +22,30 @@ return kont; } -// calls the specified function +/** + * Calls the specified function, creating a suicide continuation first. + * @param func The function object to call + * @param args The argument list to pass to the function + * @return The result of the function + */ function callFunction(func, args) { suicide = new Continuation(); return func.apply(this, args); } -// Forwards to a page and creates a continuation. Contains special support -// for client FlowCall's. +/** + * Forwards to a page and creates a continuation. Contains special support + * for client FlowCall's (calling flow functions through asynchrous javascript + * calls from the client. + * + * @param name The Struts forward name to call + * @param atts Map of business objects to place in the request scope + * @param allowedRemoteFuncs A list of remote function names that are allowed + * to be called from asynchronously from the client. An empty array + * allows any function call, a null or not specified array allows none. + * @return The continuation created used in the call + */ function forwardAndWait(name, atts, allowedRemoteFuncs) { var kont = _forwardAndWait(name, atts); @@ -63,7 +86,15 @@ return kont; } -// do the actual work to forward to a page and create a continuation +/** + * Do the actual work to forward to a page and create a continuation. The + * forward name, continuation id, and business object map are passed through + * <code>flow</code> context values. + * + * @param name The Struts forward to call + * @param atts The business object map to make available to the page + * @return The continuation created + */ function _forwardAndWait(name, atts) { var k = new Continuation(); @@ -81,8 +112,13 @@ return kont; } -// This function is called to restart a previously saved continuation -// passed as argument. +/** + * This function is called by Struts Flow to restart a previously saved continuation + * passed as argument. Override this method to have control over how continuations + * are instantiated. + * + * @param kont The continuation to reload + */ function handleContinuation(kont) { kont.continuation(kont); Modified: struts/flow/trunk/src/test/fileTest.js URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/test/fileTest.js?view=diff&r1=161160&r2=161161 ============================================================================== --- struts/flow/trunk/src/test/fileTest.js (original) +++ struts/flow/trunk/src/test/fileTest.js Tue Apr 12 23:55:50 2005 @@ -16,6 +16,24 @@ assertTrue("Didn't get text - "+txt, txt == "foo\nbar"); } +function testGetLines() { + writer = new java.io.FileWriter(file); + writer.write("foo\nbar"); + writer.close(); + txt = file.getLines(); + assertTrue("Wrong number of lines - "+txt.length, txt.length == 2); + assertTrue("Wrong second line - "+txt[1], txt[1] == "bar"); +} + +function testRemove() { + writer = new java.io.FileWriter(file); + writer.write("foo\nbar"); + writer.close(); + ret = file.remove(); + assertTrue("File should be removed", ret); + assertTrue("File should really be removed", !file.exists()); +} + function testEachLine() { writer = new java.io.FileWriter(file); writer.write("foo\nbar"); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]