##### Coverage Report - org.owasp.dependencycheck.taskdefs.DependencyCheckTask

Classes in this File | Line Coverage | Branch Coverage | Complexity
DependencyCheckTask |
52% | 73/138
37% | 23/62
| 2.2285714285714286;2.229
DependencyCheckTask$ReportFormats |
100% | 7/7
100% | 2/2
| 2.2285714285714286;2.229

1 |  |
     /*
2 |  |
      * This file is part of dependency-check-ant.
3 |  |
      *
4 |  |
      * Dependency-check-ant is free software: you can redistribute it and/or modify it
5 |  |
      * under the terms of the GNU General Public License as published by the Free
6 |  |
      * Software Foundation, either version 3 of the License, or (at your option) any
7 |  |
      * later version.
8 |  |
      *
9 |  |
      * Dependency-check-ant is distributed in the hope that it will be useful, but
10 |  |
      * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 |  |
      * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 |  |
      * details.
13 |  |
      *
14 |  |
      * You should have received a copy of the GNU General Public License along with
15 |  |
      * dependency-check-ant. If not, see http://www.gnu.org/licenses/.
16 |  |
      *
17 |  |
      * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
18 |  |
      */
19 |  |
     package org.owasp.dependencycheck.taskdefs;
20 |  |
21 |  |
     import java.io.File;
22 |  |
     import java.io.IOException;
23 |  |
     import java.io.InputStream;
24 |  |
     import java.util.List;
25 |  |
     import java.util.logging.Level;
26 |  |
     import java.util.logging.Logger;
27 |  |
     import org.apache.tools.ant.BuildException;
28 |  |
     import org.apache.tools.ant.Task;
29 |  |
     import org.apache.tools.ant.types.EnumeratedAttribute;
30 |  |
     import org.apache.tools.ant.types.Reference;
31 |  |
     import org.apache.tools.ant.types.Resource;
32 |  |
     import org.apache.tools.ant.types.ResourceCollection;
33 |  |
     import org.apache.tools.ant.types.resources.FileProvider;
34 |  |
     import org.apache.tools.ant.types.resources.Resources;
35 |  |
     import org.owasp.dependencycheck.Engine;
36 |  |
     import org.owasp.dependencycheck.dependency.Dependency;
37 |  |
     import org.owasp.dependencycheck.dependency.Vulnerability;
38 |  |
     import org.owasp.dependencycheck.reporting.ReportGenerator;
39 |  |
     import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
40 |  |
     import org.owasp.dependencycheck.utils.LogUtils;
41 |  |
     import org.owasp.dependencycheck.utils.Settings;
42 |  |
43 |  |
     /**
44 |  |
      * An Ant task definition to execute dependency-check during an Ant build.
45 |  |
      *
46 |  |
      * @author Jeremy Long (jeremy.long@owasp.org)
47 |  |
      */
