001 package org.apache.torque.mojo; 002 003 import java.io.File; 004 import java.io.IOException; 005 import java.io.OutputStream; 006 import java.util.List; 007 import java.util.Properties; 008 import java.util.Set; 009 import java.util.TreeSet; 010 011 import org.apache.commons.io.FileUtils; 012 import org.apache.commons.io.IOUtils; 013 import org.apache.maven.plugin.MojoExecutionException; 014 import org.apache.maven.plugin.MojoFailureException; 015 import org.apache.tools.ant.DirectoryScanner; 016 import org.apache.torque.engine.database.model.Database; 017 import org.apache.torque.engine.database.model.Table; 018 import org.kuali.core.db.torque.SetUtils; 019 import org.kuali.core.db.torque.Utils; 020 021 /** 022 * This mojo identifies data files that are present on the file system but are not present in schema.xml. This can 023 * happen if a table is removed from the schema. 024 * 025 * It sets a project property called "impex.data.invalid". This property is a comma delimited list of filenames that 026 * have no match in the db schema. 027 * 028 * If it finds any invalid files it will also set the project property "impex.found.invalid=true" 029 * 030 * @goal id-invalid-data-files 031 */ 032 public class IdentifyInvalidDataFiles extends BaseMojo { 033 private static final String FS = System.getProperty("file.separator"); 034 035 /** 036 * @parameter expression="${extension}" default-value=".xml" 037 * @required 038 */ 039 private String extension; 040 041 /** 042 * @parameter expression="${dataDir}" default-value="${project.basedir}/src/main/impex" 043 * @required 044 */ 045 private File dataDir; 046 047 /** 048 * @parameter expression="${dataDirIncludes}" default-value="*.xml" 049 */ 050 private String dataDirIncludes; 051 052 /** 053 * @parameter expression="${dataDirExcludes}" default-value="schema.xml" 054 */ 055 private String dataDirExcludes; 056 057 /** 058 * @parameter expression="${schemaXMLFile}" default-value="src/main/impex/schema.xml" 059 */ 060 private String schemaXMLFile; 061 062 /** 063 * @parameter expression="${targetDatabase}" default-value="oracle" 064 */ 065 private String targetDatabase; 066 067 /** 068 * Any invalid files are listed in this file. One file per line 069 * 070 * @parameter expression="${impex.markedForRemoval}" default-value="${project.build.directory}/impex/invalid.txt" 071 */ 072 private File markedForRemoval; 073 074 @Override 075 protected void executeMojo() throws MojoExecutionException, MojoFailureException { 076 Utils utils = new Utils(); 077 try { 078 getLog().info("Examining " + dataDir.getAbsolutePath()); 079 Database db = utils.getDatabase(schemaXMLFile, targetDatabase); 080 DirectoryScanner ds = getDirectoryScanner(); 081 Set<File> existing = getExistingFiles(ds); 082 Set<File> allowed = getDatabaseFiles(db); 083 Set<File> invalid = SetUtils.difference(existing, allowed); 084 getLog().info(existing.size() + " data files currently exist"); 085 getLog().info(invalid.size() + " of those are invalid"); 086 StringBuilder sb = new StringBuilder(); 087 int count = 0; 088 StringBuilder invalidFiles = new StringBuilder(); 089 for (File file : invalid) { 090 if (count != 0) { 091 sb.append(","); 092 } 093 sb.append("**/src/main/impex/" + file.getName()); 094 invalidFiles.append(file.getCanonicalPath() + "\n"); 095 getLog().info("Marked for removal: " + file.getName()); 096 count++; 097 } 098 Properties properties = getProject().getProperties(); 099 properties.setProperty("impex.data.invalid", sb.toString()); 100 if (count > 0) { 101 properties.setProperty("impex.found.invalid", Boolean.TRUE.toString()); 102 createFile(markedForRemoval, invalidFiles.toString()); 103 } 104 } catch (Exception e) { 105 throw new MojoExecutionException("Error executing mojo", e); 106 } 107 } 108 109 protected void createFile(File file, String contents) throws IOException { 110 OutputStream out = null; 111 try { 112 out = FileUtils.openOutputStream(file); 113 IOUtils.write(contents, out); 114 } finally { 115 IOUtils.closeQuietly(out); 116 } 117 } 118 119 protected Set<File> getDatabaseFiles(Database db) { 120 List<?> tables = db.getTables(); 121 Set<File> files = new TreeSet<File>(); 122 for (Object object : tables) { 123 Table table = (Table) object; 124 String tableName = table.getName(); 125 String filename = dataDir.getAbsolutePath() + FS + tableName + extension; 126 File file = new File(filename); 127 files.add(file); 128 } 129 return files; 130 } 131 132 protected Set<File> getExistingFiles(DirectoryScanner ds) { 133 ds.scan(); 134 String[] relativeFilenames = ds.getIncludedFiles(); 135 Set<File> files = new TreeSet<File>(); 136 for (int i = 0; i < relativeFilenames.length; i++) { 137 String filename = ds.getBasedir().getAbsolutePath() + FS + relativeFilenames[i]; 138 File file = new File(filename); 139 files.add(file); 140 } 141 return files; 142 } 143 144 protected DirectoryScanner getDirectoryScanner() { 145 DirectoryScanner ds = new DirectoryScanner(); 146 ds.setBasedir(dataDir); 147 ds.setIncludes(new String[] { dataDirIncludes }); 148 ds.setExcludes(new String[] { dataDirExcludes }); 149 return ds; 150 } 151 152 protected File getFile(Table table) { 153 String tableName = table.getName(); 154 String filename = dataDir.getAbsolutePath() + FS + tableName + extension; 155 File file = new File(filename); 156 return file; 157 } 158 159 public File getDataDir() { 160 return dataDir; 161 } 162 163 public void setDataDir(File dataDir) { 164 this.dataDir = dataDir; 165 } 166 167 public String getDataDirIncludes() { 168 return dataDirIncludes; 169 } 170 171 public void setDataDirIncludes(String dataDirIncludes) { 172 this.dataDirIncludes = dataDirIncludes; 173 } 174 175 public String getDataDirExcludes() { 176 return dataDirExcludes; 177 } 178 179 public void setDataDirExcludes(String dataDirExcludes) { 180 this.dataDirExcludes = dataDirExcludes; 181 } 182 183 public String getSchemaXMLFile() { 184 return schemaXMLFile; 185 } 186 187 public void setSchemaXMLFile(String schemaXMLFile) { 188 this.schemaXMLFile = schemaXMLFile; 189 } 190 191 public String getExtension() { 192 return extension; 193 } 194 195 public void setExtension(String extension) { 196 this.extension = extension; 197 } 198 199 public String getTargetDatabase() { 200 return targetDatabase; 201 } 202 203 public void setTargetDatabase(String targetDatabase) { 204 this.targetDatabase = targetDatabase; 205 } 206 207 public File getMarkedForRemoval() { 208 return markedForRemoval; 209 } 210 211 public void setMarkedForRemoval(File markedForRemoval) { 212 this.markedForRemoval = markedForRemoval; 213 } 214 215 }