当前位置: 代码迷 >> JavaScript >> 寨子一个js缩减comment的Maven Plugin
  详细解决方案

寨子一个js缩减comment的Maven Plugin

热度:346   发布时间:2012-12-27 10:17:09.0
山寨一个js缩减comment的Maven Plugin
background:
动手写一个去掉js comment的Maven Plugin, 用英文写练习练习,哈哈

steps:

1. New a maven project, the pom is like below. At the beginning I do not add the maven project api to the project, it is exhausting to find the project strutcture, build path etc and filter the resources that i want. It is better to include it in my project,

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.apache.maven</groupId>
			<artifactId>maven-plugin-api</artifactId>
			<version>2.0</version>
		</dependency>

		<dependency>
			<groupId>org.apache.maven</groupId>
			<artifactId>maven-project</artifactId>
			<version>2.0.9</version>
			<scope>provided</scope>
		</dependency>

	</dependencies>


2. Js comment is deleted by using regular expression. the code maybe like as below. The single line comment as "//...." without existing in string literal is hard to match. And a big js file is loaded into memory at one time and is treated as a really string by regular expression may cause java fatal error. So it is not very prefect, but it is enough to be fullfill my situation.
package com.mycompany.mojo.jsmin;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Pattern;

public abstract class JsFileProcessor {
	
	private static final int buffer_size = 512;
	
	private static final Pattern block = Pattern.compile( "(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)" );
	
	private static final Pattern singleLine = Pattern.compile( "(?<=.*)//[^\"\\n\\r]*(?=[\r\n])" );
	
	public static void process(File inputFile, File outputFile) throws IOException {
		
		FileInputStream fis = null;
		FileWriter fw = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream(buffer_size * 2);
		try {
			
			fis = new FileInputStream(inputFile);
			fw = new FileWriter(outputFile);
			
			int length = -1;
			byte[] buffer = new byte[buffer_size];
			while( (length = fis.read(buffer)) != -1) {
				
				baos.write(buffer, 0, length);
			}
			
		} catch (IOException e) {
			throw e;
		} finally {
			fis.close();
			baos.flush();
			baos.close();
		}
					
		String text = singleLine.matcher(
				block.matcher(baos.toString()).replaceAll("")	
				).replaceAll("");

		try {
			fw.write(text);
		} finally {
			fw.flush();
			fw.close();
		}
	}
}



3. Mojo is like as below, the annotation is required by Maven plugin to dependecy inject the parms value at runtime. It is really very convenient. to deal with resources. The plugin is binded to the life cycle: process-resources. When the war file is packaged, the comment-deleted js files may be overwritten.
package com.mycompany.mojo.jsmin;

import java.io.File;
import java.io.IOException;
import java.util.List;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.util.DirectoryScanner;

/**
 * delete the js file comment
 * @goal minify
 * @phase process-resources
 */
public class JsCommentMojo extends AbstractMojo {

    /**
     * Single directory for extra files to include in the WAR.
     *
     * @parameter expression="${basedir}/src/main/webapp"
     */
    private File warSourceDirectory;

    /**
     * The folder where the webapp is built.
     *
     * @parameter expression="${project.build.directory}/${project.build.finalName}"
     */
    private File webappDirectory;

    /**
     * excludes file
     *
     * @parameter
     */
    private List<String> excludes;
    
    /**
     * javascript file extension
     * 
     * @parameter default-value=".js"
     */
    private String extension;
    
    /**
     * Whether to skip execution.
     *
     * @parameter expression="${maven.jsmin.skip}" default-value="false"
     */
    private boolean skip;
    
    /**
     * total count of processed javascript file
     * 
     */
    private int executedCount;
    
    
	public void execute() throws MojoExecutionException, MojoFailureException {
		
		if(skip) {
			getLog().info("Run of javascript files process skipped");
            return;
		}
		
		getLog().info("Run of javascript files process is starting...");
		
		DirectoryScanner directoryScanner = new DirectoryScanner();
		directoryScanner.setBasedir(warSourceDirectory);
        if ( excludes != null && !excludes.isEmpty() ) {
            directoryScanner.setExcludes( excludes.toArray(new String[0]) );
        }
        directoryScanner.setIncludes(new String[]{"**/*" + extension});
        directoryScanner.addDefaultExcludes();
        directoryScanner.scan();
        for(String relativePath : directoryScanner.getIncludedFiles() ) {
        	
        	try {
				processFile(
						new File(warSourceDirectory, relativePath), 
						getTargetFile(relativePath));
			} catch (IOException e) {
				getLog().error(warSourceDirectory + relativePath + "  failed to be processed");
				getLog().error(e);
				throw new MojoExecutionException(e.getMessage());
			}
        }

		getLog().info("Total " + executedCount + " javascript files processed");
	}
	
	private File getTargetFile(String relativePath) throws MojoExecutionException {
		
			
		File file = new File(webappDirectory.getPath() + File.separator + 
				relativePath);

		file.getParentFile().mkdirs();
		
		if(getLog().isDebugEnabled()) {
			getLog().debug("src file [ " + 
						relativePath + " ] ==>> target [ " +
						file.getPath() + " ]");
		}
		
		return file;
	}
	
	private void processFile(File inputFile, File outputFile) throws IOException {
		
		JsFileProcessor.process(inputFile, outputFile);
		
		executedCount++;
		
		getLog().info("process file : " + inputFile.getPath() );

	}

}


作为记录, 以资参考
  相关解决方案