48 |  |
     public class DependencyCheckTask extends Task {
49 |  |
50 |  |
         /**
51 |  |
          * The properties file location.
52 |  |
          */
53 |  |
         private static final String PROPERTIES_FILE = "task.properties";
54 |  |
         /**
55 |  |
          * Name of the logging properties file.
56 |  |
          */
57 |  |
         private static final String LOG_PROPERTIES_FILE = "log.properties";
58 |  |
59 |  |
         /**
60 |  |
          * Construct a new DependencyCheckTask.
61 |  |
          */
62 |  |
         public DependencyCheckTask() {
63 | 4 |
             super();
64 | 4 |
         }
65 |  |
         //The following code was copied Apache Ant PathConvert
66 |  |
         //BEGIN COPY from org.apache.tools.ant.taskdefs.PathConvert
67 |  |
         /**
68 |  |
          * Path to be converted
69 |  |
          */
70 | 4 |
         private Resources path = null;
71 |  |
         /**
72 |  |
          * Reference to path/fileset to convert
73 |  |
          */
74 | 4 |
         private Reference refid = null;
75 |  |
76 |  |
         /**
77 |  |
          * Add an arbitrary ResourceCollection.
78 |  |
          *
79 |  |
          * @param rc the ResourceCollection to add.
80 |  |
          * @since Ant 1.7
81 |  |
          */
82 |  |
         public void add(ResourceCollection rc) {
83 | 4 |
             if (isReference()) {
84 | 0 |
                 throw new BuildException("Nested elements are not allowed when using the refid attribute.");
85 |  |
             }
86 | 4 |
             getPath().add(rc);
87 | 4 |
         }
88 |  |
89 |  |
         /**
90 |  |
          * Returns the path. If the path has not been initialized yet, this class is
91 |  |
          * synchronized, and will instantiate the path object.
92 |  |
          *
93 |  |
          * @return the path
94 |  |
          */
95 |  |
         private synchronized Resources getPath() {
96 | 4 |
             if (path == null) {
97 | 3 |
                 path = new Resources(getProject());
98 | 3 |
                 path.setCache(true);
99 |  |
             }
100 | 4 |
             return path;
101 |  |
         }
102 |  |
103 |  |
         /**
104 |  |
          * Learn whether the refid attribute of this element been set.
105 |  |
          *
106 |  |
          * @return true if refid is valid.
107 |  |
          */
108 |  |
         public boolean isReference() {
109 | 8 |
             return refid != null;
110 |  |
         }
111 |  |
112 |  |
         /**
113 |  |
          * Add a reference to a Path, FileSet, DirSet, or FileList defined
114 |  |
          * elsewhere.
115 |  |
          *
116 |  |
          * @param r the reference to a path, fileset, dirset or filelist.
117 |  |
          */
118 |  |
         public void setRefid(Reference r) {
119 | 0 |
             if (path != null) {
120 | 0 |
                 throw new BuildException("Nested elements are not allowed when using the refid attribute.");
121 |  |
             }
122 | 0 |
             refid = r;
123 | 0 |
         }
124 |  |
125 |  |
         /**
126 |  |
          * If this is a reference, this method will add the referenced resource
127 |  |
          * collection to the collection of paths.
128 |  |
          *
129 |  |
          * @throws BuildException if the reference is not to a resource collection
130 |  |
          */
131 |  |
         private void dealWithReferences() throws BuildException {
132 | 4 |
             if (isReference()) {
133 | 0 |
                 final Object o = refid.getReferencedObject(getProject());
134 | 0 |
                 if (!(o instanceof ResourceCollection)) {
135 | 0 |
                     throw new BuildException("refid '" + refid.getRefId()
136 |  |
                             + "' does not refer to a resource collection.");
137 |  |
                 }
138 | 0 |
                 getPath().add((ResourceCollection) o);
139 |  |
             }
140 | 4 |
         }
141 |  |
         // END COPY from org.apache.tools.ant.taskdefs
142 |  |
         /**
143 |  |
          * The application name for the report.
144 |  |
          */
145 | 4 |
         private String applicationName = "Dependency-Check";
146 |  |
147 |  |
         /**
148 |  |
          * Get the value of applicationName.
149 |  |
          *
150 |  |
          * @return the value of applicationName
151 |  |
          */
152 |  |
         public String getApplicationName() {
153 | 0 |
             return applicationName;
154 |  |
         }
155 |  |
156 |  |
         /**
157 |  |
          * Set the value of applicationName.
158 |  |
          *
159 |  |
          * @param applicationName new value of applicationName
160 |  |
          */
161 |  |
         public void setApplicationName(String applicationName) {
162 | 4 |
             this.applicationName = applicationName;
163 | 4 |
         }
164 |  |
         /**
165 |  |
          * The location of the data directory that contains
166 |  |
          */
167 | 4 |
         private String dataDirectory = null;
168 |  |
169 |  |
         /**
170 |  |
          * Get the value of dataDirectory.
171 |  |
          *
172 |  |
          * @return the value of dataDirectory
173 |  |
          */
174 |  |
         public String getDataDirectory() {
175 | 0 |
             return dataDirectory;
176 |  |
         }
177 |  |
178 |  |
         /**
179 |  |
          * Set the value of dataDirectory.
180 |  |
          *
181 |  |
          * @param dataDirectory new value of dataDirectory
182 |  |
          */
183 |  |
         public void setDataDirectory(String dataDirectory) {
184 | 0 |
             this.dataDirectory = dataDirectory;
185 | 0 |
         }
186 |  |
         /**
187 |  |
          * Specifies the destination directory for the generated Dependency-Check
188 |  |
          * report.
189 |  |
          */
190 | 4 |
         private String reportOutputDirectory = ".";
191 |  |
192 |  |
         /**
193 |  |
          * Get the value of reportOutputDirectory.
194 |  |
          *
195 |  |
          * @return the value of reportOutputDirectory
196 |  |
          */
197 |  |
         public String getReportOutputDirectory() {
198 | 0 |
             return reportOutputDirectory;
199 |  |
         }
200 |  |
201 |  |
         /**
202 |  |
          * Set the value of reportOutputDirectory.
203 |  |
          *
204 |  |
          * @param reportOutputDirectory new value of reportOutputDirectory
205 |  |
          */
206 |  |
         public void setReportOutputDirectory(String reportOutputDirectory) {
207 | 4 |
             this.reportOutputDirectory = reportOutputDirectory;
208 | 4 |
         }
209 |  |
         /**
210 |  |
          * Specifies if the build should be failed if a CVSS score above a specified
211 |  |
          * level is identified. The default is 11 which means since the CVSS scores
212 |  |
          * are 0-10, by default the build will never fail and the CVSS score is set
213 |  |
          * to 11. The valid range for the fail build on CVSS is 0 to 11, where
214 |  |
          * anything above 10 will not cause the build to fail.
215 |  |
          */
216 | 4 |
         private float failBuildOnCVSS = 11;
217 |  |
218 |  |
         /**
219 |  |
          * Get the value of failBuildOnCVSS.
220 |  |
          *
221 |  |
          * @return the value of failBuildOnCVSS
222 |  |
          */
223 |  |
         public float getFailBuildOnCVSS() {
224 | 0 |
             return failBuildOnCVSS;
225 |  |
         }
226 |  |
227 |  |
         /**
228 |  |
          * Set the value of failBuildOnCVSS.
229 |  |
          *
230 |  |
          * @param failBuildOnCVSS new value of failBuildOnCVSS
231 |  |
          */
232 |  |
         public void setFailBuildOnCVSS(float failBuildOnCVSS) {
233 | 1 |
             this.failBuildOnCVSS = failBuildOnCVSS;
234 | 1 |
         }
235 |  |
         /**
236 |  |
          * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
237 |  |
          * recommended that this be turned to false. Default is true.
238 |  |
          */
239 | 4 |
         private boolean autoUpdate = true;
240 |  |
241 |  |
         /**
242 |  |
          * Get the value of autoUpdate.
243 |  |
          *
244 |  |
          * @return the value of autoUpdate
245 |  |
          */
246 |  |
         public boolean isAutoUpdate() {
247 | 0 |
             return autoUpdate;
248 |  |
         }
249 |  |
250 |  |
         /**
251 |  |
          * Set the value of autoUpdate.
252 |  |
          *
253 |  |
          * @param autoUpdate new value of autoUpdate
254 |  |
          */
255 |  |
         public void setAutoUpdate(boolean autoUpdate) {
256 | 4 |
             this.autoUpdate = autoUpdate;
257 | 4 |
         }
258 |  |
         /**
259 |  |
          * The report format to be generated (HTML, XML, VULN, ALL). This
260 |  |
          * configuration option has no affect if using this within the Site plugin
261 |  |
          * unless the externalReport is set to true. Default is HTML.
262 |  |
          */
263 | 4 |
         private String reportFormat = "HTML";
264 |  |
265 |  |
         /**
266 |  |
          * Get the value of reportFormat.
267 |  |
          *
268 |  |
          * @return the value of reportFormat
269 |  |
          */
270 |  |
         public String getReportFormat() {
271 | 0 |
             return reportFormat;
272 |  |
         }
273 |  |
274 |  |
         /**
275 |  |
          * Set the value of reportFormat.
276 |  |
          *
277 |  |
          * @param reportFormat new value of reportFormat
278 |  |
          */
279 |  |
         public void setReportFormat(ReportFormats reportFormat) {
280 | 4 |
             this.reportFormat = reportFormat.getValue();
281 | 4 |
         }
282 |  |
         /**
283 |  |
          * The Proxy URL.
284 |  |
          */
285 |  |
         private String proxyUrl;
286 |  |
287 |  |
         /**
288 |  |
          * Get the value of proxyUrl.
289 |  |
          *
290 |  |
          * @return the value of proxyUrl
291 |  |
          */
292 |  |
         public String getProxyUrl() {
293 | 0 |
             return proxyUrl;
294 |  |
         }
295 |  |
296 |  |
         /**
297 |  |
          * Set the value of proxyUrl.
298 |  |
          *
299 |  |
          * @param proxyUrl new value of proxyUrl
300 |  |
          */
301 |  |
         public void setProxyUrl(String proxyUrl) {
302 | 0 |
             this.proxyUrl = proxyUrl;
303 | 0 |
         }
304 |  |
         /**
305 |  |
          * The Proxy Port.
306 |  |
          */
307 |  |
         private String proxyPort;
308 |  |
309 |  |
         /**
310 |  |
          * Get the value of proxyPort.
311 |  |
          *
312 |  |
          * @return the value of proxyPort
313 |  |
          */
314 |  |
         public String getProxyPort() {
315 | 0 |
             return proxyPort;
316 |  |
         }
317 |  |
318 |  |
         /**
319 |  |
          * Set the value of proxyPort.
320 |  |
          *
321 |  |
          * @param proxyPort new value of proxyPort
322 |  |
          */
323 |  |
         public void setProxyPort(String proxyPort) {
324 | 0 |
             this.proxyPort = proxyPort;
325 | 0 |
         }
326 |  |
327 |  |
         /**
328 |  |
          * The Proxy username.
329 |  |
          */
330 |  |
         private String proxyUsername;
331 |  |
332 |  |
         /**
333 |  |
          * Get the value of proxyUsername.
334 |  |
          *
335 |  |
          * @return the value of proxyUsername
336 |  |
          */
337 |  |
         public String getProxyUsername() {
338 | 0 |
             return proxyUsername;
339 |  |
         }
340 |  |
341 |  |
         /**
342 |  |
          * Set the value of proxyUsername.
343 |  |
          *
344 |  |
          * @param proxyUsername new value of proxyUsername
345 |  |
          */
346 |  |
         public void setProxyUsername(String proxyUsername) {
347 | 0 |
             this.proxyUsername = proxyUsername;
348 | 0 |
         }
349 |  |
350 |  |
         /**
351 |  |
          * The Proxy password.
352 |  |
          */
353 |  |
         private String proxyPassword;
354 |  |
355 |  |
         /**
356 |  |
          * Get the value of proxyPassword.
357 |  |
          *
358 |  |
          * @return the value of proxyPassword
359 |  |
          */
360 |  |
         public String getProxyPassword() {
361 | 0 |
             return proxyPassword;
362 |  |
         }
363 |  |
364 |  |
         /**
365 |  |
          * Set the value of proxyPassword.
366 |  |
          *
367 |  |
          * @param proxyPassword new value of proxyPassword
368 |  |
          */
369 |  |
         public void setProxyPassword(String proxyPassword) {
370 | 0 |
             this.proxyPassword = proxyPassword;
371 | 0 |
         }
372 |  |
373 |  |
         /**
374 |  |
          * The Connection Timeout.
375 |  |
          */
376 |  |
         private String connectionTimeout;
377 |  |
378 |  |
         /**
379 |  |
          * Get the value of connectionTimeout.
380 |  |
          *
381 |  |
          * @return the value of connectionTimeout
382 |  |
          */
383 |  |
         public String getConnectionTimeout() {
384 | 0 |
             return connectionTimeout;
385 |  |
         }
386 |  |
387 |  |
         /**
388 |  |
          * Set the value of connectionTimeout.
389 |  |
          *
390 |  |
          * @param connectionTimeout new value of connectionTimeout
391 |  |
          */
392 |  |
         public void setConnectionTimeout(String connectionTimeout) {
393 | 0 |
             this.connectionTimeout = connectionTimeout;
394 | 0 |
         }
395 |  |
         /**
396 |  |
          * The file path used for verbose logging.
397 |  |
          */
398 | 4 |
         private String logFile = null;
399 |  |
400 |  |
         /**
401 |  |
          * Get the value of logFile.
402 |  |
          *
403 |  |
          * @return the value of logFile
404 |  |
          */
405 |  |
         public String getLogFile() {
406 | 0 |
             return logFile;
407 |  |
         }
408 |  |
409 |  |
         /**
410 |  |
          * Set the value of logFile.
411 |  |
          *
412 |  |
          * @param logFile new value of logFile
413 |  |
          */
414 |  |
         public void setLogFile(String logFile) {
415 | 0 |
             this.logFile = logFile;
416 | 0 |
         }
417 |  |
418 |  |
         @Override
419 |  |
         public void execute() throws BuildException {
420 | 4 |
             final InputStream in = DependencyCheckTask.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
421 | 4 |
             LogUtils.prepareLogger(in, logFile);
422 |  |
423 | 4 |
             dealWithReferences();
424 | 4 |
             validateConfiguration();
425 | 3 |
             populateSettings();
426 |  |
427 | 3 |
             final Engine engine = new Engine();
428 | 3 |
             for (Resource resource : path) {
429 | 5 |
                 final FileProvider provider = resource.as(FileProvider.class);
430 | 5 |
                 if (provider != null) {
431 | 5 |
                     final File file = provider.getFile();
432 | 5 |
                     if (file != null && file.exists()) {
433 | 4 |
                         engine.scan(file);
434 |  |
                     }
435 |  |
                 }
436 | 5 |
             }
437 |  |
             try {
438 | 3 |
                 engine.analyzeDependencies();
439 | 3 |
                 final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers());
440 | 3 |
                 reporter.generateReports(reportOutputDirectory, reportFormat);
441 |  |
442 | 3 |
                 if (this.failBuildOnCVSS <= 10) {
443 | 0 |
                     checkForFailure(engine.getDependencies());
444 |  |
                 }
445 | 0 |
             } catch (IOException ex) {
446 | 0 |
                 Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, null, ex);
447 | 0 |
                 throw new BuildException("Unable to generate dependency-check report", ex);
448 | 0 |
             } catch (Exception ex) {
449 | 0 |
                 Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.SEVERE, null, ex);
