1 18 package org.objectweb.speedo.generation.recompiler; 19 20 import org.objectweb.speedo.generation.mivisitor.MetaInfoVisitorImpl; 21 import org.objectweb.speedo.generation.mivisitor.MetaInfoVisitor; 22 import org.objectweb.speedo.generation.api.SpeedoCompilerParameter; 23 import org.objectweb.speedo.metadata.SpeedoXMLDescriptor; 24 import org.objectweb.speedo.metadata.SpeedoClass; 25 import org.objectweb.speedo.api.SpeedoException; 26 import org.objectweb.speedo.mapper.lib.Object2StringSerializer; 27 import org.objectweb.speedo.tools.StringReplace; 28 import org.objectweb.speedo.mim.api.SpeedoProxy; 29 import org.objectweb.util.monolog.api.BasicLevel; 30 31 import java.io.File ; 32 import java.util.List ; 33 import java.util.ArrayList ; 34 import java.util.Arrays ; 35 import java.net.URLClassLoader ; 36 import java.net.URL ; 37 import java.net.MalformedURLException ; 38 39 51 public class UpToDateVisitor extends MetaInfoVisitorImpl { 52 53 private File output; 54 private File input; 55 private ClassLoader classloader; 56 private List xmlsToRemove; 57 private List enhancedClasses; 58 59 60 61 64 public UpToDateVisitor() { 65 } 66 67 70 public UpToDateVisitor(MetaInfoVisitor mim) { 71 super(mim); 72 } 73 74 protected String getLoggerName() { 75 return super.getLoggerName() + ".uptodate"; 76 } 77 78 public boolean init() throws SpeedoException { 79 super.init(); 80 output = new File (scp.output); 81 if (!output.exists() && output.mkdirs()) { 82 throw new SpeedoException( 83 "Impossible to create the output directory: " 84 + output.getAbsolutePath()); 85 } 86 input = new File (scp.input); 87 if (!input.exists()) { 88 throw new SpeedoException("No input directory: " 89 + input.getAbsolutePath()); 90 } 91 try { 92 classloader = new URLClassLoader ( 93 new URL []{new File (scp.output).toURL()}, 94 getClass().getClassLoader()); 95 } catch (MalformedURLException e) { 96 97 } 98 enhancedClasses = new ArrayList (); 99 return !scp.getXmldescriptor().isEmpty(); 100 } 101 102 public void visitCompilerParameter(SpeedoCompilerParameter scp) throws SpeedoException { 103 super.visitCompilerParameter(scp); 104 if (xmlsToRemove != null) { 105 for(int i=(xmlsToRemove.size() -1); i>=0; i--) { 106 SpeedoXMLDescriptor xml = (SpeedoXMLDescriptor) xmlsToRemove.get(i); 107 scp.getXmldescriptor().remove(xml.xmlFile); 108 } 109 } 110 } 111 112 public void visitXml(SpeedoXMLDescriptor xml) throws SpeedoException { 113 File jdoFile = new File (scp.jdoDir, xml.xmlFile); 115 File jmiFile = new File (output, 116 Object2StringSerializer.jdoFileName2ClassName(xml.xmlFile) 117 + ".class"); 118 if (debug) { 119 logger.log(BasicLevel.DEBUG, "JDO file: " 120 + jdoFile.getAbsolutePath() 121 + "\n\ttime=" + jdoFile.lastModified()); 122 if (jmiFile.exists()) { 123 logger.log(BasicLevel.DEBUG, "JMI file: " 124 + jmiFile.getAbsolutePath() 125 + "\n\ttime=" + jmiFile.lastModified()); 126 } else { 127 logger.log(BasicLevel.DEBUG, "NO JMI file found : " 128 + jmiFile.getAbsolutePath()); 129 } 130 } 131 xml.requireEnhancement = !jmiFile.exists() 132 || (jdoFile.lastModified() > jmiFile.lastModified()); 133 if (debug) { 134 logger.log(BasicLevel.DEBUG, "Enhancement " 135 + (xml.requireEnhancement ? "" : "not ") 136 + "required for the jdo file:" + xml.xmlFile); 137 } 138 enhancedClasses.clear(); 139 super.visitXml(xml); 140 List classes = xml.getSpeedoClasses(); 141 142 if (!xml.requireEnhancement) { 143 for(int i=(classes.size() -1); i>=0 && !xml.requireEnhancement; i--) { 144 SpeedoClass sc = (SpeedoClass) classes.get(i); 145 sc.requireEnhancement = xml.requireEnhancement; 146 } 147 } 148 if (xml.requireEnhancement) { 149 logger.log(BasicLevel.INFO, "Enhancement required for :" + xml.xmlFile); 150 151 if (debug) { 153 logger.log(BasicLevel.DEBUG, "Removing the jmi file:" 154 + jmiFile.getAbsolutePath()); 155 } 156 if (jmiFile.exists() && !jmiFile.delete()) { 157 throw new SpeedoException( 158 "Impossible to remove the JMI file associated to the jdo file:" 159 + xml.xmlFile); 160 } 161 162 for (int i = (enhancedClasses.size() - 1); i >= 0; i--) { 163 SpeedoClass sc = (SpeedoClass) enhancedClasses.get(i); 164 String baseName = StringReplace.replaceChar( 165 '.', File.separatorChar, sc.getFQName()); 166 File classFile = new File (output, baseName + ".class"); 167 if (debug) { 168 logger.log(BasicLevel.DEBUG, "Removing class files:" + classFile); 169 } 170 if (classFile.exists() && !classFile.delete()) { 171 throw new SpeedoException("Impossible to remove the file:" 172 + classFile.getAbsolutePath()); 173 } 174 } 175 } else { 176 if (xmlsToRemove == null) { 177 xmlsToRemove = new ArrayList (); 178 } 179 xmlsToRemove.add(xml); 180 } 181 enhancedClasses.clear(); } 183 184 public void visitClass(SpeedoClass sc) throws SpeedoException { 185 super.visitClass(sc); 186 SpeedoXMLDescriptor xml = sc.jdoPackage.jdoXMLDescriptor; 187 sc.requireEnhancement = xml.requireEnhancement; 188 String baseName = StringReplace.replaceChar( 189 '.', File.separatorChar, sc.getFQName()); 190 File classFile = new File (output, baseName + ".class"); 191 boolean classExist = classFile.exists(); 192 if (debug) { 193 logger.log(BasicLevel.DEBUG, "Examining the class: " + sc.getFQName()); 194 if (classExist) { 195 logger.log(BasicLevel.DEBUG, "class file: " + classFile.getAbsolutePath()); 196 } 197 } 198 199 boolean javaModified = !classExist; 200 if (classExist) { 201 File javaFile = new File (scp.input, baseName + ".java"); 203 logger.log(BasicLevel.DEBUG, "java file: " + javaFile.getAbsolutePath()); 204 javaModified = (javaFile.lastModified() > classFile.lastModified()); 205 206 if (!javaModified) { 207 try { 209 Class clazz = classloader.loadClass(sc.getFQName()); 210 sc.classAlreadyEnhanced = implement(clazz, SpeedoProxy.class); 211 } catch (NoClassDefFoundError e) { 212 logger.log(BasicLevel.DEBUG, "Class " + sc.getFQName(), e); 213 javaModified = true; } catch (ClassNotFoundException e) { 215 logger.log(BasicLevel.DEBUG, "Class " + sc.getFQName(), e); 216 } catch (ClassFormatError e) { 217 logger.log(BasicLevel.DEBUG, "Class " + sc.getFQName(), e); 218 } catch (Throwable e) { 219 String msg = "Impossible to analyze the class '" + sc.getFQName() + "': "; 220 logger.log(BasicLevel.ERROR, msg, e); 221 throw new SpeedoException(msg); 222 } 223 if (debug) { 224 logger.log(BasicLevel.DEBUG, "The class " + sc.getFQName() 225 + " is " 226 + (sc.classAlreadyEnhanced ? "": "not ") 227 + "already enhanced."); 228 } 229 } 230 } 231 if (classExist && javaModified) { 232 logger.log(BasicLevel.INFO, "The class " + sc.getFQName() + " has been modified (Remove the .class)."); 233 if (!classFile.delete()) { 234 throw new SpeedoException("Impossible to remove the file:" 235 + classFile.getAbsolutePath()); 236 } 237 } 238 sc.requireEnhancement = !classExist || javaModified || !sc.classAlreadyEnhanced; 239 if (!sc.requireEnhancement) { 240 enhancedClasses.add(sc); 241 } 242 243 xml.requireEnhancement |= sc.requireEnhancement ; 245 } 246 247 private boolean implement(Class clazz, Class itf) { 248 boolean res = Arrays.asList(clazz.getInterfaces()).contains(SpeedoProxy.class); 249 if (debug) { 250 logger.log(BasicLevel.DEBUG, "The class " + clazz.getName() + " is " 251 + (res ? "" : "not ") + "a " + itf.getName()); 252 } 253 return res || (clazz.getSuperclass() != null 254 && implement(clazz.getSuperclass(), itf)); 255 } 256 } 257 | Popular Tags |