001 package railo.commons.net; 002 003 import java.io.IOException; 004 import java.io.InputStream; 005 import java.io.PrintWriter; 006 import java.net.MalformedURLException; 007 import java.net.URL; 008 import java.util.ArrayList; 009 import java.util.List; 010 011 import railo.commons.io.IOUtil; 012 import railo.commons.io.res.Resource; 013 import railo.commons.io.res.util.ResourceClassLoader; 014 import railo.commons.io.res.util.ResourceUtil; 015 import railo.commons.lang.SystemOut; 016 import railo.loader.TP; 017 import railo.loader.engine.CFMLEngine; 018 import railo.loader.engine.CFMLEngineFactory; 019 import railo.runtime.PageContext; 020 import railo.runtime.config.Config; 021 import railo.runtime.config.ConfigImpl; 022 import railo.runtime.config.ConfigWeb; 023 import railo.runtime.config.ConfigWebImpl; 024 025 public class JarLoader { 026 027 public static final short WHEN_EXISTS_UPDATE=1; 028 public static final short WHEN_EXISTS_RETURN_JAR=2; 029 public static final short WHEN_EXISTS_THROW_EXP=4; 030 public static final short WHEN_EXISTS_RETURN_NULL=8; 031 032 033 034 035 /** 036 * this loads the given jars from update provider, copy it to lib directory (where railo.jar is located) and load them to a ClassLoader 037 * @param pc 038 * @param jars jars names to Load 039 * @return Classloader with loaded jars for temporary use, after restart the engine this jars are loaded by the servlet engine 040 * @throws IOException 041 */ 042 public static ClassLoader loadJars(PageContext pc, String[] jars,ClassLoader parent) throws IOException { 043 return new ResourceClassLoader(download(pc, jars),parent); 044 } 045 046 047 public static Resource[] download(PageContext pc, String[] jars) throws IOException { 048 List<Resource> list=new ArrayList<Resource>(); 049 Resource jar; 050 lastCheck=-1; 051 for(int i=0;i<jars.length;i++){ 052 jar=download(pc, jars[i], WHEN_EXISTS_UPDATE); 053 if(jar!=null) list.add(jar); 054 } 055 return list.toArray(new Resource[list.size()]); 056 } 057 058 059 private static Resource download(PageContext pc,String jarName, short whenExists) throws IOException { 060 // some variables nned later 061 ConfigWebImpl config=(ConfigWebImpl) pc.getConfig(); 062 PrintWriter out = pc.getConfig().getOutWriter(); 063 064 URL dataUrl=toURL(config,jarName); 065 066 // destination file 067 ClassLoader mainClassLoader = new TP().getClass().getClassLoader(); 068 Resource lib = ResourceUtil.toResourceNotExisting(pc,CFMLEngineFactory.getClassLoaderRoot(mainClassLoader).getCanonicalPath(),false); 069 070 Resource jar=lib.getRealResource(jarName); 071 SystemOut.printDate(out,"Check for jar at "+dataUrl); 072 if(jar.exists()){ 073 if(whenExists==WHEN_EXISTS_RETURN_JAR) return jar; 074 else if(whenExists==WHEN_EXISTS_RETURN_NULL) return null; 075 else if(whenExists==WHEN_EXISTS_UPDATE) { 076 // compare local and remote 077 long localLen=jar.length(); 078 long remoteLengh=HTTPUtil.length(dataUrl); 079 // only update when size change more than 10 080 if(localLen==remoteLengh){ 081 SystemOut.printDate(out,"jar "+jar+" is up to date"); 082 return jar; 083 } 084 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."); 085 } 086 else throw new IOException("jar ["+jar+"] already exists"); 087 } 088 089 090 //long len=HTTPUtil.length(); 091 InputStream is = (InputStream)dataUrl.getContent(); 092 // copy input stream to lib directory 093 IOUtil.copy(is, jar,true); 094 095 SystemOut.printDate(out,"created/updated jar "+jar); 096 097 return jar; 098 } 099 100 private static URL toURL(Config config, String jarName) throws MalformedURLException { 101 URL hostUrl=((ConfigImpl)config).getUpdateLocation(); 102 if(hostUrl==null)hostUrl=new URL("http://www.getrailo.org"); 103 return new URL(hostUrl,"/railo/remote/jars/"+jarName); 104 } 105 106 107 public static boolean exists(ConfigWeb config,String[] jarNames) { 108 for(int i=0;i<jarNames.length;i++){ 109 if(!exists(config, jarNames[i])) return false; 110 } 111 return true; 112 } 113 114 /** 115 * check if one of given jar has changed or not exist 116 * @param config 117 * @param jarNames 118 * @return 119 */ 120 private static boolean changed=false; 121 private static long lastCheck=-1; 122 public static boolean changed(ConfigWeb config,String[] jarNames) { 123 if((lastCheck+300000)<System.currentTimeMillis()) { 124 changed=false; 125 for(int i=0;i<jarNames.length;i++){ 126 if(changed(config, jarNames[i])) { 127 changed=true; 128 break; 129 } 130 } 131 lastCheck=System.currentTimeMillis(); 132 } 133 return changed; 134 } 135 136 private static boolean exists(ConfigWeb config,String jarName) { 137 Resource res = _toResource(config, jarName); 138 if(res==null) return false; 139 return res.exists(); 140 } 141 142 private static boolean changed(ConfigWeb config,String jarName) { 143 Resource res = _toResource(config, jarName); 144 if(res==null) { 145 return true; 146 } 147 148 try { 149 URL dataUrl = toURL(config,jarName); 150 boolean changed=res.length()!=HTTPUtil.length(dataUrl); 151 152 return changed; 153 } catch (MalformedURLException e) { 154 return false; 155 } 156 } 157 158 private static Resource _toResource(ConfigWeb config,String jarName) { 159 // destination file 160 ClassLoader mainClassLoader = new TP().getClass().getClassLoader(); 161 try { 162 Resource lib = ResourceUtil.toResourceNotExisting(config,CFMLEngineFactory.getClassLoaderRoot(mainClassLoader).getCanonicalPath()); 163 return lib.getRealResource(jarName); 164 } catch (IOException e) { 165 return null; 166 } 167 } 168 }