450 | 0 |
                 throw new BuildException("An exception occured; unable to continue task", ex);
451 | 3 |
             }
452 | 3 |
         }
453 |  |
454 |  |
         /**
455 |  |
          * Validate the configuration to ensure the parameters have been properly
456 |  |
          * configured/initialized.
457 |  |
          *
458 |  |
          * @throws BuildException if the task was not configured correctly.
459 |  |
          */
460 |  |
         private void validateConfiguration() throws BuildException {
461 | 4 |
             if (path == null) {
462 | 1 |
                 throw new BuildException("No project dependencies have been defined to analyze.");
463 |  |
             }
464 | 3 |
             if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) {
465 | 0 |
                 throw new BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11.");
466 |  |
             }
467 | 3 |
         }
468 |  |
469 |  |
         /**
470 |  |
          * Takes the properties supplied and updates the dependency-check settings.
471 |  |
          * Additionally, this sets the system properties required to change the
472 |  |
          * proxy url, port, and connection timeout.
473 |  |
          */
474 |  |
         private void populateSettings() {
475 | 3 |
             InputStream taskProperties = null;
476 |  |
             try {
477 | 3 |
                 taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
478 | 3 |
                 Settings.mergeProperties(taskProperties);
479 | 0 |
             } catch (IOException ex) {
480 | 0 |
                 Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
481 | 0 |
                 Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, null, ex);
482 |  |
             } finally {
483 | 3 |
                 if (taskProperties != null) {
484 |  |
                     try {
485 | 3 |
                         taskProperties.close();
486 | 0 |
                     } catch (IOException ex) {
487 | 0 |
                         Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINEST, null, ex);
488 | 3 |
                     }
489 |  |
                 }
