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