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.File; 029 import java.io.IOException; 030 import java.util.HashMap; 031 import java.util.Map; 032 033 import org.apache.commons.io.FileUtils; 034 import org.apache.log4j.Logger; 035 036 import com.softwarementors.extjs.djn.StringUtils; 037 import com.softwarementors.extjs.djn.api.RegisteredApi; 038 import com.softwarementors.extjs.djn.api.Registry; 039 import com.softwarementors.extjs.djn.config.GlobalConfiguration; 040 041 public class CodeFileGenerator { 042 private Registry registry; 043 Map<String, StringBuilder> debugFileOutputs = new HashMap<String,StringBuilder>(); 044 Map<String, StringBuilder> noCommentsFileOutputs = new HashMap<String,StringBuilder>(); 045 046 private GlobalConfiguration getGlobalConfiguration() { 047 return this.registry.getGlobalConfiguration(); 048 } 049 050 private CodeFileGenerator( Registry registry) { 051 assert registry != null; 052 053 this.registry = registry; 054 } 055 056 private static final Logger logger = Logger.getLogger( CodeFileGenerator.class); 057 058 public static void updateApiFiles( Registry registry ) throws IOException { 059 assert registry != null; 060 061 CodeFileGenerator generator = new CodeFileGenerator(registry); 062 063 generator.generateCode(); 064 generator.saveCode(); 065 } 066 067 private void generateCode() { 068 for( RegisteredApi api : this.registry.getApis() ) { 069 String fileName = api.getFullApiFileName(); 070 StringBuilder debugOutput = this.debugFileOutputs.get(fileName); 071 StringBuilder noCommentsOutput = this.noCommentsFileOutputs.get(fileName); 072 assert (debugOutput == null) == (noCommentsOutput == null); 073 074 if( debugOutput == null) { 075 debugOutput = new StringBuilder(); 076 this.debugFileOutputs.put( fileName, debugOutput); 077 078 noCommentsOutput = new StringBuilder(); 079 this.noCommentsFileOutputs.put( fileName, noCommentsOutput); 080 } 081 082 ApiCodeGenerator generator = new ApiCodeGenerator( getGlobalConfiguration(), api ); 083 generator.appendCode(debugOutput, false); 084 generator.appendCode(noCommentsOutput, true); 085 } 086 } 087 088 private void saveCode() throws IOException 089 { 090 for( String defaultFileName : this.debugFileOutputs.keySet() ) { 091 String debugFileName = getDebugFileName(defaultFileName); 092 String minifiedFileName = Minifier.getMinifiedFileName(defaultFileName); 093 094 boolean minify = getGlobalConfiguration().getMinify(); 095 boolean debug = getGlobalConfiguration().getDebug(); 096 097 String debugCode = this.debugFileOutputs.get(defaultFileName).toString(); 098 String defaultCode = debugCode; 099 String minifiedCode = debugCode; 100 101 boolean haveMinifiedCode = false; 102 if( minify ) { 103 String noCommentsCode = this.noCommentsFileOutputs.get(defaultFileName).toString(); 104 minifiedCode = Minifier.minify(noCommentsCode, defaultFileName, debugCode.length()); 105 if( minifiedCode == null ) { 106 logger.warn( "Unable to minify code: using Debug code for '" + minifiedFileName + "'."); 107 minifiedCode = debugCode; 108 } 109 else { 110 haveMinifiedCode = true; 111 } 112 } 113 114 if( !debug && haveMinifiedCode) { 115 defaultCode = minifiedCode; 116 if( logger.isDebugEnabled()) { 117 logger.debug( "Production mode: using minified code for '" + defaultFileName + "'"); 118 } 119 } 120 else { 121 if( logger.isDebugEnabled()) { 122 logger.debug( "Using Debug code for '" + defaultFileName + "'"); 123 } 124 } 125 126 updateFile( debugFileName, debugCode ); 127 updateFile( defaultFileName, defaultCode ); 128 if( minify ) { 129 updateFile( minifiedFileName, minifiedCode ); 130 } 131 else { 132 deleteFile( minifiedFileName ); 133 } 134 135 } 136 } 137 138 private void deleteFile( String fullFileName ) { 139 assert !StringUtils.isEmpty(fullFileName); 140 141 File file = new File( fullFileName ); 142 if( file.exists()) { 143 file.delete(); 144 if( logger.isDebugEnabled() ) { 145 logger.debug( "Api file deleted: '" + file.getAbsolutePath() + "'"); 146 } 147 } 148 } 149 150 private void updateFile( String fullFileName, String code ) throws IOException { 151 assert !StringUtils.isEmpty(fullFileName); 152 assert code != null; 153 154 File file = new File( fullFileName ); 155 if( !fileContentEquals(file, code) ) { 156 FileUtils.writeStringToFile(file, code); 157 if( logger.isDebugEnabled() ) { 158 logger.debug( "Api file updated: '" + file.getAbsolutePath() + "'"); 159 } 160 } 161 else { 162 if( logger.isDebugEnabled() ) { 163 logger.debug( "Api file '" + file.getAbsolutePath() + '\'' + " is up to date: it was not rewritten."); 164 } 165 } 166 } 167 168 private boolean fileContentEquals(File file, String code) throws IOException { 169 assert file != null; 170 assert code != null; 171 172 if( file.exists()) { 173 String contents = FileUtils.readFileToString(file); 174 boolean result = contents.equals( code ); 175 return result; 176 } 177 return false; 178 } 179 180 private String getDebugFileName( String file ) { 181 String result = file.replace( ".js", "-debug.js"); 182 return result; 183 } 184 }