490 |  |
             }
491 | 3 |
             if (dataDirectory != null) {
492 | 0 |
                 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
493 |  |
             } else {
494 | 3 |
                 final File jarPath = new File(DependencyCheckTask.class.getProtectionDomain().getCodeSource().getLocation().getPath());
495 | 3 |
                 final File base = jarPath.getParentFile();
496 | 3 |
                 final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
497 | 3 |
                 final File dataDir = new File(base, sub);
498 | 3 |
                 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
499 |  |
             }
500 |  |
501 | 3 |
             Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
502 |  |
503 | 3 |
             if (proxyUrl != null && !proxyUrl.isEmpty()) {
504 | 0 |
                 Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
505 |  |
             }
506 | 3 |
             if (proxyPort != null && !proxyPort.isEmpty()) {
507 | 0 |
                 Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
508 |  |
             }
509 | 3 |
             if (proxyUsername != null && !proxyUsername.isEmpty()) {
510 | 0 |
                 Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername);
511 |  |
             }
512 | 3 |
             if (proxyPassword != null && !proxyPassword.isEmpty()) {
513 | 0 |
                 Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
514 |  |
             }
515 | 3 |
             if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
516 | 0 |
                 Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
517 |  |
             }
518 | 3 |
         }
519 |  |
520 |  |
         /**
521 |  |
          * Checks to see if a vulnerability has been identified with a CVSS score
522 |  |
          * that is above the threshold set in the configuration.
523 |  |
          *
524 |  |
          * @param dependencies the list of dependency objects
525 |  |
          * @throws BuildException thrown if a CVSS score is found that is higher
526 |  |
          * then the threshold set
527 |  |
          */
