package com.laytonsmith.core.functions;
import com.laytonsmith.PureUtilities.ZipReader;
import com.laytonsmith.core.CHLog;
import com.laytonsmith.core.LogLevel;
import com.laytonsmith.core.MethodScriptCompiler;
import com.laytonsmith.core.ParseTree;
import com.laytonsmith.core.Security;
import com.laytonsmith.core.constructs.Target;
import com.laytonsmith.core.exceptions.CRE.CREIOException;
import com.laytonsmith.core.exceptions.CRE.CREIncludeException;
import com.laytonsmith.core.exceptions.CRE.CRESecurityException;
import com.laytonsmith.core.exceptions.ConfigCompileException;
import com.laytonsmith.core.exceptions.ConfigCompileGroupException;
import com.laytonsmith.core.exceptions.ConfigRuntimeException;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
/**
*
*/
public class IncludeCache {
private static final CHLog.Tags TAG = CHLog.Tags.INCLUDES;
private static HashMap<File, ParseTree> cache = new HashMap<File, ParseTree>();
private static void add(File file, ParseTree tree){
cache.put(file, tree);
}
public static ParseTree get(File file, Target t){
CHLog.GetLogger().Log(TAG, LogLevel.DEBUG, "Loading " + file.getAbsolutePath(), t);
if(!cache.containsKey(file)){
CHLog.GetLogger().Log(TAG, LogLevel.VERBOSE, "Cache does not already contain include file, compiling, then caching.", t);
//We have to pull the file from the FS, and compile it.
if(Security.CheckSecurity(file.getAbsolutePath())){
CHLog.GetLogger().Log(TAG, LogLevel.VERBOSE, "Security check passed", t);
try {
String s = new ZipReader(file).getFileContents();
ParseTree tree = MethodScriptCompiler.compile(MethodScriptCompiler.lex(s, file, true));
CHLog.GetLogger().Log(TAG, LogLevel.VERBOSE, "Compilation succeeded, adding to cache.", t);
IncludeCache.add(file, tree);
} catch (ConfigCompileException ex) {
throw new CREIncludeException("There was a compile error when trying to include the script at " + file
+ "\n" + ex.getMessage() + " :: " + file.getName() + ":" + ex.getLineNum(), t);
} catch(ConfigCompileGroupException ex){
StringBuilder b = new StringBuilder();
b.append("There were compile errors when trying to include the script at ").append(file).append("\n");
for(ConfigCompileException e : ex.getList()){
b.append(e.getMessage()).append(" :: ").append(e.getFile().getName()).append(":").append(e.getLineNum());
}
throw new CREIncludeException(b.toString(), t);
} catch (IOException ex) {
throw new CREIOException("The script at " + file + " could not be found or read in.", t);
}
} else {
throw new CRESecurityException("The script cannot access " + file + " due to restrictions imposed by the base-dir setting.", t);
}
}
CHLog.GetLogger().Log(TAG, LogLevel.INFO, "Returning " + file.getAbsolutePath() + " from cache", t);
return cache.get(file);
}
public static void clearCache(){
CHLog.GetLogger().Log(TAG, LogLevel.INFO, "Clearing include cache", Target.UNKNOWN);
cache.clear();
}
}