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