528 |  |
         private void checkForFailure(List<Dependency> dependencies) throws BuildException {
529 | 0 |
             final StringBuilder ids = new StringBuilder();
530 | 0 |
             for (Dependency d : dependencies) {
531 | 0 |
                 for (Vulnerability v : d.getVulnerabilities()) {
532 | 0 |
                     if (v.getCvssScore() >= failBuildOnCVSS) {
533 | 0 |
                         if (ids.length() == 0) {
534 | 0 |
                             ids.append(v.getName());
535 |  |
                         } else {
536 | 0 |
                             ids.append(", ").append(v.getName());
537 |  |
                         }
538 |  |
                     }
539 |  |
                 }
540 |  |
             }
541 | 0 |
             if (ids.length() > 0) {
542 | 0 |
                 final String msg = String.format("%n%nDependency-Check Failure:%n"
543 |  |
                         + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
544 |  |
                         + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
545 | 0 |
                 throw new BuildException(msg);
546 |  |
             }
547 | 0 |
         }
548 |  |
549 |  |
         /**
550 |  |
          * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN",
551 |  |
          * etc..
552 |  |
          */
553 | 4 |
         public static class ReportFormats extends EnumeratedAttribute {
554 |  |
555 |  |
             /**
556 |  |
              * Returns the list of values for the report format.
557 |  |
              *
558 |  |
              * @return the list of values for the report format
559 |  |
              */
560 |  |
             @Override
561 |  |
             public String[] getValues() {
562 | 4 |
                 int i = 0;
563 | 4 |
                 final Format[] formats = Format.values();
564 | 4 |
                 final String[] values = new String[formats.length];
565 | 20 |
                 for (Format format : formats) {
566 | 16 |
                     values[i++] = format.name();
567 |  |
                 }
568 | 4 |
                 return values;
569 |  |
             }
570 |  |
         }
571 |  |
     }