001/* 002 * Copyright (C) 2005 Christian Schulte <cs@schulte.it> 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions 007 * are met: 008 * 009 * o Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 012 * o Redistributions in binary form must reproduce the above copyright 013 * notice, this list of conditions and the following disclaimer in 014 * the documentation and/or other materials provided with the 015 * distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 027 * 028 * $JOMC: AbstractJomcMojo.java 5328 2016-09-01 01:05:43Z schulte $ 029 * 030 */ 031package org.jomc.mojo; 032 033import java.io.BufferedReader; 034import java.io.File; 035import java.io.FileInputStream; 036import java.io.FileOutputStream; 037import java.io.IOException; 038import java.io.InputStream; 039import java.io.OutputStream; 040import java.io.StringReader; 041import java.io.StringWriter; 042import java.net.HttpURLConnection; 043import java.net.MalformedURLException; 044import java.net.SocketTimeoutException; 045import java.net.URI; 046import java.net.URISyntaxException; 047import java.net.URL; 048import java.net.URLClassLoader; 049import java.net.URLConnection; 050import java.util.Collection; 051import java.util.Date; 052import java.util.HashSet; 053import java.util.Iterator; 054import java.util.List; 055import java.util.Locale; 056import java.util.Map; 057import java.util.Properties; 058import java.util.Set; 059import java.util.concurrent.ExecutorService; 060import java.util.concurrent.Executors; 061import java.util.concurrent.ThreadFactory; 062import java.util.concurrent.atomic.AtomicInteger; 063import java.util.logging.Level; 064import javax.xml.bind.JAXBException; 065import javax.xml.bind.Marshaller; 066import javax.xml.transform.ErrorListener; 067import javax.xml.transform.Transformer; 068import javax.xml.transform.TransformerConfigurationException; 069import javax.xml.transform.TransformerException; 070import javax.xml.transform.TransformerFactory; 071import javax.xml.transform.stream.StreamSource; 072import org.apache.commons.lang.StringEscapeUtils; 073import org.apache.commons.lang.StringUtils; 074import org.apache.maven.artifact.Artifact; 075import org.apache.maven.artifact.ArtifactUtils; 076import org.apache.maven.execution.MavenSession; 077import org.apache.maven.plugin.AbstractMojo; 078import org.apache.maven.plugin.MojoExecutionException; 079import org.apache.maven.plugin.MojoFailureException; 080import org.apache.maven.plugin.descriptor.MojoDescriptor; 081import org.apache.maven.plugins.annotations.Parameter; 082import org.apache.maven.project.MavenProject; 083import org.jomc.model.Module; 084import org.jomc.model.Modules; 085import org.jomc.model.modlet.DefaultModelProcessor; 086import org.jomc.model.modlet.DefaultModelProvider; 087import org.jomc.model.modlet.DefaultModelValidator; 088import org.jomc.model.modlet.ModelHelper; 089import org.jomc.modlet.DefaultModelContext; 090import org.jomc.modlet.DefaultModletProvider; 091import org.jomc.modlet.Model; 092import org.jomc.modlet.ModelContext; 093import org.jomc.modlet.ModelContextFactory; 094import org.jomc.modlet.ModelException; 095import org.jomc.modlet.ModelValidationReport; 096import org.jomc.modlet.Modlet; 097import org.jomc.modlet.Modlets; 098import org.jomc.tools.ClassFileProcessor; 099import org.jomc.tools.JomcTool; 100import org.jomc.tools.ResourceFileProcessor; 101import org.jomc.tools.SourceFileProcessor; 102import org.jomc.tools.modlet.ToolsModelProcessor; 103import org.jomc.tools.modlet.ToolsModelProvider; 104 105/** 106 * Base class for executing {@code JomcTool}s. 107 * 108 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 109 * @version $JOMC: AbstractJomcMojo.java 5328 2016-09-01 01:05:43Z schulte $ 110 */ 111public abstract class AbstractJomcMojo extends AbstractMojo 112{ 113 114 /** 115 * The encoding to use for reading and writing files. 116 */ 117 @Parameter( name = "sourceEncoding", 118 property = "jomc.sourceEncoding", 119 defaultValue = "${project.build.sourceEncoding}" ) 120 private String sourceEncoding; 121 122 /** 123 * The encoding to use for reading templates. 124 * <p> 125 * <strong>Deprecated:</strong> As of JOMC 1.3, please use the 'defaultTemplateEncoding' parameter. This 126 * parameter will be removed in version 2.0. 127 * </p> 128 */ 129 @Deprecated 130 @Parameter( name = "templateEncoding", 131 property = "jomc.templateEncoding" ) 132 private String templateEncoding; 133 134 /** 135 * The encoding to use for reading templates. 136 * 137 * @since 1.3 138 */ 139 @Parameter( name = "defaultTemplateEncoding", 140 property = "jomc.defaultTemplateEncoding" ) 141 private String defaultTemplateEncoding; 142 143 /** 144 * Location to search for templates in addition to searching the class path of the plugin. 145 * <p> 146 * First an attempt is made to parse the location value to an URL. On successful parsing, that URL is used. 147 * Otherwise the location value is interpreted as a directory name relative to the base directory of the project. 148 * If that directory exists, that directory is used. If nothing is found at the given location, a warning message is 149 * logged. 150 * </p> 151 * 152 * @since 1.2 153 */ 154 @Parameter( name = "templateLocation", 155 property = "jomc.templateLocation" ) 156 private String templateLocation; 157 158 /** 159 * The template profile to use when accessing templates. 160 */ 161 @Parameter( name = "templateProfile", 162 property = "jomc.templateProfile" ) 163 private String templateProfile; 164 165 /** 166 * The default template profile to use when accessing templates. 167 */ 168 @Parameter( name = "defaultTemplateProfile", 169 property = "jomc.defaultTemplateProfile" ) 170 private String defaultTemplateProfile; 171 172 /** 173 * The location to search for providers. 174 */ 175 @Parameter( name = "providerLocation", 176 property = "jomc.providerLocation" ) 177 private String providerLocation; 178 179 /** 180 * The location to search for platform providers. 181 */ 182 @Parameter( name = "platformProviderLocation", 183 property = "jomc.platformProviderLocation" ) 184 private String platformProviderLocation; 185 186 /** 187 * The identifier of the model to process. 188 */ 189 @Parameter( name = "model", 190 property = "jomc.model", 191 defaultValue = "http://jomc.org/model" ) 192 private String model; 193 194 /** 195 * The name of the {@code ModelContextFactory} implementation class backing the task. 196 * 197 * @since 1.2 198 */ 199 @Parameter( name = "modelContextFactoryClassName", 200 property = "jomc.modelContextFactoryClassName" ) 201 private String modelContextFactoryClassName; 202 203 /** 204 * The location to search for modlets. 205 */ 206 @Parameter( name = "modletLocation", 207 property = "jomc.modletLocation" ) 208 private String modletLocation; 209 210 /** 211 * The {@code http://jomc.org/modlet} namespace schema system id. 212 * 213 * @since 1.2 214 */ 215 @Parameter( name = "modletSchemaSystemId", 216 property = "jomc.modletSchemaSystemId" ) 217 private String modletSchemaSystemId; 218 219 /** 220 * The location to search for modules. 221 */ 222 @Parameter( name = "moduleLocation", 223 property = "jomc.moduleLocation" ) 224 private String moduleLocation; 225 226 /** 227 * The location to search for transformers. 228 */ 229 @Parameter( name = "transformerLocation", 230 property = "jomc.transformerLocation" ) 231 private String transformerLocation; 232 233 /** 234 * The indentation string ('\t' for tab). 235 */ 236 @Parameter( name = "indentation", 237 property = "jomc.indentation" ) 238 private String indentation; 239 240 /** 241 * The line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix). 242 */ 243 @Parameter( name = "lineSeparator", 244 property = "jomc.lineSeparator" ) 245 private String lineSeparator; 246 247 /** 248 * The locale. 249 * <pre> 250 * <locale> 251 * <language>Lowercase two-letter ISO-639 code.</language> 252 * <country>Uppercase two-letter ISO-3166 code.</country> 253 * <variant>Vendor and browser specific code.</variant> 254 * </locale> 255 * </pre> 256 * 257 * @since 1.2 258 * @see Locale 259 */ 260 @Parameter( name = "locale" ) 261 private LocaleType locale; 262 263 /** 264 * Controls verbosity of the plugin. 265 */ 266 @Parameter( name = "verbose", 267 property = "jomc.verbose", 268 defaultValue = "false" ) 269 private boolean verbose; 270 271 /** 272 * Controls processing of source code files. 273 */ 274 @Parameter( name = "sourceProcessingEnabled", 275 property = "jomc.sourceProcessing", 276 defaultValue = "true" ) 277 private boolean sourceProcessingEnabled; 278 279 /** 280 * Controls processing of resource files. 281 */ 282 @Parameter( name = "resourceProcessingEnabled", 283 property = "jomc.resourceProcessing", 284 defaultValue = "true" ) 285 private boolean resourceProcessingEnabled; 286 287 /** 288 * Controls processing of class files. 289 */ 290 @Parameter( name = "classProcessingEnabled", 291 property = "jomc.classProcessing", 292 defaultValue = "true" ) 293 private boolean classProcessingEnabled; 294 295 /** 296 * Controls processing of models. 297 */ 298 @Parameter( name = "modelProcessingEnabled", 299 property = "jomc.modelProcessing", 300 defaultValue = "true" ) 301 private boolean modelProcessingEnabled; 302 303 /** 304 * Controls model object class path resolution. 305 */ 306 @Parameter( name = "modelObjectClasspathResolutionEnabled", 307 property = "jomc.modelObjectClasspathResolution", 308 defaultValue = "true" ) 309 private boolean modelObjectClasspathResolutionEnabled; 310 311 /** 312 * Name of the module to process. 313 */ 314 @Parameter( name = "moduleName", 315 property = "jomc.moduleName", 316 defaultValue = "${project.name}" ) 317 private String moduleName; 318 319 /** 320 * Name of the test module to process. 321 */ 322 @Parameter( name = "testModuleName", 323 property = "jomc.testModuleName", 324 defaultValue = "${project.name} Tests" ) 325 private String testModuleName; 326 327 /** 328 * Directory holding the compiled class files of the project. 329 * <p> 330 * <strong>Deprecated:</strong> As of JOMC 1.1, please use the 'outputDirectory' parameter. This parameter will 331 * be removed in version 2.0. 332 * </p> 333 */ 334 @Deprecated 335 @Parameter( name = "classesDirectory" ) 336 private String classesDirectory; 337 338 /** 339 * Directory holding the compiled test class files of the project. 340 * <p> 341 * <strong>Deprecated:</strong> As of JOMC 1.1, please use the 'testOutputDirectory' parameter. This parameter 342 * will be removed in version 2.0. 343 * </p> 344 */ 345 @Deprecated 346 @Parameter( name = "testClassesDirectory" ) 347 private String testClassesDirectory; 348 349 /** 350 * Output directory of the project. 351 * 352 * @since 1.1 353 */ 354 @Parameter( name = "outputDirectory", 355 property = "jomc.outputDirectory", 356 defaultValue = "${project.build.outputDirectory}" ) 357 private String outputDirectory; 358 359 /** 360 * Test output directory of the project. 361 * 362 * @since 1.1 363 */ 364 @Parameter( name = "testOutputDirectory", 365 property = "jomc.testOutputDirectory", 366 defaultValue = "${project.build.testOutputDirectory}" ) 367 private String testOutputDirectory; 368 369 /** 370 * Directory holding the source files of the project. 371 * 372 * @since 1.1 373 */ 374 @Parameter( name = "sourceDirectory", 375 property = "jomc.sourceDirectory", 376 defaultValue = "${project.build.sourceDirectory}" ) 377 private String sourceDirectory; 378 379 /** 380 * Directory holding the test source files of the project. 381 * 382 * @since 1.1 383 */ 384 @Parameter( name = "testSourceDirectory", 385 property = "jomc.testSourceDirectory", 386 defaultValue = "${project.build.testSourceDirectory}" ) 387 private String testSourceDirectory; 388 389 /** 390 * Directory holding the session related files of the project. 391 * 392 * @since 1.1 393 */ 394 @Parameter( name = "sessionDirectory", 395 property = "jomc.sessionDirectory", 396 defaultValue = "${project.build.directory}/jomc-sessions" ) 397 private String sessionDirectory; 398 399 /** 400 * Directory holding the reports of the project. 401 * 402 * @since 1.1 403 */ 404 @Parameter( name = "reportOutputDirectory", 405 property = "jomc.reportOutputDirectory", 406 defaultValue = "${project.reporting.outputDirectory}" ) 407 private String reportOutputDirectory; 408 409 /** 410 * Velocity runtime properties. 411 * <pre> 412 * <velocityProperties> 413 * <velocityProperty> 414 * <key>The name of the property.</key> 415 * <value>The value of the property.</value> 416 * <type>The name of the class of the properties object.</type> 417 * </velocityProperty> 418 * </velocityProperties> 419 * </pre> 420 * 421 * @since 1.2 422 */ 423 @Parameter( name = "velocityProperties" ) 424 private List<VelocityProperty> velocityProperties; 425 426 /** 427 * Velocity runtime property resources. 428 * <pre> 429 * <velocityPropertyResources> 430 * <velocityPropertyResource> 431 * <location>The location of the properties resource.</location> 432 * <optional>Flag indicating the properties resource is optional.</optional> 433 * <format>The format of the properties resource.</format> 434 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout> 435 * <readTimeout>Timeout value, in milliseconds.</readTimeout> 436 * </velocityPropertyResource> 437 * </velocityPropertyResources> 438 * </pre> 439 * <p> 440 * The location value is used to first search the class path of the plugin and the project's main or test class 441 * path. If a class path resource is found, that resource is used. If no class path resource is found, an attempt is 442 * made to parse the location value to an URL. On successful parsing, that URL is used. Otherwise the location value 443 * is interpreted as a file name relative to the base directory of the project. If that file exists, that file is 444 * used. If nothing is found at the given location, depending on the optional flag, a warning message is logged or a 445 * build failure is produced. 446 * </p> 447 * <p> 448 * The optional flag is used to flag the resource optional. When an optional resource is not found, a warning 449 * message is logged instead of producing a build failure.<br/><b>Default value is:</b> false 450 * </p> 451 * <p> 452 * The format value is used to specify the format of the properties resource. Supported values are {@code plain} 453 * and {@code xml}.<br/><b>Default value is:</b> plain 454 * </p> 455 * <p> 456 * The connectTimeout value is used to specify the timeout, in milliseconds, to be used when opening 457 * communications links to the resource. A timeout of zero is interpreted as an infinite timeout.<br/> 458 * <b>Default value is:</b> 60000 459 * </p> 460 * <p> 461 * The readTimeout value is used to specify the timeout, in milliseconds, to be used when reading the resource. 462 * A timeout of zero is interpreted as an infinite timeout.<br/> 463 * <b>Default value is:</b> 60000 464 * </p> 465 * 466 * @since 1.2 467 */ 468 @Parameter( name = "velocityPropertyResources" ) 469 private List<VelocityPropertyResource> velocityPropertyResources; 470 471 /** 472 * Template parameters. 473 * <pre> 474 * <templateParameters> 475 * <templateParameter> 476 * <key>The name of the parameter.</key> 477 * <value>The value of the parameter.</value> 478 * <type>The name of the class of the parameter's object.</type> 479 * </templateParameter> 480 * </templateParameters> 481 * </pre> 482 * 483 * @since 1.2 484 */ 485 @Parameter( name = "templateParameters" ) 486 private List<TemplateParameter> templateParameters; 487 488 /** 489 * Template parameter resources. 490 * <pre> 491 * <templateParameterResources> 492 * <templateParameterResource> 493 * <location>The location of the properties resource.</location> 494 * <optional>Flag indicating the properties resource is optional.</optional> 495 * <format>The format of the properties resource.</format> 496 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout> 497 * <readTimeout>Timeout value, in milliseconds.</readTimeout> 498 * </templateParameterResource> 499 * </templateParameterResources> 500 * </pre> 501 * <p> 502 * The location value is used to first search the class path of the plugin and the project's main or test class 503 * path. If a class path resource is found, that resource is used. If no class path resource is found, an attempt is 504 * made to parse the location value to an URL. On successful parsing, that URL is used. Otherwise the location value 505 * is interpreted as a file name relative to the base directory of the project. If that file exists, that file is 506 * used. If nothing is found at the given location, depending on the optional flag, a warning message is logged or a 507 * build failure is produced. 508 * </p> 509 * <p> 510 * The optional flag is used to flag the resource optional. When an optional resource is not found, a warning 511 * message is logged instead of producing a build failure.<br/><b>Default value is:</b> false 512 * </p> 513 * <p> 514 * The format value is used to specify the format of the properties resource. Supported values are {@code plain} 515 * and {@code xml}.<br/><b>Default value is:</b> plain 516 * </p> 517 * <p> 518 * The connectTimeout value is used to specify the timeout, in milliseconds, to be used when opening 519 * communications links to the resource. A timeout of zero is interpreted as an infinite timeout.<br/> 520 * <b>Default value is:</b> 60000 521 * </p> 522 * <p> 523 * The readTimeout value is used to specify the timeout, in milliseconds, to be used when reading the resource. 524 * A timeout of zero is interpreted as an infinite timeout.<br/> 525 * <b>Default value is:</b> 60000 526 * </p> 527 * 528 * @since 1.2 529 */ 530 @Parameter( name = "templateParameterResources" ) 531 private List<TemplateParameterResource> templateParameterResources; 532 533 /** 534 * Global transformation parameters. 535 * <pre> 536 * <transformationParameters> 537 * <transformationParameter> 538 * <key>The name of the parameter.</key> 539 * <value>The value of the parameter.</value> 540 * <type>The name of the class of the parameter's object.</type> 541 * </transformationParameter> 542 * </transformationParameters> 543 * </pre> 544 * 545 * @since 1.2 546 */ 547 @Parameter( name = "transformationParameters" ) 548 private List<TransformationParameter> transformationParameters; 549 550 /** 551 * Global transformation output properties. 552 * <pre> 553 * <transformationOutputProperties> 554 * <transformationOutputProperty> 555 * <key>The name of the property.</key> 556 * <value>The value of the property.</value> 557 * <type>The name of the class of the properties object.</type> 558 * </transformationOutputProperty> 559 * </transformationOutputProperties> 560 * </pre> 561 * 562 * @since 1.2 563 */ 564 @Parameter( name = "transformationOutputProperties" ) 565 private List<TransformationOutputProperty> transformationOutputProperties; 566 567 /** 568 * Global transformation parameter resources. 569 * <pre> 570 * <transformationParameterResources> 571 * <transformationParameterResource> 572 * <location>The location of the properties resource.</location> 573 * <optional>Flag indicating the properties resource is optional.</optional> 574 * <format>The format of the properties resource.</format> 575 * <connectTimeout>Timeout value, in milliseconds.</connectTimeout> 576 * <readTimeout>Timeout value, in milliseconds.</readTimeout> 577 * </transformationParameterResource> 578 * </transformationParameterResources> 579 * </pre> 580 * <p> 581 * The location value is used to first search the class path of the plugin and the project's main or test class 582 * path. If a class path resource is found, that resource is used. If no class path resource is found, an attempt is 583 * made to parse the location value to an URL. On successful parsing, that URL is used. Otherwise the location value 584 * is interpreted as a file name relative to the base directory of the project. If that file exists, that file is 585 * used. If nothing is found at the given location, depending on the optional flag, a warning message is logged or a 586 * build failure is produced. 587 * </p> 588 * <p> 589 * The optional flag is used to flag the resource optional. When an optional resource is not found, a warning 590 * message is logged instead of producing a build failure.<br/><b>Default value is:</b> false 591 * </p> 592 * <p> 593 * The format value is used to specify the format of the properties resource. Supported values are {@code plain} 594 * and {@code xml}.<br/><b>Default value is:</b> plain 595 * </p> 596 * <p> 597 * The connectTimeout value is used to specify the timeout, in milliseconds, to be used when opening 598 * communications links to the resource. A timeout of zero is interpreted as an infinite timeout.<br/> 599 * <b>Default value is:</b> 60000 600 * </p> 601 * <p> 602 * The readTimeout value is used to specify the timeout, in milliseconds, to be used when reading the resource. 603 * A timeout of zero is interpreted as an infinite timeout.<br/> 604 * <b>Default value is:</b> 60000 605 * </p> 606 * 607 * @since 1.2 608 */ 609 @Parameter( name = "transformationParameterResources" ) 610 private List<TransformationParameterResource> transformationParameterResources; 611 612 /** 613 * Class name of the {@code ClassFileProcessor} backing the goal. 614 * 615 * @since 1.2 616 */ 617 @Parameter( name = "classFileProcessorClassName", 618 property = "jomc.classFileProcessorClassName", 619 defaultValue = "org.jomc.tools.ClassFileProcessor" ) 620 private String classFileProcessorClassName; 621 622 /** 623 * Class name of the {@code ResourceFileProcessor} backing the goal. 624 * 625 * @since 1.2 626 */ 627 @Parameter( name = "resourceFileProcessorClassName", 628 property = "jomc.resourceFileProcessorClassName", 629 defaultValue = "org.jomc.tools.ResourceFileProcessor" ) 630 private String resourceFileProcessorClassName; 631 632 /** 633 * Class name of the {@code SourceFileProcessor} backing the goal. 634 * 635 * @since 1.2 636 */ 637 @Parameter( name = "sourceFileProcessorClassName", 638 property = "jomc.sourceFileProcessorClassName", 639 defaultValue = "org.jomc.tools.SourceFileProcessor" ) 640 private String sourceFileProcessorClassName; 641 642 /** 643 * {@code ModelContext} attributes. 644 * <pre> 645 * <modelContextAttributes> 646 * <modelContextAttribute> 647 * <key>The name of the attribute.</key> 648 * <value>The value of the attribute.</value> 649 * <type>The name of the class of the attributes's object.</type> 650 * </modelContextAttribute> 651 * </modelContextAttributes> 652 * </pre> 653 * 654 * @since 1.2 655 */ 656 @Parameter( name = "modelContextAttributes" ) 657 private List<ModelContextAttribute> modelContextAttributes; 658 659 /** 660 * Flag controlling JAXP schema validation of model resources. 661 * 662 * @since 1.2 663 */ 664 @Parameter( name = "modelResourceValidationEnabled", 665 property = "jomc.modelResourceValidationEnabled", 666 defaultValue = "true" ) 667 private boolean modelResourceValidationEnabled; 668 669 /** 670 * Flag controlling JAXP schema validation of modlet resources. 671 * 672 * @since 1.2 673 */ 674 @Parameter( name = "modletResourceValidationEnabled", 675 property = "jomc.modletResourceValidationEnabled", 676 defaultValue = "true" ) 677 private boolean modletResourceValidationEnabled; 678 679 /** 680 * Flag controlling Java validation. 681 * 682 * @since 1.4 683 */ 684 @Parameter( name = "javaValidationEnabled", 685 property = "jomc.javaValidationEnabled", 686 defaultValue = "true" ) 687 private boolean javaValidationEnabled; 688 689 /** 690 * Names of modlets to exclude. 691 * 692 * @since 1.6 693 */ 694 @Parameter( name = "modletExcludes", 695 property = "jomc.modletExcludes" ) 696 private List<String> modletExcludes; 697 698 /** 699 * Names of modlets to include. 700 * 701 * @since 1.6 702 */ 703 @Parameter( name = "modletIncludes", 704 property = "jomc.modletIncludes" ) 705 private List<String> modletIncludes; 706 707 /** 708 * A formula used to calculate the maximum number of threads to create for running tasks in parallel. If the 709 * formular contains the character {@code C}, the number of threads will be calculated by multiplying the value by 710 * the number of available processors. The default number of threads is the number of available processors (1.0C). 711 * 712 * @since 1.10 713 */ 714 @Parameter( name = "threads", 715 property = "jomc.threads", 716 defaultValue = "1.0C" ) 717 private String threads; 718 719 /** 720 * The Maven project of the instance. 721 */ 722 @Parameter( name = "mavenProject", 723 defaultValue = "${project}", 724 readonly = true, 725 required = true ) 726 private MavenProject mavenProject; 727 728 /** 729 * List of plugin artifacts. 730 */ 731 @Parameter( name = "pluginArtifacts", 732 defaultValue = "${plugin.artifacts}", 733 readonly = true, 734 required = true ) 735 private List<Artifact> pluginArtifacts; 736 737 /** 738 * The Maven session of the instance. 739 * 740 * @since 1.1 741 */ 742 @Parameter( name = "mavenSession", 743 defaultValue = "${session}", 744 readonly = true, 745 required = true ) 746 private MavenSession mavenSession; 747 748 /** 749 * The executor service, if using threads. 750 * 751 * @since 1.10 752 */ 753 private ExecutorService executorService; 754 755 /** 756 * Creates a new {@code AbstractJomcMojo} instance. 757 */ 758 public AbstractJomcMojo() 759 { 760 super(); 761 } 762 763 /** 764 * {@inheritDoc} 765 * 766 * @see #assertValidParameters() 767 * @see #isExecutionPermitted() 768 * @see #executeTool() 769 */ 770 @SuppressWarnings( "deprecation" ) 771 public void execute() throws MojoExecutionException, MojoFailureException 772 { 773 this.assertValidParameters(); 774 775 try 776 { 777 this.logSeparator(); 778 779 if ( this.isLoggable( Level.INFO ) ) 780 { 781 this.log( Level.INFO, Messages.getMessage( "title" ), null ); 782 } 783 784 if ( this.isExecutionPermitted() ) 785 { 786 this.executeTool(); 787 } 788 else if ( this.isLoggable( Level.INFO ) ) 789 { 790 this.log( Level.INFO, Messages.getMessage( "executionSuppressed", this.getExecutionStrategy() ), null ); 791 } 792 } 793 catch ( final Exception e ) 794 { 795 throw new MojoExecutionException( Messages.getMessage( e ), e ); 796 } 797 finally 798 { 799 try 800 { 801 JomcTool.setDefaultTemplateProfile( null ); 802 this.logSeparator(); 803 } 804 finally 805 { 806 if ( this.executorService != null ) 807 { 808 this.executorService.shutdown(); 809 this.executorService = null; 810 } 811 } 812 } 813 } 814 815 /** 816 * Validates the parameters of the goal. 817 * 818 * @throws MojoFailureException if illegal parameter values are detected. 819 * 820 * @see #assertValidResources(java.util.Collection) 821 * @since 1.2 822 */ 823 protected void assertValidParameters() throws MojoFailureException 824 { 825 this.assertValidResources( this.templateParameterResources ); 826 this.assertValidResources( this.transformationParameterResources ); 827 this.assertValidResources( this.velocityPropertyResources ); 828 } 829 830 /** 831 * Validates a given resource collection. 832 * 833 * @param resources The resource collection to validate or {@code null}. 834 * 835 * @throws MojoFailureException if a location property of a given resource holds a {@code null} value or a given 836 * {@code PropertiesResourceType} holds an illegal format. 837 * 838 * @see #assertValidParameters() 839 * @see PropertiesResourceType#isFormatSupported(java.lang.String) 840 * @since 1.2 841 */ 842 protected final void assertValidResources( final Collection<? extends ResourceType> resources ) 843 throws MojoFailureException 844 { 845 if ( resources != null ) 846 { 847 for ( final ResourceType r : resources ) 848 { 849 if ( r.getLocation() == null ) 850 { 851 throw new MojoFailureException( Messages.getMessage( "mandatoryParameter", "location" ) ); 852 } 853 854 if ( r instanceof PropertiesResourceType ) 855 { 856 final PropertiesResourceType p = (PropertiesResourceType) r; 857 858 if ( !PropertiesResourceType.isFormatSupported( p.getFormat() ) ) 859 { 860 throw new MojoFailureException( Messages.getMessage( 861 "illegalPropertiesFormat", p.getFormat(), 862 StringUtils.join( PropertiesResourceType.getSupportedFormats(), ',' ) ) ); 863 864 } 865 } 866 } 867 } 868 } 869 870 /** 871 * Executes this tool. 872 * 873 * @throws Exception if execution of this tool fails. 874 */ 875 protected abstract void executeTool() throws Exception; 876 877 /** 878 * Gets the goal of the instance. 879 * 880 * @return The goal of the instance. 881 * 882 * @throws MojoExecutionException if getting the goal of the instance fails. 883 * @since 1.1 884 */ 885 protected abstract String getGoal() throws MojoExecutionException; 886 887 /** 888 * Gets the execution strategy of the instance. 889 * 890 * @return The execution strategy of the instance. 891 * 892 * @throws MojoExecutionException if getting the execution strategy of the instance fails. 893 * @since 1.1 894 */ 895 protected abstract String getExecutionStrategy() throws MojoExecutionException; 896 897 /** 898 * Gets a flag indicating the current execution is permitted. 899 * 900 * @return {@code true}, if the current execution is permitted; {@code false}, if the current execution is 901 * suppressed. 902 * 903 * @throws MojoExecutionException if getting the flag fails. 904 * 905 * @since 1.1 906 * @see #getGoal() 907 * @see #getExecutionStrategy() 908 */ 909 protected boolean isExecutionPermitted() throws MojoExecutionException 910 { 911 try 912 { 913 boolean permitted = true; 914 915 if ( MojoDescriptor.SINGLE_PASS_EXEC_STRATEGY.equals( this.getExecutionStrategy() ) ) 916 { 917 final File flagFile = 918 new File( this.getSessionDirectory(), 919 ArtifactUtils.versionlessKey( this.getMavenProject().getArtifact() ).hashCode() 920 + "-" + this.getGoal() 921 + "-" + this.getMavenSession().getStartTime().getTime() + ".flg" ); 922 923 if ( !this.getSessionDirectory().exists() && !this.getSessionDirectory().mkdirs() ) 924 { 925 throw new MojoExecutionException( Messages.getMessage( 926 "failedCreatingDirectory", this.getSessionDirectory().getAbsolutePath() ) ); 927 928 } 929 930 permitted = flagFile.createNewFile(); 931 } 932 933 return permitted; 934 } 935 catch ( final IOException e ) 936 { 937 throw new MojoExecutionException( Messages.getMessage( e ), e ); 938 } 939 } 940 941 /** 942 * Gets the {@code ExecutorService} used to run tasks in parallel. 943 * 944 * @return The {@code ExecutorService} used to run tasks in parallel or {@code null}. 945 * 946 * @since 1.10 947 */ 948 protected final ExecutorService getExecutorService() 949 { 950 if ( this.executorService == null ) 951 { 952 final Double parallelism = 953 this.threads != null 954 ? this.threads.toLowerCase( new Locale( "" ) ).contains( "c" ) 955 ? Double.valueOf( this.threads.toLowerCase( new Locale( "" ) ).replace( "c", "" ) ) 956 * Runtime.getRuntime().availableProcessors() 957 : Double.valueOf( this.threads ) 958 : 0.0D; 959 960 if ( parallelism.intValue() > 1 ) 961 { 962 this.executorService = Executors.newFixedThreadPool( 963 parallelism.intValue(), new ThreadFactory() 964 { 965 966 private final ThreadGroup group; 967 968 private final AtomicInteger threadNumber = new AtomicInteger( 1 ); 969 970 971 { 972 final SecurityManager s = System.getSecurityManager(); 973 this.group = s != null 974 ? s.getThreadGroup() 975 : Thread.currentThread().getThreadGroup(); 976 977 } 978 979 @Override 980 public Thread newThread( final Runnable r ) 981 { 982 final Thread t = 983 new Thread( this.group, r, "maven-jomc-plugin-" + this.threadNumber.getAndIncrement(), 0 ); 984 985 if ( t.isDaemon() ) 986 { 987 t.setDaemon( false ); 988 } 989 if ( t.getPriority() != Thread.NORM_PRIORITY ) 990 { 991 t.setPriority( Thread.NORM_PRIORITY ); 992 } 993 994 return t; 995 } 996 997 } ); 998 } 999 } 1000 1001 return this.executorService; 1002 } 1003 1004 /** 1005 * Gets the Maven project of the instance. 1006 * 1007 * @return The Maven project of the instance. 1008 * 1009 * @throws MojoExecutionException if getting the Maven project of the instance fails. 1010 */ 1011 protected MavenProject getMavenProject() throws MojoExecutionException 1012 { 1013 return this.mavenProject; 1014 } 1015 1016 /** 1017 * Gets the Maven session of the instance. 1018 * 1019 * @return The Maven session of the instance. 1020 * 1021 * @throws MojoExecutionException if getting the Maven session of the instance fails. 1022 * 1023 * @since 1.1 1024 */ 1025 protected MavenSession getMavenSession() throws MojoExecutionException 1026 { 1027 return this.mavenSession; 1028 } 1029 1030 /** 1031 * Gets an absolute {@code File} instance for a given name. 1032 * <p> 1033 * This method constructs a new {@code File} instance using the given name. If the resulting file is not 1034 * absolute, the value of the {@code basedir} property of the current Maven project is prepended. 1035 * </p> 1036 * 1037 * @param name The name to get an absolute {@code File} instance for. 1038 * 1039 * @return An absolute {@code File} instance constructed from {@code name}. 1040 * 1041 * @throws MojoExecutionException if getting an absolute {@code File} instance for {@code name} fails. 1042 * @throws NullPointerException if {@code name} is {@code null}. 1043 * 1044 * @since 1.1 1045 */ 1046 protected File getAbsoluteFile( final String name ) throws MojoExecutionException 1047 { 1048 if ( name == null ) 1049 { 1050 throw new NullPointerException( "name" ); 1051 } 1052 1053 File file = new File( name ); 1054 if ( !file.isAbsolute() ) 1055 { 1056 file = new File( this.getMavenProject().getBasedir(), name ); 1057 } 1058 1059 return file; 1060 } 1061 1062 /** 1063 * Gets the directory holding the compiled class files of the project. 1064 * 1065 * @return The directory holding the compiled class files of the project. 1066 * 1067 * @throws MojoExecutionException if getting the directory fails. 1068 * 1069 * @since 1.1 1070 */ 1071 protected File getOutputDirectory() throws MojoExecutionException 1072 { 1073 if ( this.classesDirectory != null ) 1074 { 1075 if ( this.isLoggable( Level.WARNING ) ) 1076 { 1077 this.log( Level.WARNING, Messages.getMessage( 1078 "deprecationWarning", "classesDirectory", "outputDirectory" ), null ); 1079 1080 } 1081 1082 if ( !this.classesDirectory.equals( this.outputDirectory ) ) 1083 { 1084 if ( this.isLoggable( Level.WARNING ) ) 1085 { 1086 this.log( Level.WARNING, Messages.getMessage( "ignoringParameter", "outputDirectory" ), null ); 1087 } 1088 1089 this.outputDirectory = this.classesDirectory; 1090 } 1091 1092 this.classesDirectory = null; 1093 } 1094 1095 final File dir = this.getAbsoluteFile( this.outputDirectory ); 1096 if ( !dir.exists() && !dir.mkdirs() ) 1097 { 1098 throw new MojoExecutionException( Messages.getMessage( "failedCreatingDirectory", dir.getAbsolutePath() ) ); 1099 } 1100 1101 return dir; 1102 } 1103 1104 /** 1105 * Gets the directory holding the compiled test class files of the project. 1106 * 1107 * @return The directory holding the compiled test class files of the project. 1108 * 1109 * @throws MojoExecutionException if getting the directory fails. 1110 * 1111 * @since 1.1 1112 */ 1113 protected File getTestOutputDirectory() throws MojoExecutionException 1114 { 1115 if ( this.testClassesDirectory != null ) 1116 { 1117 if ( this.isLoggable( Level.WARNING ) ) 1118 { 1119 this.log( Level.WARNING, Messages.getMessage( 1120 "deprecationWarning", "testClassesDirectory", "testOutputDirectory" ), null ); 1121 1122 } 1123 1124 if ( !this.testClassesDirectory.equals( this.testOutputDirectory ) ) 1125 { 1126 if ( this.isLoggable( Level.WARNING ) ) 1127 { 1128 this.log( Level.WARNING, Messages.getMessage( "ignoringParameter", "testOutputDirectory" ), null ); 1129 } 1130 1131 this.testOutputDirectory = this.testClassesDirectory; 1132 } 1133 1134 this.testClassesDirectory = null; 1135 } 1136 1137 final File dir = this.getAbsoluteFile( this.testOutputDirectory ); 1138 if ( !dir.exists() && !dir.mkdirs() ) 1139 { 1140 throw new MojoExecutionException( Messages.getMessage( "failedCreatingDirectory", dir.getAbsolutePath() ) ); 1141 } 1142 1143 return dir; 1144 } 1145 1146 /** 1147 * Gets the directory holding the source files of the project. 1148 * 1149 * @return The directory holding the source files of the project. 1150 * 1151 * @throws MojoExecutionException if getting the directory fails. 1152 * 1153 * @since 1.1 1154 */ 1155 protected File getSourceDirectory() throws MojoExecutionException 1156 { 1157 return this.getAbsoluteFile( this.sourceDirectory ); 1158 } 1159 1160 /** 1161 * Gets the directory holding the test source files of the project. 1162 * 1163 * @return The directory holding the test source files of the project. 1164 * 1165 * @throws MojoExecutionException if getting the directory fails. 1166 * 1167 * @since 1.1 1168 */ 1169 protected File getTestSourceDirectory() throws MojoExecutionException 1170 { 1171 return this.getAbsoluteFile( this.testSourceDirectory ); 1172 } 1173 1174 /** 1175 * Gets the directory holding the session related files of the project. 1176 * 1177 * @return The directory holding the session related files of the project. 1178 * 1179 * @throws MojoExecutionException if getting the directory fails. 1180 * 1181 * @since 1.1 1182 */ 1183 protected File getSessionDirectory() throws MojoExecutionException 1184 { 1185 return this.getAbsoluteFile( this.sessionDirectory ); 1186 } 1187 1188 /** 1189 * Gets the directory holding the reports of the project. 1190 * 1191 * @return The directory holding the reports of the project. 1192 * 1193 * @throws MojoExecutionException if getting the directory fails. 1194 * 1195 * @since 1.1 1196 */ 1197 protected File getReportOutputDirectory() throws MojoExecutionException 1198 { 1199 return this.getAbsoluteFile( this.reportOutputDirectory ); 1200 } 1201 1202 /** 1203 * Gets the project's runtime class loader of the instance. 1204 * 1205 * @return The project's runtime class loader of the instance. 1206 * 1207 * @throws MojoExecutionException if getting the class loader fails. 1208 */ 1209 protected ClassLoader getMainClassLoader() throws MojoExecutionException 1210 { 1211 try 1212 { 1213 final Set<String> mainClasspathElements = this.getMainClasspathElements(); 1214 final Set<URI> uris = new HashSet<URI>( mainClasspathElements.size() ); 1215 1216 for ( final String element : mainClasspathElements ) 1217 { 1218 final URI uri = new File( element ).toURI(); 1219 if ( !uris.contains( uri ) ) 1220 { 1221 uris.add( uri ); 1222 } 1223 } 1224 1225 if ( this.isLoggable( Level.FINEST ) ) 1226 { 1227 this.log( Level.FINEST, Messages.getMessage( "mainClasspathInfo" ), null ); 1228 } 1229 1230 int i = 0; 1231 final URL[] urls = new URL[ uris.size() ]; 1232 for ( final URI uri : uris ) 1233 { 1234 urls[i++] = uri.toURL(); 1235 1236 if ( this.isLoggable( Level.FINEST ) ) 1237 { 1238 this.log( Level.FINEST, "\t" + urls[i - 1].toExternalForm(), null ); 1239 } 1240 } 1241 1242 return new URLClassLoader( urls, Thread.currentThread().getContextClassLoader() ); 1243 } 1244 catch ( final MalformedURLException e ) 1245 { 1246 throw new MojoExecutionException( Messages.getMessage( e ), e ); 1247 } 1248 } 1249 1250 /** 1251 * Gets the project's test class loader of the instance. 1252 * 1253 * @return The project's test class loader of the instance. 1254 * 1255 * @throws MojoExecutionException if getting the class loader fails. 1256 */ 1257 protected ClassLoader getTestClassLoader() throws MojoExecutionException 1258 { 1259 try 1260 { 1261 final Set<String> testClasspathElements = this.getTestClasspathElements(); 1262 final Set<URI> uris = new HashSet<URI>( testClasspathElements.size() ); 1263 1264 for ( final String element : testClasspathElements ) 1265 { 1266 final URI uri = new File( element ).toURI(); 1267 if ( !uris.contains( uri ) ) 1268 { 1269 uris.add( uri ); 1270 } 1271 } 1272 1273 if ( this.isLoggable( Level.FINEST ) ) 1274 { 1275 this.log( Level.FINEST, Messages.getMessage( "testClasspathInfo" ), null ); 1276 } 1277 1278 int i = 0; 1279 final URL[] urls = new URL[ uris.size() ]; 1280 for ( final URI uri : uris ) 1281 { 1282 urls[i++] = uri.toURL(); 1283 1284 if ( this.isLoggable( Level.FINEST ) ) 1285 { 1286 this.log( Level.FINEST, "\t" + urls[i - 1].toExternalForm(), null ); 1287 } 1288 } 1289 1290 return new URLClassLoader( urls, Thread.currentThread().getContextClassLoader() ); 1291 } 1292 catch ( final MalformedURLException e ) 1293 { 1294 throw new MojoExecutionException( Messages.getMessage( e ), e ); 1295 } 1296 } 1297 1298 /** 1299 * Gets the project's runtime class path elements. 1300 * 1301 * @return A set of class path element strings. 1302 * 1303 * @throws MojoExecutionException if getting the class path elements fails. 1304 */ 1305 protected Set<String> getMainClasspathElements() throws MojoExecutionException 1306 { 1307 final List<?> runtimeArtifacts = this.getMavenProject().getRuntimeArtifacts(); 1308 final List<?> compileArtifacts = this.getMavenProject().getCompileArtifacts(); 1309 final Set<String> elements = new HashSet<String>( runtimeArtifacts.size() + compileArtifacts.size() + 1 ); 1310 elements.add( this.getOutputDirectory().getAbsolutePath() ); 1311 1312 for ( final Iterator<?> it = runtimeArtifacts.iterator(); it.hasNext(); ) 1313 { 1314 final Artifact a = (Artifact) it.next(); 1315 final Artifact pluginArtifact = this.getPluginArtifact( a ); 1316 1317 if ( a.getFile() == null ) 1318 { 1319 if ( this.isLoggable( Level.WARNING ) ) 1320 { 1321 this.log( Level.WARNING, Messages.getMessage( "ignoringArtifact", a.toString() ), null ); 1322 } 1323 1324 continue; 1325 } 1326 1327 if ( pluginArtifact != null ) 1328 { 1329 if ( this.isLoggable( Level.FINER ) ) 1330 { 1331 this.log( Level.FINER, Messages.getMessage( 1332 "ignoringPluginArtifact", a.toString(), pluginArtifact.toString() ), null ); 1333 1334 } 1335 1336 continue; 1337 } 1338 1339 final String element = a.getFile().getAbsolutePath(); 1340 elements.add( element ); 1341 } 1342 1343 for ( final Iterator<?> it = compileArtifacts.iterator(); it.hasNext(); ) 1344 { 1345 final Artifact a = (Artifact) it.next(); 1346 final Artifact pluginArtifact = this.getPluginArtifact( a ); 1347 1348 if ( a.getFile() == null ) 1349 { 1350 if ( this.isLoggable( Level.WARNING ) ) 1351 { 1352 this.log( Level.WARNING, Messages.getMessage( "ignoringArtifact", a.toString() ), null ); 1353 } 1354 1355 continue; 1356 } 1357 1358 if ( pluginArtifact != null ) 1359 { 1360 if ( this.isLoggable( Level.FINER ) ) 1361 { 1362 this.log( Level.FINER, Messages.getMessage( 1363 "ignoringPluginArtifact", a.toString(), pluginArtifact.toString() ), null ); 1364 1365 } 1366 1367 continue; 1368 } 1369 1370 final String element = a.getFile().getAbsolutePath(); 1371 elements.add( element ); 1372 } 1373 1374 return elements; 1375 } 1376 1377 /** 1378 * Gets the project's test class path elements. 1379 * 1380 * @return A set of class path element strings. 1381 * 1382 * @throws MojoExecutionException if getting the class path elements fails. 1383 */ 1384 protected Set<String> getTestClasspathElements() throws MojoExecutionException 1385 { 1386 final List<?> testArtifacts = this.getMavenProject().getTestArtifacts(); 1387 final Set<String> elements = new HashSet<String>( testArtifacts.size() + 2 ); 1388 elements.add( this.getOutputDirectory().getAbsolutePath() ); 1389 elements.add( this.getTestOutputDirectory().getAbsolutePath() ); 1390 1391 for ( final Iterator<?> it = testArtifacts.iterator(); it.hasNext(); ) 1392 { 1393 final Artifact a = (Artifact) it.next(); 1394 final Artifact pluginArtifact = this.getPluginArtifact( a ); 1395 1396 if ( a.getFile() == null ) 1397 { 1398 if ( this.isLoggable( Level.WARNING ) ) 1399 { 1400 this.log( Level.WARNING, Messages.getMessage( "ignoringArtifact", a.toString() ), null ); 1401 } 1402 1403 continue; 1404 } 1405 1406 if ( pluginArtifact != null ) 1407 { 1408 if ( this.isLoggable( Level.FINER ) ) 1409 { 1410 this.log( Level.FINER, Messages.getMessage( 1411 "ignoringPluginArtifact", a.toString(), pluginArtifact.toString() ), null ); 1412 1413 } 1414 1415 continue; 1416 } 1417 1418 final String element = a.getFile().getAbsolutePath(); 1419 elements.add( element ); 1420 } 1421 1422 return elements; 1423 } 1424 1425 /** 1426 * Gets a flag indicating verbose output is enabled. 1427 * 1428 * @return {@code true}, if verbose output is enabled; {@code false}, if information messages are suppressed. 1429 * 1430 * @throws MojoExecutionException if getting the flag fails. 1431 * 1432 * @since 1.1 1433 */ 1434 protected final boolean isVerbose() throws MojoExecutionException 1435 { 1436 return this.verbose; 1437 } 1438 1439 /** 1440 * Sets the flag indicating verbose output is enabled. 1441 * 1442 * @param value {@code true}, to enable verbose output; {@code false}, to suppress information messages. 1443 * 1444 * @throws MojoExecutionException if setting the flag fails. 1445 * 1446 * @since 1.1 1447 */ 1448 protected final void setVerbose( final boolean value ) throws MojoExecutionException 1449 { 1450 this.verbose = value; 1451 } 1452 1453 /** 1454 * Gets a flag indicating the processing of sources is enabled. 1455 * 1456 * @return {@code true}, if processing of sources is enabled; {@code false}, else. 1457 * 1458 * @throws MojoExecutionException if getting the flag fails. 1459 */ 1460 protected final boolean isSourceProcessingEnabled() throws MojoExecutionException 1461 { 1462 return this.sourceProcessingEnabled; 1463 } 1464 1465 /** 1466 * Sets the flag indicating the processing of sources is enabled. 1467 * 1468 * @param value {@code true}, to enable processing of sources; {@code false}, to disable processing of sources. 1469 * 1470 * @throws MojoExecutionException if setting the flag fails. 1471 * 1472 * @since 1.1 1473 */ 1474 protected final void setSourceProcessingEnabled( final boolean value ) throws MojoExecutionException 1475 { 1476 this.sourceProcessingEnabled = value; 1477 } 1478 1479 /** 1480 * Gets a flag indicating the processing of resources is enabled. 1481 * 1482 * @return {@code true}, if processing of resources is enabled; {@code false}, else. 1483 * 1484 * @throws MojoExecutionException if getting the flag fails. 1485 */ 1486 protected final boolean isResourceProcessingEnabled() throws MojoExecutionException 1487 { 1488 return this.resourceProcessingEnabled; 1489 } 1490 1491 /** 1492 * Sets the flag indicating the processing of resources is enabled. 1493 * 1494 * @param value {@code true}, to enable processing of resources; {@code false}, to disable processing of resources. 1495 * 1496 * @throws MojoExecutionException if setting the flag fails. 1497 * 1498 * @since 1.1 1499 */ 1500 protected final void setResourceProcessingEnabled( final boolean value ) throws MojoExecutionException 1501 { 1502 this.resourceProcessingEnabled = value; 1503 } 1504 1505 /** 1506 * Gets a flag indicating the processing of classes is enabled. 1507 * 1508 * @return {@code true}, if processing of classes is enabled; {@code false}, else. 1509 * 1510 * @throws MojoExecutionException if getting the flag fails. 1511 */ 1512 protected final boolean isClassProcessingEnabled() throws MojoExecutionException 1513 { 1514 return this.classProcessingEnabled; 1515 } 1516 1517 /** 1518 * Sets the flag indicating the processing of classes is enabled. 1519 * 1520 * @param value {@code true}, to enable processing of classes; {@code false}, to disable processing of classes. 1521 * 1522 * @throws MojoExecutionException if setting the flag fails. 1523 * 1524 * @since 1.1 1525 */ 1526 protected final void setClassProcessingEnabled( final boolean value ) throws MojoExecutionException 1527 { 1528 this.classProcessingEnabled = value; 1529 } 1530 1531 /** 1532 * Gets a flag indicating the processing of models is enabled. 1533 * 1534 * @return {@code true}, if processing of models is enabled; {@code false}, else. 1535 * 1536 * @throws MojoExecutionException if getting the flag fails. 1537 */ 1538 protected final boolean isModelProcessingEnabled() throws MojoExecutionException 1539 { 1540 return this.modelProcessingEnabled; 1541 } 1542 1543 /** 1544 * Sets the flag indicating the processing of models is enabled. 1545 * 1546 * @param value {@code true}, to enable processing of models; {@code false}, to disable processing of models. 1547 * 1548 * @throws MojoExecutionException if setting the flag fails. 1549 * 1550 * @since 1.1 1551 */ 1552 protected final void setModelProcessingEnabled( final boolean value ) throws MojoExecutionException 1553 { 1554 this.modelProcessingEnabled = value; 1555 } 1556 1557 /** 1558 * Gets a flag indicating model object class path resolution is enabled. 1559 * 1560 * @return {@code true}, if model object class path resolution is enabled; {@code false}, else. 1561 * 1562 * @throws MojoExecutionException if getting the flag fails. 1563 */ 1564 protected final boolean isModelObjectClasspathResolutionEnabled() throws MojoExecutionException 1565 { 1566 return this.modelObjectClasspathResolutionEnabled; 1567 } 1568 1569 /** 1570 * Sets the flag indicating model object class path resolution is enabled. 1571 * 1572 * @param value {@code true}, to enable model object class path resolution; {@code false}, to disable model object 1573 * class path resolution. 1574 * 1575 * @throws MojoExecutionException if setting the flag fails. 1576 * 1577 * @since 1.1 1578 */ 1579 protected final void setModelObjectClasspathResolutionEnabled( final boolean value ) throws MojoExecutionException 1580 { 1581 this.modelObjectClasspathResolutionEnabled = value; 1582 } 1583 1584 /** 1585 * Gets the identifier of the model to process. 1586 * 1587 * @return The identifier of the model to process. 1588 * 1589 * @throws MojoExecutionException if getting the identifier fails. 1590 */ 1591 protected String getModel() throws MojoExecutionException 1592 { 1593 return this.model; 1594 } 1595 1596 /** 1597 * Gets the name of the module to process. 1598 * 1599 * @return The name of the module to process. 1600 * 1601 * @throws MojoExecutionException if getting the name of the module fails. 1602 */ 1603 protected String getModuleName() throws MojoExecutionException 1604 { 1605 return this.moduleName; 1606 } 1607 1608 /** 1609 * Gets the name of the test module to process. 1610 * 1611 * @return The name of the test module to process. 1612 * 1613 * @throws MojoExecutionException if getting the name of the test module fails. 1614 */ 1615 protected String getTestModuleName() throws MojoExecutionException 1616 { 1617 return this.testModuleName; 1618 } 1619 1620 /** 1621 * Gets the model to process. 1622 * 1623 * @param context The model context to get the model to process with. 1624 * 1625 * @return The model to process. 1626 * 1627 * @throws NullPointerException if {@code context} is {@code null}. 1628 * @throws MojoExecutionException if getting the model fails. 1629 */ 1630 protected Model getModel( final ModelContext context ) throws MojoExecutionException 1631 { 1632 if ( context == null ) 1633 { 1634 throw new NullPointerException( "context" ); 1635 } 1636 1637 try 1638 { 1639 Model m = context.findModel( this.getModel() ); 1640 final Modules modules = ModelHelper.getModules( m ); 1641 1642 if ( modules != null && this.isModelObjectClasspathResolutionEnabled() ) 1643 { 1644 final Module classpathModule = 1645 modules.getClasspathModule( Modules.getDefaultClasspathModuleName(), context.getClassLoader() ); 1646 1647 if ( classpathModule != null ) 1648 { 1649 modules.getModule().add( classpathModule ); 1650 } 1651 } 1652 1653 if ( this.isModelProcessingEnabled() ) 1654 { 1655 m = context.processModel( m ); 1656 } 1657 1658 return m; 1659 } 1660 catch ( final ModelException e ) 1661 { 1662 throw new MojoExecutionException( Messages.getMessage( e ), e ); 1663 } 1664 } 1665 1666 /** 1667 * Creates a new model context instance for a given class loader. 1668 * 1669 * @param classLoader The class loader to use for creating the context. 1670 * 1671 * @return A new model context instance for {@code classLoader}. 1672 * 1673 * @throws MojoExecutionException if creating the model context fails. 1674 * 1675 * @see #setupModelContext(org.jomc.modlet.ModelContext) 1676 */ 1677 protected ModelContext createModelContext( final ClassLoader classLoader ) throws MojoExecutionException 1678 { 1679 final ModelContextFactory modelContextFactory; 1680 if ( this.modelContextFactoryClassName != null ) 1681 { 1682 modelContextFactory = ModelContextFactory.newInstance( this.modelContextFactoryClassName ); 1683 } 1684 else 1685 { 1686 modelContextFactory = ModelContextFactory.newInstance(); 1687 } 1688 1689 final ModelContext context = modelContextFactory.newModelContext( classLoader ); 1690 this.setupModelContext( context ); 1691 1692 return context; 1693 } 1694 1695 /** 1696 * Creates a new tool instance for processing source files. 1697 * 1698 * @param context The context of the tool. 1699 * 1700 * @return A new tool instance for processing source files. 1701 * 1702 * @throws NullPointerException if {@code context} is {@code null}. 1703 * @throws MojoExecutionException if creating a new tool instance fails. 1704 * 1705 * @see #createJomcTool(org.jomc.modlet.ModelContext, java.lang.String, java.lang.Class) 1706 */ 1707 protected SourceFileProcessor createSourceFileProcessor( final ModelContext context ) throws MojoExecutionException 1708 { 1709 if ( context == null ) 1710 { 1711 throw new NullPointerException( "context" ); 1712 } 1713 1714 return this.createJomcTool( context, this.sourceFileProcessorClassName, SourceFileProcessor.class ); 1715 } 1716 1717 /** 1718 * Creates a new tool instance for processing resource files. 1719 * 1720 * @param context The context of the tool. 1721 * 1722 * @return A new tool instance for processing resource files. 1723 * 1724 * @throws NullPointerException if {@code context} is {@code null}. 1725 * @throws MojoExecutionException if creating a new tool instance fails. 1726 * 1727 * @see #createJomcTool(org.jomc.modlet.ModelContext, java.lang.String, java.lang.Class) 1728 */ 1729 protected ResourceFileProcessor createResourceFileProcessor( final ModelContext context ) 1730 throws MojoExecutionException 1731 { 1732 if ( context == null ) 1733 { 1734 throw new NullPointerException( "context" ); 1735 } 1736 1737 return this.createJomcTool( context, this.resourceFileProcessorClassName, ResourceFileProcessor.class ); 1738 } 1739 1740 /** 1741 * Creates a new tool instance for processing class files. 1742 * 1743 * @param context The context of the tool. 1744 * 1745 * @return A new tool instance for processing class files. 1746 * 1747 * @throws NullPointerException if {@code context} is {@code null}. 1748 * @throws MojoExecutionException if creating a new tool instance fails. 1749 * 1750 * @see #createJomcTool(org.jomc.modlet.ModelContext, java.lang.String, java.lang.Class) 1751 */ 1752 protected ClassFileProcessor createClassFileProcessor( final ModelContext context ) throws MojoExecutionException 1753 { 1754 if ( context == null ) 1755 { 1756 throw new NullPointerException( "context" ); 1757 } 1758 1759 return this.createJomcTool( context, this.classFileProcessorClassName, ClassFileProcessor.class ); 1760 } 1761 1762 /** 1763 * Creates a new {@code JomcTool} object for a given class name and type. 1764 * 1765 * @param context The context of the tool. 1766 * @param className The name of the class to create an object of. 1767 * @param type The class of the type of object to create. 1768 * @param <T> The type of the object to create. 1769 * 1770 * @return A new instance of the class with name {@code className}. 1771 * 1772 * @throws NullPointerException if {@code context}, {@code className} or {@code type} is {@code null}. 1773 * @throws MojoExecutionException if creating a new {@code JomcTool} object fails. 1774 * 1775 * @see #createObject(org.jomc.modlet.ModelContext, java.lang.String, java.lang.Class) 1776 * @see #setupJomcTool(org.jomc.modlet.ModelContext, org.jomc.tools.JomcTool) 1777 * 1778 * @since 1.2 1779 */ 1780 protected <T extends JomcTool> T createJomcTool( final ModelContext context, final String className, 1781 final Class<T> type ) throws MojoExecutionException 1782 { 1783 if ( context == null ) 1784 { 1785 throw new NullPointerException( "context" ); 1786 } 1787 if ( className == null ) 1788 { 1789 throw new NullPointerException( "className" ); 1790 } 1791 if ( type == null ) 1792 { 1793 throw new NullPointerException( "type" ); 1794 } 1795 1796 final T tool = this.createObject( context, className, type ); 1797 this.setupJomcTool( context, tool ); 1798 return tool; 1799 } 1800 1801 /** 1802 * Creates a new object for a given class name and type. 1803 * 1804 * @param className The name of the class to create an object of. 1805 * @param type The class of the type of object to create. 1806 * @param <T> The type of the object to create. 1807 * 1808 * @return A new instance of the class with name {@code className}. 1809 * 1810 * @throws NullPointerException if {@code className} or {@code type} is {@code null}. 1811 * @throws MojoExecutionException if creating a new object fails. 1812 * 1813 * @since 1.2 1814 * @deprecated As of JOMC 1.8, replaced by method {@link #createObject(org.jomc.modlet.ModelContext, java.lang.String, java.lang.Class)}. 1815 * This method will be removed in JOMC 2.0. 1816 */ 1817 @Deprecated 1818 @SuppressWarnings( "deprecation" ) 1819 protected <T> T createObject( final String className, final Class<T> type ) throws MojoExecutionException 1820 { 1821 if ( className == null ) 1822 { 1823 throw new NullPointerException( "className" ); 1824 } 1825 if ( type == null ) 1826 { 1827 throw new NullPointerException( "type" ); 1828 } 1829 1830 try 1831 { 1832 return Class.forName( className ).asSubclass( type ).newInstance(); 1833 } 1834 catch ( final InstantiationException e ) 1835 { 1836 throw new MojoExecutionException( Messages.getMessage( "failedCreatingObject", className ), e ); 1837 } 1838 catch ( final IllegalAccessException e ) 1839 { 1840 throw new MojoExecutionException( Messages.getMessage( "failedCreatingObject", className ), e ); 1841 } 1842 catch ( final ClassNotFoundException e ) 1843 { 1844 throw new MojoExecutionException( Messages.getMessage( "failedCreatingObject", className ), e ); 1845 } 1846 catch ( final ClassCastException e ) 1847 { 1848 throw new MojoExecutionException( Messages.getMessage( "failedCreatingObject", className ), e ); 1849 } 1850 } 1851 1852 /** 1853 * Creates a new object for a given class name and type. 1854 * 1855 * @param modelContext The model context to search. 1856 * @param className The name of the class to create an object of. 1857 * @param type The class of the type of object to create. 1858 * @param <T> The type of the object to create. 1859 * 1860 * @return A new instance of the class with name {@code className}. 1861 * 1862 * @throws NullPointerException if {@code modelContext}, {@code className} or {@code type} is {@code null}. 1863 * @throws MojoExecutionException if creating a new object fails. 1864 * 1865 * @since 1.8 1866 */ 1867 protected <T> T createObject( final ModelContext modelContext, final String className, final Class<T> type ) 1868 throws MojoExecutionException 1869 { 1870 if ( modelContext == null ) 1871 { 1872 throw new NullPointerException( "modelContext" ); 1873 } 1874 if ( className == null ) 1875 { 1876 throw new NullPointerException( "className" ); 1877 } 1878 if ( type == null ) 1879 { 1880 throw new NullPointerException( "type" ); 1881 } 1882 1883 try 1884 { 1885 final Class<?> javaClass = modelContext.findClass( className ); 1886 1887 if ( javaClass == null ) 1888 { 1889 throw new MojoExecutionException( Messages.getMessage( "classNotFound", className ) ); 1890 } 1891 1892 return javaClass.asSubclass( type ).newInstance(); 1893 } 1894 catch ( final ModelException e ) 1895 { 1896 String m = Messages.getMessage( e ); 1897 m = m == null ? "" : " " + m; 1898 1899 throw new MojoExecutionException( Messages.getMessage( "failedSearchingClass", className, m ), e ); 1900 } 1901 catch ( final InstantiationException e ) 1902 { 1903 throw new MojoExecutionException( Messages.getMessage( "failedCreatingObject", className ), e ); 1904 } 1905 catch ( final IllegalAccessException e ) 1906 { 1907 throw new MojoExecutionException( Messages.getMessage( "failedCreatingObject", className ), e ); 1908 } 1909 catch ( final ClassCastException e ) 1910 { 1911 throw new MojoExecutionException( Messages.getMessage( "failedCreatingObject", className ), e ); 1912 } 1913 } 1914 1915 /** 1916 * Creates an {@code URL} for a given resource location. 1917 * <p> 1918 * This method first searches the class path of the plugin for a single resource matching {@code location}. If 1919 * such a resource is found, the URL of that resource is returned. If no such resource is found, an attempt is made 1920 * to parse the given location to an URL. On successful parsing, that URL is returned. Failing that, the given 1921 * location is interpreted as a file name relative to the project's base directory. If that file is found, the URL 1922 * of that file is returned. Otherwise {@code null} is returned. 1923 * </p> 1924 * 1925 * @param location The location to create an {@code URL} from. 1926 * 1927 * @return An {@code URL} for {@code location} or {@code null}, if parsing {@code location} to an URL fails and 1928 * {@code location} points to a non-existent resource. 1929 * 1930 * @throws NullPointerException if {@code location} is {@code null}. 1931 * @throws MojoExecutionException if creating an URL fails. 1932 * 1933 * @since 1.2 1934 * @deprecated As of JOMC 1.8, replaced by method {@link #getResource(org.jomc.modlet.ModelContext, java.lang.String)}. 1935 * This method will be removed in JOMC 2.0. 1936 */ 1937 @Deprecated 1938 @SuppressWarnings( "deprecation" ) 1939 protected URL getResource( final String location ) throws MojoExecutionException 1940 { 1941 if ( location == null ) 1942 { 1943 throw new NullPointerException( "location" ); 1944 } 1945 1946 try 1947 { 1948 String absolute = location; 1949 if ( !absolute.startsWith( "/" ) ) 1950 { 1951 absolute = "/" + location; 1952 } 1953 1954 URL resource = this.getClass().getResource( absolute ); 1955 if ( resource == null ) 1956 { 1957 try 1958 { 1959 resource = new URL( location ); 1960 } 1961 catch ( final MalformedURLException e ) 1962 { 1963 if ( this.isLoggable( Level.FINEST ) ) 1964 { 1965 this.log( Level.FINEST, Messages.getMessage( e ), e ); 1966 } 1967 1968 resource = null; 1969 } 1970 } 1971 1972 if ( resource == null ) 1973 { 1974 final File f = this.getAbsoluteFile( location ); 1975 1976 if ( f.isFile() ) 1977 { 1978 resource = f.toURI().toURL(); 1979 } 1980 } 1981 1982 return resource; 1983 } 1984 catch ( final MalformedURLException e ) 1985 { 1986 String m = Messages.getMessage( e ); 1987 m = m == null ? "" : " " + m; 1988 1989 throw new MojoExecutionException( Messages.getMessage( "malformedLocation", location, m ), e ); 1990 } 1991 } 1992 1993 /** 1994 * Creates an {@code URL} for a given resource location. 1995 * <p> 1996 * This method first searches the given model context for a single resource matching {@code location}. If such a 1997 * resource is found, the URL of that resource is returned. If no such resource is found, an attempt is made to 1998 * parse the given location to an URL. On successful parsing, that URL is returned. Failing that, the given location 1999 * is interpreted as a file name relative to the project's base directory. If that file is found, the URL of that 2000 * file is returned. Otherwise {@code null} is returned. 2001 * </p> 2002 * 2003 * @param modelContext The model conext to search. 2004 * @param location The location to create an {@code URL} from. 2005 * 2006 * @return An {@code URL} for {@code location} or {@code null}, if parsing {@code location} to an URL fails and 2007 * {@code location} points to a non-existent resource. 2008 * 2009 * @throws NullPointerException if {@code modelContext} or {@code location} is {@code null}. 2010 * @throws MojoExecutionException if creating an URL fails. 2011 * 2012 * @since 1.8 2013 */ 2014 protected URL getResource( final ModelContext modelContext, final String location ) throws MojoExecutionException 2015 { 2016 if ( modelContext == null ) 2017 { 2018 throw new NullPointerException( "modelContext" ); 2019 } 2020 if ( location == null ) 2021 { 2022 throw new NullPointerException( "location" ); 2023 } 2024 2025 try 2026 { 2027 String absolute = location; 2028 if ( !absolute.startsWith( "/" ) ) 2029 { 2030 absolute = "/" + location; 2031 } 2032 2033 URL resource = modelContext.findResource( absolute ); 2034 2035 if ( resource == null ) 2036 { 2037 try 2038 { 2039 resource = new URL( location ); 2040 } 2041 catch ( final MalformedURLException e ) 2042 { 2043 if ( this.isLoggable( Level.FINEST ) ) 2044 { 2045 this.log( Level.FINEST, Messages.getMessage( e ), e ); 2046 } 2047 2048 resource = null; 2049 } 2050 } 2051 2052 if ( resource == null ) 2053 { 2054 final File f = this.getAbsoluteFile( location ); 2055 2056 if ( f.isFile() ) 2057 { 2058 resource = f.toURI().toURL(); 2059 } 2060 } 2061 2062 return resource; 2063 } 2064 catch ( final ModelException e ) 2065 { 2066 String m = Messages.getMessage( e ); 2067 m = m == null ? "" : " " + m; 2068 2069 throw new MojoExecutionException( Messages.getMessage( "failedSearchingResource", location, m ), e ); 2070 } 2071 catch ( final MalformedURLException e ) 2072 { 2073 String m = Messages.getMessage( e ); 2074 m = m == null ? "" : " " + m; 2075 2076 throw new MojoExecutionException( Messages.getMessage( "malformedLocation", location, m ), e ); 2077 } 2078 } 2079 2080 /** 2081 * Creates an {@code URL} for a given directory location. 2082 * <p> 2083 * This method first attempts to parse the given location to an URL. On successful parsing, that URL is returned. 2084 * Failing that, the given location is interpreted as a directory name relative to the project's base directory. 2085 * If that directory is found, the URL of that directory is returned. Otherwise {@code null} is returned. 2086 * </p> 2087 * 2088 * @param location The directory location to create an {@code URL} from. 2089 * 2090 * @return An {@code URL} for {@code location} or {@code null}, if parsing {@code location} to an URL fails and 2091 * {@code location} points to a non-existent directory. 2092 * 2093 * @throws NullPointerException if {@code location} is {@code null}. 2094 * @throws MojoExecutionException if creating an URL fails. 2095 * 2096 * @since 1.2 2097 */ 2098 protected URL getDirectory( final String location ) throws MojoExecutionException 2099 { 2100 if ( location == null ) 2101 { 2102 throw new NullPointerException( "location" ); 2103 } 2104 2105 try 2106 { 2107 URL resource; 2108 2109 try 2110 { 2111 resource = new URL( location ); 2112 } 2113 catch ( final MalformedURLException e ) 2114 { 2115 if ( this.isLoggable( Level.FINEST ) ) 2116 { 2117 this.log( Level.FINEST, Messages.getMessage( e ), e ); 2118 } 2119 2120 resource = null; 2121 } 2122 2123 if ( resource == null ) 2124 { 2125 final File f = this.getAbsoluteFile( location ); 2126 2127 if ( f.isDirectory() ) 2128 { 2129 resource = f.toURI().toURL(); 2130 } 2131 } 2132 2133 return resource; 2134 } 2135 catch ( final MalformedURLException e ) 2136 { 2137 String m = Messages.getMessage( e ); 2138 m = m == null ? "" : " " + m; 2139 2140 throw new MojoExecutionException( Messages.getMessage( "malformedLocation", location, m ), e ); 2141 } 2142 } 2143 2144 /** 2145 * Creates a new {@code Transformer} from a given {@code TransformerResourceType}. 2146 * 2147 * @param resource The resource to initialize the transformer with. 2148 * 2149 * @return A {@code Transformer} for {@code resource} or {@code null}, if {@code resource} is not found and flagged 2150 * optional. 2151 * 2152 * @throws NullPointerException if {@code resource} is {@code null}. 2153 * @throws MojoExecutionException if creating a transformer fails. 2154 * 2155 * @see #getResource(java.lang.String) 2156 * @since 1.2 2157 * @deprecated As of JOMC 1.8, replaced by method {@link #getTransformer(org.jomc.modlet.ModelContext, org.jomc.mojo.TransformerResourceType)}. 2158 * This method will be removed in JOMC 2.0. 2159 */ 2160 @Deprecated 2161 @SuppressWarnings( "deprecation" ) 2162 protected Transformer getTransformer( final TransformerResourceType resource ) throws MojoExecutionException 2163 { 2164 if ( resource == null ) 2165 { 2166 throw new NullPointerException( "resource" ); 2167 } 2168 2169 URLConnection con = null; 2170 InputStream in = null; 2171 final URL url = this.getResource( resource.getLocation() ); 2172 final ErrorListener errorListener = new ErrorListener() 2173 { 2174 2175 public void warning( final TransformerException exception ) throws TransformerException 2176 { 2177 try 2178 { 2179 log( Level.WARNING, Messages.getMessage( exception ), exception ); 2180 } 2181 catch ( final MojoExecutionException e ) 2182 { 2183 getLog().warn( exception ); 2184 getLog().error( e ); 2185 } 2186 } 2187 2188 public void error( final TransformerException exception ) throws TransformerException 2189 { 2190 try 2191 { 2192 log( Level.SEVERE, Messages.getMessage( exception ), exception ); 2193 } 2194 catch ( final MojoExecutionException e ) 2195 { 2196 getLog().error( exception ); 2197 getLog().error( e ); 2198 } 2199 2200 throw exception; 2201 } 2202 2203 public void fatalError( final TransformerException exception ) throws TransformerException 2204 { 2205 try 2206 { 2207 log( Level.SEVERE, Messages.getMessage( exception ), exception ); 2208 } 2209 catch ( final MojoExecutionException e ) 2210 { 2211 getLog().error( exception ); 2212 getLog().error( e ); 2213 } 2214 2215 throw exception; 2216 } 2217 2218 }; 2219 2220 try 2221 { 2222 if ( url != null ) 2223 { 2224 if ( this.isLoggable( Level.FINER ) ) 2225 { 2226 this.log( Level.FINER, Messages.getMessage( "loadingTransformer", url.toExternalForm() ), null ); 2227 } 2228 2229 con = url.openConnection(); 2230 con.setConnectTimeout( resource.getConnectTimeout() ); 2231 con.setReadTimeout( resource.getReadTimeout() ); 2232 con.connect(); 2233 in = con.getInputStream(); 2234 2235 final TransformerFactory transformerFactory = TransformerFactory.newInstance(); 2236 transformerFactory.setErrorListener( errorListener ); 2237 final Transformer transformer = 2238 transformerFactory.newTransformer( new StreamSource( in, url.toURI().toASCIIString() ) ); 2239 2240 transformer.setErrorListener( errorListener ); 2241 2242 for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() ) 2243 { 2244 transformer.setParameter( e.getKey().toString(), e.getValue() ); 2245 } 2246 2247 if ( this.getMavenProject().getProperties() != null ) 2248 { 2249 for ( final Map.Entry<Object, Object> e : this.getMavenProject().getProperties().entrySet() ) 2250 { 2251 transformer.setParameter( e.getKey().toString(), e.getValue() ); 2252 } 2253 } 2254 2255 if ( this.transformationParameterResources != null ) 2256 { 2257 for ( int i = 0, s0 = this.transformationParameterResources.size(); i < s0; i++ ) 2258 { 2259 for ( final Map.Entry<Object, Object> e : this.getProperties( 2260 this.transformationParameterResources.get( i ) ).entrySet() ) 2261 { 2262 transformer.setParameter( e.getKey().toString(), e.getValue() ); 2263 } 2264 } 2265 } 2266 2267 if ( this.transformationParameters != null ) 2268 { 2269 for ( final TransformationParameter e : this.transformationParameters ) 2270 { 2271 transformer.setParameter( e.getKey(), e.getObject() ); 2272 } 2273 } 2274 2275 if ( this.transformationOutputProperties != null ) 2276 { 2277 for ( final TransformationOutputProperty e : this.transformationOutputProperties ) 2278 { 2279 transformer.setOutputProperty( e.getKey(), e.getValue() ); 2280 } 2281 } 2282 2283 for ( int i = 0, s0 = resource.getTransformationParameterResources().size(); i < s0; i++ ) 2284 { 2285 for ( final Map.Entry<Object, Object> e : this.getProperties( 2286 resource.getTransformationParameterResources().get( i ) ).entrySet() ) 2287 { 2288 transformer.setParameter( e.getKey().toString(), e.getValue() ); 2289 } 2290 } 2291 2292 for ( final TransformationParameter e : resource.getTransformationParameters() ) 2293 { 2294 transformer.setParameter( e.getKey(), e.getObject() ); 2295 } 2296 2297 for ( final TransformationOutputProperty e : resource.getTransformationOutputProperties() ) 2298 { 2299 transformer.setOutputProperty( e.getKey(), e.getValue() ); 2300 } 2301 2302 in.close(); 2303 in = null; 2304 2305 return transformer; 2306 } 2307 else if ( resource.isOptional() ) 2308 { 2309 if ( this.isLoggable( Level.WARNING ) ) 2310 { 2311 this.log( Level.WARNING, Messages.getMessage( 2312 "transformerNotFound", resource.getLocation() ), null ); 2313 2314 } 2315 } 2316 else 2317 { 2318 throw new MojoExecutionException( Messages.getMessage( 2319 "transformerNotFound", resource.getLocation() ) ); 2320 2321 } 2322 } 2323 catch ( final InstantiationException e ) 2324 { 2325 throw new MojoExecutionException( Messages.getMessage( e ), e ); 2326 } 2327 catch ( final URISyntaxException e ) 2328 { 2329 throw new MojoExecutionException( Messages.getMessage( e ), e ); 2330 } 2331 catch ( final TransformerConfigurationException e ) 2332 { 2333 String m = Messages.getMessage( e ); 2334 if ( m == null ) 2335 { 2336 m = Messages.getMessage( e.getException() ); 2337 } 2338 2339 m = m == null ? "" : " " + m; 2340 2341 throw new MojoExecutionException( Messages.getMessage( 2342 "failedCreatingTransformer", resource.getLocation(), m ), e ); 2343 2344 } 2345 catch ( final SocketTimeoutException e ) 2346 { 2347 String m = Messages.getMessage( e ); 2348 m = m == null ? "" : " " + m; 2349 2350 if ( resource.isOptional() ) 2351 { 2352 if ( this.isLoggable( Level.WARNING ) ) 2353 { 2354 this.log( Level.WARNING, Messages.getMessage( 2355 "failedLoadingTransformer", url.toExternalForm(), m ), e ); 2356 2357 } 2358 } 2359 else 2360 { 2361 throw new MojoExecutionException( Messages.getMessage( 2362 "failedLoadingTransformer", url.toExternalForm(), m ), e ); 2363 2364 } 2365 } 2366 catch ( final IOException e ) 2367 { 2368 String m = Messages.getMessage( e ); 2369 m = m == null ? "" : " " + m; 2370 2371 if ( resource.isOptional() ) 2372 { 2373 if ( this.isLoggable( Level.WARNING ) ) 2374 { 2375 this.log( Level.WARNING, Messages.getMessage( 2376 "failedLoadingTransformer", url.toExternalForm(), m ), e ); 2377 2378 } 2379 } 2380 else 2381 { 2382 throw new MojoExecutionException( Messages.getMessage( 2383 "failedLoadingTransformer", url.toExternalForm(), m ), e ); 2384 2385 } 2386 } 2387 finally 2388 { 2389 try 2390 { 2391 if ( in != null ) 2392 { 2393 in.close(); 2394 } 2395 } 2396 catch ( final IOException e ) 2397 { 2398 this.getLog().error( e ); 2399 } 2400 finally 2401 { 2402 if ( con instanceof HttpURLConnection ) 2403 { 2404 ( (HttpURLConnection) con ).disconnect(); 2405 } 2406 } 2407 } 2408 2409 return null; 2410 } 2411 2412 /** 2413 * Creates a new {@code Transformer} from a given {@code TransformerResourceType}. 2414 * 2415 * @param modelContext The model context to search. 2416 * @param resource The resource to initialize the transformer with. 2417 * 2418 * @return A {@code Transformer} for {@code resource} or {@code null}, if {@code resource} is not found and flagged 2419 * optional. 2420 * 2421 * @throws NullPointerException if {@code modelContext} or {@code resource} is {@code null}. 2422 * @throws MojoExecutionException if creating a transformer fails. 2423 * 2424 * @see #getResource(org.jomc.modlet.ModelContext, java.lang.String) 2425 * @since 1.8 2426 */ 2427 protected Transformer getTransformer( final ModelContext modelContext, final TransformerResourceType resource ) 2428 throws MojoExecutionException 2429 { 2430 if ( modelContext == null ) 2431 { 2432 throw new NullPointerException( "modelContext" ); 2433 } 2434 if ( resource == null ) 2435 { 2436 throw new NullPointerException( "resource" ); 2437 } 2438 2439 URLConnection con = null; 2440 InputStream in = null; 2441 final URL url = this.getResource( modelContext, resource.getLocation() ); 2442 final ErrorListener errorListener = new ErrorListener() 2443 { 2444 2445 public void warning( final TransformerException exception ) throws TransformerException 2446 { 2447 try 2448 { 2449 log( Level.WARNING, Messages.getMessage( exception ), exception ); 2450 } 2451 catch ( final MojoExecutionException e ) 2452 { 2453 getLog().warn( exception ); 2454 getLog().error( e ); 2455 } 2456 } 2457 2458 public void error( final TransformerException exception ) throws TransformerException 2459 { 2460 try 2461 { 2462 log( Level.SEVERE, Messages.getMessage( exception ), exception ); 2463 } 2464 catch ( final MojoExecutionException e ) 2465 { 2466 getLog().error( exception ); 2467 getLog().error( e ); 2468 } 2469 2470 throw exception; 2471 } 2472 2473 public void fatalError( final TransformerException exception ) throws TransformerException 2474 { 2475 try 2476 { 2477 log( Level.SEVERE, Messages.getMessage( exception ), exception ); 2478 } 2479 catch ( final MojoExecutionException e ) 2480 { 2481 getLog().error( exception ); 2482 getLog().error( e ); 2483 } 2484 2485 throw exception; 2486 } 2487 2488 }; 2489 2490 try 2491 { 2492 if ( url != null ) 2493 { 2494 if ( this.isLoggable( Level.FINER ) ) 2495 { 2496 this.log( Level.FINER, Messages.getMessage( "loadingTransformer", url.toExternalForm() ), null ); 2497 } 2498 2499 con = url.openConnection(); 2500 con.setConnectTimeout( resource.getConnectTimeout() ); 2501 con.setReadTimeout( resource.getReadTimeout() ); 2502 con.connect(); 2503 in = con.getInputStream(); 2504 2505 final TransformerFactory transformerFactory = TransformerFactory.newInstance(); 2506 transformerFactory.setErrorListener( errorListener ); 2507 final Transformer transformer = 2508 transformerFactory.newTransformer( new StreamSource( in, url.toURI().toASCIIString() ) ); 2509 2510 transformer.setErrorListener( errorListener ); 2511 2512 for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() ) 2513 { 2514 transformer.setParameter( e.getKey().toString(), e.getValue() ); 2515 } 2516 2517 if ( this.getMavenProject().getProperties() != null ) 2518 { 2519 for ( final Map.Entry<Object, Object> e : this.getMavenProject().getProperties().entrySet() ) 2520 { 2521 transformer.setParameter( e.getKey().toString(), e.getValue() ); 2522 } 2523 } 2524 2525 if ( this.transformationParameterResources != null ) 2526 { 2527 for ( int i = 0, s0 = this.transformationParameterResources.size(); i < s0; i++ ) 2528 { 2529 for ( final Map.Entry<Object, Object> e : this.getProperties( 2530 modelContext, this.transformationParameterResources.get( i ) ).entrySet() ) 2531 { 2532 transformer.setParameter( e.getKey().toString(), e.getValue() ); 2533 } 2534 } 2535 } 2536 2537 if ( this.transformationParameters != null ) 2538 { 2539 for ( final TransformationParameter e : this.transformationParameters ) 2540 { 2541 transformer.setParameter( e.getKey(), e.getObject( modelContext ) ); 2542 } 2543 } 2544 2545 if ( this.transformationOutputProperties != null ) 2546 { 2547 for ( final TransformationOutputProperty e : this.transformationOutputProperties ) 2548 { 2549 transformer.setOutputProperty( e.getKey(), e.getValue() ); 2550 } 2551 } 2552 2553 for ( int i = 0, s0 = resource.getTransformationParameterResources().size(); i < s0; i++ ) 2554 { 2555 for ( final Map.Entry<Object, Object> e : this.getProperties( 2556 modelContext, resource.getTransformationParameterResources().get( i ) ).entrySet() ) 2557 { 2558 transformer.setParameter( e.getKey().toString(), e.getValue() ); 2559 } 2560 } 2561 2562 for ( final TransformationParameter e : resource.getTransformationParameters() ) 2563 { 2564 transformer.setParameter( e.getKey(), e.getObject( modelContext ) ); 2565 } 2566 2567 for ( final TransformationOutputProperty e : resource.getTransformationOutputProperties() ) 2568 { 2569 transformer.setOutputProperty( e.getKey(), e.getValue() ); 2570 } 2571 2572 in.close(); 2573 in = null; 2574 2575 return transformer; 2576 } 2577 else if ( resource.isOptional() ) 2578 { 2579 if ( this.isLoggable( Level.WARNING ) ) 2580 { 2581 this.log( Level.WARNING, Messages.getMessage( 2582 "transformerNotFound", resource.getLocation() ), null ); 2583 2584 } 2585 } 2586 else 2587 { 2588 throw new MojoExecutionException( Messages.getMessage( 2589 "transformerNotFound", resource.getLocation() ) ); 2590 2591 } 2592 } 2593 catch ( final InstantiationException e ) 2594 { 2595 throw new MojoExecutionException( Messages.getMessage( e ), e ); 2596 } 2597 catch ( final URISyntaxException e ) 2598 { 2599 throw new MojoExecutionException( Messages.getMessage( e ), e ); 2600 } 2601 catch ( final TransformerConfigurationException e ) 2602 { 2603 String m = Messages.getMessage( e ); 2604 if ( m == null ) 2605 { 2606 m = Messages.getMessage( e.getException() ); 2607 } 2608 2609 m = m == null ? "" : " " + m; 2610 2611 throw new MojoExecutionException( Messages.getMessage( 2612 "failedCreatingTransformer", resource.getLocation(), m ), e ); 2613 2614 } 2615 catch ( final SocketTimeoutException e ) 2616 { 2617 String m = Messages.getMessage( e ); 2618 m = m == null ? "" : " " + m; 2619 2620 if ( resource.isOptional() ) 2621 { 2622 if ( this.isLoggable( Level.WARNING ) ) 2623 { 2624 this.log( Level.WARNING, Messages.getMessage( 2625 "failedLoadingTransformer", url.toExternalForm(), m ), e ); 2626 2627 } 2628 } 2629 else 2630 { 2631 throw new MojoExecutionException( Messages.getMessage( 2632 "failedLoadingTransformer", url.toExternalForm(), m ), e ); 2633 2634 } 2635 } 2636 catch ( final IOException e ) 2637 { 2638 String m = Messages.getMessage( e ); 2639 m = m == null ? "" : " " + m; 2640 2641 if ( resource.isOptional() ) 2642 { 2643 if ( this.isLoggable( Level.WARNING ) ) 2644 { 2645 this.log( Level.WARNING, Messages.getMessage( 2646 "failedLoadingTransformer", url.toExternalForm(), m ), e ); 2647 2648 } 2649 } 2650 else 2651 { 2652 throw new MojoExecutionException( Messages.getMessage( 2653 "failedLoadingTransformer", url.toExternalForm(), m ), e ); 2654 2655 } 2656 } 2657 finally 2658 { 2659 try 2660 { 2661 if ( in != null ) 2662 { 2663 in.close(); 2664 } 2665 } 2666 catch ( final IOException e ) 2667 { 2668 this.getLog().error( e ); 2669 } 2670 finally 2671 { 2672 if ( con instanceof HttpURLConnection ) 2673 { 2674 ( (HttpURLConnection) con ).disconnect(); 2675 } 2676 } 2677 } 2678 2679 return null; 2680 } 2681 2682 /** 2683 * Creates a new {@code Properties} instance from a {@code PropertiesResourceType}. 2684 * 2685 * @param propertiesResourceType The {@code PropertiesResourceType} specifying the properties to create. 2686 * 2687 * @return The properties for {@code propertiesResourceType}. 2688 * 2689 * @throws NullPointerException if {@code propertiesResourceType} is {@code null}. 2690 * @throws MojoExecutionException if loading properties fails. 2691 * 2692 * @see #getResource(java.lang.String) 2693 * @since 1.2 2694 * @deprecated As of JOMC 1.8, replaced by method {@link #getProperties(org.jomc.modlet.ModelContext, org.jomc.mojo.PropertiesResourceType)}. 2695 * This method will be removed in JOMC 2.0. 2696 */ 2697 @Deprecated 2698 @SuppressWarnings( "deprecation" ) 2699 protected Properties getProperties( final PropertiesResourceType propertiesResourceType ) 2700 throws MojoExecutionException 2701 { 2702 if ( propertiesResourceType == null ) 2703 { 2704 throw new NullPointerException( "propertiesResourceType" ); 2705 } 2706 2707 URLConnection con = null; 2708 InputStream in = null; 2709 final URL url = this.getResource( propertiesResourceType.getLocation() ); 2710 final Properties properties = new Properties(); 2711 2712 try 2713 { 2714 if ( url != null ) 2715 { 2716 if ( this.isLoggable( Level.FINER ) ) 2717 { 2718 this.log( Level.FINER, Messages.getMessage( "loadingProperties", url.toExternalForm() ), null ); 2719 } 2720 2721 con = url.openConnection(); 2722 con.setConnectTimeout( propertiesResourceType.getConnectTimeout() ); 2723 con.setReadTimeout( propertiesResourceType.getReadTimeout() ); 2724 con.connect(); 2725 in = con.getInputStream(); 2726 2727 if ( PropertiesResourceType.PLAIN_FORMAT.equalsIgnoreCase( propertiesResourceType.getFormat() ) ) 2728 { 2729 properties.load( in ); 2730 } 2731 else if ( PropertiesResourceType.XML_FORMAT.equalsIgnoreCase( propertiesResourceType.getFormat() ) ) 2732 { 2733 properties.loadFromXML( in ); 2734 } 2735 2736 in.close(); 2737 in = null; 2738 } 2739 else if ( propertiesResourceType.isOptional() ) 2740 { 2741 if ( this.isLoggable( Level.WARNING ) ) 2742 { 2743 this.log( Level.WARNING, Messages.getMessage( 2744 "propertiesNotFound", propertiesResourceType.getLocation() ), null ); 2745 2746 } 2747 } 2748 else 2749 { 2750 throw new MojoExecutionException( Messages.getMessage( 2751 "propertiesNotFound", propertiesResourceType.getLocation() ) ); 2752 2753 } 2754 } 2755 catch ( final SocketTimeoutException e ) 2756 { 2757 String m = Messages.getMessage( e ); 2758 m = m == null ? "" : " " + m; 2759 2760 if ( propertiesResourceType.isOptional() ) 2761 { 2762 if ( this.isLoggable( Level.WARNING ) ) 2763 { 2764 this.log( Level.WARNING, Messages.getMessage( 2765 "failedLoadingProperties", url.toExternalForm(), m ), e ); 2766 2767 } 2768 } 2769 else 2770 { 2771 throw new MojoExecutionException( Messages.getMessage( 2772 "failedLoadingProperties", url.toExternalForm(), m ), e ); 2773 2774 } 2775 } 2776 catch ( final IOException e ) 2777 { 2778 String m = Messages.getMessage( e ); 2779 m = m == null ? "" : " " + m; 2780 2781 if ( propertiesResourceType.isOptional() ) 2782 { 2783 if ( this.isLoggable( Level.WARNING ) ) 2784 { 2785 this.log( Level.WARNING, Messages.getMessage( 2786 "failedLoadingProperties", url.toExternalForm(), m ), e ); 2787 2788 } 2789 } 2790 else 2791 { 2792 throw new MojoExecutionException( Messages.getMessage( 2793 "failedLoadingProperties", url.toExternalForm(), m ), e ); 2794 2795 } 2796 } 2797 finally 2798 { 2799 try 2800 { 2801 if ( in != null ) 2802 { 2803 in.close(); 2804 } 2805 } 2806 catch ( final IOException e ) 2807 { 2808 this.getLog().error( e ); 2809 } 2810 finally 2811 { 2812 if ( con instanceof HttpURLConnection ) 2813 { 2814 ( (HttpURLConnection) con ).disconnect(); 2815 } 2816 } 2817 } 2818 2819 return properties; 2820 } 2821 2822 /** 2823 * Creates a new {@code Properties} instance from a {@code PropertiesResourceType}. 2824 * 2825 * @param modelContext The model context to search. 2826 * @param propertiesResourceType The {@code PropertiesResourceType} specifying the properties to create. 2827 * 2828 * @return The properties for {@code propertiesResourceType}. 2829 * 2830 * @throws NullPointerException if {@code modelContext} or {@code propertiesResourceType} is {@code null}. 2831 * @throws MojoExecutionException if loading properties fails. 2832 * 2833 * @see #getResource(org.jomc.modlet.ModelContext, java.lang.String) 2834 * @since 1.8 2835 */ 2836 protected Properties getProperties( final ModelContext modelContext, 2837 final PropertiesResourceType propertiesResourceType ) 2838 throws MojoExecutionException 2839 { 2840 if ( modelContext == null ) 2841 { 2842 throw new NullPointerException( "modelContext" ); 2843 } 2844 if ( propertiesResourceType == null ) 2845 { 2846 throw new NullPointerException( "propertiesResourceType" ); 2847 } 2848 2849 URLConnection con = null; 2850 InputStream in = null; 2851 final URL url = this.getResource( modelContext, propertiesResourceType.getLocation() ); 2852 final Properties properties = new Properties(); 2853 2854 try 2855 { 2856 if ( url != null ) 2857 { 2858 if ( this.isLoggable( Level.FINER ) ) 2859 { 2860 this.log( Level.FINER, Messages.getMessage( "loadingProperties", url.toExternalForm() ), null ); 2861 } 2862 2863 con = url.openConnection(); 2864 con.setConnectTimeout( propertiesResourceType.getConnectTimeout() ); 2865 con.setReadTimeout( propertiesResourceType.getReadTimeout() ); 2866 con.connect(); 2867 in = con.getInputStream(); 2868 2869 if ( PropertiesResourceType.PLAIN_FORMAT.equalsIgnoreCase( propertiesResourceType.getFormat() ) ) 2870 { 2871 properties.load( in ); 2872 } 2873 else if ( PropertiesResourceType.XML_FORMAT.equalsIgnoreCase( propertiesResourceType.getFormat() ) ) 2874 { 2875 properties.loadFromXML( in ); 2876 } 2877 2878 in.close(); 2879 in = null; 2880 } 2881 else if ( propertiesResourceType.isOptional() ) 2882 { 2883 if ( this.isLoggable( Level.WARNING ) ) 2884 { 2885 this.log( Level.WARNING, Messages.getMessage( 2886 "propertiesNotFound", propertiesResourceType.getLocation() ), null ); 2887 2888 } 2889 } 2890 else 2891 { 2892 throw new MojoExecutionException( Messages.getMessage( 2893 "propertiesNotFound", propertiesResourceType.getLocation() ) ); 2894 2895 } 2896 } 2897 catch ( final SocketTimeoutException e ) 2898 { 2899 String m = Messages.getMessage( e ); 2900 m = m == null ? "" : " " + m; 2901 2902 if ( propertiesResourceType.isOptional() ) 2903 { 2904 if ( this.isLoggable( Level.WARNING ) ) 2905 { 2906 this.log( Level.WARNING, Messages.getMessage( 2907 "failedLoadingProperties", url.toExternalForm(), m ), e ); 2908 2909 } 2910 } 2911 else 2912 { 2913 throw new MojoExecutionException( Messages.getMessage( 2914 "failedLoadingProperties", url.toExternalForm(), m ), e ); 2915 2916 } 2917 } 2918 catch ( final IOException e ) 2919 { 2920 String m = Messages.getMessage( e ); 2921 m = m == null ? "" : " " + m; 2922 2923 if ( propertiesResourceType.isOptional() ) 2924 { 2925 if ( this.isLoggable( Level.WARNING ) ) 2926 { 2927 this.log( Level.WARNING, Messages.getMessage( 2928 "failedLoadingProperties", url.toExternalForm(), m ), e ); 2929 2930 } 2931 } 2932 else 2933 { 2934 throw new MojoExecutionException( Messages.getMessage( 2935 "failedLoadingProperties", url.toExternalForm(), m ), e ); 2936 2937 } 2938 } 2939 finally 2940 { 2941 try 2942 { 2943 if ( in != null ) 2944 { 2945 in.close(); 2946 } 2947 } 2948 catch ( final IOException e ) 2949 { 2950 this.getLog().error( e ); 2951 } 2952 finally 2953 { 2954 if ( con instanceof HttpURLConnection ) 2955 { 2956 ( (HttpURLConnection) con ).disconnect(); 2957 } 2958 } 2959 } 2960 2961 return properties; 2962 } 2963 2964 /** 2965 * Tests if messages at a given level are logged. 2966 * 2967 * @param level The level to test. 2968 * 2969 * @return {@code true}, if messages at {@code level} are logged; {@code false}, if messages at {@code level} are 2970 * suppressed. 2971 * 2972 * @throws NullPointerException if {@code level} is {@code null}. 2973 * @throws MojoExecutionException if testing the level fails. 2974 * 2975 * @see #isVerbose() 2976 * @since 1.2 2977 */ 2978 protected boolean isLoggable( final Level level ) throws MojoExecutionException 2979 { 2980 if ( level == null ) 2981 { 2982 throw new NullPointerException( "level" ); 2983 } 2984 2985 boolean loggable = false; 2986 2987 if ( level.intValue() <= Level.CONFIG.intValue() ) 2988 { 2989 loggable = this.getLog().isDebugEnabled(); 2990 } 2991 else if ( level.intValue() <= Level.INFO.intValue() ) 2992 { 2993 loggable = this.getLog().isInfoEnabled() && this.isVerbose(); 2994 } 2995 else if ( level.intValue() <= Level.WARNING.intValue() ) 2996 { 2997 loggable = this.getLog().isWarnEnabled(); 2998 } 2999 else if ( level.intValue() <= Level.SEVERE.intValue() ) 3000 { 3001 loggable = this.getLog().isErrorEnabled(); 3002 } 3003 3004 return loggable; 3005 } 3006 3007 /** 3008 * Logs a separator at a given level. 3009 * 3010 * @param level The level to log a separator at. 3011 * 3012 * @throws MojoExecutionException if logging fails. 3013 * 3014 * @deprecated As of JOMC 1.1, please use method {@link #logSeparator()}. This method will be removed in version 3015 * 2.0. 3016 */ 3017 @Deprecated 3018 protected void logSeparator( final Level level ) throws MojoExecutionException 3019 { 3020 this.logSeparator(); 3021 } 3022 3023 /** 3024 * Logs a separator. 3025 * 3026 * @throws MojoExecutionException if logging fails. 3027 * 3028 * @since 1.1 3029 */ 3030 protected void logSeparator() throws MojoExecutionException 3031 { 3032 if ( this.isLoggable( Level.INFO ) ) 3033 { 3034 this.log( Level.INFO, Messages.getMessage( "separator" ), null ); 3035 } 3036 } 3037 3038 /** 3039 * Logs a message stating a tool is starting to process a module. 3040 * 3041 * @param toolName The tool starting execution. 3042 * @param module The module getting processed. 3043 * 3044 * @throws MojoExecutionException if logging fails. 3045 */ 3046 protected void logProcessingModule( final String toolName, final String module ) throws MojoExecutionException 3047 { 3048 if ( this.isLoggable( Level.INFO ) ) 3049 { 3050 this.log( Level.INFO, Messages.getMessage( "processingModule", toolName, module ), null ); 3051 } 3052 } 3053 3054 /** 3055 * Logs a message stating a tool is starting to process a model. 3056 * 3057 * @param toolName The tool starting execution. 3058 * @param model The model getting processed. 3059 * 3060 * @throws MojoExecutionException if logging fails. 3061 * 3062 * @since 1.1 3063 */ 3064 protected void logProcessingModel( final String toolName, final String model ) throws MojoExecutionException 3065 { 3066 if ( this.isLoggable( Level.INFO ) ) 3067 { 3068 this.log( Level.INFO, Messages.getMessage( "processingModel", toolName, model ), null ); 3069 } 3070 } 3071 3072 /** 3073 * Logs a message stating that a module has not been found. 3074 * 3075 * @param module The module not having been found. 3076 * 3077 * @throws MojoExecutionException if logging fails. 3078 */ 3079 protected void logMissingModule( final String module ) throws MojoExecutionException 3080 { 3081 if ( this.isLoggable( Level.WARNING ) ) 3082 { 3083 this.log( Level.WARNING, Messages.getMessage( "missingModule", module ), null ); 3084 } 3085 } 3086 3087 /** 3088 * Logs a message stating that a tool successfully completed execution. 3089 * 3090 * @param toolName The name of the tool. 3091 * 3092 * @throws MojoExecutionException if logging fails. 3093 */ 3094 protected void logToolSuccess( final String toolName ) throws MojoExecutionException 3095 { 3096 if ( this.isLoggable( Level.INFO ) ) 3097 { 3098 this.log( Level.INFO, Messages.getMessage( "toolSuccess", toolName ), null ); 3099 } 3100 } 3101 3102 /** 3103 * Logs a {@code ModelValidationReport}. 3104 * 3105 * @param context The context to use when marshalling detail elements of the report. 3106 * @param level The level to log at. 3107 * @param report The report to log. 3108 * 3109 * @throws MojoExecutionException if logging {@code report} fails. 3110 */ 3111 protected void log( final ModelContext context, final Level level, final ModelValidationReport report ) 3112 throws MojoExecutionException 3113 { 3114 try 3115 { 3116 if ( !report.getDetails().isEmpty() ) 3117 { 3118 this.logSeparator(); 3119 Marshaller marshaller = null; 3120 3121 for ( final ModelValidationReport.Detail detail : report.getDetails() ) 3122 { 3123 this.log( detail.getLevel(), "o " + detail.getMessage(), null ); 3124 3125 if ( detail.getElement() != null && this.isLoggable( Level.FINEST ) ) 3126 { 3127 if ( marshaller == null ) 3128 { 3129 marshaller = context.createMarshaller( this.getModel() ); 3130 marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); 3131 } 3132 3133 final StringWriter stringWriter = new StringWriter(); 3134 marshaller.marshal( detail.getElement(), stringWriter ); 3135 this.log( Level.FINEST, stringWriter.toString(), null ); 3136 } 3137 } 3138 } 3139 } 3140 catch ( final ModelException e ) 3141 { 3142 throw new MojoExecutionException( Messages.getMessage( e ), e ); 3143 } 3144 catch ( final JAXBException e ) 3145 { 3146 String message = Messages.getMessage( e ); 3147 if ( message == null && e.getLinkedException() != null ) 3148 { 3149 message = Messages.getMessage( e.getLinkedException() ); 3150 } 3151 3152 throw new MojoExecutionException( message, e ); 3153 } 3154 } 3155 3156 /** 3157 * Logs a message and throwable at a given level. 3158 * 3159 * @param level The level to log at. 3160 * @param message The message to log or {@code null}. 3161 * @param throwable The throwable to log or {@code null}. 3162 * 3163 * @throws MojoExecutionException if logging fails. 3164 */ 3165 protected void log( final Level level, final String message, final Throwable throwable ) 3166 throws MojoExecutionException 3167 { 3168 BufferedReader reader = null; 3169 3170 try 3171 { 3172 if ( this.isLoggable( level ) ) 3173 { 3174 reader = new BufferedReader( new StringReader( message == null ? "" : message ) ); 3175 boolean throwableLogged = false; 3176 3177 for ( String line = reader.readLine(); line != null; line = reader.readLine() ) 3178 { 3179 final String mojoMessage = 3180 Messages.getMessage( this.getLog().isDebugEnabled() ? "debugMessage" : "logMessage", line, 3181 Thread.currentThread().getName(), new Date( System.currentTimeMillis() ) ); 3182 3183 if ( level.intValue() <= Level.CONFIG.intValue() ) 3184 { 3185 this.getLog().debug( mojoMessage, throwableLogged ? null : throwable ); 3186 } 3187 else if ( level.intValue() <= Level.INFO.intValue() ) 3188 { 3189 this.getLog().info( mojoMessage, throwableLogged ? null : throwable ); 3190 } 3191 else if ( level.intValue() <= Level.WARNING.intValue() ) 3192 { 3193 this.getLog().warn( mojoMessage, throwableLogged ? null : throwable ); 3194 } 3195 else if ( level.intValue() <= Level.SEVERE.intValue() ) 3196 { 3197 this.getLog().error( mojoMessage, throwableLogged ? null : throwable ); 3198 } 3199 3200 throwableLogged = true; 3201 } 3202 3203 reader.close(); 3204 reader = null; 3205 } 3206 } 3207 catch ( final IOException e ) 3208 { 3209 this.getLog().error( e ); 3210 throw new AssertionError( e ); 3211 } 3212 finally 3213 { 3214 try 3215 { 3216 if ( reader != null ) 3217 { 3218 reader.close(); 3219 } 3220 } 3221 catch ( final IOException e ) 3222 { 3223 this.getLog().error( e ); 3224 } 3225 } 3226 } 3227 3228 /** 3229 * Configures a {@code ModelContext} instance. 3230 * 3231 * @param context The model context to configure. 3232 * 3233 * @throws NullPointerException if {@code context} is {@code null}. 3234 * @throws MojoExecutionException if configuring {@code context} fails. 3235 */ 3236 protected void setupModelContext( final ModelContext context ) throws MojoExecutionException 3237 { 3238 if ( context == null ) 3239 { 3240 throw new NullPointerException( "context" ); 3241 } 3242 3243 if ( this.isVerbose() || this.getLog().isDebugEnabled() ) 3244 { 3245 context.setLogLevel( this.getLog().isDebugEnabled() ? Level.ALL : Level.INFO ); 3246 } 3247 3248 try 3249 { 3250 context.setExecutorService( this.getExecutorService() ); 3251 context.setModletSchemaSystemId( this.modletSchemaSystemId ); 3252 context.getListeners().add( new ModelContext.Listener() 3253 { 3254 3255 @Override 3256 public void onLog( final Level level, final String message, final Throwable t ) 3257 { 3258 super.onLog( level, message, t ); 3259 3260 try 3261 { 3262 log( level, message, t ); 3263 } 3264 catch ( final MojoExecutionException e ) 3265 { 3266 getLog().error( e ); 3267 } 3268 } 3269 3270 } ); 3271 3272 if ( this.providerLocation != null ) 3273 { 3274 context.setAttribute( DefaultModelContext.PROVIDER_LOCATION_ATTRIBUTE_NAME, this.providerLocation ); 3275 } 3276 3277 if ( this.platformProviderLocation != null ) 3278 { 3279 context.setAttribute( DefaultModelContext.PLATFORM_PROVIDER_LOCATION_ATTRIBUTE_NAME, 3280 this.platformProviderLocation ); 3281 3282 } 3283 3284 if ( this.modletLocation != null ) 3285 { 3286 context.setAttribute( DefaultModletProvider.MODLET_LOCATION_ATTRIBUTE_NAME, this.modletLocation ); 3287 } 3288 3289 if ( this.transformerLocation != null ) 3290 { 3291 context.setAttribute( DefaultModelProcessor.TRANSFORMER_LOCATION_ATTRIBUTE_NAME, 3292 this.transformerLocation ); 3293 } 3294 3295 if ( this.moduleLocation != null ) 3296 { 3297 context.setAttribute( DefaultModelProvider.MODULE_LOCATION_ATTRIBUTE_NAME, this.moduleLocation ); 3298 } 3299 3300 context.setAttribute( ToolsModelProvider.MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME, 3301 this.modelObjectClasspathResolutionEnabled ); 3302 3303 context.setAttribute( ToolsModelProcessor.MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME, 3304 this.modelObjectClasspathResolutionEnabled ); 3305 3306 context.setAttribute( DefaultModletProvider.VALIDATING_ATTRIBUTE_NAME, 3307 this.modletResourceValidationEnabled ); 3308 3309 context.setAttribute( DefaultModelProvider.VALIDATING_ATTRIBUTE_NAME, this.modelResourceValidationEnabled ); 3310 context.setAttribute( DefaultModelValidator.VALIDATE_JAVA_ATTRIBUTE_NAME, this.javaValidationEnabled ); 3311 3312 if ( this.modelContextAttributes != null ) 3313 { 3314 for ( final ModelContextAttribute e : this.modelContextAttributes ) 3315 { 3316 final Object object = e.getObject( context ); 3317 3318 if ( object != null ) 3319 { 3320 context.setAttribute( e.getKey(), object ); 3321 } 3322 else 3323 { 3324 context.clearAttribute( e.getKey() ); 3325 } 3326 } 3327 } 3328 3329 if ( ( this.modletIncludes != null && !this.modletIncludes.isEmpty() ) 3330 || ( this.modletExcludes != null && !this.modletExcludes.isEmpty() ) ) 3331 { 3332 final Modlets modlets = context.getModlets().clone(); 3333 3334 for ( final Iterator<Modlet> it = modlets.getModlet().iterator(); it.hasNext(); ) 3335 { 3336 final Modlet modlet = it.next(); 3337 3338 if ( this.modletIncludes != null 3339 && !this.modletIncludes.isEmpty() 3340 && !this.modletIncludes.contains( modlet.getName() ) ) 3341 { 3342 it.remove(); 3343 this.log( Level.INFO, Messages.getMessage( "excludingModlet", modlet.getName() ), null ); 3344 continue; 3345 } 3346 3347 if ( this.modletExcludes != null 3348 && !this.modletExcludes.isEmpty() 3349 && this.modletExcludes.contains( modlet.getName() ) ) 3350 { 3351 it.remove(); 3352 this.log( Level.INFO, Messages.getMessage( "excludingModlet", modlet.getName() ), null ); 3353 continue; 3354 } 3355 3356 this.log( Level.INFO, Messages.getMessage( "includingModlet", modlet.getName() ), null ); 3357 } 3358 3359 context.setModlets( modlets ); 3360 } 3361 } 3362 catch ( final InstantiationException e ) 3363 { 3364 throw new MojoExecutionException( Messages.getMessage( e ), e ); 3365 } 3366 catch ( final ModelException e ) 3367 { 3368 throw new MojoExecutionException( Messages.getMessage( e ), e ); 3369 } 3370 } 3371 3372 /** 3373 * Configures a {@code JomcTool} instance. 3374 * 3375 * @param context The model context to use for configuring {@code tool}. 3376 * @param tool The tool to configure. 3377 * 3378 * @throws NullPointerException if {@code context} of {@code tool} is {@code null}. 3379 * @throws MojoExecutionException if configuring {@code tool} fails. 3380 */ 3381 @SuppressWarnings( "deprecation" ) 3382 protected void setupJomcTool( final ModelContext context, final JomcTool tool ) throws MojoExecutionException 3383 { 3384 if ( context == null ) 3385 { 3386 throw new NullPointerException( "context" ); 3387 } 3388 if ( tool == null ) 3389 { 3390 throw new NullPointerException( "tool" ); 3391 } 3392 3393 try 3394 { 3395 if ( this.isVerbose() || this.getLog().isDebugEnabled() ) 3396 { 3397 tool.setLogLevel( this.getLog().isDebugEnabled() ? Level.ALL : Level.INFO ); 3398 } 3399 3400 tool.setExecutorService( this.getExecutorService() ); 3401 tool.getListeners().add( new JomcTool.Listener() 3402 { 3403 3404 @Override 3405 public void onLog( final Level level, final String message, final Throwable t ) 3406 { 3407 super.onLog( level, message, t ); 3408 3409 try 3410 { 3411 log( level, message, t ); 3412 } 3413 catch ( final MojoExecutionException e ) 3414 { 3415 getLog().error( e ); 3416 } 3417 } 3418 3419 } ); 3420 3421 if ( this.templateEncoding != null ) 3422 { 3423 if ( this.isLoggable( Level.WARNING ) ) 3424 { 3425 this.log( Level.WARNING, Messages.getMessage( 3426 "deprecationWarning", "templateEncoding", "defaultTemplateEncoding" ), null ); 3427 3428 } 3429 3430 tool.setDefaultTemplateEncoding( this.templateEncoding ); 3431 } 3432 else 3433 { 3434 tool.setDefaultTemplateEncoding( this.defaultTemplateEncoding ); 3435 } 3436 3437 tool.setInputEncoding( this.sourceEncoding ); 3438 tool.setOutputEncoding( this.sourceEncoding ); 3439 tool.setDefaultTemplateProfile( this.defaultTemplateProfile ); 3440 tool.setTemplateProfile( this.templateProfile ); 3441 tool.setModel( this.getModel( context ) ); 3442 3443 if ( this.indentation != null ) 3444 { 3445 tool.setIndentation( StringEscapeUtils.unescapeJava( this.indentation ) ); 3446 } 3447 3448 if ( this.lineSeparator != null ) 3449 { 3450 tool.setLineSeparator( StringEscapeUtils.unescapeJava( this.lineSeparator ) ); 3451 } 3452 3453 if ( this.locale != null ) 3454 { 3455 tool.setLocale( new Locale( StringUtils.defaultString( this.locale.getLanguage() ), 3456 StringUtils.defaultString( this.locale.getCountry() ), 3457 StringUtils.defaultString( this.locale.getVariant() ) ) ); 3458 3459 } 3460 3461 if ( this.velocityPropertyResources != null ) 3462 { 3463 for ( int i = 0, s0 = this.velocityPropertyResources.size(); i < s0; i++ ) 3464 { 3465 for ( final Map.Entry<Object, Object> e : this.getProperties( 3466 context, this.velocityPropertyResources.get( i ) ).entrySet() ) 3467 { 3468 if ( e.getValue() != null ) 3469 { 3470 tool.getVelocityEngine().setProperty( e.getKey().toString(), e ); 3471 } 3472 else 3473 { 3474 tool.getVelocityEngine().clearProperty( e.getKey().toString() ); 3475 } 3476 } 3477 } 3478 } 3479 3480 if ( this.velocityProperties != null ) 3481 { 3482 for ( final VelocityProperty e : this.velocityProperties ) 3483 { 3484 final Object object = e.getObject( context ); 3485 3486 if ( object != null ) 3487 { 3488 tool.getVelocityEngine().setProperty( e.getKey(), object ); 3489 } 3490 else 3491 { 3492 tool.getVelocityEngine().clearProperty( e.getKey() ); 3493 } 3494 } 3495 } 3496 3497 for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() ) 3498 { 3499 tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() ); 3500 } 3501 3502 if ( this.getMavenProject().getProperties() != null ) 3503 { 3504 for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() ) 3505 { 3506 tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() ); 3507 } 3508 } 3509 3510 if ( this.templateParameterResources != null ) 3511 { 3512 for ( int i = 0, s0 = this.templateParameterResources.size(); i < s0; i++ ) 3513 { 3514 for ( final Map.Entry<Object, Object> e : this.getProperties( 3515 context, this.templateParameterResources.get( i ) ).entrySet() ) 3516 { 3517 if ( e.getValue() != null ) 3518 { 3519 tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() ); 3520 } 3521 else 3522 { 3523 tool.getTemplateParameters().remove( e.getKey().toString() ); 3524 } 3525 } 3526 } 3527 } 3528 3529 if ( this.templateParameters != null ) 3530 { 3531 for ( final TemplateParameter e : this.templateParameters ) 3532 { 3533 final Object object = e.getObject( context ); 3534 3535 if ( object != null ) 3536 { 3537 tool.getTemplateParameters().put( e.getKey(), object ); 3538 } 3539 else 3540 { 3541 tool.getTemplateParameters().remove( e.getKey() ); 3542 } 3543 } 3544 } 3545 3546 if ( this.templateLocation != null ) 3547 { 3548 final URL url = this.getDirectory( this.templateLocation ); 3549 tool.setTemplateLocation( url ); 3550 3551 if ( url == null && this.isLoggable( Level.WARNING ) ) 3552 { 3553 this.log( Level.WARNING, Messages.getMessage( "locationNotFound", this.templateLocation ), null ); 3554 } 3555 } 3556 } 3557 catch ( final InstantiationException e ) 3558 { 3559 throw new MojoExecutionException( Messages.getMessage( e ), e ); 3560 } 3561 } 3562 3563 /** 3564 * Copies a file. 3565 * 3566 * @param source The file to copy. 3567 * @param target The file to copy the source file to. 3568 * 3569 * @throws IOException if copying fails. 3570 * 3571 * @since 1.10 3572 * 3573 * @deprecated This method will be removed in 2.0 due to availability of Java 7 file copying features. 3574 */ 3575 @Deprecated 3576 protected final void copyFile( final File source, final File target ) throws IOException 3577 { 3578 InputStream in = null; 3579 OutputStream out = null; 3580 try 3581 { 3582 if ( !source.equals( target ) ) 3583 { 3584 in = new FileInputStream( source ); 3585 out = new FileOutputStream( target ); 3586 3587 final byte[] buffer = new byte[ 65536 ]; 3588 3589 for ( int read = in.read( buffer ); 3590 read >= 0; 3591 out.write( buffer, 0, read ), read = in.read( buffer ) ); 3592 3593 out.close(); 3594 out = null; 3595 3596 in.close(); 3597 in = null; 3598 } 3599 } 3600 finally 3601 { 3602 try 3603 { 3604 if ( out != null ) 3605 { 3606 out.close(); 3607 } 3608 } 3609 catch ( final IOException e ) 3610 { 3611 this.getLog().warn( e ); 3612 } 3613 finally 3614 { 3615 try 3616 { 3617 if ( in != null ) 3618 { 3619 in.close(); 3620 } 3621 } 3622 catch ( final IOException e ) 3623 { 3624 this.getLog().warn( e ); 3625 } 3626 } 3627 } 3628 } 3629 3630 /** 3631 * Copies a directory recursively. 3632 * 3633 * @param source The directory to copy. 3634 * @param target The directory to copy to. 3635 * 3636 * @throws IOException if copying fails. 3637 * 3638 * @since 1.10 3639 */ 3640 @SuppressWarnings( "deprecation" ) 3641 protected final void copyDirectory( final File source, final File target ) throws IOException 3642 { 3643 if ( !target.isDirectory() && !target.mkdirs() ) 3644 { 3645 throw new IOException( Messages.getMessage( "failedCreatingDirectory", target.getAbsolutePath() ) ); 3646 } 3647 3648 for ( final File file : source.listFiles() ) 3649 { 3650 final File targetFile = new File( target, file.getName() ); 3651 3652 if ( file.isFile() ) 3653 { 3654 this.copyFile( file, targetFile ); 3655 } 3656 else if ( file.isDirectory() ) 3657 { 3658 this.copyDirectory( file, targetFile ); 3659 } 3660 else 3661 { 3662 throw new IOException( Messages.getMessage( "failedCopying", file.getAbsolutePath(), 3663 targetFile.getAbsolutePath() ) ); 3664 3665 } 3666 } 3667 } 3668 3669 private Artifact getPluginArtifact( final Artifact a ) 3670 { 3671 for ( int i = 0, s0 = this.pluginArtifacts.size(); i < s0; i++ ) 3672 { 3673 final Artifact pluginArtifact = this.pluginArtifacts.get( i ); 3674 3675 if ( pluginArtifact.getGroupId().equals( a.getGroupId() ) 3676 && pluginArtifact.getArtifactId().equals( a.getArtifactId() ) 3677 && ( pluginArtifact.hasClassifier() 3678 ? pluginArtifact.getClassifier().equals( a.getClassifier() ) 3679 : !a.hasClassifier() ) ) 3680 { 3681 return pluginArtifact; 3682 } 3683 } 3684 3685 return null; 3686 } 3687 3688}