001 /* 002 * Copyright © 2008, 2009 Pedro Agulló Soliveres. 003 * 004 * This file is part of DirectJNgine. 005 * 006 * DirectJNgine is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License. 009 * 010 * Commercial use is permitted to the extent that the code/component(s) 011 * do NOT become part of another Open Source or Commercially developed 012 * licensed development library or toolkit without explicit permission. 013 * 014 * DirectJNgine is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with DirectJNgine. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * This software uses the ExtJs library (http://extjs.com), which is 023 * distributed under the GPL v3 license (see http://extjs.com/license). 024 */ 025 026 package com.softwarementors.extjs.djn.jscodegen; 027 028 import java.io.IOException; 029 import java.io.Reader; 030 import java.io.StringReader; 031 import java.io.StringWriter; 032 import java.io.UnsupportedEncodingException; 033 import java.io.Writer; 034 035 import org.apache.log4j.Logger; 036 import org.mozilla.javascript.ErrorReporter; 037 import org.mozilla.javascript.EvaluatorException; 038 039 import com.softwarementors.extjs.djn.StringUtils; 040 import com.softwarementors.extjs.djn.Timer; 041 import com.yahoo.platform.yui.compressor.JavaScriptCompressor; 042 043 public class Minifier { 044 045 private static final Logger logger = Logger.getLogger( Minifier.class); 046 047 private Minifier() { 048 // Avoid instantation 049 } 050 051 public static String getMinifiedFileName(String file) { 052 assert !StringUtils.isEmpty(file); 053 054 String result = file.replace( ".js", "-min.js" ); 055 return result; 056 } 057 058 public static final String minify( String input, String inputFilename, int debugCodeLength ) throws IOException { 059 assert input != null; 060 assert !StringUtils.isEmpty(inputFilename); 061 assert debugCodeLength > 0; 062 063 try { 064 Timer timer = new Timer(); 065 // logger.debug( "Starting minification for '" + inputFilename + "'..."); 066 Reader in = new StringReader( input ); 067 JavaScriptCompressor compressor = new JavaScriptCompressor(in, new ErrorReporter() { 068 public void warning(String message, String sourceName, 069 int line, String lineSource, int lineOffset) { 070 if (line < 0) { 071 logger.warn("Minifier Warning: " + message); 072 } else { 073 logger.warn("Minifier Warning, " + line + ':' + lineOffset + ':' + message); 074 } 075 } 076 077 public void error(String message, String sourceName, 078 int line, String lineSource, int lineOffset) { 079 if (line < 0) { 080 logger.warn("Minifier Error: " + message); 081 } else { 082 logger.warn("Minifier Error, " + line + ':' + lineOffset + ':' + message); 083 } 084 } 085 086 public EvaluatorException runtimeError(String message, String sourceName, 087 int line, String lineSource, int lineOffset) { 088 error(message, sourceName, line, lineSource, lineOffset); 089 return new EvaluatorException(message); 090 } 091 }); 092 093 // Close the input stream first, and then open the output stream, 094 // in case the output file should override the input file. 095 in.close(); in = null; 096 097 try { 098 Writer out = new StringWriter(); 099 boolean munge = true; 100 boolean preserveAllSemiColons = false; 101 boolean disableOptimizations = false; 102 boolean verbose = false; 103 int linebreakpos = 0; 104 105 compressor.compress(out, linebreakpos, munge, verbose, 106 preserveAllSemiColons, disableOptimizations); 107 out.close(); 108 String result = out.toString(); 109 if( logger.isDebugEnabled() ) { 110 timer.stop(); 111 int compressionPercentage = 100 - (result.length() * 100 / debugCodeLength); 112 timer.logDebugTimeInMilliseconds( "Finished minification for '" + inputFilename + "'. Debug code length: " + debugCodeLength + ", Minified length: " + result.length() + ", Compression: " + compressionPercentage + "%. Time"); 113 } 114 return result; 115 } 116 catch (UnsupportedEncodingException e) { 117 logger.warn( "Unable to minify '" + inputFilename + "'.", e ); 118 return null; 119 } 120 } 121 catch (EvaluatorException e) { 122 logger.warn( "Unable to minify '" + inputFilename + "' due to a problem with the Javascript evaluator.", e ); 123 return null; 124 } 125 } 126 127 }