package railo.commons.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import railo.commons.io.IOUtil;
import railo.commons.io.res.Resource;
import railo.commons.io.res.util.ResourceClassLoader;
import railo.commons.io.res.util.ResourceUtil;
import railo.commons.lang.SystemOut;
import railo.loader.TP;
import railo.loader.engine.CFMLEngineFactory;
import railo.runtime.Info;
import railo.runtime.config.Config;
import railo.runtime.config.ConfigWeb;
public class JarLoader {
public static final short WHEN_EXISTS_UPDATE=1;
public static final short WHEN_EXISTS_RETURN_JAR=2;
public static final short WHEN_EXISTS_THROW_EXP=4;
public static final short WHEN_EXISTS_RETURN_NULL=8;
/**
* this loads the given jars from update provider, copy it to lib directory (where railo.jar is located) and load them to a ClassLoader
* @param pc
* @param jars jars names to Load
* @return Classloader with loaded jars for temporary use, after restart the engine this jars are loaded by the servlet engine
* @throws IOException
*/
public static ClassLoader loadJars(Config config, String[] jars,ClassLoader parent) throws IOException {
return new ResourceClassLoader(download(config, jars),parent);
}
public static Resource[] download(Config config, String[] jars) throws IOException {
List<Resource> list=new ArrayList<Resource>();
Resource jar;
lastCheck=-1;
for(int i=0;i<jars.length;i++){
jar=download(config, jars[i], WHEN_EXISTS_UPDATE);
if(jar!=null) list.add(jar);
}
return list.toArray(new Resource[list.size()]);
}
private static Resource download(Config config,String jarName, short whenExists) throws IOException {
// some variables nned later
PrintWriter out = config.getOutWriter();
URL dataUrl=toURL(config,jarName);
// destination file
ClassLoader mainClassLoader = new TP().getClass().getClassLoader();
Resource lib = config.getResource(CFMLEngineFactory.getClassLoaderRoot(mainClassLoader).getCanonicalPath());
Resource jar=lib.getRealResource(jarName);
SystemOut.printDate(out,"Check for jar at "+dataUrl);
if(jar.exists()){
if(whenExists==WHEN_EXISTS_RETURN_JAR) return jar;
else if(whenExists==WHEN_EXISTS_RETURN_NULL) return null;
else if(whenExists==WHEN_EXISTS_UPDATE) {
// compare local and remote
long localLen=jar.length();
long remoteLengh=HTTPUtil.length(dataUrl);
// only update when size change more than 10
if(localLen==remoteLengh){
SystemOut.printDate(out,"jar "+jar+" is up to date");
return jar;
}
if(!jar.delete()) throw new IOException("cannot update jar ["+jar+"], jar is locked or write protected, stop the servlet engine and delete this jar manually.");
}
else throw new IOException("jar ["+jar+"] exists already");
}
//long len=HTTPUtil.length();
InputStream is = (InputStream)dataUrl.getContent();
// copy input stream to lib directory
IOUtil.copy(is, jar,true);
SystemOut.printDate(out,"created/updated jar "+jar);
return jar;
}
private static URL toURL(Config config, String jarName) throws MalformedURLException {
URL hostUrl=config.getUpdateLocation();
if(hostUrl==null)hostUrl=new URL("http://www.getrailo.org");
return new URL(hostUrl,"/railo/remote/jars/"+(Info.getMajorVersion()+"."+Info.getMinorVersion())+"/"+jarName);
}
public static boolean exists(ConfigWeb config,String[] jarNames) {
for(int i=0;i<jarNames.length;i++){
if(!exists(config, jarNames[i])) return false;
}
return true;
}
/**
* check if one of given jar has changed or not exist
* @param config
* @param jarNames
* @return
*/
private static boolean changed=false;
private static long lastCheck=-1;
public static boolean changed(ConfigWeb config,String[] jarNames) {
if((lastCheck+300000)<System.currentTimeMillis()) {
changed=false;
for(int i=0;i<jarNames.length;i++){
if(changed(config, jarNames[i])) {
changed=true;
break;
}
}
lastCheck=System.currentTimeMillis();
}
return changed;
}
private static boolean exists(ConfigWeb config,String jarName) {
Resource res = _toResource(config, jarName);
if(res==null) return false;
return res.exists();
}
private static boolean changed(ConfigWeb config,String jarName) {
Resource res = _toResource(config, jarName);
if(res==null) {
return true;
}
try {
URL dataUrl = toURL(config,jarName);
boolean changed=res.length()!=HTTPUtil.length(dataUrl);
return changed;
} catch (IOException e) {
return false;
}
}
private static Resource _toResource(ConfigWeb config,String jarName) {
// destination file
ClassLoader mainClassLoader = new TP().getClass().getClassLoader();
try {
Resource lib = ResourceUtil.toResourceNotExisting(config,CFMLEngineFactory.getClassLoaderRoot(mainClassLoader).getCanonicalPath());
return lib.getRealResource(jarName);
} catch (IOException e) {
return null;
}
}
}