Coverage Report - liquibase.change.core.SQLFileChange
 
Classes in this File Line Coverage Branch Coverage Complexity
SQLFileChange
64%
42/65
53%
15/28
3.071
 
 1  
 package liquibase.change.core;
 2  
 
 3  
 import java.io.FileNotFoundException;
 4  
 import java.io.IOException;
 5  
 import java.io.InputStream;
 6  
 
 7  
 import liquibase.change.AbstractSQLChange;
 8  
 import liquibase.change.ChangeMetaData;
 9  
 import liquibase.change.CheckSum;
 10  
 import liquibase.database.Database;
 11  
 import liquibase.exception.SetupException;
 12  
 import liquibase.exception.ValidationErrors;
 13  
 import liquibase.exception.Warnings;
 14  
 import liquibase.logging.LogFactory;
 15  
 import liquibase.resource.ResourceAccessor;
 16  
 import liquibase.util.StreamUtil;
 17  
 import liquibase.util.StringUtils;
 18  
 
 19  
 /**
 20  
  * Represents a Change for custom SQL stored in a File.
 21  
  * <p/>
 22  
  * To create an instance call the constructor as normal and then call
 23  
  * 
 24  
  * @author <a href="mailto:csuml@yahoo.co.uk">Paul Keeble</a>
 25  
  * @link{#setFileOpener(FileOpener) before calling setPath otherwise the file will likely not be found.
 26  
  */
 27  
 public class SQLFileChange extends AbstractSQLChange {
 28  
 
 29  
     private String path;
 30  27
     private String encoding = null;
 31  
     private Boolean relativeToChangelogFile;
 32  
 
 33  
     public SQLFileChange() {
 34  27
         super("sqlFile", "SQL From File", ChangeMetaData.PRIORITY_DEFAULT);
 35  27
     }
 36  
 
 37  
     public String getPath() {
 38  15
         return path;
 39  
     }
 40  
 
 41  
     /**
 42  
      * Sets the file name but setUp must be called for the change to have impact.
 43  
      * 
 44  
      * @param fileName
 45  
      *            The file to use
 46  
      */
 47  
     public void setPath(String fileName) {
 48  14
         path = fileName;
 49  14
     }
 50  
 
 51  
     /**
 52  
      * The encoding of the file containing SQL statements
 53  
      * 
 54  
      * @return the encoding
 55  
      */
 56  
     public String getEncoding() {
 57  0
         return encoding;
 58  
     }
 59  
 
 60  
     /**
 61  
      * @param encoding
 62  
      *            the encoding to set
 63  
      */
 64  
     public void setEncoding(String encoding) {
 65  0
         this.encoding = encoding;
 66  0
     }
 67  
 
 68  
     public Boolean isRelativeToChangelogFile() {
 69  0
         return relativeToChangelogFile;
 70  
     }
 71  
 
 72  
     public void setRelativeToChangelogFile(Boolean relativeToChangelogFile) {
 73  0
         this.relativeToChangelogFile = relativeToChangelogFile;
 74  0
     }
 75  
 
 76  
     @Override
 77  
     public void init() throws SetupException {
 78  11
         if (path == null) {
 79  0
             throw new SetupException("<sqlfile> - No path specified");
 80  
         }
 81  11
         LogFactory.getLogger().debug("SQLFile file:" + path);
 82  11
         boolean loaded = loadFromClasspath(path);
 83  11
         if (!loaded) {
 84  1
             loaded = loadFromFileSystem(path);
 85  
         }
 86  
 
 87  10
         if (!loaded) {
 88  0
             throw new SetupException("<sqlfile path=" + path + "> - Could not find file");
 89  
         }
 90  10
         LogFactory.getLogger().debug("SQLFile file contents is:" + getSql());
 91  10
     }
 92  
 
 93  
     @Override
 94  
     public ValidationErrors validate(Database database) {
 95  15
         ValidationErrors validationErrors = new ValidationErrors();
 96  15
         if (StringUtils.trimToNull(getPath()) == null) {
 97  15
             validationErrors.addError("'path' is required");
 98  
         }
 99  15
         return validationErrors;
 100  
     }
 101  
 
 102  
     @Override
 103  
     public Warnings warn(Database database) {
 104  0
         return new Warnings();
 105  
     }
 106  
 
 107  
     /**
 108  
      * Tries to load the file from the file system.
 109  
      * 
 110  
      * @param file
 111  
      *            The name of the file to search for
 112  
      * @return True if the file was found, false otherwise.
 113  
      */
 114  
     private boolean loadFromFileSystem(String file) throws SetupException {
 115  1
         if (relativeToChangelogFile != null && relativeToChangelogFile) {
 116  0
             file = getChangeSet().getFilePath().replaceFirst("/[^/]*$", "") + "/" + file;
 117  
         }
 118  
 
 119  1
         InputStream fis = null;
 120  
         try {
 121  1
             fis = getResourceAccessor().getResourceAsStream(file);
 122  1
             if (fis == null) {
 123  1
                 throw new SetupException("<sqlfile path=" + file + "> -Unable to read file");
 124  
             }
 125  0
             setSql(StreamUtil.getStreamContents(fis, encoding));
 126  0
             return true;
 127  0
         } catch (FileNotFoundException fnfe) {
 128  0
             return false;
 129  0
         } catch (IOException e) {
 130  0
             throw new SetupException("<sqlfile path=" + file + "> -Unable to read file", e);
 131  
         } finally {
 132  1
             if (fis != null) {
 133  
                 try {
 134  0
                     fis.close();
 135  0
                 } catch (IOException ioe) { // NOPMD
 136  
                     // safe to ignore
 137  1
                 }
 138  
             }
 139  
         }
 140  
 
 141  
     }
 142  
 
 143  
     /**
 144  
      * Tries to load a file using the FileOpener.
 145  
      * <p/>
 146  
      * If the fileOpener can not be found then the attempt to load from the classpath the return is false.
 147  
      * 
 148  
      * @param file
 149  
      *            The file name to try and find.
 150  
      * @return True if the file was found and loaded, false otherwise.
 151  
      */
 152  
     private boolean loadFromClasspath(String file) throws SetupException {
 153  11
         if (relativeToChangelogFile != null && relativeToChangelogFile) {
 154  0
             file = getChangeSet().getFilePath().replaceFirst("/[^/]*$", "") + "/" + file;
 155  
         }
 156  
 
 157  11
         InputStream in = null;
 158  
         try {
 159  11
             ResourceAccessor fo = getResourceAccessor();
 160  11
             if (fo == null) {
 161  0
                 return false;
 162  
             }
 163  
 
 164  11
             in = fo.getResourceAsStream(file);
 165  11
             if (in == null) {
 166  1
                 return false;
 167  
             }
 168  10
             setSql(StreamUtil.getStreamContents(in, encoding));
 169  10
             return true;
 170  0
         } catch (IOException ioe) {
 171  0
             return false;
 172  
         } finally {
 173  11
             if (in != null) {
 174  
                 try {
 175  10
                     in.close();
 176  0
                 } catch (IOException ioe) { // NOPMD
 177  
                     // safe to ignore
 178  21
                 }
 179  
             }
 180  
         }
 181  
     }
 182  
 
 183  
     /**
 184  
      * Calculates an MD5 from the contents of the file.
 185  
      * 
 186  
      * @see liquibase.change.AbstractChange#generateCheckSum()
 187  
      */
 188  
     @Override
 189  
     public CheckSum generateCheckSum() {
 190  1
         String sql = getSql();
 191  1
         if (sql == null) {
 192  1
             sql = "";
 193  
         }
 194  1
         return CheckSum.compute(sql);
 195  
     }
 196  
 
 197  
     @Override
 198  
     public String getConfirmationMessage() {
 199  1
         return "SQL in file " + path + " executed";
 200  
     }
 201  
 }