001 /* 002 * Copyright © 2008, 2012 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 Lesser 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 Lesser General Public License for more details. 018 * 019 * You should have received a copy of the GNU Lesser 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.RegisteredCode; 039 import com.softwarementors.extjs.djn.api.Registry; 040 import com.softwarementors.extjs.djn.config.GlobalConfiguration; 041 042 import edu.umd.cs.findbugs.annotations.NonNull; 043 044 public class CodeFileGenerator { 045 @NonNull private Registry registry; 046 047 private GlobalConfiguration getGlobalConfiguration() { 048 return this.registry.getGlobalConfiguration(); 049 } 050 051 private CodeFileGenerator( Registry registry) { 052 assert registry != null; 053 054 this.registry = registry; 055 } 056 057 @NonNull 058 private static final Logger logger = Logger.getLogger( CodeFileGenerator.class); 059 060 public static void updateSource( Registry registry, boolean saveApiFiles ) throws IOException { 061 assert registry != null; 062 063 CodeFileGenerator generator = new CodeFileGenerator(registry); 064 generator.generateCode(saveApiFiles); 065 } 066 067 private void generateCode(boolean saveApiFiles) throws IOException { 068 boolean minify = getGlobalConfiguration().getMinify(); 069 boolean debug = getGlobalConfiguration().getDebug(); 070 071 // Generate code 072 Map<String, RegisteredCode> registeredCodes = new HashMap<String,RegisteredCode>(); 073 for( RegisteredApi api : this.registry.getApis() ) { 074 String apiFile = api.getApiFile(); 075 String fullApiFileName = api.getFullApiFileName(); 076 RegisteredCode code = registeredCodes.get( apiFile ); 077 if( code == null ) { 078 code = new RegisteredCode( apiFile, fullApiFileName, minify, debug ); 079 registeredCodes.put( apiFile, code); 080 } 081 ApiCodeGenerator generator = new ApiCodeGenerator( getGlobalConfiguration(), api ); 082 generator.appendCode(code.getDebugCodeBuilder(), false); 083 generator.appendCode(code.getNonCommentsCodeBuilder(), true); 084 } 085 086 // Return source-code pairs! 087 for( Map.Entry<String, RegisteredCode> entry : registeredCodes.entrySet()) { 088 String sourceName = entry.getKey(); 089 RegisteredCode code = entry.getValue(); 090 091 // Return source name-code pairs! 092 String debugSourceName = getDebugFileName(sourceName); 093 this.registry.addSource(sourceName, code.getCode()); 094 this.registry.addSource(debugSourceName, code.getDebugCode()); 095 if( minify ) { 096 String minifiedSourceName = Minifier.getMinifiedFileName(sourceName); 097 this.registry.addSource( minifiedSourceName, code.getMinifiedCode()); 098 } 099 100 // Save files, if needed 101 if( saveApiFiles ) { 102 if( logger.isInfoEnabled()) { 103 logger.info( "Creating source files for APIs..."); 104 } 105 String defaultFileName = code.getFullApiFileName(); 106 String debugFileName = getDebugFileName(defaultFileName); 107 String minifiedFileName = Minifier.getMinifiedFileName(defaultFileName); 108 updateFile( debugFileName, code.getDebugCode() ); 109 updateFile( defaultFileName, code.getCode() ); 110 if( minify ) { 111 updateFile( minifiedFileName, code.getMinifiedCode() ); 112 } 113 else { 114 deleteFile( minifiedFileName ); 115 } 116 } 117 else { 118 if( logger.isInfoEnabled()) { 119 logger.info( "Source files for APIs have not been created: you will need to reference them dynamically"); 120 } 121 } 122 } 123 } 124 125 126 private static void deleteFile( String fullFileName ) throws IOException { 127 assert !StringUtils.isEmpty(fullFileName); 128 129 File file = new File( fullFileName ); 130 if( file.exists()) { 131 if( !file.delete() ) { 132 throw new IOException( "Unable to delete " + fullFileName); 133 } 134 if( logger.isDebugEnabled() ) { 135 logger.debug( "Api file deleted: '" + file.getAbsolutePath() + "'"); 136 } 137 } 138 } 139 140 private static void updateFile( String fullFileName, String code ) throws IOException { 141 assert !StringUtils.isEmpty(fullFileName); 142 assert code != null; 143 144 File file = new File( fullFileName ); 145 if( !fileContentEquals(file, code) ) { 146 FileUtils.writeStringToFile(file, code); 147 if( logger.isDebugEnabled() ) { 148 logger.debug( "Api file updated: '" + file.getAbsolutePath() + "'"); 149 } 150 } 151 else { 152 if( logger.isDebugEnabled() ) { 153 logger.debug( "Api file '" + file.getAbsolutePath() + '\'' + " is up to date: it was not rewritten."); 154 } 155 } 156 } 157 158 private static boolean fileContentEquals(File file, String code) throws IOException { 159 assert file != null; 160 assert code != null; 161 162 if( file.exists()) { 163 String contents = FileUtils.readFileToString(file); 164 boolean result = contents.equals( code ); 165 return result; 166 } 167 return false; 168 } 169 170 private static String getDebugFileName( String file ) { 171 String result = file.replace( ".js", "-debug.js"); 172 return result; 173 } 174 }