001 package org.shiftone.jrat.inject.process; 002 003 004 import org.shiftone.jrat.core.JRatException; 005 import org.shiftone.jrat.inject.Injector; 006 import org.shiftone.jrat.inject.InjectorOptions; 007 import org.shiftone.jrat.inject.bytecode.Transformer; 008 import org.shiftone.jrat.util.Assert; 009 import org.shiftone.jrat.util.io.IOUtil; 010 import org.shiftone.jrat.util.log.Logger; 011 012 import java.io.File; 013 import java.io.InputStream; 014 import java.io.OutputStream; 015 016 017 /** 018 * @author jeff@shiftone.org (Jeff Drost) 019 * <p/> 020 * todo - this logic should all go in the Injector. 021 */ 022 public abstract class AbstractFileProcessor implements FileProcessor { 023 024 private static final Logger LOG = Logger.getLogger(AbstractFileProcessor.class); 025 private static final long DEFAULT_BUFFER_SIZE = 1024 * 6; 026 private boolean forceOverwrite = true; // false; 027 private boolean overwriteNewer = false; 028 private boolean preserveLastModified = false; 029 030 public void process(Transformer transformer, InjectorOptions options, File source, File target) { 031 032 LOG.debug("process " + source.getAbsolutePath() + " " + target.getAbsolutePath()); 033 Assert.assertNotNull("transformer", transformer); 034 035 long lastModified; 036 037 if (!source.exists()) { 038 throw new JRatException("source file does not exist : " + source); 039 } 040 041 LOG.debug("source exists"); 042 043 if (source.isDirectory()) { 044 throw new JRatException("source file is a directory : " + source); 045 } 046 047 LOG.debug("source is real file (not dir)"); 048 049 if (source.canRead() == false) { 050 throw new JRatException("source file can not be read (check permissions): " + source); 051 } 052 053 LOG.debug("source can be read"); 054 055 lastModified = source.lastModified(); 056 057 if (target.exists()) { 058 LOG.debug("target exists " + target.getAbsolutePath()); 059 060 if (forceOverwrite == false) { 061 throw new JRatException("target exists and forceOverwrite is disabled : " + source); 062 } 063 064 if (target.isDirectory()) { 065 throw new JRatException("target is directory : " + target); 066 } 067 068 if (target.canWrite() == false) { 069 throw new JRatException("unable to write to target (check permissions) : " + target); 070 } 071 072 // newer is bigger 073 if (target.lastModified() > source.lastModified()) { 074 075 // target is newer than source 076 if (!overwriteNewer) { 077 throw new JRatException("target is newer than source and overwriteNewer is disabled : " 078 + source); 079 } 080 } 081 082 processUsingSwapFile(transformer, options, source, target); 083 } else { 084 LOG.debug("target does not exist " + target.getAbsolutePath()); 085 processFile(transformer, options, source, target); 086 } 087 088 if (preserveLastModified) { 089 target.setLastModified(lastModified); 090 } 091 } 092 093 094 protected void processUsingSwapFile(Transformer transformer, InjectorOptions options, File source, File target) { 095 096 LOG.debug("processUsingSwapFile " + source.getAbsolutePath() + " " + target.getAbsolutePath()); 097 098 File workFile = new File(target.getAbsolutePath() + Injector.WORK_FILE_END); 099 100 if (workFile.exists()) { 101 LOG.info("workfile found, deleting"); 102 IOUtil.delete(workFile); 103 } 104 105 try { 106 processFile(transformer, options, source, workFile); 107 108 if (!workFile.exists()) { 109 throw new JRatException("processFile seems to have worked, but target file doesn't exist : " 110 + source); 111 } 112 113 IOUtil.rename(workFile, target, true); 114 } 115 catch (Throwable e) { 116 String msg = "Failed to instrument " + source + " : " + e; 117 118 if ((workFile.exists()) && (!workFile.delete())) { 119 msg += " and couldn't delete the corrupt file " + workFile.getAbsolutePath(); 120 } 121 122 throw new JRatException(msg, e); 123 } 124 finally { 125 IOUtil.deleteIfExists(workFile); 126 } 127 } 128 129 130 protected void processFile(Transformer transformer, InjectorOptions options, File source, File target) { 131 132 int bufferSize = (int) Math.min(DEFAULT_BUFFER_SIZE, source.length()); 133 InputStream inputStream = null; 134 OutputStream outputStream = null; 135 136 try { 137 inputStream = IOUtil.openInputStream(source, bufferSize); 138 outputStream = IOUtil.openOutputStream(target, bufferSize); 139 140 LOG.debug("calling processStream"); 141 processStream(transformer, options, inputStream, outputStream, source.getName()); 142 } 143 finally { 144 IOUtil.close(inputStream); 145 IOUtil.close(outputStream); 146 } 147 } 148 149 150 protected void processStream( 151 Transformer transformer, InjectorOptions options, InputStream inputStream, OutputStream outputStream, String fileName) { 152 throw new UnsupportedOperationException("processStream should be implemented by derived class"); 153 } 154 }