Writing an ANT task is easy; all you need to extend is
Task Class. I have written one, it is
simple java program. This ant task is
now being added in our application build tasks. This will help us in keeping
the developers comments for readability and future reference, but cleaning all
the JS comments from final build, hence mitigating the reputation risk. Here is
the ant task declaration and configuration.
<taskdef
name="jsscript"
classname="com.aman.task.JSPDeleteScriptCommensRegExp"/>
<target name="allcomments">
<fileset
id="jsp.fileset" dir="${src.dir}" includes="**/*.jsp"/>
<jsscript
matchInline="(^|[^:\-'\"])(//+.*(?!(\*/))$)" replaceInline="\1"
matchMultiline="(^|[^/])(/\*+([\S\s](?!(/+\*+)))+?\*+/+)"
replaceMultiline="\1">
<fileset
refid="jsp.fileset"/>
</jsscript>
</target>
com.aman.task.JSPDeleteScriptCommensRegExp is the class that I
have written to delete all the JS comment.
matchInline - is the property of the above class,
this hold the inline comment pattern and this will be replaced with replaceInline “\1”: this
is the backreference of regular expression. We are replacing only the first
group as second group is all comment.
matchMultiline – is the again a
similar property to delete multiline comments and this will be replaced by replaceMultiline – “\1”.
Matching and replacing the inline and multiline comments are
handled differently.
Every line is searched for and replaced with pattern one at
a time in inline matching, whereas in multiline all the code inside the script
block is first buffred in and then matched and replaced.
I am not describing the regex used in detail, but if you
have any concern please do contact me.
Here is the full code for reference
package
com.aman.task;
import
java.io.BufferedReader;
import
java.io.BufferedWriter;
import
java.io.File;
import
java.io.FileReader;
import
java.io.FileWriter;
import
java.io.IOException;
import
java.io.PrintWriter;
import
java.io.Reader;
import
java.io.Writer;
import
java.util.Vector;
import
java.util.regex.Matcher;
import
java.util.regex.Pattern;
import
org.apache.tools.ant.BuildException;
import
org.apache.tools.ant.DirectoryScanner;
import
org.apache.tools.ant.Project;
import
org.apache.tools.ant.Task;
import
org.apache.tools.ant.taskdefs.optional.ReplaceRegExp;
import
org.apache.tools.ant.types.FileSet;
import
org.apache.tools.ant.types.RegularExpression;
import
org.apache.tools.ant.types.Substitution;
import
org.apache.tools.ant.util.FileUtils;
import
org.apache.tools.ant.util.regexp.Regexp;
public
class JSPDeleteScriptCommensRegExp extends Task {
private long totalline;
private long comment;
private long mcomment;
private Vector filesets;
private RegularExpression inlineRegex;
private Substitution inlineSubs;
private RegularExpression multilineRegex;
private Substitution multiLineSubs;
FileUtils fileUtils =
FileUtils.getFileUtils();
public JSPDeleteScriptCommensRegExp() {
super();
this.filesets = new Vector();
this.inlineRegex = null;
this.inlineSubs = null;
}
public void setMatchInline(String match) {
if (inlineRegex != null) {
throw new
BuildException("Only one inline regular expression is allowed");
}
inlineRegex = new RegularExpression();
inlineRegex.setPattern(match);
}
public void setReplaceInline(String replace) {
if (inlineSubs != null) {
throw new
BuildException("Only one inline substitution expression is "
+ "allowed");
}
inlineSubs = new Substitution();
inlineSubs.setExpression(replace);
}
public void setMatchMultiline(String match) {
if (multilineRegex != null) {
throw new
BuildException("Only one multiline regular expression is allowed");
}
multilineRegex = new RegularExpression();
multilineRegex.setPattern(match);
}
public void setReplaceMultiline(String
replace) {
if (multiLineSubs != null) {
throw new
BuildException("Only one multiline substitution expression is "
+
"allowed");
}
multiLineSubs = new Substitution();
multiLineSubs.setExpression(replace);
}
public void addFileset(FileSet set) {
filesets.addElement(set);
}
protected String doReplace(RegularExpression
r, Substitution s, String input, int options) {
String res = input;
Regexp regexp = r.getRegexp(getProject());
if (regexp.matches(input, options)) {
log("Found match;
substituting", Project.MSG_DEBUG);
res = regexp.substitute(input,
s.getExpression(getProject()),
options);
}
return res;
}
protected void doReplaceInline(File f, int
options) throws IOException {
File temp =
fileUtils.createTempFile("replace", ".txt", null);
temp.deleteOnExit();
Reader r = null;
Writer w = null;
try {
r = new FileReader(f);
w = new FileWriter(temp);
BufferedReader br = new
BufferedReader(r);
BufferedWriter bw = new
BufferedWriter(w);
PrintWriter pw = new
PrintWriter(bw);
boolean changes = false;
StringBuffer linebuf = new
StringBuffer();
String line = null;
String res = null;
int c;
boolean scriptFound = false;
Pattern scriptStart =
Pattern.compile("<script[\\S\\s]*?>");
Pattern inlineScript =
Pattern.compile("<script[\\S\\s]*?((/>)|(</script>))");
Pattern scriptend = Pattern.compile("</script");
while((line = br.readLine()) !=
null)
{
totalline++;
Matcher
scriptMacther = scriptStart.matcher(line);
Matcher
inlineMatcher = inlineScript.matcher(line);
Matcher
sciptendMatcher = scriptend.matcher(line);
if(inlineMatcher.find())
{
//
dont do anything just print it in final file and escape
}
else
if(scriptMacther.find())
{
scriptFound = true;
}
else
if(sciptendMatcher.find())
{
scriptFound
= false;
}
if(scriptFound)
{
res = doReplace(inlineRegex, inlineSubs, line,
options);
if
(!res.equals(line)) {
changes = true;
comment++;
}
pw.println(res);
}
else
{
pw.println(line);
}
}
pw.flush();
r.close();
r = null;
w.close();
w = null;
if (changes) {
log("File has changed;
saving the updated file", Project.MSG_VERBOSE);
try {
fileUtils.rename(temp, f);
temp = null;
} catch (IOException e) {
throw new BuildException("Couldn't
rename temporary file "
+
temp, getLocation());
}
} else {
log("No change made",
Project.MSG_DEBUG);
}
} finally {
try {
if (r != null) {
r.close();
}
} catch (Exception e) {
// ignore any secondary
exceptions
}
try {
if (w != null) {
w.close();
}
} catch (Exception e) {
// ignore any secondary
exceptions
}
if (temp != null) {
temp.delete();
}
}
}
protected void doReplaceMuliline(File f, int
options) throws IOException {
File temp = fileUtils.createTempFile("replace",
".txt", null);
temp.deleteOnExit();
Reader r = null;
Writer w = null;
try {
r = new FileReader(f);
w = new FileWriter(temp);
BufferedReader br = new BufferedReader(r);
BufferedWriter bw = new BufferedWriter(w);
PrintWriter pw = new PrintWriter(bw);
boolean changes = false;
StringBuffer linebuf = new StringBuffer();
String line = null;
String res = null;
int c;
boolean scriptFound = false;
boolean startMatch = false;
Pattern scriptStart =
Pattern.compile("<script[\\S\\s]*?>");
Pattern inlineScript =
Pattern.compile("<script[\\S\\s]*?((/>)|(</script>))");
Pattern scriptend = Pattern.compile("</script");
while((line = br.readLine()) != null)
{
Matcher scriptMacther =
scriptStart.matcher(line);
Matcher inlineMatcher =
inlineScript.matcher(line);
Matcher sciptendMatcher =
scriptend.matcher(line);
if(inlineMatcher.find())
{
}
else if(scriptMacther.find())
{
scriptFound = true;
}
else if(sciptendMatcher.find()
&& scriptFound)
{
startMatch = true;
scriptFound
= false;
}
if(scriptFound || (!scriptFound
&& startMatch))
{
linebuf.append(line).append(System.getProperty("line.separator"));
}
else
{
pw.println(line);
}
if(startMatch)
{
line = linebuf.toString();
res = doReplace(multilineRegex, multiLineSubs,
line, options);
if (!res.equals(line)) {
changes = true;
mcomment++;
}
pw.print(res);
linebuf = new StringBuffer();
startMatch = false;
}
}
pw.flush();
r.close();
r = null;
w.close();
w = null;
if (changes) {
log("File has changed;
saving the updated file", Project.MSG_VERBOSE);
try {
fileUtils.rename(temp, f);
temp = null;
} catch (IOException e) {
throw new
BuildException("Couldn't rename temporary file "
+
temp, getLocation());
}
} else {
log("No change made",
Project.MSG_DEBUG);
}
} finally {
try {
if (r != null) {
r.close();
}
} catch (Exception e) {
// ignore any secondary
exceptions
}
try {
if (w != null) {
w.close();
}
} catch (Exception e) {
// ignore any secondary
exceptions
}
if (temp != null) {
temp.delete();
}
}
}
public void execute() throws
BuildException {
if (inlineRegex == null) {
throw new
BuildException("No inline expression to match.");
}
if (inlineSubs == null) {
throw new
BuildException("Nothing to replace inline expression with.");
}
if (multilineRegex == null) {
throw new
BuildException("No multiline expression to match.");
}
if (multiLineSubs == null) {
throw new
BuildException("Nothing to replace multiline expression with.");
}
int options = 0;
options |= Regexp.REPLACE_ALL;
options |=
Regexp.MATCH_CASE_INSENSITIVE;
int sz = filesets.size();
for (int i = 0; i < sz; i++) {
FileSet fs = (FileSet)
(filesets.elementAt(i));
DirectoryScanner ds =
fs.getDirectoryScanner(getProject());
String[] files = ds.getIncludedFiles();
for (int j = 0; j < files.length;
j++) {
File f = new
File(fs.getDir(getProject()), files[j]);
if (f.exists()) {
try {
long tempTotalLine =totalline;
long tempComment = comment;
long tempMComment = mcomment;
String fileNameWithPath = f.getAbsolutePath();
doReplaceInline(f,
options);
doReplaceMuliline(f,
options);
log("File -
"+fileNameWithPath +" Line -
"+(totalline-tempTotalLine)+" inline
comments - "+(comment-tempComment)+" multiline
comments - "+(mcomment-tempMComment), Project.MSG_INFO);
} catch (Exception e) {
log("An error occurred processing
file: '"
+ f.getAbsolutePath() +
"': " + e.toString(),
Project.MSG_ERR);
}
} else {
log("The following file is
missing: '"
+ f.getAbsolutePath() +
"'", Project.MSG_ERR);
}
}
}
log("Total Line -
"+totalline+" total
inline comments - "+comment+" total multiline comments -
"+mcomment);
}
}