1 package net.sf.mvnflexreports; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.util.ArrayList; 7 import java.util.HashSet; 8 import java.util.List; 9 import java.util.Locale; 10 import java.util.Map; 11 import java.util.ResourceBundle; 12 import java.util.Set; 13 import java.util.TreeMap; 14 15 import javax.xml.namespace.QName; 16 import javax.xml.stream.XMLInputFactory; 17 import javax.xml.stream.XMLStreamConstants; 18 import javax.xml.stream.XMLStreamException; 19 import javax.xml.stream.XMLStreamReader; 20 21 import org.apache.maven.doxia.siterenderer.Renderer; 22 import org.apache.maven.project.MavenProject; 23 import org.apache.maven.reporting.MavenReportException; 24 25 /*** 26 * @author RĂ©mi Flament 27 * @goal remoteobject-maven-report 28 * @phase site 29 */ 30 public class RemoteObjectMavenReport extends AbstractGraphvizMavenReport { 31 32 /*** 33 * The output directory for the final HTML report. Note that this parameter 34 * is only evaluated if the goal is run directly from the command line or 35 * during the default lifecycle. If the goal is run indirectly as part of a 36 * site generation, the output directory configured in the Maven Site Plugin 37 * is used instead. 38 * 39 * @parameter expression="${project.reporting.outputDirectory}" 40 * @required 41 */ 42 protected File outputDirectory; 43 44 /*** 45 * The project to analyse. 46 * 47 * @parameter expression="${project}" 48 * @required 49 * @readonly 50 */ 51 protected MavenProject project; 52 53 /*** 54 * The directory containing source code to parse. 55 * 56 * @parameter expression="${basedir}/src/main/flex" 57 * @required 58 */ 59 private File sourceDir; 60 61 /*** 62 * The layout to use. This parameter will be used as the rankdir parameter. 63 * 64 * @parameter expression="TB" 65 */ 66 protected String remoteObjectLayout; 67 68 /*** 69 * @parameter 70 */ 71 private Set<String> remoteObjectPatterns; 72 73 /*** 74 * @parameter 75 */ 76 private Set<String> remoteMethodPatterns; 77 78 /*** 79 * The fill color for remote objects in the graphical report 80 * 81 * @parameter expression="cornflowerblue" 82 */ 83 private String remoteObjectColor; 84 85 /*** 86 * The fill color for mxml components in the graphical report 87 * 88 * @parameter expression="firebrick1" 89 */ 90 private String mxmlComponentColor; 91 92 /*** 93 * Site rendering component for generating the HTML report. 94 * 95 * @component 96 */ 97 private Renderer siteRenderer; 98 99 protected void executeReport(Locale locale) throws MavenReportException { 100 101 if (remoteObjectPatterns == null) { 102 remoteObjectPatterns = new HashSet<String>(); 103 } 104 105 if (remoteMethodPatterns == null) { 106 remoteMethodPatterns = new HashSet<String>(); 107 } 108 109 if (remoteObjectPatterns.size() == 0) { 110 remoteObjectPatterns.add("RemoteObject"); 111 } 112 113 if (remoteMethodPatterns.size() == 0) { 114 remoteMethodPatterns.add("method"); 115 } 116 117 List<File> files = new ArrayList<File>(); 118 getFiles(sourceDir.getAbsoluteFile(), files, ".as", ".mxml"); 119 ClassLoader origLoader = Thread.currentThread().getContextClassLoader(); 120 121 try { 122 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); 123 Map<String, RemoteObject> remoteObjects = new TreeMap<String, RemoteObject>(); 124 Map<String, MXMLComponent> components = new TreeMap<String, MXMLComponent>(); 125 for (File sourceFile : files) { 126 getLog().debug("Processing flex source file " + sourceFile.getCanonicalPath()); 127 findRemoteObjects(sourceFile, remoteObjects, components); 128 } 129 130 RemoteObjectReportGenerator generator = new RemoteObjectReportGenerator(getSink()); 131 generator.setMxmlComponentColor(mxmlComponentColor); 132 generator.setRemoteObjectColor(remoteObjectColor); 133 generator.setFontName(fontName); 134 generator.setFontSize(fontSize); 135 generator.setProgramName(programName); 136 generator.setLayout(remoteObjectLayout); 137 getLog().debug("mxmlComponentColor = " + mxmlComponentColor); 138 getLog().debug("remoteObjectColor = " + remoteObjectColor); 139 generator.generate(remoteObjects.values(), components.values(), this.getReportOutputDirectory(), getLog()); 140 141 } catch (Exception e) { 142 throw new MavenReportException(e.getMessage(), e); 143 } finally { 144 Thread.currentThread().setContextClassLoader(origLoader); 145 } 146 147 } 148 149 private void findRemoteObjects(File file, Map<String, RemoteObject> remoteObjects, Map<String, MXMLComponent> components) throws FileNotFoundException, XMLStreamException { 150 151 getLog().debug("getUsedRemoteObjects() for file " + file.getAbsolutePath()); 152 153 MXMLComponent currentComponent = null; 154 155 if (file.getName().toLowerCase().endsWith(".mxml")) { 156 157 currentComponent = components.get(file.getName()); 158 if (currentComponent == null) { 159 currentComponent = new MXMLComponent(); 160 currentComponent.setFilename(file.getName()); 161 components.put(file.getName(), currentComponent); 162 } 163 164 XMLInputFactory factory = XMLInputFactory.newInstance(); 165 XMLStreamReader parser = factory.createXMLStreamReader(new FileInputStream(file)); 166 167 RemoteObject currentRemoteObject = null; 168 RemoteObjectUse currentRemoteObjectUse = null; 169 while (true) { 170 int event = parser.next(); 171 if (event == XMLStreamConstants.END_DOCUMENT) { 172 parser.close(); 173 break; 174 } 175 if (event == XMLStreamConstants.START_ELEMENT) { 176 177 if (remoteObjectPatterns.contains(parser.getLocalName())) { 178 179 String destination = null; 180 String id = null; 181 String type = parser.getLocalName(); 182 for (int i = 0; i < parser.getAttributeCount(); i++) { 183 QName localName = parser.getAttributeName(i); 184 if (localName.getLocalPart().equals("destination")) { 185 186 destination = parser.getAttributeValue(i); 187 getLog().debug(file.getAbsolutePath() + " uses remote object " + destination); 188 189 currentRemoteObject = remoteObjects.get(destination); 190 if (currentRemoteObject == null) { 191 currentRemoteObject = new RemoteObject(); 192 currentRemoteObject.setDestination(destination); 193 194 remoteObjects.put(destination, currentRemoteObject); 195 } 196 currentRemoteObject.increment(); 197 198 } 199 200 if (localName.getLocalPart().equals("id")) { 201 id = parser.getAttributeValue(i); 202 } 203 204 } 205 206 if (id != null && destination != null) { 207 currentRemoteObjectUse = currentComponent.getUsedRemoteObjects().get(destination + "#" + id); 208 if (currentRemoteObjectUse == null) { 209 currentRemoteObjectUse = new RemoteObjectUse(); 210 currentRemoteObjectUse.setDestination(destination); 211 currentRemoteObjectUse.setRemoteObject(currentRemoteObject); 212 currentRemoteObjectUse.setId(id); 213 currentRemoteObjectUse.setRemoteObjectType(type); 214 currentComponent.getUsedRemoteObjects().put(destination + "#" + id, currentRemoteObjectUse); 215 } 216 currentRemoteObjectUse.setComponent(currentComponent); 217 } 218 219 } else if (remoteMethodPatterns.contains(parser.getLocalName()) && currentRemoteObject != null) { 220 for (int i = 0; i < parser.getAttributeCount(); i++) { 221 QName localName = parser.getAttributeName(i); 222 if (localName.getLocalPart().equals("name")) { 223 224 String methodName = parser.getAttributeValue(i); 225 getLog().debug(file.getAbsolutePath() + " uses method " + methodName + " on remote object " + currentRemoteObject.getDestination()); 226 RemoteObjectMethod method = currentRemoteObject.getMethods().get(methodName); 227 if (method == null) { 228 method = new RemoteObjectMethod(); 229 method.setName(methodName); 230 231 currentRemoteObject.getMethods().put(methodName, method); 232 } 233 234 method.increment(); 235 if (currentRemoteObjectUse != null) { 236 currentRemoteObjectUse.getUsedMethods().add(method); 237 } 238 } 239 } 240 } 241 } 242 243 } 244 245 } else if (file.getName().toLowerCase().endsWith(".as")) { 246 getLog().debug("ignoring " + file.getAbsolutePath() + " : not implemented yet"); 247 } else { 248 getLog().info("ignoring " + file.getAbsolutePath() + " because we don't know how to search remote objects in it."); 249 } 250 251 } 252 253 /*** 254 * @return Returns the sourceDir. 255 */ 256 public File getSourceDir() { 257 return sourceDir; 258 } 259 260 /*** 261 * @param sourceDir 262 * The sourceDir to set. 263 */ 264 public void setSourceDir(File sourceDir) { 265 this.sourceDir = sourceDir; 266 } 267 268 protected String getOutputDirectory() { 269 return outputDirectory.getAbsolutePath(); 270 271 } 272 273 protected MavenProject getProject() { 274 return project; 275 } 276 277 protected Renderer getSiteRenderer() { 278 return siteRenderer; 279 } 280 281 public String getDescription(Locale locale) { 282 return getBundle(locale).getString("report.remoteobject-flex-maven.name"); 283 284 } 285 286 public String getName(Locale locale) { 287 return getBundle(locale).getString("report.remoteobject-flex-maven.name"); 288 289 } 290 291 private static ResourceBundle getBundle(Locale locale) { 292 return ResourceBundle.getBundle("remoteobject-maven-report", locale, RemoteObjectMavenReport.class.getClassLoader()); 293 } 294 295 public String getOutputName() { 296 return "remoteobject-maven-report"; 297 } 298 299 public Set<String> getRemoteObjectPatterns() { 300 return remoteObjectPatterns; 301 } 302 303 public void setRemoteObjectPatterns(Set<String> remoteObjectPatterns) { 304 this.remoteObjectPatterns = remoteObjectPatterns; 305 } 306 307 public Set<String> getRemoteMethodPatterns() { 308 return remoteMethodPatterns; 309 } 310 311 public void setRemoteMethodPatterns(Set<String> remoteMethodPatterns) { 312 this.remoteMethodPatterns = remoteMethodPatterns; 313 } 314 315 public String getRemoteObjectColor() { 316 return remoteObjectColor; 317 } 318 319 public void setRemoteObjectColor(String remoteObjectColor) { 320 this.remoteObjectColor = remoteObjectColor; 321 } 322 323 public String getMxmlComponentColor() { 324 return mxmlComponentColor; 325 } 326 327 public void setMxmlComponentColor(String mxmlComponentColor) { 328 this.mxmlComponentColor = mxmlComponentColor; 329 } 330 331 public String getRemoteObjectLayout() { 332 return remoteObjectLayout; 333 } 334 335 public void setRemoteObjectLayout(String remoteObjectLayout) { 336 this.remoteObjectLayout = remoteObjectLayout; 337 } 338 339 }