View Javadoc

1   package org.appfuse.tool;
2   
3   import org.apache.maven.plugin.logging.Log;
4   import org.apache.maven.plugin.logging.SystemStreamLog;
5   import org.apache.maven.project.MavenProject;
6   import org.apache.tools.ant.Project;
7   import org.apache.tools.ant.taskdefs.Delete;
8   import org.apache.tools.ant.taskdefs.Replace;
9   import org.apache.tools.ant.taskdefs.optional.ReplaceRegExp;
10  import org.apache.tools.ant.types.FileSet;
11  import org.appfuse.mojo.installer.AntUtils;
12  
13  import java.io.File;
14  import java.util.ArrayList;
15  
16  /**
17   * This class is responsible for removing generated CRUD artifacts from an AppFuse application.
18   *
19   * @author mraible
20   */
21  public class ArtifactUninstaller {
22      private Log log;
23      static final String FILE_SEP = System.getProperty("file.separator");
24      Project antProject;
25      String pojoName;
26      String pojoNameLower;
27      String installedDirectory;
28      MavenProject project;
29      boolean genericCore;
30  
31      public ArtifactUninstaller(MavenProject project, String pojoName, String installedDirectory, boolean genericCore) {
32          this.project = project;
33          this.pojoName = pojoName;
34          this.pojoNameLower = pojoLowerCase(pojoName);
35          this.installedDirectory = installedDirectory;
36          this.genericCore = genericCore;
37      }
38  
39      public void execute() {
40          antProject = AntUtils.createProject();
41          
42          log("Removing sample data for DbUnit...");
43          removeSampleData();
44  
45          // install dao and manager if jar (modular/core) or war w/o parent (basic)
46          if (project.getPackaging().equals("jar") || (project.getPackaging().equals("war") && project.getParent() == null)) {
47              removeGeneratedFiles(installedDirectory, "**/dao/**/" + pojoName + "*.java");
48              removeGeneratedFiles(installedDirectory, "**/service/**/" + pojoName + "*.java");
49              if (genericCore) {
50                  log("Removing Spring bean definitions...");
51                  removeGenericBeanDefinitions();
52              } else {
53                  // APF-1105: Changed to use Spring annotations (@Repository, @Service and @Autowired)
54                  //removeDaoAndManagerBeanDefinitions();
55              }
56              // only installs if iBATIS is configured as dao.framework
57              removeiBATISFiles();
58          }
59  
60          if (project.getPackaging().equalsIgnoreCase("war")) {
61              removeGeneratedFiles(installedDirectory, "**/webapp/**/" + pojoName + "*.java");
62              
63              String webFramework = project.getProperties().getProperty("web.framework");
64  
65              if ("jsf".equalsIgnoreCase(webFramework)) {
66                  log("Installing JSF views and configuring...");
67                  removeJSFNavigationAndBeans();
68                  removeJSFViews();
69              } else if ("struts".equalsIgnoreCase(webFramework)) {
70                  log("Removing Struts views and configuring...");
71                  // A bean definition for an Action is not used anymore (APF-798)
72                  // installStrutsBeanDefinition();
73                  removeStrutsActionDefinitions();
74                  removeGeneratedFiles(installedDirectory + "/src/main/resources", "**/model/" + pojoName + "*.xml");
75                  removeGeneratedFiles(installedDirectory + "/src/main/resources", "**/webapp/action/" + pojoName + "*.xml");
76                  removeStrutsViews();
77              } else if ("spring".equalsIgnoreCase(webFramework)) {
78                  log("Removing Spring views and configuring...");
79                  removeSpringControllerBeanDefinitions();
80                  removeSpringValidation();
81                  removeSpringViews();
82              } else if ("tapestry".equalsIgnoreCase(webFramework)) {
83                  log("Removing Tapestry views and configuring...");
84                  removeTapestryViews();
85              }
86  
87              log("Removing i18n messages...");
88              removeInternationalizationKeys();
89  
90              log("Removing menu...");
91              removeMenu();
92  
93              log("Removing UI tests...");
94              removeUITests();
95          }
96      }
97  
98      /**
99       * This method will remove files from the source directory.
100      *
101      * @param installedDirectory The destination directory to copy to.
102      * @param removePattern      The file pattern to match to locate files to copy.
103      */
104     protected void removeGeneratedFiles(final String installedDirectory, final String removePattern) {
105         Delete deleteTask = (Delete) antProject.createTask("delete");
106 
107         FileSet fileSet = AntUtils.createFileset(installedDirectory, removePattern, new ArrayList());
108         log("Removing generated files (pattern: " + removePattern + ")...");
109         deleteTask.addFileset(fileSet);
110         deleteTask.execute();
111     }
112 
113     private String pojoLowerCase(String name) {
114         return name.substring(0, 1).toLowerCase() + name.substring(1);
115     }
116 
117     private String getPathToApplicationContext() {
118         if (project.getPackaging().equalsIgnoreCase("war")) {
119             return "/src/main/webapp/WEB-INF/applicationContext.xml";
120         } else { // if (project.getPackaging().equalsIgnoreCase("jar")) {
121             return "/src/main/resources/applicationContext.xml";
122         }
123     }
124 
125     /**
126      * Remove table from project's sample-data.xml
127      */
128     private void removeSampleData() {
129         File existingFile = new File(installedDirectory + "/src/test/resources/sample-data.xml");
130         parseXMLFile(existingFile, null);
131     }
132 
133     /* APF-1105: Changed to use Spring annotations (@Repository, @Service and @Autowired)
134     private void removeDaoAndManagerBeanDefinitions() {
135         File generatedFile = new File(installedDirectory + getPathToApplicationContext());
136         parseXMLFile(generatedFile, pojoName + "Dao");
137 
138         generatedFile = new File(installedDirectory + getPathToApplicationContext());
139         parseXMLFile(generatedFile, pojoName + "Manager");
140     }*/
141 
142     private void removeiBATISFiles() {
143         if (project.getProperties().getProperty("dao.framework").equals("ibatis")) {
144             log("Removing iBATIS SQL Maps...");
145             File sqlMapConfig = new File(installedDirectory + "/src/main/resources/sql-map-config.xml");
146             parseXMLFile(sqlMapConfig, null);
147 
148             File sqlMapsDir = new File(installedDirectory + "/src/main/resources/sqlmaps");
149             if (!sqlMapsDir.exists()) {
150                 return;
151             }
152 
153             removeGeneratedFiles(installedDirectory + "/src/main/resources/sqlmaps", pojoName + "SQL.xml");
154         }
155     }
156 
157     private void removeGenericBeanDefinitions() {
158         File generatedFile = new File(installedDirectory + getPathToApplicationContext());
159         parseXMLFile(generatedFile, pojoName + "Manager");
160     }
161 
162     private void removeJSFNavigationAndBeans() {
163         File generatedFile = new File(installedDirectory + "/src/main/webapp/WEB-INF/faces-config.xml");
164         parseXMLFile(generatedFile, pojoName + "-nav");
165 
166         // JSF managed beans configured by Spring annotations in 2.1+
167         //generatedFile = new File(installedDirectory + "/src/main/webapp/WEB-INF/faces-config.xml");
168         //parseXMLFile(generatedFile, pojoName + "-beans");
169     }
170 
171     private void removeSpringControllerBeanDefinitions() {
172         File generatedFile = new File(installedDirectory + "/src/main/webapp/WEB-INF/dispatcher-servlet.xml");
173         parseXMLFile(generatedFile, pojoName);
174     }
175 
176     private void removeSpringValidation() {
177         File generatedFile = new File(installedDirectory + "/src/main/webapp/WEB-INF/validation.xml");
178         parseXMLFile(generatedFile, pojoName);
179     }
180 
181     private void removeStrutsActionDefinitions() {
182         File existingFile = new File(installedDirectory + "/src/main/resources/struts.xml");
183         parseXMLFile(existingFile, pojoName + "Action");
184     }
185 
186     // =================== Views ===================
187 
188     private void removeJSFViews() {
189         removeGeneratedFiles(installedDirectory + "/src/main/webapp", pojoNameLower + "*.xhtml");
190     }
191 
192     private void removeSpringViews() {
193         removeGeneratedFiles(installedDirectory + "/src/main/webapp/WEB-INF/pages", pojoNameLower + "*.jsp");
194     }
195 
196     private void removeStrutsViews() {
197         removeGeneratedFiles(installedDirectory + "/src/main/webapp/WEB-INF/pages", pojoNameLower + "*.jsp");
198     }
199 
200     private void removeTapestryViews() {
201         removeGeneratedFiles(installedDirectory + "/src/main/webapp", pojoName + "*.tml");
202     }
203 
204     // =================== End of Views ===================
205 
206     private void removeMenu() {
207         File existingFile = new File(installedDirectory + "/src/main/webapp/common/menu.jsp");
208         if (existingFile.exists()) { // no menu in AppFuse Light
209             parseXMLFile(existingFile, pojoName);
210 
211             existingFile = new File(installedDirectory + "/src/main/webapp/WEB-INF/menu-config.xml");
212             parseXMLFile(existingFile, pojoName);
213         } else {
214             existingFile = new File(installedDirectory + "/src/main/webapp/decorators/default.jsp");
215             parseXMLFile(existingFile, pojoName);
216         }
217     }
218 
219     private void removeInternationalizationKeys() {
220         File existingFile = new File(installedDirectory + "/src/main/resources/ApplicationResources.properties");
221         if (!existingFile.exists()) { // assume appfuse-light
222             existingFile = new File(installedDirectory + "/src/main/resources/messages.properties");
223         }
224         parsePropertiesFile(existingFile, pojoName);
225     }
226 
227     private void removeUITests() {
228         File existingFile = new File(installedDirectory + "/src/test/resources/web-tests.xml");
229         if (existingFile.exists()) {
230 
231             parseXMLFile(existingFile, pojoName);
232 
233             // Remove tests in run-all-tests target
234             Replace replace = (Replace) antProject.createTask("replace");
235             replace.setFile(existingFile);
236             replace.setToken("," + pojoName + "Tests");
237             replace.execute();
238         }
239     }
240 
241     private void parseXMLFile(File existingFile, String beanName) {
242         String nameInComment = beanName;
243         if (beanName == null) {
244             nameInComment = pojoName;
245         }
246         Replace replace1 = (Replace) antProject.createTask("replace");
247         replace1.setFile(existingFile);
248         replace1.setToken("<!--" + nameInComment + "-START-->");
249         replace1.setValue("REGULAR-START");
250         replace1.execute();
251 
252         Replace replace2 = (Replace) antProject.createTask("replace");
253         replace2.setFile(existingFile);
254         replace2.setToken("<!--" + nameInComment + "-END-->");
255         replace2.setValue("REGULAR-END");
256         replace2.execute();
257 
258         ReplaceRegExp regExpTask = (ReplaceRegExp) antProject.createTask("replaceregexp");
259         regExpTask.setFile(existingFile);
260         regExpTask.setMatch("REGULAR-START(?s:.)*REGULAR-END");
261         regExpTask.setReplace("");
262         regExpTask.setFlags("g");
263         regExpTask.execute();
264     }
265 
266     /**
267      * This file is the same as the method above, except for different comment placeholder formats.
268      * Yeah, I know, it's ugly.
269      *
270      * @param existingFile file to merge with in project
271      * @param beanName     name of placeholder string that goes in comment
272      */
273     private void parsePropertiesFile(File existingFile, String beanName) {
274         String nameInComment = beanName;
275         if (beanName == null) {
276             nameInComment = pojoName;
277         }
278 
279         Replace replace1 = (Replace) antProject.createTask("replace");
280         replace1.setFile(existingFile);
281         replace1.setToken("# -- " + nameInComment + "-START");
282         replace1.setValue("REGULAR-START");
283         replace1.execute();
284 
285         Replace replace2 = (Replace) antProject.createTask("replace");
286         replace2.setFile(existingFile);
287         replace2.setToken("# -- " + nameInComment + "-END");
288         replace2.setValue("REGULAR-END");
289         replace2.execute();
290 
291         ReplaceRegExp regExpTask = (ReplaceRegExp) antProject.createTask("replaceregexp");
292         regExpTask.setFile(existingFile);
293         regExpTask.setMatch("REGULAR-START(?s:.)*REGULAR-END");
294         regExpTask.setReplace("");
295         regExpTask.setFlags("g");
296         regExpTask.execute();
297     }
298 
299     private void log(String msg) {
300         getLog().info("[AppFuse] " + msg);
301     }
302 
303     public Log getLog() {
304         if (log == null) {
305             log = new SystemStreamLog();
306         }
307 
308         return log;
309     }
310 
311     public void setProject(MavenProject project) {
312         this.project = project;
313     }
314 
315     public void setGenericCore(boolean genericCore) {
316         this.genericCore = genericCore;
317     }
318 }