View Javadoc

1   /**
2    * Copyright 2004-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.torque.mojo;
17  
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Properties;
26  import java.util.Set;
27  import java.util.TreeSet;
28  
29  import org.apache.commons.io.FileUtils;
30  import org.apache.commons.io.IOUtils;
31  import org.apache.maven.plugin.MojoExecutionException;
32  import org.apache.maven.plugin.MojoFailureException;
33  import org.apache.tools.ant.DirectoryScanner;
34  import org.apache.torque.engine.database.model.Database;
35  import org.apache.torque.engine.database.model.Table;
36  import org.kuali.core.db.torque.SetUtils;
37  import org.kuali.core.db.torque.Utils;
38  
39  /**
40   * This mojo identifies data files that are present on the file system but are not present in schema.xml. This can
41   * happen if a table is removed from the schema.
42   * 
43   * It sets a project property called "impex.data.invalid". This property is a comma delimited list of filenames that
44   * have no match in the db schema.
45   * 
46   * If it finds any invalid files it will also set the project property "impex.found.invalid=true"
47   * 
48   * @goal id-invalid-data-files
49   */
50  public class IdentifyInvalidDataFiles extends BaseMojo {
51      private static final String FS = System.getProperty("file.separator");
52  
53      /**
54       * @parameter expression="${extension}" default-value=".xml"
55       * @required
56       */
57      private String extension;
58  
59      /**
60       * @parameter expression="${dataDir}" default-value="${project.basedir}/src/main/impex"
61       * @required
62       */
63      private File dataDir;
64  
65      /**
66       * @parameter expression="${dataDirIncludes}" default-value="*.xml"
67       */
68      private String dataDirIncludes;
69  
70      /**
71       * @parameter expression="${dataDirExcludes}" default-value="schema.xml"
72       */
73      private String dataDirExcludes;
74  
75      /**
76       * @parameter expression="${schemaXMLFile}" default-value="src/main/impex/schema.xml"
77       */
78      private String schemaXMLFile;
79  
80      /**
81       * @parameter expression="${targetDatabase}" default-value="oracle"
82       */
83      private String targetDatabase;
84  
85      /**
86       * Any invalid files are listed in this file. One file per line
87       * 
88       * @parameter expression="${impex.markedForRemoval}" default-value="${project.build.directory}/impex/invalid.txt"
89       */
90      private File markedForRemoval;
91  
92      protected Set<File> getExportedFiles() throws MojoExecutionException {
93          String filename = getProject().getBuild().getDirectory() + "/impex/exported-tables.txt";
94          File file = new File(filename);
95          if (!file.exists()) {
96              getLog().warn("Could not locate " + file.getAbsolutePath());
97              return new HashSet<File>();
98          }
99          List<String> tablenames = getContents(file);
100         return getExportedFiles(tablenames);
101     }
102 
103     protected Set<File> getExportedFiles(List<String> tablenames) {
104         Set<File> files = new TreeSet<File>();
105         for (String tablename : tablenames) {
106             String filename = dataDir.getAbsolutePath() + FS + tablename + extension;
107             File file = new File(filename);
108             files.add(file);
109         }
110         return files;
111     }
112 
113     @SuppressWarnings("unchecked")
114     protected List<String> getContents(File file) throws MojoExecutionException {
115         InputStream in = null;
116         try {
117             in = new FileInputStream(file);
118             return IOUtils.readLines(in);
119         } catch (IOException e) {
120             throw new MojoExecutionException("Unexpected error", e);
121         } finally {
122             IOUtils.closeQuietly(in);
123         }
124     }
125 
126     @Override
127     protected void executeMojo() throws MojoExecutionException, MojoFailureException {
128         Utils utils = new Utils();
129         try {
130             getLog().info("Examining " + dataDir.getAbsolutePath());
131             Database db = utils.getDatabase(schemaXMLFile, targetDatabase);
132             DirectoryScanner ds = getDirectoryScanner();
133             Set<File> existing = getExistingFiles(ds);
134             Set<File> exported = getExportedFiles();
135             Set<File> allowed = getDatabaseFiles(db);
136             if (exported.size() > 0) {
137                 allowed = exported;
138             }
139             Set<File> invalid = SetUtils.difference(existing, allowed);
140             getLog().info(existing.size() + " data files currently exist");
141             getLog().info(invalid.size() + " of those are invalid");
142             StringBuilder sb = new StringBuilder();
143             int count = 0;
144             StringBuilder invalidFiles = new StringBuilder();
145             for (File file : invalid) {
146                 if (count != 0) {
147                     sb.append(",");
148                 }
149                 sb.append("**/src/main/impex/" + file.getName());
150                 invalidFiles.append(file.getCanonicalPath() + "\n");
151                 getLog().info("Marked for removal: " + file.getName());
152                 count++;
153             }
154             Properties properties = getProject().getProperties();
155             properties.setProperty("impex.data.invalid", sb.toString());
156             if (count > 0) {
157                 properties.setProperty("impex.found.invalid", Boolean.TRUE.toString());
158                 createFile(markedForRemoval, invalidFiles.toString());
159             }
160         } catch (Exception e) {
161             throw new MojoExecutionException("Error executing mojo", e);
162         }
163     }
164 
165     protected void createFile(File file, String contents) throws IOException {
166         OutputStream out = null;
167         try {
168             out = FileUtils.openOutputStream(file);
169             IOUtils.write(contents, out);
170         } finally {
171             IOUtils.closeQuietly(out);
172         }
173     }
174 
175     protected Set<File> getDatabaseFiles(Database db) {
176         List<?> tables = db.getTables();
177         Set<File> files = new TreeSet<File>();
178         for (Object object : tables) {
179             Table table = (Table) object;
180             String tableName = table.getName();
181             String filename = dataDir.getAbsolutePath() + FS + tableName + extension;
182             File file = new File(filename);
183             files.add(file);
184         }
185         return files;
186     }
187 
188     protected Set<File> getExistingFiles(DirectoryScanner ds) {
189         ds.scan();
190         String[] relativeFilenames = ds.getIncludedFiles();
191         Set<File> files = new TreeSet<File>();
192         for (int i = 0; i < relativeFilenames.length; i++) {
193             String filename = ds.getBasedir().getAbsolutePath() + FS + relativeFilenames[i];
194             File file = new File(filename);
195             files.add(file);
196         }
197         return files;
198     }
199 
200     protected DirectoryScanner getDirectoryScanner() {
201         DirectoryScanner ds = new DirectoryScanner();
202         ds.setBasedir(dataDir);
203         ds.setIncludes(new String[] { dataDirIncludes });
204         ds.setExcludes(new String[] { dataDirExcludes });
205         return ds;
206     }
207 
208     protected File getFile(Table table) {
209         String tableName = table.getName();
210         String filename = dataDir.getAbsolutePath() + FS + tableName + extension;
211         File file = new File(filename);
212         return file;
213     }
214 
215     public File getDataDir() {
216         return dataDir;
217     }
218 
219     public void setDataDir(File dataDir) {
220         this.dataDir = dataDir;
221     }
222 
223     public String getDataDirIncludes() {
224         return dataDirIncludes;
225     }
226 
227     public void setDataDirIncludes(String dataDirIncludes) {
228         this.dataDirIncludes = dataDirIncludes;
229     }
230 
231     public String getDataDirExcludes() {
232         return dataDirExcludes;
233     }
234 
235     public void setDataDirExcludes(String dataDirExcludes) {
236         this.dataDirExcludes = dataDirExcludes;
237     }
238 
239     public String getSchemaXMLFile() {
240         return schemaXMLFile;
241     }
242 
243     public void setSchemaXMLFile(String schemaXMLFile) {
244         this.schemaXMLFile = schemaXMLFile;
245     }
246 
247     public String getExtension() {
248         return extension;
249     }
250 
251     public void setExtension(String extension) {
252         this.extension = extension;
253     }
254 
255     public String getTargetDatabase() {
256         return targetDatabase;
257     }
258 
259     public void setTargetDatabase(String targetDatabase) {
260         this.targetDatabase = targetDatabase;
261     }
262 
263     public File getMarkedForRemoval() {
264         return markedForRemoval;
265     }
266 
267     public void setMarkedForRemoval(File markedForRemoval) {
268         this.markedForRemoval = markedForRemoval;
269     }
270 
271 }