001    package com.softwarementors.extjs.djn.config;
002    
003    import java.io.IOException;
004    import java.io.Reader;
005    import java.io.StringReader;
006    import java.io.StringWriter;
007    import java.io.UnsupportedEncodingException;
008    import java.io.Writer;
009    
010    import org.apache.log4j.Logger;
011    import org.mozilla.javascript.ErrorReporter;
012    import org.mozilla.javascript.EvaluatorException;
013    
014    import com.softwarementors.extjs.djn.StringUtils;
015    import com.softwarementors.extjs.djn.Timer;
016    import com.yahoo.platform.yui.compressor.JavaScriptCompressor;
017    
018    public class Minifier {
019    
020      private static final Logger logger = Logger.getLogger( Minifier.class);
021    
022      private Minifier() {
023        // Avoid instantation
024      }
025    
026      public static String getMinifiedFileName(String file) {
027        assert !StringUtils.isEmpty(file);
028        
029        String result = file.replace( ".js", "-min.js" );
030        return result;
031      }
032    
033      public static final String minify( String input, String inputFilename, int debugCodeLength ) throws IOException {
034        assert input != null;
035        assert !StringUtils.isEmpty(inputFilename);
036        assert debugCodeLength > 0;
037    
038        try {
039          Timer timer = new Timer();      
040          // logger.debug( "Starting minification for '" + inputFilename + "'...");
041          Reader in = new StringReader( input );
042          JavaScriptCompressor compressor = new JavaScriptCompressor(in, new ErrorReporter() {
043            public void warning(String message, String sourceName,
044                int line, String lineSource, int lineOffset) {
045              if (line < 0) {
046                logger.warn("Minifier Warning: " + message);
047              } else {
048                logger.warn("Minifier Warning, " + line + ':' + lineOffset + ':' + message);
049              }
050            }
051    
052            public void error(String message, String sourceName,
053                int line, String lineSource, int lineOffset) {
054              if (line < 0) {
055                logger.warn("Minifier Error: " + message);
056              } else {
057                logger.warn("Minifier Error, " + line + ':' + lineOffset + ':' + message);
058              }
059            }
060    
061            public EvaluatorException runtimeError(String message, String sourceName,
062                int line, String lineSource, int lineOffset) {
063              error(message, sourceName, line, lineSource, lineOffset);
064              return new EvaluatorException(message);
065            }
066          });
067    
068          // Close the input stream first, and then open the output stream,
069          // in case the output file should override the input file.
070          in.close(); in = null;
071    
072          try {
073            Writer out = new StringWriter();
074            boolean munge = true;
075            boolean preserveAllSemiColons = false;
076            boolean disableOptimizations = false;
077            boolean verbose = false;
078            int linebreakpos = 0;
079    
080            compressor.compress(out, linebreakpos, munge, verbose,
081                preserveAllSemiColons, disableOptimizations);
082            out.close();
083            String result = out.toString();
084            if( logger.isDebugEnabled() ) {
085              timer.stop();
086              int compressionPercentage = 100 - (result.length() * 100 / debugCodeLength);
087              timer.logDebugTimeInMilliseconds( "Finished minification for '" + inputFilename + "'. Debug code length: " + debugCodeLength + ", Minified length: " + result.length() + ", Compression: " + compressionPercentage + "%. Time");
088            }
089            return result;
090          }
091          catch (UnsupportedEncodingException e) {
092            logger.warn( "Unable to minify '" + inputFilename + "'.", e );
093            return null;
094          }
095        } 
096        catch (EvaluatorException e) {
097          logger.warn( "Unable to minify '" + inputFilename + "' due to a problem with the Javascript evaluator.", e );
098          return null;
099        }
100      }
101    
102    }