pax_global_header00006660000000000000000000000064135110021340014500gustar00rootroot0000000000000052 comment=1ac2e020aaca2fb82514bf1f0d9d90fa899227c7 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/000077500000000000000000000000001351100213400205165ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/.gitignore000066400000000000000000000071401351100213400225100ustar00rootroot00000000000000# # Standard gitignore file for Java and Maven development. # ### TortoiseGit ### # Project-level settings /.tgitconfig ### OSX ### .DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear on external disk .Spotlight-V100 .Trashes # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk ### Windows ### # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp # Windows shortcuts *.lnk ### Linux ### *~ # KDE directory preferences .directory ### Eclipse ### *.pydevproject .metadata .gradle bin/ tmp/ *.tmp *.bak *.swp *~.nib local.properties .settings/ .loadpath .project .classpath # External tool builders .externalToolBuilders/ # Locally stored "Eclipse launch configurations" *.launch # CDT-specific .cproject # PDT-specific .buildpath # sbteclipse plugin .target # TeXlipse plugin .texlipse ### NetBeans ### nbproject/private/ build/ nbbuild/ dist/ nbdist/ nbactions.xml nb-configuration.xml ### Intellij ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm *.iml ## Directory-based project format: .idea/ # if you remove the above rule, at least ignore the following: # User-specific stuff: # .idea/workspace.xml # .idea/tasks.xml # .idea/dictionaries # Sensitive or high-churn files: # .idea/dataSources.ids # .idea/dataSources.xml # .idea/sqlDataSources.xml # .idea/dynamic.xml # .idea/uiDesigner.xml # Gradle: # .idea/gradle.xml # .idea/libraries # Mongo Explorer plugin: # .idea/mongoSettings.xml ## File-based project format: *.ipr *.iws ## Plugin-specific files: # IntelliJ out/ # mpeltonen/sbt-idea plugin .idea_modules/ # JIRA plugin atlassian-ide-plugin.xml # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties ### vim ### [._]*.s[a-w][a-z] [._]s[a-w][a-z] *.un~ Session.vim .netrwhist *~ ### Maven ### target/ pom.xml.tag pom.xml.releaseBackup pom.xml.versionsBackup pom.xml.next release.properties ### Karma ### node/ node_modules/ ### Java ### *.class # Mobile Tools for Java (J2ME) .mtj.tmp/ # Package Files # *.jar *.war *.ear # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # PyBuilder target/ ### CVS ### /CVS/* */CVS/* .cvsignore */.cvsignore ### SVN ### .svn/ ### Mercurial ### /.hg/* */.hg/* .hgignore ### Windows ### # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp # Windows shortcuts *.lnk ### Linux ### *~ # KDE directory preferences .directory # Linux trash folder which might appear on any partition or disk .Trash-* ### Takari Maven Wrapper ### /mvnw.bat /mvnw /.mvn/ jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/.java-version000066400000000000000000000000041351100213400231150ustar00rootroot000000000000001.8 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/.travis.yml000066400000000000000000000004731351100213400226330ustar00rootroot00000000000000language: java jdk: - openjdk8 - openjdk11 addons: apt: packages: - graphviz script: "mvn --show-version --errors --batch-mode -Prun-its clean verify" cache: directories: - $HOME/.m2 branches: except: - gh-pages notifications: email: - lennart.jorelid@gmail.comjaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/LICENSE.txt000066400000000000000000000261201351100213400223420ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2014 MOJO Codehaus Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/README.md000066400000000000000000000140331351100213400217760ustar00rootroot00000000000000# About the Jaxb2-Maven-Plugin [![Build Status](https://travis-ci.org/mojohaus/jaxb2-maven-plugin.svg?branch=master)](https://travis-ci.org/mojohaus/jaxb2-maven-plugin) This Maven plugin uses the Java API for XML Binding (JAXB), version 2+, to perform one of 2 main tasks: 1. Generate Java classes from XML Schemas (and optionally binding files). This is done by delegating work to the XJC tool, bundled with the Java SDK. Documentation for the XJC tool is found at two places - the [Unix Documentation](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/xjc.html) and the [Windows Documentation](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/xjc.html). 2. Create XML Schemas from annotated Java classes. This is done by delegating work to the Schemagen tool, bundled with the Java SDK. Documentation for the Schemagen tool is also found at two places - the [Unix Documentation](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/schemagen.html) and the [Windows Documentation](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/schemagen.html) ## [Plugin Documentation Hub](https://www.mojohaus.org/jaxb2-maven-plugin/) On Github, Maven site documentation is shown for the [5 latest releases of the JAXB2 plugin](https://www.mojohaus.org/jaxb2-maven-plugin/). The root URL for each static site is `http://www.mojohaus.org/jaxb2-maven-plugin/Documentation/v{theVersionNumber}/index.html` where `{theVersionNumber}` should be replaced with the actual version, such as `2.3.1`. However, [the documentation hub page](https://www.mojohaus.org/jaxb2-maven-plugin/) attempts to simplify access by presenting version number and link to the documentation for each listed release. # Release process for Jaxb2-Maven-Plugin Due to its documentation structure, the Jaxb2-Maven-Plugin has a slightly different release process - mainly due to the difference in publishing its Plugin Site Documentation. This is currently done in two steps. ## Publishing the Plugin artifacts to Maven Central This part of the release process is more-or-less identical to the standard Mojohaus release process - except that we do not automatically publish the plugin documentation. #### a. Preparing the binary artifact release Clone the repo and issue the standard maven release preparation, substituting the appropriate values for the release version and tag. Semantic versioning applies, so unless you know that the next upcoming version should contain only documentation changes, let the development version have its minor version number bumped by 1 (i.e. use `2.5.0` instead of `2.4.1` in the example below). Of course, since the snapshot/development stream may contain unexpected changes, the development version is merely an indication. mvn -DpushChanges=false -DreleaseVersion=2.4.0 -DdevelopmentVersion=2.5.0-SNAPSHOT -Dtag=jaxb2-maven-plugin-2.4.0 release:prepare If the release preparation build completed without errors, your local release repository should now contain two new commits with the commit message starting with `[maven-release-plugin]` on the form shown below. We have still not pushed anything to any source code or artifact repository. * b229a34 - Lennart Jörelid (20 seconds ago) (HEAD -> master) | [maven-release-plugin] prepare for next development iteration * 31f498f - Lennart Jörelid (20 seconds ago) (tag: jaxb2-maven-plugin-2.4.0) | [maven-release-plugin] prepare release jaxb2-maven-plugin-2.4.0 * b4499f9 - Lennart Jörelid (9 hours ago) (origin/master, origin/HEAD) | Using only JDK 8 since that is the defaults in travis. #### b. Perform normal deployment of the artifact Checkout the release tag on the master branch, rebuild and deploy to the OSS repository server. git checkout jaxb2-maven-plugin-2.4.0 mvn -Pmojo-release clean deploy The normal Mojohaus process for the binary release (send mail to group etc.) follows. When the release is approved by the community, build and publish the release documentation as described below. ## Publishing the Plugin Documentation to Github **Note** You must have `Graphviz` installed and within the path in order to be able to generate some of the release documentation images. Graphviz can be downloaded from its site, [http://graphviz.org](http://graphviz.org) #### a. Checkout the local release and build the release Documentation Checkout the newly prepared release and build its artifact and release documentation. Note that the system property `https.protocols` is required to generate the site, since GitHub's api refuses to use the default TLS version of java (i.e. TLSv1.0). git checkout jaxb2-maven-plugin-2.4.0 mvn -Dhttps.protocols="TLSv1,TLSv1.1,TLSv1.2" clean package site #### b. Copy the content of the `target/site` directory The release site documentation is now found within the target/site directory of the build. Copy the content of this directory to a temporary place, such as `/tmp`: cp -r target/site/* /tmp/ #### c. Move the plugin documentation to its gh-pages branch location Check out the `gh-pages` branch, and copy the documentation to a directory named `Documentation/v2.4.0` (substitute the version number with the release version). Simply build on the structure shown in the image below: ![Structure](src/site/resources/images/documentation_structure.png "Documentation Structure") #### d. Add the documentation to git, and push to publish Assuming that the repository id is `github`, add the static documentation pages to git, commit the addition using a standard message, and push: git add Documentation/v2.4.0 git commit -m "Added plugin documentation for version 2.4.0" git push github Following the push, verify that the newly released documentation site is available on github. Simply originate from the [Plugin Documentation Hub Page](https://www.mojohaus.org/jaxb2-maven-plugin/#/repo), which should look somewhat like the image below. ![Documentation Hub](src/site/resources/images/documentation_hub.png "Documentation Hub") jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/pom.xml000066400000000000000000000470461351100213400220460ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo mojo-parent 40 jaxb2-maven-plugin 2.5.0 maven-plugin JAXB-2 Maven Plugin Mojo's JAXB-2 Maven plugin is used to create an object graph from XSDs based on the JAXB 2.x implementation and to generate XSDs from JAXB annotated Java classes. https://github.com/mojohaus/jaxb2-maven-plugin/ 2005 The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo Lennart Jörelid lj@jguru.se Committer jGuru Europe AB http://www.jguru.se Europe/Stockholm jgenender Jeff Genender jgenender@codehaus.org Savoir Technologies, Inc http://www.savoirtech.com Committer -7 rfscholte Robert Scholte rfscholte@codehaus.org Committer Europe/Amsterdam ${mavenVersion} scm:git:https://github.com/mojohaus/jaxb2-maven-plugin.git scm:git:ssh://git@github.com/mojohaus/jaxb2-maven-plugin.git https://github.com/mojohaus/jaxb2-maven-plugin.git jaxb2-maven-plugin-2.5.0 GitHub https://github.com/mojohaus/jaxb2-maven-plugin/issues TravisCI https://travis-ci.org/mojohaus/jaxb2-maven-plugin 3.0.5 1.7 2.5 3.1.0 0.0.7 2.3.2 1.8.1 2.0-M10 7.1 2.6.3 3.5.1 0.9.3 org.ow2.asm asm ${asm.version} org.glassfish.jaxb jaxb-bom ${jaxb.version} pom import se.jguru.shared.algorithms.api jguru-shared-algorithms-api ${shared-algorithms.version} org.jvnet.staxex stax-ex ${stax-ex.version} javax.activation activation stax-api javax.xml.stream org.glassfish.jaxb jaxb-xjc org.glassfish.jaxb jaxb-jxc com.thoughtworks.qdox qdox ${qdox.version} org.apache.maven maven-plugin-api ${mavenVersion} org.apache.maven maven-core ${mavenVersion} org.apache.maven maven-artifact ${mavenVersion} org.apache.maven maven-model ${mavenVersion} org.apache.maven.plugin-tools maven-plugin-annotations ${maven-plugin-plugin.version} true org.apache.maven.skins maven-fluido-skin 1.6 org.codehaus.plexus plexus-compiler-api ${plexus-compiler-api.version} org.codehaus.plexus plexus-utils ${plexus-utils.version} org.sonatype.plexus plexus-build-api ${plexus-build-api.version} junit junit test org.xmlunit xmlunit-matchers ${xmlunit.version} test javax.xml.bind jaxb-api org.xmlunit xmlunit-legacy ${xmlunit.version} test se.jguru.shared.algorithms.api jguru-shared-algorithms-api test org.eclipse.ecf org.objectweb.asm 5.0.1.v201404251740 test ch.qos.logback logback-classic 1.1.7 test com.sun.istack istack-commons-runtime runtime org.apache.maven.plugins maven-site-plugin 3.7.1 true org.ow2.asm asm ${asm.version} org.apache.maven.plugins maven-plugin-plugin ${maven-plugin-plugin.version} true org.apache.maven.plugin-tools maven-plugin-annotations ${maven-plugin-plugin.version} help-mojo helpmojo org.apache.maven.plugins maven-plugin-plugin generate-descriptor descriptor org.apache.servicemix.tooling depends-maven-plugin 1.2 generate-depends-file generate-depends-file com.github.jeluard plantuml-maven-plugin 7954 ${basedir} src/site/**/*.puml ${project.build.directory}/site/images/plantuml generate-plantuml-diagrams generate pre-site net.sourceforge.plantuml plantuml 8017 org.apache.maven.plugins maven-plugin-plugin ${maven-plugin-plugin.version} ${mojo.java.target} run-its skipTests !true org.apache.maven.plugins maven-invoker-plugin 3.2.0 true ${project.build.directory}/it verify ${project.build.directory}/local-repo src/it/settings.xml clean test-compile integration-test install run org.xmlunit xmlunit-matchers ${xmlunit.version} org.xmlunit xmlunit-core ${xmlunit.version} jakarta.activation jakarta.activation-api 1.2.1 reporting skipReports !true org.apache.maven.plugins maven-checkstyle-plugin ${maven-checkstyle-plugin.version} true config/maven_checks.xml config/maven-header.txt jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/000077500000000000000000000000001351100213400213055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/000077500000000000000000000000001351100213400217215ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-14/000077500000000000000000000000001351100213400232445ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-14/pom.xml000066400000000000000000000060121351100213400245600ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-14 1.0-SNAPSHOT Purpose: Generate JAXB classes from a DTD. Show source and sourceType config options. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema dtd src/main/dtd true jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-14/src/000077500000000000000000000000001351100213400240335ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-14/src/main/000077500000000000000000000000001351100213400247575ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-14/src/main/dtd/000077500000000000000000000000001351100213400255325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-14/src/main/dtd/library.dtd000066400000000000000000000003411351100213400276710ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-14/verify.groovy000066400000000000000000000033241351100213400260210ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Verify the existence of some of the generated classes File objectFactory = new File( basedir,'target/generated-sources/jaxb/com/example/myschema/ObjectFactory.java' ) assert objectFactory.exists() File book = new File( basedir,'target/generated-sources/jaxb/com/example/myschema/Book.java' ) assert book.exists() File library = new File( basedir,'target/generated-sources/jaxb/com/example/myschema/Library.java' ) assert library.exists() File testSources = new File( basedir,'target/generated-test-sources/jaxb/' ) assert !testSources.exists() File objectFactoryCompiled = new File( basedir,'target/classes/com/example/myschema/ObjectFactory.class' ) assert objectFactoryCompiled.exists() File bookCompiled = new File( basedir,'target/classes/com/example/myschema/Book.class' ) assert bookCompiled.exists() File libraryCompiled = new File( basedir,'target/classes/com/example/myschema/Library.class' ) assert libraryCompiled.exists() jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-16/000077500000000000000000000000001351100213400232465ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-16/pom.xml000066400000000000000000000054671351100213400245770ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-16 1.0-SNAPSHOT Purpose: Validate target config parameter, and generated JAXB episode file. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema 2.0 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-16/src/000077500000000000000000000000001351100213400240355ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-16/src/main/000077500000000000000000000000001351100213400247615ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-16/src/main/xsd/000077500000000000000000000000001351100213400255575ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-16/src/main/xsd/address.xsd000066400000000000000000000010411351100213400277200ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-16/verify.groovy000066400000000000000000000065111351100213400260240ustar00rootroot00000000000000import java.util.regex.Pattern /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* +=================== [13 XJC Arguments] | | [0]: -xmlschema | [1]: -encoding | [2]: UTF-8 | [3]: -p | [4]: com.example.myschema | [5]: -target | [6]: 2.0 | [7]: -d | [8]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-16/target/generated-sources/jaxb | [9]: -extension | [10]: -episode | [11]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-16/target/generated-sources/jaxb/META-INF/sun-jaxb.episode | [12]: src/main/xsd/address.xsd | +=================== [End 13 XJC Arguments] */ File buildLog = new File(basedir, 'build.log') def logPattern = "\\| \\[\\p{Digit}+\\]: "; def sep = Pattern.quote(System.getProperty("file.separator")); Pattern expectedTargetPattern = Pattern.compile(logPattern + "\\-target"); Pattern expectedTargetVersionPattern = Pattern.compile(logPattern + "2.0"); Pattern expectedExtensionPattern = Pattern.compile(logPattern + "\\-extension"); Pattern expectedEpisodePattern = Pattern.compile(logPattern + "\\-episode"); Pattern expectedEpisodeFilePattern = Pattern.compile(logPattern + ".*target" + sep + "generated-sources" + sep + "jaxb" + sep + "META-INF" + sep + "JAXB" + sep + "episode_xjc\\.xjb"); boolean foundTarget = false; boolean foundTargetVersion = false; boolean foundExtension = false; boolean foundEpisode = false; boolean foundEpisodeFile = false; List lines = buildLog.readLines(); for (line in lines) { String trimmedLine = line.trim() if (trimmedLine.isEmpty()) { continue }; if(!foundTarget && expectedTargetPattern.matcher(trimmedLine).matches()) { foundTarget = true; } if(!foundTargetVersion && expectedTargetVersionPattern.matcher(trimmedLine).matches()) { foundTargetVersion = true; } if(!foundExtension && expectedExtensionPattern.matcher(trimmedLine).matches()) { foundExtension = true; } if(!foundEpisode && expectedEpisodePattern.matcher(trimmedLine).matches()) { foundEpisode = true; } if(!foundEpisodeFile && expectedEpisodeFilePattern.matcher(trimmedLine).matches()) { foundEpisodeFile = true; } } // Assert some def missingRequired(Pattern pattern) { return "Missing required pattern: [" + pattern.pattern() + "]" ; } assert foundTarget, missingRequired(expectedTargetPattern); assert foundTargetVersion, missingRequired(expectedTargetVersionPattern); assert foundExtension, missingRequired(expectedExtensionPattern); assert foundEpisode, missingRequired(expectedEpisodePattern); assert foundEpisodeFile, missingRequired(expectedEpisodeFilePattern); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17-warning/000077500000000000000000000000001351100213400247125ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17-warning/pom.xml000066400000000000000000000057321351100213400262360ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-17-warning 1.0-SNAPSHOT Purpose: Test of proper handling of folder with name ending with '.xsd' (not failing build as 'failOnNoSchemas' set to false). UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc false com.example.myschema xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17/000077500000000000000000000000001351100213400232475ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17/invoker.properties000066400000000000000000000000351351100213400270400ustar00rootroot00000000000000invoker.buildResult = failurejaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17/pom.xml000066400000000000000000000056071351100213400245740ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-17 1.0-SNAPSHOT Purpose: Test of proper handling of folder with name ending with '.xsd' (build failing due to no schemas found). UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17/src/000077500000000000000000000000001351100213400240365ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17/src/main/000077500000000000000000000000001351100213400247625ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17/src/main/xsd/000077500000000000000000000000001351100213400255605ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-17/src/main/xsd/noSchemasHere.txt000066400000000000000000000000461351100213400310450ustar00rootroot00000000000000This directory should contain no XSDs.jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/000077500000000000000000000000001351100213400232515ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/invoker.properties000066400000000000000000000000351351100213400270420ustar00rootroot00000000000000invoker.goals = clean compilejaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/pom.xml000066400000000000000000000066721351100213400246010ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-37 1.0-SNAPSHOT Purpose: Check if primitive Boolean is generated instead of the default Boolean object. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema xsd true jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/src/000077500000000000000000000000001351100213400240405ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/src/main/000077500000000000000000000000001351100213400247645ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/src/main/java/000077500000000000000000000000001351100213400257055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/src/main/java/foo/000077500000000000000000000000001351100213400264705ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/src/main/java/foo/bar/000077500000000000000000000000001351100213400272345ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/src/main/java/foo/bar/Main.java000066400000000000000000000005641351100213400307700ustar00rootroot00000000000000package foo.bar; import com.example.myschema.*; public class Main { public static void main( String args ) { ObjectFactory objectFactory = new ObjectFactory(); AddressType address = objectFactory.createAddressType(); boolean primary = address.isPrimary(); Boolean expensive = address.getExpensive(); } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/src/main/xsd/000077500000000000000000000000001351100213400255625ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/src/main/xsd/address.xsd000066400000000000000000000012701351100213400277270ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-37/verify.groovy000066400000000000000000000043061351100213400260270ustar00rootroot00000000000000/* target/it/mjaxb-37/target/classes/com/example/myschema/AddressType.class target/it/mjaxb-37/target/classes/com/example/myschema/ObjectFactory.class target/it/mjaxb-37/target/classes/foo/bar/Main.class target/it/mjaxb-37/target/classes/xsd/address.xsd target/it/mjaxb-37/target/generated-sources/jaxb/META-INF/sun-jaxb.episode target/it/mjaxb-37/target/generated-sources/jaxb/com/example/myschema/AddressType.java target/it/mjaxb-37/target/generated-sources/jaxb/com/example/myschema/ObjectFactory.java target/it/mjaxb-37/target/jaxb2/.xjc-xjcStaleFlag */ // Assemble File generatedSourcesDir = new File(basedir, "target/generated-sources") File classesDir = new File(basedir, "target/classes") File episodeFile = new File(classesDir, 'META-INF/JAXB/episode_xjc.xjb') File addressTypeSourceFile = new File(generatedSourcesDir, 'jaxb/com/example/myschema/AddressType.java') List addressTypeSource = addressTypeSourceFile.readLines(); String expectedPrimitiveBooleanLine = "protected boolean primary;"; String expectedBooleanClassLine = "protected Boolean expensive;"; String expectedBooleanClassAnnotationLine = "@XmlElement(required = true, type = Boolean.class, nillable = true)"; boolean primitiveBooleanPrimaryFound = false; boolean classBooleanExpensiveFound = false; boolean expensiveAnnotationLineFound = false; // Act for(line in addressTypeSource) { String trimmedLine = line.trim() if (trimmedLine.isEmpty()) { continue }; if(trimmedLine.equals(expectedPrimitiveBooleanLine)) { primitiveBooleanPrimaryFound = true; } if(trimmedLine.equals(expectedBooleanClassLine)) { classBooleanExpensiveFound = true; } if(trimmedLine.equals(expectedBooleanClassAnnotationLine)) { expensiveAnnotationLineFound = true; } } // Assert def missingRequired(String trimmedLine) { return "Missing required line: [" + trimmedLine + "]" ; } assert primitiveBooleanPrimaryFound, missingRequired(expectedPrimitiveBooleanLine); assert classBooleanExpensiveFound, missingRequired(expectedBooleanClassLine); assert expensiveAnnotationLineFound, missingRequired(expectedBooleanClassAnnotationLine); assert episodeFile.exists() && episodeFile.isFile(), "Episode file [" + episodeFile.getPath() + "] not found"jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/000077500000000000000000000000001351100213400264335ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/pom.xml000066400000000000000000000126101351100213400277500ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-55-partialdefaults 1.0-SNAPSHOT Validate schema namepace prefix and output filename using partial default settings. UTF-8 se.jguru.nazgul.test.xmlbinding nazgul-core-xmlbinding-test 2.1.0 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen XmlNormalizer\.java \.properties \.xjb false http://some/namespace some some_schema.xsd http://another/namespace another http://yet/another/namespace yet_another_schema.xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/000077500000000000000000000000001351100213400272225ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/000077500000000000000000000000001351100213400301465ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/java/000077500000000000000000000000001351100213400310675ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/java/se/000077500000000000000000000000001351100213400314765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/java/se/west/000077500000000000000000000000001351100213400324605ustar00rootroot00000000000000schema/000077500000000000000000000000001351100213400336415ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/java/se/westFooBar.java000066400000000000000000000021501351100213400356520ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/java/se/west/schemapackage se.west.schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * @author Lennart Jörelid */ @XmlType(namespace = Namespaces.SOME_NAMESPACE, propOrder = {"requiredElement", "aRequiredElementInAnotherNamespace", "optionalElement", "requiredAttribute", "optionalAttribute"}) @XmlAccessorType(XmlAccessType.FIELD) public class FooBar { @XmlElement(required = true, defaultValue = "requiredElementValue") private String requiredElement; @XmlElement(namespace = Namespaces.ANOTHER_NAMESPACE, required = true, defaultValue = "requiredElementValue") private String aRequiredElementInAnotherNamespace; @XmlElement(required = false) private String optionalElement; @XmlAttribute(required = true) private String requiredAttribute; @XmlAttribute(required = false) private String optionalAttribute; } FooBaz.java000066400000000000000000000022761351100213400356730ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/java/se/west/schemapackage se.west.schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * @author Lennart Jörelid */ @XmlType(namespace = Namespaces.ANOTHER_NAMESPACE, propOrder = {"requiredElement", "anOptionalElementInSomeNamespace", "aRequiredElementInYetAnotherNamespace", "requiredAttribute", "optionalAttribute"}) @XmlAccessorType(XmlAccessType.FIELD) public class FooBaz { @XmlElement(required = true, defaultValue = "requiredElementValue") private String requiredElement; @XmlElement(namespace = Namespaces.YET_ANOTHER_NAMESPACE, required = true, defaultValue = "requiredElementValue") private String aRequiredElementInYetAnotherNamespace; @XmlElement(namespace = Namespaces.SOME_NAMESPACE, required = false) private String anOptionalElementInSomeNamespace; @XmlAttribute(required = true) private String requiredAttribute; @XmlAttribute(required = false) private String optionalAttribute; } Namespaces.java000066400000000000000000000005751351100213400365720ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/java/se/west/schemapackage se.west.schema; /** * @author Lennart Jörelid */ public interface Namespaces { public static final String SOME_NAMESPACE = "http://some/namespace"; public static final String ANOTHER_NAMESPACE = "http://another/namespace"; public static final String YET_ANOTHER_NAMESPACE = "http://yet/another/namespace"; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/resources/000077500000000000000000000000001351100213400321605ustar00rootroot00000000000000expected/000077500000000000000000000000001351100213400337025ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/resourcesschema3.xsd000066400000000000000000000020231351100213400357420ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/resources/expected some_schema.xsd000066400000000000000000000016021351100213400367040ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/resources/expected yet_another_schema.xsd000066400000000000000000000004111351100213400402570ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/src/main/resources/expected jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55-partialdefaults/verify.groovy000066400000000000000000000054341351100213400312140ustar00rootroot00000000000000import org.xmlunit.builder.DiffBuilder import org.xmlunit.builder.Input import org.xmlunit.diff.Diff import javax.xml.transform.Source String generatedPath = "target/generated-resources/schemagen/"; String[] beforeMoveFilenames = ["schema1.xsd", "schema2.xsd", "schema3.xsd"] String[] afterMoveFilenames = ["some_schema.xsd", "yet_another_schema.xsd", "schema3.xsd"] for (int i = 0; i < beforeMoveFilenames.length; i++) { // Check that the files were actually renamed as per the configuration within the pom. File beforeMove = new File(basedir, generatedPath + beforeMoveFilenames[i]); File afterMove = new File(basedir, generatedPath + afterMoveFilenames[i]); if(beforeMove.absolutePath != afterMove.absolutePath) { if (beforeMove.exists()) { println("Rename failed. [" + beforeMove.getAbsolutePath() + "] exists."); return false; } if (!afterMove.exists() || afterMove.length() == 0) { println("Rename failed. [" + afterMove.getAbsolutePath() + "] does not exist."); return false; } println("Successful rename of [" + beforeMove.getName() + "] to [" + afterMove.getName() + "]"); } else { println("Success: Not renaming file [" + beforeMove.getName() + "] as expected."); } } // Validate the content of the generated schema files String expectedPath = "target/classes/expected/"; boolean allTransformationsAreCorrect = true; for (int i = 0; i < afterMoveFilenames.length; i++) { // Read the file content. File expected = new File(basedir, expectedPath + afterMoveFilenames[i]); File actual = new File(basedir, generatedPath + afterMoveFilenames[i]); // Normalize the XML Source expectedXML = Input.fromFile(expected).build() Source actualXML = Input.fromFile(actual).build() // Check contents. Diff anyDiffs = DiffBuilder.compare(expectedXML) .withTest(actualXML) .ignoreComments() .ignoreWhitespace() .build() if (!anyDiffs.hasDifferences()) { println("[Correct Transform]: [" + (i + 1) + "/" + afterMoveFilenames.length + "] for XML Schema file " + expected.getName()); } else { println("Found differences: " + anyDiffs.toString()) println("[Failed Transform]: [" + (i + 1) + "/" + afterMoveFilenames.length + "] for XML Schema file " + actual.getName()); println("[Failed Transform]: [" + (i + 1) + "/" + afterMoveFilenames.length + "] Actual: [" + actual.getPath() + "]"); println("[Failed Transform]: [" + (i + 1) + "/" + afterMoveFilenames.length + "] Expected: [" + expected.getPath() + "]"); // Mismatch. allTransformationsAreCorrect = false; } } return allTransformationsAreCorrect;jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/000077500000000000000000000000001351100213400232515ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/pom.xml000066400000000000000000000124101351100213400245640ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-55 1.0-SNAPSHOT Validate schema namepace prefix and output filename. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen XmlNormalizer\.java \.properties \.xjb false http://some/namespace some some_schema.xsd http://another/namespace another another_schema.xsd http://yet/another/namespace yetAnother yet_another_schema.xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/000077500000000000000000000000001351100213400240405ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/000077500000000000000000000000001351100213400247645ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/java/000077500000000000000000000000001351100213400257055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/java/se/000077500000000000000000000000001351100213400263145ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/java/se/west/000077500000000000000000000000001351100213400272765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/java/se/west/schema/000077500000000000000000000000001351100213400305365ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/java/se/west/schema/FooBar.java000066400000000000000000000021501351100213400325470ustar00rootroot00000000000000package se.west.schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * @author Lennart Jörelid */ @XmlType(namespace = Namespaces.SOME_NAMESPACE, propOrder = {"requiredElement", "aRequiredElementInAnotherNamespace", "optionalElement", "requiredAttribute", "optionalAttribute"}) @XmlAccessorType(XmlAccessType.FIELD) public class FooBar { @XmlElement(required = true, defaultValue = "requiredElementValue") private String requiredElement; @XmlElement(namespace = Namespaces.ANOTHER_NAMESPACE, required = true, defaultValue = "requiredElementValue") private String aRequiredElementInAnotherNamespace; @XmlElement(required = false) private String optionalElement; @XmlAttribute(required = true) private String requiredAttribute; @XmlAttribute(required = false) private String optionalAttribute; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/java/se/west/schema/FooBaz.java000066400000000000000000000022761351100213400325700ustar00rootroot00000000000000package se.west.schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * @author Lennart Jörelid */ @XmlType(namespace = Namespaces.ANOTHER_NAMESPACE, propOrder = {"requiredElement", "anOptionalElementInSomeNamespace", "aRequiredElementInYetAnotherNamespace", "requiredAttribute", "optionalAttribute"}) @XmlAccessorType(XmlAccessType.FIELD) public class FooBaz { @XmlElement(required = true, defaultValue = "requiredElementValue") private String requiredElement; @XmlElement(namespace = Namespaces.YET_ANOTHER_NAMESPACE, required = true, defaultValue = "requiredElementValue") private String aRequiredElementInYetAnotherNamespace; @XmlElement(namespace = Namespaces.SOME_NAMESPACE, required = false) private String anOptionalElementInSomeNamespace; @XmlAttribute(required = true) private String requiredAttribute; @XmlAttribute(required = false) private String optionalAttribute; } Namespaces.java000066400000000000000000000005751351100213400334100ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/java/se/west/schemapackage se.west.schema; /** * @author Lennart Jörelid */ public interface Namespaces { public static final String SOME_NAMESPACE = "http://some/namespace"; public static final String ANOTHER_NAMESPACE = "http://another/namespace"; public static final String YET_ANOTHER_NAMESPACE = "http://yet/another/namespace"; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/resources/000077500000000000000000000000001351100213400267765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/resources/expected/000077500000000000000000000000001351100213400305775ustar00rootroot00000000000000another_schema.xsd000066400000000000000000000020321351100213400342150ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/resources/expected some_schema.xsd000066400000000000000000000016111351100213400335220ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/resources/expected yet_another_schema.xsd000066400000000000000000000004111351100213400350750ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/src/main/resources/expected jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-55/verify.groovy000066400000000000000000000052201351100213400260230ustar00rootroot00000000000000import org.xmlunit.builder.DiffBuilder import org.xmlunit.builder.Input import org.xmlunit.diff.Diff import javax.xml.transform.Source String generatedPath = "target/generated-resources/schemagen/"; String[] beforeMoveFilenames = ["schema1.xsd", "schema2.xsd", "schema3.xsd"] String[] afterMoveFilenames = ["some_schema.xsd", "another_schema.xsd", "yet_another_schema.xsd"] for (int i = 0; i < beforeMoveFilenames.length; i++) { // Check that the files were actually renamed as per the configuration within the pom. File beforeMove = new File(basedir, generatedPath + beforeMoveFilenames[i]); File afterMove = new File(basedir, generatedPath + afterMoveFilenames[i]); if (beforeMove.exists()) { println("Rename failed. [" + beforeMove.getAbsolutePath() + "] exists."); return false; } if (!afterMove.exists() || afterMove.length() == 0) { println("Rename failed. [" + afterMove.getAbsolutePath() + "] does not exist."); return false; } println("Successful rename of [" + beforeMove.getName() + "] to [" + afterMove.getName() + "]"); } // Configure XMLUnit // XMLUnit.setIgnoreWhitespace(true); // Validate the content of the generated schema files String expectedPath = "target/classes/expected/"; boolean allTransformationsAreCorrect = true; for (int i = 0; i < afterMoveFilenames.length; i++) { // Read the file content. File expected = new File(basedir, expectedPath + afterMoveFilenames[i]); File actual = new File(basedir, generatedPath + afterMoveFilenames[i]); // Normalize the XML Source expectedXML = Input.fromFile(expected).build() Source actualXML = Input.fromFile(actual).build() // Check contents. Diff anyDiffs = DiffBuilder.compare(expectedXML) .withTest(actualXML) .ignoreComments() .ignoreWhitespace() .build() if (!anyDiffs.hasDifferences()) { println("[Correct Transform]: [" + (i + 1) + "/" + afterMoveFilenames.length + "] for XML Schema file " + expected.getName()); } else { println("Found differences: " + anyDiffs.toString()) println("[Failed Transform]: [" + (i + 1) + "/" + afterMoveFilenames.length + "] for XML Schema file " + actual.getName()); println("[Failed Transform]: [" + (i + 1) + "/" + afterMoveFilenames.length + "] Actual: [" + actual.getPath() + "]"); println("[Failed Transform]: [" + (i + 1) + "/" + afterMoveFilenames.length + "] Expected: [" + expected.getPath() + "]"); // Mismatch. allTransformationsAreCorrect = false; } } return allTransformationsAreCorrect;jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/000077500000000000000000000000001351100213400232555ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/000077500000000000000000000000001351100213400246235ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/pom.xml000066400000000000000000000027521351100213400261460ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-59 1.0-SNAPSHOT mjaxb-59-module1 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/src/000077500000000000000000000000001351100213400254125ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/src/main/000077500000000000000000000000001351100213400263365ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/src/main/java/000077500000000000000000000000001351100213400272575ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/src/main/java/se/000077500000000000000000000000001351100213400276665ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/src/main/java/se/west/000077500000000000000000000000001351100213400306505ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/src/main/java/se/west/gnat/000077500000000000000000000000001351100213400316015ustar00rootroot00000000000000Foo.java000066400000000000000000000003441351100213400331110ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/module1/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/pom.xml000066400000000000000000000060051351100213400245730ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-59 1.0-SNAPSHOT pom Purpose: Test of performing a SchemaGeneration within a multi-module reactor project (i.e. validation of plugin configuration inheritance, despite that SchemaGen requires its path parameters to be based on the System.property "user.dir", rather than Maven's "basedir"). UTF-8 module1 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen org.codehaus.mojo jaxb2-maven-plugin jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-59/verify.groovy000066400000000000000000000057111351100213400260340ustar00rootroot00000000000000import java.util.regex.Pattern /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble File buildLog = new File(basedir, 'build.log'); List lines = buildLog.readLines(); /* +=================== [Filtered sources] | | 6 Exclude patterns: | [1/6]: (\p{javaLetterOrDigit}|\p{Punct})+README.* | [2/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.xml | [3/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.txt | [4/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.xjb | [5/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.xsd | [6/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.properties | | 1 Sources: | [1/1]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-59/module1/src/main/java | | 1 Results: | [1/1]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-59/module1/src/main/java/se/west/gnat/Foo.java | +=================== [End Filtered sources] ... +=================== [9 SchemaGen Arguments] | | [0]: -encoding | [1]: UTF-8 | [2]: -d | [3]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-59/module1/target/generated-resources/schemagen | [4]: -classpath | [5]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-59/module1/src/main/java/ | [6]: -episode | [7]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-59/module1/target/generated-resources/schemagen/META-INF/sun-jaxb.episode | [8]: module1/src/main/java/se/west/gnat/Foo.java | +=================== [End 9 SchemaGen Arguments] */ def xjcArgumentPatternPrefix = "\\| \\[\\p{Digit}+\\]: "; def sep = Pattern.quote(System.getProperty("file.separator")); final Pattern expectedSourcePattern = Pattern.compile(xjcArgumentPatternPrefix + ("module1/src/main/java/se/west/gnat/Foo.java").replace("/", sep)); boolean foundSourceArgument = false; // Act for (line in lines) { String trimmedLine = line.trim() if (trimmedLine.isEmpty()) { continue }; if(!foundSourceArgument && expectedSourcePattern.matcher(trimmedLine).matches()) { foundSourceArgument = true; } } // Assert static def missingRequired(Pattern pattern) { return "Missing required pattern: [" + pattern.pattern() + "]" ; } assert foundSourceArgument, missingRequired(expectedSourcePattern); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/000077500000000000000000000000001351100213400232515ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/pom.xml000066400000000000000000000066561351100213400246030ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-64 1.0-SNAPSHOT Purpose: Test for bug reported in MJAXB-64 (Combinations of name attributes for XmlTypes and XmlRootElement). UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen false http://acme.com/customer-api customer customer-api.xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/src/000077500000000000000000000000001351100213400240405ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/src/main/000077500000000000000000000000001351100213400247645ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/src/main/java/000077500000000000000000000000001351100213400257055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/src/main/java/se/000077500000000000000000000000001351100213400263145ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/src/main/java/se/west/000077500000000000000000000000001351100213400272765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/src/main/java/se/west/shauqra/000077500000000000000000000000001351100213400307425ustar00rootroot00000000000000FooWithEmptyXmlTypeName.java000066400000000000000000000017271351100213400362570ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/src/main/java/se/west/shauqrapackage se.west.shauqra; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "customerForNamelessFoo", namespace = "http://acme.com/customer-api") @XmlType(name = "", namespace = "http://acme.com/customer-api") @XmlAccessorType(XmlAccessType.FIELD) public class FooWithEmptyXmlTypeName { @XmlElement(required = true, defaultValue = "defaultName") private String name; @XmlElement(required = true, namespace = "http://acme.com/customer-api") private String anotherName; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAnotherName() { return anotherName; } public void setAnotherName(String name) { this.anotherName = name; } } FooWithSuppliedXmlTypeName.java000066400000000000000000000017351351100213400367450ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/src/main/java/se/west/shauqrapackage se.west.shauqra; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "customerForSomeFoo", namespace = "http://acme.com/customer-api") @XmlType(name = "someFoo", namespace = "http://acme.com/customer-api") @XmlAccessorType(XmlAccessType.FIELD) public class FooWithSuppliedXmlTypeName { @XmlElement(required = true, defaultValue = "defaultName") private String name; @XmlElement(required = true, namespace = "http://acme.com/customer-api") private String anotherName; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAnotherName() { return anotherName; } public void setAnotherName(String name) { this.anotherName = name; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-64/verify.groovy000066400000000000000000000120051351100213400260220ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* +=================== [10 SchemaGen Arguments] | | [0]: -encoding | [1]: UTF-8 | [2]: -d | [3]: /Users/lj/Development/Projects/Mojohaus/jaxb2-maven-plugin/target/it/mjaxb-64/target/schemagen-work/compile_scope | [4]: -classpath | [5]: /Users/lj/Development/Projects/Mojohaus/jaxb2-maven-plugin/target/it/mjaxb-64/src/main/java/ | [6]: -episode | [7]: /Users/lj/Development/Projects/Mojohaus/jaxb2-maven-plugin/target/it/mjaxb-64/target/classes/META-INF/sun-jaxb.episode | [8]: src/main/java/se/west/shauqra/FooWithEmptyXmlTypeName.java | [9]: src/main/java/se/west/shauqra/FooWithSuppliedXmlTypeName.java | +=================== [End 10 SchemaGen Arguments] */ // Assemble def expectedXmlForm = ''' ''' final File classesDir = new File(basedir, 'target/classes') final File generatedSchemaDir = new File(basedir, 'target/generated-resources/schemagen'); final File vanillaSchema = new File(basedir, 'target/schemagen-work/compile_scope/schema1.xsd'); final File processedSchema = new File(generatedSchemaDir, 'customer-api.xsd'); final File generatedEpisode = new File(classesDir, 'META-INF/JAXB/episode_schemagen.xjb'); assert processedSchema.exists(), "Expected file [" + processedSchema.getAbsolutePath() + "] not found." assert generatedEpisode.exists(), "Expected file [" + generatedEpisode.getAbsolutePath() + "] not found." assert vanillaSchema.exists(), "Expected file [" + vanillaSchema.getAbsolutePath() + "] not found." // Act def schemaElement = new XmlSlurper().parse(processedSchema) // Assert println "\nValidating namespace changes" println "===================================" def expectedTargetNS = 'http://acme.com/customer-api'; assert ("" + schemaElement.@targetNamespace) == expectedTargetNS, "Incorrect target namespace " + schemaElement.@targetNamespace + ". Expected " + expectedTargetNS + "."; println "1. Correct target namespace: " + expectedTargetNS; println "\nValidating schema content" println "===================================" def namelessFooRootElements = schemaElement.element.findAll { it.@name == "customerForNamelessFoo" } def someFooRootElements = schemaElement.element.findAll { it.@name == "customerForSomeFoo" } def someFooComplexTypes = schemaElement.complexType.findAll { it.@name == "someFoo" } assert 1 == namelessFooRootElements.size(), "Got ${namelessFooRootElements.size} namelessFoo root elements. Expected 1."; println "1. Got correct size for namelessFooRootElements." assert 1 == namelessFooRootElements[0].children().size(), "Expected 1 child, but got ${namelessFooRootElements[0].children().size()}."; println "2. Got correct size for namelessFooRootElements children." assert "${namelessFooRootElements[0].complexType.@name}" == "", "Got unexpected name for namelessFoo complex type."; println "3. Got correct name (none) for namelessFooRootElements complexType child." assert 1 == someFooRootElements.size(), "Got ${someFooRootElements.size} someFooRootElements. Expected 1."; println "4. Got correct size for someFooRootElements." assert "${someFooRootElements[0].@type}" == 'customer:someFoo', "Got unexpected ComplexType type ${someFooRootElements[0].@type} for element " + "${someFooRootElements[0].@name} Expected 'customer:someFoo'."; println "5. Got correct ComplexType type 'customer:someFoo'." assert 1 == someFooComplexTypes.size(), "Got ${someFooComplexTypes.size} someFooComplexTypes. Expected 1."; println "6. Got correct size for someFooComplexTypes."jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/000077500000000000000000000000001351100213400232475ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/pom.xml000066400000000000000000000106331351100213400245670ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-71 1.0-SNAPSHOT Purpose: Validate that the schemagen mojo ... a) ... does not fail with a non-existent source directory. b) ... compiles all sources found within any of the compile source directories. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen http://acme.com/customer-api customer customer-api.xsd org.codehaus.mojo build-helper-maven-plugin 1.9.1 add-nonexisting-source add-source generate-sources src/main/nonexistent src/main/fooBarSource jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/src/000077500000000000000000000000001351100213400240365ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/src/main/000077500000000000000000000000001351100213400247625ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/src/main/fooBarSource/000077500000000000000000000000001351100213400273535ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/src/main/fooBarSource/se/000077500000000000000000000000001351100213400277625ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/src/main/fooBarSource/se/west/000077500000000000000000000000001351100213400307445ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/src/main/fooBarSource/se/west/shauqra/000077500000000000000000000000001351100213400324105ustar00rootroot00000000000000FooWithEmptyXmlTypeName.java000066400000000000000000000020071351100213400377150ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/src/main/fooBarSource/se/west/shauqrapackage se.west.shauqra; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "customerForNamelessFoo", namespace = "http://acme.com/customer-api") @XmlType(name = "", namespace = "http://acme.com/customer-api") @XmlAccessorType(XmlAccessType.FIELD) public class FooWithEmptyXmlTypeName { @XmlElement(required = true, defaultValue = "defaultName") private String name; /** * JavaDoc for anotherName. */ @XmlElement(required = true, namespace = "http://acme.com/customer-api") private String anotherName; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAnotherName() { return anotherName; } public void setAnotherName(String name) { this.anotherName = name; } } FooWithSuppliedXmlTypeName.java000066400000000000000000000017351351100213400404130ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/src/main/fooBarSource/se/west/shauqrapackage se.west.shauqra; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "customerForSomeFoo", namespace = "http://acme.com/customer-api") @XmlType(name = "someFoo", namespace = "http://acme.com/customer-api") @XmlAccessorType(XmlAccessType.FIELD) public class FooWithSuppliedXmlTypeName { @XmlElement(required = true, defaultValue = "defaultName") private String name; @XmlElement(required = true, namespace = "http://acme.com/customer-api") private String anotherName; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAnotherName() { return anotherName; } public void setAnotherName(String name) { this.anotherName = name; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-71/verify.groovy000066400000000000000000000135771351100213400260370ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* +=================== [10 SchemaGen Arguments] | | [0]: -encoding | [1]: UTF-8 | [2]: -d | [3]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-71/target/generated-resources/schemagen | [4]: -classpath | [5]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-71/src/main/fooBarSource/ | [6]: -episode | [7]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/mjaxb-71/target/generated-resources/schemagen/META-INF/sun-jaxb.episode | [8]: src/main/fooBarSource/se/west/shauqra/FooWithEmptyXmlTypeName.java | [9]: src/main/fooBarSource/se/west/shauqra/FooWithSuppliedXmlTypeName.java | +=================== [End 10 SchemaGen Arguments] */ // Assemble def expectedXmlForm = ''' ''' def slashify(String path) { return path.replace("/", System.getProperty("file.separator")); } def ignoredPrefix = "[INFO] Ignored given or default sources ["; def ignoredSuffix = slashify("target/it/mjaxb-71/src/main/nonexistent], " + "since it is not an existent file or directory."); def generatedSchemaDir = new File(basedir, 'target/generated-resources/schemagen'); def vanillaSchema = new File(generatedSchemaDir, 'schema1.xsd'); def processedSchema = new File(generatedSchemaDir, 'customer-api.xsd'); def generatedEpisode = new File(basedir, 'target/classes/META-INF/JAXB/episode_schemagen.xjb'); def buildLog = new File(basedir, 'build.log'); final List lines = buildLog.readLines(); assert processedSchema.exists(), "Expected file [" + processedSchema.getAbsolutePath() + "] not found." assert generatedEpisode.exists(), "Expected file [" + generatedEpisode.getAbsolutePath() + "] not found." assert !vanillaSchema.exists(), "Found unexpected file [" + vanillaSchema.getAbsolutePath() + "]." // Act def schemaElement = new XmlSlurper().parse(processedSchema) boolean foundIgnoreLine = false; for (line in lines) { String trimmedLine = line.trim() if (trimmedLine.isEmpty()) { continue }; if (trimmedLine.contains(ignoredPrefix) && trimmedLine.contains(ignoredSuffix)) { foundIgnoreLine = true; } } // Assert println "\nValidating accepted build root directories" println "===================================" assert foundIgnoreLine, "Could not locate build statement about ignoring nonexistent source directory." println "1. Found correct build statement about ignoring nonexistent source directory." println "\nValidating namespace changes" println "===================================" def expectedTargetNS = 'http://acme.com/customer-api'; assert "${schemaElement.@targetNamespace}" == expectedTargetNS, "Incorrect target namespace ${schemaElement.@targetNamespace}. Expected " + expectedTargetNS + "."; println "1. Correct target namespace: " + expectedTargetNS; println "\nValidating schema content" println "===================================" def namelessFooRootElements = schemaElement.element.findAll { it.@name == "customerForNamelessFoo" } def someFooRootElements = schemaElement.element.findAll { it.@name == "customerForSomeFoo" } def someFooComplexTypes = schemaElement.complexType.findAll { it.@name == "someFoo" } assert 1 == namelessFooRootElements.size(), "Got ${namelessFooRootElements.size} namelessFoo root elements. Expected 1."; println "1. Got correct size for namelessFooRootElements." assert 1 == namelessFooRootElements[0].children().size(), "Expected 1 child, but got ${namelessFooRootElements[0].children().size()}."; println "2. Got correct size for namelessFooRootElements children." assert "${namelessFooRootElements[0].complexType.@name}" == "", "Got unexpected name for namelessFoo complex type."; println "3. Got correct name (none) for namelessFooRootElements complexType child." assert 1 == someFooRootElements.size(), "Got ${someFooRootElements.size} someFooRootElements. Expected 1."; println "4. Got correct size for someFooRootElements." assert "${someFooRootElements[0].@type}" == 'customer:someFoo', "Got unexpected ComplexType type ${someFooRootElements[0].@type} for element " + "${someFooRootElements[0].@name} Expected 'customer:someFoo'."; println "5. Got correct ComplexType type 'customer:someFoo'." assert 1 == someFooComplexTypes.size(), "Got ${someFooComplexTypes.size} someFooComplexTypes. Expected 1."; println "6. Got correct size for someFooComplexTypes."jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/000077500000000000000000000000001351100213400232475ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/pom.xml000066400000000000000000000065701351100213400245740ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-80 1.0-SNAPSHOT Purpose: Test of issue MJAXB-80 (namespace prefix problem in NodeProcessor algorithm). UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb\.index false http://schema.domain.org/integration/1.0 smoothIntegration smooth.xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/000077500000000000000000000000001351100213400240365ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/000077500000000000000000000000001351100213400247625ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/000077500000000000000000000000001351100213400257035ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/org/000077500000000000000000000000001351100213400264725ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/org/domain/000077500000000000000000000000001351100213400277415ustar00rootroot00000000000000ImportItemDTO.java000066400000000000000000000012521351100213400331650ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/org/domainpackage org.domain; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(namespace = "http://schema.domain.org/integration/1.0", name = "importItem") @XmlSeeAlso({ SomeImportItemDTO.class, SomeOtherImportItemDTO.class }) public abstract class ImportItemDTO { @XmlAttribute private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } ImportItemsDTO.java000066400000000000000000000017551351100213400333600ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/org/domainpackage org.domain; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.util.ArrayList; import java.util.List; @XmlType(namespace = "http://schema.domain.org/integration/1.0", name = "importItems", propOrder = {"someImportItems", "someOtherImportItems"}) @XmlRootElement(namespace = "http://schema.domain.org/integration/1.0", name = "importItems") public class ImportItemsDTO { @XmlElementRef private List someImportItems = new ArrayList(); public List getSomeImportItems() { return someImportItems; } @XmlElementRef private List someOtherImportItems = new ArrayList(); public List getSomeOtherImportItems() { return someOtherImportItems; } } SomeImportItemDTO.java000066400000000000000000000015611351100213400340140ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/org/domainpackage org.domain; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(namespace = "http://schema.domain.org/integration/1.0", name = "someImportItem", propOrder = {"someIdentifier"}) @XmlRootElement(namespace = "http://schema.domain.org/integration/1.0", name = "someImportItem") public class SomeImportItemDTO extends ImportItemDTO { @XmlElement(name = "someIdentifier", required = true) private String someIdentifier; public String getSomeIdentifier() { return someIdentifier; } public void setSomeIdentifier(String id) { this.someIdentifier = id; } } SomeOtherImportItemDTO.java000066400000000000000000000016311351100213400350140ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/org/domainpackage org.domain; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(namespace = "http://schema.domain.org/integration/1.0", name = "someOtherImportItem", propOrder = {"someWeirdIdentifier"}) @XmlRootElement(namespace = "http://schema.domain.org/integration/1.0", name = "someOtherImportItem") public class SomeOtherImportItemDTO extends ImportItemDTO { @XmlElement(name = "someWeirdIdentifier", required = true) private String someWeirdIdentifier; public String getSomeIdentifier() { return someWeirdIdentifier; } public void setSomeIdentifier(String id) { this.someWeirdIdentifier = id; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/org/domain/jaxb.index000066400000000000000000000001101351100213400317060ustar00rootroot00000000000000ImportItemsDTO ImportItemDTO SomeImportItemDTO SomeOtherImportItemDTOpackage-info.java000066400000000000000000000005731351100213400330560ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/src/main/java/org/domain@XmlSchema(xmlns = { @XmlNs(prefix = "smoothIntegration", namespaceURI = "http://schema.domain.org/integration/1.0")}) @XmlAccessorType(XmlAccessType.FIELD) package org.domain; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlNs; import javax.xml.bind.annotation.XmlSchema; jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-80/verify.groovy000066400000000000000000000106411351100213400260240ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ def expectedSchemaPath = 'target/generated-resources/schemagen/smooth.xsd' File schema = new File( basedir, expectedSchemaPath) println "\nValidating that schema exists at expected path \"" + expectedSchemaPath + "\"" assert schema.exists() // Validate content as reported in issue MJAXB-80 def xml = new XmlSlurper().parse(schema) // 1) Validate the required Element tags /* */ println "\nElement namespace change validation" println "===================================" def importItemsElement = xml.element.findAll{ it.@name.text().equals('importItems') } def someImportItemElement = xml.element.findAll{ it.@name.text().equals('someImportItem') } def someOtherImportItemElement = xml.element.findAll{ it.@name.text().equals('someOtherImportItem') } assert 'smoothIntegration:importItems' == importItemsElement.@type.text() println "Namespace change in element 'importItems': OK" assert 'smoothIntegration:someImportItem' == someImportItemElement.@type.text() println "Namespace change in element 'someImportItem': OK" assert 'smoothIntegration:someOtherImportItem' == someOtherImportItemElement.@type.text() println "Namespace change in element 'someOtherImportItem': OK" // 2) Validate the complex types /* */ println "\nSequence ref namespace change validation" println "========================================" def importItemsType = xml.complexType.findAll{ it.@name.text().equals('importItems') } assert 'smoothIntegration:someImportItem' == importItemsType[0].sequence[0].element[0].@ref.text() println "Namespace change in sequence ref 'someImportItem': OK" assert 'smoothIntegration:someOtherImportItem' == importItemsType[0].sequence[0].element[1].@ref.text() println "Namespace change in sequence ref 'someOtherImportItem': OK" println "\nExtension base namespace change validation" println "==========================================" def someImportItemType = xml.complexType.findAll{ it.@name.text().equals('someImportItem') } assert 'smoothIntegration:importItem' == someImportItemType[0].complexContent.extension.@base.text() println "Namespace change in sequence ref 'someImportItem': OK" def someOtherImportItemType = xml.complexType.findAll{ it.@name.text().equals('someOtherImportItem') } assert 'smoothIntegration:importItem' == someOtherImportItemType[0].complexContent.extension.@base.text() println "Namespace change in sequence ref 'someOtherImportItem': OK" println "\nValidation script done."jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/000077500000000000000000000000001351100213400232505ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/pom.xml000066400000000000000000000062721351100213400245740ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-81 1.0-SNAPSHOT Purpose: Test of issue MJAXB-81 (transformSchema should also replace prefix in "type" attribute). UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen http://www.someuri som some.xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/src/000077500000000000000000000000001351100213400240375ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/src/main/000077500000000000000000000000001351100213400247635ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/src/main/java/000077500000000000000000000000001351100213400257045ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/src/main/java/org/000077500000000000000000000000001351100213400264735ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/src/main/java/org/acme/000077500000000000000000000000001351100213400274005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/src/main/java/org/acme/FooBar.java000066400000000000000000000006041351100213400314130ustar00rootroot00000000000000package org.acme; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlType( name = "BarType", namespace="##default" ) @XmlAccessorType( XmlAccessType.FIELD ) public class FooBar { @XmlElement( required = false ) private FooBaz bazElement; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/src/main/java/org/acme/FooBaz.java000066400000000000000000000011441351100213400314230ustar00rootroot00000000000000package org.acme; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlType( name = "BazType", namespace = "##default", propOrder = { "requiredElement", "requiredAttribute" } ) @XmlAccessorType( XmlAccessType.FIELD ) public class FooBaz { @XmlElement( required = true, defaultValue = "requiredElementValue" ) private String requiredElement; @XmlAttribute( required = true ) private String requiredAttribute; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/src/main/java/org/acme/package-info.java000066400000000000000000000002351351100213400325670ustar00rootroot00000000000000@javax.xml.bind.annotation.XmlSchema( elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, namespace="http://www.someuri" ) package org.acme; jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/mjaxb-81/verify.groovy000066400000000000000000000022021351100213400260170ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ File schema = new File( basedir,'target/generated-resources/schemagen/some.xsd' ) assert schema.exists() // Validate content as reported in issue MJAXB-81 def xml = new XmlSlurper(true, true).parse(schema) def baz = xml.complexType.findAll{ it.@name.text().equals('BarType') } assert 'som:BazType' == baz[0].sequence[0].element[0].@type.text() jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/000077500000000000000000000000001351100213400271705ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/000077500000000000000000000000001351100213400313625ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/pom.xml000066400000000000000000000046461351100213400327110ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-custom-converter-converters 1.0-SNAPSHOT Purpose: Validate that a custom StringConverter can be used for filtering. UTF-8 org.codehaus.mojo jaxb2-maven-plugin @project.version@ jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/src/000077500000000000000000000000001351100213400321515ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/src/main/000077500000000000000000000000001351100213400330755ustar00rootroot00000000000000java/000077500000000000000000000000001351100213400337375ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/src/mainse/000077500000000000000000000000001351100213400343465ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/src/main/javawest/000077500000000000000000000000001351100213400353305ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/src/main/java/seconverter/000077500000000000000000000000001351100213400373375ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/src/main/java/se/westFileNameConverter.java000066400000000000000000000004501351100213400435510ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/converters/src/main/java/se/west/converterpackage se.west.converter; import org.codehaus.mojo.jaxb2.shared.filters.pattern.StringConverter; import java.io.File; public class FileNameConverter implements StringConverter { @Override public String convert(final File toConvert) { return toConvert.getName(); } }jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/invoker.properties000066400000000000000000000002451351100213400327640ustar00rootroot00000000000000# A comma or space separated list of goals/phases to execute, may # specify an empty list to execute the default goal of the IT project invoker.goals = clean installjaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/pom.xml000066400000000000000000000031401351100213400305030ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-custom-converter 1.0-SNAPSHOT pom Purpose: Validate that a custom StringConverter can be used for filtering. UTF-8 converters some_project jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/000077500000000000000000000000001351100213400316615ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/pom.xml000066400000000000000000000103611351100213400331770ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-custom-converter-some-project 1.0-SNAPSHOT Purpose: Validate that a custom StringConverter can be used for filtering. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen generated/xsds Bar\.java .* org.codehaus.mojo.jaxb2.its schemagen-custom-converter-converters 1.0-SNAPSHOT jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/src/000077500000000000000000000000001351100213400324505ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/src/main/000077500000000000000000000000001351100213400333745ustar00rootroot00000000000000java/000077500000000000000000000000001351100213400342365ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/src/mainse/000077500000000000000000000000001351100213400346455ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/src/main/javawest/000077500000000000000000000000001351100213400356275ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/src/main/java/segnat/000077500000000000000000000000001351100213400365605ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/src/main/java/se/westBar.java000066400000000000000000000003451351100213400401310ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Bar { // Internal state private String gnus; } Foo.java000066400000000000000000000003441351100213400401470ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/some_project/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-custom-converter/verify.groovy000066400000000000000000000053001351100213400317410ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } def outputDir = new File(basedir, 'some_project/target/generated-resources/schemagen') def workDir = new File(basedir, 'some_project/target/schemagen-work/compile_scope') // Act: Validate content def schemaElement = new XmlSlurper().parse(new File(workDir, 'schema1.xsd')); assert 1 == schemaElement.complexType.size(); assert "foo" == ("" + schemaElement.complexType[0].@name); // Assert println "\nValidating work directory content" println "===================================" validateExistingFile(new File(workDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(workDir, 'META-INF/sun-jaxb.episode'), 2); validateExistingFile(new File(workDir, 'se/west/gnat/Foo.class'), 3); println "\nValidating output directory content" println "=====================================" validateExistingFile(new File(outputDir, 'schema1.xsd'), 1); validateExistingFile(new File(outputDir, 'META-INF/JAXB/episode_schemagen.xjb'), 2); validateNonexistentFile(new File(outputDir, 'se/west/gnat/Foo.class'), 3); validateNonexistentDirectory(new File(basedir, 'some_project/target/generated-test-resources/schemagen/'), 4); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/000077500000000000000000000000001351100213400264145ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/pom.xml000066400000000000000000000056601351100213400277400ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-main 1.0-SNAPSHOT Purpose: Ensure that XML Schema are generated from annotated Java files. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/000077500000000000000000000000001351100213400272035ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/main/000077500000000000000000000000001351100213400301275ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/main/java/000077500000000000000000000000001351100213400310505ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/main/java/se/000077500000000000000000000000001351100213400314575ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/main/java/se/west/000077500000000000000000000000001351100213400324415ustar00rootroot00000000000000gnat/000077500000000000000000000000001351100213400333135ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/main/java/se/westAmericanCoin.java000066400000000000000000000022571351100213400365140ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlType; /** * Simple enumeration example defining standard US coins. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlType(namespace = "http://gnat.west.se/foods") @XmlEnum(Integer.class) @XmlAccessorType(XmlAccessType.FIELD) public enum AmericanCoin { /** * The penny is worth of 1 cent. */ @XmlEnumValue("1") PENNY(1), /** * The nickel is worth of 5 cents. */ @XmlEnumValue("5") NICKEL(5), /** * The dime is worth of 10 cents. */ @XmlEnumValue("10") DIME(10), /** * The quarter is worth of 25 cents. */ @XmlEnumValue("25") QUARTER(25); // Internal state private int value; AmericanCoin(final int value) { this.value = value; } /** * The value - in cents - of this coin. * * @return the value - in cents - of this coin. */ public int getValue() { return value; } } FoodPreference.java000066400000000000000000000026301351100213400370450ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlType; /** * Simple enumeration example defining some Food preferences. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlType(namespace = "http://gnat.west.se/foods") @XmlEnum(String.class) @XmlAccessorType(XmlAccessType.FIELD) public enum FoodPreference { /** * No special food preferences; eats everything. */ NONE(true, true), /** * Vegetarian who will not eat meats, but drinks milk. */ LACTO_VEGETARIAN(false, true), /** * Vegan who will neither eat meats nor drink milk. */ VEGAN(false, false); /** * Boolean value indicating if this {@link FoodPreference} eats meats. */ @XmlAttribute private boolean meatEater; /** * Boolean value indicating if this {@link FoodPreference} drinks milk. */ @XmlAttribute boolean milkDrinker; private FoodPreference(final boolean meatEater, final boolean milkDrinker) { this.meatEater = meatEater; this.milkDrinker = milkDrinker; } public boolean isMeatEater() { return meatEater; } public boolean isMilkDrinker() { return milkDrinker; } } FoodPreferences.java000066400000000000000000000025761351100213400372410ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * Trivial transport object type for enumerations. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(namespace = "http://gnat.west.se/foods") @XmlType(namespace = "http://gnat.west.se/foods", propOrder = {"preferences", "coins"}) @XmlAccessorType(XmlAccessType.FIELD) public class FoodPreferences implements Serializable { /** * A List of {@link FoodPreference} instances. */ @XmlElementWrapper @XmlElement(name = "preference") private List preferences; /** * A List of {@link FoodPreference} instances. */ @XmlElementWrapper @XmlElement(name = "coin") private List coins; public FoodPreferences() { preferences = new ArrayList(); coins = new ArrayList(); } public List getPreferences() { return preferences; } public List getCoins() { return coins; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-enums/verify.groovy000066400000000000000000000126121351100213400311710ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } def classesDir = new File(basedir, 'target/classes') def outputDir = new File(basedir, 'target/generated-resources/schemagen') def workDir = new File(basedir, 'target/schemagen-work/compile_scope') /* Lennart Jörelid, jGuru Europe AB]]> Lennart Jörelid, jGuru Europe AB]]> Lennart Jörelid, jGuru Europe AB]]> */ // Act: Validate content def xml = new XmlSlurper().parse(new File(workDir, 'schema1.xsd')); assert 1 == xml.complexType.size(); def americanCoinElement = xml.simpleType.find { it.@name == 'americanCoin' } def foodPreferenceElement = xml.simpleType.find { it.@name == 'foodPreference' } assert null != americanCoinElement.annotation.documentation.text() assert null != foodPreferenceElement.annotation.documentation.text() // Assert println "\nValidating work directory content" println "===================================" validateExistingFile(new File(workDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(workDir, 'META-INF/sun-jaxb.episode'), 2); validateExistingFile(new File(workDir, 'se/west/gnat/AmericanCoin.class'), 3); validateExistingFile(new File(workDir, 'se/west/gnat/FoodPreference.class'), 4); validateExistingFile(new File(workDir, 'se/west/gnat/FoodPreferences.class'), 5); println "\nValidating output directory content" println "=====================================" validateExistingFile(new File(outputDir, 'schema1.xsd'), 1); validateExistingFile(new File(classesDir, 'META-INF/JAXB/episode_schemagen.xjb'), 2); validateNonexistentDirectory(new File(basedir, 'target/generated-test-resources/schemagen/'), 4); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/000077500000000000000000000000001351100213400276115ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/pom.xml000066400000000000000000000062011351100213400311250ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-handles-package-info 1.0-SNAPSHOT Purpose: Ensure that the plugin handles information given in package-info.java properly. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen example ex example.xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/src/000077500000000000000000000000001351100213400304005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/src/main/000077500000000000000000000000001351100213400313245ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/src/main/java/000077500000000000000000000000001351100213400322455ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/src/main/java/org/000077500000000000000000000000001351100213400330345ustar00rootroot00000000000000testing/000077500000000000000000000000001351100213400344325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/src/main/java/orgxml/000077500000000000000000000000001351100213400352325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/src/main/java/org/testingMyType.java000066400000000000000000000011051351100213400373210ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/src/main/java/org/testing/xmlpackage org.testing.xml; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; /** * This is a class-level comment. */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class MyType { /** * This is a field-level comment. */ @XmlElement(required = true) private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }package-info.java000066400000000000000000000003521351100213400404210ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/src/main/java/org/testing/xml/** * This is a package-level comment. */ @XmlSchema(namespace = "example", elementFormDefault = XmlNsForm.QUALIFIED) package org.testing.xml; import javax.xml.bind.annotation.XmlSchema; import javax.xml.bind.annotation.XmlNsForm; jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-package-info/verify.groovy000066400000000000000000000063371351100213400323750ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } /* +=================== [10 SchemaGen Arguments] | | [0]: -encoding | [1]: UTF-8 | [2]: -d | [3]: /Users/lj/Development/Projects/MojoHaus/jaxb2-maven-plugin/target/it/schemagen-handles-package-info/target/schemagen-work/compile_scope | [4]: -classpath | [5]: /Users/lj/Development/Projects/MojoHaus/jaxb2-maven-plugin/target/it/schemagen-handles-package-info/src/main/java/ | [6]: -episode | [7]: /Users/lj/Development/Projects/MojoHaus/jaxb2-maven-plugin/target/it/schemagen-handles-package-info/target/generated-resources/schemagen/META-INF/sun-jaxb.episode | [8]: src/main/java/org/testing/xml/MyType.java | [9]: src/main/java/org/testing/xml/package-info.java | +=================== [End 10 SchemaGen Arguments] */ def outputDir = new File(basedir, 'target/generated-resources/schemagen') def transformed = new File(outputDir, 'example.xsd') def episodeFile = new File(basedir, 'target/classes/META-INF/JAXB/episode_schemagen.xjb') // Assert: Validate existing files validateExistingFile(transformed, 1) validateExistingFile(episodeFile, 2) // Assert: Validate content def xml = new XmlSlurper().parse(transformed); assert 1 == xml.complexType.size(), 'Found ' + xml.complexType.size() + ' generated complex types in the example.xsd file. (Expected 1).'; assert 'myType' == xml.complexType[0].@name.text(); println "3. Correctly detected generated ComplexType." assert 1 == xml.element.size(), 'Found ' + xml.element.size() + ' generated elements in the example.xsd file. (Expected 1).'; assert 'myType' == xml.element[0].@name.text(); assert 'ex:myType' == xml.element[0].@type.text(); println "3. Correctly detected generated Element."jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in paths/000077500000000000000000000000001351100213400302325ustar00rootroot00000000000000invoker.properties000066400000000000000000000000351351100213400337440ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in pathsinvoker.buildResult = failurejaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in paths/pom.xml000066400000000000000000000052721351100213400315550ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-jaxb-spaces-in-paths 1.0-SNAPSHOT Purpose: Ensure that the plugin properly provides File paths with whitespace to Schemagen. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in paths/src/000077500000000000000000000000001351100213400310215ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in paths/src/main/000077500000000000000000000000001351100213400317455ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in paths/src/main/java/000077500000000000000000000000001351100213400326665ustar00rootroot00000000000000se/000077500000000000000000000000001351100213400332165ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in paths/src/main/javawest/000077500000000000000000000000001351100213400342005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in paths/src/main/java/seSomeType.java000066400000000000000000000013121351100213400366050ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-spaces in paths/src/main/java/se/westpackage se.west; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(name = "someType", namespace = "http://mojohaus.org/whitespacetest") @XmlType(name = "someType", namespace = "http://mojohaus.org/whitespacetest") @XmlAccessorType(XmlAccessType.FIELD) public class SomeType { private String name; public SomeType() { } public SomeType(final String name) { this.name = name; } public String getName() { return name; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/000077500000000000000000000000001351100213400276515ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/pom.xml000066400000000000000000000053171351100213400311740ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-jaxb-xmlwrappers 1.0-SNAPSHOT Purpose: Ensure that the plugin properly generates XML documentation for fields annotated with @XmlWrapper. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/000077500000000000000000000000001351100213400304405ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/000077500000000000000000000000001351100213400313645ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/000077500000000000000000000000001351100213400323055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/000077500000000000000000000000001351100213400330745ustar00rootroot00000000000000codehaus/000077500000000000000000000000001351100213400346105ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/orgmojo/000077500000000000000000000000001351100213400355545ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/codehausjaxb2/000077500000000000000000000000001351100213400365625ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/codehaus/mojoschemageneration/000077500000000000000000000000001351100213400420765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/codehaus/mojo/jaxb2postprocessing/000077500000000000000000000000001351100213400451605ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/codehaus/mojo/jaxb2/schemagenerationjavadoc/000077500000000000000000000000001351100213400465675ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingjavadoc/wrappers/000077500000000000000000000000001351100213400504325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingjavadoc/wrappers/ExampleXmlWrapperUsingFieldAccess.java000066400000000000000000000034531351100213400600130ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * A really trivial transport object type for collections, demonstrating that * the jaxb2-maven-plugin's schemagen goal correctly can extract XSD documentation * annotations when using @XmlElementWrapper annotations placed on Fields. * * This requires use of the @XmlAccessorType(XmlAccessType.FIELD) on the class in question, * or - alternatively - on a package-info.java file containing the equivalent annotation. */ @XmlRootElement(namespace = "http://jaxb.mojohaus.org/wrappers") @XmlType(namespace = "http://jaxb.mojohaus.org/wrappers", propOrder = {"strings", "integerSet"}) @XmlAccessorType(XmlAccessType.FIELD) public class ExampleXmlWrapperUsingFieldAccess implements Serializable { /** * List containing some strings. */ @XmlElementWrapper(name = "foobar") @XmlElement(name = "aString") private List strings; /** * SortedSet containing Integers. */ @XmlElementWrapper @XmlElement(name = "anInteger") private SortedSet integerSet; public ExampleXmlWrapperUsingFieldAccess() { this.strings = new ArrayList(); this.integerSet = new TreeSet(); } public List getStrings() { return strings; } public SortedSet getIntegerSet() { return integerSet; } } javadoc/wrappers/ExampleXmlWrapperUsingMethodAccess.java000066400000000000000000000036021351100213400602040ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * Another trivial transport object type for collections, demonstrating that * the jaxb2-maven-plugin's schemagen goal correctly can extract XSD documentation * annotations when using @XmlElementWrapper annotations placed on Method accessors * (which is the default for SchemaGen). */ @XmlRootElement(namespace = "http://jaxb.mojohaus.org/wrappers") @XmlType(namespace = "http://jaxb.mojohaus.org/wrappers", propOrder = {"methodStrings", "methodIntegerSet"}) @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) public class ExampleXmlWrapperUsingMethodAccess implements Serializable { private List methodStrings; private SortedSet methodIntegerSet; public ExampleXmlWrapperUsingMethodAccess() { this.methodStrings = new ArrayList(); this.methodIntegerSet = new TreeSet(); } /** * JavaBean getter method containing some method strings. * * @return some method strings. */ @XmlElementWrapper(name = "foobar") @XmlElement(name = "aString") public List getMethodStrings() { return methodStrings; } /** * JavaBean getter method returning Integers. * * @return a Set of integers. * @see #getMethodStrings() */ @XmlElementWrapper @XmlElement(name = "anInteger") public SortedSet getMethodIntegerSet() { return methodIntegerSet; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-handles-xmlwrappers/verify.groovy000066400000000000000000000126611351100213400324320ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import groovy.util.slurpersupport.*; // Assemble final File outputDir = new File(basedir, 'target/generated-resources/schemagen') final File workDir = new File(basedir, 'target/schemagen-work/compile_scope') /* First Complex Type: Second Complex Type: */ // Act: Validate transformed content def xml = new XmlSlurper().parse(new File(outputDir, 'schema1.xsd')); assert 2 == xml.complexType.size(), 'Found ' + xml.complexType.size() + ' generated complex types in the schema1.xsd file. (Expected 2).'; def fieldAccessType = xml.'xs:complexType'.find { it.@name == 'exampleXmlWrapperUsingFieldAccess' } def methodAccessType = xml.'xs:complexType'.find { it.@name == 'exampleXmlWrapperUsingMethodAccess' } assert fieldAccessType != null, "Found no FieldAccessType" assert methodAccessType != null, "Found no MethodAccessType" println "Got fieldAccessType of type [" + fieldAccessType.getClass().getName() + "]" println "Got methodAccessType of type [" + methodAccessType.getClass().getName() + "]" // Assert println "\nValidating Documentation Annotations for String List" println "====================================================" // /xs:schema/xs:complexType/xs:sequence/xs:element/xs:annotation/xs:documentation def expectedStringListDocComment = "List containing some strings." def expectedIntegerSetDocComment = "SortedSet containing Integers." def stringListDocComment = xml.complexType .find { it.@name == 'exampleXmlWrapperUsingFieldAccess' } .sequence .element .find { it.@name == 'foobar' } .annotation .documentation .toString() .trim() def intSetDocComment = xml.complexType .find { it.@name == 'exampleXmlWrapperUsingFieldAccess' } .sequence .element .find { it.@name == 'integerSet' } .annotation .documentation .toString() .trim() assert expectedStringListDocComment == stringListDocComment, "Expected [" + expectedStringListDocComment + "], but got [" + stringListDocComment + "]" println "Correctly found stringListDocComment [" + stringListDocComment + "] for Field Access type." assert expectedIntegerSetDocComment == intSetDocComment, "Expected [" + expectedIntegerSetDocComment + "], but got [" + intSetDocComment + "]" println "Correctly found intSetDocComment [" + intSetDocComment + "] for Field Access type." // println "\nValidating Documentation Annotations for int Set" println "==================================================" jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/000077500000000000000000000000001351100213400267555ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/pom.xml000066400000000000000000000055721351100213400303030ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-include-sources 1.0-SNAPSHOT Purpose: Ensure that source directives work properly. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen src/main/java/se/west/gnat jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/src/000077500000000000000000000000001351100213400275445ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/src/main/000077500000000000000000000000001351100213400304705ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/src/main/java/000077500000000000000000000000001351100213400314115ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/src/main/java/se/000077500000000000000000000000001351100213400320205ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/src/main/java/se/west/000077500000000000000000000000001351100213400330025ustar00rootroot00000000000000ANonAnnotatedClass.java000066400000000000000000000001641351100213400372460ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/src/main/java/se/westpackage se.west; public class ANonAnnotatedClass { // Internal state private String shouldNotBeIncluded; }gnat/000077500000000000000000000000001351100213400336545ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/src/main/java/se/westFoo.java000066400000000000000000000003441351100213400352430ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-sources/verify.groovy000066400000000000000000000054141351100213400315340ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } def episodeFile = new File(basedir, 'target/classes/META-INF/JAXB/episode_schemagen.xjb') def outputDir = new File(basedir, 'target/generated-resources/schemagen') def workDir = new File(basedir, 'target/schemagen-work/compile_scope') // Act: Validate content def xml = new XmlSlurper().parse(new File(workDir, 'schema1.xsd')); assert 1 == xml.complexType.size(), 'Found ' + xml.complexType.size() + ' generated complex types in the schema1.xsd file. (Expected 1).'; assert 'foo' == xml.complexType[0].@name.text(); // Assert println "\nValidating work directory content" println "===================================" validateExistingFile(new File(workDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(workDir, 'META-INF/sun-jaxb.episode'), 2); validateExistingFile(new File(workDir, 'se/west/gnat/Foo.class'), 3); println "\nValidating output directory content" println "=====================================" validateExistingFile(new File(outputDir, 'schema1.xsd'), 1); validateExistingFile(episodeFile, 2); validateNonexistentFile(new File(outputDir, 'se/west/gnat/Foo.class'), 3); validateNonexistentDirectory(new File(basedir, 'target/generated-test-resources/schemagen/'), 4); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/000077500000000000000000000000001351100213400277325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/pom.xml000066400000000000000000000056271351100213400312610ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-include-test-sources 1.0-SNAPSHOT Purpose: Ensure that source directives work properly. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ testSchemagen testSchemagen src/test/java/se/west/gnat jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/src/000077500000000000000000000000001351100213400305215ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/src/test/000077500000000000000000000000001351100213400315005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/src/test/java/000077500000000000000000000000001351100213400324215ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/src/test/java/se/000077500000000000000000000000001351100213400330305ustar00rootroot00000000000000west/000077500000000000000000000000001351100213400337335ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/src/test/java/seANonAnnotatedClass.java000066400000000000000000000001641351100213400402560ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/src/test/java/se/westpackage se.west; public class ANonAnnotatedClass { // Internal state private String shouldNotBeIncluded; }gnat/000077500000000000000000000000001351100213400346645ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/src/test/java/se/westFoo.java000066400000000000000000000003441351100213400362530ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/src/test/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-include-test-sources/verify.groovy000066400000000000000000000055021351100213400325070ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } // Note: The execution ID is "testSchemagen" // def episodeFile = new File(basedir, 'target/test-classes/META-INF/JAXB/episode_testSchemagen.xjb') def outputDir = new File(basedir, 'target/generated-test-resources/schemagen') def workDir = new File(basedir, 'target/schemagen-work/test_scope') // Act: Validate content def xml = new XmlSlurper().parse(new File(workDir, 'schema1.xsd')); assert 1 == xml.complexType.size(), 'Found ' + xml.complexType.size() + ' generated complex types in the schema1.xsd file. (Expected 1).'; assert 'foo' == xml.complexType[0].@name.text(); // Assert println "\nValidating work directory content" println "===================================" validateExistingFile(new File(workDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(workDir, 'META-INF/sun-jaxb.episode'), 2); validateExistingFile(new File(workDir, 'se/west/gnat/Foo.class'), 3); println "\nValidating output directory content" println "=====================================" validateExistingFile(new File(outputDir, 'schema1.xsd'), 1); validateExistingFile(episodeFile, 2); validateNonexistentFile(new File(outputDir, 'se/west/gnat/Foo.class'), 3); validateNonexistentDirectory(new File(basedir, 'target/generated-resources/schemagen/'), 4); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/000077500000000000000000000000001351100213400261075ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/invoker.properties000066400000000000000000000000351351100213400317000ustar00rootroot00000000000000invoker.buildResult = failurejaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/pom.xml000066400000000000000000000052511351100213400274270ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-jaxb-errors 1.0-SNAPSHOT Purpose: Ensure that JAXB error messages are propagated properly as plugin errors. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/src/000077500000000000000000000000001351100213400266765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/src/main/000077500000000000000000000000001351100213400276225ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/src/main/java/000077500000000000000000000000001351100213400305435ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/src/main/java/se/000077500000000000000000000000001351100213400311525ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/src/main/java/se/west/000077500000000000000000000000001351100213400321345ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/src/main/java/se/west/gnat/000077500000000000000000000000001351100213400330655ustar00rootroot00000000000000IncorrectJaxbAnnotationClass.java000066400000000000000000000006031351100213400414260ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @XmlAccessorType(XmlAccessType.FIELD) public class IncorrectJaxbAnnotationClass { // Internal state private String bar; @XmlElement(required = true) private String getBar() { return bar; } }jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-jaxb-errors/verify.groovy000066400000000000000000000044201351100213400306620ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } final File workDir = new File(basedir, 'target/schemagen-work/compile_scope') // Validate that no schemas was produced by this invocation. def normalResult = new File(workDir, 'schema1.xsd'); validateNonexistentFile(normalResult, 1); // Validate that the expected JAXB error message is stashed in the log def expectedErrorMessage = 'Class has two properties of the same name "bar"'; List lines = new File(basedir, 'build.log').readLines(); boolean foundExpectedErrorMessage = false; for(line in lines) { if(line.trim().startsWith(expectedErrorMessage)) { foundExpectedErrorMessage = true; } } assert foundExpectedErrorMessage, "Expected JAXB error message not found."jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/000077500000000000000000000000001351100213400245755ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/pom.xml000066400000000000000000000056601351100213400261210ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-main 1.0-SNAPSHOT Purpose: Ensure that XML Schema are generated from annotated Java files. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/src/000077500000000000000000000000001351100213400253645ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/src/main/000077500000000000000000000000001351100213400263105ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/src/main/java/000077500000000000000000000000001351100213400272315ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/src/main/java/se/000077500000000000000000000000001351100213400276405ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/src/main/java/se/west/000077500000000000000000000000001351100213400306225ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/src/main/java/se/west/gnat/000077500000000000000000000000001351100213400315535ustar00rootroot00000000000000Foo.java000066400000000000000000000003441351100213400330630ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-main/verify.groovy000066400000000000000000000057071351100213400273610ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } def classesDir = new File(basedir, 'target/classes') def outputDir = new File(basedir, 'target/generated-resources/schemagen') def workDir = new File(basedir, 'target/schemagen-work/compile_scope') // Act: Validate content def xml = new XmlSlurper().parse(new File(workDir, 'schema1.xsd')); assert 1 == xml.complexType.size(); assert 'foo' == xml.complexType[0].@name.text(); // Assert println "\nValidating work directory content" println "===================================" /* [INFO] The post-build script did not succeed. Missing required file [/Users/lenjor/Development/Projects/Mojohaus/jaxb2-maven-plugin/target/it/schemagen-main/ target/generated-resources/schemagen/META-INF/sun-jaxb.episode]. Expression: (aFile.exists() && aFile.isFile()) */ validateExistingFile(new File(workDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(workDir, 'META-INF/sun-jaxb.episode'), 2); validateExistingFile(new File(workDir, 'se/west/gnat/Foo.class'), 3); println "\nValidating output directory content" println "=====================================" validateExistingFile(new File(outputDir, 'schema1.xsd'), 1); validateExistingFile(new File(classesDir, 'META-INF/JAXB/episode_schemagen.xjb'), 2); validateNonexistentFile(new File(outputDir, 'se/west/gnat/Foo.class'), 3); validateNonexistentDirectory(new File(basedir, 'target/generated-test-resources/schemagen/'), 4); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/000077500000000000000000000000001351100213400276555ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/000077500000000000000000000000001351100213400310045ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/pom.xml000066400000000000000000000052101351100213400323170ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-multimodule-project 1.0-SNAPSHOT first 1.0-SNAPSHOT Purpose: Validate that XSDs are generated properly in multi-module projects. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/000077500000000000000000000000001351100213400315735ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/main/000077500000000000000000000000001351100213400325175ustar00rootroot00000000000000java/000077500000000000000000000000001351100213400333615ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/mainse/000077500000000000000000000000001351100213400337705ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/main/javawest/000077500000000000000000000000001351100213400347525ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/main/java/sefirst/000077500000000000000000000000001351100213400361015ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/main/java/se/westNonAnnotatedFirst.java000066400000000000000000000001631351100213400423440ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/main/java/se/west/firstpackage se.west; public class NonAnnotatedFirst { // Internal state private String shouldNotBeIncluded; }gnat/000077500000000000000000000000001351100213400370325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/main/java/se/west/firstFirstFoo.java000066400000000000000000000003641351100213400414330ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/first/src/main/java/se/west/first/gnatpackage se.west.first.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class FirstFoo { // Internal state private String firstBar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/pom.xml000066400000000000000000000100411351100213400311660ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-multimodule-project 1.0-SNAPSHOT pom Purpose: Validate that XSDs are generated properly in multi-module projects. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen src/main/java/se/west/first/gnat src/main/java/se/west/third/gnat \.xjb \.xsd Excluded\.java first second third jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/000077500000000000000000000000001351100213400311305ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/pom.xml000066400000000000000000000052121351100213400324450ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-multimodule-project 1.0-SNAPSHOT second 1.0-SNAPSHOT Purpose: Validate that XSDs are generated properly in multi-module projects. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/src/000077500000000000000000000000001351100213400317175ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/src/main/000077500000000000000000000000001351100213400326435ustar00rootroot00000000000000java/000077500000000000000000000000001351100213400335055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/src/mainse/000077500000000000000000000000001351100213400341145ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/src/main/javawest/000077500000000000000000000000001351100213400350765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/src/main/java/sesecond/000077500000000000000000000000001351100213400363515ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/src/main/java/se/westgnat/000077500000000000000000000000001351100213400373025ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/src/main/java/se/west/secondSecondFoo.java000066400000000000000000000003671351100213400420320ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/second/src/main/java/se/west/second/gnatpackage se.west.second.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class SecondFoo { // Internal state private String secondBar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/000077500000000000000000000000001351100213400307675ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/pom.xml000066400000000000000000000052111351100213400323030ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-multimodule-project 1.0-SNAPSHOT third 1.0-SNAPSHOT Purpose: Validate that XSDs are generated properly in multi-module projects. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/000077500000000000000000000000001351100213400315565ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/main/000077500000000000000000000000001351100213400325025ustar00rootroot00000000000000java/000077500000000000000000000000001351100213400333445ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/mainse/000077500000000000000000000000001351100213400337535ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/main/javawest/000077500000000000000000000000001351100213400347355ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/main/java/seShouldNotBeIncluded.java000066400000000000000000000003741351100213400414420ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/main/java/se/westpackage se.west; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class ShouldNotBeIncluded { // Internal state private String someInternalState; }third/000077500000000000000000000000001351100213400360475ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/main/java/se/westgnat/000077500000000000000000000000001351100213400370005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/main/java/se/west/thirdExplicitlyExcluded.java000066400000000000000000000004061351100213400434470ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/main/java/se/west/third/gnatpackage se.west.third.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class ExplicitlyExcluded { // Internal state private String thirdExcludedBar; } ThirdFoo.java000066400000000000000000000003641351100213400413640ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/third/src/main/java/se/west/third/gnatpackage se.west.third.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class ThirdFoo { // Internal state private String thirdBar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-multimodule-project/verify.groovy000066400000000000000000000061411351100213400324320ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } def validateSingleComplexType(final String submoduleName, final String expectedName, final int index) { final File xsdSchemaFile = new File(basedir, submoduleName + '/target/generated-resources/schemagen/schema1.xsd'); def xml = new XmlSlurper().parse(xsdSchemaFile); // Validate that we only have 1 complexType in the XML read from the XSD File. assert 1 == xml.complexType.size(), 'Found ' + xml.complexType.size() + ' generated complex types in the ' + xsdSchemaFile.getAbsolutePath() + ' file. (Expected ' + expectedName + ').'; println "" + index + ". Correctly found [" + expectedName + "] ComplexTypes in [" + xsdSchemaFile.getAbsolutePath() + "]"; // Validate the name of the first/single complex type assert expectedName == xml.complexType[0].@name.text(); println "" + index + ". Correctly expected name [" + expectedName + "] for first ComplexType in [" + xsdSchemaFile.absolutePath + "]"; } // Validate content for first sub-project println "\nValidating schema for submodule 'first'" println "=========================================" validateSingleComplexType('first', 'firstFoo', 1); println "\nValidating non-existent schema for submodule 'second'" println "=======================================================" validateNonexistentDirectory(new File(basedir, 'second/target/schemagen-work'), 2); println "\nValidating schema for submodule 'first'" println "=========================================" validateSingleComplexType('third', 'thirdFoo', 3); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/000077500000000000000000000000001351100213400272615ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/pom.xml000066400000000000000000000050701351100213400306000ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-platform-encoding 1.0-SNAPSHOT Test of basic usage when platform encoding is used (no encoding specified) jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/src/000077500000000000000000000000001351100213400300505ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/src/main/000077500000000000000000000000001351100213400307745ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/src/main/java/000077500000000000000000000000001351100213400317155ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/src/main/java/se/000077500000000000000000000000001351100213400323245ustar00rootroot00000000000000west/000077500000000000000000000000001351100213400332275ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/src/main/java/segnat/000077500000000000000000000000001351100213400341605ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/src/main/java/se/westFoo.java000066400000000000000000000003441351100213400355470ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-platform-encoding/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/000077500000000000000000000000001351100213400260775ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/pom.xml000066400000000000000000000057011351100213400274170ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-main 1.0-SNAPSHOT Purpose: Ensure that XML Schema renames are generated properly from annotated Java files. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/src/000077500000000000000000000000001351100213400266665ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/src/main/000077500000000000000000000000001351100213400276125ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/src/main/java/000077500000000000000000000000001351100213400305335ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/src/main/java/se/000077500000000000000000000000001351100213400311425ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/src/main/java/se/west/000077500000000000000000000000001351100213400321245ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/src/main/java/se/west/gnat/000077500000000000000000000000001351100213400330555ustar00rootroot00000000000000Foo.java000066400000000000000000000006201351100213400343620ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; @XmlType(name="RenamedFoo") @XmlAccessorType(XmlAccessType.FIELD) public class Foo { /** * This is a Bar. */ @XmlAttribute(name = "renamedBar") private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-rename-type/verify.groovy000066400000000000000000000066111351100213400306560ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } def outputDir = new File(basedir, 'target/generated-resources/schemagen') def workDir = new File(basedir, 'target/schemagen-work/compile_scope') def episodeFile = new File(basedir, 'target/classes/META-INF/JAXB/episode_schemagen.xjb') /* */ // Act: Validate content def xml = new XmlSlurper().parse(new File(outputDir, 'schema1.xsd')); def renamedFooType = xml.complexType[0]; def renamedBarAttribute = renamedFooType.attribute[0]; assert 1 == xml.complexType.size(); assert 'RenamedFoo' == renamedFooType.@name.text().trim() assert 'renamedBar' == renamedBarAttribute.@name.text().trim() assert 'xs:string' == renamedBarAttribute.@type.text().trim() assert 'This is a Bar.' == renamedBarAttribute.annotation[0].documentation[0].text().trim() // Assert println "\nValidating work directory content" println "===================================" validateExistingFile(new File(workDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(workDir, 'META-INF/sun-jaxb.episode'), 2); validateExistingFile(new File(workDir, 'se/west/gnat/Foo.class'), 3); println "\nValidating output directory content" println "=====================================" validateExistingFile(new File(outputDir, 'schema1.xsd'), 1); validateExistingFile(episodeFile, 2); validateNonexistentFile(new File(outputDir, 'se/west/gnat/Foo.class'), 3); validateNonexistentDirectory(new File(basedir, 'target/generated-test-resources/schemagen/'), 4); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-skipping-nonexistent-sources/000077500000000000000000000000001351100213400315325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-skipping-nonexistent-sources/pom.xml000066400000000000000000000056631351100213400330610ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-main 1.0-SNAPSHOT Purpose: Verify that SchemaGen skips any nonexistent sources given. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen verify.groovy000066400000000000000000000050461351100213400342330ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-skipping-nonexistent-sources/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* +=================== [Filtered sources] | | 6 Exclude patterns: | [1/6]: (\p{javaLetterOrDigit}|\p{Punct})+README.* | [2/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.xml | [3/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.txt | [4/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.xjb | [5/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.xsd | [6/6]: (\p{javaLetterOrDigit}|\p{Punct})+\.properties | | 1 Sources: | [1/1]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/schemagen-skipping-nonexistent-sources/src/main/java | | 0 Results: | +=================== [End Filtered sources] ... and ... +=================== [Incorrect Plugin Configuration Detected] | | Property : sources | Problem : At least one Java Source file has to be included. | +=================== [End Incorrect Plugin Configuration Detected] */ File buildLog = new File(basedir, 'build.log') final String expectedConfigWarning = "| Problem : At least one Java Source file has to be included."; final String expectedSkippingExecution = "[DEBUG] Skipping execution, as instructed."; boolean foundIncorrectConfigWarning = false; boolean foundExpectedSkippingExecution = false; List lines = buildLog.readLines(); for (line in lines) { String trimmedLine = line.trim() if (trimmedLine.isEmpty()) { continue }; if(!foundIncorrectConfigWarning && trimmedLine.equalsIgnoreCase(expectedConfigWarning)) { foundIncorrectConfigWarning = true; } if(!foundExpectedSkippingExecution && trimmedLine.equalsIgnoreCase(expectedSkippingExecution)) { foundExpectedSkippingExecution = true; } } // Assert assert foundIncorrectConfigWarning, "Missing required line: [" + expectedConfigWarning + "]" assert foundExpectedSkippingExecution, "Missing required line: [" + expectedSkippingExecution + "]" jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/000077500000000000000000000000001351100213400246305ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/pom.xml000066400000000000000000000060131351100213400261450ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-test 1.0-SNAPSHOT Purpose: Ensure that test-scope XML Schema are generated from annotated test-scope Java files. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen-test testSchemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/src/000077500000000000000000000000001351100213400254175ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/src/test/000077500000000000000000000000001351100213400263765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/src/test/java/000077500000000000000000000000001351100213400273175ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/src/test/java/se/000077500000000000000000000000001351100213400277265ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/src/test/java/se/west/000077500000000000000000000000001351100213400307105ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/src/test/java/se/west/blah/000077500000000000000000000000001351100213400316165ustar00rootroot00000000000000Foo.java000066400000000000000000000003441351100213400331260ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/src/test/java/se/west/blahpackage se.west.blah; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-test/verify.groovy000066400000000000000000000034431351100213400274070ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // java.lang.AssertionError: Expected file [/Users/lenjor/Development/Projects/Mojohaus/jaxb2-maven-plugin/target/ // it/schemagen-test/target/generated-test-resources/schemagen/META-INF/sun-jaxb.episode] not found.. // Expression: testEpisode.exists() def testSchema = new File(basedir, 'target/generated-test-resources/schemagen/schema1.xsd'); def testEpisode = new File(basedir, 'target/generated-test-resources/schemagen/META-INF' + '/JAXB/episode_schemagen-test.xjb'); assert testSchema.exists(), "Expected file [" + testSchema.getAbsolutePath() + "] not found." assert testEpisode.exists(), "Expected file [" + testEpisode.getAbsolutePath() + "] not found." // Validate content def xml = new XmlSlurper().parse(testSchema) assert 1 == xml.complexType.size() assert 'foo' == xml.complexType[0].@name.text() File mainSchemagen = new File(basedir, 'target/generated-resources/schemagen/') assert !mainSchemagen.exists(), "Found unexpected generated Resources [" + mainSchemagen.getAbsolutePath() + "]"; jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/000077500000000000000000000000001351100213400277005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/pom.xml000066400000000000000000000054311351100213400312200ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-main 1.0-SNAPSHOT Purpose: Ensure that XML Schema are generated from annotated Java files. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen fr jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/src/000077500000000000000000000000001351100213400304675ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/src/main/000077500000000000000000000000001351100213400314135ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/src/main/java/000077500000000000000000000000001351100213400323345ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/src/main/java/se/000077500000000000000000000000001351100213400327435ustar00rootroot00000000000000west/000077500000000000000000000000001351100213400336465ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/src/main/java/segnat/000077500000000000000000000000001351100213400345775ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/src/main/java/se/westFoo.java000066400000000000000000000003441351100213400361660ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-with-explicit-locale/verify.groovy000066400000000000000000000052451351100213400324610ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } def outputDir = new File(basedir, 'target/generated-resources/schemagen') def workDir = new File(basedir, 'target/schemagen-work/compile_scope') def episodeFile = new File(basedir, 'target/classes/META-INF/JAXB/episode_schemagen.xjb') // Act: Validate content def xml = new XmlSlurper().parse(new File(workDir, 'schema1.xsd')); assert 1 == xml.complexType.size(); assert 'foo' == xml.complexType[0].@name.text(); // Assert println "\nValidating work directory content" println "===================================" validateExistingFile(new File(workDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(workDir, 'META-INF/sun-jaxb.episode'), 2); validateExistingFile(new File(workDir, 'se/west/gnat/Foo.class'), 3); println "\nValidating output directory content" println "=====================================" validateExistingFile(new File(outputDir, 'schema1.xsd'), 1); validateExistingFile(episodeFile, 2); validateNonexistentFile(new File(outputDir, 'se/west/gnat/Foo.class'), 3); validateNonexistentDirectory(new File(basedir, 'target/generated-test-resources/schemagen/'), 4); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/000077500000000000000000000000001351100213400270025ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/pom.xml000066400000000000000000000054561351100213400303310ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-main 1.0-SNAPSHOT Purpose: Ensure that XML Schema are generated from annotated Java files. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen false jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/src/000077500000000000000000000000001351100213400275715ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/src/main/000077500000000000000000000000001351100213400305155ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/src/main/java/000077500000000000000000000000001351100213400314365ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/src/main/java/se/000077500000000000000000000000001351100213400320455ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/src/main/java/se/west/000077500000000000000000000000001351100213400330275ustar00rootroot00000000000000gnat/000077500000000000000000000000001351100213400337015ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/src/main/java/se/westFoo.java000066400000000000000000000003441351100213400352700ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-without-episode/verify.groovy000066400000000000000000000052011351100213400315530ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble def validateExistingFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert aFile.exists() && aFile.isFile(), "Missing required file [" + path + "]"; println "" + index + ". Expected file exists correctly. [" + path + "]"; } def validateNonexistentFile(final File aFile, final int index) { final String path = aFile.getCanonicalPath(); assert !aFile.exists(), "File should not exist: [" + path + "]"; println "" + index + ". File correctly non-existent. [" + path + "]"; } def validateNonexistentDirectory(final File aDirectory, final int index) { final String path = aDirectory.getCanonicalPath(); assert !aDirectory.exists(), "Directory should not exist: [" + path + "]"; println "" + index + ". Directory correctly non-existent. [" + path + "]"; } final File outputDir = new File(basedir, 'target/generated-resources/schemagen') final File workDir = new File(basedir, 'target/schemagen-work/compile_scope') // Act: Validate content def xml = new XmlSlurper().parse(new File(workDir, 'schema1.xsd')); assert 1 == xml.complexType.size(); assert 'foo' == xml.complexType[0].@name.text(); // Assert println "\nValidating work directory content" println "===================================" validateExistingFile(new File(workDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(workDir, 'META-INF/sun-jaxb.episode'), 2); validateExistingFile(new File(workDir, 'se/west/gnat/Foo.class'), 3); println "\nValidating output directory content" println "=====================================" validateExistingFile(new File(outputDir, 'schema1.xsd'), 1); validateNonexistentFile(new File(outputDir, 'META-INF/sun-jaxb.episode'), 2); validateNonexistentFile(new File(outputDir, 'se/west/gnat/Foo.class'), 3); validateNonexistentDirectory(new File(basedir, 'target/generated-test-resources/schemagen/'), 4); jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/000077500000000000000000000000001351100213400266355ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/pom.xml000066400000000000000000000060421351100213400301540ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its schemagen-main 1.0-SNAPSHOT Purpose: Validate that the SchemaGenerator uses the work-directory for initial generation and copies non-bytecode files to the generated-resources directory. (MJAXB-114). UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ schemagen schemagen jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/src/000077500000000000000000000000001351100213400274245ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/src/main/000077500000000000000000000000001351100213400303505ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/src/main/java/000077500000000000000000000000001351100213400312715ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/src/main/java/se/000077500000000000000000000000001351100213400317005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/src/main/java/se/west/000077500000000000000000000000001351100213400326625ustar00rootroot00000000000000gnat/000077500000000000000000000000001351100213400335345ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/src/main/java/se/westFoo.java000066400000000000000000000003441351100213400351230ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/src/main/java/se/west/gnatpackage se.west.gnat; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class Foo { // Internal state private String bar; } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/schemagen-work-directory/verify.groovy000066400000000000000000000030601351100213400314070ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ final File generatedSchema = new File(basedir, 'target/generated-resources/schemagen/schema1.xsd') final File generatedEpisode = new File(basedir, 'target/classes/META-INF/JAXB/episode_schemagen.xjb') assert generatedSchema.exists(), "Expected file [" + generatedSchema.getAbsolutePath() + "] not found." assert generatedEpisode.exists(), "Expected file [" + generatedEpisode.getAbsolutePath() + "] not found." // Validate content def xml = new XmlSlurper().parse(generatedSchema) assert 1 == xml.complexType.size() assert 'foo' == xml.complexType[0].@name.text() final File testSchemagen = new File(basedir, 'target/generated-test-resources/schemagen/') assert !testSchemagen.exists(), "Found unexpected generated TestResources [" + testSchemagen.getAbsolutePath() + "]"; jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/settings.xml000066400000000000000000000040061351100213400243030ustar00rootroot00000000000000 it-repo true local.central @localRepositoryUrl@ true true apache.snapshots Apache Snapshot Repository http://people.apache.org/repo/m2-snapshot-repository false true local.central @localRepositoryUrl@ true true jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/000077500000000000000000000000001351100213400267075ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/pom.xml000066400000000000000000000103751351100213400302320ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-include-file-regularExpressions 1.0-SNAPSHOT Purpose: Validation of the sources and excludeSourcesPatterns. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc src/main/someOtherXsds src/main/foo/gnat.txt src/main/nonexistent/paths \.xsd \.foo se.west source/xsds jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/000077500000000000000000000000001351100213400274765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/main/000077500000000000000000000000001351100213400304225ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/main/foo/000077500000000000000000000000001351100213400312055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/main/foo/gnat.txt000066400000000000000000000010771351100213400327040ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/main/someOtherXsds/000077500000000000000000000000001351100213400332315ustar00rootroot00000000000000another_schema.foo000066400000000000000000000020251351100213400366360ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/main/someOtherXsds fooSchema.txt000066400000000000000000000003671351100213400356250ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/main/someOtherXsds some_schema.bar000066400000000000000000000016131351100213400361240ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/main/someOtherXsds thisShouldBeIgnored.xsd000066400000000000000000000011161351100213400375760ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/src/main/someOtherXsds jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-exclude-file-patterns/verify.groovy000066400000000000000000000124121351100213400314620ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble File buildLog = new File(basedir, 'build.log') List lines = buildLog.readLines(); /* [DEBUG] Accepted configured sources [/Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-include-file-patterns/src/main/someOtherXsds] [DEBUG] Accepted configured sources [/Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-include-file-patterns/src/main/foo/gnat.txt] [INFO] Ignored given or default sources [src/main/nonexistent/paths], since it is not an existent file or directory. [INFO] Got resolvedSources: [ /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-include-file-patterns/src/main/someOtherXsds/fooSchema.txt, /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-include-file-patterns/src/main/someOtherXsds/some_schema.bar, /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-include-file-patterns/src/main/foo/gnat.txt] [DEBUG] Processing file [0/5]: se/west/AddressTypeFromGnatTxt.java [DEBUG] Processing file [1/5]: se/west/FooBar.java [DEBUG] Processing file [2/5]: se/west/FooBaz.java [DEBUG] Processing file [3/5]: se/west/ObjectFactory.java [DEBUG] Processing file [4/5]: se/west/package-info.java */ def sep = System.getProperty("file.separator"); def isProcessingFileLine(final String aLine, final String className) { def marker = ("se/west/" + className + ".java").replace("/", System.getProperty("file.separator")); return aLine.contains("[DEBUG] Processing file [") && aLine.contains(marker); } String expectedIgnoreLine = "Ignored given or default sources [src/main/nonexistent/paths], " + "since it is not an existent file or directory.".replace("/", sep); String acceptedLinePrefix = "Accepted configured sources"; String acceptedSomeOtherPath = "src/main/someOtherXsds".replace("/", sep); String acceptedFooGnatTxt = "src/main/foo/gnat.txt".replace("/", sep); def foundIgnoreLine = false; def foundSomeOtherPathLine = false; def foundFooGnatTextLine = false; def foundProcessingShouldBeIgnoredAddressType = false; def foundProcessingAddressTypeFromGnatTxtType = false; def foundProcessingFooBarType = false; def foundProcessingFooBazType = false; def foundProcessingObjectFactoryType = false; def foundProcessingPackageInfoType = false; // Act for (line in lines) { String trimmedLine = line.trim() if (!trimmedLine.isEmpty()) { // Check that the appropriate "ignored" lines are present if (trimmedLine.contains(expectedIgnoreLine)) { foundIgnoreLine = true; } // Check that the appropriate "accepted" lines are present if (trimmedLine.contains(acceptedLinePrefix)) { if (trimmedLine.contains(acceptedSomeOtherPath)) { foundSomeOtherPathLine = true; } else if (trimmedLine.contains(acceptedFooGnatTxt)) { foundFooGnatTextLine = true; } } // Check what was processed if (isProcessingFileLine(trimmedLine, "FooBar")) { foundProcessingFooBarType = true; } else if (isProcessingFileLine(trimmedLine, "FooBaz")) { foundProcessingFooBazType = true; } else if (isProcessingFileLine(trimmedLine, "ObjectFactory")) { foundProcessingObjectFactoryType = true; } else if (isProcessingFileLine(trimmedLine, "package-info")) { foundProcessingPackageInfoType = true; } else if (isProcessingFileLine(trimmedLine, "ShouldBeIgnoredAddressType")) { foundProcessingShouldBeIgnoredAddressType = true; } else if (isProcessingFileLine(trimmedLine, "AddressTypeFromGnatTxt")) { foundProcessingAddressTypeFromGnatTxtType = true; } } } // Assert def missingRequired(value) { return "Missing required text: [" + value.replace("/", sep) + "]"; } def illegalButPresent(value) { return "Found illegal statement: [" + value.replace("/", sep) + "]"; } assert foundIgnoreLine, missingRequired(expectedIgnoreLine); assert foundSomeOtherPathLine, missingRequired(acceptedSomeOtherPath); assert foundFooGnatTextLine, missingRequired(acceptedFooGnatTxt); assert !foundProcessingShouldBeIgnoredAddressType, illegalButPresent("se/west/ShouldBeIgnoredAddressType.java"); assert foundProcessingFooBazType, missingRequired("se/west/FooBaz.java"); assert foundProcessingAddressTypeFromGnatTxtType, missingRequired("se/west/AddressTypeFromGnatTxt.java"); assert foundProcessingFooBarType, missingRequired("se/west/FooBar.java"); assert foundProcessingObjectFactoryType, missingRequired("se/west/ObjectFactory.java"); assert foundProcessingPackageInfoType, missingRequired("se/west/package-info.java")jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/000077500000000000000000000000001351100213400277425ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/pom.xml000066400000000000000000000054131351100213400312620ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-handles-spaces-in-filenames 1.0-SNAPSHOT Purpose: Test of extra arguments configuration containing spaces. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/src/000077500000000000000000000000001351100213400305315ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/src/main/000077500000000000000000000000001351100213400314555ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/src/main/xjb/000077500000000000000000000000001351100213400322405ustar00rootroot00000000000000spaced filename.xjb000066400000000000000000000010731351100213400356670ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/src/main/xjb jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/src/main/xsd/000077500000000000000000000000001351100213400322535ustar00rootroot00000000000000address.xsd000066400000000000000000000010411351100213400343350ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/src/main/xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-handles-spaces-in-filenames/verify.groovy000066400000000000000000000105061351100213400325170ustar00rootroot00000000000000import java.util.regex.Pattern /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Assemble File buildLog = new File(basedir, 'build.log') List lines = buildLog.readLines(); String pathToLeafPackage = "target/generated-sources/jaxb/com/example/myschema/"; File expectedAddressTypeFile = new File(basedir, pathToLeafPackage + "AddressType.java"); File expectedObjectFactoryFile = new File(basedir, pathToLeafPackage + "ObjectFactory.java"); /* +=================== [11 XJC Arguments] (Mac/Linux version) | | [0]: -xmlschema | [1]: -encoding | [2]: UTF-8 | [3]: -d | [4]: /Users/lj/Development/Projects/Codehaus/lennartj-jaxb2-maven-plugin/target/it/xjc-handles-spaces-in-filenames/target/generated-sources/jaxb | [5]: -extension | [6]: -episode | [7]: /Users/lj/Development/Projects/Codehaus/lennartj-jaxb2-maven-plugin/target/it/xjc-handles-spaces-in-filenames/target/generated-sources/jaxb/META-INF/sun-jaxb.episode | [8]: -b | [9]: /Users/lj/Development/Projects/Codehaus/lennartj-jaxb2-maven-plugin/target/it/xjc-handles-spaces-in-filenames/src/main/xjb/spaced filename.xjb | [10]: /Users/lj/Development/Projects/Codehaus/lennartj-jaxb2-maven-plugin/target/it/xjc-handles-spaces-in-filenames/src/main/xsd/address.xsd | +=================== [End 11 XJC Arguments] +=================== [11 XJC Arguments] (Windows version) | | [0]: -xmlschema | [1]: -encoding | [2]: UTF-8 | [3]: -d | [4]: E:\Mojohaus\jaxb2-maven-plugin\target\it\xjc-handles-spaces-in-filenames\target\generated-sources\jaxb | [5]: -extension | [6]: -episode | [7]: E:\Mojohaus\jaxb2-maven-plugin\target\it\xjc-handles-spaces-in-filenames\target\generated-sources\jaxb\META-INF\sun-jaxb.episode | [8]: -b | [9]: E:\Mojohaus\jaxb2-maven-plugin\target\it\xjc-handles-spaces-in-filenames\src\main\xjb\spaced filename.xjb | [10]: /E:/Mojohaus/jaxb2-maven-plugin/target/it/xjc-handles-spaces-in-filenames/src/main/xsd/address.xsd | +=================== [End 11 XJC Arguments] */ def sep = Pattern.quote(System.getProperty("file.separator")); def xjcArgumentPatternPrefix = "\\| \\[\\p{Digit}+\\]: "; Pattern expectedBArgumentPattern = Pattern.compile(xjcArgumentPatternPrefix + "\\-b"); Pattern expectedXjbArgumentPattern = Pattern.compile(xjcArgumentPatternPrefix + ".*src/main/xjb/spaced filename.xjb".replace("/", sep)); Pattern expectedSourceArgumentPattern = Pattern.compile(xjcArgumentPatternPrefix + ".*src/main/xsd/address.xsd"); boolean foundBArgument = false; boolean foundXjbArgument = false; boolean foundSourceArgument = false; // Act for (line in lines) { String trimmedLine = line.trim() if (trimmedLine.isEmpty()) { continue }; if(!foundBArgument && expectedBArgumentPattern.matcher(trimmedLine).matches()) { foundBArgument = true; } if(!foundXjbArgument && expectedXjbArgumentPattern.matcher(trimmedLine).matches()) { foundXjbArgument = true; } if(!foundSourceArgument && expectedSourceArgumentPattern.matcher(trimmedLine).matches()) { foundSourceArgument = true; } } // Assert def missingRequired(Pattern pattern) { return "Missing required pattern: [" + pattern.pattern() + "]" ; } assert foundBArgument, missingRequired(expectedBArgumentPattern); assert foundXjbArgument, missingRequired(expectedXjbArgumentPattern); assert foundSourceArgument, missingRequired(expectedSourceArgumentPattern); assert expectedAddressTypeFile.exists() && expectedAddressTypeFile.isFile(), "Missing required file: [" + expectedAddressTypeFile.getPath() + "]" ; assert expectedObjectFactoryFile.exists() && expectedObjectFactoryFile.isFile(), "Missing required file: [" + expectedObjectFactoryFile.getPath() + "]" ;jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-include-xsds-in-artifact/000077500000000000000000000000001351100213400273045ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-include-xsds-in-artifact/pom.xml000066400000000000000000000056171351100213400306320ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its mjaxb-18 1.0-SNAPSHOT Purpose: Validate that XSDs are included in the resulting artifact when the xsdPathWithinArtifact parameter is supplied. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-include-xsds-in-artifact/src/000077500000000000000000000000001351100213400300735ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-include-xsds-in-artifact/src/main/000077500000000000000000000000001351100213400310175ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-include-xsds-in-artifact/src/main/xsd/000077500000000000000000000000001351100213400316155ustar00rootroot00000000000000address.xsd000066400000000000000000000010411351100213400336770ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-include-xsds-in-artifact/src/main/xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-include-xsds-in-artifact/verify.groovy000066400000000000000000000016161351100213400320630ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ File outputSchema = new File(basedir, 'target/classes/xsd/address.xsd') assert outputSchema.exists() jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-main/000077500000000000000000000000001351100213400234275ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-main/pom.xml000066400000000000000000000053471351100213400247550ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-main 1.0-SNAPSHOT Test of basic usage of the xjc mojo. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-main/src/000077500000000000000000000000001351100213400242165ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-main/src/main/000077500000000000000000000000001351100213400251425ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-main/src/main/xsd/000077500000000000000000000000001351100213400257405ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-main/src/main/xsd/address.xsd000066400000000000000000000010411351100213400301010ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-main/verify.groovy000066400000000000000000000025111351100213400262010ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ File addressTypeSource = new File( basedir,'target/generated-sources/jaxb/com/example/myschema/AddressType.java' ) assert addressTypeSource.exists() File testSources = new File( basedir,'target/generated-test-sources/jaxb/' ) assert !testSources.exists() File addressTypeCompiled = new File( basedir,'target/classes/com/example/myschema/AddressType.class' ) assert addressTypeCompiled.exists() File addressTypeCopiedSource = new File( basedir,'target/classes/com/example/myschema/AddressType.java' ) assert !addressTypeCopiedSource.exists() jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-mark-generated/000077500000000000000000000000001351100213400253715ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-mark-generated/pom.xml000066400000000000000000000061701351100213400267120ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-mark-generated 1.0-SNAPSHOT Purpose: Test that addGeneratedAnnotation and noGeneratedHeaderComments works properly. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 javax.annotation javax.annotation-api 1.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema true true jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-mark-generated/src/000077500000000000000000000000001351100213400261605ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-mark-generated/src/main/000077500000000000000000000000001351100213400271045ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-mark-generated/src/main/xsd/000077500000000000000000000000001351100213400277025ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-mark-generated/src/main/xsd/address.xsd000066400000000000000000000010411351100213400320430ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-mark-generated/verify.groovy000066400000000000000000000031461351100213400301500ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ File addressType = new File(basedir, 'target/generated-sources/jaxb/com/example/myschema/AddressType.java') assert addressType.exists() File testSources = new File(basedir, 'target/generated-test-sources/jaxb/') assert !testSources.exists() File addressTypeCompiled = new File(basedir, 'target/classes/com/example/myschema/AddressType.class') assert addressTypeCompiled.exists() // Validate that the @Generated annotations are injected into the source file. int hitCount = 0; List lines = addressType.readLines(); for (line in lines) { String trimmedLine = line.trim() if (trimmedLine.isEmpty()) { continue }; if (trimmedLine.startsWith("@Generated(value = \"com.sun.tools.xjc.Driver\"")) { hitCount++; } } assert 19 == hitCount, "Found [" + hitCount + "] @Generated annotations. (Expected 19)."; jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-executions/000077500000000000000000000000001351100213400265225ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-executions/pom.xml000066400000000000000000000122021351100213400300340ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-multiple-xsd-specified 1.0-SNAPSHOT Purpose: Test of multiple executions for the XjcMojo, and excluding different filesets from each. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc-exec1 xjc b\.xsd com.example.schema.a xjc-exec2 xjc a\.xsd com.example.schema.b false jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-executions/src/000077500000000000000000000000001351100213400273115ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-executions/src/main/000077500000000000000000000000001351100213400302355ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-executions/src/main/xsd/000077500000000000000000000000001351100213400310335ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-executions/src/main/xsd/a.xsd000066400000000000000000000006171351100213400317770ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-executions/src/main/xsd/b.xsd000066400000000000000000000006171351100213400320000ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-executions/verify.groovy000066400000000000000000000020301351100213400312700ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ File aType = new File( basedir,'target/generated-sources/jaxb/com/example/schema/a/AType.java' ) assert aType.exists() File bType = new File( basedir,'target/generated-sources/jaxb/com/example/schema/b/BType.java' ) assert bType.exists() jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/000077500000000000000000000000001351100213400270635ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/pom.xml000066400000000000000000000071151351100213400304040ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-multiple-xsd-specified 1.0-SNAPSHOT Purpose: Test of using multiple XSD files for an XJC compilation. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc d\.xsd com.example.myschema jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/src/000077500000000000000000000000001351100213400276525ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/src/main/000077500000000000000000000000001351100213400305765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/src/main/xsd/000077500000000000000000000000001351100213400313745ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/src/main/xsd/a.xsd000066400000000000000000000005471351100213400323420ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/src/main/xsd/b.xsd000066400000000000000000000005471351100213400323430ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/src/main/xsd/c.xsd000066400000000000000000000005471351100213400323440ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/src/main/xsd/d.xsd000066400000000000000000000005471351100213400323450ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-multiple-xsd-specified/verify.bsh000066400000000000000000000023711351100213400310700ustar00rootroot00000000000000import java.io.*; import java.util.*; import java.util.jar.*; try { File jaxbDir = new File( basedir, "target/generated-sources/jaxb" ); if ( !jaxbDir.exists() || !jaxbDir.isDirectory() ) { System.err.println( "Could not find directory for JAXB generated sources: " + jaxbDir ); return false; } File file; file = new File( jaxbDir, "com/example/myschema/AType.java" ); if ( !file.exists() || file.isDirectory() ) { System.err.println( "Could not find file: " + file ); return false; } file = new File( jaxbDir, "com/example/myschema/BType.java" ); if ( !file.exists() || file.isDirectory() ) { System.err.println( "Could not find file: " + file ); return false; } file = new File( jaxbDir, "com/example/myschema/CType.java" ); if ( !file.exists() || file.isDirectory() ) { System.err.println( "Could not find file: " + file ); return false; } file = new File( jaxbDir, "com/example/myschema/DType.java" ); if ( file.exists() ) { System.err.println( "File '" + file + "' found, which shouldn't exist" ); return false; } } catch( Throwable t ) { t.printStackTrace(); return false; } return true; jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-platform-encoding/000077500000000000000000000000001351100213400261135ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-platform-encoding/pom.xml000066400000000000000000000052531351100213400274350ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-platform-encoding 1.0-SNAPSHOT Test of basic usage when platform encoding is used (no encoding specified) jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-platform-encoding/src/000077500000000000000000000000001351100213400267025ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-platform-encoding/src/main/000077500000000000000000000000001351100213400276265ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-platform-encoding/src/main/xsd/000077500000000000000000000000001351100213400304245ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-platform-encoding/src/main/xsd/address.xsd000066400000000000000000000010411351100213400325650ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-test/000077500000000000000000000000001351100213400234625ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-test/pom.xml000066400000000000000000000046571351100213400250130ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-test 1.0-SNAPSHOT Test of basic usage of the testXjc mojo. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc-test testXjc com.example.myschema jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-test/src/000077500000000000000000000000001351100213400242515ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-test/src/test/000077500000000000000000000000001351100213400252305ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-test/src/test/xsd/000077500000000000000000000000001351100213400260265ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-test/src/test/xsd/address.xsd000066400000000000000000000010411351100213400301670ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-test/verify.groovy000066400000000000000000000022561351100213400262420ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ File addressType = new File( basedir,'target/generated-test-sources/jaxb/com/example/myschema/AddressType.java' ) assert addressType.exists() File mainSources = new File( basedir,'target/generated-sources/jaxb/' ) assert !mainSources.exists() File addressTypeCompiled = new File( basedir,'target/test-classes/com/example/myschema/AddressType.class' ) assert addressTypeCompiled.exists() jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-with-explicit-locale/000077500000000000000000000000001351100213400265325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-with-explicit-locale/pom.xml000066400000000000000000000061201351100213400300460ustar00rootroot00000000000000 4.0.0 org.codehaus.mojo.jaxb2.its xjc-mark-generated 1.0-SNAPSHOT Purpose: Test that addGeneratedAnnotation and noGeneratedHeaderComments works properly. UTF-8 jakarta.xml.bind jakarta.xml.bind-api 2.3.2 javax.annotation javax.annotation-api 1.3.2 org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin @project.version@ xjc xjc com.example.myschema true fr jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-with-explicit-locale/src/000077500000000000000000000000001351100213400273215ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-with-explicit-locale/src/main/000077500000000000000000000000001351100213400302455ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-with-explicit-locale/src/main/xsd/000077500000000000000000000000001351100213400310435ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-with-explicit-locale/src/main/xsd/address.xsd000066400000000000000000000010411351100213400332040ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/it/xjc-with-explicit-locale/verify.groovy000066400000000000000000000030451351100213400313070ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ File addressType = new File(basedir, 'target/generated-sources/jaxb/com/example/myschema/AddressType.java') assert addressType.exists() File testSources = new File(basedir, 'target/generated-test-sources/jaxb/') assert !testSources.exists() File addressTypeCompiled = new File(basedir, 'target/classes/com/example/myschema/AddressType.class') assert addressTypeCompiled.exists() // Validate that XJC ran with French locale. int hitCount = 0; List lines = addressType.readLines(); for (line in lines) { String trimmedLine = line.trim() if (trimmedLine.isEmpty()) { continue }; if (trimmedLine.endsWith("Classe Java pour AddressType complex type.")) { hitCount++; } } assert 1 == hitCount, "Found [" + hitCount + "] . (Expected 1)."; jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/000077500000000000000000000000001351100213400222315ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/000077500000000000000000000000001351100213400231525ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/000077500000000000000000000000001351100213400237415ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/000077500000000000000000000000001351100213400255345ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/000077500000000000000000000000001351100213400265005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/000077500000000000000000000000001351100213400275065ustar00rootroot00000000000000AbstractJaxbMojo.java000066400000000000000000000730371351100213400335010ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2package org.codehaus.mojo.jaxb2; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.model.Resource; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.environment.EnvironmentFacet; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.pattern.FileFilterAdapter; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.codehaus.mojo.jaxb2.shared.version.DependencyInfo; import org.codehaus.mojo.jaxb2.shared.version.DependsFileParser; import org.sonatype.plexus.build.incremental.BuildContext; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; /** * Abstract Mojo which collects common infrastructure, required and needed * by all subclass Mojos in the JAXB2 maven plugin codebase. * * @author Lennart Jörelid */ public abstract class AbstractJaxbMojo extends AbstractMojo { /** * Standard name of the generated JAXB episode file. */ public static final String STANDARD_EPISODE_FILENAME = "sun-jaxb.episode"; /** * Standard name of the package-info.java file which may contain * JAXB annotations and Package JavaDoc. */ public static final String PACKAGE_INFO_FILENAME = "package-info.java"; /** * Platform-independent newline control string. */ public static final String NEWLINE = System.getProperty("line.separator"); /** * Pattern matching strings containing whitespace (or consisting only of whitespace). */ public static final Pattern CONTAINS_WHITESPACE = Pattern.compile("(\\S*\\s+\\S*)+", Pattern.UNICODE_CASE); /** *

Standard excludes Filters for all Java generator Mojos. * The List is unmodifiable, and contains Filters on the following form:

*
     *     
     *         // The standard exclude filters contain simple, exclude pattern filters.
     *         final List<Filter<File>> tmp = new ArrayList<Filter<File>>();
     *         tmp.add(new PatternFileFilter(Arrays.asList({"README.*", "\\.xml", "\\.txt"}), true));
     *         tmp.add(new FileFilterAdapter(new FileFilter() {
     *
     *             @Override
     *             public boolean accept(final File aFileOrDir) {
     *
     *                 // Check sanity
     *                 if (aFileOrDir == null) {
     *                     return false;
     *                 }
     *
     *                 final String name = aFileOrDir.getName();
     *
     *                 // Ignore hidden files and CVS directories
     *                 return name.startsWith(".")
     *                         || (aFileOrDir.isDirectory() && name.equals("CVS"));
     *
     *             }
     *         }));
     *     
     * 
*

Note! Since the plugin is currently developed in jdk 1.7-compliant code, we cannot * use lambdas within Filters just yet.

*/ public static final List> STANDARD_EXCLUDE_FILTERS; private static final List RELEVANT_GROUPIDS = Arrays.asList("org.glassfish.jaxb", "jakarta.xml.bind"); private static final String OWN_ARTIFACT_ID = "jaxb2-maven-plugin"; private static final String SYSTEM_FILE_ENCODING_PROPERTY = "file.encoding"; private static final String[] STANDARD_EXCLUDE_SUFFIXES = {"README.*", "\\.xml", "\\.txt"}; private static final String[] STANDARD_PRELOADED_CLASSES = { "com.sun.tools.xjc.addon.episode.package-info", "com.sun.tools.xjc.reader.xmlschema.bindinfo.package-info", "com.sun.xml.bind.v2.model.core.package-info", "com.sun.xml.bind.v2.model.runtime.package-info", "com.sun.xml.bind.v2.schemagen.episode.package-info", "com.sun.xml.bind.v2.schemagen.xmlschema.package-info" }; static { // The standard exclude filters contain simple, exclude pattern filters. final List> tmp = new ArrayList>(); tmp.add(new PatternFileFilter(Arrays.asList(STANDARD_EXCLUDE_SUFFIXES), true)); tmp.add(new FileFilterAdapter(new FileFilter() { @Override public boolean accept(final File aFileOrDir) { // Check sanity if (aFileOrDir == null) { return false; } final String name = aFileOrDir.getName(); // Ignore hidden files and CVS directories return name.startsWith(".") || (aFileOrDir.isDirectory() && name.equals("CVS")); } })); // Make STANDARD_EXCLUDE_FILTERS be unmodifiable. STANDARD_EXCLUDE_FILTERS = Collections.unmodifiableList(tmp); // TODO: These are hardcoded. Move to overridable using a system property? // Preload relevant package-info classes to work around MNG-6506. try { final ClassLoader cl = AbstractJaxbMojo.class.getClassLoader(); for(String current : STANDARD_PRELOADED_CLASSES) { cl.loadClass(current); } } catch (ClassNotFoundException ex) { throw new Error(ex); } } /** * The Plexus BuildContext is used to identify files or directories modified since last build, * implying functionality used to define if java generation must be performed again. */ @Component private BuildContext buildContext; /** * The injected Maven project. */ @Parameter(defaultValue = "${project}", readonly = true) private MavenProject project; /** * Note that the execution parameter will be injected ONLY if this plugin is executed as part * of a maven standard lifecycle - as opposed to directly invoked with a direct invocation. * When firing this mojo directly (i.e. {@code mvn xjc:something} or {@code mvn schemagen:something}), the * {@code execution} object will not be injected. */ @Parameter(defaultValue = "${mojoExecution}", readonly = true) private MojoExecution execution; /** *

The directory where the staleFile is found. * The staleFile assists in determining if re-generation of JAXB build products is required.

*

While it is permitted to re-define the staleFileDirectory, it is recommended to keep it * below the ${project.build.directory}, to ensure that JAXB code or XSD re-generation * occurs after cleaning the project.

* * @since 2.0 */ @Parameter(defaultValue = "${project.build.directory}/jaxb2", readonly = true, required = true) protected File staleFileDirectory; /** *

Defines the encoding used by XJC (for generating Java Source files) and schemagen (for generating XSDs). * The corresponding argument parameter for XJC and SchemaGen is: {@code encoding}.

*

The algorithm for finding the encoding to use is as follows * (where the first non-null value found is used for encoding): *

    *
  1. If the configuration property is explicitly given within the plugin's configuration, use that value.
  2. *
  3. If the Maven property project.build.sourceEncoding is defined, use its value.
  4. *
  5. Otherwise use the value from the system property file.encoding.
  6. *
*

* * @see #getEncoding(boolean) * @since 2.0 */ @Parameter(defaultValue = "${project.build.sourceEncoding}") private String encoding; /** *

A Locale definition to create and set the system (default) Locale when the XJB or SchemaGen tools executes. * The Locale will be reset to its default value after the execution of XJC or SchemaGen is complete.

*

The configuration parameter must be supplied on the form {@code language[,country[,variant]]}, * such as {@code sv,SE} or {@code fr}. Refer to * {@code org.codehaus.mojo.jaxb2.shared.environment.locale.LocaleFacet.createFor(String, Log)} for further * information.

*

Example (assigns french locale):

*
     *     
     *         <configuration>
     *              <locale>fr</locale>
     *         </configuration>
     *     
     * 
* * @see org.codehaus.mojo.jaxb2.shared.environment.locale.LocaleFacet#createFor(String, Log) * @see Locale#getAvailableLocales() * @since 2.2 */ @Parameter(required = false) protected String locale; /** *

Defines a set of extra EnvironmentFacet instances which are used to further configure the * ToolExecutionEnvironment used by this plugin to fire XJC or SchemaGen.

*

Example: If you implement the EnvironmentFacet interface in the class * {@code org.acme.MyCoolEnvironmentFacetImplementation}, its {@code setup()} method is called before the * XJC or SchemaGen tools are executed to setup some facet of their Execution environment. Correspondingly, the * {@code restore()} method in your {@code org.acme.MyCoolEnvironmentFacetImplementation} class is invoked after * the XJC or SchemaGen execution terminates.

*
     *     
     *         <configuration>
     *         ...
     *              <extraFacets>
     *                  <extraFacet implementation="org.acme.MyCoolEnvironmentFacetImplementation" />
     *              </extraFacets>
     *         ...
     *         </configuration>
     *     
     * 
* * @see EnvironmentFacet * @see org.codehaus.mojo.jaxb2.shared.environment.ToolExecutionEnvironment#add(EnvironmentFacet) * @since 2.2 */ @Parameter(required = false) protected List extraFacets; /** * Adds the supplied Resource to the project using the appropriate scope (i.e. resource or testResource) * depending on the exact implementation of this AbstractJaxbMojo. * * @param resource The resource to add. */ protected abstract void addResource(final Resource resource); /** * The Plexus BuildContext is used to identify files or directories modified since last build, * implying functionality used to define if java generation must be performed again. * * @return the active Plexus BuildContext. */ protected final BuildContext getBuildContext() { return getInjectedObject(buildContext, "buildContext"); } /** * @return The active MavenProject. */ protected final MavenProject getProject() { return getInjectedObject(project, "project"); } /** * @return The active MojoExecution. */ public MojoExecution getExecution() { return getInjectedObject(execution, "execution"); } /** * {@inheritDoc} */ @Override public final void execute() throws MojoExecutionException, MojoFailureException { // 0) Get the log and its relevant level final Log log = getLog(); final boolean isDebugEnabled = log.isDebugEnabled(); final boolean isInfoEnabled = log.isInfoEnabled(); // 1) Should we skip execution? if (shouldExecutionBeSkipped()) { if (isDebugEnabled) { log.debug("Skipping execution, as instructed."); } return; } // 2) Printout relevant version information. if (isDebugEnabled) { logPluginAndJaxbDependencyInfo(); } // 3) Are generated files stale? if (isReGenerationRequired()) { if (performExecution()) { // As instructed by the performExecution() method, update // the timestamp of the stale File. updateStaleFileTimestamp(); // Hack to support M2E buildContext.refresh(getOutputDirectory()); } else if (isInfoEnabled) { log.info("Not updating staleFile timestamp as instructed."); } } else if (isInfoEnabled) { log.info("No changes detected in schema or binding files - skipping JAXB generation."); } // 4) If the output directories exist, add them to the MavenProject's source directories if (getOutputDirectory().exists() && getOutputDirectory().isDirectory()) { final String canonicalPathToOutputDirectory = FileSystemUtilities.getCanonicalPath(getOutputDirectory()); if (log.isDebugEnabled()) { log.debug("Adding existing JAXB outputDirectory [" + canonicalPathToOutputDirectory + "] to Maven's sources."); } // Add the output Directory. getProject().addCompileSourceRoot(canonicalPathToOutputDirectory); } } /** * Implement this method to check if this AbstractJaxbMojo should skip executing altogether. * * @return {@code true} to indicate that this AbstractJaxbMojo should bail out of its execute method. */ protected abstract boolean shouldExecutionBeSkipped(); /** * @return {@code true} to indicate that this AbstractJaxbMojo should be run since its generated files were * either stale or not present, and {@code false} otherwise. */ protected abstract boolean isReGenerationRequired(); /** *

Implement this method to perform this Mojo's execution. * This method will only be called if {@code !shouldExecutionBeSkipped() && isReGenerationRequired()}.

* * @return {@code true} if the timestamp of the stale file should be updated. * @throws MojoExecutionException if an unexpected problem occurs. * Throwing this exception causes a "BUILD ERROR" message to be displayed. * @throws MojoFailureException if an expected problem (such as a compilation failure) occurs. * Throwing this exception causes a "BUILD FAILURE" message to be displayed. */ protected abstract boolean performExecution() throws MojoExecutionException, MojoFailureException; /** * Override this method to acquire a List holding all URLs to the sources which this * AbstractJaxbMojo should use to produce its output (XSDs files for AbstractXsdGeneratorMojos and * Java Source Code for AbstractJavaGeneratorMojos). * * @return A non-null List holding URLs to sources used by this AbstractJaxbMojo to produce its output. */ protected abstract List getSources(); /** * Retrieves the directory where the generated files should be written to. * * @return the directory where the generated files should be written to. */ protected abstract File getOutputDirectory(); /** * Retrieves the configured List of paths from which this AbstractJaxbMojo and its internal toolset * (XJC or SchemaGen) should read bytecode classes. * * @return the configured List of paths from which this AbstractJaxbMojo and its internal toolset (XJC or * SchemaGen) should read classes. * @throws org.apache.maven.plugin.MojoExecutionException if the classpath could not be retrieved. */ protected abstract List getClasspath() throws MojoExecutionException; /** * Convenience method to invoke when some plugin configuration is incorrect. * Will output the problem as a warning with some degree of log formatting. * * @param propertyName The name of the problematic property. * @param description The problem description. */ @SuppressWarnings("all") protected void warnAboutIncorrectPluginConfiguration(final String propertyName, final String description) { final StringBuilder builder = new StringBuilder(); builder.append("\n+=================== [Incorrect Plugin Configuration Detected]\n"); builder.append("|\n"); builder.append("| Property : " + propertyName + "\n"); builder.append("| Problem : " + description + "\n"); builder.append("|\n"); builder.append("+=================== [End Incorrect Plugin Configuration Detected]\n\n"); getLog().warn(builder.toString().replace("\n", NEWLINE)); } /** * @param arguments The final arguments to be passed to a JAXB tool (XJC or SchemaGen). * @param toolName The name of the tool. * @return the arguments, untouched. */ protected final String[] logAndReturnToolArguments(final String[] arguments, final String toolName) { // Check sanity Validate.notNull(arguments, "arguments"); if (getLog().isDebugEnabled()) { final StringBuilder argBuilder = new StringBuilder(); argBuilder.append("\n+=================== [" + arguments.length + " " + toolName + " Arguments]\n"); argBuilder.append("|\n"); for (int i = 0; i < arguments.length; i++) { argBuilder.append("| [").append(i).append("]: ").append(arguments[i]).append("\n"); } argBuilder.append("|\n"); argBuilder.append("+=================== [End " + arguments.length + " " + toolName + " Arguments]\n\n"); getLog().debug(argBuilder.toString().replace("\n", NEWLINE)); } // All done. return arguments; } /** * Retrieves the last name part of the stale file. * The full name of the stale file will be generated by pre-pending {@code "." + getExecution().getExecutionId()} * before this staleFileName. * * @return The name of the stale file used by this AbstractJavaGeneratorMojo to detect staleness amongst its * generated files. */ protected abstract String getStaleFileName(); /** * Acquires the staleFile for this execution * * @return the staleFile (used to define where) for this execution */ protected final File getStaleFile() { final String staleFileName = "." + (getExecution() == null ? "nonExecutionJaxb" : getExecution().getExecutionId()) + "-" + getStaleFileName(); return new File(staleFileDirectory, staleFileName); } /** *

The algorithm for finding the encoding to use is as follows (where the first non-null value found * is used for encoding):

*
    *
  1. If the configuration property is explicitly given within the plugin's configuration, use that value.
  2. *
  3. If the Maven property project.build.sourceEncoding is defined, use its value.
  4. *
  5. Otherwise use the value from the system property file.encoding.
  6. *
* * @param warnIfPlatformEncoding Defines if a warning should be logged if encoding is not configured but * the platform encoding (system property {@code file.encoding}) is used * @return The encoding to be used by this AbstractJaxbMojo and its tools. * @see #encoding */ protected final String getEncoding(final boolean warnIfPlatformEncoding) { // Harvest information final boolean configuredEncoding = encoding != null; final String fileEncoding = System.getProperty(SYSTEM_FILE_ENCODING_PROPERTY); final String effectiveEncoding = configuredEncoding ? encoding : fileEncoding; // Should we warn if using platform encoding (i.e. platform dependent)? if (!configuredEncoding && warnIfPlatformEncoding) { getLog().warn("Using platform encoding [" + effectiveEncoding + "], i.e. build is platform dependent!"); } else if (getLog().isDebugEnabled()) { getLog().debug("Using " + (configuredEncoding ? "explicitly configured" : "system property") + " encoding [" + effectiveEncoding + "]"); } // All Done. return effectiveEncoding; } /** * Retrieves a File to the JAXB Episode (which is normally written during the XJC process). * Moreover, ensures that the parent directory of that File is created, to enable writing the File. * * @param episodeFileName {@code null} to indicate that the standard episode file name ("sun-jaxb.episode") * should be used, and otherwise a non-empty name which should be used * as the episode file name. * @return A non-null File where the JAXB episode file should be written. * @throws MojoExecutionException if the parent directory of the episode file could not be created. */ protected File getEpisodeFile(final String episodeFileName) throws MojoExecutionException { // Get the execution ID final String executionID = getExecution() != null && getExecution().getExecutionId() != null ? getExecution().getExecutionId() : null; final String effectiveEpisodeFileName = episodeFileName == null ? (executionID == null ? STANDARD_EPISODE_FILENAME : "episode_" + executionID) : episodeFileName; if (effectiveEpisodeFileName.isEmpty()) { throw new MojoExecutionException("Cannot handle null or empty JAXB Episode filename. " + "Check 'episodeFileName' configuration property."); } // Find or create the episode directory. final Path episodePath; final File generatedJaxbEpisodeDirectory; try { final Path path = Paths.get(getOutputDirectory().getAbsolutePath(), "META-INF", "JAXB"); episodePath = java.nio.file.Files.createDirectories(path); generatedJaxbEpisodeDirectory = episodePath.toFile(); if (getLog().isInfoEnabled()) { getLog().info("Created EpisodePath [" + episodePath.toString() + "]: " + (generatedJaxbEpisodeDirectory.exists() && generatedJaxbEpisodeDirectory.isDirectory())); } } catch (IOException e) { throw new MojoExecutionException("Could not create output directory.", e); } if (!generatedJaxbEpisodeDirectory.exists() || !generatedJaxbEpisodeDirectory.isDirectory()) { throw new MojoExecutionException("Could not create directory [" + episodePath.toString() + "]"); } // Is there already an episode file here? File episodeFile = new File(generatedJaxbEpisodeDirectory, effectiveEpisodeFileName + ".xjb"); final AtomicInteger index = new AtomicInteger(1); while (episodeFile.exists()) { episodeFile = new File(generatedJaxbEpisodeDirectory, effectiveEpisodeFileName + "_" + index.getAndIncrement() + ".xjb"); } // Add the (generated) outputDirectory to the Resources. final Resource outputDirectoryResource = new Resource(); outputDirectoryResource.setDirectory(getOutputDirectory().getAbsolutePath()); outputDirectoryResource.setIncludes(Collections.singletonList("**/" + episodeFile.getName())); this.addResource(outputDirectoryResource); // All Done. return episodeFile; } // // Private helpers // private void logPluginAndJaxbDependencyInfo() { if (getLog().isDebugEnabled()) { final StringBuilder builder = new StringBuilder(); builder.append("\n+=================== [Brief Plugin Build Dependency Information]\n"); builder.append("|\n"); builder.append("| Note: These dependencies pertain to what was used to build *the plugin*.\n"); builder.append("| Check project dependencies to see the ones used in *your build*.\n"); builder.append("|\n"); // Find the dependency and version information within the dependencies.properties file. final SortedMap versionMap = DependsFileParser.getVersionMap(OWN_ARTIFACT_ID); builder.append("|\n"); builder.append("| Plugin's own information\n"); builder.append("| GroupId : " + versionMap.get(DependsFileParser.OWN_GROUPID_KEY) + "\n"); builder.append("| ArtifactID : " + versionMap.get(DependsFileParser.OWN_ARTIFACTID_KEY) + "\n"); builder.append("| Version : " + versionMap.get(DependsFileParser.OWN_VERSION_KEY) + "\n"); builder.append("| Buildtime : " + versionMap.get(DependsFileParser.BUILDTIME_KEY) + "\n"); builder.append("|\n"); builder.append("| Plugin's JAXB-related dependencies\n"); builder.append("|\n"); final SortedMap diMap = DependsFileParser.createDependencyInfoMap(versionMap); int dependencyIndex = 0; for (Map.Entry current : diMap.entrySet()) { final String key = current.getKey().trim(); for (String currentRelevantGroupId : RELEVANT_GROUPIDS) { if (key.startsWith(currentRelevantGroupId)) { final DependencyInfo di = current.getValue(); builder.append("| " + (++dependencyIndex) + ") [" + di.getArtifactId() + "]\n"); builder.append("| GroupId : " + di.getGroupId() + "\n"); builder.append("| ArtifactID : " + di.getArtifactId() + "\n"); builder.append("| Version : " + di.getVersion() + "\n"); builder.append("| Scope : " + di.getScope() + "\n"); builder.append("| Type : " + di.getType() + "\n"); builder.append("|\n"); } } } builder.append("+=================== [End Brief Plugin Build Dependency Information]\n\n"); getLog().debug(builder.toString().replace("\n", NEWLINE)); } } private T getInjectedObject(final T objectOrNull, final String objectName) { if (objectOrNull == null) { getLog().error( "Found null '" + objectName + "', implying that Maven @Component injection was not done properly."); } return objectOrNull; } private void updateStaleFileTimestamp() throws MojoExecutionException { final File staleFile = getStaleFile(); if (!staleFile.exists()) { // Ensure that the staleFileDirectory exists FileSystemUtilities.createDirectory(staleFile.getParentFile(), false); try { staleFile.createNewFile(); if (getLog().isDebugEnabled()) { getLog().debug("Created staleFile [" + FileSystemUtilities.getCanonicalPath(staleFile) + "]"); } } catch (IOException e) { throw new MojoExecutionException("Could not create staleFile.", e); } } else { if (!staleFile.setLastModified(System.currentTimeMillis())) { getLog().warn("Failed updating modification time of staleFile [" + FileSystemUtilities.getCanonicalPath(staleFile) + "]"); } } } /** * Prints out the system properties to the Maven Log at Debug level. */ protected void logSystemPropertiesAndBasedir() { if (getLog().isDebugEnabled()) { final StringBuilder builder = new StringBuilder(); builder.append("\n+=================== [System properties]\n"); builder.append("|\n"); // Sort the system properties final SortedMap props = new TreeMap(); props.put("basedir", FileSystemUtilities.getCanonicalPath(getProject().getBasedir())); for (Map.Entry current : System.getProperties().entrySet()) { props.put("" + current.getKey(), current.getValue()); } for (Map.Entry current : props.entrySet()) { builder.append("| [" + current.getKey() + "]: " + current.getValue() + "\n"); } builder.append("|\n"); builder.append("+=================== [End System properties]\n"); // All done. getLog().debug(builder.toString().replace("\n", NEWLINE)); } } } NoSchemasException.java000066400000000000000000000017521351100213400340360ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2package org.codehaus.mojo.jaxb2; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * @author olamy * @version $Id$ */ public class NoSchemasException extends Exception { // Do Nothing } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/javageneration/000077500000000000000000000000001351100213400325035ustar00rootroot00000000000000AbstractJavaGeneratorMojo.java000066400000000000000000000725031351100213400403370ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/javagenerationpackage org.codehaus.mojo.jaxb2.javageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import com.sun.tools.xjc.Driver; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.settings.Proxy; import org.apache.maven.settings.Settings; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.NoSchemasException; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.arguments.ArgumentBuilder; import org.codehaus.mojo.jaxb2.shared.environment.EnvironmentFacet; import org.codehaus.mojo.jaxb2.shared.environment.ToolExecutionEnvironment; import org.codehaus.mojo.jaxb2.shared.environment.classloading.ThreadContextClassLoaderBuilder; import org.codehaus.mojo.jaxb2.shared.environment.locale.LocaleFacet; import org.codehaus.mojo.jaxb2.shared.environment.logging.LoggingHandlerEnvironmentFacet; import org.codehaus.mojo.jaxb2.shared.environment.sysprops.SystemPropertyChangeEnvironmentFacet; import org.codehaus.mojo.jaxb2.shared.environment.sysprops.SystemPropertySaveEnvironmentFacet; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.IOUtil; import java.io.File; import java.io.FileWriter; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** *

Abstract superclass for Mojos generating Java source or binaries from XML schema(s) by invoking the JAXB XJC * binding compiler. Most of the Configuration options for the AbstractJavaGeneratorMojo are set or copied to the * XJC directly; refer to their documentation in the JAXB Reference Implementation * site.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ public abstract class AbstractJavaGeneratorMojo extends AbstractJaxbMojo { private static final List PROXY_PROPERTY_KEYS = Arrays.asList("http.proxyHost", "http.proxyPort", "https.proxyHost", "https.proxyPort"); private static final int XJC_COMPLETED_OK = 0; /** *

Corresponding XJC parameter: {@code catalog}.

*

Specify catalog files to resolve external entity references. * Supports TR9401, XCatalog, and OASIS XML Catalog format.

*/ @Parameter protected File catalog; /** * Deprecated - will be removed in a future release *

From plugin version 2.4, this parameter will not be used. * Instead, episode files are generated by default with all JAXB operations.

*

Starting with plugin version 2.4, use the parameter {@link #episodeFileName} to provide a custom * name of the generated episode File (or rely on the standard file name {@link #STANDARD_EPISODE_FILENAME}).

* * @since 2.0 * @deprecated */ @Deprecated @Parameter(defaultValue = "true") protected boolean generateEpisode; /** *

Corresponding XJC parameter: {@code episode}.

*

Generate an episode file with the supplied name from this XJC compilation, so that other schemas that rely * on this schema can be compiled later and rely on classes that are generated from this compilation. * The generated episode file is simply a JAXB customization file (but with vendor extensions), normally known * as a binding file with the suffix .xjb.

*

If the episodeFileName parameter is not given, the episode file name is synthesized on the form * "episode_" + executionID + ".xjb" - typically something like episode_my_xjc.xjb, but * it depends on the actual ID given in the execution element:

*
     *     
     * <executions>
     *     <execution>
     *         <id>my_xjc</id>
     *         <goals>
     *             <goal>xjc</goal>
     *         </goals>
     *     </execution>
     * </executions>
     *      
     * 
* * @see #STANDARD_EPISODE_FILENAME * @since 2.4 */ @Parameter protected String episodeFileName; /** *

Sets the HTTP/HTTPS proxy to be used by the XJC, on the format * {@code [user[:password]@]proxyHost[:proxyPort]}. * All information is retrieved from the active proxy within the standard maven settings file.

*/ @Parameter(defaultValue = "${settings}", readonly = true) protected Settings settings; /** *

Defines the content type of sources for the XJC. To simplify usage of the JAXB2 maven plugin, * all source files are assumed to have the same type of content.

*

This parameter replaces the previous multiple-choice boolean configuration options for the * jaxb2-maven-plugin (i.e. dtd, xmlschema, relaxng, relaxng-compact, wsdl), and * corresponds to setting one of those flags as an XJC argument.

* * @since 2.0 */ @Parameter(defaultValue = "XmlSchema") protected SourceContentType sourceType; /** *

Corresponding XJC parameter: {@code npa}.

*

Suppress the generation of package level annotations into {@code package-info.java}. * Using this switch causes the generated code to internalize those annotations into the other * generated classes.

* * @since 2.0 */ @Parameter(defaultValue = "false") protected boolean noPackageLevelAnnotations; /** *

Corresponding XJC parameter: {@code no-header}.

*

Suppress the generation of a file header comment that includes some note and timestamp. * Using this makes the generated code more diff-friendly.

* * @since 2.0 */ @Parameter(defaultValue = "false") protected boolean noGeneratedHeaderComments; /** *

Corresponding XJC parameter: {@code mark-generated}.

*

This feature causes all of the generated code to have {@code @Generated} annotation.

* * @since 2.0 */ @Parameter(defaultValue = "false") protected boolean addGeneratedAnnotation; /** *

Corresponding XJC parameter: {@code nv}.

*

By default, the XJC binding compiler performs strict validation of the source schema before processing it. * Use this option to disable strict schema validation. This does not mean that the binding compiler will not * perform any validation, it simply means that it will perform less-strict validation.

* * @since 2.0 */ @Parameter(defaultValue = "false") protected boolean laxSchemaValidation; /** *

Corresponding XJC parameter: {@code quiet}.

*

Suppress compiler output, such as progress information and warnings.

*/ @Parameter(defaultValue = "false") protected boolean quiet; /** *

Corresponding XJC parameter: {@code verbose}.

*

Tells XJC to be extra verbose, such as printing informational messages or displaying stack traces.

*/ @Parameter(property = "xjc.verbose", defaultValue = "false") protected boolean verbose; /** *

Corresponding XJC parameter: {@code extension}.

*

By default, the XJC binding compiler strictly enforces the rules outlined in the Compatibility chapter of * the JAXB Specification. Appendix E.2 defines a set of W3C XML Schema features that are not completely * supported by JAXB v1.0. In some cases, you may be allowed to use them in the "-extension" mode enabled by * this switch. In the default (strict) mode, you are also limited to using only the binding customizations * defined in the specification.

*/ @Parameter(defaultValue = "true") protected boolean extension; /** * Fails the Mojo execution if no XSDs/schemas are found. * * @since 1.3 */ @Parameter(defaultValue = "true") protected boolean failOnNoSchemas; /** *

Removes all files from the output directory before running XJC.

*/ @Parameter(defaultValue = "true") protected boolean clearOutputDir; /** *

Corresponding XJC parameter: {@code readOnly}.

*

By default, the XJC binding compiler does not write-protect the Java source files it generates. * Use this option to force the XJC binding compiler to mark the generated Java sources read-only.

* * @since 2.0 */ @Parameter(defaultValue = "false") protected boolean readOnly; /** *

List of ordered extra arguments to the XJC command. Each extra argument is interpreted as a word, intended * to be copied verbatim to the XJC argument list with spaces in between:

*
     * 
     *   <configuration>
     *   ...
     *       <arguments>
     *          <argument>-Xfluent-api</argument>
     *          <argument>somefile</argument>
     *      </arguments>
     *   </configuration>
     * 
     * 
*

The arguments configured above yields the following extra arguments to the XJC command: * -Xfluent-api -episode somefile

* * @since 2.0 * @deprecated This should be removed in the 2.0+ release, as all arguments should be handled by other parameters. */ @Parameter(property = "xjc.arguments") protected List arguments; /** *

Corresponding XJC parameter: {@code enableIntrospection}.

*

Enable correct generation of Boolean getters/setters to enable Bean Introspection APIs.

* * @since 1.4 */ @Parameter(defaultValue = "false") private boolean enableIntrospection; /** *

Corresponding XJC parameter: {@code p}.

*

The package under which the source files will be generated. Quoting the XJC documentation: * "Specifying a target package via this command-line option overrides any binding customization for package * name and the default package name algorithm defined in the specification".

*/ @Parameter protected String packageName; /** *

Corresponding XJC parameter: {@code target}.

*

Permitted values: {@code "2.0"} and {@code "2.1"}. Avoid generating code that relies on JAXB newer than the * version given. This will allow the generated code to run with JAXB 2.0 runtime (such as JavaSE 6.)

* * @since 1.3 */ @Parameter protected String target; /** *

If provided, this parameter indicates that the XSDs used by XJC to generate Java code should be * copied into the resulting artifact of this project (the JAR, WAR or whichever artifact type is generated). * The value of the {@code xsdPathWithinArtifact} parameter is the relative path within the artifact where * all source XSDs are copied to (hence the name "XSD Path Within Artifact").

*

The target directory is created within the artifact if it does not already exist. * If the {@code xsdPathWithinArtifact} parameter is not given, the XSDs used to generate Java code are * not included within the project's artifact.

*

Example:Adding the sample configuration below would copy all source XSDs to the given directory * within the resulting JAR (and/or test-JAR). If the directory {@code META-INF/jaxb/xsd} does not exist, it * will be created.

*
     *     
     *         <configuration>
     *             ...
     *             <xsdPathWithinArtifact>META-INF/jaxb/xsd</xsdPathWithinArtifact>
     *         </configuration>
     *     
     * 
*

Note: This parameter was previously called {@code includeSchemasOutputPath} * in the 1.x versions of this plugin, but was renamed and re-documented for improved usability and clarity.

* * @since 2.0 */ @Parameter protected String xsdPathWithinArtifact; /** *

If set to true, the system property enableExternalEntityProcessing is set for the * duration of the Java generation by this plugin, permitting DTD sources to use external entity URIs such as * file://. Typically, this is used in conjunction with the sourceType similar to the * configuration snippet below where DTDs are used as sourceType and read from the src/main/dtd * directory. This implies a file:// URI.

*
     *      
     *      <configuration>
     *          ...
     *          <sourceType>dtd</sourceType>
     *          <sources>
     *              <source>src/main/dtd</source>
     *          </sources>
     *          <externalEntityProcessing>true</externalEntityProcessing>
     *      </configuration>
     *      
     * 
* * @since 2.4 */ @Parameter(defaultValue = "false") protected boolean externalEntityProcessing; /** *

Java generation is required if any of the file products is outdated/stale.

* {@inheritDoc} */ @Override protected boolean isReGenerationRequired() { // // Use the stale flag method to identify if we should re-generate the java source code from the supplied // Xml Schema. Basically, we should regenerate the JAXB code if: // // a) The staleFile does not exist // b) The staleFile exists and is older than one of the sources (XSD or XJB files). // "Older" is determined by comparing the modification timestamp of the staleFile and the source files. // final File staleFile = getStaleFile(); final String debugPrefix = "StaleFile [" + FileSystemUtilities.getCanonicalPath(staleFile) + "]"; boolean stale = !staleFile.exists(); if (stale) { getLog().debug(debugPrefix + " not found. JAXB (re-)generation required."); } else { final List sourceXSDs = getSources(); final List sourceXJBs = getSourceXJBs(); if (getLog().isDebugEnabled()) { getLog().debug(debugPrefix + " found. Checking timestamps on source XSD and XJB " + "files to determine if JAXB (re-)generation is required."); } final long staleFileLastModified = staleFile.lastModified(); for (URL current : sourceXSDs) { final URLConnection sourceXsdConnection; try { sourceXsdConnection = current.openConnection(); sourceXsdConnection.connect(); } catch (Exception e) { // Can't determine if the staleFile is younger than this sourceXSD. // Re-generate to be on the safe side. stale = true; break; } try { if (sourceXsdConnection.getLastModified() > staleFileLastModified) { if (getLog().isDebugEnabled()) { getLog().debug(current.toString() + " is newer than the stale flag file."); } stale = true; } } finally { if (sourceXsdConnection instanceof HttpURLConnection) { ((HttpURLConnection) sourceXsdConnection).disconnect(); } } } for (File current : sourceXJBs) { if (current.lastModified() > staleFileLastModified) { if (getLog().isDebugEnabled()) { getLog().debug(FileSystemUtilities.getCanonicalPath(current) + " is newer than the stale flag file."); } stale = true; break; } } } // All done. return stale; } /** * {@inheritDoc} */ @Override protected boolean performExecution() throws MojoExecutionException, MojoFailureException { boolean updateStaleFileTimestamp = false; try { // Setup the Tool's execution environment ToolExecutionEnvironment environment = null; try { // Create a LocaleFacet if the user has configured an explicit Locale for the tool. final LocaleFacet localeFacet = locale == null ? null : LocaleFacet.createFor(locale, getLog()); // Create the ToolExecutionEnvironment environment = new ToolExecutionEnvironment(getLog(), ThreadContextClassLoaderBuilder.createFor(this.getClass(), getLog(), getEncoding(false)) .addPaths(getClasspath()), LoggingHandlerEnvironmentFacet.create(getLog(), getClass(), getEncoding(false)), localeFacet); // Add any extra configured EnvironmentFacets, as configured in the POM. if (extraFacets != null) { for (EnvironmentFacet current : extraFacets) { environment.add(current); } } // Handle extended properties? if (externalEntityProcessing) { final List sysPropChanges = SystemPropertyChangeEnvironmentFacet.getBuilder(getLog()) .addOrChange("enableExternalEntityProcessing", "" + externalEntityProcessing) .build(); for (SystemPropertyChangeEnvironmentFacet current : sysPropChanges) { environment.add(current); } } // XJC overwrites proxy properties if so inclined, so we use this facet to save them for (String key : PROXY_PROPERTY_KEYS) { environment.add(new SystemPropertySaveEnvironmentFacet(key, getLog())); } // Setup the environment. environment.setup(); // Compile the XJC arguments final String[] xjcArguments = getXjcArguments(environment.getClassPathAsArgument(), episodeFileName); // Ensure that the outputDirectory exists, but only clear it if does not already FileSystemUtilities.createDirectory(getOutputDirectory(), clearOutputDir); // Do we need to re-create the episode file's parent directory. final boolean reCreateEpisodeFileParentDirectory = generateEpisode && clearOutputDir; if (reCreateEpisodeFileParentDirectory) { getEpisodeFile(episodeFileName); } // Check the system properties. logSystemPropertiesAndBasedir(); // Fire XJC if (XJC_COMPLETED_OK != Driver.run(xjcArguments, new XjcLogAdapter(getLog()))) { final StringBuilder errorMsgBuilder = new StringBuilder(); errorMsgBuilder.append("\n+=================== [XJC Error]\n"); errorMsgBuilder.append("|\n"); final List sourceXSDs = getSources(); for (int i = 0; i < sourceXSDs.size(); i++) { errorMsgBuilder.append("| " + i + ": ").append(sourceXSDs.get(i).toString()).append("\n"); } errorMsgBuilder.append("|\n"); errorMsgBuilder.append("+=================== [End XJC Error]\n"); throw new MojoExecutionException(errorMsgBuilder.toString()); } // Indicate that the output directory was updated. getBuildContext().refresh(getOutputDirectory()); // Update the modification timestamp of the staleFile. updateStaleFileTimestamp = true; } finally { if (environment != null) { environment.restore(); } } // Add the generated source root to the project, enabling tooling and other plugins to see them. addGeneratedSourcesToProjectSourceRoot(); // Copy all source XSDs to the resulting artifact? if (xsdPathWithinArtifact != null) { final String buildOutputDirectory = getProject().getBuild().getOutputDirectory(); final File targetXsdDirectory = new File(buildOutputDirectory, xsdPathWithinArtifact); FileUtils.forceMkdir(targetXsdDirectory); for (URL current : getSources()) { String fileName = null; if ("file".equalsIgnoreCase(current.getProtocol())) { fileName = new File(current.getPath()).getName(); } else if ("jar".equalsIgnoreCase(current.getProtocol())) { // Typical JAR path // jar:file:/path/to/aJar.jar!/some/path/xsd/aResource.xsd final int bangIndex = current.toString().indexOf("!"); if (bangIndex == -1) { throw new MojoExecutionException("Illegal JAR URL [" + current.toString() + "]: lacks a '!'"); } final String internalPath = current.toString().substring(bangIndex + 1); fileName = new File(internalPath).getName(); } else { throw new MojoExecutionException("Could not extract FileName from URL [" + current + "]"); } final File targetFile = new File(targetXsdDirectory, fileName); if (targetFile.exists()) { // TODO: Should we throw an exception here instead? getLog().warn("File [" + FileSystemUtilities.getCanonicalPath(targetFile) + "] already exists. Not copying XSD file [" + current.getPath() + "] to it."); } IOUtil.copy(current.openStream(), new FileWriter(targetFile)); } // Refresh the BuildContext getBuildContext().refresh(targetXsdDirectory); } } catch (MojoExecutionException e) { throw e; } catch (NoSchemasException e) { if (failOnNoSchemas) { throw new MojoExecutionException("", e); } } catch (Exception e) { throw new MojoExecutionException(e.getMessage(), e); } // All done. return updateStaleFileTimestamp; } /** * Override this method to acquire a List holding all URLs to the JAXB sources for which this * AbstractJavaGeneratorMojo should generate Java files. Sources are assumed to be in the form given by * the {@code sourceType} value. * * @return A non-null List holding URLs to sources for the XJC generation. * @see #sourceType */ @Override protected abstract List getSources(); /** * Override this method to retrieve a list of Files to all XJB files for which this * AbstractJavaGeneratorMojo should generate Java files. * * @return A non-null List holding binding files. */ protected abstract List getSourceXJBs(); /** * Adds any directories containing the generated XJC classes to the appropriate Project compilation sources; * either {@code TestCompileSourceRoot} or {@code CompileSourceRoot} depending on the exact Mojo implementation * of this AbstractJavaGeneratorMojo. */ protected abstract void addGeneratedSourcesToProjectSourceRoot(); // // Private helpers // private String[] getXjcArguments(final String classPath, final String episodeFileNameOrNull) throws MojoExecutionException, NoSchemasException { final ArgumentBuilder builder = new ArgumentBuilder(); // Add all flags on the form '-flagName' builder.withFlag(true, sourceType.getXjcArgument()); builder.withFlag(noPackageLevelAnnotations, "npa"); builder.withFlag(laxSchemaValidation, "nv"); builder.withFlag(verbose, "verbose"); builder.withFlag(quiet, "quiet"); builder.withFlag(enableIntrospection, "enableIntrospection"); builder.withFlag(extension, "extension"); builder.withFlag(readOnly, "readOnly"); builder.withFlag(noGeneratedHeaderComments, "no-header"); builder.withFlag(addGeneratedAnnotation, "mark-generated"); // Add all arguments on the form '-argumentName argumentValue' // (i.e. in 2 separate elements of the returned String[]) builder.withNamedArgument("httpproxy", getProxyString(settings.getActiveProxy())); builder.withNamedArgument("encoding", getEncoding(true)); builder.withNamedArgument("p", packageName); builder.withNamedArgument("target", target); builder.withNamedArgument("d", getOutputDirectory().getAbsolutePath()); builder.withNamedArgument("classpath", classPath); // We must add the -extension flag in order to generate the episode file. if (!extension) { if (getLog().isInfoEnabled()) { getLog().info("Adding 'extension' flag to XJC arguments, to generate an episode " + "file named '" + (episodeFileName == null ? STANDARD_EPISODE_FILENAME : episodeFileName) + "'. (XJCs 'episode' argument requires that the 'extension' argument is provided)."); } } builder.withFlag(true, "extension"); final File episodeFile = getEpisodeFile(episodeFileNameOrNull); builder.withNamedArgument("episode", FileSystemUtilities.getCanonicalPath(episodeFile)); if (catalog != null) { builder.withNamedArgument("catalog", FileSystemUtilities.getCanonicalPath(catalog)); } if (arguments != null) { builder.withPreCompiledArguments(arguments); } for (File current : getSourceXJBs()) { // Shorten the argument? // final String strippedXjbPath = FileSystemUtilities.relativize( // current.getAbsolutePath(), getProject().getBasedir()); // Each XJB must be given as a separate argument. builder.withPreCompiledArguments(Arrays.asList("-b", current.getAbsolutePath())); } final List sourceXSDs = getSources(); if (sourceXSDs.isEmpty()) { // If we have no XSDs, we are not going to be able to run XJC. getLog().warn("No XSD files found. Please check your plugin configuration."); throw new NoSchemasException(); } else { final List unwrappedSourceXSDs = new ArrayList(); for (URL current : sourceXSDs) { // Shorten the argument if possible. if ("file".equalsIgnoreCase(current.getProtocol())) { unwrappedSourceXSDs.add(FileSystemUtilities.relativize( current.getPath(), new File(System.getProperty("user.dir")), true)); } else { unwrappedSourceXSDs.add(current.toString()); } } builder.withPreCompiledArguments(unwrappedSourceXSDs); } // All done. return logAndReturnToolArguments(builder.build(), "XJC"); } private String getProxyString(final Proxy activeProxy) { // Check sanity if (activeProxy == null) { return null; } // The XJC proxy argument should be on the form // [user[:password]@]proxyHost[:proxyPort] // // builder.withNamedArgument("httpproxy", httpproxy); // final StringBuilder proxyBuilder = new StringBuilder(); if (activeProxy.getUsername() != null) { // Start with the username. proxyBuilder.append(activeProxy.getUsername()); // Append the password if provided. if (activeProxy.getPassword() != null) { proxyBuilder.append(":").append(activeProxy.getPassword()); } proxyBuilder.append("@"); } // Append hostname and port. proxyBuilder.append(activeProxy.getHost()).append(":").append(activeProxy.getPort()); // All done. return proxyBuilder.toString(); } } SourceContentType.java000066400000000000000000000117611351100213400367320ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/javagenerationpackage org.codehaus.mojo.jaxb2.javageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * The type of source input used by XJC. * The constants are duplicated in lowercase since Maven's Mojo argument matcher is case sensitive. * * @author Lennart Jörelid, jGuru Europe AB * @see The JAXB Reference Implementation * @since 2.0 */ public enum SourceContentType { /** *

Treat input as DTDs (i.e. Document Type * Definitions). This option is labelled as "experimental,unsupported" in the XJC documentation.

*/ DTD("dtd"), /** *

Treat input as DTDs (i.e. Document Type * Definitions). This option is labelled as "experimental,unsupported" in the XJC documentation.

* * @see #DTD */ dtd("dtd"), /** *

Treat input as W3C XML Schema (i.e. Xml Schema Definitions). * This is the standard mode of the XJC (and is recommended by the Codehaus Mojo team as well).

*/ XmlSchema("xmlschema"), /** *

Treat input as W3C XML Schema (i.e. Xml Schema Definitions). * This is the standard mode of the XJC (and is recommended by the Codehaus Mojo team as well).

* * @see #XmlSchema */ xmlschema("xmlschema"), /** *

Treat input as Relax NG. * This option is labelled as "experimental,unsupported" in the XJC documentation.

* * @see Relax NG on WikiPedia */ RelaxNG("relaxng"), /** *

Treat input as Relax NG. * This option is labelled as "experimental,unsupported" in the XJC documentation.

* * @see Relax NG on WikiPedia * @see #RelaxNG */ relaxng("relaxng"), /** *

Treat input as Relax * NG with Compact syntax. This option is labelled as "experimental,unsupported" in the XJC documentation.

* * @see Relax NG on WikiPedia */ RelaxNGCompact("relaxng-compact"), /** *

Treat input as Relax * NG with Compact syntax. This option is labelled as "experimental,unsupported" in the XJC documentation.

* * @see Relax NG on WikiPedia * @see #RelaxNGCompact */ relaxng_compact("relaxng-compact"), /** *

Treat input as Relax * NG with Compact syntax. This option is labelled as "experimental,unsupported" in the XJC documentation.

* * @see Relax NG on WikiPedia * @see #RelaxNGCompact */ relaxngcompact("relaxng-compact"), /** *

Treat input as WSDL, and compile schemas inside it. * This option is labelled as "experimental,unsupported" in the XJC documentation.

* * @see Web Services Description Language (WSDL) 1.1 */ WSDL("wsdl"), /** *

Treat input as WSDL, and compile schemas inside it. * This option is labelled as "experimental,unsupported" in the XJC documentation.

* * @see Web Services Description Language (WSDL) 1.1 * @see #WSDL */ wsdl("wsdl"); // Internal state private String xjcArgument; SourceContentType(final String xjcArgument) { this.xjcArgument = xjcArgument; } /** * @return The XJC argument flag corresponding to this InputType. */ public String getXjcArgument() { return xjcArgument; } } TestXjcMojo.java000066400000000000000000000336621351100213400355120ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/javagenerationpackage org.codehaus.mojo.jaxb2.javageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** *

Mojo that creates test-scope Java source or binaries from XML schema(s) * by invoking the JAXB XJC binding compiler. This implementation is tailored * to use the JAXB Reference Implementation from project Kenai.

*

Note that the TestXjcMojo was completely re-implemented for the 2.x versions. * Its configuration semantics and parameter set is not necessarily * backwards compatible with the 1.x plugin versions. If you are * upgrading from version 1.x of the plugin, read the documentation carefully.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ @Mojo(name = "testXjc", defaultPhase = LifecyclePhase.GENERATE_TEST_SOURCES, requiresDependencyResolution = ResolutionScope.TEST, threadSafe = false) public class TestXjcMojo extends AbstractJavaGeneratorMojo { /** * The last part of the stale fileName for this TestXjcMojo. */ public static final String STALE_FILENAME = "testXjcStaleFlag"; /** * Standard directory path (relative to basedir) searched recursively for test * source files (typically XSDs), unless overridden by a * testSources configuration element. */ public static final String STANDARD_TEST_SOURCE_DIRECTORY = "src/test/xsd"; /** *

Default exclude Filters for test sources, used unless overridden by an * explicit configuration in the {@code testSourceExcludeFilters} parameter. * The default values are found as follows:

*
     *     
     *         final List<Filter<File>> xjbTemp = new ArrayList<Filter<File>>();
     *         xjbTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
     *         xsdTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb"), true));
     *         STANDARD_TEST_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(xsdTemp);
     *     
     * 
* * @see #STANDARD_EXCLUDE_FILTERS */ public static final List> STANDARD_TEST_SOURCE_EXCLUDE_FILTERS; /** *

Standard directory path (relative to basedir) searched recursively for XJB * files, unless overridden by an testXjbSources configuration element. * As explained in the JAXB specification, XJB files (JAXB Xml Binding files) * are used to configure parts of the Java source generation.

*/ public static final String STANDARD_TEST_XJB_DIRECTORY = "src/test/xjb"; /** *

Default List of exclude Filters for XJB files, unless overridden by providing * an explicit configuration in the {@code testXjbExcludeFilters} parameter. * The default values are found as follows:

*
     *     
     *         final List<Filter<File>> xjbTemp = new ArrayList<Filter<File>>();
     *         xjbTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
     *         xjbTemp.add(new PatternFileFilter(Arrays.asList("\\.xsd"), true));
     *         STANDARD_TEST_XJB_EXCLUDE_FILTERS = Collections.unmodifiableList(xjbTemp);
     *     
     * 
* * @see #STANDARD_EXCLUDE_FILTERS */ public static final List> STANDARD_TEST_XJB_EXCLUDE_FILTERS; static { final List> xjbTemp = new ArrayList>(); xjbTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS); xjbTemp.add(new PatternFileFilter(Arrays.asList("\\.xsd"), true)); STANDARD_TEST_XJB_EXCLUDE_FILTERS = Collections.unmodifiableList(xjbTemp); final List> xsdTemp = new ArrayList>(); xsdTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS); xsdTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb"), true)); STANDARD_TEST_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(xsdTemp); } /** *

Corresponding XJC parameter: {@code d}.

*

The working directory where the generated Java test source files are created.

*/ @Parameter(defaultValue = "${project.build.directory}/generated-test-sources/jaxb", required = true) private File outputDirectory; /** *

Parameter holding List of XSD paths to files and/or directories which should be recursively searched * for XSD files. Only files or directories that actually exist will be included (in the case of files) * or recursively searched for XSD files to include (in the case of directories). * Configure using standard Maven structure for Lists:

*
     * 
     *   <configuration>
     *   ...
     *       <testSources>
     *          <testSource>some/explicit/relative/file.xsd</testSource>
     *          <testSource>/another/absolute/path/to/a/specification.xsd</testSource>
     *          <testSource>a/directory/holding/xsds</testSource>
     *      </testSources>
     *   </configuration>
     * 
     * 
* * @see #STANDARD_TEST_SOURCE_DIRECTORY */ @Parameter(required = false) private List testSources; /** *

Parameter holding List of XJB Files and/or directories which should be recursively searched * for XJB files. Only files or directories that actually exist will be included (in the case of files) * or recursively searched for XJB files to include (in the case of directories). JAXB binding files are * used to configure parts of the Java source generation. * Supply the configuration using the standard Maven structure for configuring plugin Lists:

*
     * 
     *   <configuration>
     *   ...
     *       <testXjbSources>
     *          <testXjbSource>bindings/aBindingConfiguration.xjb</testXjbSource>
     *          <testXjbSource>bindings/config/directory</testXjbSource>
     *      </testXjbSources>
     *   </configuration>
     * 
     * 
* * @see #STANDARD_TEST_XJB_DIRECTORY */ @Parameter(required = false) private List testXjbSources; /** *

Parameter holding a List of Filters, used to match all files under the {@code testSources} directories * which should not be considered XJC test source files. (The filters identify files to * exclude, and hence this parameter is called {@code testS§ourceExcludeFilters}). If a file under any of the * test source directories matches at least one of the Filters supplied in the {@code testSourceExcludeFilters}, * it is not considered an XJC source file, and therefore excluded from processing.

*

If not explicitly provided, the Mojo uses the value within {@code STANDARD_TEST_SOURCE_EXCLUDE_FILTERS}. * The algorithm for finding XJC test sources is as follows:

*
    *
  1. Find all files given in the testSources List. Any Directories provided are searched for files * recursively.
  2. *
  3. Exclude any found files matching any of the supplied {@code testSourceExcludeFilters} List.
  4. *
  5. The remaining Files are submitted for processing by the XJC tool.
  6. *
*

Example: The following configuration would exclude any sources whose names end with * {@code txt} or {@code foo}:

*
     *     
     *         <configuration>
     *         ...
     *              <testSourceExcludeFilters>
     *                  <suffixFilter impl="org.codehaus.mojo.jaxb2.shared.filters.source.ExclusionRegularExpressionFileFilter">txt</suffixFilter>
     *                  <suffixFilter impl="org.codehaus.mojo.jaxb2.shared.filters.source.ExclusionRegularExpressionFileFilter">foo</suffixFilter>
     *              </testSourceExcludeFilters>
     *         </configuration>
     *     
     * 
* * @see #STANDARD_TEST_SOURCE_EXCLUDE_FILTERS * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.AbstractPatternFilter * @see org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter */ @Parameter(required = false) private List> testSourceExcludeFilters; /*** *

Parameter holding a List of Filters, used to match all files under the {@code testXjbSources} directories * which should not be considered XJB files. (The filters identify files to exclude, and hence * this parameter is called {@code testXjbExcludeFilters}). If a file matches at least one of the supplied Filters, * it is not considered an XJB file, and therefore excluded from processing.

*

If not explicitly provided, the Mojo uses the value within {@code STANDARD_TEST_XJB_EXCLUDE_FILTERS}.

*

Example: The following configuration would exclude any XJB files whose names end with * {@code xml} or {@code foo}:

*
     *     
     *         <configuration>
     *         ...
     *              <testXjbExcludeFilters>
     *                  <suffixFilter impl="org.codehaus.mojo.jaxb2.shared.filters.source.ExclusionRegularExpressionFileFilter">xml</suffixFilter>
     *                  <suffixFilter impl="org.codehaus.mojo.jaxb2.shared.filters.source.ExclusionRegularExpressionFileFilter">foo</suffixFilter>
     *              </sourceExcludeFilters>
     *         </testXjbExcludeFilters>
     *     
     * 
* * @see #STANDARD_TEST_XJB_EXCLUDE_FILTERS * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.AbstractPatternFilter * @see org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter */ @Parameter(required = false) private List> testXjbExcludeFilters; /** * Indicate if the XjcMojo execution should be skipped. */ @Parameter(property = "xjc.test.skip", defaultValue = "false") private boolean skipTestXjc; /** * {@inheritDoc} */ @Override protected boolean shouldExecutionBeSkipped() { return skipTestXjc; } /** * {@inheritDoc} */ @Override protected List getSources() { final List> excludePatterns = testSourceExcludeFilters == null ? STANDARD_TEST_SOURCE_EXCLUDE_FILTERS : testSourceExcludeFilters; Filters.initialize(getLog(), excludePatterns); // All done. return FileSystemUtilities.filterFiles( getProject().getBasedir(), testSources, Arrays.asList(STANDARD_TEST_SOURCE_DIRECTORY), getLog(), "testSources", excludePatterns); } /** * {@inheritDoc} */ @Override protected List getSourceXJBs() { final List> excludePatterns = testXjbExcludeFilters == null ? STANDARD_TEST_XJB_EXCLUDE_FILTERS : testXjbExcludeFilters; Filters.initialize(getLog(), excludePatterns); return FileSystemUtilities.filterFiles( getProject().getBasedir(), testXjbSources, STANDARD_TEST_XJB_DIRECTORY, getLog(), "testXjbSources", excludePatterns); } /** * {@inheritDoc} */ @Override protected String getStaleFileName() { return STALE_FILENAME; } /** * {@inheritDoc} */ @Override protected File getOutputDirectory() { return outputDirectory; } /** * {@inheritDoc} */ @Override protected List getClasspath() throws MojoExecutionException { try { return (List) getProject().getTestClasspathElements(); } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("Could not retrieve Compile classpath.", e); } } /** * {@inheritDoc} */ @Override protected void addGeneratedSourcesToProjectSourceRoot() { getProject().addTestCompileSourceRoot(getOutputDirectory().getAbsolutePath()); } /** * {@inheritDoc} */ @Override protected void addResource(final Resource resource) { getProject().addTestResource(resource); } } XjcLogAdapter.java000066400000000000000000000055231351100213400357630ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/javagenerationpackage org.codehaus.mojo.jaxb2.javageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import com.sun.tools.xjc.XJCListener; import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; import org.xml.sax.SAXParseException; /** * Adapter implementation emitting XJC events to a Maven Log. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class XjcLogAdapter extends XJCListener { // Internal state private Log log; /** * Creates an XjcLogAdapter which emits all XJC events onto the supplied Maven Log. * * @param log A non-null Log logging all inbound XJC events. */ public XjcLogAdapter(final Log log) { // Check sanity Validate.notNull(log, "log"); // Assign internal state this.log = log; } /** * {@inheritDoc} */ @Override public void generatedFile(final String fileName, final int current, final int total) { if (log.isDebugEnabled()) { log.debug("Processing file [" + current + "/" + total + "]: " + fileName); } } /** * {@inheritDoc} */ @Override public void error(final SAXParseException exception) { log.error(getLocation(exception), exception); } /** * {@inheritDoc} */ @Override public void fatalError(final SAXParseException exception) { log.error(getLocation(exception), exception); } /** * {@inheritDoc} */ @Override public void warning(final SAXParseException exception) { log.warn(getLocation(exception), exception); } /** * {@inheritDoc} */ @Override public void info(final SAXParseException exception) { log.info(getLocation(exception), exception); } // // Private helpers // private String getLocation(final SAXParseException e) { final String exceptionId = e.getPublicId() == null ? e.getSystemId() : e.getPublicId(); return exceptionId + " [" + e.getLineNumber() + "," + e.getColumnNumber() + "] "; } } XjcMojo.java000066400000000000000000000346461351100213400346550ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/javagenerationpackage org.codehaus.mojo.jaxb2.javageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** *

Mojo that creates compile-scope Java source or binaries from XML schema(s) * by invoking the JAXB XJC binding compiler. This implementation is tailored * to use the JAXB Reference Implementation from project Kenai.

*

Note that the XjcMojo was completely re-implemented for the 2.x versions. * Its configuration semantics and parameter set is not necessarily * backwards compatible with the 1.x plugin versions. If you are * upgrading from version 1.x of the plugin, read the documentation carefully.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ @Mojo(name = "xjc", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE) public class XjcMojo extends AbstractJavaGeneratorMojo { /** * The last part of the stale fileName for this XjcMojo. */ public static final String STALE_FILENAME = "xjcStaleFlag"; /** *

Standard directory path (relative to basedir) searched recursively for source * files (typically XSDs), unless overridden by an sources configuration element.

*/ public static final String STANDARD_SOURCE_DIRECTORY = "src/main/xsd"; /** *

Default exclude Filters for sources, used unless overridden by an * explicit configuration in the {@code xjcSourceExcludeFilters} parameter. * The default values are found as follows:

*
     *     
     *         final List<Filter<File>> xsdTemp = new ArrayList<Filter<File>>();
     *         xsdTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
     *         xsdTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb"), true));
     *         STANDARD_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(xsdTemp);
     *     
     * 
* @see #STANDARD_EXCLUDE_FILTERS */ public static final List> STANDARD_SOURCE_EXCLUDE_FILTERS; /** *

Standard directory path (relative to basedir) searched recursively for XJB * files, unless overridden by an xjbSources configuration element. * As explained in the JAXB specification, XJB files (JAXB Xml Binding files) * are used to configure parts of the Java source generation.

*/ public static final String STANDARD_XJB_DIRECTORY = "src/main/xjb"; /** *

Default List of exclude Filters for XJB files, unless overridden by providing * an explicit configuration in the {@code xjbExcludeSuffixes} parameter. * The default values are found as follows:

*
     *     
     *         final List<Filter<File>> xjbTemp = new ArrayList<Filter<File>>();
     *         xjbTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
     *         xjbTemp.add(new PatternFileFilter(Arrays.asList("\\.xsd"), true));
     *         STANDARD_XJB_EXCLUDE_FILTERS = Collections.unmodifiableList(xjbTemp);
     *     
     * 
* @see #STANDARD_EXCLUDE_FILTERS */ public static final List> STANDARD_XJB_EXCLUDE_FILTERS; static { final List> xjbTemp = new ArrayList>(); xjbTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS); xjbTemp.add(new PatternFileFilter(Arrays.asList("\\.xsd"), true)); STANDARD_XJB_EXCLUDE_FILTERS = Collections.unmodifiableList(xjbTemp); final List> xsdTemp = new ArrayList>(); xsdTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS); xsdTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb"), true)); STANDARD_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(xsdTemp); } /** *

Corresponding XJC parameter: {@code d}.

*

The working directory where the generated Java source files are created.

*/ @Parameter(defaultValue = "${project.build.directory}/generated-sources/jaxb", required = true) private File outputDirectory; /** *

Parameter holding List of XSD paths to files and/or directories which should be recursively searched * for XSD files. Only files or directories that actually exist will be included (in the case of files) * or recursively searched for XSD files to include (in the case of directories). * Configure using standard Maven structure for Lists:

*
     * 
     *   <configuration>
     *   ...
     *       <sources>
     *          <source>some/explicit/relative/file.xsd</source>
     *          <source>/another/absolute/path/to/a/specification.xsd</source>
     *          <source>a/directory/holding/xsds</source>
     *      </sources>
     *   </configuration>
     * 
     * 
* * @see #STANDARD_SOURCE_DIRECTORY */ @Parameter(required = false) private List sources; /** *

Parameter holding List of XJB Files and/or directories which should be recursively searched * for XJB files. Only files or directories that actually exist will be included (in the case of files) * or recursively searched for XJB files to include (in the case of directories). JAXB binding files are * used to configure parts of the Java source generation. * Supply the configuration using the standard Maven structure for configuring plugin Lists:

*
     * 
     *   <configuration>
     *   ...
     *       <xjbSources>
     *          <xjbSource>bindings/aBindingConfiguration.xjb</xjbSource>
     *          <xjbSource>bindings/config/directory</xjbSource>
     *      </xjbSources>
     *   </configuration>
     * 
     * 
* * @see #STANDARD_XJB_DIRECTORY */ @Parameter(required = false) private List xjbSources; /** *

Parameter holding a List of Filters, used to match all files under the {@code sources} directories * which should not be considered XJC source files. (The filters identify files to * exclude, and hence this parameter is called {@code xjcSourceExcludeFilters}). If a file under any of the * source directories matches at least one of the Filters supplied in the {@code xjcSourceExcludeFilters}, * it is not considered an XJC source file, and therefore excluded from processing.

*

If not explicitly provided, the Mojo uses the value within {@code STANDARD_SOURCE_EXCLUDE_FILTERS}. * The algorithm for finding XJC sources is as follows:

*
    *
  1. Find all files given in the sources List. Any Directories provided are searched for files * recursively.
  2. *
  3. Exclude any found files matching any of the supplied {@code xjcSourceExcludeFilters} List.
  4. *
  5. The remaining Files are submitted for processing by the XJC tool.
  6. *
*

Example: The following configuration would exclude any sources whose names end with * {@code txt} or {@code foo}:

*
     *     
     *         <configuration>
     *         ...
     *              <xjcSourceExcludeFilters>
     *                  <filter implementation="org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter">
     *                      <patterns>
     *                          <pattern>\.txt</pattern>
     *                          <pattern>\.foo</pattern>
     *                      </patterns>
     *                  </filter>
     *              </xjcSourceExcludeFilters>
     *         </configuration>
     *     
     * 
*

Note that inner workings of the Dependency Injection mechanism used by Maven Plugins (i.e. the DI from * the Plexus container) requires that the full class name to the Filter implementation should be supplied for * each filter, as is illustrated in the sample above. This is true also if you implement custom Filters.

* * @see #STANDARD_SOURCE_EXCLUDE_FILTERS * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.AbstractPatternFilter * @see org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter */ @Parameter(required = false) private List> xjcSourceExcludeFilters; /** *

Parameter holding a List of Filters, used to match all files under the {@code xjbSources} directories * which should not be considered XJB files. (The filters identify files to exclude, and hence * this parameter is called {@code xjbExcludeFilters}). If a file matches at least one of the supplied Filters, * it is not considered an XJB file, and therefore excluded from processing.

*

If not explicitly provided, the Mojo uses the value within {@code STANDARD_XJB_EXCLUDE_FILTERS}.

*

Example: The following configuration would exclude any XJB files whose names end with * {@code xml} or {@code foo}:

*
     *     
     *         <configuration>
     *         ...
     *              <xjbExcludeFilters>
     *                  <filter implementation="org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter">
     *                      <patterns>
     *                          <pattern>\.txt</pattern>
     *                          <pattern>\.foo</pattern>
     *                      </patterns>
     *                  </filter>
     *              </xjbExcludeFilters>
     *         ...
     *         </configuration>
     *     
     * 
*

Note that inner workings of the Dependency Injection mechanism used by Maven Plugins (i.e. the DI from * the Plexus container) requires that the full class name to the Filter implementation should be supplied for * each filter, as is illustrated in the sample above. This is true also if you implement custom Filters.

* * @see #STANDARD_XJB_EXCLUDE_FILTERS * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.AbstractPatternFilter * @see org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter */ @Parameter(required = false) private List> xjbExcludeFilters; /** * Indicate if the XjcMojo execution should be skipped. */ @Parameter(property = "xjc.skip", defaultValue = "false") private boolean skipXjc; /** * {@inheritDoc} */ @Override protected boolean shouldExecutionBeSkipped() { return skipXjc; } /** * {@inheritDoc} */ @Override protected List getSources() { final List> excludePatterns = xjcSourceExcludeFilters == null ? STANDARD_SOURCE_EXCLUDE_FILTERS : xjcSourceExcludeFilters; Filters.initialize(getLog(), excludePatterns); return FileSystemUtilities.filterFiles( getProject().getBasedir(), sources, Arrays.asList(STANDARD_SOURCE_DIRECTORY), getLog(), "sources", excludePatterns); } /** * {@inheritDoc} */ @Override protected List getSourceXJBs() { final List> excludePatterns = xjbExcludeFilters == null ? STANDARD_XJB_EXCLUDE_FILTERS : xjbExcludeFilters; Filters.initialize(getLog(), excludePatterns); return FileSystemUtilities.filterFiles( getProject().getBasedir(), xjbSources, STANDARD_XJB_DIRECTORY, getLog(), "xjbSources", excludePatterns); } /** * {@inheritDoc} */ @Override protected String getStaleFileName() { return STALE_FILENAME; } /** * {@inheritDoc} */ @Override protected File getOutputDirectory() { return outputDirectory; } /** * {@inheritDoc} */ @Override protected List getClasspath() throws MojoExecutionException { try { return (List) getProject().getCompileClasspathElements(); } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("Could not retrieve Compile classpath.", e); } } /** * {@inheritDoc} */ @Override protected void addGeneratedSourcesToProjectSourceRoot() { getProject().addCompileSourceRoot(FileSystemUtilities.getCanonicalPath(getOutputDirectory())); } /** * {@inheritDoc} */ @Override protected void addResource(final Resource resource) { getProject().addResource(resource); } } package-info.java000066400000000000000000000007571351100213400356240ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/javageneration/** *

The jaxb2-maven-plugin wraps and adapts the JAXB reference implementation * to be useful within the Maven build process.

*

The javageneration package (including subpackages) contains Mojos for generating Java files from * XSDs or DTDs.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ package org.codehaus.mojo.jaxb2.javageneration;jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/package-info.java000066400000000000000000000022041351100213400326730ustar00rootroot00000000000000/** *

The jaxb2-maven-plugin wraps and adapts the JAXB reference implementation * to be useful within the Maven build process.

*

The plugin's code is divided into 3 main blocks, each placed within a separate package structure:

* *
    *
  1. javageneration. Contains code involved in creating java code from XSD or DTDs. * This package structure adapts the plugin to using the XJC ("Xml-to-Java-Compiler") from the * JAXB reference implementation.
  2. *
  3. schemageneration. Contains code involved in creating XSDs from annotated Java classes. * This package structure adapts the plugin to using the schemagen tool from the JDK. (Typically found in the * bin directory of the java installation).
  4. *
  5. shared. Contains shared utility classes used by both the java- and xsd-generation * structure classes.
  6. *
* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ package org.codehaus.mojo.jaxb2;jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/000077500000000000000000000000001351100213400330225ustar00rootroot00000000000000AbstractXsdGeneratorMojo.java000066400000000000000000001251351351100213400405330ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemagenerationpackage org.codehaus.mojo.jaxb2.schemageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import com.sun.tools.jxc.SchemaGenerator; import com.thoughtworks.qdox.JavaProjectBuilder; import com.thoughtworks.qdox.model.JavaClass; import com.thoughtworks.qdox.model.JavaPackage; import com.thoughtworks.qdox.model.JavaSource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Parameter; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.DefaultJavaDocRenderer; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocExtractor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocRenderer; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SearchableDocumentation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.TransformSchema; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.arguments.ArgumentBuilder; import org.codehaus.mojo.jaxb2.shared.environment.EnvironmentFacet; import org.codehaus.mojo.jaxb2.shared.environment.ToolExecutionEnvironment; import org.codehaus.mojo.jaxb2.shared.environment.classloading.ThreadContextClassLoaderBuilder; import org.codehaus.mojo.jaxb2.shared.environment.locale.LocaleFacet; import org.codehaus.mojo.jaxb2.shared.environment.logging.LoggingHandlerEnvironmentFacet; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.util.FileUtils; import javax.tools.ToolProvider; import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import java.util.regex.Pattern; /** *

Abstract superclass for Mojos that generate XSD files from annotated Java Sources. * This Mojo delegates execution to the {@code schemagen} tool to perform the XSD file * generation. Moreover, the AbstractXsdGeneratorMojo provides an augmented processing * pipeline by optionally letting a set of NodeProcessors improve the 'vanilla' XSD files.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ public abstract class AbstractXsdGeneratorMojo extends AbstractJaxbMojo { /** *

Pattern matching the names of files emitted by the JAXB/JDK SchemaGenerator. * According to the JAXB Schema Generator documentation:

*
There is no way to control the name of the generated schema files at this time.
*/ public static final Pattern SCHEMAGEN_EMITTED_FILENAME = Pattern.compile("schema\\p{javaDigit}+.xsd"); /** *

The default JavaDocRenderer used unless another JavaDocRenderer should be used.

* * @see #javaDocRenderer * @since 2.0 */ public static final JavaDocRenderer STANDARD_JAVADOC_RENDERER = new DefaultJavaDocRenderer(); /** *

Default exclude file name suffixes for testSources, used unless overridden by an * explicit configuration in the {@code testSourceExcludeSuffixes} parameter. *

*
     *     
     *         final List<Filter<File>> schemagenTmp = new ArrayList<Filter<File>>();
     *         schemagenTmp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
     *         schemagenTmp.add(new PatternFileFilter(Arrays.asList("\\.java", "\\.scala", "\\.mdo"), false));
     *         STANDARD_BYTECODE_EXCLUDE_FILTERS = Collections.unmodifiableList(schemagenTmp);
     *     
     * 
*/ public static final List> STANDARD_BYTECODE_EXCLUDE_FILTERS; /** * Filter list containing a PatternFileFilter including ".class" files. */ public static final List> CLASS_INCLUDE_FILTERS; /** * Specification for packages which must be loaded using the SystemToolClassLoader (and not in the plugin's * ThreadContext ClassLoader). The SystemToolClassLoader is used by SchemaGen to process some stuff from the * {@code tools.jar} archive, in particular its exception types used to signal JAXB annotation Exceptions. * * @see ToolProvider#getSystemToolClassLoader() */ public static final List SYSTEM_TOOLS_CLASSLOADER_PACKAGES = Arrays.asList( "com.sun.source.util", "com.sun.source.tree"); static { final List> schemagenTmp = new ArrayList>(); schemagenTmp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS); schemagenTmp.add(new PatternFileFilter(Arrays.asList("\\.java", "\\.scala", "\\.mdo"), false)); STANDARD_BYTECODE_EXCLUDE_FILTERS = Collections.unmodifiableList(schemagenTmp); CLASS_INCLUDE_FILTERS = new ArrayList>(); CLASS_INCLUDE_FILTERS.add(new PatternFileFilter(Arrays.asList("\\.class"), true)); } // Internal state private static final int SCHEMAGEN_INCORRECT_OPTIONS = -1; private static final int SCHEMAGEN_COMPLETED_OK = 0; private static final int SCHEMAGEN_JAXB_ERRORS = 1; /** *

A List holding desired schema mappings, each of which binds a schema namespace URI to its desired prefix * [optional] and the name of the resulting schema file [optional]. All given elements (uri, prefix, file) must be * unique within the configuration; no two elements may have the same values.

*

The example schema configuration below maps two namespace uris to prefixes and generated file names. This implies * that http://some/namespace will be represented by the prefix some within the generated XML * Schema files; creating namespace definitions on the form xmlns:some="http://some/namespace", and * corresponding uses on the form <xs:element minOccurs="0" * ref="some:anOptionalElementInSomeNamespace"/>. Moreover, the file element defines that the * http://some/namespace definitions will be written to the file some_schema.xsd, and that all * import references will be on the form <xs:import namespace="http://some/namespace" * schemaLocation="some_schema.xsd"/>

*

The example configuration below also performs identical operations for the namespace uri * http://another/namespace with the prefix another and the file another_schema.xsd. *

*
     *     
     * <transformSchemas>
     *   <transformSchema>
     *     <uri>http://some/namespace</uri>
     *     <toPrefix>some</toPrefix>
     *     <toFile>some_schema.xsd</toFile>
     *   <transformSchema>
     *     <uri>http://another/namespace</uri>
     *     <toPrefix>another</toPrefix>
     *     <toFile>another_schema.xsd</toFile>
     *   </transformSchema>
     * </transformSchemas>
     *     
     * 
* * @since 1.4 */ @Parameter private List transformSchemas; /** * Deprecated - will be removed in a future release *

From plugin version 2.4, this parameter will not be used. * Instead, episode files are generated by default with all JAXB operations.

*

Starting with plugin version 2.4, use the parameter {@link #episodeFileName} to provide a custom * name of the generated episode File (or rely on the standard file name {@link #STANDARD_EPISODE_FILENAME}).

* * @since 2.0 * @deprecated */ @Deprecated @Parameter(defaultValue = "true") protected boolean generateEpisode; /** *

Corresponding SchemaGen parameter: {@code episode}.

*

Generate an episode file with the supplied name from this XSD generation, so that other schemas that rely * on this schema can be compiled later and rely on classes that are generated from this compilation. * The generated episode file is simply a JAXB customization file (but with vendor extensions), normally known * as a binding file with the suffix .xjb.

*

If the episodeFileName parameter is not given, the episode file name is synthesized on the form * "episode_" + executionID + ".xjb" - typically something like episode_schemagen.xjb, but * it depends on the actual ID given in the execution element:

*
     *     
     * <executions>
     *     <execution>
     *         <id>schemagen</id>
     *         <goals>
     *             <goal>schemagen</goal>
     *         </goals>
     *     </execution>
     * </executions>
     *      
     * 
* * @see #STANDARD_EPISODE_FILENAME * @since 2.4 */ @Parameter protected String episodeFileName; /** *

If {@code true}, Elements or Attributes in the generated XSD files will be annotated with any * JavaDoc found for their respective properties. If {@code false}, no XML documentation annotations will be * generated in post-processing any results from the JAXB SchemaGenerator.

* * @since 2.0 */ @Parameter(defaultValue = "true") protected boolean createJavaDocAnnotations; /** *

A renderer used to create XML annotation text from JavaDoc comments found within the source code. * Unless another implementation is provided, the standard JavaDocRenderer used is * {@linkplain org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.DefaultJavaDocRenderer}.

* * @see org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.DefaultJavaDocRenderer * @since 2.0 */ @Parameter protected JavaDocRenderer javaDocRenderer; /** *

Removes all files from the output directory before running SchemaGenerator.

* * @since 2.0 */ @Parameter(defaultValue = "true") protected boolean clearOutputDir; /** *

XSD schema files are not generated from POM projects or if no includes have been supplied.

* {@inheritDoc} */ @Override protected boolean shouldExecutionBeSkipped() { boolean toReturn = false; if ("pom".equalsIgnoreCase(getProject().getPackaging())) { warnAboutIncorrectPluginConfiguration("packaging", "POM-packaged projects should not generate XSDs."); toReturn = true; } if (getSources().isEmpty()) { warnAboutIncorrectPluginConfiguration("sources", "At least one Java Source file has to be included."); toReturn = true; } // All done. return toReturn; } /** * {@inheritDoc} */ @Override protected boolean isReGenerationRequired() { // // Use the stale flag method to identify if we should re-generate the XSDs from the sources. // Basically, we should re-generate the XSDs if: // // a) The staleFile does not exist // b) The staleFile exists and is older than one of the sources (Java or XJB files). // "Older" is determined by comparing the modification timestamp of the staleFile and the source files. // final File staleFile = getStaleFile(); final String debugPrefix = "StaleFile [" + FileSystemUtilities.getCanonicalPath(staleFile) + "]"; boolean stale = !staleFile.exists(); if (stale) { getLog().debug(debugPrefix + " not found. XML Schema (re-)generation required."); } else { final List sources = getSources(); if (getLog().isDebugEnabled()) { getLog().debug(debugPrefix + " found. Checking timestamps on source Java " + "files to determine if XML Schema (re-)generation is required."); } final long staleFileLastModified = staleFile.lastModified(); for (URL current : sources) { final URLConnection sourceFileConnection; try { sourceFileConnection = current.openConnection(); sourceFileConnection.connect(); } catch (Exception e) { if (getLog().isDebugEnabled()) { getLog().debug("Could not open a sourceFileConnection to [" + current + "]", e); } // Can't determine if the staleFile is younger than this source. // Re-generate to be on the safe side. stale = true; break; } try { if (sourceFileConnection.getLastModified() > staleFileLastModified) { if (getLog().isDebugEnabled()) { getLog().debug(current.toString() + " is newer than the stale flag file."); } stale = true; } } finally { if (sourceFileConnection instanceof HttpURLConnection) { ((HttpURLConnection) sourceFileConnection).disconnect(); } } } } // All done. return stale; } /** * {@inheritDoc} */ @Override protected boolean performExecution() throws MojoExecutionException, MojoFailureException { boolean updateStaleFileTimestamp = false; ToolExecutionEnvironment environment = null; try { // // Ensure that classes that SchemaGen expects to be loaded in the SystemToolClassLoader // is delegated to that ClassLoader, to comply with SchemaGen's internal reflective loading // of classes. Otherwise we will have ClassCastExceptions instead of proper execution. // final ClassRealm localRealm = (ClassRealm) getClass().getClassLoader(); for (String current : SYSTEM_TOOLS_CLASSLOADER_PACKAGES) { localRealm.importFrom(ToolProvider.getSystemToolClassLoader(), current); } // Configure the ThreadContextClassLoaderBuilder, to enable synthesizing a correct ClassPath for the tool. final ThreadContextClassLoaderBuilder classLoaderBuilder = ThreadContextClassLoaderBuilder .createFor(this.getClass(), getLog(), getEncoding(false)) .addPaths(getClasspath()) .addPaths(getProject().getCompileSourceRoots()); final LocaleFacet localeFacet = locale == null ? null : LocaleFacet.createFor(locale, getLog()); // Create the execution environment as required by the XJC tool. environment = new ToolExecutionEnvironment( getLog(), classLoaderBuilder, LoggingHandlerEnvironmentFacet.create(getLog(), getClass(), getEncoding(false)), localeFacet); final String projectBasedirPath = FileSystemUtilities.getCanonicalPath(getProject().getBasedir()); // Add any extra configured EnvironmentFacets, as configured in the POM. if (extraFacets != null) { for (EnvironmentFacet current : extraFacets) { environment.add(current); } } // Setup the environment. environment.setup(); // Compile the SchemaGen arguments final File episodeFile = getEpisodeFile(episodeFileName); final List sources = getSources(); final String[] schemaGenArguments = getSchemaGenArguments( environment.getClassPathAsArgument(), episodeFile, sources); // Ensure that the outputDirectory and workDirectory exists. // Clear them if configured to do so. FileSystemUtilities.createDirectory(getOutputDirectory(), clearOutputDir); FileSystemUtilities.createDirectory(getWorkDirectory(), clearOutputDir); // Re-generate the episode file's parent directory. getEpisodeFile(episodeFileName); // Do we need to re-create the episode file's parent directory? /*final boolean reCreateEpisodeFileParentDirectory = generateEpisode && clearOutputDir; if (reCreateEpisodeFileParentDirectory) { } */ try { // Check the system properties. // logSystemPropertiesAndBasedir(); // Fire the SchemaGenerator final int result = SchemaGenerator.run( schemaGenArguments, Thread.currentThread().getContextClassLoader()); if (SCHEMAGEN_INCORRECT_OPTIONS == result) { printSchemaGenCommandAndThrowException(projectBasedirPath, sources, schemaGenArguments, result, null); } else if (SCHEMAGEN_JAXB_ERRORS == result) { // TODO: Collect the error message(s) which was emitted by SchemaGen. How can this be done? throw new MojoExecutionException("JAXB errors arose while SchemaGen compiled sources to XML."); } // Copy generated XSDs and episode files from the WorkDirectory to the OutputDirectory, // but do not copy the intermediary bytecode files generated by schemagen. final List> exclusionFilters = PatternFileFilter.createIncludeFilterList( getLog(), "\\.class"); final List toCopy = FileSystemUtilities.resolveRecursively( Arrays.asList(getWorkDirectory()), exclusionFilters, getLog()); for (File current : toCopy) { // Get the path to the current file final String currentPath = FileSystemUtilities.getCanonicalPath(current.getAbsoluteFile()); final File target = new File(getOutputDirectory(), FileSystemUtilities.relativize(currentPath, getWorkDirectory(), true)); // Copy the file to the same relative structure within the output directory. FileSystemUtilities.createDirectory(target.getParentFile(), false); FileUtils.copyFile(current, target); } // // The XSD post-processing should be applied in the following order: // // 1. [XsdAnnotationProcessor]: Inject JavaDoc annotations for Classes. // 2. [XsdEnumerationAnnotationProcessor]: Inject JavaDoc annotations for Enums. // 3. [ChangeNamespacePrefixProcessor]: Change namespace prefixes within XSDs. // 4. [ChangeFilenameProcessor]: Change the fileNames of XSDs. // final boolean performPostProcessing = createJavaDocAnnotations || transformSchemas != null; if (performPostProcessing) { // Map the XML Namespaces to their respective XML URIs (and reverse) // The keys are the generated 'vanilla' XSD file names. final Map resolverMap = XsdGeneratorHelper.getFileNameToResolverMap(getOutputDirectory()); if (createJavaDocAnnotations) { if (getLog().isInfoEnabled()) { getLog().info("XSD post-processing: Adding JavaDoc annotations in generated XSDs."); } // Resolve the sources final List fileSources = new ArrayList(); for (URL current : sources) { if ("file".equalsIgnoreCase(current.getProtocol())) { final File toAdd = new File(current.getPath()); if (toAdd.exists()) { fileSources.add(toAdd); } else { if (getLog().isWarnEnabled()) { getLog().warn("Ignoring URL [" + current + "] as it is a nonexistent file."); } } } } final List files = FileSystemUtilities.resolveRecursively( fileSources, null, getLog()); // Acquire JavaDocs final JavaDocExtractor extractor = new JavaDocExtractor(getLog()).addSourceFiles(files); final SearchableDocumentation javaDocs = extractor.process(); // Modify the 'vanilla' generated XSDs by inserting the JavaDoc as annotations final JavaDocRenderer renderer = javaDocRenderer == null ? STANDARD_JAVADOC_RENDERER : javaDocRenderer; final int numProcessedFiles = XsdGeneratorHelper.insertJavaDocAsAnnotations(getLog(), getEncoding(false), getOutputDirectory(), javaDocs, renderer); if (getLog().isDebugEnabled()) { getLog().info("XSD post-processing: " + numProcessedFiles + " files processed."); } } if (transformSchemas != null) { if (getLog().isInfoEnabled()) { getLog().info("XSD post-processing: Renaming and converting XSDs."); } // Transform all namespace prefixes as requested. XsdGeneratorHelper.replaceNamespacePrefixes(resolverMap, transformSchemas, getLog(), getOutputDirectory(), getEncoding(false)); // Rename all generated schema files as requested. XsdGeneratorHelper.renameGeneratedSchemaFiles(resolverMap, transformSchemas, getLog(), getOutputDirectory(), getEncoding(false)); } } } catch (MojoExecutionException e) { throw e; } catch (Exception e) { // Find the root exception, and print its stack trace to the Maven Log. // These invocation target exceptions tend to produce really deep stack traces, // hiding the actual root cause of the exception. Throwable current = e; while (current.getCause() != null) { current = current.getCause(); } getLog().error("Execution failed."); // // Print a stack trace // StringBuilder rootCauseBuilder = new StringBuilder(); rootCauseBuilder.append("\n"); rootCauseBuilder.append("[Exception]: " + current.getClass().getName() + "\n"); rootCauseBuilder.append("[Message]: " + current.getMessage() + "\n"); for (StackTraceElement el : current.getStackTrace()) { rootCauseBuilder.append(" " + el.toString()).append("\n"); } getLog().error(rootCauseBuilder.toString().replaceAll("[\r\n]+", "\n")); printSchemaGenCommandAndThrowException(projectBasedirPath, sources, schemaGenArguments, -1, current); } // Indicate that the output directory was updated. getBuildContext().refresh(getOutputDirectory()); // Update the modification timestamp of the staleFile. updateStaleFileTimestamp = true; } finally { // Restore the environment if (environment != null) { environment.restore(); } } // Add generated directories to // All done. return updateStaleFileTimestamp; } /** * @return The working directory to which the SchemaGenerator should initially copy all its generated files, * including bytecode files, compiled from java sources. */ protected abstract File getWorkDirectory(); /** * Finds a List containing URLs to compiled bytecode files within this Compilation Unit. * Typically this equals the resolved files under the project's build directories, plus any * JAR artifacts found on the classpath. * * @return A non-null List containing URLs to bytecode files within this compilation unit. * Typically this equals the resolved files under the project's build directories, plus any JAR * artifacts found on the classpath. */ protected abstract List getCompiledClassNames(); /** * Override this method to acquire a List holding all URLs to the SchemaGen Java sources for which this * AbstractXsdGeneratorMojo should generate Xml Schema Descriptor files. * * @return A non-null List holding URLs to sources for the XSD generation. */ @Override protected abstract List getSources(); // // Private helpers // private String[] getSchemaGenArguments(final String classPath, final File episodeFile, final List sources) throws MojoExecutionException { final ArgumentBuilder builder = new ArgumentBuilder(); // Add all flags on the form '-flagName' // builder.withFlag(); // Add all arguments on the form '-argumentName argumentValue' // (i.e. in 2 separate elements of the returned String[]) builder.withNamedArgument("encoding", getEncoding(true)); builder.withNamedArgument("d", getWorkDirectory().getAbsolutePath()); builder.withNamedArgument("classpath", classPath); // From 2.4: Always generate an episode file. // builder.withNamedArgument("episode", FileSystemUtilities.getCanonicalPath(episodeFile)); try { // // The SchemaGenerator does not support directories as arguments: // "Caused by: java.lang.IllegalArgumentException: directories not supported" // ... implying we must resolve source files in the compilation unit. // // There seems to be two ways of adding sources to the SchemaGen tool: // 1) Using java source files // Define the relative paths to source files, calculated from the System.property "user.dir" // (i.e. *not* the Maven "basedir" property) on the form 'src/main/java/se/west/something/SomeClass.java'. // Sample: javac -d . ../github_jaxb2_plugin/src/it/schemagen-main/src/main/java/se/west/gnat/Foo.java // // 2) Using bytecode files // Define the CLASSPATH to point to build output directories (such as target/classes), and then use // package notation arguments on the form 'se.west.something.SomeClass'. // Sample: schemagen -d . -classpath brat se.west.gnat.Foo // // The jaxb2-maven-plugin uses these two methods in the order given. // builder.withPreCompiledArguments(getSchemaGeneratorSourceFiles(sources)); } catch (IOException e) { throw new MojoExecutionException("Could not compile source paths for the SchemaGenerator", e); } // All done. return logAndReturnToolArguments(builder.build(), "SchemaGen"); } /** *

The SchemaGenerator does not support directories as arguments, implying we must resolve source * files in the compilation unit. This fact is shown when supplying a directory argument as source, when * the tool emits: *

Caused by: java.lang.IllegalArgumentException: directories not supported

*

There seems to be two ways of adding sources to the SchemaGen tool:

*
*
1. Java Source files
*
Define the relative paths to source files, calculated from the System.property {@code user.dir} * (i.e. not the Maven {@code basedir} property) on the form * {@code src/main/java/se/west/something/SomeClass.java}.
* Sample: {@code javac -d . . * ./github_jaxb2_plugin/src/it/schemagen-main/src/main/java/se/west/gnat/Foo.java}
*
2. Bytecode files
*
Define the {@code CLASSPATH} to point to build output directories (such as target/classes), and then * use package notation arguments on the form {@code se.west.something.SomeClass}.
* Sample: {@code schemagen -d . -classpath brat se.west.gnat.Foo}
*
*

The jaxb2-maven-plugin uses these two methods in the order given

* * @param sources The compiled sources (as calculated from the local project's * source paths, {@code getSources()}). * @return A sorted List holding all sources to be used by the SchemaGenerator. According to the SchemaGenerator * documentation, the order in which the source arguments are provided is irrelevant. * The sources are to be rendered as the final (open-ended) argument to the schemagen execution. * @see #getSources() */ private List getSchemaGeneratorSourceFiles(final List sources) throws IOException, MojoExecutionException { final SortedMap className2SourcePath = new TreeMap(); final File baseDir = getProject().getBasedir(); final File userDir = new File(System.getProperty("user.dir")); final String encoding = getEncoding(true); // 1) Find/add all sources available in the compilation unit. for (URL current : sources) { final File sourceCodeFile = FileSystemUtilities.getFileFor(current, encoding); // Calculate the relative path for the current source final String relativePath = FileSystemUtilities.relativize( FileSystemUtilities.getCanonicalPath(sourceCodeFile), userDir, true); if (getLog().isDebugEnabled()) { getLog().debug("SourceCodeFile [" + FileSystemUtilities.getCanonicalPath(sourceCodeFile) + "] and userDir [" + FileSystemUtilities.getCanonicalPath(userDir) + "] ==> relativePath: " + relativePath + ". (baseDir: " + FileSystemUtilities.getCanonicalPath(baseDir) + "]"); } // Find the Java class(es) within the source. final JavaProjectBuilder builder = new JavaProjectBuilder(); builder.setEncoding(encoding); // // Ensure that we include package-info.java classes in the SchemaGen compilation. // if (sourceCodeFile.getName().trim().equalsIgnoreCase(PACKAGE_INFO_FILENAME)) { // For some reason, QDox requires the package-info.java to be added as a URL instead of a File. builder.addSource(current); final Collection packages = builder.getPackages(); if (packages.size() != 1) { throw new MojoExecutionException("Exactly one package should be present in file [" + sourceCodeFile.getPath() + "]"); } // Make the key indicate that this is the package-info.java file. final JavaPackage javaPackage = packages.iterator().next(); className2SourcePath.put("package-info for (" + javaPackage.getName() + ")", relativePath); continue; } // This is not a package-info.java file, so QDox lets us add this as a File. builder.addSource(sourceCodeFile); // Map any found FQCN to the relativized path of its source file. for (JavaSource currentJavaSource : builder.getSources()) { for (JavaClass currentJavaClass : currentJavaSource.getClasses()) { final String className = currentJavaClass.getFullyQualifiedName(); if (className2SourcePath.containsKey(className)) { if (getLog().isWarnEnabled()) { getLog().warn("Already mapped. Source class [" + className + "] within [" + className2SourcePath.get(className) + "]. Not overwriting with [" + relativePath + "]"); } } else { className2SourcePath.put(className, relativePath); } } } } /* // 2) Find any bytecode available in the compilation unit, and add its file as a SchemaGen argument. // // The algorithm is: // 1) Add bytecode classpath unless its class is already added in source form. // 2) SchemaGen cannot handle directory arguments, so any bytecode files in classpath directories // must be resolved. // 3) All JARs in the classpath should be added as arguments to SchemaGen. // // .... Gosh ... // for (URL current : getCompiledClassNames()) { getLog().debug(" (compiled ClassName) --> " + current.toExternalForm()); } Filters.initialize(getLog(), CLASS_INCLUDE_FILTERS); final List classPathURLs = new ArrayList(); for (String current : getClasspath()) { final File currentFile = new File(current); if (FileSystemUtilities.EXISTING_FILE.accept(currentFile)) { // This is a file/JAR. Simply add its path to SchemaGen's arguments. classPathURLs.add(FileSystemUtilities.getUrlFor(currentFile)); } else if (FileSystemUtilities.EXISTING_DIRECTORY.accept(currentFile)) { // Resolve all bytecode files within this directory. // FileSystemUtilities.filterFiles(baseDir, ) if (getLog().isDebugEnabled()) { getLog().debug("TODO: Resolve and add bytecode files within: [" + FileSystemUtilities.getCanonicalPath(currentFile) + "]"); } // Find the byte code files within the current directory. final List byteCodeFiles = new ArrayList(); for(File currentResolvedFile : FileSystemUtilities.resolveRecursively( Arrays.asList(currentFile), null, getLog())) { if(Filters.matchAtLeastOnce(currentResolvedFile, CLASS_INCLUDE_FILTERS)) { byteCodeFiles.add(currentResolvedFile); } } for(File currentByteCodeFile : byteCodeFiles) { final String currentCanonicalPath = FileSystemUtilities.getCanonicalPath( currentByteCodeFile.getAbsoluteFile()); final String relativized = FileSystemUtilities.relativize(currentCanonicalPath, FileSystemUtilities.getCanonicalFile(currentFile.getAbsoluteFile())); final String pathFromUserDir = FileSystemUtilities.relativize(currentCanonicalPath, userDir); final String className = relativized.substring(0, relativized.indexOf(".class")) .replace("/", ".") .replace(File.separator, "."); if(!className2SourcePath.containsKey(className)) { className2SourcePath.put(className, pathFromUserDir); if(getLog().isDebugEnabled()) { getLog().debug("Adding ByteCode [" + className + "] at relativized path [" + pathFromUserDir + "]"); } } else { if(getLog().isDebugEnabled()) { getLog().debug("ByteCode [" + className + "] already added. Not re-adding."); } } } } else if (getLog().isWarnEnabled()) { final String suffix = !currentFile.exists() ? " nonexistent" : " was neither a File nor a Directory"; getLog().warn("Classpath part [" + current + "] " + suffix + ". Ignoring it."); } } /* for (URL current : getCompiledClassNames()) { // TODO: FIX THIS! // Get the class information data from the supplied URL for (String currentClassPathElement : getClasspath()) { if(getLog().isDebugEnabled()) { getLog().debug("Checking class path element: [" + currentClassPathElement + "]"); } } if(getLog().isDebugEnabled()) { getLog().debug("Processing compiledClassName: [" + current + "]"); } // Find the Java class(es) within the source. final JavaProjectBuilder builder = new JavaProjectBuilder(); builder.setEncoding(getEncoding(true)); builder.addSource(current); for (JavaSource currentSource : builder.getSources()) { for (JavaClass currentClass : currentSource.getClasses()) { final String className = currentClass.getFullyQualifiedName(); if (className2SourcePath.containsKey(className)) { if (getLog().isWarnEnabled()) { getLog().warn("Already mapped. Source class [" + className + "] within [" + className2SourcePath.get(className) + "]. Not overwriting with [" + className + "]"); } } else { className2SourcePath.put(className, className); } } } } */ if (getLog().isDebugEnabled()) { final int size = className2SourcePath.size(); getLog().debug("[ClassName-2-SourcePath Map (size: " + size + ")] ..."); int i = 0; for (Map.Entry current : className2SourcePath.entrySet()) { getLog().debug(" " + (++i) + "/" + size + ": [" + current.getKey() + "]: " + current.getValue()); } getLog().debug("... End [ClassName-2-SourcePath Map]"); } // Sort the source paths and place them first in the argument array final ArrayList toReturn = new ArrayList(className2SourcePath.values()); Collections.sort(toReturn); // All Done. return toReturn; } private void printSchemaGenCommandAndThrowException(final String projectBasedirPath, final List sources, final String[] schemaGenArguments, final int result, final Throwable cause) throws MojoExecutionException { final StringBuilder errorMsgBuilder = new StringBuilder(); errorMsgBuilder.append("\n+=================== [SchemaGenerator Error '" + (result == -1 ? "" : result) + "']\n"); errorMsgBuilder.append("|\n"); errorMsgBuilder.append("| SchemaGen did not complete its operation correctly.\n"); errorMsgBuilder.append("|\n"); errorMsgBuilder.append("| To re-create the error (and get a proper error message), cd to:\n"); errorMsgBuilder.append("| ").append(projectBasedirPath).append("\n"); errorMsgBuilder.append("| ... and fire the following on a command line/in a shell:\n"); errorMsgBuilder.append("|\n"); final StringBuilder builder = new StringBuilder("schemagen "); for (String current : schemaGenArguments) { builder.append(current).append(" "); } errorMsgBuilder.append("| " + builder.toString() + "\n"); errorMsgBuilder.append("|\n"); errorMsgBuilder.append("| The following source files should be processed by schemagen:\n"); for (int i = 0; i < sources.size(); i++) { errorMsgBuilder.append("| " + i + ": ").append(sources.get(i).toString()).append("\n"); } errorMsgBuilder.append("|\n"); errorMsgBuilder.append("+=================== [End SchemaGenerator Error]\n"); final String msg = errorMsgBuilder.toString().replaceAll("[\r\n]+", "\n"); if (cause != null) { throw new MojoExecutionException(msg, cause); } else { throw new MojoExecutionException(msg); } } } SchemaGenerationMojo.java000066400000000000000000000274131351100213400376560ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemagenerationpackage org.codehaus.mojo.jaxb2.schemageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** *

Mojo that creates XML schema(s) from compile-scope Java sources or binaries * by invoking the JAXB SchemaGenerator. This implementation is tailored to use the * JAXB Reference Implementation from project Kenai.

*

Note that the SchemaGenerationMojo was completely re-implemented for the 2.x versions. * Its configuration semantics and parameter set is not necessarily * backwards compatible with the 1.x plugin versions. If you are * upgrading from version 1.x of the plugin, read the documentation carefully.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ @Mojo(name = "schemagen", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true) public class SchemaGenerationMojo extends AbstractXsdGeneratorMojo { /** * The last part of the stale fileName for this SchemaGenerationMojo. */ public static final String STALE_FILENAME = "schemaGenerationStaleFlag"; /** *

Default exclude file name suffixes for sources, used unless overridden by an * explicit configuration in the {@code sourceExcludeSuffixes} parameter. * The default values are found as follows:

*
     *     
     *         final List<Filter<File>> srcTemp = new ArrayList<Filter<File>>();
     *         srcTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
     *         srcTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb", "\\.xsd", "\\.properties"), true));
     *         STANDARD_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(srcTemp);
     *     
     * 
* * @see #STANDARD_EXCLUDE_FILTERS */ public static final List> STANDARD_SOURCE_EXCLUDE_FILTERS; static { final List> srcTemp = new ArrayList>(); srcTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS); srcTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb", "\\.xsd", "\\.properties"), true)); STANDARD_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(srcTemp); } /** *

Parameter holding List of paths to files and/or directories which should be recursively searched * for Java source files. Only files or directories that actually exist will be included (in the case of files) * or recursively searched for source files to include (in the case of directories or JARs). * Configure using standard Maven structure for Lists:

*
     * 
     *   <configuration>
     *   ...
     *       <sources>
     *          <source>/a/full/absolute/path/to/a/SourceFile.java</source>
     *          <source>target/some/sourceJar.jar</source>
     *          <source>src/main/java</source>
     *      </sources>
     *   </configuration>
     * 
     * 
*

Note: if configured, the sources parameters replace the default * value, which is a List containing the paths to the directories defined by * {@code getProject().getCompileSourceRoots()}.

* * @since 2.0 */ @Parameter(required = false) private List sources; /** *

Parameter holding a List of Filters, used to match all files under the {@code sources} directories * which should not be considered SchemaGenerator source files. (The filters identify files to * exclude, and hence this parameter is called {@code schemaSourceExcludeFilters}). If a file under any of the * source directories matches at least one of the Filters supplied in the {@code schemaSourceExcludeFilters}, * it is not considered an XJC source file, and therefore excluded from processing.

*

If not explicitly provided, the Mojo uses the value within {@code STANDARD_SOURCE_EXCLUDE_FILTERS}. * The algorithm for finding XJC sources is as follows:

*
    *
  1. Find all files given in the sources List. Any Directories provided are searched for files * recursively.
  2. *
  3. Exclude any found files matching any of the supplied {@code schemaSourceExcludeFilters} List.
  4. *
  5. The remaining Files are submitted for processing by the XJC tool.
  6. *
*

Example: The following configuration would exclude any sources whose names end with * {@code .txt} or {@code .foo}:

*
     *     
     *         <configuration>
     *         ...
     *              <schemaSourceExcludeFilters>
     *                  <filter implementation="org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter">
     *                      <patterns>
     *                          <pattern>\.txt</pattern>
     *                          <pattern>\.foo</pattern>
     *                      </patterns>
     *                  </filter>
     *              </schemaSourceExcludeFilters>
     *         </configuration>
     *     
     * 
*

Note that inner workings of the Dependency Injection mechanism used by Maven Plugins (i.e. the DI from * the Plexus container) requires that the full class name to the Filter implementation should be supplied for * each filter, as is illustrated in the sample above. This is true also if you implement custom Filters.

* * @see #STANDARD_SOURCE_EXCLUDE_FILTERS * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.AbstractPatternFilter * @see org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter * @since 2.0 */ @Parameter(required = false) private List> schemaSourceExcludeFilters; /** *

The directory where the generated XML Schema file(s) will be * placed, after all transformations are done.

*/ @Parameter(defaultValue = "${project.build.directory}/generated-resources/schemagen", required = true) private File outputDirectory; /** *

The directory where the {@code schemagen} tool will output XSDs, episode files - and intermediary bytecode * files. From this directory the XSDs and the episode file (but not the bytecode files) will be copied to the * outputDirectory for further processing.

* * @see #outputDirectory */ @Parameter(defaultValue = "${project.build.directory}/schemagen-work/compile_scope", required = true) private File workDirectory; /** * {@inheritDoc} */ @Override protected List getCompiledClassNames() { List> excludeFilters = schemaSourceExcludeFilters == null ? STANDARD_BYTECODE_EXCLUDE_FILTERS : schemaSourceExcludeFilters; Filters.initialize(getLog(), excludeFilters); try { return FileSystemUtilities.filterFiles( getProject().getBasedir(), null, getProject().getCompileClasspathElements(), getLog(), "compiled bytecode", excludeFilters); } catch (DependencyResolutionRequiredException e) { throw new IllegalStateException("Could not resolve dependencies.", e); } } /** * {@inheritDoc} */ @Override protected List getSources() { final List> sourceExcludes = schemaSourceExcludeFilters == null ? STANDARD_SOURCE_EXCLUDE_FILTERS : schemaSourceExcludeFilters; Filters.initialize(getLog(), sourceExcludes); final List defaultSources = getProject().getCompileSourceRoots(); // All Done. return FileSystemUtilities.filterFiles( getProject().getBasedir(), (sources == null) ? defaultSources : sources, defaultSources, getLog(), "sources", sourceExcludes); } /** * {@inheritDoc} */ @Override protected File getOutputDirectory() { return outputDirectory; } /** * {@inheritDoc} */ @Override protected List getClasspath() throws MojoExecutionException { List toReturn = null; try { toReturn = getProject().getCompileClasspathElements(); } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("Could not acquire compile classpath elements from MavenProject", e); } // All done. return toReturn; } /** * {@inheritDoc} */ @Override protected String getStaleFileName() { return STALE_FILENAME; } /** * {@inheritDoc} */ @Override protected File getWorkDirectory() { return workDirectory; } /** * {@inheritDoc} */ @Override protected void addResource(final Resource resource) { if(resource != null) { final String newDirectory = resource.getDirectory(); // Is the supplied resource already added? final List currentResources = getProject().getResources(); if(getLog().isDebugEnabled()) { getLog().debug("Candidate Resource Directory [" + newDirectory + "]"); getLog().debug("Found [" + currentResources.size() + "] current Resources: " + currentResources); } for (Resource current : currentResources) { // Is the resource already added? if(current.getDirectory() != null && current.getDirectory().equalsIgnoreCase(newDirectory)) { getLog().debug("Resource already added [" + newDirectory + "]. Not adding again."); return; } } // Add the new Resource currentResources.add(resource); if(getLog().isDebugEnabled()) { getLog().debug("Added resource [" + newDirectory + "] to existing resources."); } } } } TestSchemaGenerationMojo.java000066400000000000000000000276751351100213400405300ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemagenerationpackage org.codehaus.mojo.jaxb2.schemageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** *

Mojo that creates XML schema(s) from test-scope Java testSources or binaries * by invoking the JAXB SchemaGenerator. This implementation is tailored to use the * JAXB Reference Implementation from project Kenai.

*

Note that the TestSchemaGenerationMojo was completely re-implemented for the 2.x versions. * Its configuration semantics and parameter set is not backwards compatible * with the 1.x plugin versions. If you are upgrading from version 1.x of the plugin, read * the documentation carefully.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ @Mojo(name = "testSchemagen", defaultPhase = LifecyclePhase.GENERATE_TEST_RESOURCES, requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true) public class TestSchemaGenerationMojo extends AbstractXsdGeneratorMojo { /** * The last part of the stale fileName for this TestSchemaGenerationMojo. */ public static final String STALE_FILENAME = "testSchemaGenerationStaleFlag"; /** *

Default exclude file name suffixes for testSources, used unless overridden by an * explicit configuration in the {@code testSchemaSourceExcludeFilters} parameter. * The default values are found as follows:

*
     *     
     *         final List<Filter<File>> testSrcTemp = new ArrayList<Filter<File>>();
     *         testSrcTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS);
     *         testSrcTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb", "\\.xsd", "\\.properties"), true));
     *         STANDARD_TEST_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(testSrcTemp);
     *     
     * 
* * @see #STANDARD_EXCLUDE_FILTERS */ public static final List> STANDARD_TEST_SOURCE_EXCLUDE_FILTERS; static { final List> testSrcTemp = new ArrayList>(); testSrcTemp.addAll(AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS); testSrcTemp.add(new PatternFileFilter(Arrays.asList("\\.xjb", "\\.xsd", "\\.properties"), true)); STANDARD_TEST_SOURCE_EXCLUDE_FILTERS = Collections.unmodifiableList(testSrcTemp); } /** *

Parameter holding List of paths to files and/or directories which should be recursively searched * for Java source files. Only files or directories that actually exist will be included (in the case of files) * or recursively searched for source files to include (in the case of directories or JARs). * Configure using standard Maven structure for Lists:

*
     * 
     *   <configuration>
     *   ...
     *       <testSources>
     *          <testSource>/a/full/absolute/path/to/a/SourceFile.java</testSource>
     *          <testSource>target/some/sourceJar.jar</test>
     *          <testSource>src/test/java</test>
     *      </testSources>
     *   </configuration>
     * 
     * 
*

Note: if configured, the sources parameters replace the default * value, which is a List containing the paths to the directories defined by * {@code getProject().getTestCompileSourceRoots()}.

* * @since 2.0 */ @Parameter(required = false) private List testSources; /** *

Parameter holding a List of Filters, used to match all files under the {@code testSources} directories * which should not be considered SchemaGenerator testSource files. (The filters identify files to * exclude, and hence this parameter is called {@code testSchemaSourceExcludeFilters}). If a file under any of the * testSource directories matches at least one of the Filters supplied in the * {@code testSchemaSourceExcludeFilters}, it is not considered an XJC test source file, and therefore excluded * from processing.

*

If not explicitly provided, the Mojo uses the value within {@code STANDARD_TEST_SOURCE_EXCLUDE_FILTERS}. * The algorithm for finding XJC sources is as follows:

*
    *
  1. Find all files given in the testSources List. Any Directories provided are searched for files * recursively.
  2. *
  3. Exclude any found files matching any of the supplied {@code testSchemaSourceExcludeFilters} List.
  4. *
  5. The remaining Files are submitted for processing by the XJC tool.
  6. *
*

Example: The following configuration would exclude any testSources whose names end with * {@code .txt} or {@code .foo}:

*
     *     
     *         <configuration>
     *         ...
     *              <testSchemaSourceExcludeFilters>
     *                  <filter implementation="org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter">
     *                      <patterns>
     *                          <pattern>\.txt</pattern>
     *                          <pattern>\.foo</pattern>
     *                      </patterns>
     *                  </filter>
     *              </testSchemaSourceExcludeFilters>
     *         </configuration>
     *     
     * 
*

Note that inner workings of the Dependency Injection mechanism used by Maven Plugins (i.e. the DI from * the Plexus container) requires that the full class name to the Filter implementation should be supplied for * each filter, as is illustrated in the sample above. This is true also if you implement custom Filters.

* * @see #STANDARD_TEST_SOURCE_EXCLUDE_FILTERS * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter * @see org.codehaus.mojo.jaxb2.shared.filters.pattern.AbstractPatternFilter * @see org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter */ @Parameter(required = false) private List> testSchemaSourceExcludeFilters; /** *

The directory where the generated XML Schema file(s) will be placed.

*/ @Parameter(defaultValue = "${project.build.directory}/generated-test-resources/schemagen", required = true) private File outputDirectory; /** *

The directory where the {@code schemagen} tool will output XSDs, episode files - and intermediary bytecode * files. From this directory the XSDs and the episode file (but not the bytecode files) will be copied to the * outputDirectory for further processing.

* * @see #outputDirectory */ @Parameter(defaultValue = "${project.build.directory}/schemagen-work/test_scope", required = true) private File testWorkDirectory; /** * {@inheritDoc} */ @Override protected List getCompiledClassNames() { final List> excludeFilters = testSchemaSourceExcludeFilters == null ? STANDARD_BYTECODE_EXCLUDE_FILTERS : testSchemaSourceExcludeFilters; Filters.initialize(getLog(), excludeFilters); final List defaultTestSources = getProject().getTestCompileSourceRoots(); try { return FileSystemUtilities.filterFiles( getProject().getBasedir(), (testSources == null) ? defaultTestSources : testSources, defaultTestSources, getLog(), "test-compiled bytecode", excludeFilters); } catch (Exception e) { throw new IllegalStateException("Could not resolve test classpath elements.", e); } } /** * {@inheritDoc} */ @Override protected List getClasspath() throws MojoExecutionException { List toReturn = null; try { toReturn = getProject().getTestClasspathElements(); } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("Could not acquire compile classpath elements from MavenProject", e); } // All done. return toReturn; } /** * {@inheritDoc} */ @Override protected List getSources() { final List> excludeFilters = testSchemaSourceExcludeFilters == null ? STANDARD_TEST_SOURCE_EXCLUDE_FILTERS : testSchemaSourceExcludeFilters; Filters.initialize(getLog(), excludeFilters); return FileSystemUtilities.filterFiles( getProject().getBasedir(), testSources, getProject().getTestCompileSourceRoots(), getLog(), "test schema sources", excludeFilters); } /** * {@inheritDoc} */ @Override protected File getOutputDirectory() { return outputDirectory; } /** * {@inheritDoc} */ @Override protected String getStaleFileName() { return STALE_FILENAME; } /** * {@inheritDoc} */ @Override protected File getWorkDirectory() { return testWorkDirectory; } /** * {@inheritDoc} */ @Override protected void addResource(final Resource resource) { if (resource != null) { final String newDirectory = resource.getDirectory(); // Is the supplied resource already added? final List currentResources = getProject().getTestResources(); if (getLog().isDebugEnabled()) { getLog().debug("Candidate Test Resource Directory [" + newDirectory + "]"); getLog().debug("Found [" + currentResources.size() + "] current Test Resources: " + currentResources); } for (Resource current : currentResources) { // Is the resource already added? if (current.getDirectory() != null && current.getDirectory().equalsIgnoreCase(newDirectory)) { getLog().debug("Test resource already added [" + newDirectory + "]. Not adding again."); return; } } // Add the new Resource currentResources.add(resource); if (getLog().isDebugEnabled()) { getLog().debug("Added test resource [" + newDirectory + "] to existing test resources."); } } } } XsdGeneratorHelper.java000066400000000000000000000652541351100213400373670ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemagenerationpackage org.codehaus.mojo.jaxb2.schemageneration; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocRenderer; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SearchableDocumentation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdAnnotationProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdEnumerationAnnotationProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.ChangeFilenameProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.ChangeNamespacePrefixProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.TransformSchema; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.BufferedWriter; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * Utility class holding algorithms used when generating XSD schema. * * @author Lennart Jörelid * @since 1.4 */ public final class XsdGeneratorHelper { // Constants private static final String MISCONFIG = "Misconfiguration detected: "; private static TransformerFactory FACTORY; private static final FileFilter RECURSIVE_XSD_FILTER; /** * Hide the constructor for utility classes. */ private XsdGeneratorHelper() { // Do nothing. } static { // Create the static filter used for recursive generated XSD files detection. RECURSIVE_XSD_FILTER = new FileFilter() { @Override public boolean accept(final File toMatch) { if (toMatch.exists()) { // Accept directories for recursive operation, and // files with names matching the SCHEMAGEN_EMITTED_FILENAME Pattern. return toMatch.isDirectory() || AbstractXsdGeneratorMojo.SCHEMAGEN_EMITTED_FILENAME.matcher(toMatch.getName()).matches(); } // Not a directory or XSD file. return false; } }; } /** * Acquires a map relating generated schema filename to its SimpleNamespaceResolver. * * @param outputDirectory The output directory of the generated schema files. * @return a map relating generated schema filename to an initialized SimpleNamespaceResolver. * @throws MojoExecutionException if two generated schema files used the same namespace URI. */ public static Map getFileNameToResolverMap(final File outputDirectory) throws MojoExecutionException { final Map toReturn = new TreeMap(); // Each generated schema file should be written to the output directory. // Each generated schema file should have a unique targetNamespace. File[] generatedSchemaFiles = outputDirectory.listFiles(new FileFilter() { public boolean accept(File pathname) { return pathname.getName().startsWith("schema") && pathname.getName().endsWith(".xsd"); } }); for (File current : generatedSchemaFiles) { toReturn.put(current.getName(), new SimpleNamespaceResolver(current)); } return toReturn; } /** * Validates that the list of Schemas provided within the configuration all contain unique values. Should a * MojoExecutionException be thrown, it contains informative text about the exact nature of the configuration * problem - we should simplify for all plugin users. * * @param configuredTransformSchemas The List of configuration schemas provided to this mojo. * @throws MojoExecutionException if any two configuredSchemas instances contain duplicate values for any of the * properties uri, prefix or file. Also throws a MojoExecutionException if the uri of any Schema is null * or empty, or if none of the 'file' and 'prefix' properties are given within any of the * configuredSchema instances. */ public static void validateSchemasInPluginConfiguration(final List configuredTransformSchemas) throws MojoExecutionException { final List uris = new ArrayList(); final List prefixes = new ArrayList(); final List fileNames = new ArrayList(); for (int i = 0; i < configuredTransformSchemas.size(); i++) { final TransformSchema current = configuredTransformSchemas.get(i); final String currentURI = current.getUri(); final String currentPrefix = current.getToPrefix(); final String currentFile = current.getToFile(); // We cannot work with a null or empty uri if (StringUtils.isEmpty(currentURI)) { throw new MojoExecutionException(MISCONFIG + "Null or empty property 'uri' found in " + "plugin configuration for schema element at index [" + i + "]: " + current); } // No point in having *only* a namespace. if (StringUtils.isEmpty(currentPrefix) && StringUtils.isEmpty(currentFile)) { throw new MojoExecutionException(MISCONFIG + "Null or empty properties 'prefix' " + "and 'file' found within plugin configuration for schema element at index [" + i + "]: " + current); } // Validate that all given uris are unique. if (uris.contains(currentURI)) { throw new MojoExecutionException(getDuplicationErrorMessage("uri", currentURI, uris.indexOf(currentURI), i)); } uris.add(currentURI); // Validate that all given prefixes are unique. if (prefixes.contains(currentPrefix) && !(currentPrefix == null)) { throw new MojoExecutionException(getDuplicationErrorMessage("prefix", currentPrefix, prefixes.indexOf(currentPrefix), i)); } prefixes.add(currentPrefix); // Validate that all given files are unique. if (fileNames.contains(currentFile)) { throw new MojoExecutionException(getDuplicationErrorMessage("file", currentFile, fileNames.indexOf(currentFile), i)); } fileNames.add(currentFile); } } /** * Inserts XML documentation annotations into all generated XSD files found * within the supplied outputDir. * * @param log A Maven Log. * @param outputDir The outputDir, where generated XSD files are found. * @param docs The SearchableDocumentation for the source files within the compilation unit. * @param renderer The JavaDocRenderer used to convert JavaDoc annotations into XML documentation annotations. * @return The number of processed XSDs. */ public static int insertJavaDocAsAnnotations(final Log log, final String encoding, final File outputDir, final SearchableDocumentation docs, final JavaDocRenderer renderer) { // Check sanity Validate.notNull(docs, "docs"); Validate.notNull(log, "log"); Validate.notNull(outputDir, "outputDir"); Validate.isTrue(outputDir.isDirectory(), "'outputDir' must be a Directory."); Validate.notNull(renderer, "renderer"); int processedXSDs = 0; final List foundFiles = new ArrayList(); addRecursively(foundFiles, RECURSIVE_XSD_FILTER, outputDir); if (foundFiles.size() > 0) { // Create the processors. final XsdAnnotationProcessor classProcessor = new XsdAnnotationProcessor(docs, renderer); final XsdEnumerationAnnotationProcessor enumProcessor = new XsdEnumerationAnnotationProcessor(docs, renderer); for (File current : foundFiles) { // Create an XSD document from the current File. final Document generatedSchemaFileDocument = parseXmlToDocument(current); // Replace all namespace prefixes within the provided document. process(generatedSchemaFileDocument.getFirstChild(), true, classProcessor); processedXSDs++; // Overwrite the vanilla file. savePrettyPrintedDocument(generatedSchemaFileDocument, current, encoding); } } else { if (log.isWarnEnabled()) { log.warn("Found no generated 'vanilla' XSD files to process under [" + FileSystemUtilities.getCanonicalPath(outputDir) + "]. Aborting processing."); } } // All done. return processedXSDs; } /** * Replaces all namespaces within generated schema files, as instructed by the configured Schema instances. * * @param resolverMap The map relating generated schema file name to SimpleNamespaceResolver instances. * @param configuredTransformSchemas The Schema instances read from the configuration of this plugin. * @param mavenLog The active Log. * @param schemaDirectory The directory where all generated schema files reside. * @param encoding The encoding to use when writing the file. * @throws MojoExecutionException If the namespace replacement could not be done. */ public static void replaceNamespacePrefixes( final Map resolverMap, final List configuredTransformSchemas, final Log mavenLog, final File schemaDirectory, final String encoding) throws MojoExecutionException { if (mavenLog.isDebugEnabled()) { mavenLog.debug("Got resolverMap.keySet() [generated filenames]: " + resolverMap.keySet()); } for (SimpleNamespaceResolver currentResolver : resolverMap.values()) { File generatedSchemaFile = new File(schemaDirectory, currentResolver.getSourceFilename()); Document generatedSchemaFileDocument = null; for (TransformSchema currentTransformSchema : configuredTransformSchemas) { // Should we alter the namespace prefix as instructed by the current schema? final String newPrefix = currentTransformSchema.getToPrefix(); final String currentUri = currentTransformSchema.getUri(); if (StringUtils.isNotEmpty(newPrefix)) { // Find the old/current prefix of the namespace for the current schema uri. final String oldPrefix = currentResolver.getNamespaceURI2PrefixMap().get(currentUri); if (StringUtils.isNotEmpty(oldPrefix)) { // Can we perform the prefix substitution? validatePrefixSubstitutionIsPossible(oldPrefix, newPrefix, currentResolver); if (mavenLog.isDebugEnabled()) { mavenLog.debug("Subtituting namespace prefix [" + oldPrefix + "] with [" + newPrefix + "] in file [" + currentResolver.getSourceFilename() + "]."); } // Get the Document of the current schema file. if (generatedSchemaFileDocument == null) { generatedSchemaFileDocument = parseXmlToDocument(generatedSchemaFile); } // Replace all namespace prefixes within the provided document. process(generatedSchemaFileDocument.getFirstChild(), true, new ChangeNamespacePrefixProcessor(oldPrefix, newPrefix)); } } } if (generatedSchemaFileDocument != null) { // Overwrite the generatedSchemaFile with the content of the generatedSchemaFileDocument. mavenLog.debug("Overwriting file [" + currentResolver.getSourceFilename() + "] with content [" + getHumanReadableXml(generatedSchemaFileDocument) + "]"); savePrettyPrintedDocument(generatedSchemaFileDocument, generatedSchemaFile, encoding); } else { mavenLog.debug("No namespace prefix changes to generated schema file [" + generatedSchemaFile.getName() + "]"); } } } /** * Updates all schemaLocation attributes within the generated schema files to match the 'file' properties within the * Schemas read from the plugin configuration. After that, the files are physically renamed. * * @param resolverMap The map relating generated schema file name to SimpleNamespaceResolver instances. * @param configuredTransformSchemas The Schema instances read from the configuration of this plugin. * @param mavenLog The active Log. * @param schemaDirectory The directory where all generated schema files reside. * @param charsetName The encoding / charset name. */ public static void renameGeneratedSchemaFiles(final Map resolverMap, final List configuredTransformSchemas, final Log mavenLog, final File schemaDirectory, final String charsetName) { // Create the map relating namespace URI to desired filenames. Map namespaceUriToDesiredFilenameMap = new TreeMap(); for (TransformSchema current : configuredTransformSchemas) { if (StringUtils.isNotEmpty(current.getToFile())) { namespaceUriToDesiredFilenameMap.put(current.getUri(), current.getToFile()); } } // Replace the schemaLocation values to correspond to the new filenames for (SimpleNamespaceResolver currentResolver : resolverMap.values()) { File generatedSchemaFile = new File(schemaDirectory, currentResolver.getSourceFilename()); Document generatedSchemaFileDocument = parseXmlToDocument(generatedSchemaFile); // Replace all namespace prefixes within the provided document. process(generatedSchemaFileDocument.getFirstChild(), true, new ChangeFilenameProcessor(namespaceUriToDesiredFilenameMap)); // Overwrite the generatedSchemaFile with the content of the generatedSchemaFileDocument. if (mavenLog.isDebugEnabled()) { mavenLog.debug("Changed schemaLocation entries within [" + currentResolver.getSourceFilename() + "]. " + "Result: [" + getHumanReadableXml(generatedSchemaFileDocument) + "]"); } savePrettyPrintedDocument(generatedSchemaFileDocument, generatedSchemaFile, charsetName); } // Now, rename the actual files. for (SimpleNamespaceResolver currentResolver : resolverMap.values()) { final String localNamespaceURI = currentResolver.getLocalNamespaceURI(); if (StringUtils.isEmpty(localNamespaceURI)) { mavenLog.warn("SimpleNamespaceResolver contained no localNamespaceURI; aborting rename."); continue; } final String newFilename = namespaceUriToDesiredFilenameMap.get(localNamespaceURI); final File originalFile = new File(schemaDirectory, currentResolver.getSourceFilename()); if (StringUtils.isNotEmpty(newFilename)) { File renamedFile = FileUtils.resolveFile(schemaDirectory, newFilename); String renameResult = (originalFile.renameTo(renamedFile) ? "Success " : "Failure "); if (mavenLog.isDebugEnabled()) { String suffix = "renaming [" + originalFile.getAbsolutePath() + "] to [" + renamedFile + "]"; mavenLog.debug(renameResult + suffix); } } } } /** * Drives the supplied visitor to process the provided Node and all its children, should the recurseToChildren flag * be set to true. All attributes of the current node are processed before recursing to children (i.e. * breadth first recursion). * * @param node The Node to process. * @param recurseToChildren if true, processes all children of the supplied node recursively. * @param visitor The NodeProcessor instance which should process the nodes. */ public static void process(final Node node, final boolean recurseToChildren, final NodeProcessor visitor) { // Process the current Node, if the NodeProcessor accepts it. if (visitor.accept(node)) { visitor.process(node); } NamedNodeMap attributes = node.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node attribute = attributes.item(i); // Process the current attribute, if the NodeProcessor accepts it. if (visitor.accept(attribute)) { visitor.process(attribute); } } if (recurseToChildren) { NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); // Recurse to Element children. if (child.getNodeType() == Node.ELEMENT_NODE) { process(child, true, visitor); } } } } /** * Parses the provided InputStream to create a dom Document. * * @param xmlStream An InputStream connected to an XML document. * @return A DOM Document created from the contents of the provided stream. */ public static Document parseXmlStream(final Reader xmlStream) { // Build a DOM model of the provided xmlFileStream. final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); try { return factory.newDocumentBuilder().parse(new InputSource(xmlStream)); } catch (Exception e) { throw new IllegalArgumentException("Could not acquire DOM Document", e); } } /** * Converts the provided DOM Node to a pretty-printed XML-formatted string. * * @param node The Node whose children should be converted to a String. * @return a pretty-printed XML-formatted string. */ protected static String getHumanReadableXml(final Node node) { StringWriter toReturn = new StringWriter(); try { Transformer transformer = getFactory().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); transformer.transform(new DOMSource(node), new StreamResult(toReturn)); } catch (TransformerException e) { throw new IllegalStateException("Could not transform node [" + node.getNodeName() + "] to XML", e); } return toReturn.toString(); } // // Private helpers // private static String getDuplicationErrorMessage(final String propertyName, final String propertyValue, final int firstIndex, final int currentIndex) { return MISCONFIG + "Duplicate '" + propertyName + "' property with value [" + propertyValue + "] found in plugin configuration. Correct schema elements index (" + firstIndex + ") and (" + currentIndex + "), to ensure that all '" + propertyName + "' values are unique."; } /** * Validates that the transformation from oldPrefix to newPrefix is possible, in that * newPrefix is not already used by a schema file. This would corrupt the schema by assigning elements * from one namespace to another. * * @param oldPrefix The old/current namespace prefix. * @param newPrefix The new/future namespace prefix. * @param currentResolver The currently active SimpleNamespaceResolver. * @throws MojoExecutionException if any schema file currently uses newPrefix. */ private static void validatePrefixSubstitutionIsPossible(final String oldPrefix, final String newPrefix, final SimpleNamespaceResolver currentResolver) throws MojoExecutionException { // Make certain the newPrefix does not exist already. if (currentResolver.getNamespaceURI2PrefixMap().containsValue(newPrefix)) { throw new MojoExecutionException(MISCONFIG + "Namespace prefix [" + newPrefix + "] is already in use." + " Cannot replace namespace prefix [" + oldPrefix + "] with [" + newPrefix + "] in file [" + currentResolver.getSourceFilename() + "]."); } } /** * Creates a Document from parsing the XML within the provided xmlFile. * * @param xmlFile The XML file to be parsed. * @return The Document corresponding to the xmlFile. */ private static Document parseXmlToDocument(final File xmlFile) { Document result = null; Reader reader = null; try { reader = new FileReader(xmlFile); result = parseXmlStream(reader); } catch (FileNotFoundException e) { // This should never happen... } finally { IOUtil.close(reader); } return result; } private static void savePrettyPrintedDocument(final Document toSave, final File targetFile, final String charsetName) { Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), charsetName)); out.write(getHumanReadableXml(toSave.getFirstChild())); } catch (IOException e) { throw new IllegalStateException("Could not write to file [" + targetFile.getAbsolutePath() + "]", e); } finally { IOUtil.close(out); } } private static void addRecursively(final List toPopulate, final FileFilter fileFilter, final File aDir) { // Check sanity Validate.notNull(toPopulate, "toPopulate"); Validate.notNull(fileFilter, "fileFilter"); Validate.notNull(aDir, "aDir"); // Add all matching files. for (File current : aDir.listFiles(fileFilter)) { if (current.isFile()) { toPopulate.add(current); } else if (current.isDirectory()) { addRecursively(toPopulate, fileFilter, current); } } } private static TransformerFactory getFactory() { if (FACTORY == null) { try { FACTORY = TransformerFactory.newInstance(); // Harmonize XML formatting for (String currentAttributeName : Arrays.asList("indent-number", OutputKeys.INDENT)) { try { FACTORY.setAttribute(currentAttributeName, 2); } catch (IllegalArgumentException ex) { // Ignore this. } } } catch (Throwable exception) { // This should really not happen... but it seems to happen in some test cases. throw new IllegalStateException("Could not acquire TransformerFactory implementation.", exception); } } // All done. return FACTORY; } }package-info.java000066400000000000000000000012361351100213400361340ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/** *

The jaxb2-maven-plugin wraps and adapts the JAXB reference implementation * to be useful within the Maven build process.

*

The schemageneneration package (including subpackages) contains Mojos for generating XSD files from * annotated Java classes. It also contains subpackages for post-processing the results of the schemagen tool, * to create XSDs with better usability than the XSDs generated by default.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ package org.codehaus.mojo.jaxb2.schemageneration;postprocessing/000077500000000000000000000000001351100213400360255ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemagenerationNodeProcessor.java000066400000000000000000000027721351100213400414650ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.w3c.dom.Node; /** * Processor/visitor pattern specification for DOM Nodes. * * @author Lennart Jörelid * @since 1.4 */ public interface NodeProcessor { /** * Defines if this visitor should process the provided node. * * @param aNode The DOM node to process. * @return true if the provided Node should be processed by this NodeProcessor. */ boolean accept(Node aNode); /** * Processes the provided DOM Node. * * @param aNode The DOM Node to process. */ void process(Node aNode); }javadoc/000077500000000000000000000000001351100213400374345ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingDefaultJavaDocRenderer.java000066400000000000000000000072461351100213400446130ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.util.Map; /** *

Default JavaDocRenderer implementation which provides a plain JavaDocData rendering, on the form:

*
 *     [JavaDoc comment]
 *     (tag1): [tag1 value]
 *     (tag2): [tag2 value]
 * 
* * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class DefaultJavaDocRenderer implements JavaDocRenderer { /** * {@inheritDoc} */ @Override public String render(final JavaDocData nonNullData, final SortableLocation location) { // Compile the XSD documentation string for this Node. final StringBuilder builder = new StringBuilder(); // First, render the JavaDoc comment. builder.append(renderJavaDocComment(nonNullData.getComment(), location)).append("\n"); // Then, render each JavaDoc tag. for (Map.Entry current : nonNullData.getTag2ValueMap().entrySet()) { final String tagXsdDoc = renderJavaDocTag(current.getKey(), current.getValue(), location); if (tagXsdDoc != null && !tagXsdDoc.isEmpty()) { builder.append(tagXsdDoc); } } // All done. return builder.toString(); } /** * Override this method to yield another rendering of the javadoc comment. * * @param comment The comment to render. * @param location the SortableLocation where the JavaDocData was harvested. Never {@code null}. * @return The XSD documentation for the supplied JavaDoc comment. A null or empty value will not be rendered. */ protected String renderJavaDocComment(final String comment, final SortableLocation location) { return harmonizeNewlines(comment); } /** * Override this method to yield another * * @param name The name of a JavaDoc tag. * @param value The value of a JavaDoc tag. * @param location the SortableLocation where the JavaDocData was harvested. Never {@code null}. * @return The XSD documentation for the supplied JavaDoc tag. */ protected String renderJavaDocTag(final String name, final String value, final SortableLocation location) { final String nameKey = name != null ? name.trim() : ""; final String valueKey = value != null ? value.trim() : ""; // All Done. return "(" + nameKey + "): " + harmonizeNewlines(valueKey); } /** * Squashes newline characters into * * @param original the original string, potentially containing newline characters. * @return A string where all newline characters are removed */ protected String harmonizeNewlines(final String original) { final String toReturn = original.trim().replaceAll("[\r\n]+", "\n"); return toReturn.endsWith("\n") ? toReturn : toReturn + "\n"; } } DomHelper.java000066400000000000000000000443601351100213400421650ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.ClassLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.FieldLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.MethodLocation; import org.w3c.dom.CDATASection; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import javax.xml.XMLConstants; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.SortedMap; /** * Helper class stashing commonly used algorithms to work with DOM documents. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.3 */ public final class DomHelper { private static final String NAME_ATTRIBUTE = "name"; private static final String VALUE_ATTRIBUTE = "value"; /** * The name of the annotation element. */ public static final String ANNOTATION_ELEMENT_NAME = "annotation"; /** * The name of the documentation element. */ public static final String DOCUMENTATION_ELEMENT_NAME = "documentation"; /** * The namespace schema prefix for the URI {@code http://www.w3.org/2001/XMLSchema} * (i.e. {@code XMLConstants.W3C_XML_SCHEMA_NS_URI}). * * @see javax.xml.XMLConstants#W3C_XML_SCHEMA_NS_URI */ public static final String XSD_SCHEMA_NAMESPACE_PREFIX = "xs"; /** * The names of DOM Elements corresponding to Java class Fields or Methods. */ public static final List CLASS_FIELD_METHOD_ELEMENT_NAMES = Arrays.asList("element", "attribute"); /** * The names of DOM Elements corresponding to Java enum Fields or Methods. */ public static final List ENUMERATION_FIELD_METHOD_ELEMENT_NAMES = Collections.singletonList("enumeration"); /* * Hide constructor for utility classes */ private DomHelper() { } /** * Retrieves the value of the {@code name} attribute of the supplied Node. * * @param aNode A DOM Node. * @return the value of the {@code name} attribute of the supplied Node/Element. */ public static String getNameAttribute(final Node aNode) { return getNamedAttribute(aNode, NAME_ATTRIBUTE); } /** * Retrieves the value of the {@code value} attribute of the supplied Node. * * @param aNode A DOM Node. * @return the value of the {@code value} attribute of the supplied Node/Element. */ public static String getValueAttribute(final Node aNode) { return getNamedAttribute(aNode, VALUE_ATTRIBUTE); } /** * Checks if the supplied DOM Node is a DOM Element having a defined "name" attribute. * * @param aNode A DOM Node. * @return {@code true} if the supplied aNode is an Elemnet having a defined "name" attribute. */ public static boolean isNamedElement(final Node aNode) { final boolean isElementNode = aNode != null && aNode.getNodeType() == Node.ELEMENT_NODE; return isElementNode && getNamedAttribute(aNode, NAME_ATTRIBUTE) != null && !getNamedAttribute(aNode, NAME_ATTRIBUTE).isEmpty(); } /** * Retrieves the TagName for the supplied Node if it is an Element, and null otherwise. * * @param aNode A DOM Node. * @return The TagName of the Node if it is an Element, and null otherwise. */ public static String getElementTagName(final Node aNode) { if (aNode != null && aNode.getNodeType() == Node.ELEMENT_NODE) { final Element theElement = (Element) aNode; return theElement.getTagName(); } // The Node was not an Element. return null; } /** *

Adds the given formattedDocumentation within an XML documentation annotation under the supplied Node. * Only adds the documentation annotation if the formattedDocumentation is non-null and non-empty. The * documentation annotation is on the form:

*
     *     
     *         <xs:annotation>
     *             <xs:documentation>(JavaDoc here, within a CDATA section)</xs:documentation>
     *         </xs:annotation>
     *     
     * 
* * @param aNode The non-null Node to which an XML documentation annotation should be added. * @param formattedDocumentation The documentation text to add. */ public static void addXmlDocumentAnnotationTo(final Node aNode, final String formattedDocumentation) { if (aNode != null && formattedDocumentation != null && !formattedDocumentation.isEmpty()) { // Add the new Elements, as required. final Document doc = aNode.getOwnerDocument(); final Element annotation = doc.createElementNS( XMLConstants.W3C_XML_SCHEMA_NS_URI, ANNOTATION_ELEMENT_NAME); final Element docElement = doc.createElementNS( XMLConstants.W3C_XML_SCHEMA_NS_URI, DOCUMENTATION_ELEMENT_NAME); final CDATASection xsdDocumentation = doc.createCDATASection(formattedDocumentation); // Set the prefixes annotation.setPrefix(XSD_SCHEMA_NAMESPACE_PREFIX); docElement.setPrefix(XSD_SCHEMA_NAMESPACE_PREFIX); // Inject the formattedDocumentation into the CDATA section. annotation.appendChild(docElement); final Node firstChildOfCurrentNode = aNode.getFirstChild(); if (firstChildOfCurrentNode == null) { aNode.appendChild(annotation); } else { aNode.insertBefore(annotation, firstChildOfCurrentNode); } // All Done. docElement.appendChild(xsdDocumentation); } } /** * Retrieves the XPath for the supplied Node within its document. * * @param aNode The DOM Node for which the XPath should be retrieved. * @return The XPath to the supplied DOM Node. */ public static String getXPathFor(final Node aNode) { List nodeNameList = new ArrayList(); for (Node current = aNode; current != null; current = current.getParentNode()) { final String currentNodeName = current.getNodeName(); final String nameAttribute = DomHelper.getNameAttribute(current); if (currentNodeName.toLowerCase().endsWith("enumeration")) { // We should print the "value" attribute here. nodeNameList.add(currentNodeName + "[@value='" + getValueAttribute(current) + "']"); } else if (nameAttribute == null) { // Just emit the node's name. nodeNameList.add(current.getNodeName()); } else { // We should print the "name" attribute here. nodeNameList.add(current.getNodeName() + "[@name='" + nameAttribute + "']"); } } StringBuilder builder = new StringBuilder(); for (ListIterator it = nodeNameList.listIterator(nodeNameList.size()); it.hasPrevious(); ) { builder.append(it.previous()); if (it.hasPrevious()) { builder.append("/"); } } return builder.toString(); } /** * Retrieves the ClassLocation for the supplied aNode. * * @param aNode A non-null DOM Node. * @param classLocations The set of known ClassLocations, extracted from the JavaDocs. * @return the ClassLocation matching the supplied Node */ public static ClassLocation getClassLocation(final Node aNode, final Set classLocations) { if (aNode != null) { // The LocalName of the supplied DOM Node should be either "complexType" or "simpleType". final String nodeLocalName = aNode.getLocalName(); final boolean acceptableType = "complexType".equalsIgnoreCase(nodeLocalName) || "simpleType".equalsIgnoreCase(nodeLocalName); if (acceptableType) { final String nodeClassName = DomHelper.getNameAttribute(aNode); for (ClassLocation current : classLocations) { // TODO: Ensure that the namespace of the supplied aNode matches the expected namespace. // Issue #25: Handle XML Type renaming. final String effectiveClassName = current.getAnnotationRenamedTo() == null ? current.getClassName() : current.getAnnotationRenamedTo(); if (effectiveClassName.equalsIgnoreCase(nodeClassName)) { return current; } } } } // Nothing found return null; } /** * Finds the MethodLocation within the given Set, which corresponds to the supplied DOM Node. * * @param aNode A DOM Node. * @param methodLocations The Set of all found/known MethodLocation instances. * @return The MethodLocation matching the supplied Node - or {@code null} if no match was found. */ public static MethodLocation getMethodLocation(final Node aNode, final Set methodLocations) { MethodLocation toReturn = null; if (aNode != null && CLASS_FIELD_METHOD_ELEMENT_NAMES.contains(aNode.getLocalName().toLowerCase())) { final MethodLocation validLocation = getFieldOrMethodLocationIfValid(aNode, getContainingClassOrNull(aNode), methodLocations); // The MethodLocation should represent a normal getter; no arguments should be present. if (validLocation != null && MethodLocation.NO_PARAMETERS.equalsIgnoreCase(validLocation.getParametersAsString())) { toReturn = validLocation; } } // All done. return toReturn; } /** * Retrieves a FieldLocation from the supplied Set, provided that the FieldLocation matches the supplied Node. * * @param aNode The non-null Node. * @param fieldLocations The Set of known/found FieldLocation instances. * @return The FieldLocation corresponding to the supplied DOM Node. */ public static FieldLocation getFieldLocation(final Node aNode, final Set fieldLocations) { FieldLocation toReturn = null; if (aNode != null) { if (CLASS_FIELD_METHOD_ELEMENT_NAMES.contains(aNode.getLocalName().toLowerCase())) { // This is a ComplexType which correspond to a Java class. toReturn = getFieldOrMethodLocationIfValid(aNode, getContainingClassOrNull(aNode), fieldLocations); } else if (ENUMERATION_FIELD_METHOD_ELEMENT_NAMES.contains(aNode.getLocalName().toLowerCase())) { // This is a SimpleType which correspond to a Java enum. toReturn = getFieldOrMethodLocationIfValid(aNode, getContainingClassOrNull(aNode), fieldLocations); } } // All done. return toReturn; } /** * Retrieves a FieldLocation or MethodLocation from the supplied Set of Field- or MethodLocations, provided that * the supplied Node has the given containing Node corresponding to a Class or an Enum. * * @param aNode A non-null DOM Node. * @param containingClassNode A Non-null DOM Node corresponding to a Class or Enum. * @param locations A Set containing known/found Field- and MethodLocations. * @param The FieldLocation type. * @return The Matching Field- or MethodLocation. */ public static T getFieldOrMethodLocationIfValid( final Node aNode, final Node containingClassNode, final Set locations) { T toReturn = null; if (containingClassNode != null) { // Do we have a FieldLocation corresponding to the supplied Node? for (FieldLocation current : locations) { // Validate that the field and class names match the FieldLocation's corresponding values, // minding that annotations such as XmlType, XmlElement and XmlAttribute may override the // reflective Class, Field and Method names. // // Note that we cannot match package names here, as the generated XSD does not contain package // information directly. Instead, we must get the Namespace for the generated Class, and compare // it to the effective Namespace of the current Node. // // However, this is a computational-expensive operation, implying we would rather // do it at processing time when the number of nodes are (considerably?) reduced. // Issue #25: Handle XML Type renaming. final String fieldName = current.getAnnotationRenamedTo() == null ? current.getMemberName() : current.getAnnotationRenamedTo(); final String className = current.getClassName(); try { // // Fields in XML enums are rendered on the form // , implying that // we must retrieve the 'value' attribute's value. // // Fields in XML classes are rendered on the form // , implying that // we must retrieve the 'name' attribute's value. // final String attributeValue = DomHelper.getNameAttribute(aNode) == null ? DomHelper.getValueAttribute(aNode) : DomHelper.getNameAttribute(aNode); if (fieldName.equalsIgnoreCase(attributeValue) && className.equalsIgnoreCase(DomHelper.getNameAttribute(containingClassNode))) { toReturn = (T) current; } } catch (Exception e) { throw new IllegalStateException("Could not acquire FieldLocation for fieldName [" + fieldName + "] and className [" + className + "]", e); } } } // All done. return toReturn; } /** * Processes the supplied DOM Node, inserting XML Documentation annotations if applicable. * * @param aNode The DOM Node to process. * @param classJavaDocs A Map relating {@link ClassLocation}s to {@link JavaDocData}. * @param fieldJavaDocs A Map relating {@link FieldLocation}s to {@link JavaDocData}. * @param methodJavaDocs A Map relating {@link MethodLocation}s to {@link JavaDocData}. * @param renderer A non-null {@link JavaDocRenderer}. */ public static void insertXmlDocumentationAnnotationsFor( final Node aNode, final SortedMap classJavaDocs, final SortedMap fieldJavaDocs, final SortedMap methodJavaDocs, final JavaDocRenderer renderer) { JavaDocData javaDocData = null; SortableLocation location = null; // Insert the documentation annotation into the current Node. final ClassLocation classLocation = DomHelper.getClassLocation(aNode, classJavaDocs.keySet()); if (classLocation != null) { javaDocData = classJavaDocs.get(classLocation); location = classLocation; } else { final FieldLocation fieldLocation = DomHelper.getFieldLocation(aNode, fieldJavaDocs.keySet()); if (fieldLocation != null) { javaDocData = fieldJavaDocs.get(fieldLocation); location = fieldLocation; } else { final MethodLocation methodLocation = DomHelper.getMethodLocation(aNode, methodJavaDocs.keySet()); if (methodLocation != null) { javaDocData = methodJavaDocs.get(methodLocation); location = methodLocation; } } } // We should have a JavaDocData here. if (javaDocData == null) { final String nodeName = aNode.getNodeName(); String humanReadableName = DomHelper.getNameAttribute(aNode); if (humanReadableName == null && nodeName.toLowerCase().endsWith("enumeration")) { humanReadableName = "enumeration#" + getValueAttribute(aNode); } throw new IllegalStateException("Could not find JavaDocData for XSD node [" + humanReadableName + "] with XPath [" + DomHelper.getXPathFor(aNode) + "]"); } // Add the XML documentation annotation. final String processedJavaDoc = renderer.render(javaDocData, location).trim(); DomHelper.addXmlDocumentAnnotationTo(aNode, processedJavaDoc); } // // Private helpers // private static Node getContainingClassOrNull(final Node aNode) { for (Node current = aNode.getParentNode(); current != null; current = current.getParentNode()) { final String localName = current.getLocalName(); final boolean foundClassMatch = "complexType".equalsIgnoreCase(localName) || "simpleType".equalsIgnoreCase(localName); if (foundClassMatch) { return current; } } // No parent Node found. return null; } private static String getNamedAttribute(final Node aNode, final String attributeName) { // Fail fast if (aNode == null) { return null; } final NamedNodeMap attributes = aNode.getAttributes(); if (attributes != null) { final Node nameNode = attributes.getNamedItem(attributeName); if (nameNode != null) { return nameNode.getNodeValue().trim(); } } // Not found. return null; } } JavaDocData.java000066400000000000000000000105511351100213400424020ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import com.thoughtworks.qdox.model.DocletTag; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; /** * Simplified structure containing comments and tags read from a JavaDoc comment block. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class JavaDocData { /** * Substitution value for when no JavaDoc comment text was found within a JavaDoc comment block. */ public static final String NO_COMMENT = ""; // Internal state private String comment; private SortedMap tag2ValueMap; /** * Creates a JavaDocData for a particular entry with the supplied JavaDoc comment and List of DocletTags. * * @param comment The actual comment in the JavaDoc. Null values are replaced with the value {@code NO_COMMENT}, * to ensure that the {@code getComment() } method does not return null values. * @param tags The DocletTags of the JavaDoc entry. Can be null or empty. */ public JavaDocData(final String comment, final List tags) { // Assign internal state this.comment = comment == null ? NO_COMMENT : comment; this.tag2ValueMap = new TreeMap(); // Parse, and assign internal state for (DocletTag current : tags) { final String tagName = current.getName(); String tagValue = current.getValue(); // Handle the case of multi-valued tags, such as // // @author SomeAuthor // @author AnotherAuthor // // which becomes [author] --> [SomeAuthor, AnotherAuthor] String currentValue = tag2ValueMap.get(tagName); if (currentValue != null) { tagValue = currentValue + ", " + current.getValue(); } tag2ValueMap.put(tagName, tagValue); } } /** * Retrieves the comment/text in the JavaDoc structure, minus the names and values of any given JavaDoc tags. * * @return the comment/text in the JavaDoc structure, or {@code NO_COMMENT} if no JavaDoc was provided. * Never returns a {@code null} value. */ public String getComment() { return comment; } /** * Retrieves the names and values of all JavaDoc tags found. * If two tags were found (such as two {@code @author} tags, the * value contains all found * * @return A non-null Map relating the names of all supplied JavaDoc Tags to their value(s). */ public SortedMap getTag2ValueMap() { return tag2ValueMap; } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder toReturn = new StringBuilder(); toReturn.append("\n+=================\n"); toReturn.append("| Comment: ").append(comment).append("\n"); if (tag2ValueMap.size() == 0) { toReturn.append("| No JavaDoc tags.\n"); } else { toReturn.append("| ").append(tag2ValueMap.size()).append(" JavaDoc tags ...\n"); for (Map.Entry current : tag2ValueMap.entrySet()) { toReturn.append("| ").append(current.getKey()).append(": ").append(current.getValue()).append("\n"); } } toReturn.append("+=================\n\n"); return toReturn.toString().replace("\n", AbstractJaxbMojo.NEWLINE); } } JavaDocExtractor.java000066400000000000000000000523561351100213400435150ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import com.thoughtworks.qdox.JavaProjectBuilder; import com.thoughtworks.qdox.model.JavaAnnotatedElement; import com.thoughtworks.qdox.model.JavaAnnotation; import com.thoughtworks.qdox.model.JavaClass; import com.thoughtworks.qdox.model.JavaField; import com.thoughtworks.qdox.model.JavaMethod; import com.thoughtworks.qdox.model.JavaPackage; import com.thoughtworks.qdox.model.JavaSource; import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.ClassLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.FieldLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.MethodLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.PackageLocation; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.Validate; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlType; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; /** *

The schemagen tool operates on compiled bytecode, where JavaDoc comments are not present. * However, the javadoc documentation present in java source files is required within the generated * XSD to increase usability and produce an XSD which does not loose out on important usage information.

*

The JavaDocExtractor is used as a post processor after creating the XSDs within the compilation * unit, and injects XSD annotations into the appropriate XSD elements or types.

* * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class JavaDocExtractor { /** * The default value given as the return value from some annotation classes whenever the attribute * has not been supplied within the codebase. */ private static final String DEFAULT_VALUE = "##default"; // Internal state private JavaProjectBuilder builder; private Log log; /** * Creates a JavaDocExtractor wrapping the supplied Maven Log. * * @param log A non-null Log. */ public JavaDocExtractor(final Log log) { // Check sanity Validate.notNull(log, "log"); // Create internal state this.log = log; this.builder = new JavaProjectBuilder(); } /** * Assigns the encoding of the underlying {@link JavaProjectBuilder}. * * @param encoding The non-empty encoding to be set into the underlying {@link JavaProjectBuilder}. */ public void setEncoding(final String encoding) { this.builder.setEncoding(encoding); } /** * Adds the supplied sourceCodeFiles for processing by this JavaDocExtractor. * * @param sourceCodeFiles The non-null List of source code files to add. * @return This JavaDocExtractor, for call chaining. * @throws IllegalArgumentException If any of the given sourceCodeFiles could not be read properly. */ public JavaDocExtractor addSourceFiles(final List sourceCodeFiles) throws IllegalArgumentException { // Check sanity Validate.notNull(sourceCodeFiles, "addSourceFiles"); // Add the files. for (File current : sourceCodeFiles) { try { builder.addSource(current); } catch (IOException e) { throw new IllegalArgumentException("Could not add file [" + FileSystemUtilities.getCanonicalPath(current) + "]", e); } } // All done. return this; } /** * Adds the supplied sourceCodeFiles for processing by this JavaDocExtractor. * * @param sourceCodeURLs The non-null List of source code URLs to add. * @return This JavaDocExtractor, for call chaining. * @throws IllegalArgumentException If any of the given sourceCodeURLs could not be read properly. */ public JavaDocExtractor addSourceURLs(final List sourceCodeURLs) throws IllegalArgumentException { // Check sanity Validate.notNull(sourceCodeURLs, "sourceCodeURLs"); // Add the URLs for (URL current : sourceCodeURLs) { try { builder.addSource(current); } catch (IOException e) { throw new IllegalArgumentException("Could not add URL [" + current.toString() + "]", e); } } // All done return this; } /** * Processes all supplied Java source Files and URLs to extract JavaDocData for all ClassLocations from which * JavaDoc has been collected. * * @return A SearchableDocumentation relating SortableLocations and their paths to harvested JavaDocData. */ public SearchableDocumentation process() { // Start processing. final SortedMap dataHolder = new TreeMap(); final Collection sources = builder.getSources(); if (log.isInfoEnabled()) { log.info("Processing [" + sources.size() + "] java sources."); } for (JavaSource current : sources) { // Add the package-level JavaDoc final JavaPackage currentPackage = current.getPackage(); final String packageName = currentPackage.getName(); addEntry(dataHolder, new PackageLocation(packageName), currentPackage); if (log.isDebugEnabled()) { log.debug("Added package-level JavaDoc for [" + packageName + "]"); } for (JavaClass currentClass : current.getClasses()) { // Add the class-level JavaDoc final String simpleClassName = currentClass.getName(); final String classXmlName = getAnnotationAttributeValueFrom(XmlType.class, "name", currentClass.getAnnotations()); final ClassLocation classLocation = new ClassLocation(packageName, simpleClassName, classXmlName); addEntry(dataHolder, classLocation, currentClass); if (log.isDebugEnabled()) { log.debug("Added class-level JavaDoc for [" + classLocation + "]"); } for (JavaField currentField : currentClass.getFields()) { final List currentFieldAnnotations = currentField.getAnnotations(); String annotatedXmlName = null; // // Is this field a collection, annotated with @XmlElementWrapper? // If so, the documentation should pertain to the corresponding XML Sequence, // rather than the individual XML elements. // if (hasAnnotation(XmlElementWrapper.class, currentFieldAnnotations)) { // There are 2 cases here: // // 1: The XmlElementWrapper is named. // ================================== // @XmlElementWrapper(name = "foobar") // @XmlElement(name = "aString") // private List strings; // // ==> annotatedXmlName == "foobar" // // 2: The XmlElementWrapper is not named. // ====================================== // @XmlElementWrapper // @XmlElement(name = "anInteger") // private SortedSet integerSet; // // ==> annotatedXmlName == "integerSet" // annotatedXmlName = getAnnotationAttributeValueFrom( XmlElementWrapper.class, "name", currentFieldAnnotations); if (annotatedXmlName == null || annotatedXmlName.equals(DEFAULT_VALUE)) { annotatedXmlName = currentField.getName(); } } // Find the XML name if provided within an annotation. if (annotatedXmlName == null) { annotatedXmlName = getAnnotationAttributeValueFrom( XmlElement.class, "name", currentFieldAnnotations); } if (annotatedXmlName == null) { annotatedXmlName = getAnnotationAttributeValueFrom( XmlAttribute.class, "name", currentFieldAnnotations); } if (annotatedXmlName == null) { annotatedXmlName = getAnnotationAttributeValueFrom( XmlEnumValue.class, "value", currentFieldAnnotations); } // Add the field-level JavaDoc final FieldLocation fieldLocation = new FieldLocation( packageName, simpleClassName, classXmlName, currentField.getName(), annotatedXmlName); addEntry(dataHolder, fieldLocation, currentField); if (log.isDebugEnabled()) { log.debug("Added field-level JavaDoc for [" + fieldLocation + "]"); } } for (JavaMethod currentMethod : currentClass.getMethods()) { final List currentMethodAnnotations = currentMethod.getAnnotations(); String annotatedXmlName = null; // // Is this field a collection, annotated with @XmlElementWrapper? // If so, the documentation should pertain to the corresponding XML Sequence, // rather than the individual XML elements. // if (hasAnnotation(XmlElementWrapper.class, currentMethodAnnotations)) { // There are 2 cases here: // // 1: The XmlElementWrapper is named. // ================================== // @XmlElementWrapper(name = "foobar") // @XmlElement(name = "aString") // public List getStrings() { ... }; // // ==> annotatedXmlName == "foobar" // // 2: The XmlElementWrapper is not named. // ====================================== // @XmlElementWrapper // @XmlElement(name = "anInteger") // public SortedSet getIntegerSet() { ... }; // // ==> annotatedXmlName == "getIntegerSet" // annotatedXmlName = getAnnotationAttributeValueFrom( XmlElementWrapper.class, "name", currentMethodAnnotations); if (annotatedXmlName == null || annotatedXmlName.equals(DEFAULT_VALUE)) { annotatedXmlName = currentMethod.getName(); } } // Find the XML name if provided within an annotation. if (annotatedXmlName == null) { annotatedXmlName = getAnnotationAttributeValueFrom( XmlElement.class, "name", currentMethod.getAnnotations()); } if (annotatedXmlName == null) { annotatedXmlName = getAnnotationAttributeValueFrom( XmlAttribute.class, "name", currentMethod.getAnnotations()); } // Add the method-level JavaDoc final MethodLocation location = new MethodLocation(packageName, simpleClassName, classXmlName, currentMethod.getName(), annotatedXmlName, currentMethod.getParameters()); addEntry(dataHolder, location, currentMethod); if (log.isDebugEnabled()) { log.debug("Added method-level JavaDoc for [" + location + "]"); } } } } // All done. return new ReadOnlySearchableDocumentation(dataHolder); } /** * Finds the value of the attribute with the supplied name within the first matching JavaAnnotation of * the given type encountered in the given annotations List. This is typically used for reading values of * annotations such as {@link XmlElement}, {@link XmlAttribute} or {@link XmlEnumValue}. * * @param annotations The list of JavaAnnotations to filter from. * @param annotationType The type of annotation to read attribute values from. * @param attributeName The name of the attribute the value of which should be returned. * @return The first matching JavaAnnotation of type annotationType within the given annotations * List, or {@code null} if none was found. * @since 2.2 */ private static String getAnnotationAttributeValueFrom( final Class annotationType, final String attributeName, final List annotations) { // QDox uses the fully qualified class name of the annotation for comparison. // Extract it. final String fullyQualifiedClassName = annotationType.getName(); JavaAnnotation annotation = null; String toReturn = null; if (annotations != null) { for (JavaAnnotation current : annotations) { if (current.getType().isA(fullyQualifiedClassName)) { annotation = current; break; } } if (annotation != null) { final Object nameValue = annotation.getNamedParameter(attributeName); if (nameValue != null && nameValue instanceof String) { toReturn = ((String) nameValue).trim(); // Remove initial and trailing " chars, if present. if (toReturn.startsWith("\"") && toReturn.endsWith("\"")) { toReturn = (((String) nameValue).trim()).substring(1, toReturn.length() - 1); } } } } // All Done. return toReturn; } private static boolean hasAnnotation(final Class annotationType, final List annotations) { if (annotations != null && !annotations.isEmpty() && annotationType != null) { final String fullAnnotationClassName = annotationType.getName(); for (JavaAnnotation current : annotations) { if (current.getType().isA(fullAnnotationClassName)) { return true; } } } return false; } // // Private helpers // private void addEntry(final SortedMap map, final SortableLocation key, final JavaAnnotatedElement value) { // Check sanity if (map.containsKey(key)) { // Get something to compare with final JavaDocData existing = map.get(key); // Is this an empty package-level documentation? if (key instanceof PackageLocation) { final boolean emptyExisting = existing.getComment() == null || existing.getComment().isEmpty(); final boolean emptyGiven = value.getComment() == null || value.getComment().isEmpty(); if (emptyGiven) { if (log.isDebugEnabled()) { log.debug("Skipping processing empty Package javadoc from [" + key + "]"); } return; } else if (emptyExisting && log.isWarnEnabled()) { log.warn("Overwriting empty Package javadoc from [" + key + "]"); } } else { final String given = "[" + value.getClass().getName() + "]: " + value.getComment(); throw new IllegalArgumentException("Not processing duplicate SortableLocation [" + key + "]. " + "\n Existing: " + existing + ".\n Given: [" + given + "]"); } } // Validate.isTrue(!map.containsKey(key), "Found duplicate SortableLocation [" + key + "] in map. " // + "Current map keySet: " + map.keySet() + ". Got comment: [" + value.getComment() + "]"); map.put(key, new JavaDocData(value.getComment(), value.getTags())); } /** * Standard read-only SearchableDocumentation implementation. */ private class ReadOnlySearchableDocumentation implements SearchableDocumentation { // Internal state private TreeMap keyMap; private SortedMap valueMap; ReadOnlySearchableDocumentation(final SortedMap valueMap) { // Create internal state this.valueMap = valueMap; keyMap = new TreeMap(); for (Map.Entry current : valueMap.entrySet()) { final SortableLocation key = current.getKey(); keyMap.put(key.getPath(), key); } } /** * {@inheritDoc} */ @Override public SortedSet getPaths() { return Collections.unmodifiableSortedSet(keyMap.navigableKeySet()); } /** * {@inheritDoc} */ @Override public JavaDocData getJavaDoc(final String path) { // Check sanity Validate.notNull(path, "path"); // All done. final SortableLocation location = getLocation(path); return (location == null) ? null : valueMap.get(location); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public T getLocation(final String path) { // Check sanity Validate.notNull(path, "path"); // All done return (T) keyMap.get(path); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public SortedMap getAll() { return (SortedMap) Collections.unmodifiableSortedMap(valueMap); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public SortedMap getAll(final Class type) { // Check sanity Validate.notNull(type, "type"); // Filter the valueMap. final SortedMap toReturn = new TreeMap(); for (Map.Entry current : valueMap.entrySet()) { if (type == current.getKey().getClass()) { toReturn.put((T) current.getKey(), current.getValue()); } } // All done. return toReturn; } } } JavaDocRenderer.java000066400000000000000000000060571351100213400433050ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** *

Specification for how to convert/render JavaDocData into an XML annotation. As an example, let us * assume that a class contains the following field and JavaDoc:

*
 *     
 *         {@literal /}**
 *         The last name of the SomewhatNamedPerson.
 *         *{@literal /}
 *         {@literal @}XmlElement(nillable = false, required = true)
 *         private String lastName;
 *     
 * 
*

The standard SchemaGen generation creates a complex type with the following element declaration:

*
 *     
 *         <xs:element name="lastName" type="xs:string" />
 *     
 * 
*

However, if we use the jaxb2-maven-plugin for post-processing, we can inject the javadoc as an XSD * annotation into the resulting schema, yielding the following result:

*
 *     
 *         <xs:element name="lastName" type="xs:string">
 *             <xs:annotation>
 *                 <xs:documentation><![CDATA[The last name of the SomewhatNamedPerson.]]></xs:documentation>
 *             </xs:annotation>
 *         </xs:element>
 *     
 * 
*

The JavaDocRenderer will create the content of the CDATA element within the XSD documentation annotation, * given the JavaDocData for each field, such as the lastName in our example.

* * @author Lennart Jörelid, jGuru Europe AB * @see org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.DefaultJavaDocRenderer * @since 2.0 */ public interface JavaDocRenderer { /** *

Renders the supplied JavaDocData structure as text to be used within an XSD documentation annotation. * The XSD documentation annotation will contain a CDATA section to which the rendered JavaDocData is * emitted.

* * @param nonNullData the JavaDocData instance to render as XSD documentation. Will never be {@code null}. * @param location the SortableLocation where the JavaDocData was harvested. Never {@code null}. * @return The rendered text contained within the XML annotation. */ String render(JavaDocData nonNullData, SortableLocation location); } NoAuthorJavaDocRenderer.java000066400000000000000000000033761351100213400447660ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** *

Default JavaDocRenderer implementation which provides a plain JavaDocData rendering, while skipping * output from the {@code author} tag, on the form:

*
 *     [JavaDoc comment]
 *     (tag1): [tag1 value]
 *     (tag2): [tag2 value]
 * 
* * @author Lennart Jörelid, jGuru Europe AB * @since 2.3 */ public class NoAuthorJavaDocRenderer extends DefaultJavaDocRenderer { /** * The author key. */ private static final String AUTHOR_KEY = "author"; /** * {@inheritDoc} */ @Override protected String renderJavaDocTag(final String name, final String value, final SortableLocation location) { // Don't render the author if(AUTHOR_KEY.equalsIgnoreCase(name)) { return ""; } // Delegate. return super.renderJavaDocTag(name, value, location); } } SearchableDocumentation.java000066400000000000000000000071461351100213400450720ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.util.SortedMap; import java.util.SortedSet; /** *

Specification for a Map of SortableLocations correlated to their respective JavaDocData. * To simplify searching and accessing within the JavaDocData, the paths of each SortableLocation * is exposed for searching and listing.

* * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public interface SearchableDocumentation { /** * Retrieves all unique SortableLocation paths within this SearchableDocumentation. * * @return all unique SortableLocation paths within this SearchableDocumentation. * The result may be empty, but will never be {@code null}. */ SortedSet getPaths(); /** * Convenience method to acquire the JavaDocData for a SortableLocation with the supplied path. * * @param path A non-null path for which the harvested JavaDocData should be retrieved. * @return The JavaDocData matching the SortableLocation with the supplied path, or {@code null} if no * SortableLocation with the supplied path was found within this SearchableDocumentation. */ JavaDocData getJavaDoc(String path); /** * Convenience method to acquire the SortableLocation corresponding to the given path. * * @param path The path of a SortableLocation, which is retrieved by a call to its {@code toString()} method. * @param The SortableLocation subtype. * @return the SortableLocation corresponding to the given path, or {@code null} if this SearchableDocumentation * does not contain a SortableLocation with the provided path. */ T getLocation(String path); /** * The full map relating each SortableLocation subclass to its corresponding JavaDocData. * * @return The full map relating each SortableLocation subclass to its corresponding JavaDocData. Never null. */ SortedMap getAll(); /** * Convenience method which retrieves a SortedMap relating all SortableLocations of a particular type * to their JavaDocData, respectively. * * @param type The exact type of SortableLocation which should be filtered from the result and returned in the * form of a SortedMap, along with its respective JavaDocData. * @param The SortableLocation subtype for which all JavaDocData should be retrieved. * @return a SortedMap relating all SortableLocations of a particular (exact) type (i.e. any subclass types will * not be returned) to their JavaDocData, respectively. * May return empty Maps, but never {@code null}. */ SortedMap getAll(Class type); } SortableLocation.java000066400000000000000000000045661351100213400435560ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * Common specification for a JavaDoc location which can be compared and sorted. * JavaDoc locations must be comparable and also convert-able to unique strings. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public interface SortableLocation extends Comparable { /** * Validates if the supplied path is equal to this SortableLocation. * * @param path The non-null path to compare to this SortableLocation. * @return {@code true} if this SortableLocation is equal to the supplied path. */ boolean isEqualToPath(final String path); /** * Retrieves the path of this SortableLocation. The path must uniquely correspond to each unique SortableLocation, * implying that SortableLocations could be sorted and compared for equality using the path property. * * @return the path of this SortableLocation. Never null. */ String getPath(); /** * Retrieves the value of the name attribute provided by a JAXB annotation, implying that * the XSD type should use another name than the default. * * @return the value of the name attribute provided by a JAXB annotation relevant to this {@link SortableLocation}. * @see XmlElement#name() * @see XmlAttribute#name() * @see XmlType#name() */ String getAnnotationRenamedTo(); } XsdAnnotationProcessor.java000066400000000000000000000174641351100213400450040ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.ClassLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.FieldLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.MethodLocation; import org.codehaus.mojo.jaxb2.shared.Validate; import org.w3c.dom.Node; import java.util.SortedMap; /** *

Node processor that injects XSD documentation annotations consisting of JavaDoc harvested Java source code * into ComplexTypes, Elements and Attributes. The documentation is injected as follows:

*
    *
  1. ComplexType: Class-level JavaDoc from the corresponding type is injected as an * annotation directly inside the complexType.
  2. *
  3. Element: Field-level JavaDoc (or getter Method-level JavaDoc, in case the Field does * not contain a JavaDoc annotation) from the corresponding member is injected as an * annotation directly inside the element.
  4. *
  5. Attribute: Field-level JavaDoc (or getter Method-level JavaDoc, in case the Field does * not contain a JavaDoc annotation) from the corresponding member is injected as an * annotation directly inside the element.
  6. *
*

Thus, the following 'vanilla'-generated XSD:

*
 *     
 *         <xs:complexType name="somewhatNamedPerson">
 *             <xs:sequence>
 *                 <xs:element name="firstName" type="xs:string" nillable="true" minOccurs="0"/>
 *                 <xs:element name="lastName" type="xs:string"/>
 *             </xs:sequence>
 *             <xs:attribute name="age" type="xs:int" use="required"/>
 *         </xs:complexType>
 *     
 * 
*

... would be converted to the following annotated XSD, given a DefaultJavaDocRenderer:

*
 *     
 *         <xs:complexType name="somewhatNamedPerson">
 *             <xs:annotation>
 *                 <xs:documentation><![CDATA[Definition of a person with lastName and age, and optionally a firstName as well...
 *
 *                 (author): <a href="mailto:lj@jguru.se">Lennart Jörelid</a>, jGuru Europe AB
 *                 (custom): A custom JavaDoc annotation.]]></xs:documentation>
 *             </xs:annotation>
 *             <xs:sequence>
 *                 <xs:element minOccurs="0" name="firstName" nillable="true" type="xs:string">
 *                     <xs:annotation>
 *                         <xs:documentation><![CDATA[The first name of the SomewhatNamedPerson.]]></xs:documentation>
 *                     </xs:annotation>
 *                 </xs:element>
 *                 <xs:element name="lastName" type="xs:string">
 *                     <xs:annotation>
 *                         <xs:documentation><![CDATA[The last name of the SomewhatNamedPerson.]]></xs:documentation>
 *                     </xs:annotation>
 *                 </xs:element>
 *            </xs:sequence>
 *            <xs:attribute name="age" type="xs:int" use="required">
 *                <xs:annotation>
 *                    <xs:documentation><![CDATA[The age of the SomewhatNamedPerson. Must be positive.]]></xs:documentation>
 *                </xs:annotation>
 *            </xs:attribute>
 *          </xs:complexType>
 *     
 * 
*

... given that the Java class SomewhatNamedPerson has JavaDoc on its class and fields * corresponding to the injected XSD annotation/documentation elements.

* * @author Lennart Jörelid, jGuru Europe AB * @see org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocRenderer * @since 2.0 */ public class XsdAnnotationProcessor implements NodeProcessor { // Internal state private SortedMap classJavaDocs; private SortedMap fieldJavaDocs; private SortedMap methodJavaDocs; private JavaDocRenderer renderer; /** * Creates an XsdAnnotationProcessor that uses the supplied/generated SearchableDocumentation to read all * JavaDoc structures and the supplied JavaDocRenderer to render JavaDocs into XSD documentation annotations. * * @param docs A non-null SearchableDocumentation, produced from the source code of the JAXB compilation unit. * @param renderer A non-null JavaDocRenderer, used to render the JavaDocData within the SearchableDocumentation. */ public XsdAnnotationProcessor(final SearchableDocumentation docs, final JavaDocRenderer renderer) { // Check sanity Validate.notNull(docs, "docs"); Validate.notNull(renderer, "renderer"); // Assign internal state this.classJavaDocs = docs.getAll(ClassLocation.class); this.fieldJavaDocs = docs.getAll(FieldLocation.class); this.methodJavaDocs = docs.getAll(MethodLocation.class); this.renderer = renderer; } /** * {@inheritDoc} */ @Override public boolean accept(final Node aNode) { // Only deal with Element nodes with "name" attributes. if (!DomHelper.isNamedElement(aNode)) { return false; } /* */ // Only process nodes corresponding to Types we have any JavaDoc for. // TODO: How should we handle PackageLocations and package documentation? boolean toReturn = false; if (DomHelper.getMethodLocation(aNode, methodJavaDocs.keySet()) != null) { toReturn = true; } else if (DomHelper.getFieldLocation(aNode, fieldJavaDocs.keySet()) != null) { toReturn = true; } else if (DomHelper.getClassLocation(aNode, classJavaDocs.keySet()) != null) { toReturn = true; } // All done. return toReturn; } /** * {@inheritDoc} */ @Override public void process(final Node aNode) { DomHelper.insertXmlDocumentationAnnotationsFor(aNode, classJavaDocs, fieldJavaDocs, methodJavaDocs, renderer); } } XsdEnumerationAnnotationProcessor.java000066400000000000000000000165471351100213400472140ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.ClassLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.FieldLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.MethodLocation; import org.codehaus.mojo.jaxb2.shared.Validate; import org.w3c.dom.Element; import org.w3c.dom.Node; import java.util.SortedMap; /** *

Node processor that injects XSD documentation annotations consisting of JavaDoc harvested Java source code * into SimpleTypes, Elements and Attributes typically produced by SchemaGen when generate XSDs for Java Enumerations. * The documentation is injected as follows:

*
    *
  1. SimpleType: Class-level JavaDoc from the corresponding type is injected as an * annotation directly inside the SimpleType.
  2. *
  3. Element: Field-level JavaDoc (or getter Method-level JavaDoc, in case the Field does * not contain a JavaDoc annotation) from the corresponding member is injected as an * annotation directly inside the element.
  4. *
  5. Attribute: Field-level JavaDoc (or getter Method-level JavaDoc, in case the Field does * not contain a JavaDoc annotation) from the corresponding member is injected as an * annotation directly inside the element.
  6. *
*

Thus, the following 'vanilla'-generated XSD:

*
 *     
 *           <xs:simpleType name="foodPreference">
 *               <xs:restriction base="xs:string">
 *                   <xs:enumeration value="NONE"/>
 *                   <xs:enumeration value="VEGAN"/>
 *                   <xs:enumeration value="LACTO_VEGETARIAN"/>
 *               </xs:restriction>
 *           </xs:simpleType>
 *     
 * 
*

... will be converted in a manner similar to the one below:

*
 *     
 *         <xs:simpleType name="foodPreference">
 *             <xs:annotation>
 *                 <xs:documentation><![CDATA[Simple enumeration example defining some Food preferences.]]></xs:documentation>
 *             </xs:annotation>
 *             <xs:restriction base="xs:string">
 *                 <xs:enumeration value="LACTO_VEGETARIAN">
 *                     <xs:annotation>
 *                         <xs:documentation><![CDATA[Vegetarian who will not eat meats, but drinks milk.]]></xs:documentation>
 *                     </xs:annotation>
 *                 </xs:enumeration>
 *                 <xs:enumeration value="NONE">
 *                     <xs:annotation>
 *                         <xs:documentation><![CDATA[No special food preferences; eats everything.]]></xs:documentation>
 *                     </xs:annotation>
 *                 </xs:enumeration>
 *                 <xs:enumeration value="VEGAN">
 *                     <xs:annotation>
 *                         <xs:documentation><![CDATA[Vegan who will neither eat meats nor drink milk.]]></xs:documentation>
 *                     </xs:annotation>
 *                 </xs:enumeration>
 *             </xs:restriction>
 *         </xs:simpleType>
 *     
 * 
*

... given that the Java class FoodPreference has JavaDoc on its class and fields * corresponding to the injected XSD annotation/documentation elements.

* * @author Lennart Jörelid, jGuru Europe AB */ public class XsdEnumerationAnnotationProcessor implements NodeProcessor { // Internal state private SortedMap classJavaDocs; private SortedMap fieldJavaDocs; private SortedMap methodJavaDocs; private JavaDocRenderer renderer; /** * Creates an XsdEnumerationAnnotationProcessor that uses the supplied/generated SearchableDocumentation to read all * JavaDoc structures and the supplied JavaDocRenderer to render JavaDocs into XSD documentation annotations. * * @param docs A non-null SearchableDocumentation, produced from the source code of the JAXB compilation unit. * @param renderer A non-null JavaDocRenderer, used to render the JavaDocData within the SearchableDocumentation. */ public XsdEnumerationAnnotationProcessor(final SearchableDocumentation docs, final JavaDocRenderer renderer) { // Check sanity Validate.notNull(docs, "docs"); Validate.notNull(renderer, "renderer"); // Assign internal state this.classJavaDocs = docs.getAll(ClassLocation.class); this.fieldJavaDocs = docs.getAll(FieldLocation.class); this.methodJavaDocs = docs.getAll(MethodLocation.class); this.renderer = renderer; } /** *

Only accept simpleTypes which are restrictions to either xs:string or xs:integer. * The former is generated by JAXB when the Java Enum uses String values, and the latter is used * for ordinal values.

* * {@inheritDoc} */ @Override public boolean accept(final Node aNode) { // Only deal with Element nodes. if (aNode.getNodeType() != Node.ELEMENT_NODE) { return false; } // We should accept: // // 1) A simpleType Element // 2) An enumeration Element final Element theElement = (Element) aNode; final String localName = theElement.getLocalName(); if (localName != null) { final String trimmed = localName.trim(); return trimmed.equalsIgnoreCase("enumeration") || trimmed.equalsIgnoreCase("simpleType"); } /* */ /* */ // All done. return false; } /** * {@inheritDoc} */ @Override public void process(final Node aNode) { DomHelper.insertXmlDocumentationAnnotationsFor(aNode, classJavaDocs, fieldJavaDocs, methodJavaDocs, renderer); } } location/000077500000000000000000000000001351100213400412445ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocClassLocation.java000066400000000000000000000075711351100213400446570ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/locationpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.shared.Validate; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * Comparable path structure to locate a particular class within compilation unit. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class ClassLocation extends PackageLocation { // Internal state private String className; private String classXmlName; /** * Creates a new ClassLocation with the supplied package and class names. * * @param packageName The name of the package for a class potentially holding JavaDoc. Cannot be {@code null}. * @param classXmlName The name given as the {@link XmlType#name()} value of an annotation placed on the Class, * or {@code null} if none is provided. * @param className The (simple) name of a class. Cannot be null or empty. */ public ClassLocation(final String packageName, final String className, final String classXmlName) { super(packageName); // Check sanity Validate.notEmpty(className, "className"); // Assign internal state this.className = className; this.classXmlName = classXmlName; } /** * Retrieves the simple class name for the class potentially holding JavaDoc. Never {@code null} or empty. * * @return The simple class name for the class potentially holding JavaDoc. Never {@code null} or empty. */ public String getClassName() { return classXmlName == null ? className : classXmlName; } /** * Always appends the effective className to the path from the superclass {@link PackageLocation}. * If the {@link #getAnnotationRenamedTo()} method returns a non-null value, that value is the effective className. * Otherwise, the {@link #getClassName()} method is used as the effective className. * * This is to handle renames such as provided in a {@link javax.xml.bind.annotation.XmlType} annotation's * {@link XmlType#name()} attribute value. * * @return the path of the PackageLocation superclass, appended with the effective className. * @see XmlType * @see XmlAttribute#name() * @see XmlElement#name() */ @Override public String getPath() { return super.toString() + "." + getClassName(); } /** * {@inheritDoc} */ @Override public String getAnnotationRenamedTo() { return classXmlName; } /** * {@inheritDoc} */ @Override public int hashCode() { return this.toString().hashCode(); } /** * {@inheritDoc} */ @Override public String toString() { final String xmlOverriddenFrom = classXmlName != null && !className.equals(classXmlName) ? " (from: " + className + ")" : ""; return super.toString() + "." + getClassName() + xmlOverriddenFrom; } } FieldLocation.java000066400000000000000000000072731351100213400446340ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/locationpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.shared.Validate; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * Comparable path structure to locate a particular field within compilation unit. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class FieldLocation extends ClassLocation { // Internal state private String memberName; private String memberXmlName; /** * Creates a new FieldLocation with the supplied package, class and member names. * * @param packageName The name of the package for a class potentially holding JavaDoc. Cannot be {@code null}. * @param className The (simple) name of a class. Cannot be null or empty. * @param memberName The name of a (method or) field. Cannot be null or empty. * @param classXmlName The name given as the {@link XmlType#name()} value of an annotation placed on the Class, * or {@code null} if none is provided. * @param memberXmlName The name given as the {@link XmlElement#name()} or {@link XmlAttribute#name()} value of * an annotation placed on this Field, or {@code null} if none is provided. */ public FieldLocation(final String packageName, final String className, final String classXmlName, final String memberName, final String memberXmlName) { // Delegate super(packageName, className, classXmlName); // Check sanity Validate.notEmpty(memberName, "memberName"); // Assign internal state this.memberName = memberName; this.memberXmlName = memberXmlName; } /** * Retrieves the name of the member (i.e. method or field), potentially holding JavaDoc. * * @return The name of the member (i.e. method or field), potentially holding JavaDoc. * Never null or empty. */ public String getMemberName() { return memberXmlName == null ? memberName : memberXmlName; } /** * {@inheritDoc} */ @Override public String getAnnotationRenamedTo() { return memberXmlName; } /** * {@inheritDoc} */ @Override public String getPath() { return super.getPath() + "#" + getMemberName(); } /** * {@inheritDoc} */ @Override public String toString() { final String xmlOverriddenFrom = memberXmlName != null && !memberName.equals(memberXmlName) ? " (from: " + memberName + ")" : ""; return super.toString() + "#" + getMemberName() + xmlOverriddenFrom; } /** * {@inheritDoc} */ @Override public int hashCode() { return this.toString().hashCode(); } } MethodLocation.java000066400000000000000000000100761351100213400450240ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/locationpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import com.thoughtworks.qdox.model.JavaParameter; import org.codehaus.mojo.jaxb2.shared.Validate; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; import java.util.List; /** * Comparable path structure to locate a particular method within compilation unit. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class MethodLocation extends FieldLocation { /** * Signature for a method without any parameters. */ public static final String NO_PARAMETERS = "()"; /** * Separator for a method's parameters. */ public static final String PARAMETER_SEPARATOR = ","; // Internal state private String parameters = NO_PARAMETERS; /** * Creates a new MethodLocation with the supplied package, class and member names. * * @param packageName The name of the package for a class potentially holding JavaDoc. Cannot be {@code null}. * @param className The (simple) name of a class. Cannot be null or empty. * @param classXmlName The name given as the {@link XmlType#name()} value of an annotation placed on the Class, * or {@code null} if none is provided. * @param memberName The name of a (method or) field. Cannot be null or empty. * @param memberXmlName The name given as the {@link XmlElement#name()} or {@link XmlAttribute#name()} value of * an annotation placed on this Field, or {@code null} if none is provided. * @param parameters The names of the types which are parameters to this method. */ public MethodLocation(final String packageName, final String className, final String classXmlName, final String memberName, final String memberXmlName, final List parameters) { super(packageName, className, classXmlName, memberName, memberXmlName); // Check sanity Validate.notNull(parameters, "parameters"); // Stringify the parameter types if (parameters.size() > 0) { final StringBuilder builder = new StringBuilder(); for (JavaParameter current : parameters) { builder.append(current.getType().getFullyQualifiedName()).append(PARAMETER_SEPARATOR); } this.parameters = "(" + builder.substring(0, builder.lastIndexOf(PARAMETER_SEPARATOR)) + ")"; } } /** * {@inheritDoc} */ @Override public String getPath() { return super.getPath() + parameters; } /** * {@inheritDoc} */ @Override public String toString() { return super.toString() + parameters; } /** * {@inheritDoc} */ @Override public int hashCode() { return this.toString().hashCode(); } /** * @return The parameters, concatenated into a String. */ public String getParametersAsString() { return parameters; } /** * @return True if this MethodLocation has no parameters. */ public boolean hasNoParameters() { return NO_PARAMETERS.equals(parameters); } } PackageLocation.java000066400000000000000000000067471351100213400451510ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/locationpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SortableLocation; import org.codehaus.mojo.jaxb2.shared.Validate; /** * Comparable path structure to locate a particular package within compilation unit. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class PackageLocation implements SortableLocation { // Internal state private String packageName; /** * Creates a new PackageLocation with the supplied package name. * * @param packageName The name of the package potentially holding JavaDoc. Cannot be {@code null}. */ public PackageLocation(final String packageName) { // Check sanity Validate.notNull(packageName, "packageName"); // Assign internal state this.packageName = packageName; } /** * Retrieves the name of the package potentially holding JavaDoc. * * @return The name of the package potentially holding JavaDoc. Can be empty, but never {@code null}. */ public String getPackageName() { return packageName; } /** * {@inheritDoc} */ @Override public boolean equals(final Object obj) { // Check sanity if (obj == this) { return true; } // Delegate return obj instanceof PackageLocation && toString().equals(obj.toString()); } /** * {@inheritDoc} */ @Override public int hashCode() { return toString().hashCode(); } /** * Note: Packages cannot be renamed from a JAXB annotation. * {@inheritDoc} */ @Override public String getAnnotationRenamedTo() { return null; } /** * {@inheritDoc} */ @Override public String getPath() { return toString(); } /** * {@inheritDoc} */ @Override public String toString() { return packageName; } /** * {@inheritDoc} */ @Override public boolean isEqualToPath(final String path) { // Check sanity Validate.notNull(path, "path"); // All done. return toString().equals(path); } /** *

Compares the string representations of this PackageLocation and the supplied SortableLocation.

* {@inheritDoc} */ @Override public int compareTo(final SortableLocation that) { // Check sanity Validate.notNull(that, "that"); if (this == that) { return 0; } // Delegate return this.toString().compareTo(that.toString()); } } schemaenhancement/000077500000000000000000000000001351100213400414735ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingChangeFilenameProcessor.java000066400000000000000000000114021351100213400470620ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor; import org.codehaus.mojo.jaxb2.shared.Validate; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; import javax.xml.XMLConstants; import java.util.Map; /** *

NodeProcessor which alters the filename for generated XML schema files. * The ChangeNamespacePrefixProcessor alters the following:

*
*
Schema Import Definitions
*
<xs:import namespace="http://some/namespace" schemaLocation="schema2.xsd"/> is * altered to * <xs:import namespace="http://some/namespace" schemaLocation="anotherFile.xsd"/>
*
* * @author Lennart Jörelid * @since 1.4 */ public class ChangeFilenameProcessor implements NodeProcessor { // Constants private static final String SCHEMA_LOCATION = "schemaLocation"; private static final String IMPORT = "import"; private static final String NAMESPACE = "namespace"; // Internal state private Map namespaceUriToNewFilenameMap; /** *

Creates a new ChangeFilenameProcessor using the provided map relating namespace URIs * to desired new file names.

* * @param namespaceUriToNewFilenameMap A map relating namespace URIs [key] to * new/desired schema filenames [value]. */ public ChangeFilenameProcessor(final Map namespaceUriToNewFilenameMap) { // Check sanity Validate.notNull(namespaceUriToNewFilenameMap, "namespaceUriToNewFilenameMap"); // Assign internal state this.namespaceUriToNewFilenameMap = namespaceUriToNewFilenameMap; } /** * {@inheritDoc} */ public boolean accept(final Node aNode) { return aNode instanceof Attr && isSchemaLocationAttributeForKnownNamespaceUri((Attr) aNode); } /** * {@inheritDoc} */ public void process(final Node aNode) { // Only attributes are permitted here. Attr attribute = (Attr) aNode; // Change the fileName. String newFilename = namespaceUriToNewFilenameMap.get(getNamespace(attribute)); attribute.setValue(newFilename); } // // Private helpers // /** * Discovers if the provided attribute is a schemaLocation definition, which should * be changed by this ChangeFilenameProcessor. Such an attribute is on the form * <xs:import namespace="http://a/registered/namespace" schemaLocation="schema1.xsd"/>. * * @param attribute the attribute to test. * @return true if the provided attribute is a schemaLocation definition * whose namespace is known to this ChangeFilenameProcessor. */ private boolean isSchemaLocationAttributeForKnownNamespaceUri(final Attr attribute) { final Element parent = attribute.getOwnerElement(); // return XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(parent.getNamespaceURI()) && IMPORT.equalsIgnoreCase(parent.getLocalName()) && namespaceUriToNewFilenameMap.containsKey(getNamespace(attribute)) && SCHEMA_LOCATION.equals(attribute.getName()); } /** * Retrieves the value of the "namespace" attribute found within the parent element of the provided attribute. * * @param attribute An attribute defined within the parent holding the "namespace" attribute. * @return The value of the "namespace" attribute. */ private String getNamespace(final Attr attribute) { final Element parent = attribute.getOwnerElement(); return parent.getAttribute(NAMESPACE); } }ChangeNamespacePrefixProcessor.java000066400000000000000000000205211351100213400504160ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; import javax.xml.XMLConstants; /** *

NodeProcessor which alters the namespace prefix for all relevant Nodes within an XML * document Node. It alters namespace prefixes in the following logical places:

*
*
Schema Namespace Definition
*
xmlns:oldPrefix="http://some/namespace" is altered to xmlns:newPrefix="http://some/namespace"
*
Elements Namespace Prefix
*
<oldPrefix:someElement ... > is altered to <newPrefix:someElement ... >
*
Element Reference
*
<xs:element ref="oldPrefix:aRequiredElementInTheOldPrefixNamespace"/> is altered to * <xs:element ref="newPrefix:aRequiredElementInTheOldPrefixNamespace"/>
*
Type Attribute
*
<xs:element type="oldPrefix:something"/> is altered to * <xs:element type="newPrefix:something"/>
*
Type Extension
*
<xs:extension base="oldPrefix:something"/> is altered to * <xs:extension base="newPrefix:something"/>
*
* * @author Lennart Jörelid * @since 1.4 */ public class ChangeNamespacePrefixProcessor implements NodeProcessor { // Constants // private static final String EXTENSION_ELEMENT_NAME = "extension"; private static final String EXTENSION_BASE_ATTRIBUTE_NAME = "base"; private static final String REFERENCE_ATTRIBUTE_NAME = "ref"; private static final String TYPE_ATTRIBUTE_NAME = "type"; private static final String SCHEMA = "schema"; private static final String XMLNS = "xmlns:"; // // private static final String ELEMENT_NAME = "element"; // Internal state private String oldPrefix; private String newPrefix; /** * Creates a new ChangeNamespacePrefixProcessor providing the oldPrefix which should be replaced by the newPrefix. * * @param oldPrefix The old/current namespace prefix * @param newPrefix The new/substituted namespace prefix */ public ChangeNamespacePrefixProcessor(final String oldPrefix, final String newPrefix) { this.oldPrefix = oldPrefix; this.newPrefix = newPrefix; } /** * {@inheritDoc} */ public boolean accept(final Node aNode) { if (oldPrefix.equals(aNode.getPrefix())) { // Process any nodes on the form [oldPrefix]:something. return true; } if (aNode instanceof Attr) { // These cases are defined by attribute properties. final Attr attribute = (Attr) aNode; if (isNamespaceDefinition(attribute) || isElementReference(attribute) || isTypeAttributeWithPrefix(attribute) || isExtension(attribute)) { return true; } } // Nopes. return false; } /** * {@inheritDoc} */ public void process(final Node aNode) { if (aNode instanceof Attr) { final Attr attribute = (Attr) aNode; final Element parentElement = attribute.getOwnerElement(); if (isNamespaceDefinition(attribute)) { // Use the incredibly smooth DOM way to rename an attribute... parentElement.setAttributeNS(attribute.getNamespaceURI(), XMLNS + newPrefix, aNode.getNodeValue()); parentElement.removeAttribute(XMLNS + oldPrefix); } else if (isElementReference(attribute) || isTypeAttributeWithPrefix(attribute) || isExtension(attribute)) { // Simply alter the value of the reference final String value = attribute.getValue(); final String elementName = value.substring(value.indexOf(":") + 1); attribute.setValue(newPrefix + ":" + elementName); } } if (oldPrefix.equals(aNode.getPrefix())) { // Simply change the prefix to the new one. aNode.setPrefix(newPrefix); } } // // Private helpers // /** * Discovers if the provided attribute is the oldPrefix namespace definition, i.e. if the given attribute is the * xmlns:[oldPrefix] within the schema Element. * * @param attribute the attribute to test. * @return true if the provided attribute is the oldPrefix namespace definition, i.e. if the given * attribute is the xmlns:[oldPrefix] within the schema Element. */ private boolean isNamespaceDefinition(final Attr attribute) { final Element parent = attribute.getOwnerElement(); return XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(parent.getNamespaceURI()) && SCHEMA.equalsIgnoreCase(parent.getLocalName()) && oldPrefix.equals(attribute.getLocalName()); } /** * Discovers if the provided attribute is a namespace reference to the oldPrefix namespace, on the form * <xs:element ref="oldPrefix:anElementInTheOldPrefixNamespace"/> * * @param attribute the attribute to test. * @return true if the provided attribute is named "ref" and starts with [oldPrefix]:, in * which case it is a reference to the oldPrefix namespace. */ private boolean isElementReference(final Attr attribute) { return REFERENCE_ATTRIBUTE_NAME.equals(attribute.getName()) && attribute.getValue().startsWith(oldPrefix + ":"); } /** * Discovers if the provided attribute is a type attribute using the oldPrefix namespace, on the form * <xs:element type="oldPrefix:anElementInTheOldPrefixNamespace"/> * * @param attribute the attribute to test. * @return true if the provided attribute is named "type" and starts with [oldPrefix]:, in * which case it is a type in the oldPrefix namespace. */ private boolean isTypeAttributeWithPrefix(final Attr attribute) { return TYPE_ATTRIBUTE_NAME.equals(attribute.getName()) && attribute.getValue().startsWith(oldPrefix + ":"); } /** * Discovers if the provided attribute is a namespace reference to the oldPrefix namespace, on the form *

*

     *     <xs:extension base="[oldPrefix]:importItem">
     * 
* * @param attribute the attribute to test. * @return true if the provided attribute is named "extension" and starts with * [oldPrefix]:, in which case it is a reference to the oldPrefix namespace. */ private boolean isExtension(final Attr attribute) { final Element parent = attribute.getOwnerElement(); return XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(parent.getNamespaceURI()) && EXTENSION_ELEMENT_NAME.equalsIgnoreCase(parent.getLocalName()) && EXTENSION_BASE_ATTRIBUTE_NAME.equalsIgnoreCase(attribute.getName()) && attribute.getValue().startsWith(oldPrefix + ":"); } }SimpleNamespaceResolver.java000066400000000000000000000177531351100213400471430ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor; import org.codehaus.plexus.util.IOUtil; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.Reader; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** *

Namespace resolver for XML documents, which relates XML Namespace Prefixes to XML Namespace URIs. * Doubles as a JAXB NamespaceContext, if we decide to use JAXB instead of DOM to parse our generated * schema files.

* * @author Lennart Jörelid * @since 1.4 */ public class SimpleNamespaceResolver implements NamespaceContext { // Constants private static final String DEFAULT_NS = "DEFAULT"; private static final String TARGET_NAMESPACE = "targetNamespace"; private static final String SCHEMA = "schema"; // Internal state private String sourceFilename; private String localNamespaceURI; private Map prefix2Uri = new HashMap(); private Map uri2Prefix = new HashMap(); /** * Creates a new SimpleNamespaceResolver which collects namespace data * from the provided XML file. * * @param xmlFile The XML file from which to collect namespace data, should not be null. */ public SimpleNamespaceResolver(final File xmlFile) { this.sourceFilename = xmlFile.getName(); Reader reader = null; try { reader = new FileReader(xmlFile); initialize(reader); } catch (FileNotFoundException e) { throw new IllegalArgumentException("File [" + xmlFile + "] could not be found."); } finally { IOUtil.close(reader); } } /** * {@inheritDoc} */ public String getNamespaceURI(final String prefix) { if (prefix == null) { // Be compliant with the JAXB contract for NamespaceResolver. throw new IllegalArgumentException("Cannot handle null prefix argument."); } return prefix2Uri.get(XMLConstants.DEFAULT_NS_PREFIX.equals(prefix) ? DEFAULT_NS : prefix); } /** * {@inheritDoc} */ public String getPrefix(final String namespaceURI) { if (namespaceURI == null) { // Be compliant with the JAXB contract for NamespaceResolver. throw new IllegalArgumentException("Cannot acquire prefix for null namespaceURI."); } return uri2Prefix.get(namespaceURI); } /** * {@inheritDoc} */ public Iterator getPrefixes(final String namespaceURI) { if (namespaceURI == null) { // Be compliant with the JAXB contract for NamespaceResolver. throw new IllegalArgumentException("Cannot acquire prefixes for null namespaceURI."); } return Collections.singletonList(uri2Prefix.get(namespaceURI)).iterator(); } /** * @return A readonly map relating namespace URIs to namespace prefixes. */ public Map getNamespaceURI2PrefixMap() { return Collections.unmodifiableMap(uri2Prefix); } /** * @return The namespace URI of the default namespace within the sourceFile of this SimpleNamespaceResolver. */ public String getLocalNamespaceURI() { return localNamespaceURI; } /** * @return The name of the source file used for this SimpleNamespaceResolver. */ public String getSourceFilename() { return sourceFilename; } // // Private helpers // /** * Initializes this SimpleNamespaceResolver to collect namespace data from the provided stream. * * @param xmlFileStream A Reader connected to the XML file from which we should read namespace data. */ private void initialize(final Reader xmlFileStream) { // Build a DOM model. final Document parsedDocument = XsdGeneratorHelper.parseXmlStream(xmlFileStream); // Process the DOM model. XsdGeneratorHelper.process(parsedDocument.getFirstChild(), true, new NamespaceAttributeNodeProcessor()); } private class NamespaceAttributeNodeProcessor implements NodeProcessor { /** * Defines if this visitor should process the provided node. * * @param aNode The DOM node to process. * @return true if the provided Node should be processed by this NodeProcessor. */ public boolean accept(final Node aNode) { // Correct namespace? if (aNode.getNamespaceURI() != null && XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(aNode.getNamespaceURI())) { return true; } // Is this Node the targetNamespace attribute? if (aNode instanceof Attr) { final Attr attribute = (Attr) aNode; final Element parent = attribute.getOwnerElement(); if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(parent.getNamespaceURI()) && SCHEMA.equalsIgnoreCase(parent.getLocalName()) && TARGET_NAMESPACE.equals(attribute.getLocalName())) { SimpleNamespaceResolver.this.localNamespaceURI = attribute.getNodeValue(); } } // Ignore processing this Node. return false; } /** * Processes the provided DOM Node. * * @param aNode The DOM Node to process. */ public void process(final Node aNode) { // If we have no namespace, use the DEFAULT_NS as the prefix final String cacheKey = XMLConstants.XMLNS_ATTRIBUTE.equals(aNode.getNodeName()) ? DEFAULT_NS : aNode.getLocalName(); final String nodeValue = aNode.getNodeValue(); // Cache the namespace in both caches. final String oldUriValue = prefix2Uri.put(cacheKey, nodeValue); final String oldPrefixValue = uri2Prefix.put(nodeValue, cacheKey); // Check sanity; we should not be overwriting values here. if (oldUriValue != null) { throw new IllegalStateException( "Replaced URI [" + oldUriValue + "] with [" + aNode.getNodeValue() + "] for prefix [" + cacheKey + "]"); } if (oldPrefixValue != null) { throw new IllegalStateException( "Replaced prefix [" + oldPrefixValue + "] with [" + cacheKey + "] for URI [" + aNode.getNodeValue() + "]"); } } } }TransformSchema.java000066400000000000000000000205131351100213400454330ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.shared.Validate; /** *

Data holder for schema transformation operations, to permit customization of the * schema namespace prefix and file name of generated schema. As the schemagen * tool has no mechanics to control namespace prefix and file name of generated schema, * the Jaxb2-Maven-plugin must supply a post-processing step to work around this situation.

*

Each TransformSchema object holds data pertaining to changes for one namespace * URI - either namespace prefix used within the generated XSD or resulting filename for * the schema definition.

*
    *
  1. Namespace prefix. Each XML element within a namespace uses the supplied * prefix. (As a reference, in the XML element <foo:bar/>, the namespace prefix * is "foo" and the element name is "bar"). The Schemagen tool by default only generates namespace * prefixes on the form "ns1", "ns2" etc., which means that the generated schema will contain elements * on the form <xs:extension base="ns1:nazgulEntity">. * Use a toPrefix element to change the namespace prefix of a particular XML URI to * simplify understanding the schema.
  2. *
  3. Filename. By default, the Schemagen tool creates files called "schema1.xsd", * "schema2.xsd" etc. Since the XSD imports one another, simply changing the filename will frequently * break the schema structure - you will need to change all import statements in all generated XSD files * to match the new file names. The Jaxb2 Maven plugin can do all this housekeeping automatically, if you * create a transformSchema element containing a toFile element to change the filename for a * particular XML URI. Changing the file names frequently improves overview and usability of the generated schema * files.
  4. *
*

Example TransformSchemas

*

The URI element is mandatory for each TransformSchema element. The first example illustrates how * to use the TransformSchema element to change the prefix and file name of 3 XML URIs. This is the recommended * use of a TransformSchema - change both prefix and filename to something meaningful for each URI:

*
 * <transformSchemas>
 *      <transformSchema>
 *          <uri>http://some/namespace</uri>
 *          <toPrefix>some</toPrefix>
 *          <toFile>some_schema.xsd</toFile>
 *      </transformSchema>
 *      <transformSchema>
 *          <uri>http://another/namespace</uri>
 *          <toPrefix>another</toPrefix>
 *          <toFile>another_schema.xsd</toFile>
 *      </transformSchema>
 *      <transformSchema>
 *          <uri>http://yet/another/namespace</uri>
 *          <toPrefix>yetAnother</toPrefix>
 *          <toFile>yet_another_schema.xsd</toFile>
 *      </transformSchema>
 * </transformSchemas>
 * 
*

The URI element is mandatory for each TransformSchema element, along with at least one of the other two * elements in the TransformSchema. This implies that partial configuration for TransformSchema can be used, * although this is not recommended since the readability and usability of the automatically generated * namespace prefixes and file names are poor. The second example illustrates how to use the TransformSchema element * to change either prefix or file name for 2 XML URIs:

*
 * <transformSchemas>
 *      <transformSchema>
 *          <uri>http://another/namespace</uri>
 *          <toPrefix>another</toPrefix>
 *      </transformSchema>
 *      <transformSchema>
 *          <uri>http://yet/another/namespace</uri>
 *          <toFile>yet_another_schema.xsd</toFile>
 *      </transformSchema>
 * </transformSchemas>
 * 
* * @author Lennart Jörelid * @since 1.4 */ public class TransformSchema { /** * The empty XML Namespace. */ public static final String EMPTY_NAMESPACE = ""; // Internal state private String uri = EMPTY_NAMESPACE; private String toPrefix; private String toFile; /** * Default constructor. */ public TransformSchema() { } /** * Compound constructor, creating a TransformSchema instruction wrapping the supplied data. * * @param uri The URI of this Schema, such as * http://www.jguru.se/some/namespace. Cannot be null or empty. * @param toPrefix The new namespace prefix for this Schema. Optional. * @param toFile The new name of the generated schema file. */ public TransformSchema(final String uri, final String toPrefix, final String toFile) { this.uri = uri; this.toPrefix = toPrefix; this.toFile = toFile; } /** * @return The URI of this Schema, such as http://www.jguru.se/some/namespace. * The namespace URI is mapped to its prefix in the schema element, i.e: * xmlns:xs="http://www.w3.org/2001/XMLSchema" or * xmlns:foo="http://www.acme.com/xml/schema/foo". */ public String getUri() { return uri; } /** * @return The namespace prefix of this Schema. Each schema element is related to its namespace using the prefix. * For an XML element <foo:bar/>, the prefix is "foo" (and the element name is "bar"). */ public String getToPrefix() { return toPrefix; } /** * @return the name of the target file if/when renamed. */ public String getToFile() { return toFile; } /** * Assigns the URI of this Schema, such as http://www.jguru.se/some/namespace. * The namespace URI is mapped to its prefix in the schema element, i.e: * xmlns:xs="http://www.w3.org/2001/XMLSchema" or * xmlns:foo="http://www.acme.com/xml/schema/foo". * * @param uri The non-empty uri of this Schema. */ public void setUri(final String uri) { // Check sanity Validate.notEmpty(uri, "uri"); // Assign internal state this.uri = uri; } /** * Assigns the namespace prefix of this Schema. Each schema element is related to its namespace * using the prefix. For an XML element <foo:bar/>, the prefix is "foo" * (and the element name is "bar"). * * @param toPrefix The non-empty prefix to assign. */ public void setToPrefix(final String toPrefix) { // Check sanity Validate.notEmpty(toPrefix, "toPrefix"); // Assign internal state this.toPrefix = toPrefix; } /** * Assigns the the name of the target file if/when renamed. * * @param toFile The non-empty filename to assign. */ public void setToFile(final String toFile) { // Check sanity Validate.notEmpty(toFile, "toFile"); // Assign internal state this.toFile = toFile; } /** * {@inheritDoc} */ public String toString() { return "[ uri: " + uri + " --> prefix: " + toPrefix + ", file: " + toFile + " ]"; } }jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/000077500000000000000000000000001351100213400307545ustar00rootroot00000000000000FileSystemUtilities.java000066400000000000000000000741531351100213400355320ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/sharedpackage org.codehaus.mojo.jaxb2.shared; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.Os; import org.codehaus.plexus.util.StringUtils; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; /** * The Jaxb2 Maven Plugin needs to fiddle with the filesystem a great deal, to create and optionally prune * directories or detect/create various files. This utility class contains all such algorithms, and serves as * an entry point to any Plexus Utils methods. * * @author Lennart Jörelid * @since 2.0 */ public final class FileSystemUtilities { /* * Hide the constructor for utility classes. */ private FileSystemUtilities() { // Do nothing } /** * FileFilter which accepts Files that exist and for which {@code File.isFile() } is {@code true}. */ public static final FileFilter EXISTING_FILE = new FileFilter() { @Override public boolean accept(final File candidate) { return candidate != null && candidate.exists() && candidate.isFile(); } }; /** * FileFilter which accepts Files that exist and for which {@code File.isDirectory() } is {@code true}. */ public static final FileFilter EXISTING_DIRECTORY = new FileFilter() { @Override public boolean accept(final File candidate) { return candidate != null && candidate.exists() && candidate.isDirectory(); } }; /** * Acquires the canonical path for the supplied file. * * @param file A non-null File for which the canonical path should be retrieved. * @return The canonical path of the supplied file. */ public static String getCanonicalPath(final File file) { return getCanonicalFile(file).getPath(); } /** * Non-valid Characters for naming files, folders under Windows: ":", "*", "?", "\"", "<", ">", "|" * * @see * http://support.microsoft.com/?scid=kb%3Ben-us%3B177506&x=12&y=13 * @see org.codehaus.plexus.util.FileUtils */ private static final String[] INVALID_CHARACTERS_FOR_WINDOWS_FILE_NAME = {":", "*", "?", "\"", "<", ">", "|"}; /** * Acquires the canonical File for the supplied file. * * @param file A non-null File for which the canonical File should be retrieved. * @return The canonical File of the supplied file. */ public static File getCanonicalFile(final File file) { // Check sanity Validate.notNull(file, "file"); // All done try { return file.getCanonicalFile(); } catch (IOException e) { throw new IllegalArgumentException("Could not acquire the canonical file for [" + file.getAbsolutePath() + "]", e); } } /** *

Retrieves the canonical File matching the supplied path in the following order or priority:

*
    *
  1. Absolute path: The path is used by itself (i.e. {@code new File(path);}). If an * existing file or directory matches the provided path argument, its canonical path will be returned.
  2. *
  3. Relative path: The path is appended to the baseDir (i.e. * {@code new File(baseDir, path);}). If an existing file or directory matches the provided path argument, * its canonical path will be returned. Only in this case will be baseDir argument be considered.
  4. *
*

If no file or directory could be derived from the supplied path and baseDir, {@code null} is returned.

* * @param path A non-null path which will be used to find an existing file or directory. * @param baseDir A directory to which the path will be appended to search for the existing file or directory in * case the file was nonexistent when interpreted as an absolute path. * @return either a canonical File for the path, or {@code null} if no file or directory matched * the supplied path and baseDir. */ public static File getExistingFile(final String path, final File baseDir) { // Check sanity Validate.notEmpty(path, "path"); final File theFile = new File(path); File toReturn = null; // Is 'path' absolute? if (theFile.isAbsolute() && (EXISTING_FILE.accept(theFile) || EXISTING_DIRECTORY.accept(theFile))) { toReturn = getCanonicalFile(theFile); } // Is 'path' relative? if (!theFile.isAbsolute()) { // In this case, baseDir cannot be null. Validate.notNull(baseDir, "baseDir"); final File relativeFile = new File(baseDir, path); if (EXISTING_FILE.accept(relativeFile) || EXISTING_DIRECTORY.accept(relativeFile)) { toReturn = getCanonicalFile(relativeFile); } } // The path provided did not point to an existing File or Directory. return toReturn; } /** * Retrieves the URL for the supplied File. Convenience method which hides exception handling * for the operation in question. * * @param aFile A File for which the URL should be retrieved. * @return The URL for the supplied aFile. * @throws java.lang.IllegalArgumentException if getting the URL yielded a MalformedURLException. */ public static URL getUrlFor(final File aFile) throws IllegalArgumentException { // Check sanity Validate.notNull(aFile, "aFile"); try { return aFile.toURI().normalize().toURL(); } catch (MalformedURLException e) { throw new IllegalArgumentException("Could not retrieve the URL from file [" + getCanonicalPath(aFile) + "]", e); } } /** * Acquires the file for a supplied URL, provided that its protocol is is either a file or a jar. * * @param anURL a non-null URL. * @param encoding The encoding to be used by the URLDecoder to decode the path found. * @return The File pointing to the supplied URL, for file or jar protocol URLs and null otherwise. */ public static File getFileFor(final URL anURL, final String encoding) { // Check sanity Validate.notNull(anURL, "anURL"); Validate.notNull(encoding, "encoding"); final String protocol = anURL.getProtocol(); File toReturn = null; if ("file".equalsIgnoreCase(protocol)) { try { final String decodedPath = URLDecoder.decode(anURL.getPath(), encoding); toReturn = new File(decodedPath); } catch (Exception e) { throw new IllegalArgumentException("Could not get the File for [" + anURL + "]", e); } } else if ("jar".equalsIgnoreCase(protocol)) { try { // Decode the JAR final String tmp = URLDecoder.decode(anURL.getFile(), encoding); // JAR URLs generally contain layered protocols, such as: // jar:file:/some/path/to/nazgul-tools-validation-aspect-4.0.2.jar!/the/package/ValidationAspect.class final URL innerURL = new URL(tmp); // We can handle File protocol URLs here. if ("file".equalsIgnoreCase(innerURL.getProtocol())) { // Peel off the inner protocol final String innerUrlPath = innerURL.getPath(); final String filePath = innerUrlPath.contains("!") ? innerUrlPath.substring(0, innerUrlPath.indexOf("!")) : innerUrlPath; toReturn = new File(URLDecoder.decode(filePath, encoding)); } } catch (Exception e) { throw new IllegalArgumentException("Could not get the File for [" + anURL + "]", e); } } // All done. return toReturn; } /** * Filters files found either in the sources paths (or in the standardDirectory if no explicit sources are given), * and retrieves a List holding those files that do not match any of the supplied Java Regular Expression * excludePatterns. * * @param baseDir The non-null basedir Directory. * @param sources The sources which should be either absolute or relative (to the given baseDir) * paths to files or to directories that should be searched recursively for files. * @param standardDirectories If no sources are given, revert to searching all files under these standard * directories. Each path is {@code relativize()}-d to the supplied baseDir to * reach a directory path. * @param log A non-null Maven Log for logging any operations performed. * @param fileTypeDescription A human-readable short description of what kind of files are searched for, such as * "xsdSources" or "xjbSources". * @param excludePatterns An optional List of patterns used to construct an ExclusionRegExpFileFilter used to * identify files which should be excluded from the result. * @return URLs to all Files under the supplied sources (or standardDirectories, if no explicit sources * are given) which do not match the supplied Java Regular excludePatterns. */ @SuppressWarnings("all") public static List filterFiles(final File baseDir, final List sources, final List standardDirectories, final Log log, final String fileTypeDescription, final List> excludePatterns) { final SortedMap pathToResolvedSourceMap = new TreeMap(); for (String current : standardDirectories) { for (File currentResolvedSource : FileSystemUtilities.filterFiles( baseDir, sources, FileSystemUtilities.relativize(current, baseDir, true), log, fileTypeDescription, excludePatterns)) { // Add the source pathToResolvedSourceMap.put( FileSystemUtilities.getCanonicalPath(currentResolvedSource), currentResolvedSource); } } final List toReturn = new ArrayList(); // Extract the URLs for all resolved Java sources. for (Map.Entry current : pathToResolvedSourceMap.entrySet()) { toReturn.add(FileSystemUtilities.getUrlFor(current.getValue())); } if (log.isDebugEnabled()) { final StringBuilder builder = new StringBuilder(); builder.append("\n+=================== [Filtered " + fileTypeDescription + "]\n"); builder.append("|\n"); builder.append("| " + excludePatterns.size() + " Exclude patterns:\n"); for (int i = 0; i < excludePatterns.size(); i++) { builder.append("| [" + (i + 1) + "/" + excludePatterns.size() + "]: " + excludePatterns.get(i) + "\n"); } builder.append("|\n"); builder.append("| " + standardDirectories.size() + " Standard Directories:\n"); for (int i = 0; i < standardDirectories.size(); i++) { builder.append("| [" + (i + 1) + "/" + standardDirectories.size() + "]: " + standardDirectories.get(i) + "\n"); } builder.append("|\n"); builder.append("| " + toReturn.size() + " Results:\n"); for (int i = 0; i < toReturn.size(); i++) { builder.append("| [" + (i + 1) + "/" + toReturn.size() + "]: " + toReturn.get(i) + "\n"); } builder.append("|\n"); builder.append("+=================== [End Filtered " + fileTypeDescription + "]\n\n"); // Log all. log.debug(builder.toString().replace("\n", AbstractJaxbMojo.NEWLINE)); } // All done. return toReturn; } /** * Filters files found either in the sources paths (or in the standardDirectory if no explicit sources are given), * and retrieves a List holding those files that do not match any of the supplied Java Regular Expression * excludePatterns. * * @param baseDir The non-null basedir Directory. * @param sources The sources which should be either absolute or relative (to the given baseDir) * paths to files or to directories that should be searched recursively for files. * @param standardDirectory If no sources are given, revert to searching all files under this standard directory. * This is the path appended to the baseDir to reach a directory. * @param log A non-null Maven Log for logging any operations performed. * @param fileTypeDescription A human-readable short description of what kind of files are searched for, such as * "xsdSources" or "xjbSources". * @param excludeFilters An optional List of Filters used to identify files which should be excluded from * the result. * @return All files under the supplied sources (or standardDirectory, if no explicit sources are given) which * do not match the supplied Java Regular excludePatterns. */ @SuppressWarnings("CheckStyle") public static List filterFiles(final File baseDir, final List sources, final String standardDirectory, final Log log, final String fileTypeDescription, final List> excludeFilters) { // Check sanity Validate.notNull(baseDir, "baseDir"); Validate.notNull(log, "log"); Validate.notEmpty(standardDirectory, "standardDirectory"); Validate.notEmpty(fileTypeDescription, "fileTypeDescription"); // No sources provided? Fallback to the standard (which should be a relative path). List effectiveSources = sources; if (sources == null || sources.isEmpty()) { effectiveSources = new ArrayList(); final File tmp = new File(standardDirectory); final File rootDirectory = tmp.isAbsolute() ? tmp : new File(baseDir, standardDirectory); effectiveSources.add(FileSystemUtilities.getCanonicalPath(rootDirectory)); } // First, remove the non-existent sources. List existingSources = new ArrayList(); for (String current : effectiveSources) { final File existingFile = FileSystemUtilities.getExistingFile(current, baseDir); if (existingFile != null) { existingSources.add(existingFile); if (log.isDebugEnabled()) { log.debug("Accepted configured " + fileTypeDescription + " [" + FileSystemUtilities.getCanonicalFile(existingFile) + "]"); } } else { if (log.isInfoEnabled()) { log.info("Ignored given or default " + fileTypeDescription + " [" + current + "], since it is not an existent file or directory."); } } } if (log.isDebugEnabled() && existingSources.size() > 0) { final int size = existingSources.size(); log.debug(" [" + size + " existing " + fileTypeDescription + "] ..."); for (int i = 0; i < size; i++) { log.debug(" " + (i + 1) + "/" + size + ": " + existingSources.get(i)); } log.debug(" ... End [" + size + " existing " + fileTypeDescription + "]"); } // All Done. return FileSystemUtilities.resolveRecursively(existingSources, excludeFilters, log); } /** * Filters all supplied files using the provided {@code acceptFilter}. * * @param files The list of files to resolve, filter and return. If the {@code files} List * contains directories, they are searched for Files recursively. Any found Files in such * a search are included in the resulting File List if they match the acceptFilter supplied. * @param acceptFilter A filter matched to all files in the given List. If the acceptFilter matches a file, it is * included in the result. * @param log The active Maven Log. * @return All files in (or files in subdirectories of directories provided in) the files List, provided that each * file is accepted by an ExclusionRegExpFileFilter. */ public static List filterFiles(final List files, final Filter acceptFilter, final Log log) { // Check sanity Validate.notNull(files, "files"); final List toReturn = new ArrayList(); if (files.size() > 0) { for (File current : files) { final boolean isAcceptedFile = EXISTING_FILE.accept(current) && acceptFilter.accept(current); final boolean isAcceptedDirectory = EXISTING_DIRECTORY.accept(current) && acceptFilter.accept(current); if (isAcceptedFile) { toReturn.add(current); } else if (isAcceptedDirectory) { recurseAndPopulate(toReturn, Collections.singletonList(acceptFilter), current, false, log); } } } // All done return toReturn; } /** * Retrieves a List of Files containing all the existing files within the supplied files List, including all * files found in directories recursive to any directories provided in the files list. Each file included in the * result must pass an ExclusionRegExpFileFilter synthesized from the supplied exclusions pattern(s). * * @param files The list of files to resolve, filter and return. If the {@code files} List * contains directories, they are searched for Files recursively. Any found Files in such * a search are included in the resulting File List if they do not match any of the * exclusionFilters supplied. * @param exclusionFilters A List of Filters which identify files to remove from the result - implying that any * File matched by any of these exclusionFilters will not be included in the result. * @param log The active Maven Log. * @return All files in (or files in subdirectories of directories provided in) the files List, provided that each * file is accepted by an ExclusionRegExpFileFilter. */ public static List resolveRecursively(final List files, final List> exclusionFilters, final Log log) { // Check sanity Validate.notNull(files, "files"); final List> effectiveExclusions = exclusionFilters == null ? new ArrayList>() : exclusionFilters; final List toReturn = new ArrayList(); if (files.size() > 0) { for (File current : files) { final boolean isAcceptedFile = EXISTING_FILE.accept(current) && Filters.noFilterMatches(current, effectiveExclusions); final boolean isAcceptedDirectory = EXISTING_DIRECTORY.accept(current) && Filters.noFilterMatches(current, effectiveExclusions); if (isAcceptedFile) { toReturn.add(current); } else if (isAcceptedDirectory) { recurseAndPopulate(toReturn, effectiveExclusions, current, true, log); } } } // All done return toReturn; } /** * Convenience method to successfully create a directory - or throw an exception if failing to create it. * * @param aDirectory The directory to create. * @param cleanBeforeCreate if {@code true}, the directory and all its content will be deleted before being * re-created. This will ensure that the created directory is really clean. * @throws MojoExecutionException if the aDirectory could not be created (and/or cleaned). */ public static void createDirectory(final File aDirectory, final boolean cleanBeforeCreate) throws MojoExecutionException { // Check sanity Validate.notNull(aDirectory, "aDirectory"); validateFileOrDirectoryName(aDirectory); // Clean an existing directory? if (cleanBeforeCreate) { try { FileUtils.deleteDirectory(aDirectory); } catch (IOException e) { throw new MojoExecutionException("Could not clean directory [" + getCanonicalPath(aDirectory) + "]", e); } } // Now, make the required directory, if it does not already exist as a directory. final boolean existsAsFile = aDirectory.exists() && aDirectory.isFile(); if (existsAsFile) { throw new MojoExecutionException("[" + getCanonicalPath(aDirectory) + "] exists and is a file. " + "Cannot make directory"); } else if (!aDirectory.exists() && !aDirectory.mkdirs()) { throw new MojoExecutionException("Could not create directory [" + getCanonicalPath(aDirectory) + "]"); } } /** * If the supplied path refers to a file or directory below the supplied basedir, the returned * path is identical to the part below the basedir. * * @param path The path to strip off basedir path from, and return. * @param parentDir The maven project basedir. * @param removeInitialFileSep If true, an initial {@code File#separator} is removed before returning. * @return The path relative to basedir, if it is situated below the basedir. Otherwise the supplied path. */ public static String relativize(final String path, final File parentDir, final boolean removeInitialFileSep) { // Check sanity Validate.notNull(path, "path"); Validate.notNull(parentDir, "parentDir"); final String basedirPath = FileSystemUtilities.getCanonicalPath(parentDir); String toReturn = path; // Compare case insensitive if (path.toLowerCase().startsWith(basedirPath.toLowerCase())) { toReturn = path.substring(basedirPath.length()); } // Handle whitespace in the argument. return removeInitialFileSep && toReturn.startsWith(File.separator) ? toReturn.substring(File.separator.length()) : toReturn; } /** * If the supplied fileOrDir is a File, it is added to the returned List if any of the filters Match. * If the supplied fileOrDir is a Directory, it is listed and any of the files immediately within the fileOrDir * directory are returned within the resulting List provided that they match any of the supplied filters. * * @param fileOrDir A File or Directory. * @param fileFilters A List of filter of which at least one must match to add the File * (or child Files, in case of a directory) to the resulting List. * @param log The active Maven Log * @return A List holding the supplied File (or child Files, in case fileOrDir is a Directory) given that at * least one Filter accepts them. */ @SuppressWarnings("all") public static List listFiles(final File fileOrDir, final List> fileFilters, final Log log) { return listFiles(fileOrDir, fileFilters, false, log); } /** * If the supplied fileOrDir is a File, it is added to the returned List if any of the filters Match. * If the supplied fileOrDir is a Directory, it is listed and any of the files immediately within the fileOrDir * directory are returned within the resulting List provided that they match any of the supplied filters. * * @param fileOrDir A File or Directory. * @param fileFilters A List of filter of which at least one must match to add the File (or child Files, in case * of a directory) to the resulting List. * @param excludeFilterOperation if {@code true}, all fileFilters are considered exclude filter, i.e. if * any of the Filters match the fileOrDir, that fileOrDir will be excluded from the * result. * @param log The active Maven Log * @return A List holding the supplied File (or child Files, in case fileOrDir is a Directory) given that at * least one Filter accepts them. */ @SuppressWarnings("all") public static List listFiles(final File fileOrDir, final List> fileFilters, final boolean excludeFilterOperation, final Log log) { // Check sanity Validate.notNull(log, "log"); Validate.notNull(fileFilters, "fileFilters"); final List toReturn = new ArrayList(); if (EXISTING_FILE.accept(fileOrDir)) { checkAndAdd(toReturn, fileOrDir, fileFilters, excludeFilterOperation, log); } else if (EXISTING_DIRECTORY.accept(fileOrDir)) { final File[] listedFiles = fileOrDir.listFiles(); if (listedFiles != null) { for (File current : listedFiles) { // Typically, hidden directories start with '.' // Except them from automagic filtering. if (current.getName().charAt(0) != '.') { checkAndAdd(toReturn, current, fileFilters, excludeFilterOperation, log); } } } } // All done. return toReturn; } // // Private helpers // private static void checkAndAdd(final List toPopulate, final File current, final List> fileFilters, final boolean excludeFilterOperation, final Log log) { // // When no filters are supplied... // [Include Operation]: all files will be rejected // [Exclude Operation]: all files will be included // final boolean noFilters = fileFilters == null || fileFilters.isEmpty(); final boolean addFile = excludeFilterOperation ? noFilters || Filters.rejectAtLeastOnce(current, fileFilters) : noFilters || Filters.matchAtLeastOnce(current, fileFilters); final String logPrefix = (addFile ? "Accepted " : "Rejected ") + (current.isDirectory() ? "directory" : "file") + " ["; if (addFile) { toPopulate.add(current); } if (log.isDebugEnabled()) { log.debug(logPrefix + getCanonicalPath(current) + "]"); } } private static void validateFileOrDirectoryName(final File fileOrDir) { if (Os.isFamily(Os.FAMILY_WINDOWS) && !FileUtils.isValidWindowsFileName(fileOrDir)) { throw new IllegalArgumentException( "The file (" + fileOrDir + ") cannot contain any of the following characters: \n" + StringUtils.join(INVALID_CHARACTERS_FOR_WINDOWS_FILE_NAME, " ")); } } private static void recurseAndPopulate(final List toPopulate, final List> fileFilters, final File aDirectory, final boolean excludeOperation, final Log log) { final List files = listFiles(aDirectory, fileFilters, excludeOperation, log); for (File current : files) { if (EXISTING_FILE.accept(current)) { toPopulate.add(current); } if (EXISTING_DIRECTORY.accept(current)) { recurseAndPopulate(toPopulate, fileFilters, current, excludeOperation, log); } } } } JavaVersion.java000066400000000000000000000046321351100213400337740ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/sharedpackage org.codehaus.mojo.jaxb2.shared; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Helper to extract the runtime Java version from the System.properties. * * @author Lennart Jörelid * @since 2.4 */ public final class JavaVersion { private static final String JAVA_VERSION_PROPERTY = "java.specification.version"; /** * Retrieves the major java runtime version as an integer. * * @return the major java runtime version as an integer. */ public static int getJavaMajorVersion() { final String[] versionElements = System.getProperty(JAVA_VERSION_PROPERTY).split("\\."); final int[] versionNumbers = new int[versionElements.length]; for (int i = 0; i < versionElements.length; i++) { try { versionNumbers[i] = Integer.parseInt(versionElements[i]); } catch (NumberFormatException e) { versionNumbers[i] = 0; } } /* Java versions 1 - 8 (i.e. jdk 1.1 through 1.8) yields the structure 1.8 Java versions 9 - yields the structure 10 JDK 10 ====== [java.specification.version]: 10 JDK 8 ===== [java.specification.version]: 1.8 JDK 7 ===== [java.specification.version]: 1.7 */ return versionNumbers[0] == 1 ? versionNumbers[1] : versionNumbers[0]; } /** * Checks if the runtime java version is JDK 8 or lower. * * @return true if the runtime java version is JDK 8 or lower. */ public static boolean isJdk8OrLower() { return getJavaMajorVersion() <= 8; } } Validate.java000066400000000000000000000062341351100213400332760ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/sharedpackage org.codehaus.mojo.jaxb2.shared; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Simple argument validator, inspired by the commons-lang. * * @author Lennart Jörelid * @since 2.0 */ public final class Validate { /** * Hide constructor for utility classes. */ private Validate() { } /** * Validates that the supplied object is not null, and throws a NullPointerException otherwise. * * @param object The object to validate for {@code null}-ness. * @param argumentName The argument name of the object to validate. If supplied (i.e. non-{@code null}), * this value is used in composing a better exception message. */ public static void notNull(final Object object, final String argumentName) { if (object == null) { throw new NullPointerException(getMessage("null", argumentName)); } } /** * Validates that the supplied object is not null, and throws an IllegalArgumentException otherwise. * * @param aString The string to validate for emptyness. * @param argumentName The argument name of the object to validate. * If supplied (i.e. non-{@code null}), this value is used in composing * a better exception message. */ public static void notEmpty(final String aString, final String argumentName) { // Check sanity notNull(aString, argumentName); if (aString.length() == 0) { throw new IllegalArgumentException(getMessage("empty", argumentName)); } } /** * Validates that the supplied condition is true, and throws an IllegalArgumentException otherwise. * * @param condition The condition to validate for truth. * @param message The exception message used within the IllegalArgumentException if the condition is false. */ public static void isTrue(final boolean condition, final String message) { if (!condition) { throw new IllegalArgumentException(message); } } // // Private helpers // private static String getMessage(final String exceptionDefinition, final String argumentName) { return "Cannot handle " + exceptionDefinition + (argumentName == null ? "" : " '" + argumentName + "'") + " argument."; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/arguments/000077500000000000000000000000001351100213400327615ustar00rootroot00000000000000ArgumentBuilder.java000066400000000000000000000204641351100213400366440ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/argumentspackage org.codehaus.mojo.jaxb2.shared.arguments; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.Validate; import java.util.ArrayList; import java.util.List; /** * Utility class to build an array containing method arguments, as received from a command-line invocation of a tool. * * @author Lennart Jörelid */ public final class ArgumentBuilder { // Internal state private final Object lock = new Object(); private static final int NOT_FOUND = -1; private static final char DASH = '-'; private List arguments = new ArrayList(); /** *

Retrieves all arguments as a string array, usable by a method accepting a String[] for argument. * This would be true of {@code public static void main(String[] args)}, as well as the entry points * for both the XJC and the Schemagen tools.

* * @return an array holding all arguments in this ArgumentBuilder. */ public String[] build() { synchronized (lock) { final String[] toReturn = new String[arguments.size()]; return arguments.toArray(toReturn); } } /** *

Adds a flag on the form {@code -someflag} to the list of arguments contained within this ArgumentBuilder. * If the {@code flag} argument does not start with a dash ('-'), one will be prepended.

*

Typical usage:

*

     *     argumentBuilder
     *      .withFlag(someBooleanParameter, "foobar")
     *      .withFlag(someOtherBooleanParameter, "gnat")
     *      .withFlag(someThirdBooleanParameter, "gnu")
     *      ....
     * 
* * @param addFlag if {@code true}, the flag will be added to the underlying list of arguments * within this ArgumentBuilder. * @param flag The flag/argument to add. The flag must be a complete word, implying it * cannot contain whitespace. * @return This ArgumentBuilder, for chaining. */ public ArgumentBuilder withFlag(final boolean addFlag, final String flag) { // Bail out? if (!addFlag) { return this; } // Check sanity Validate.notEmpty(flag, "flag"); Validate.isTrue(!AbstractJaxbMojo.CONTAINS_WHITESPACE.matcher(flag).matches(), "Flags cannot contain whitespace. Got: [" + flag + "]"); // Trim, and add the flag as an argument. final String trimmed = flag.trim(); Validate.notEmpty(trimmed, "flag"); // Prepend the DASH if required final String toAdd = trimmed.charAt(0) != DASH ? DASH + trimmed : trimmed; // Assign the argument only if not already set. if (getIndexForFlag(toAdd) == NOT_FOUND) { synchronized (lock) { arguments.add(toAdd); } } // All done. return this; } /** *

Adds a name and an argument on the form {@code -name value} to the list of arguments contained * within this ArgumentBuilder. The two parts will yield 2 elements in the underlying argument list. * If the {@code name} argument does not start with a dash ('-'), one will be prepended.

*

Typical usage:

*

     *     // These values should be calculated as part of the business logic
     *     final boolean addFooBar = true;
     *     final boolean addGnat = true;
     *     final boolean addGnu = false;
     *
     *     // Add all relevant arguments
     *     argumentBuilder
     *      .withNamedArgument(addFooBar, "foobar", "foobarValue")
     *      .withNamedArgument(addGnat, "-gnat", "gnatValue")
     *      .withNamedArgument(addGnu, "gnu", "gnuValue")
     *      ....
     * 
* * @param addNamedArgument if {@code true}, the named argument (name and value) will be added to * the underlying list of arguments within this ArgumentBuilder. * @param name The name of the namedArgument to add. Cannot be empty. * @param value The value of the namedArgument to add. * @return This ArgumentBuilder, for chaining. */ public ArgumentBuilder withNamedArgument(final boolean addNamedArgument, final String name, final String value) { // Bail out? if (!addNamedArgument) { return this; } // Check sanity Validate.notEmpty(name, "name"); Validate.notEmpty(value, "value"); // Trim the arguments, and validate again. final String trimmedName = name.trim(); final String trimmedValue = value.trim(); Validate.notEmpty(trimmedName, "name"); Validate.notEmpty(trimmedValue, "value"); // Add or update the name and value. if (!updateValueForNamedArgument(name, value)) { synchronized (lock) { withFlag(true, trimmedName); arguments.add(value); } } // All done. return this; } /** * Convenience form for the {@code withNamedArgument} method, where a named argument is only added * if the value is non-null and non-empty after trimming. * * @param name The name of the namedArgument to add. Cannot be empty. * @param value The value of the namedArgument to add. * @return This ArgumentBuilder, for chaining. * @see #withNamedArgument(boolean, String, String) */ public ArgumentBuilder withNamedArgument(final String name, final String value) { // Check sanity Validate.notEmpty(name, "name"); // Only add a named argument if the value is non-empty. if (value != null && !value.trim().isEmpty()) { withNamedArgument(true, name, value.trim()); } // All done. return this; } /** * Adds the supplied pre-compiled arguments in the same order as they were given. * * @param preCompiledArguments A non-null List holding pre-compiled arguments. * @return This ArgumentBuilder, for chaining. */ public ArgumentBuilder withPreCompiledArguments(final List preCompiledArguments) { // Check sanity Validate.notNull(preCompiledArguments, "preCompiledArguments"); // Add the preCompiledArguments in the exact order they were given. synchronized (lock) { for (String current : preCompiledArguments) { arguments.add(current); } } // All done. return this; } // // Private helpers // private int getIndexForFlag(final String name) { // Check sanity Validate.notEmpty(name, "name"); synchronized (lock) { for (int i = 0; i < arguments.size(); i++) { if (arguments.get(i).equalsIgnoreCase(name)) { return i; } } } // Not found. return NOT_FOUND; } private boolean updateValueForNamedArgument(final String name, final String newValue) { // Check sanity Validate.notEmpty(name, "name"); int flagIndex = getIndexForFlag(name); if (flagIndex == NOT_FOUND) { // Nothing updated return false; } // Updating the value of the named argument. int valueIndex = flagIndex + 1; synchronized (lock) { arguments.set(valueIndex, newValue); } return true; } } environment/000077500000000000000000000000001351100213400332415ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/sharedAbstractLogAwareFacet.java000066400000000000000000000030641351100213400402370ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environmentpackage org.codehaus.mojo.jaxb2.shared.environment; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; /** * Abstract EnvironmentFacet which sports a non-null Maven Log for use by subclasses. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.1 */ public abstract class AbstractLogAwareFacet implements EnvironmentFacet { // Internal state protected Log log; /** * Creates an AbstractLogAwareFacet wrapping the supplied, non-null Log. * * @param log The active Maven Log. */ public AbstractLogAwareFacet(final Log log) { // Check sanity Validate.notNull(log, "log"); // Assign internal state this.log = log; } } EnvironmentFacet.java000066400000000000000000000042051351100213400373540ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environmentpackage org.codehaus.mojo.jaxb2.shared.environment; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** *

Specification for an Environment controller, which can infer a temporary and reversible change * to the environment of an executing task. Any changes performed by this Environment * must be reversible, and should be restored to their original values in the {@code restore()} method.

*

EnvironmentFacets are required since the JDK tools (XJC, SchemaGen, JXC) expect certain configuration * or setup to be present during their execution. For improved usability within the JAXB2-Maven-Plugin, we * would like to supply all configuration to the plugin, and delegate the setting of various system-, thread-, * logging- or environment properties to explicit EnvironmentFacet implementations.

* * @author Lennart Jörelid, jGuru Europe AB * @since 2.1 */ public interface EnvironmentFacet { /** * Sets up this Environment, inferring temporary changes to environment variables or conditions. * The changes must be reversible, and should be restored to their original values in the {@code restore()} method. */ void setup(); /** * Restores the original Environment, implying that the change performed in {@code setup()} * method are restored to the state before the setup method was called. */ void restore(); } ToolExecutionEnvironment.java000066400000000000000000000155071351100213400411420ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environmentpackage org.codehaus.mojo.jaxb2.shared.environment; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.environment.classloading.ThreadContextClassLoaderBuilder; import org.codehaus.mojo.jaxb2.shared.environment.classloading.ThreadContextClassLoaderHolder; import org.codehaus.mojo.jaxb2.shared.environment.locale.LocaleFacet; import org.codehaus.mojo.jaxb2.shared.environment.logging.LoggingHandlerEnvironmentFacet; import java.util.ArrayList; import java.util.List; /** * Compound EnvironmentFacet implementation which is used to set up and use a collection * of other EnvironmentFacet instances during the run of the JAXB2 Maven Plugin. * * @author Lennart Jörelid, jGuru Europe AB */ public class ToolExecutionEnvironment extends AbstractLogAwareFacet { // Internal state private ThreadContextClassLoaderBuilder builder; private ThreadContextClassLoaderHolder holder; private LoggingHandlerEnvironmentFacet loggingHandlerEnvironmentFacet; private List extraFacets; private LocaleFacet localeFacet; /** * Creates a new ToolExecutionEnvironment object wrapping the supplied Maven Log. * * @param mavenLog The active Maven Log. * @param builder The ThreadContextClassLoaderBuilder used to set up a ThreadContext ClassLoader for * this tool execution environment. * @param localeFacet An optional LocaleFacet to alter the Locale for the tool execution environment. If * the localeFacet is {@code null}, the locale will not be changed. * @param loggingHandlerFacet The EnvironmentFacet for replacing Handlers from Java Util Logging with a Maven Log. */ public ToolExecutionEnvironment(final Log mavenLog, final ThreadContextClassLoaderBuilder builder, final LoggingHandlerEnvironmentFacet loggingHandlerFacet, final LocaleFacet localeFacet) { super(mavenLog); // Check sanity Validate.notNull(builder, "builder"); Validate.notNull(loggingHandlerFacet, "loggingHandlerFacet"); // Assign internal state this.builder = builder; this.loggingHandlerEnvironmentFacet = loggingHandlerFacet; this.localeFacet = localeFacet; extraFacets = new ArrayList(); } /** * Adds the supplied EnvironmentFacet to this ToolExecutionEnvironment. * * @param facet the non-null EnvironmentFacet to add to this ToolExecutionEnvironment. */ public void add(final EnvironmentFacet facet) { // Check sanity Validate.notNull(facet, "facet"); // All done. extraFacets.add(facet); } /** * Delegate method retrieving the classpath as argument from the underlying ThreadContextClassLoaderHolder. * Note that the setup method must be invoked before this one is. * * @return the ClassPath as an argument to external processes such as XJC. * @see ThreadContextClassLoaderHolder#getClassPathAsArgument() */ public String getClassPathAsArgument() { // Check sanity if (holder == null) { throw new IllegalStateException("Cannot retrieve the classpath argument before calling 'setup'"); } // Delegate and return return holder.getClassPathAsArgument(); } /** * {@inheritDoc} */ @Override public final void setup() { // Setup mandatory environment facets try { if (log.isDebugEnabled()) { log.debug("ToolExecutionEnvironment setup -- Starting."); } // Build the ClassLoader as required for the JAXB tools holder = builder.buildAndSet(); // Redirect the JUL logging handler used by the tools to the Maven log. loggingHandlerEnvironmentFacet.setup(); // If requested, switch the locale if (localeFacet != null) { localeFacet.setup(); } // Setup optional/extra environment facets for (EnvironmentFacet current : extraFacets) { try { current.setup(); } catch (Exception e) { throw new IllegalStateException("Could not setup() EnvironmentFacet of type [" + current.getClass().getName() + "]", e); } } if (log.isDebugEnabled()) { log.debug("ToolExecutionEnvironment setup -- Done."); } } catch (IllegalStateException e) { throw e; } catch (Exception e) { throw new IllegalStateException("Could not setup mandatory ToolExecutionEnvironment.", e); } } /** * {@inheritDoc} */ @Override public final void restore() { try { if (log.isDebugEnabled()) { log.debug("ToolExecutionEnvironment restore -- Starting."); } for (EnvironmentFacet current : extraFacets) { try { current.restore(); } catch (Exception e) { throw new IllegalStateException("Could not restore() EnvironmentFacet of type [" + current.getClass().getName() + "]", e); } } } finally { // Restore the logging handler structure. loggingHandlerEnvironmentFacet.restore(); // Restore the original locale if (localeFacet != null) { localeFacet.restore(); } if (holder != null) { // Restore the original ClassLoader holder.restoreClassLoaderAndReleaseThread(); } if (log.isDebugEnabled()) { log.debug("ToolExecutionEnvironment restore -- Done."); } } } } classloading/000077500000000000000000000000001351100213400357045ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environmentContextClassLoaderEnvironmentFacet.java000066400000000000000000000055551351100213400455120ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environment/classloadingpackage org.codehaus.mojo.jaxb2.shared.environment.classloading; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.environment.AbstractLogAwareFacet; /** * Adapter converting a ThreadContextClassLoaderHolder to the standard lifecycle * defined within the EnvironmentFacet. * * @author Lennart Jörelid, jGuru Europe AB */ public class ContextClassLoaderEnvironmentFacet extends AbstractLogAwareFacet { // Internal state private ThreadContextClassLoaderBuilder builder; private ThreadContextClassLoaderHolder holder; /** * Compound constructor creating a ContextClassLoaderEnvironmentFacet wrapping the supplied data. * * @param log The active Maven Log. * @param builder A fully set up ThreadContextClassLoaderBuilder, where the {@code buildAndSet()} method * should not be invoked yet. * @see ThreadContextClassLoaderBuilder */ public ContextClassLoaderEnvironmentFacet(final Log log, final ThreadContextClassLoaderBuilder builder) { super(log); // Check sanity Validate.notNull(builder, "builder"); // Assign internal state this.builder = builder; } /** * Delegate method retrieving the classpath as argument from the underlying ThreadContextClassLoaderHolder. * Note that the setup method must be invoked before this one is. * * @return the ClassPath as an argument to external processes such as XJC. */ public String getClassPathAsArgument() { // Check sanity Validate.notNull(holder, "holder"); // Delegate and return return holder.getClassPathAsArgument(); } /** * {@inheritDoc} */ @Override public void setup() { this.holder = builder.buildAndSet(); } /** * {@inheritDoc} */ @Override public void restore() { holder.restoreClassLoaderAndReleaseThread(); } } ThreadContextClassLoaderBuilder.java000066400000000000000000000373631351100213400447630ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environment/classloadingpackage org.codehaus.mojo.jaxb2.shared.environment.classloading; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static org.codehaus.mojo.jaxb2.shared.environment.classloading.ThreadContextClassLoaderBuilder.SupportedURLProtocols.*; /** *

Utility class which assists in synthesizing a URLClassLoader for use as a ThreadLocal ClassLoader. * Typical use:

*
 *     
 *         // Create and set the ThreadContext ClassLoader
 *         ThreadContextClassLoaderHolder holder = null;
 *
 *         try {
 *
 *          holder = ThreadContextClassLoaderBuilder.createFor(getClass())
 *              .addPath("some/path")
 *              .addURL(someURL)
 *              .addPaths(aPathList)
 *              .buildAndSet();
 *
 *          // ... perform operations using the newly set ThreadContext ClassLoader...
 *
 *         } finally {
 *          // Restore the original ClassLoader
 *          holder.restoreClassLoaderAndReleaseThread();
 *         }
 *     
 * 
* * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public final class ThreadContextClassLoaderBuilder { /** * Simple enumeration of supported classpath URL protocols. */ enum SupportedURLProtocols { FILE, JAR, HTTP, HTTPS, BUNDLERESOURCE; /** * Filter function, indicating if this {@link SupportedURLProtocols} instance can handle the supplied protocol. * @param protocol The protocol to support. * @return true if this {@link SupportedURLProtocols} instance supports the given protocol. */ public boolean supports(final String protocol) { return protocol != null && this.name().equalsIgnoreCase(protocol.trim()); } } // Internal state private ClassLoader originalClassLoader; private List urlList; private Log log; private String encoding; private ThreadContextClassLoaderBuilder(final ClassLoader classLoader, final Log aLog, final String encoding) { log = aLog; originalClassLoader = classLoader; urlList = new ArrayList(); this.encoding = encoding; } /** * Adds the supplied anURL to the list of internal URLs which should be used to build an URLClassLoader. * Will only add an URL once, and warns about trying to re-add an URL. * * @param anURL The URL to add. * @return This ThreadContextClassLoaderBuilder, for builder pattern chaining. */ public ThreadContextClassLoaderBuilder addURL(final URL anURL) { // Check sanity Validate.notNull(anURL, "anURL"); // Add the segment unless already added. for (URL current : urlList) { if (current.toString().equalsIgnoreCase(anURL.toString())) { if (log.isWarnEnabled()) { log.warn("Not adding URL [" + anURL.toString() + "] twice. Check your plugin configuration."); } // Don't re-add the supplied URL. return this; } } // Add the supplied URL to the urlList if (log.isDebugEnabled()) { log.debug("Adding URL [" + anURL.toString() + "]"); } // // According to the URLClassLoader's documentation: // "Any URL that ends with a '/' is assumed to refer to a directory. // Otherwise, the URL is assumed to refer to a JAR file which will be downloaded and opened as needed." // // ... uhm ... instead of using the 'protocol' property of the URL itself? // // So ... we need to ensure that any file-protocol URLs which point to directories are actually // terminated with a '/'. Otherwise the URLClassLoader treats those URLs as JARs - and hence ignores them. // urlList.add(addSlashToDirectoryUrlIfRequired(anURL)); return this; } /** * Converts the supplied path to an URL and adds it to this ThreadContextClassLoaderBuilder. * * @param path A path to convert to an URL and add. * @return This ThreadContextClassLoaderBuilder, for builder pattern chaining. * @see #addURL(java.net.URL) */ public ThreadContextClassLoaderBuilder addPath(final String path) { // Check sanity Validate.notEmpty(path, "path"); // Convert to an URL, and delegate. final URL anUrl; try { anUrl = new File(path).toURI().toURL(); } catch (MalformedURLException e) { throw new IllegalArgumentException("Could not convert path [" + path + "] to an URL.", e); } // Delegate return addURL(anUrl); } /** * Converts the supplied path to an URL and adds it to this ThreadContextClassLoaderBuilder. * * @param paths A List of path to convert to URLs and add. * @return This ThreadContextClassLoaderBuilder, for builder pattern chaining. * @see #addPath(String) */ public ThreadContextClassLoaderBuilder addPaths(final List paths) { // Check sanity Validate.notNull(paths, "paths"); // Delegate for (String path : paths) { addPath(path); } return this; } /** *

This method performs 2 things in order:

*
    *
  1. Builds a ThreadContext ClassLoader from the URLs supplied to this Builder, and assigns the * newly built ClassLoader to the current Thread.
  2. *
  3. Stores the ThreadContextClassLoaderHolder for later restoration.
  4. *
* References to the original ThreadContextClassLoader and the currentThread are stored within the returned * ThreadContextClassLoaderHolder, and can be restored by a call to * {@code ThreadContextClassLoaderHolder.restoreClassLoaderAndReleaseThread()}. * * @return A fully set up ThreadContextClassLoaderHolder which is used to set the */ public ThreadContextClassLoaderHolder buildAndSet() { // Create the URLClassLoader from the supplied URLs final URL[] allURLs = new URL[urlList.size()]; urlList.toArray(allURLs); final URLClassLoader classLoader = new URLClassLoader(allURLs, originalClassLoader); // Assign the ThreadContext ClassLoader final Thread currentThread = Thread.currentThread(); currentThread.setContextClassLoader(classLoader); // Build the classpath argument StringBuilder builder = new StringBuilder(); try { for (URL current : Collections.list(classLoader.getResources(""))) { final String toAppend = getClassPathElement(current, encoding); if (toAppend != null) { builder.append(toAppend).append(File.pathSeparator); } } } catch (Exception e) { // Restore the original classloader to the active thread before failing. currentThread.setContextClassLoader(originalClassLoader); throw new IllegalStateException("Could not synthesize classpath from original classloader.", e); } final String classPathString = builder.length() > 0 ? builder.toString().substring(0, builder.length() - File.pathSeparator.length()) : ""; // All done. return new DefaultHolder(currentThread, this.originalClassLoader, classPathString); } /** * Creates a new ThreadContextClassLoaderBuilder using the supplied original classLoader, as well * as the supplied Maven Log. * * @param classLoader The original ClassLoader which should be used as the parent for the ThreadContext * ClassLoader produced by the ThreadContextClassLoaderBuilder generated by this builder method. * Cannot be null. * @param log The active Maven Log. Cannot be null. * @param encoding The encoding used by Maven. Cannot be null. * @return A ThreadContextClassLoaderBuilder wrapping the supplied members. */ public static ThreadContextClassLoaderBuilder createFor(final ClassLoader classLoader, final Log log, final String encoding) { // Check sanity Validate.notNull(classLoader, "classLoader"); Validate.notNull(log, "log"); // All done. return new ThreadContextClassLoaderBuilder(classLoader, log, encoding); } /** * Creates a new ThreadContextClassLoaderBuilder using the original ClassLoader from the supplied Class, as well * as the given Maven Log. * * @param aClass A non-null class from which to extract the original ClassLoader. * @param log The active Maven Log. Cannot be null. * @param encoding The encoding used by Maven. Cannot be null. * @return A ThreadContextClassLoaderBuilder wrapping the supplied members. */ public static ThreadContextClassLoaderBuilder createFor(final Class aClass, final Log log, final String encoding) { // Check sanity Validate.notNull(aClass, "aClass"); // Delegate return createFor(aClass.getClassLoader(), log, encoding); } /** * Converts the supplied URL to a class path element. * * @param anURL The non-null URL for which to acquire a classPath element. * @param encoding The encoding used by Maven. * @return The full (i.e. non-chopped) classpath element corresponding to the supplied URL. * @throws java.lang.IllegalArgumentException if the supplied URL had an unknown protocol. */ public static String getClassPathElement(final URL anURL, final String encoding) throws IllegalArgumentException { // Check sanity Validate.notNull(anURL, "anURL"); final String protocol = anURL.getProtocol(); String toReturn = null; if (FILE.supports(protocol)) { final String originalPath = anURL.getPath(); try { return URLDecoder.decode(anURL.getPath(), encoding); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException("Could not URLDecode path [" + originalPath + "] using encoding [" + encoding + "]", e); } } else if (JAR.supports(protocol)) { toReturn = anURL.getPath(); } else if (HTTP.supports(protocol) || HTTPS.supports(protocol)) { toReturn = anURL.toString(); } else if (BUNDLERESOURCE.supports(protocol)) { // e.g. when used in Eclipse/m2e toReturn = anURL.toString(); } else { throw new IllegalArgumentException("Unknown protocol [" + protocol + "]; could not handle URL [" + anURL + "]"); } return toReturn; } // // Private helpers // private URL addSlashToDirectoryUrlIfRequired(final URL anURL) { // Check sanity Validate.notNull(anURL, "anURL"); URL toReturn = anURL; if ("file".equalsIgnoreCase(anURL.getProtocol())) { final File theFile = new File(anURL.getPath()); if (theFile.isDirectory()) { try { // This ensures that an URL pointing to a File directory // actually is terminated by a '/', which is required by // the URLClassLoader to operate properly. toReturn = theFile.toURI().toURL(); } catch (MalformedURLException e) { // This should never happen throw new IllegalArgumentException("Could not convert a File to an URL", e); } } } // All done. return toReturn; } /** * Default implementation of the ThreadContextClassLoaderCleaner specification, * with added finalizer to ensure we release the Thread reference no matter * what happens with any DefaultCleaner objects. */ @SuppressWarnings("all") class DefaultHolder implements ThreadContextClassLoaderHolder { // Internal state private Thread affectedThread; private ClassLoader originalClassLoader; private String classPathArgument; /** * Compound constructor creating a default-implementation {@link ThreadContextClassLoaderHolder} which * wraps references to the {@link Thread} affected as well as the original ClassLoader to restore during * the call to {@link #restoreClassLoaderAndReleaseThread()} method. * * @param affectedThread The non-null Thread for which a new ClassLoader should be constructed. * @param originalClassLoader The non-null original ClassLoader. * @param classPathArgument The non-null classpath argument, to be returned * from the method call to {@link #getClassPathAsArgument()}. */ public DefaultHolder(final Thread affectedThread, final ClassLoader originalClassLoader, final String classPathArgument) { // Check sanity Validate.notNull(affectedThread, "affectedThread"); Validate.notNull(originalClassLoader, "originalClassLoader"); Validate.notNull(classPathArgument, "classPathArgument"); // Assign internal state this.affectedThread = affectedThread; this.originalClassLoader = originalClassLoader; this.classPathArgument = classPathArgument; } /** * {@inheritDoc} */ @Override public void restoreClassLoaderAndReleaseThread() { if (affectedThread != null) { // Restore original state affectedThread.setContextClassLoader(originalClassLoader); // Null out the internal state affectedThread = null; originalClassLoader = null; classPathArgument = null; } } /** * {@inheritDoc} */ @Override public String getClassPathAsArgument() { return classPathArgument; } /** * {@inheritDoc} */ @Override protected void finalize() throws Throwable { try { // First, release all resources held by this object. restoreClassLoaderAndReleaseThread(); } finally { // Now, perform standard finalization. super.finalize(); } } } } ThreadContextClassLoaderHolder.java000066400000000000000000000046741351100213400446110ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environment/classloadingpackage org.codehaus.mojo.jaxb2.shared.environment.classloading; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** *

Specification for how to restore the original ThreadContext ClassLoader to a Thread. * When we support JDK 1.7, this should really be an extension of AutoCloseable instead, * to support the try-with-resources pattern. Typical use:

*
 *     
 *         // Create and set the ThreadContext ClassLoader
 *         ThreadContextClassLoaderHolder holder = null;
 *
 *         try {
 *
 *          holder = ThreadContextClassLoaderBuilder.createFor(getClass())
 *              .addPath("some/path")
 *              .addURL(someURL)
 *              .addPaths(aPathList)
 *              .buildAndSet();
 *
 *          // ... perform operations using the newly set ThreadContext ClassLoader...
 *
 *         } finally {
 *          // Restore the original ClassLoader
 *          holder.restoreClassLoaderAndReleaseThread();
 *         }
 *     
 * 
* * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public interface ThreadContextClassLoaderHolder { /** * Restores the original ThreadContext ClassLoader, and nullifies * any references to the Thread which had its ThreadContext * ClassLoader altered. */ void restoreClassLoaderAndReleaseThread(); /** * Retrieves the ClassPath held by this ThreadContextClassLoaderHolder as a * {@code File.pathSeparatorChar}-separated string. This is directly usable as a String argument by * any external process. * * @return the ClassPath as an argument to external processes such as XJC. */ String getClassPathAsArgument(); } locale/000077500000000000000000000000001351100213400345005ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environmentLocaleFacet.java000066400000000000000000000151241351100213400375100ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environment/localepackage org.codehaus.mojo.jaxb2.shared.environment.locale; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.environment.AbstractLogAwareFacet; import java.util.Locale; import java.util.StringTokenizer; /** * EnvironmentFacet implementation which alters the default Locale for the * remainder of the tool execution. * * @author Lennart Jörelid, jGuru Europe AB */ public class LocaleFacet extends AbstractLogAwareFacet { // Internal state private Locale originalLocale; private Locale newLocale; /** * Compound constructor creating a LocaleFacet wrapping the supplied instances. * * @param log The active Maven Log. * @param newLocale The non-null Locale to be set by this LocaleFacet during execution. */ @SuppressWarnings("WeakerAccess") public LocaleFacet(final Log log, final Locale newLocale) { super(log); // Check sanity Validate.notNull(newLocale, "usedLocale"); // Assign internal state this.originalLocale = Locale.getDefault(); this.newLocale = newLocale; } /** * {@inheritDoc} *

Changes the Locale during the execution of the plugin.

*/ @Override public void setup() { if (log.isInfoEnabled()) { log.info("Setting default locale to [" + newLocale + "]"); } try { Locale.setDefault(newLocale); } catch (Exception e) { log.error("Could not switch locale to [" + newLocale + "]. Continuing with standard locale.", e); } } /** * {@inheritDoc} *

Restores the original locale following the plugin's execution.

*/ @Override public void restore() { if (log.isInfoEnabled()) { log.info("Restoring default locale to [" + originalLocale + "]"); } try { Locale.setDefault(originalLocale); } catch (Exception e) { log.error("Could not restore locale to [" + originalLocale + "]. Continuing with [" + Locale.getDefault() + "]", e); } } /** * Helper method used to parse a locale configuration string into a Locale instance. * * @param localeString A configuration string parameter on the form * {@code <language>[,<country>[,<variant>]]} * @param log The active Maven Log. Cannot be null. * @return A fully constructed Locale. * @throws MojoExecutionException if the localeString was not supplied on the required form. */ public static LocaleFacet createFor(final String localeString, final Log log) throws MojoExecutionException { // Check sanity Validate.notNull(log, "log"); Validate.notEmpty(localeString, "localeString"); final StringTokenizer tok = new StringTokenizer(localeString, ",", false); final int numTokens = tok.countTokens(); if (numTokens > 3 || numTokens == 0) { throw new MojoExecutionException("A localeString must consist of up to 3 comma-separated parts on the " + "form [,[,]]. Received incorrect value '" + localeString + "'"); } // Extract the locale configuration data. final String language = tok.nextToken().trim(); final String country = numTokens > 1 ? tok.nextToken().trim() : null; final String variant = numTokens > 2 ? tok.nextToken().trim() : null; // All done. return new LocaleFacet(log, findOptimumLocale(language, country, variant)); } /** * Helper method to find the best matching locale, implying a workaround for problematic * case-sensitive Locale detection within the JDK. (C.f. Issue #112). * * @param language The given Language. * @param country The given Country. May be null or empty to indicate that the Locale returned should not * contain a Country definition. * @param variant The given Variant. May be null or empty to indicate that the Locale returned should not * contain a Variant definition. * @return The optimally matching Locale. */ @SuppressWarnings("All") public static Locale findOptimumLocale(final String language, final String country, final String variant) { final boolean hasCountry = country != null && !country.isEmpty(); final boolean hasVariant = variant != null && !variant.isEmpty(); final Locale[] availableLocales = Locale.getAvailableLocales(); for (int i = 0; i < availableLocales.length; i++) { final Locale current = availableLocales[i]; // Extract the language/country/variant of the current Locale. final String currentLanguage = current.getLanguage(); final String currentCountry = current.getCountry(); final String currentVariant = current.getVariant(); // Check if the current Locale matches the supplied final boolean isLanguageMatch = language.equalsIgnoreCase(currentLanguage); final boolean isCountryMatch = (hasCountry && country.equalsIgnoreCase(currentCountry)) || (!hasCountry && (currentCountry == null || currentCountry.isEmpty())); final boolean isVariantMatch = (hasVariant && variant.equalsIgnoreCase(currentVariant)) || (!hasVariant && (currentVariant == null || currentVariant.isEmpty())); if (isLanguageMatch && isCountryMatch && isVariantMatch) { return current; } } // Default to the default platform locale. return Locale.getDefault(); } } logging/000077500000000000000000000000001351100213400346675ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environmentLoggingHandlerEnvironmentFacet.java000066400000000000000000000136611351100213400436150ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environment/loggingpackage org.codehaus.mojo.jaxb2.shared.environment.logging; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.environment.AbstractLogAwareFacet; import java.util.ArrayList; import java.util.List; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; /** * EnvironmentFacet for replacing Handlers from Java Util Logging with a Maven Log. * This is required as an environment facet for capturing log statements from tools * that use the Java Util Logging system internally - such as the JDK SchemaGen tool. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.1 */ public class LoggingHandlerEnvironmentFacet extends AbstractLogAwareFacet { /** * Standard logger names/categories for the java.util.Logger. */ public static final String[] DEFAULT_LOGGER_NAMES = new String[]{"com.sun", "javax.xml", "javax.tools"}; // Internal state private boolean restored; private Logger rootLogger; private Level originalRootLoggerLevel; private List originalHandlers; private MavenLogHandler mavenLogHandler; private String logPrefix; private String encoding; private String[] loggerNamePrefixes; /** * Creates a new JavaLoggingEnvironment, using the supplied variables to set up a MavenLogHandler. * The MavenLogHandler is then assigned to the root logger. * * @param logPrefix The prefix to use for the logger, indicating which tool is used by the log. Example: "XJC" * or "SchemaGen". * @param mavenLog The active Maven Log. * @param encoding The configured encoding. * @param loggerNamePrefixes The prefixes of the Logger names to be permitted logging. */ public LoggingHandlerEnvironmentFacet(final String logPrefix, final Log mavenLog, final String encoding, final String[] loggerNamePrefixes) { super(mavenLog); // Check sanity Validate.notEmpty(encoding, "encoding"); Validate.notNull(loggerNamePrefixes, "loggerNamePrefixes"); // Assign internal state this.originalHandlers = new ArrayList(); this.logPrefix = logPrefix; rootLogger = Logger.getLogger(""); originalRootLoggerLevel = rootLogger.getLevel(); this.encoding = encoding; this.loggerNamePrefixes = loggerNamePrefixes; } /** * {@inheritDoc} *

Redirects JUL logging statements to the Maven Log.

*/ @Override public void setup() { // Redirect the JUL Logging statements to the Maven Log. rootLogger.setLevel(MavenLogHandler.getJavaUtilLoggingLevelFor(log)); this.mavenLogHandler = new MavenLogHandler(log, logPrefix, encoding, loggerNamePrefixes); for (Handler current : rootLogger.getHandlers()) { // Stash the original handlers from the RootLogger. originalHandlers.add(current); // Remove the original handler from the RootLogger. rootLogger.removeHandler(current); } // Add the new Maven Log handler. rootLogger.addHandler(this.mavenLogHandler); } /** * Restores the original root Logger state, including Level and Handlers. */ public void restore() { if (!restored) { // Remove the extra Handler from the RootLogger rootLogger.removeHandler(mavenLogHandler); // Restore the original state to the Root logger rootLogger.setLevel(originalRootLoggerLevel); for (Handler current : originalHandlers) { rootLogger.addHandler(current); } // All done. restored = true; } } /** * Factory method creating a new LoggingHandlerEnvironmentFacet wrapping the supplied properties. * * @param mavenLog The active Maven Log. * @param caller The AbstractJaxbMojo subclass which invoked this LoggingHandlerEnvironmentFacet factory method. * @param encoding The encoding used by the Maven Mojo subclass. * @return A fully set up LoggingHandlerEnvironmentFacet */ public static LoggingHandlerEnvironmentFacet create(final Log mavenLog, final Class caller, final String encoding) { // Check sanity Validate.notNull(mavenLog, "mavenLog"); Validate.notNull(caller, "caller"); Validate.notEmpty(encoding, "encoding"); // Find the standard log prefix for the tool in question. final String logPrefix = caller.getClass().getCanonicalName().toUpperCase().contains("XJC") ? "XJC" : "SchemaGen"; // All done. return new LoggingHandlerEnvironmentFacet(logPrefix, mavenLog, encoding, DEFAULT_LOGGER_NAMES); } } MavenLogHandler.java000066400000000000000000000134431351100213400405450ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environment/loggingpackage org.codehaus.mojo.jaxb2.shared.environment.logging; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.List; import java.util.logging.Filter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.SimpleFormatter; /** * Handler implementation which delegates its actual logging to an internal Maven log. * This is required to capture logging statements from tools that use the Java Util Logging * system internally - such as the JDK SchemaGen tool. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class MavenLogHandler extends Handler { // Internal state private Log log; private String prefix; /** * Creates a new MavenLogHandler which adapts a {@link Handler} to emit log messages onto a Maven Log. * * @param log The Maven Log to emit log messages to. * @param prefix An optional prefix used to prefix any log message. * @param encoding The encoding which should be used. * @param acceptedLogRecordPrefixes A non-null list of prefixes holding LogRecord logger names for * permitted/accepted LogRecords. */ public MavenLogHandler(final Log log, final String prefix, final String encoding, final String[] acceptedLogRecordPrefixes) { // Check sanity Validate.notNull(log, "log"); Validate.notNull(prefix, "prefix"); Validate.notEmpty(encoding, "encoding"); // Assign internal state this.log = log; this.prefix = prefix.isEmpty() ? "" : "[" + prefix + "]: "; setFormatter(new SimpleFormatter()); setLevel(getJavaUtilLoggingLevelFor(log)); try { setEncoding(encoding); } catch (UnsupportedEncodingException e) { log.error("Could not use encoding '" + encoding + "'", e); } if (acceptedLogRecordPrefixes != null && acceptedLogRecordPrefixes.length > 0) { setFilter(getLoggingFilter(acceptedLogRecordPrefixes)); } } /** * {@inheritDoc} */ @Override public void publish(final LogRecord record) { if (this.isLoggable(record)) { final Level level = record.getLevel(); final String message = prefix + getFormatter().format(record); if (Level.SEVERE.equals(level)) { log.error(message); } else if (Level.WARNING.equals(level)) { log.warn(message); } else if (Level.INFO.equals(level)) { log.info(message); } else { log.debug(message); } } } /** * {@inheritDoc} */ @Override public void flush() { // Do nothing. } /** * {@inheritDoc} */ @Override public void close() throws SecurityException { // Do nothing. } /** * Retrieves the JUL Level matching the supplied Maven Log. * * @param mavenLog A non-null Maven Log. * @return The Corresponding JUL Level. */ public static Level getJavaUtilLoggingLevelFor(final Log mavenLog) { // Check sanity Validate.notNull(mavenLog, "mavenLog"); Level toReturn = Level.SEVERE; if (mavenLog.isDebugEnabled()) { toReturn = Level.FINER; } else if (mavenLog.isInfoEnabled()) { toReturn = Level.INFO; } else if (mavenLog.isWarnEnabled()) { toReturn = Level.WARNING; } // All Done. return toReturn; } /** * Retrieves a java.util.Logging filter used to ensure that only LogRecords whose * logger names start with any of the required prefixes are logged. * * @param requiredPrefixes A non-null list of prefixes to be matched with the LogRecord logger names. * @return A java.util.logging Filter that only permits logging LogRecords whose * logger names start with any of the required prefixes. */ public static Filter getLoggingFilter(final String... requiredPrefixes) { // Check sanity Validate.notNull(requiredPrefixes, "requiredPrefixes"); // All done. return new Filter() { // Internal state private List requiredPrefs = Arrays.asList(requiredPrefixes); @Override public boolean isLoggable(final LogRecord record) { final String loggerName = record.getLoggerName(); for (String current : requiredPrefs) { if (loggerName.startsWith(current)) { return true; } } // No matches found. return false; } }; } } sysprops/000077500000000000000000000000001351100213400351435ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environmentSystemPropertyChangeEnvironmentFacet.java000066400000000000000000000212571351100213400453440ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environment/syspropspackage org.codehaus.mojo.jaxb2.shared.environment.sysprops; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.environment.AbstractLogAwareFacet; import java.util.ArrayList; import java.util.List; /** * EnvironmentFacet which changes the value of a system property for the duration * of executing a tool. This is required for tools (such as the JDK SchemaGen) which * relies on environment or system properties being set for their execution. * This faced accepts one key and two values (original/new values). * * @author Lennart Jörelid, jGuru Europe AB * @since 2.1 */ public final class SystemPropertyChangeEnvironmentFacet extends AbstractLogAwareFacet { /** * Operation definitions indicating how a System property should be changed by this EnvironmentFacet. */ public enum ChangeType { /** * Indicates that a System property should be added during {@code setup()} * and removed during {@code restore()}. If the property was already present, * this behaves like {@code #CHANGE}. */ ADD, /** * Indicates that a System property should be removed during {@code setup()} * and restored/re-added during {@code restore()} */ REMOVE, /** * Indicates that a System property should be altered during {@code setup()} * and restored during {@code restore()} */ CHANGE } // Internal state private ChangeType type; private String key; private String newValue; private String originalValue; /** * Creates a SystemPropertyChange which will remove the supplied system property for the * duration of this SystemPropertyChange. No exception will be thrown if the supplied System property * key is not found in the present System.properties. * * @param log The active Maven Log. * @param key A non-null key. * @see SystemPropertyChangeEnvironmentFacet.ChangeType#REMOVE */ private SystemPropertyChangeEnvironmentFacet(final Log log, final String key) { // Delegate super(log); // Assign internal state this.key = key; this.type = ChangeType.REMOVE; } /** * Creates a SystemPropertyChange which stores the current * * @param log The active Maven Log. * @param key The key of the System property managed by this SystemPropertyChange. * @param newValue The new value of this SystemPropertyChange. */ private SystemPropertyChangeEnvironmentFacet(final Log log, final String key, final String newValue) { // Delegate super(log); // Assign internal state this.key = key; this.originalValue = System.getProperty(key); this.newValue = newValue; this.type = existsAsSystemProperty(key) ? ChangeType.CHANGE : ChangeType.ADD; } /** * {@inheritDoc} */ @Override public void setup() { if (type == ChangeType.REMOVE) { System.clearProperty(key); } else { System.setProperty(key, newValue); } if (log.isDebugEnabled()) { log.debug("Setup " + toString()); } } /** * {@inheritDoc} */ @Override public void restore() { if (type == ChangeType.ADD) { System.clearProperty(key); } else { System.setProperty(key, originalValue); } if (log.isDebugEnabled()) { log.debug("Restored " + toString()); } } /** * @return A Debug string representation of this SystemPropertyChangeEnvironmentFacet. */ @Override public String toString() { final String toReturn = "SysProp key [" + key + "]\n" + " ... Original value: [" + originalValue + "]\n" + " ... Changed value : [" + newValue + "]"; return toReturn.replace("\n", AbstractJaxbMojo.NEWLINE); } /** * Creates a SystemPropertyChangesBuilder which uses the supplied active Maven Log. * * @param mavenLog The active Maven Log to be used by all SystemPropertyChange objects created * by this SystemPropertyChangesBuilder. * @return A SystemPropertyChangesBuilder ready for use. */ public static SystemPropertyChangesBuilder getBuilder(final Log mavenLog) { return new SystemPropertyChangesBuilder(mavenLog); } /** * Builder class intended to simplify creating SystemPropertyChange EnvironmentFacets. */ public static class SystemPropertyChangesBuilder { // Internal state private List toReturn; private Log mavenLog; private SystemPropertyChangesBuilder(final Log mavenLog) { // Check sanity Validate.notNull(mavenLog, "mavenLog"); // Assign internal state this.toReturn = new ArrayList(); this.mavenLog = mavenLog; } /** * Adds a SystemPropertyChange which removes the named System property. * * @param propertyName The name of the system property for which to create a REMOVE-type SystemPropertyChange. * @return This builder, for chaining. * @see SystemPropertyChangeEnvironmentFacet.ChangeType#REMOVE */ public SystemPropertyChangesBuilder remove(final String propertyName) { // Check sanity checkSanity(propertyName); // Add the SystemPropertyChange. toReturn.add(new SystemPropertyChangeEnvironmentFacet(mavenLog, propertyName)); // All done. return this; } /** * Adds a SystemPropertyChange which adds or changes the named System property. * * @param propertyName The name of the system property for which to create an * ADD- or CREATE-type SystemPropertyChange. * @param value The new value of the system property to set. * @return This builder, for chaining. * @see SystemPropertyChangeEnvironmentFacet.ChangeType#ADD * @see SystemPropertyChangeEnvironmentFacet.ChangeType#CHANGE */ public SystemPropertyChangesBuilder addOrChange(final String propertyName, final String value) { // Check sanity checkSanity(propertyName); // Add the SystemPropertyChange. toReturn.add(new SystemPropertyChangeEnvironmentFacet(mavenLog, propertyName, value)); // All done. return this; } /** * @return A List of SystemPropertyChange EnvironmentFacets which can be included as required into the * ToolExecutionEnvironment. */ public List build() { return toReturn; } // // Private helpers // private void checkSanity(final String propertyName) { // Check sanity Validate.notEmpty(propertyName, "propertyName"); // Validate that the property name is not already present as a SystemPropertyChange. for (SystemPropertyChangeEnvironmentFacet current : toReturn) { if (current.key.equals(propertyName)) { throw new IllegalArgumentException("A SystemPropertyChange for propertyName '" + propertyName + "' is already present. Only one SystemPropertyChange per propertyName " + "should be supplied."); } } } } // // Private helpers // private boolean existsAsSystemProperty(final String key) { return System.getProperties().keySet().contains(key); } } SystemPropertySaveEnvironmentFacet.java000066400000000000000000000040421351100213400450460ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/environment/syspropspackage org.codehaus.mojo.jaxb2.shared.environment.sysprops; import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.environment.AbstractLogAwareFacet; /** * EnvironmentFacet which saves the value of a system property for the duration * of executing a tool. This may be required for tools (such as the XJC tool) which * may overwrite property values for its own purpose. * * Unlike {@link SystemPropertyChangeEnvironmentFacet}, this does not a set a new * property value itself, just saves the old value and later restores or clears it. * * This facet accepts the key of the property to save. * * @author Svein Elgstøen * @since 2.5 */ public final class SystemPropertySaveEnvironmentFacet extends AbstractLogAwareFacet { private final String key; private final String originalValue; /** * Creates a SystemPropertySave which will remember the original value of the * supplied system property for the duration of this SystemPropertySave. * * @param key A non-null key. * @param log The active Maven Log. */ public SystemPropertySaveEnvironmentFacet(final String key, final Log log) { // Delegate super(log); // Assign internal state this.key = key; this.originalValue = System.getProperty(key); } /** * {@inheritDoc} */ @Override public void restore() { if (originalValue != null) { System.setProperty(key, originalValue); } else { System.clearProperty(key); } if (log.isDebugEnabled()) { log.debug("Restored " + toString()); } } /** * {@inheritDoc} */ @Override public void setup() { // Do nothing, value is saved in constructor if (log.isDebugEnabled()) { log.debug("Setup " + toString()); } } @Override public String toString() { return "SysProp key [" + key + "], saved value: [" + originalValue + "]"; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filters/000077500000000000000000000000001351100213400324245ustar00rootroot00000000000000AbstractFilter.java000066400000000000000000000165131351100213400361270ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filterspackage org.codehaus.mojo.jaxb2.shared.filters; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.Validate; import java.util.ArrayList; import java.util.List; /** * Abstract Filter implementation which handles separating {@code null} candidate values from non-null * ones, and delegates processing to concrete subclass implementations. Also, this AbstractFilter * implementation provides a standard for emitting Filter debug statements (i.e. for toString() calls). * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public abstract class AbstractFilter implements Filter { /** * Initial-line indent for human-readable toString() rendering. */ protected static final String TOSTRING_INDENT = "| "; class DelayedLogMessage { String message; String logLevel; public DelayedLogMessage(final String logLevel, final String message) { this.logLevel = logLevel; this.message = message; } } // Internal state protected Log log; private List delayedLogMessages; private boolean processNullValues; /** * Convenience constructor which creates an AbstractFilter which does not process null values. */ protected AbstractFilter() { // Assign internal state delayedLogMessages = new ArrayList(); setProcessNullValues(false); } /** * Validator method which should be called in a DI setter method to ensure that this AbstractFilter has * not yet been initialized. * * @param setterPropertyName The name of the property to inject. */ protected final void validateDiSetterCalledBeforeInitialization(final String setterPropertyName) { Validate.isTrue(log == null, "DI Setters should only be called before initializing. Stray call: [" + setterPropertyName + "]"); } /** * Adds a log message to be emitted when this AbstractFilter is initialized (and the Log is made available to it). * * @param logLevel The logLevel of the message to emit. * @param message The message to emit. */ protected final void addDelayedLogMessage(final String logLevel, final String message) { this.delayedLogMessages.add(new DelayedLogMessage(logLevel, message)); } /** * Assigns the {@code processNullValues} property which indicates if this AbstractFilter * should process null values or not. * * @param processNullValues {@code true} to indicate that this AbstractFilter should process null values. */ protected final void setProcessNullValues(final boolean processNullValues) { validateDiSetterCalledBeforeInitialization("processNullValues"); this.processNullValues = processNullValues; } /** * {@inheritDoc} */ @Override public final void initialize(final Log log) { // Check sanity Validate.notNull(log, "log"); // Assign internal state this.log = log; if (delayedLogMessages.size() > 0) { for (DelayedLogMessage current : delayedLogMessages) { if (current.logLevel.equalsIgnoreCase("warn") && log.isWarnEnabled()) { log.warn(current.message); } else if (current.logLevel.equals("info") && log.isInfoEnabled()) { log.info(current.message); } else if (log.isDebugEnabled()) { log.debug(current.message); } } delayedLogMessages.clear(); } // Delegate onInitialize(); } /** * {@inheritDoc} */ @Override public boolean isInitialized() { return log != null; } /** * Override this method to perform some custom action after standard initialization is complete. * Default implementation does nothing, but the log is non-null and ready for use. */ protected void onInitialize() { // Do nothing } /** * {@inheritDoc} */ @Override public final boolean accept(final T candidate) throws IllegalStateException { // Check sanity if (log == null) { throw new IllegalStateException("Filter [" + getClass().getSimpleName() + "] not initialized before use."); } // Should we process null values? if (candidate == null) { boolean toReturn = false; if (processNullValues) { toReturn = onNullCandidate(); } else { if (log.isDebugEnabled()) { log.debug("Received null candidate, and Filter [" + getClass().getSimpleName() + "] is configured not to match nulls."); } } // All done. return toReturn; } // Delegate processing. return onCandidate(candidate); } /** * Override this to perform an action other than debug logging whenever this AbstractFilter * receives a null candidate. You also need to override this implementation if you want to return a value other * than {@code false}. There is no point in calling {@code super.onNullCandidate()} whenever this method is * overridden. * * @return {@code false} - implying that AbstractFilters will not matchAtLeastOnce {@code null}s by default. */ protected boolean onNullCandidate() { if (log.isDebugEnabled()) { log.debug("Filter [" + getClass().getSimpleName() + "] is configured to matchAtLeastOnce processing null candidate " + "values, but no implementation is supplied."); } // Don't matchAtLeastOnce null values by default. return false; } /** *

Method that is invoked to determine if a candidate instance should be accepted or not.

* * @param nonNullCandidate The candidate that should be tested for acceptance by this Filter. Never null. * @return {@code true} if the candidate is accepted by this Filter and {@code false} otherwise. */ protected abstract boolean onCandidate(final T nonNullCandidate); /** * {@inheritDoc} */ @Override public String toString() { return "Filter [" + getClass().getSimpleName() + "]" + AbstractJaxbMojo.NEWLINE + TOSTRING_INDENT + "Processes nulls: [" + processNullValues + "]" + AbstractJaxbMojo.NEWLINE; } } Filter.java000066400000000000000000000042601351100213400344370ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filterspackage org.codehaus.mojo.jaxb2.shared.filters; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; /** * Generic Filter specification, whose implementations define if candidate objects should be accepted or not. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public interface Filter { /** * Initializes this Filter, and assigns the supplied Log for use by this Filter. * * @param log The non-null Log which should be used by this Filter to emit log messages. */ void initialize(Log log); /** * @return {@code true} if this Filter has been properly initialized (by a call to the {@code initialize} method). */ boolean isInitialized(); /** *

Method that is invoked to determine if a candidate instance should be accepted or not. * Implementing classes should be prepared to handle {@code null} candidate objects.

* * @param candidate The candidate that should be tested for acceptance by this Filter. * @return {@code true} if the candidate is accepted by this Filter and {@code false} otherwise. * @throws java.lang.IllegalStateException if this Filter is not initialized by a call to the * initialize method before calling this matchAtLeastOnce method. */ boolean accept(T candidate) throws IllegalStateException; } Filters.java000066400000000000000000000154021351100213400346220ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filterspackage org.codehaus.mojo.jaxb2.shared.filters; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.List; /** *

Algorithm definitions for common operations using Filters.

*

SPI Note:This class/these methods should be replaced * with stream operations when JDK8 is required to build/run this plugin.

* * @author Lennart Jörelid, jGuru Europe AB * @see org.codehaus.mojo.jaxb2.shared.filters.Filter * @since 2.0 */ @SuppressWarnings("all") public final class Filters { /** * Algorithms for accepting the supplied object if at least one of the supplied Filters accepts it. * * @param object The object to accept (or not). * @param filters The non-null list of Filters to examine the supplied object. * @param The Filter type. * @return {@code true} if at least one of the filters return true from its accept method. * @see Filter#accept(Object) */ public static boolean matchAtLeastOnce(final T object, final List> filters) { // Check sanity Validate.notNull(filters, "filters"); boolean acceptedByAtLeastOneFilter = false; for (Filter current : filters) { if (current.accept(object)) { acceptedByAtLeastOneFilter = true; break; } } // All done. return acceptedByAtLeastOneFilter; } /** * Algorithms for rejecting the supplied object if at least one of the supplied Filters does not accept it. * * @param object The object to reject (or not). * @param filters The non-null list of Filters to examine the supplied object. * @param The Filter type. * @return {@code true} if at least one of the filters returns false from its accept method. * @see Filter#accept(Object) */ public static boolean rejectAtLeastOnce(final T object, final List> filters) { // Check sanity Validate.notNull(filters, "filters"); boolean rejectedByAtLeastOneFilter = false; for (Filter current : filters) { if (!current.accept(object)) { rejectedByAtLeastOneFilter = true; break; } } // All done. return rejectedByAtLeastOneFilter; } /** * Algorithms for rejecting the supplied object if at least one of the supplied Filters rejects it. * * @param object The object to accept (or not). * @param filters The non-null list of Filters to examine the supplied object. * @param The Filter type. * @return {@code true} if at least one of the filters return false from its accept method. * @see Filter#accept(Object) */ public static boolean noFilterMatches(final T object, final List> filters) { // Check sanity Validate.notNull(filters, "filters"); boolean matchedAtLeastOnce = false; for (Filter current : filters) { if (current.accept(object)) { matchedAtLeastOnce = true; } } // All done. return !matchedAtLeastOnce; } /** * Adapts the Filter specification to the FileFilter interface, to enable immediate use * for filtering File lists. * * @param toAdapt The non-null Filter which should be adapted to a FileFilter interface. * @return If the {@code toAdapt} instance already implements the FileFilter interface, simply return the toAdapt * instance. Otherwise, returns a FileFilter interface which delegates its execution to the wrapped Filter. */ public static FileFilter adapt(final Filter toAdapt) { // Check sanity Validate.notNull(toAdapt, "toAdapt"); // Already a FileFilter? if (toAdapt instanceof FileFilter) { return (FileFilter) toAdapt; } // Wrap and return. return new FileFilter() { @Override public boolean accept(final File candidate) { return toAdapt.accept(candidate); } }; } /** * Adapts the supplied List of Filter specifications to a List of FileFilters. * * @param toAdapt The List of Filters to adapts. * @return A List holding FileFilter instances. If {@code toAdapt} is {@code null} or empty, an empty list is * returned from this method. Thus, this method will never return a {@code null} value. */ public static List adapt(final List> toAdapt) { final List toReturn = new ArrayList(); if (toAdapt != null) { for (Filter current : toAdapt) { toReturn.add(adapt(current)); } } // All done. return toReturn; } /** * Initializes the supplied Filters by assigning the given Log. * * @param log The active Maven Log. * @param filters The List of Filters to initialize. * @param The Filter type. */ public static void initialize(final Log log, final List> filters) { // Check sanity Validate.notNull(log, "log"); Validate.notNull(filters, "filters"); for (Filter current : filters) { current.initialize(log); } } /** * Initializes the supplied Filters by assigning the given Log. * * @param log The active Maven Log. * @param filters The List of Filters to initialize. * @param The Filter type. */ public static void initialize(final Log log, final Filter... filters) { // Check sanity Validate.notNull(log, "log"); if (filters != null) { for (Filter current : filters) { current.initialize(log); } } } } pattern/000077500000000000000000000000001351100213400340225ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filtersAbstractPatternFilter.java000066400000000000000000000275721351100213400411510ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; /** *

AbstractFilter implementation containing a Java Pattern which should be used to determine if candidate T objects * match any of the supplied regularExpressions. Since Java regexp Patterns only match strings, a pluggable * StringConverter is used to convert T-type objects to strings for the actual matching.

*

The structure of setter methods is provided to enable simpler configuration using the default Maven/Plexus * dependency injection mechanism. The internal state of each AbstractPatternFilter is not intended to be changed * after its creation.

* * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public abstract class AbstractPatternFilter extends AbstractFilter { // Internal state private boolean acceptCandidateOnPatternMatch; private StringConverter converter; private List regularExpressions; private String patternPrefix; private List patterns; /** * DI-friendly constructor. */ public AbstractPatternFilter() { // Delegate super(); // Assign internal state converter = new ToStringConverter(); acceptCandidateOnPatternMatch = true; } /** * Assigns a prefix to be prepended to any patterns submitted to this AbstractPatternFilter. * * @param patternPrefix A prefix to be prepended to each pattern to render a Pattern. * If a null argument is supplied, nothing will be prepended. * @see #convert(java.util.List, String) */ public final void setPatternPrefix(final String patternPrefix) { // Check sanity validateDiSetterCalledBeforeInitialization("patternPrefix"); // Check sanity if (patternPrefix != null) { // Assign internal state this.patternPrefix = patternPrefix; } else { addDelayedLogMessage("warn", "Received null patternPrefix for configuring AbstractPatternFilter of type [" + getClass().getName() + "]. Ignoring and proceeding."); } } /** * Injects a List of patterns complying with the Java Regexp {@link Pattern} specification. * Each injected pattern will be compiled to a {@link Pattern} by concatenating the {@link #patternPrefix} string, * given at construction time, to obtain the full regexp pattern. The resulting Patterns are matched for * candidates normally in the {@link #onCandidate(Object)} method. * * @param patterns The List of PatternStrings to compile. * @see #convert(java.util.List, String) * @see #setPatternPrefix(String) */ public void setPatterns(final List patterns) { // Check sanity validateDiSetterCalledBeforeInitialization("patternPrefix"); // Check sanity if (patterns != null) { // Assign internal state this.patterns = new ArrayList(); this.patterns.addAll(patterns); } else { addDelayedLogMessage("warn", "Received null patterns for configuring AbstractPatternFilter of type [" + getClass().getName() + "]. Ignoring and proceeding."); } } /** * Assigns the {@code acceptCandidateOnPatternMatch} parameter which defines the function of this * AbstractPatternFilter's accept method. * * @param acceptCandidateOnPatternMatch if {@code true}, this AbstractPatternFilter will matchAtLeastOnce * candidate objects that match at least one of the supplied * regularExpressions. if {@code false}, this AbstractPatternFilter will * noFilterMatches candidates that match at least one of the supplied * regularExpressions. */ public final void setAcceptCandidateOnPatternMatch(final boolean acceptCandidateOnPatternMatch) { // Check sanity validateDiSetterCalledBeforeInitialization("acceptCandidateOnPatternMatch"); // Assign internal state this.acceptCandidateOnPatternMatch = acceptCandidateOnPatternMatch; } /** * Assigns the StringConverter used to convert T-type objects to Strings. * This StringConverter is used to acquire input comparison values for all Patterns to T-object candidates. * * @param converter The StringConverter used to convert T-type objects to Strings which should * be matched by all supplied Patterns to T-object candidates. */ public void setConverter(final StringConverter converter) { // Check sanity Validate.notNull(converter, "converter"); validateDiSetterCalledBeforeInitialization("converter"); // Assign internal state this.converter = converter; } /** * Compiles the List of Patterns used by this AbstractPatternFilter to match candidates. * If no patterns are supplied (by configuration or constructor call), no regularExpressions Pattern List will be * created for use by this AbstractPatternFilter. Instead, some logging is emitted onto the console. * * @see #patterns */ @Override protected void onInitialize() { if (patterns == null && log.isWarnEnabled()) { // Log somewhat log.warn("No Patterns configured for AbstractPatternFilter [" + getClass().getName() + "]. " + "This could imply a configuration problem."); } else { // Complete internal state regularExpressions = convert(patterns, patternPrefix); } } /** *

Each nonNullCandidate is matched against all Patterns supplied to this AbstractPatternFilter. * The match table of this AbstractPatternFilter on each candidate is as follows:

* * * * * * * * * * * * * * * * * * * * * * * * * * * *
Truth table for the onCandidate method
at least 1 filter matchesacceptCandidateOnPatternMatchresult
truetruetrue
falsetruefalse
truefalsefalse
falsefalsetrue
* {@inheritDoc} */ @Override protected boolean onCandidate(final T nonNullCandidate) { final String candidateString = convert(nonNullCandidate); boolean atLeastOnePatternMatched = false; if (regularExpressions != null) { for (Pattern current : regularExpressions) { if (current.matcher(candidateString).matches()) { if (log.isDebugEnabled()) { log.debug("CandidateString [" + candidateString + "] matched pattern [" + current.pattern() + "]"); } // Adjust and return atLeastOnePatternMatched = true; break; } } } // Apply the reverse match logic if applicable return acceptCandidateOnPatternMatch ? atLeastOnePatternMatched : !atLeastOnePatternMatched; } /** *

Method implementation which converts a non-null T object to a String * to be matched by the Java Regexp Pattern contained within this AbstractPatternFilter implementation. * Override for a non-standard conversion.

* * @param nonNullT A non-null T object. * @return A string to be converted. */ protected String convert(final T nonNullT) { return converter.convert(nonNullT); } /** * Collects a List containing {@code java.text.Pattern} objects by concatenating * {@code prepend + current_pattern_string} and Pattern-compiling the result. * * @param patternStrings The List of PatternStrings to compile. * @param prepend A string to prepend each pattern. If a null argument is supplied, nothing * will be prepended. * @return a List containing {@code java.text.Pattern} objects by concatenating * {@code prepend + current_pattern_string} and Pattern-compiling the result. */ public static List convert(final List patternStrings, final String prepend) { // Check sanity List effectivePatternStrings = patternStrings; if (patternStrings == null) { effectivePatternStrings = new ArrayList(); effectivePatternStrings.add(".*"); } final String effectivePrepend = prepend == null ? "" : prepend; // Convert final List toReturn = new ArrayList(); for (String current : effectivePatternStrings) { toReturn.add(Pattern.compile(effectivePrepend + current, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE)); } // All done. return toReturn; } /** * {@inheritDoc} */ @Override public String toString() { final StringBuilder builder = new StringBuilder(super.toString()); builder.append(TOSTRING_INDENT + "Accept on match: [").append(acceptCandidateOnPatternMatch).append("]\n"); builder.append(TOSTRING_INDENT + "Initialized : [").append(isInitialized()).append("]\n"); final List effectivePatterns = isInitialized() ? regularExpressions : convert(patterns, patternPrefix); final int numPatterns = effectivePatterns != null && effectivePatterns.size() > 0 ? effectivePatterns.size() : 0; builder.append(TOSTRING_INDENT).append(numPatterns).append(" regularExpressions "); if (numPatterns > 0) { builder.append(":\n"); for (int i = 0; i < effectivePatterns.size(); i++) { final String prefix = TOSTRING_INDENT + " [" + (i + 1) + "/" + effectivePatterns.size() + "]: "; builder.append(prefix).append(effectivePatterns.get(i).pattern()).append("\n"); } } else { builder.append("\n"); } // All done. return builder.toString().substring(0, builder.length() - 1).replace("\n", AbstractJaxbMojo.NEWLINE); } } FileFilterAdapter.java000066400000000000000000000047021351100213400402160ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.filters.AbstractFilter; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import java.io.File; import java.io.FileFilter; /** * Filter implementation adapting a FileFilter instance to the Filter interface. * Delegates the {@link #onCandidate(File)} call to the supplied {@link FileFilter} delegate. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.3 */ public class FileFilterAdapter extends AbstractFilter implements Filter, FileFilter { // Internal state private FileFilter delegate; /** * Compound constructor, creating a FileFilterAdapter using the supplied {@link FileFilter} to determine if * candidate Files should be accepted. * * @param delegate The delegate FileFilter. */ public FileFilterAdapter(final FileFilter delegate) { setDelegate(delegate); } /** * {@inheritDoc} */ @Override public boolean isInitialized() { return super.isInitialized() && delegate != null; } /** * Assigns the supplied FileFilter delegate. * * @param delegate A non-null FileFilter instance. */ public void setDelegate(final FileFilter delegate) { // Check sanity Validate.notNull(delegate, "delegate"); // Assign internal state this.delegate = delegate; } /** * {@inheritDoc} */ @Override protected boolean onCandidate(final File nonNullCandidate) { return delegate.accept(nonNullCandidate); } } PatternFileFilter.java000066400000000000000000000225661351100213400402630ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; /** *

AbstractPatternFilter and FileFilter combination, using a set of Regular expressions * to accept the canonical absolute paths to Files.

* * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class PatternFileFilter extends AbstractPatternFilter implements FileFilter { /** * Java RegExp pattern matching one or more letters/digits/punctuation characters. * It can be flexibly used to separate normative text in a pattern: *
    *
  1. Pattern matching ends of strings. PATTERN_LETTER_DIGIT_PUNCT + "txt" * matches all file paths ending in "txt", such as "some/foobar.txt"
  2. *
  3. Pattern matching strings containing patterns. PATTERN_LETTER_DIGIT_PUNCT + * "foobar" + PATTERN_LETTER_DIGIT_PUNCT matches all file paths containing "foobar" such as * "the/file/in/directory/foobar/blah.java"
  4. *
  5. Pattern matching start of strings. "/some/prefix" * + PATTERN_LETTER_DIGIT_PUNCT matches all file paths starting in "/some/prefix", such as * "some/prefix/another/specification.xsd"
  6. *
*/ public static final String PATTERN_LETTER_DIGIT_PUNCT = "(\\p{javaLetterOrDigit}|\\p{Punct})+"; /** * Converter returning the canonical and absolute path for a File. */ public static final StringConverter FILE_PATH_CONVERTER = new StringConverter() { @Override public String convert(final File toConvert) { return FileSystemUtilities.getCanonicalPath(toConvert.getAbsoluteFile()); } }; /** * Compound constructor creating an PatternFileFilter from the supplied parameters. * * @param processNullValues if {@code true}, this PatternFileFilter process null candidate values. * @param patternPrefix a prefix to be prepended to any patterns submitted to * this PatternFileFilter * @param patterns The non-null list of Patters which should be applied within this * PatternFileFilter. * @param converter The StringConverter which converts Files to Strings for Pattern matching. * @param acceptCandidateOnPatternMatch if {@code true}, this PatternFileFilter will matchAtLeastOnce * candidate objects that match at least one of the supplied patterns. * if {@code false}, this PatternFileFilter will noFilterMatches * candidates that match at least one of the supplied patterns. */ public PatternFileFilter(final boolean processNullValues, final String patternPrefix, final List patterns, final StringConverter converter, final boolean acceptCandidateOnPatternMatch) { super(); // Assign internal state setProcessNullValues(processNullValues); setAcceptCandidateOnPatternMatch(acceptCandidateOnPatternMatch); setPatternPrefix(patternPrefix); setPatterns(patterns); setConverter(converter); } /** * Creates a new PatternFileFilter using the supplied patternStrings which are interpreted as file suffixes. * (I.e. prepended with {@code PATTERN_LETTER_DIGIT_PUNCT} and compiled to Patterns). * The {@code FILE_PATH_CONVERTER} is used to convert Files to strings. * The supplied {@code acceptCandidateOnPatternMatch} parameter indicates if this * PatternFileFilter accepts or rejects candidates that match any of the supplied patternStrings. * * @param patternStrings The list of patternStrings to be used as file path suffixes. * @param acceptCandidateOnPatternMatch if {@code true}, this PatternFileFilter will matchAtLeastOnce * candidate objects that match at least one of the supplied patterns. * if {@code false}, this PatternFileFilter will noFilterMatches * candidates that match at least one of the supplied patterns. * @see #FILE_PATH_CONVERTER * @see #PATTERN_LETTER_DIGIT_PUNCT * @see #convert(java.util.List, String) */ public PatternFileFilter(final List patternStrings, final boolean acceptCandidateOnPatternMatch) { this(false, PATTERN_LETTER_DIGIT_PUNCT, patternStrings, FILE_PATH_CONVERTER, acceptCandidateOnPatternMatch); } /** * Creates a new PatternFileFilter using the supplied patternStrings which are interpreted as file suffixes. * (I.e. prepended with {@code PATTERN_LETTER_DIGIT_PUNCT} and compiled to Patterns). * The {@code FILE_PATH_CONVERTER} is used to convert Files to strings. * The retrieved PatternFileFilter accepts candidates that match any of the supplied patternStrings. * * @param patterns The list of patternStrings to be used as file path suffixes. */ public PatternFileFilter(final List patterns) { this(false, PATTERN_LETTER_DIGIT_PUNCT, patterns, FILE_PATH_CONVERTER, true); } /** *

Creates a new PatternFileFilter with no patternStrings List, implying that calling this constructor must be * followed by a call to the {@code #setPatterns} method.

*

The default prefix is {@code PATTERN_LETTER_DIGIT_PUNCT}, the default StringConverter is * {@code FILE_PATH_CONVERTER} and this PatternFileFilter does by default accept candidates that match any of * the supplied PatternStrings (i.e. an include-mode filter)

*/ public PatternFileFilter() { this(false, PATTERN_LETTER_DIGIT_PUNCT, new ArrayList(), FILE_PATH_CONVERTER, true); } /** * Creates a new List containing an exclude-mode PatternFileFilter using the supplied patternStrings which * are interpreted as file suffixes. (I.e. prepended with {@code PATTERN_LETTER_DIGIT_PUNCT} and compiled to * Patterns). The {@code FILE_PATH_CONVERTER} is used to convert Files to strings. * * @param patterns A List of suffix patterns to be used in creating a new ExclusionRegularExpressionFileFilter. * @param log The active Maven Log. * @return A List containing a PatternFileFilter using the supplied suffix patterns to match Files. * @see PatternFileFilter */ public static List> createExcludeFilterList(final Log log, final String... patterns) { return createFilterList(log, false, patterns); } /** * Creates a new List containing an include-mode PatternFileFilter using the supplied patternStrings which * are interpreted as file suffixes. (I.e. prepended with {@code PATTERN_LETTER_DIGIT_PUNCT} and compiled to * Patterns). The {@code FILE_PATH_CONVERTER} is used to convert Files to strings. * * @param patterns A List of suffix patterns to be used in creating a new ExclusionRegularExpressionFileFilter. * @param log The active Maven Log. * @return A List containing a PatternFileFilter using the supplied suffix patterns to match Files. * @see PatternFileFilter */ public static List> createIncludeFilterList(final Log log, final String... patterns) { return createFilterList(log, true, patterns); } // // Private helpers // private static List> createFilterList(final Log log, final boolean includeOperation, final String... patterns) { // Check sanity Validate.notNull(patterns, "patterns"); Validate.notNull(log, "log"); // Convert and return. final List> toReturn = new ArrayList>(); final List patternStrings = Arrays.asList(patterns); toReturn.add(new PatternFileFilter(patternStrings, includeOperation)); // Initialize the filters. Filters.initialize(log, toReturn); return toReturn; } } PatternURLFilter.java000066400000000000000000000112151351100213400400330ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.net.URL; import java.util.List; /** * AbstractPatternFilter matching the string of URLs with to a set of Regular expressions. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class PatternURLFilter extends AbstractPatternFilter { /** * Converter returning each URL's {@code toString()} form, after normalizing it, using the * algorithm {@code toConvert.toURI().normalize().toURL().toString();} */ @SuppressWarnings("all") public static final StringConverter NORMALIZED_URL_CONVERTER = new StringConverter() { /** * {@inheritDoc} */ @Override public String convert(final URL toConvert) { try { return toConvert.toURI().normalize().toURL().toString(); } catch (Exception e) { // This should really not happen. throw new IllegalArgumentException("Could not handle URL [" + toConvert + "]", e); } } }; /** * Creates a new ExclusionRegularExpressionURLFilter using the supplied patternStrings which are * matched against each full - normalized - URL. The {@code NORMALIZED_URL_CONVERTER} is used to convert * URLs to strings. * * @param patternStrings The list of patternStrings to be used as regular expression matchers against the * normalized URLs. * @see #NORMALIZED_URL_CONVERTER * @see #convert(java.util.List, String) */ public PatternURLFilter(final List patternStrings) { this(false, "", patternStrings, NORMALIZED_URL_CONVERTER, true); } /** * Compound constructor creating an ExclusionRegularExpressionURLFilter from the supplied parameters. * * @param processNullValues if {@code true}, this ExclusionRegularExpressionURLFilter process null * candidate values. * @param patternPrefix a prefix to be prepended to any patterns submitted to * this PatternURLFilter. * @param patterns The non-null list of Patters which should be applied within this * ExclusionRegularExpressionURLFilter. A candidate of type T should only * be accepted by this ExclusionRegularExpressionURLFilter if all supplied * patterns matchAtLeastOnce the candidate. * @param converter The StringConverter used to convert T-type objects to Strings which should * be matched by all supplied Patterns to T-object candidates. * @param acceptCandidateOnPatternMatch if {@code true}, this ExclusionRegularExpressionURLFilter will matchAtLeastOnce * candidate objects that match at least one of the supplied patterns. if * {@code false}, this ExclusionRegularExpressionURLFilter will noFilterMatches * candidates that match at least one of the supplied patterns. */ public PatternURLFilter(final boolean processNullValues, final String patternPrefix, final List patterns, final StringConverter converter, final boolean acceptCandidateOnPatternMatch) { super(); // Assign internal state setProcessNullValues(processNullValues); setAcceptCandidateOnPatternMatch(acceptCandidateOnPatternMatch); setPatternPrefix(patternPrefix); setPatterns(patterns); setConverter(converter); } } StringConverter.java000066400000000000000000000024531351100213400400270ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Specification for a converter rendering a T object as a String. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public interface StringConverter { /** * Converts the supplied T object to a String. * * @param toConvert The T object to convert to a string. Not {@code null}. * @return The string form of the toConvert object. */ String convert(T toConvert); } ToStringConverter.java000066400000000000000000000023731351100213400403330ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Trivial converter using the {@code toString()} method to convert a T object to a String. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class ToStringConverter implements StringConverter { /** * {@inheritDoc} */ @Override public String convert(final T toConvert) { return toConvert.toString(); } } package-info.java000066400000000000000000000007551351100213400340730ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/** *

The jaxb2-maven-plugin wraps and adapts the JAXB reference implementation * to be useful within the Maven build process.

*

The shared package (including subpackages) contains utility classes used by both the java- and * xsd-generation Mojos.

* * @author Lennart Jörelid * @see The JAXB Reference Implementation */ package org.codehaus.mojo.jaxb2.shared;jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/version/000077500000000000000000000000001351100213400324415ustar00rootroot00000000000000DependencyInfo.java000066400000000000000000000104631351100213400361230ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/versionpackage org.codehaus.mojo.jaxb2.shared.version; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.shared.Validate; /** * Trivial holder class for dependency information, as found within a dependencies.properties file. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class DependencyInfo implements Comparable { // Internal state private static final String GROUP_ARTIFACT_SEPARATOR = "/"; private String groupId; private String artifactId; private String version; private String scope = "compile"; private String type = "jar"; public DependencyInfo(final String groupId, final String artifactId, final String version) { this.groupId = groupId; this.artifactId = artifactId; this.version = version; } /** * @return The GroupId of this DependencyInfo. */ public String getGroupId() { return groupId; } /** * @return The ArtifactId of this DependencyInfo. */ public String getArtifactId() { return artifactId; } /** * @return The Maven version of this DependencyInfo. */ public String getVersion() { return version; } /** * @return The type of this DependencyInfo. */ public String getType() { return type; } /** * @return The scope of this DependencyInfo. */ public String getScope() { return scope; } /** * Assigns the type of this DependencyInfo. * * @param type The non-empty type of this DependencyInfo. */ public void setType(final String type) { // Check sanity Validate.notEmpty(type, "type"); // Assign internal state this.type = type; } /** * Assigns the scope of this DependencyInfo. * * @param scope The non-empty scope of this DependencyInfo. */ public void setScope(final String scope) { // Check sanity Validate.notEmpty(scope, "scope"); // Assign internal state. this.scope = scope; } /** * @return A key for use within a SortedSet where this DependencyInfo should be sorted. */ public String getGroupArtifactKey() { return getGroupId() + GROUP_ARTIFACT_SEPARATOR + getArtifactId(); } /** * {@inheritDoc} */ @Override public int hashCode() { return groupId.hashCode() + artifactId.hashCode() + version.hashCode() + type.hashCode(); } /** * {@inheritDoc} */ @Override public String toString() { return groupId + GROUP_ARTIFACT_SEPARATOR + artifactId + GROUP_ARTIFACT_SEPARATOR + version + GROUP_ARTIFACT_SEPARATOR + scope + GROUP_ARTIFACT_SEPARATOR + type; } /** * {@inheritDoc} */ @Override public int compareTo(final DependencyInfo that) { // Return quick. if (that == this) { return 0; } if (that == null) { return -1; } // Compare internal stater int toReturn = this.getGroupId().compareTo(that.getGroupId()); if (toReturn == 0) { toReturn = this.getArtifactId().compareTo(that.getArtifactId()); } if (toReturn == 0) { toReturn = this.getVersion().compareTo(that.getVersion()); } if (toReturn == 0) { toReturn = this.getType().compareTo(that.getType()); } // All done. return toReturn; } } DependsFileParser.java000066400000000000000000000221731351100213400365710ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/java/org/codehaus/mojo/jaxb2/shared/versionpackage org.codehaus.mojo.jaxb2.shared.version; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.shared.Validate; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.StringTokenizer; import java.util.TreeMap; /** * Trivial parser to handle depends-plugin-style files. * * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public final class DependsFileParser { /** * String indicating that a line in a dependencies.properties file contains a version definition. */ private static final String VERSION_LINE_INDICATOR = "/version"; /** * String indicating that a line in a dependencies.properties file contains a type definition. */ private static final String TYPE_LINE_INDICATOR = "/type"; /** * String indicating that a line in a dependencies.properties file contains a scope definition. */ private static final String SCOPE_LINE_INDICATOR = "/scope"; // Internal state private static final String GROUP_ARTIFACT_SEPARATOR = "/"; private static final String KEY_VALUE_SEPARATOR = "="; private static final String DEPENDENCIES_PROPERTIES_FILE = "META-INF/maven/dependencies.properties"; private static final String GENERATION_PREFIX = "# Generated at: "; /** * The key where the build time as found within the dependencies.properties file is found. */ public static final String BUILDTIME_KEY = "buildtime"; /** * The key holding the artifactId of this plugin (within the dependencies.properties file). */ public static final String OWN_ARTIFACTID_KEY = "artifactId"; /** * The key holding the groupId of this plugin (within the dependencies.properties file). */ public static final String OWN_GROUPID_KEY = "groupId"; /** * The key holding the version of this plugin (within the dependencies.properties file). */ public static final String OWN_VERSION_KEY = "version"; /** * Hide constructors for utility classes */ private DependsFileParser() { } /** * Extracts all build-time dependency information from a dependencies.properties file * embedded in this plugin's JAR. * * @param artifactId This plugin's artifactId. * @return A SortedMap relating [groupId]/[artifactId] keys to DependencyInfo values. * @throws java.lang.IllegalStateException if no artifact in the current Thread's context ClassLoader * contained the supplied artifactNamePart. */ public static SortedMap getVersionMap(final String artifactId) { // Check sanity Validate.notEmpty(artifactId, "artifactNamePart"); Exception extractionException = null; try { // Get the ClassLoader used final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); final List manifestURLs = Collections.list( contextClassLoader.getResources(DEPENDENCIES_PROPERTIES_FILE)); // Find the latest of the URLs matching, to cope with test-scope dependencies. URL matching = null; for (URL current : manifestURLs) { if (current.toString().contains(artifactId)) { matching = current; } } if (matching != null) { return getVersionMap(matching); } } catch (Exception e) { extractionException = e; } // We should never wind up here ... if (extractionException != null) { throw new IllegalStateException("Could not read data from manifest.", extractionException); } else { throw new IllegalStateException("Found no manifest corresponding to artifact name snippet '" + artifactId + "'."); } } /** * Extracts all build-time dependency information from a dependencies.properties file * embedded in this plugin's JAR. * * @param anURL The non-empty URL to a dependencies.properties file. * @return A SortedMap holding all entries in the dependencies.properties file, plus its build * time which is found under the {@code buildtime} key. * @throws java.lang.IllegalStateException if no artifact in the current Thread's context ClassLoader * contained the supplied artifactNamePart. */ public static SortedMap getVersionMap(final URL anURL) { // Check sanity Validate.notNull(anURL, "anURL"); final SortedMap toReturn = new TreeMap(); try { final BufferedReader in = new BufferedReader(new InputStreamReader(anURL.openStream())); String aLine = null; while ((aLine = in.readLine()) != null) { final String trimmedLine = aLine.trim(); if (trimmedLine.contains(GENERATION_PREFIX)) { toReturn.put(BUILDTIME_KEY, aLine.substring(GENERATION_PREFIX.length())); } else if ("".equals(trimmedLine) || trimmedLine.startsWith("#")) { // Empty lines and comments should be ignored. continue; } else if (trimmedLine.contains("=")) { // Stash this for later use. StringTokenizer tok = new StringTokenizer(trimmedLine, KEY_VALUE_SEPARATOR, false); Validate.isTrue(tok.countTokens() == 2, "Found incorrect dependency.properties line [" + aLine + "]"); final String key = tok.nextToken().trim(); final String value = tok.nextToken().trim(); toReturn.put(key, value); } } } catch (IOException e) { throw new IllegalStateException("Could not parse dependency properties '" + anURL.toString() + "'", e); } // All done. return toReturn; } /** * Converts a SortedMap received from a {@code getVersionMap} call to hold DependencyInfo values, * and keys on the form {@code groupId/artifactId}. * * @param versionMap A non-null Map, as received from a call to {@code getVersionMap}. * @return a SortedMap received from a {@code getVersionMap} call to hold DependencyInfo values, * and keys on the form {@code groupId/artifactId}. */ public static SortedMap createDependencyInfoMap( final SortedMap versionMap) { // Check sanity Validate.notNull(versionMap, "anURL"); final SortedMap toReturn = new TreeMap(); // First, only find the version lines. for (Map.Entry current : versionMap.entrySet()) { final String currentKey = current.getKey().trim(); if (currentKey.contains(VERSION_LINE_INDICATOR)) { final StringTokenizer tok = new StringTokenizer(currentKey, GROUP_ARTIFACT_SEPARATOR, false); Validate.isTrue(tok.countTokens() == 3, "Expected key on the form [groupId]" + GROUP_ARTIFACT_SEPARATOR + "[artifactId]" + VERSION_LINE_INDICATOR + ", but got [" + currentKey + "]"); final String groupId = tok.nextToken(); final String artifactId = tok.nextToken(); final DependencyInfo di = new DependencyInfo(groupId, artifactId, current.getValue()); toReturn.put(di.getGroupArtifactKey(), di); } } for (Map.Entry current : toReturn.entrySet()) { final String currentKey = current.getKey(); final DependencyInfo di = current.getValue(); final String scope = versionMap.get(currentKey + SCOPE_LINE_INDICATOR); final String type = versionMap.get(currentKey + TYPE_LINE_INDICATOR); if (scope != null) { di.setScope(scope); } if (type != null) { di.setType(type); } } // All done. return toReturn; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/resources/000077500000000000000000000000001351100213400242435ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/resources/META-INF/000077500000000000000000000000001351100213400254035ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/resources/META-INF/m2e/000077500000000000000000000000001351100213400260665ustar00rootroot00000000000000lifecycle-mapping-metadata.xml000066400000000000000000000021241351100213400336760ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/resources/META-INF/m2e xjc testXjc true true schemagen testSchemagen true false jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/resources/META-INF/plexus/000077500000000000000000000000001351100213400267235ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/main/resources/META-INF/plexus/components.xml000066400000000000000000000003751351100213400316370ustar00rootroot00000000000000 java.util.List List java.util.ArrayList jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/000077500000000000000000000000001351100213400222515ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/fml/000077500000000000000000000000001351100213400230275ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/fml/faq.fml000066400000000000000000000173711351100213400243070ustar00rootroot00000000000000 XJC I have different schemas and want different packages for those schemas, how do I do this?

You want to create multiple executions in your plugin declaration. This will allow you to have multiple configuration declarations and you can specify the schema and package to be used for that execution. Note that you will need to not clear the output directory between executions in this case.

An example is given on the XJC usage page.

Schemagen What tool is used by the jaxb2-maven-plugin to generate the XML schema definition files?

The schemagen tool used by the plugin is part of the JDK distribution since Java 6.

The jaxb2-maven-plugin provides some augmentations to the generated schema files, such as the ability to define a schema prefix and filename for each generated XML schema.

How can I see the log messages output by the schemagen tool?

Run the jaxb2-maven-plugin in debug mode to see logging from the schemagen tool. Please refer to the examples for further information.

How do generated XML schema files correlate to annotated java files?

The schemagen tool generates one XML schema file per XML namespace it finds within the compilation unit (i.e. all annotated Java files selected for XML schema compilation).

The correlation between java files and generated XML schema files is therefore only indirect; a single generated XML schema file can hold the result of annotations within several java files - and a single annotated java source file can give rise to definitions scattered over several XML schema files.

An example is given on the usage page for the schemagen goal.

Can I generate XSDs without a namespace prefix on the target namespace?

The 2.x line of the Jaxb2-Maven-Plugin requires the namespaceURI to relate to at least one non-empty value out of the two properties below. Hence, at least one of these values must be provided and given a non-empty value:

  1. prefix
  2. toFile
When I try to generate Schema and any path contain whitespace, I get an Exception

This seems to be caused by internal implementation issues within the SchemaGen tool. The current workaround is to use a path without whitespace.

How can I annotate my java classes to generate XML schema?

For the full example (including generated XML Schema definitions), please refer to the schemagen usage page. Provided below are screenshots of two annotated source files, and a constants definition interface.

Namespaces definition interface. Simply defines constants for the three namespaces used within the two classes below.
package se.west.schema; public interface Namespaces { public static final String SOME_NAMESPACE = "http://some/namespace"; public static final String ANOTHER_NAMESPACE = "http://another/namespace"; public static final String YET_ANOTHER_NAMESPACE = "http://yet/another/namespace"; }

Class FooBar. By default, all members are compiled to XML schema with the namespace "http://some/namespace", as defined by the namespace attribute within the @XmlType annotation on line 9. The aRequiredElementInAnotherNamespace member belongs to the namespace "http://another/namespace", as defined on line 18.
package se.west.schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlType(namespace = Namespaces.SOME_NAMESPACE, propOrder = {"requiredElement", "aRequiredElementInAnotherNamespace", "optionalElement", "requiredAttribute", "optionalAttribute"}) @XmlAccessorType(XmlAccessType.FIELD) public class FooBar { @XmlElement(required = true, defaultValue = "requiredElementValue") private String requiredElement; @XmlElement(namespace = Namespaces.ANOTHER_NAMESPACE, required = true, defaultValue = "requiredElementValue") private String aRequiredElementInAnotherNamespace; @XmlElement(required = false) private String optionalElement; @XmlAttribute(required = true) private String requiredAttribute; @XmlAttribute(required = false) private String optionalAttribute; }

Class FooBaz. By default, all members are compiled to XML schema with the namespace "http://another/namespace", as defined by the namespace attribute within the @XmlType annotation on line 9. The aRequiredElementInYetAnotherNamespace member belongs to the namespace "http://yet/another/namespace", as defined on line 18. The anOptionalElementInSomeNamespace member belongs to the namespace "http://some/namespace", as defined on line 21.
package se.west.schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlType(namespace = Namespaces.ANOTHER_NAMESPACE, propOrder = {"requiredElement", "anOptionalElementInSomeNamespace", "aRequiredElementInYetAnotherNamespace", "requiredAttribute", "optionalAttribute"}) @XmlAccessorType(XmlAccessType.FIELD) public class FooBaz { @XmlElement(required = true, defaultValue = "requiredElementValue") private String requiredElement; @XmlElement(namespace = Namespaces.YET_ANOTHER_NAMESPACE, required = true, defaultValue = "requiredElementValue") private String aRequiredElementInYetAnotherNamespace; @XmlElement(namespace = Namespaces.SOME_NAMESPACE, required = false) private String anOptionalElementInSomeNamespace; @XmlAttribute(required = true) private String requiredAttribute; @XmlAttribute(required = false) private String optionalAttribute; }

jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/markdown/000077500000000000000000000000001351100213400240735ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/markdown/example_schemagen_basic.md000066400000000000000000000706671351100213400312430ustar00rootroot00000000000000# Basic Examples - XML Schema Generation > **Note**: These examples are valid for the 2.x version of the plugin, and do not work for the > jaxb2-maven-plugin version 1.x These basic examples illustrate how to generate XSDs from JAXB-annotated Java classes using the jaxb2-maven-plugin, and highlight the use of some of the plugin's common configuration options. This plugin runs the JDK distribution's SchemaGenerator compiler (check JAVA_HOME/bin/schemagen), and integrates the SchemaGenerator's configuration properties into a Maven project. Also, the jaxb2-maven-plugin [performs post-processing on generated XSD files](./example_schemagen_postprocessing.html) to improve usability and quality of the XSD files generated. > ### Jaxb2-Maven-Plugin and `Schemagen` known issues > > The `Schemagen` tool has been around in the JDK for quite awhile, and should be considered a mature codebase. > However, schemagen has some long-outstanding issues, as is shown by the > > [SchemaGen Issue Tracker on GitHub](https://github.com/javaee/jaxb-v2/labels/Component%3A%20schemagen). > > The Jaxb2-Maven-Plugin delegates its operations to the JDK-installed schemagen tool, and performs some > post-processing operations to yield schemas with somewhat improved usability than the XSDs emitted by SchemaGen. > However, the Jaxb2-Maven-Plugin does not aim to replace schemagen's implementation. Issues within SchemaGen > must be solved in that codebase. ## SchemaGenerator in the JDK The JDK contains the documentation for the SchemaGenerator arguments and switches. However, that documentation is somewhat slender and does not provide a thorough explanation for which types of "Java Files" can be used to generate XML schema: Usage: schemagen [-options ...] Options: -d : specify where to place processor and javac generated class files -cp : specify where to find user specified files -classpath : specify where to find user specified files -encoding : specify encoding to be used for apt/javac invocation -episode : generate episode file for separate compilation -version : display version information -fullversion : display full version information -help : display this usage message The help listing from the schemagen tool above is taken from a JDK 1.7 installation, and the arguments change a little for other major JDKs. However, it seems that the SchemaGenerator tool expects the following to be true for each of its "java files" arguments:
Property Description
Not directories If one of the "java files" arguments is a directory, the SchemaGenerator throws an IllegalArgumentException with the message directories not supported.
Java Source Files "java files" arguments can be relative paths to source files, calculated from the System property user.dir (i.e. not the Maven property basedir), on the form src/main/java/se/west/something/SomeClass.java.
Bytecode Files "java files" arguments can be fully qualified class names, such as se.west.gnat.Foo. In this case, the class file (Foo.class) should be in the correct directory (se/west/gnat) within the classpath (typically src/main/java or src/test/java).
**Note**: `schemagen` does not accept a mix of source and bytecode arguments as "java files". While the jaxb2-maven-plugin ensures that any sources added to the schemagen goals adheres to the criteria defined in the table above, it would lead too far to let the plugin validate that the user does not supply a mix of java source and bytecode files as arguments. If you would like to operate on bytecode files only, the plugin configuration must remove the sourcePath from the paths where it looks for jaxb sources. **Note**: `schemagen` can only insert documentation annotations when run against java source code files - not bytecode files. **Note**: The `SchemaGen` tool internally converts File paths to URIs and back, which means that exceptions occur when paths to your maven project contains whitespace. The current workaround is to avoid whitespace in paths whenever you need the plugin's `schemagen` goal to work properly. **Note**: The `episode` argument of schemagen does not seem to work. **Note**: The plugin currently requires that you run it from within the maven project directory, i.e. where the `pom.xml` file resides. If the project is part of a multi-module Maven build, Maven will take care of this for you. ## Recommended JAXB Annotations for XSD generation XSD generation from JAXB-annotated Java classes uses schemagen from the JAXB specification to generate XSDs from bytecode. While the default JAXB settings are sometimes good enough for use, tailoring generated XSDs is a task that more often than not requires quite a lot of annotations injected into the source code. For further/full information about the JAXB annotations, please refer to the [JAXB Reference Implementation](https://jaxb.java.net/). However, some best practises are recommended to generate good-quality XSD from annotated Java classes: 1. Always define an @XmlType element containing propOrder and (optionally) namespace elements. The propOrder is used to define the XSD sequence of the elements within the ComplexType synthesized from the Java class. You need to ensure that the sequence is well-defined, which means that you should define the propOrder. 2. If your java class contains collections, be sure to annotate them with `@XmlElementWrapper` **and** `@XmlElement`. It is good practise to let the member value be plural ("guildMemberships" rather than "guildMembership") in the java class, since it may contain several objects. The XmlElementWrapper annotation defines the name of the surrounding XML container, and the inner XmlElement annotation defines the name of each XML (child) element in the collection. 3. Place JavaDoc document comments on the private members. This documentation is entered as Documentation Annotations to the respective element definitions within the generated XSD file. 4. Create a TransformSchema configuration to map your namespace (`http://some/namespace`, for example) to a user friendly XML namespace prefix and a sensibly named XSD file. See the [Postprocessing Example Page](./example_schemagen_postprocessing.html) for examples on how to configure the jaxb2-maven-plugin to use TransformSchema configurations. package se.west.schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * This documentation will be copied as an XML Documentation Annotation for the ComplexType 'FooBar'. * Define it to augment usability/readability within the generated XSD. * * @author Lennart Jörelid */ @XmlType(namespace = "http://some/namespace", propOrder = {"requiredElement", "aRequiredElementInAnotherNamespace", "optionalElement", "requiredAttribute", "optionalAttribute", "guildMembership"}) @XmlAccessorType(XmlAccessType.FIELD) public class FooBar { /** * This documentation will be copied as an XML Documentation Annotation for the 'requiredElement'. * Define it to augment usability/readability within the generated XSD. */ @XmlElement(required = true, defaultValue = "requiredElementValue") private String requiredElement; @XmlElement(namespace = "http://another/namespace", required = true, defaultValue = "requiredElementValue") private String aRequiredElementInAnotherNamespace; /** * This documentation will be copied as an XML Documentation Annotation for the 'optionalElement'. * Define it to augment usability/readability within the generated XSD. */ @XmlElement(required = false) private String optionalElement; @XmlAttribute(required = true) private String requiredAttribute; @XmlAttribute(required = false) private String optionalAttribute; /** * The Guild Memberships of this FooBar. A nil value implies no GuildMemberships exist. */ @XmlElementWrapper(name = "guildMemberships", nillable = true, required = false) @XmlElement(name = "guildMembership") private Set guildMemberships; ... } The example above is by no means a complete guide to JAXB compliant class design, but serves to illustrate best practises which eliminate some of the more common mistakes for correct XSD generation. Again, for further/full information about the JAXB annotations, please refer to the [JAXB Reference Implementation](https://jaxb.java.net/). ## Standard (implicit) configuration The following settings are used by default. 1. The standard source folders (i.e. `getProject().getCompileSourceRoots()`) are expected to contain JAXB-annotated files, to be included within the Xml Schema Compilation operation. By default, files matching some Java Regexp patterns are excluded from the JXC compilation. The default exclude patterns are `"README.*", "\.xml", "\.txt", "\\.xjb", "\\.xsd", "\\.properties"` as documented on the `SchemaGenerationMojo.STANDARD_SOURCE_EXCLUDE_FILTERS` property. 2. The standard test source folders (i.e. `getProject().getTestCompileSourceRoots()`) are expected to contain JAXB-annotated files, to be included within the test-scope Xml Schema Compilation operation. By default, files matching some Java Regexp patterns are excluded from the JXC compilation. The default exclude patterns are `"README.*", "\.xml", "\.txt", "\\.xjb", "\\.xsd", "\\.properties"` as documented on the `TestSchemaGenerationMojo.STANDARD_TEST_SOURCE_EXCLUDE_FILTERS` property. The standard behavior can be overridden by the following elements: 1. `sources` - replace `getProject().getCompileSourceRoots()` as the files or directories containing JAXB-annotated source files. 2. `schemaSourceExcludeFilters` - Replace the default exclusion filters with a custom suite of Filters. 3. `testSources` - replace `getProject().getTestCompileSourceRoots()` as the files or directories containing JAXB-annotated source files for the test-scope compilation 4. `testSchemaSourceExcludeFilters` - Replace the default test-scope exclusion filters with a custom suite of Filters. These configuration options are illustrated within the examples below. Also, feel free to investigate the integration tests of the plugin itself. ## Example 1: Default XSD generation Generate XSD files from annotated Java classes is simple with the jaxb2-maven-plugin. Adding the plugin to your project and invoking its `schemagen` goal makes schemagen compile all java files found under the standard compile source roots (typically `src/main/java`): org.codehaus.mojo jaxb2-maven-plugin schemagen schemagen The output schema will be called `schema1.xsd`, `schema2.xsd` etc. and placed within the `target/generated-resources/schemagen/` folder. ## Example 2: Exclude source files from processing The jaxb2-maven-plugin permits you to exclude selected source files from processing, using a set of Filters. If a Filter matches a candidate source file, it is excluded from processing. In the sample below, any file whose full path ends with `jaxb.index` will be ignored by schemagen even if found below a `src/main/java` directory: org.codehaus.mojo jaxb2-maven-plugin schemagen schemagen jaxb\.index The PatternFileFilter matches the supplied java regexp patterns to a String expression calculated from each candidate File found under the `src/main/java` directory, which means that the power of regular expressions can be used to create several patterns to exclude files: jaxb\.index \.txt \.mdo .*blep.* **Note**: The name of the element defining the pattern (`myExcludes` in the snippet above) is unimportant. Maven will create a Filter object for each element to the `schemaSourceExcludeFilters` List, and inject it into the parameter called `schemaSourceExcludeFilters`. This is a result of the parameter definition: @Parameter(required = false) private List> schemaSourceExcludeFilters; Please refer to the standard [Maven Documentation for configuring plugins](http://maven.apache.org/guides/mini/guide-configuring-plugins.html) for further information about configuring plugins. ### Default excludes Should no configuration be given, standard excludes are: 1. Files with the name "README.*" 2. Files with the suffixes ".xml", ".txt" or ".xsd" 3. Files or Directories whose names starts with "." (normally this implies hidden directories and setting files) 4. Directories with the name "CVS" ## Example 3: PatternFileFilter custom configuration Your project might have complex rules for determining which files should be excluded from a schemagen compilation. To cater for potentially complex filtering needs, you may either configure the PatternFileFilter to cater for your needs or implement a custom Filter. This example illustrates how to configure the PatternFileFilter. PatternFileFilters may use several (optional) configuration settings to customize their work process (look for setter methods in the PatternFileFilter JavaDoc). Two of the commonly used configuration settings are: 1. *patternPrefix*: Java Regular Expressions can be rather lengthy, and frequently have similar structure with the difference only being the last part. The `patternPrefix` property contains a string to prepend to all patterns to yield the final java regexp pattern - and unless overridden, the default pattern prefix is `(\p{javaLetterOrDigit}|\p{Punct})+`. In the configuration snippet below, the patternPrefix is set to `*` instead. Therefore, the regular expression used to match Files with in the example shown below is `.*Bar\.java`. 2. *converter*: Java Regular Expressions compare and match Strings to Patterns. However, each candidate supplied to the PatternFileFiler is a `java.io.File` object, and we must therefore somehow convert the File to a String before we can match it with the complete regular expression as shown above. This conversion is done by a StringConverter (see the [JavaDoc](./javadoc/)) which simply contains a method `String convert(T toConvert);` which emits a String synthesized from each File object. The default implementation (below) simply retrieves the canonical absolute path for each File, but you may override this and supply a custom implementation - simply implement the StringConverter in a manner similar to the following (substituting for your preferred algorithm): /** * Converter returning the canonical and absolute path for a File. */ public static final StringConverter FILE_PATH_CONVERTER = new StringConverter() { @Override public String convert(final File toConvert) { return FileSystemUtilities.getCanonicalPath(toConvert.getAbsoluteFile()); } }; Finally, the configuration example below shows how to override the default pattern prefix and StringConverter: Bar\.java .* If your implementation class `se.west.converter.FileNameConverter` is located in a separate project, remember to make that implementation class accessible to the jaxb2-maven-plugin. This is done by Maven's default dependency mechanism for plugins, as illustrated by the full configuration example below. org.codehaus.mojo jaxb2-maven-plugin schemagen schemagen generated/xsds Bar\.java .* se.west.converters custom-jaxb-converters 1.2.14 ## Example 4: Debugging jaxb2-maven-plugin executions If you are curious about the exact java regexp patterns used for matching your files, or simply want to see what the jaxb2-maven-plugin does internally, run the plugin in debug mode by adding the `-X` switch. The debug log contains somewhat human-friendly log entries which contains the SchemaGen arguments synthesized by the jaxb2-maven-plugin and supplied in order: +=================== [9 SchemaGen Arguments] | | [0]: -encoding | [1]: UTF-8 | [2]: -d | [3]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/schemagen-main/target/schemagen-work/compile_scope | [4]: -classpath | [5]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/schemagen-main/src/main/java/ | [6]: -episode | [7]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/schemagen-main/target/generated-resources/schemagen/META-INF/sun-jaxb.episode | [8]: src/main/java/se/west/gnat/Foo.java | +=================== [End 9 SchemaGen Arguments] If you would like to run SchemaGen manually in the same way as the jaxb2-maven-plugin runs the tool, simply paste the arguments given in the debug listing into a shell (separate with spaces). The debug log also shows the configuration and result of the configured PatternFileFilters; as shown in the listing below, two PatternFileFilters containing 3 java regular expression patterns each are applied to the files found below the standard directory `src/main/java`. The listing shows the java regexps in use, and the resulting file after removing all files identified by the two PatternFileFilters: +=================== [Filtered sources] | | 2 Exclude patterns: | [1/2]: Filter [PatternFileFilter] | Processes nulls: [false] | Accept on match: [true] | 3 regularExpressions ... | [0/3]: (\p{javaLetterOrDigit}|\p{Punct})+README.* | [1/3]: (\p{javaLetterOrDigit}|\p{Punct})+\.xml | [2/3]: (\p{javaLetterOrDigit}|\p{Punct})+\.txt | [2/2]: Filter [PatternFileFilter] | Processes nulls: [false] | Accept on match: [true] | 3 regularExpressions ... | [0/3]: (\p{javaLetterOrDigit}|\p{Punct})+\.xjb | [1/3]: (\p{javaLetterOrDigit}|\p{Punct})+\.xsd | [2/3]: (\p{javaLetterOrDigit}|\p{Punct})+\.properties | | 1 Standard Directories: | [1/1]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/schemagen-main/src/main/java | | 1 Results: | [1/1]: file:/Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/schemagen-main/src/main/java/se/west/gnat/Foo.java | +=================== [End Filtered sources] Also, the jaxb2-maven-plugin debug log contains debug log statements emitted from the underlying tools themselves (SchemaGen or XJC). These statements may be formatted in somewhat strange ways, but starts with the name of the tool encased in brackets. As illustrated below, the SchemaGen tool emitted a debug statement from the createOutput method with the content `ENTRY schema1.xsd`: [DEBUG] [SchemaGen]: feb 03, 2015 3:39:15 EM com.sun.xml.bind.v2.schemagen.FoolProofResolver createOutput FINER: ENTRY schema1.xsd Yes ... you get the timestamp for free ... # Example 5: Setting the locale for the SchemaGen execution If you require the SchemaGen tool to be executed with a default Locale other than your standard default Locale, simply use the `locale` configuration parameter and supply a string parseable to a Locale on the form `[,[,]]`. For example, to generate the schema using french locale despite running Maven with another Locale, configure the jaxb2-maven-plugin as follows: org.codehaus.mojo jaxb2-maven-plugin schemagen schemagen fr The generated schema /** *

Classe Java pour AddressType complex type. * *

Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe. * *

     * <complexType name="AddressType">
     *   <complexContent>
     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *       <sequence>
     *         <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="Line1" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="Line2" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="City" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="State" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="ZipCode" type="{http://www.w3.org/2001/XMLSchema}decimal"/>
     *       </sequence>
     *     </restriction>
     *   </complexContent>
     * </complexType>
     * 
* * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AddressType", propOrder = { "name", "line1", "line2", "city", "state", "zipCode" }) @Generated(value = "com.sun.tools.xjc.Driver", date = "2015-07-12T08:33:24+02:00", comments = "JAXB RI v2.2.11") public class AddressType { .... } ## Advanced topic: SchemaGen source vs. bytecode arguments The SchemaGen tool assumes that all relative paths to source files are calculated from the system property `user.dir`, as described above. For maven multi-module projects the `user.dir` property is defined as the directory where the `mvn` command was launched - and the jaxb2-maven-plugin calculates the relative path from this directory to the actual file. This implies that schemagen will need a full path to its source file arguments, but only a fully qualified classname for bytecode arguments. Also, the schemagen tool requires *either* source or bytecode arguments - not both. A native schemagen command will therefore take one of the following forms: schemagen -d target/classes src/main/java/se/west/gnat/Foo.java ... or, if you generate schema from already compiled bytecode files: schemagen -d target/classes se.west.gnat.Bar While the jaxb2-maven-plugin could potentially include some snazzy and complex code to ensure that the arguments would be only either source or bytecode files, the underlying schemagen tool will complain visibly if the argument combinations are incorrect. Thus, the jaxb2-maven-plugin authors felt it would be better to simply delegate the error handling in this case to schemagen, to avoid creating a new layer of potentially complex logic within the plugin.jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/markdown/example_schemagen_postprocessing.md000066400000000000000000000366261351100213400332410ustar00rootroot00000000000000# Post-processing Examples - XML Schema Generation > **Note**: These examples are valid for the 2.x version of the plugin, and do not work for the > jaxb2-maven-plugin version 1.x. Post-processing was introduced in version 2 of the jaxb2-maven-plugin. The SchemaGenerator ("schemagen") tool which is used by the Jaxb2-Maven-plugin to create XML Schema files from JAXB-annotated java source code does not necessarily produce professional-grade XSD files by default. Some properties of the generated XSD files can be augmented for improved usability; this is done by the jaxb2-maven-plugin following the standard SchemaGenerator in the following order: Each post-processor used by the jaxb2-maven-plugin process XML nodes and hence implement the `NodeProcessor` interface. A brief explanation of what they do is given in the table below.
NodeProcessor Description Why do we need it?
XsdAnnotationProcessor Copies JavaDoc from Java classes, fields or methods into the generated XSD as XML annotations. Professional XSDs should not be denied containing the JavaDoc supplied in the source code, in particular as those JavaDocs frequently explain important facts about permitted values or data use. This postprocessor generates XML documentation annotations from the JavaDoc in source code.
ChangeFilenameProcessor Alters the filename of a generated XSD, which by default is schema1.xsd, schema2.xsd etc. Professional XSDs should be defined within usable/understandable file names. SchemaGen creates one file per XML namespace in the compilation unit, but the tool cannot figure out how to name the XSD files sensibly. With several namespaces in use, it quickly becomes problematic to keep track of which XSD file contains which namespace.
ChangeNamespacePrefixProcessor Alters the namespace prefix for namespaces within generated XSDs, which by default is ns1, ns2 etc. Professional XSDs should contain usable/understandable namespace prefixes. For example, this post-processor permits changing <xs1:fiscalLaw> to <swedishLaws:fiscalLaw>, to distinguish it from <britishLaws:fiscalLaw>.
## Example 1: Adding XML documentation annotations into generated XSDs The XsdAnnotationProcessor is used to copy JavaDoc comments from Java source files into generated XSDs. This preserves parts of the information provided in Java source code in the generated XSD files. A typical standard/vanilla XSD file generated by schemagen looks like the following: While the significance of the elements and attribute in the complex type above might appear self-evident, the XSD is somewhat barren since no JavaDoc information is injected into it. XML has a standard for documenting elements, described in the [XML Schema Definitions standard](http://www.w3.org/TR/xmlschema11-1/#cAnnotations). This standard is used by the XsdAnnotationProcessor to insert JavaDoc from fields into the XSD, augmenting the result from above to the following: Lennart Jörelid, jGuru Europe AB (custom): A custom JavaDoc annotation.]]> The JavaDoc inserted as XML documentation elements is read directly from the source code (shown below). Note that all copied JavaDoc is wrapped in [CDATA](http://www.w3schools.com/xml/xml_cdata.asp) tags to permit any JavaDoc text without risking to create invalid XML within the XSD file. /** * Definition of a person with lastName and age, and optionally a firstName as well... * * @author Lennart Jörelid, jGuru Europe AB * @custom A custom JavaDoc annotation. */ @XmlRootElement @XmlType(namespace = SomewhatNamedPerson.NAMESPACE, propOrder = {"firstName", "lastName", "age"}) @XmlAccessorType(XmlAccessType.FIELD) public class SomewhatNamedPerson { /** * The XML namespace of this SomewhatNamedPerson. */ public static final String NAMESPACE = "http://some/namespace"; /** * The first name of the SomewhatNamedPerson. */ @XmlElement(nillable = true, required = false) private String firstName; /** * The last name of the SomewhatNamedPerson. */ @XmlElement(nillable = false, required = true) private String lastName; /** * The age of the SomewhatNamedPerson. Must be positive. */ @XmlAttribute(required = true) private int age; ... The rest of the class omitted in this listing ... } The `schemagen` goal configuration within the POM automatically copies JavaDoc data as annotations into the XSD files - simply activate the goal within the plugin's configuration. org.codehaus.mojo jaxb2-maven-plugin schemagen schemagen ### Formatting XSD documentation annotations The jaxb2-maven-plugin holds a JavaDocRenderer instance used to convert a JavaDoc comment into plain text, to be inserted into the annotation element. Unless overridden in the plugin's configuration, a default JavaDocRenderer is used. You can change the formatting to a format better suited to your needs by implementing a custom JavaDocRenderer and telling the plugin to use it: org.codehaus.mojo jaxb2-maven-plugin schemagen schemagen org.acme.render.MyJavaDocRenderer The class provided should implement the interface `JavaDocRenderer`; the default implementation is shown below. The result of the `render` method is inserted into the generated XSD. Neither of the two parameters will be null for any call to the render method. The JavaDocData structure contains the JavaDoc comment (which is all text in the JavaDoc not part of a JavaDoc tag) and a Map relating tag names to their respective values. public class DefaultJavaDocRenderer implements JavaDocRenderer { /** *

Renders the supplied JavaDocData structure as text to be used within an XSD documentation annotation. * The XSD documentation annotation will contain a CDATA section to which the rendered JavaDocData is * emitted.

* * @param nonNullData the JavaDocData instance to render as XSD documentation. Will never be {@code null}. * @param location the SortableLocation where the JavaDocData was harvested. Never {@code null}. * @return The rendered text contained within the XML annotation. */ @Override public String render(final JavaDocData nonNullData, final SortableLocation location) { // Compile the XSD documentation string for this Node. final StringBuilder builder = new StringBuilder(); builder.append(nonNullData.getComment()).append("\n\n"); for (Map.Entry current : nonNullData.getTag2ValueMap().entrySet()) { final String tagDocumentation = "(" + current.getKey() + "): " + current.getValue() + "\n"; builder.append(tagDocumentation); } // All done. return builder.toString(); } } ## Example 2: Transforming schema XSD files, like java classes, are combined data- and structure definitions. As such they should communicate structure clearly to anyone consuming/using the definitions, and also adhere to usability engineering principles. Sadly, the schemagen tool distributed with the JDK does not generate XSD files which comply with some minimalistic usability principles: 1. schemagen's generated XSD files have names on the form `schema#.xsd` (where "#" is a number), which makes it unnecessarily difficult to understand which XML ComplexType is defined where, or what domain the ComplexTypes in the file belongs to. 2. schemagen's generated XSD files have XML namespaces prefixes on the form `ns#` (where "#" is a number). This makes it unnecessarily complex to understand which complex type is actually referred to. (Does `ns2:fiscalLaw` refer to the ComplexType in the swedish or the british namespace? It would be much simpler to use appropriate XML namespace prefixes in the generated files, such as `swedishLaws:fiscalLaw` or `britishLaws:fiscalLaw`). The TransformSchema element permits developers to both change the names of generated XSD files and the XML namespace prefixes within the generated files. A TransformSchemas configuration element is a list of transformSchema objects, each of which has a namespace URI (mandatory) and two optional properties (toPrefix and toFile). As shown in the snippet below, 3 namespaces are transformed to be given user-friendly prefixes and file names: http://some/namespace some some_schema.xsd http://another/namespace another another_schema.xsd http://yet/another/namespace yetAnother yet_another_schema.xsd The full plugin configuration containing 2 post-processors is shown below: org.codehaus.mojo jaxb2-maven-plugin schemagen schemagen false http://some/namespace some some_schema.xsd http://another/namespace another another_schema.xsd http://yet/another/namespace yetAnother yet_another_schema.xsd Note that a TransformSchema element can omit either `toPrefix` or `toFile` to yield a configuration similar to the following: http://some/namespace some some_schema.xsd http://another/namespace another http://yet/another/namespace yet_another_schema.xsd jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/markdown/example_xjc_basic.md000066400000000000000000000632241351100213400300640ustar00rootroot00000000000000# Basic Examples - Java Generation > **Note**: These examples are valid for the 2.x version of the plugin, and do not necessarily > work for the jaxb2-maven-plugin version 1.x These basic examples show how to generate Java code from JAXB using the jaxb2-maven-plugin, and highlight the use of some of the plugin's common configuration options. This plugin runs the XJC binding compiler from the JAXB distribution, and integrates XJC's configuration properties into a Maven project. The plugin will delegate all JAXB-related work to its [JAXB implementation dependencies](./dependencies.html). The actual JAXB dependencies used when compiling the plugin will also be collected and listed when the plugin is run in debug mode. Due to the construction of the Java platform the JAXB API used is the one defined by the platform. This means that the used JAXB API version will be the endorsed one of the JDK, regardless of what is specified in the plugin (or its dependencies). You may override the endorsed API outside of Maven and this plugin, but that is typically viewed as advanced usage. A better option is to align the version of the compiled code with the requirement on the JAXB runtime environment of the generated code. **Note**: The plugin currently requires that you run it from within the maven project directory, i.e. where the `pom.xml` file resides. If the project is part of a multi-module Maven build, Maven will take care of this for you. ## Standard (implicit) configuration To find which files should be included within an XJC compilation the jaxb2-maven-plugin uses the following algorithm. Note that the find-and-filter algorithm is applied to find both XSD files and XJB files. 1. Find source files. Source files are either given as an explicit path, or found by recursively listing all files below a source directory given as an explicit path. For example, if `src/main/xsd` is the relative path to a directory, all files within it would be found. 2. Filter source files. A (set of) exclude Filters are applied to each found source file. Any file matching at least one Filter is excluded from the XJC compilation. Unless overridden by the configuration, the following settings are used by default: 1. The `src/main/xsd` directory (including subdirectories) is expected to contain compile-scope XSD files, as documented within the `XjcMojo.STANDARD_SOURCE_DIRECTORY` property. By default, files matching some Java Regexp patterns are excluded from the XJC compilation. The default exclude patterns are `"README.*", "\.xml", "\.txt", "\.java", "\.scala", "\.mdo"`. 2. The `src/test/xsd` directory (including subdirectories) is expected to contain test-scope XSD files, as documented within the `TestXjcMojo.STANDARD_TEST_SOURCE_DIRECTORY` property. By default, files matching some Java Regexp patterns are excluded from the XJC compilation. The default exclude patterns are `"README.*", "\.xml", "\.txt", "\.java", "\.scala", "\.mdo"`. 3. The `src/main/xjb` directory (including subdirectories) is expected to contain compile-scope XJB files, as documented within the `XjcMojo.STANDARD_XJB_DIRECTORY` property. By default, files matching some Java Regexp patterns are excluded from the XJC compilation. The default exclude patterns are `"README.*", "\\.xml", "\\.txt", "\\.xsd"`. 4. The `src/test/xjb` directory (including subdirectories) is expected to contain test-scope XJB files, as documented within the `TestXjcMojo.STANDARD_TEST_XJB_DIRECTORY` property. By default, files matching some Java Regexp patterns are excluded from the XJC compilation. The default exclude patterns are `"README.*", "\\.xml", "\\.txt", "\\.xsd"`. The standard behavior can be overridden by the following elements: 1. `sources` - replace `src/main/xsd` as the directory containing XSD files 2. `xjbSource` - replace `src/main/xjb` as the directory containing XJB files 3. `xjcSourceExcludeFilters` - replace the default Filters for XSD file exclusions 4. `xjbExcludeFilters` - replace the default Filters for the XJB file exclusions For test-scope XJC compilation, the following configuration elements can be used to override the default behavior: 1. `testSources` - replace `src/test/xsd` as the directory containing (test-scope) XSD files 2. `testXjbSources` - replace `src/test/xjb` as the directory containing (test-scope) XJB files 3. `testSourceExcludeFilters` - replace the default Filters for (test-scope) XSD exclusions 4. `testXjbExcludeFilters` - replace the default Filters for (test-scope) XJB exclusions. These configuration options are illustrated within the examples below. Also, feel free to investigate the integration tests of the plugin itself. ## Example 1: Generate Java code within provided package The plugin will process all XSD files found within the [source directories](xjc-mojo.html#sources), and create Java source code in the given package (`com.example.myschema`) as defined by the `packageName` configuration parameter. The required JAXB runtime version of the generated code will be the same as the plugin's JAXB implementation dependency (see the [target parameter](./xjc-mojo.html#target)). ... ... ... org.apache.maven.plugins maven-compiler-plugin 1.7 1.7 org.codehaus.mojo jaxb2-maven-plugin ${project.version} xjc xjc com.example.myschema ... ... ## Example 2: Aligning JDK with JAXB API and JAXB runtime environment So you want to use JAXB on JDK 1.6? You would then need to configure the jaxb2-maven-plugin for a Java 6+ project, which implies two separate configuration properties: 1. *maven-compiler-plugin*: Define java version 1.6 for the compiler, to use the Java 6+ platform as the runtime environment for the compiled code. Use 1.6 for both the `source` and `target` properties. 2. *jaxb-maven-plugin*: Use the `target` configuration parameter to set the JAXB runtime version to 2.1, which is included in the JDK 1.6 (starting with JDK 1.6u4). The project can now be built with JDK 1.6. ... org.apache.maven.plugins maven-compiler-plugin 1.6 1.6 org.codehaus.mojo jaxb2-maven-plugin ${project.version} xjc xjc 2.1 ... ... ... ## Example 3: Using another type of input source Normally, you would use XML Schema Definitions as the standard type of JAXB source. However, other standards can be used as source type provided that the configuration parameter `sourceType` is assigned one of the existing values of the [org.codehaus.mojo.jaxb2.javageneration.SourceContentType](http://mojo.codehaus.org/jaxb2-maven-plugin/apidocs/org/codehaus/mojo/jaxb2/javageneration/SourceContentType.html) enum. In the example below, the source files contain [Document Type Descriptions](http://en.wikipedia.org/wiki/Document_type_definition) instead of XML Schema, and they are placed within the `src/main/dtd` directory. Note that the `sourceType` configuration parameter is case sensitive for matching the enum values. Refer to the plugin's [JavaDoc](./apidocs/index.html) to see all possible values. org.codehaus.mojo jaxb2-maven-plugin ${project.version} xjc xjc com.example.myschema dtd src/main/dtd ## Example 4: Defining sources and XJC exclude filters By default, the jaxb2-maven-plugin examines the directory `src/main/xsd` for XSD files which should be used by JAXB to create Java source code (and `src/test/xsd` for test XSD sources). If you would like to place your XSD somewhere else, you need to define source elements as shown in the configuration below. The paths given are interpreted relative to the `basedir` property, which is set to reference the maven project directory. Files found (using a recursive search) within the sources elements are read and used by the XJC tool only if they are **not** matched by any xjcSourceExcludeFilters. Therefore, the configuration below should include `src/main/some/other/xsds/aFile.txt` as an XSD source, but exclude `src/main/some/other/xsds/thisIsASource.xsd` due to the pattern definition `\.xsd`. (For a full explanation of filters, please refer to the [Filters](./filters.html) documentation). org.codehaus.mojo jaxb2-maven-plugin ${project.version} xjc xjc src/main/some/other/xsds src/main/foo/gnat.xsd src/main/a/nonexistent/path \.xsd \.foo se.west source/xsds Unless xjcSourceExclude filters are given, standard excludes are in effect. These are: 1. Files with the name "README.*" 2. Files with the suffixes ".xml", ".txt" or ".xjb" 3. Files or Directories whose names starts with "." (normally this implies hidden directories and setting files) 4. Directories with the name "CVS" ## Example 5: Multiple schemas with different configuration In the case of having multiple XML schema files which should be processed with different configuration, you need to have multiple plugin execution bindings. One execution binding per unique configuration, as shown in the snippet below: org.codehaus.mojo jaxb2-maven-plugin ${project.version} xjc-schema1 xjc src/main/xsds/west se.west xjc-schema2 xjc src/main/xsds/east se.east false ## Example 6: Using an XML Java Binding file ("XJB") By default, the XjcMojo searches directory `src/main/xjb` (and the XjcTestMojo searches `src/test/xjb`) for external XML schema generation binding files. Such files are used to control many aspects of the Java generation from XSD files; please refer to the [JAXB Reference Implementation](https://jaxb.java.net/) for full details. However, a small XJB file is found below. The JXB file above defines the package of the generated Java source code found in the XSD file `../xsd/address.xsd`, relative to the JXB file above. This implies that each JXB file must contain a path to the XSD files they tailor. Each file found under within the JXB source directories is considered a JXB file, unless it is excluded by means of an xjbExcludeFilter. A sample xjbExcludeFilter is found below; any file matching an xjbExcludeFilter is not used as a binding file in the XJC compilation, implying that any file found within the standard XJB directory/directories are not used if it ends with `.txt` or `.xsd`: ... \.txt \.xsd ... Just like the XJC source files, you can change the directories where the XjcMojo searches for binding files by using the xjbSources configuration parameter. Each `xjbSource` element can be a relative path to a directory (in which case all its files are searched and included recursively) or explicit files: ... src/dataexchange/special/aBindingConfiguration.xjb src/dataexchange/xjbs ... Unless xjbExcludes filters are given, standard excludes are in effect. These are: 1. Files with the name "README.*" 2. Files with the suffixes ".xml", ".txt" or ".xsd" 3. Files or Directories whose names starts with "." (normally this implies hidden directories and setting files) 4. Directories with the name "CVS" ## Example 7: Debugging jaxb2-maven-plugin executions If you are curious about the exact java regexp patterns used for matching your files, or simply want to see what the jaxb2-maven-plugin does internally, run the plugin in debug mode by adding the `-X` switch. The debug log contains somewhat human-friendly log entries which contains the XJC arguments synthesized by the jaxb2-maven-plugin and supplied in order: +=================== [11 XJC Arguments] | | [0]: -xmlschema | [1]: -encoding | [2]: UTF-8 | [3]: -p | [4]: com.example.myschema | [5]: -d | [6]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-main/target/generated-sources/jaxb | [7]: -extension | [8]: -episode | [9]: /Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-main/target/generated-sources/jaxb/META-INF/sun-jaxb.episode | [10]: src/main/xsd/address.xsd | +=================== [End 11 XJC Arguments] If you would like to run XJC manually in the same way as the jaxb2-maven-plugin runs the tool, simply paste the arguments given in the debug listing into a shell (separate with spaces). The debug log also shows the configuration and result of the configured PatternFileFilters; as shown in the listing below, two PatternFileFilters containing 3 java regular expression patterns each are applied to the files found below the standard directory `src/main/xsd`. The listing shows the java regexps in use, and the resulting file after removing all files identified by the two PatternFileFilters: +=================== [Filtered sources] | | 2 Exclude patterns: | [1/2]: Filter [PatternFileFilter] | Processes nulls: [false] | Accept on match: [true] | 3 regularExpressions ... | [0/3]: (\p{javaLetterOrDigit}|\p{Punct})+README.* | [1/3]: (\p{javaLetterOrDigit}|\p{Punct})+\.xml | [2/3]: (\p{javaLetterOrDigit}|\p{Punct})+\.txt | [2/2]: Filter [PatternFileFilter] | Processes nulls: [false] | Accept on match: [true] | 1 regularExpressions ... | [0/1]: (\p{javaLetterOrDigit}|\p{Punct})+\.xjb | | 1 Standard Directories: | [1/1]: src/main/xsd | | 1 Results: | [1/1]: file:/Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-main/src/main/xsd/address.xsd | +=================== [End Filtered sources] Also, the jaxb2-maven-plugin debug log contains debug log statements emitted from the underlying tools themselves (SchemaGen or XJC). These statements may be formatted in somewhat strange ways, but starts with the name of the tool encased in brackets. As illustrated below, the XJC tool emitted debug statements, one of which is from the allowExternalAccess method indicating that the property `http://javax.xml.XMLConstants/property/accessExternalSchema` is supported and successfully set: [DEBUG] Using explicitly configured encoding [UTF-8] [DEBUG] [XJC]: feb 03, 2015 3:39:32 EM com.sun.xml.bind.v2.util.XmlFactory createSchemaFactory FINE: SchemaFactory instance: com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory@5b6813df [DEBUG] [XJC]: feb 03, 2015 3:39:32 EM com.sun.xml.bind.v2.util.XmlFactory allowExternalAccess FINE: Property "http://javax.xml.XMLConstants/property/accessExternalSchema" is supported and has been successfully set by used JAXP implementation. Yes ... you get the timestamp for free ... # Example 8: Setting the locale for the XJC execution If you require the XJC tool to be executed with a default Locale other than your standard default Locale, simply use the `locale` configuration parameter and supply a string parseable to a Locale on the form `[,[,]]`. For example, to generate the XJC using french locale despite running Maven with another Locale, configure the jaxb2-maven-plugin as follows: org.codehaus.mojo jaxb2-maven-plugin xjc xjc com.example.myschema true fr The generated source code will contain french comments: /** *

Classe Java pour AddressType complex type. * *

Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe. * *

     * <complexType name="AddressType">
     *   <complexContent>
     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *       <sequence>
     *         <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="Line1" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="Line2" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="City" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="State" type="{http://www.w3.org/2001/XMLSchema}string"/>
     *         <element name="ZipCode" type="{http://www.w3.org/2001/XMLSchema}decimal"/>
     *       </sequence>
     *     </restriction>
     *   </complexContent>
     * </complexType>
     * 
* * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AddressType", propOrder = { "name", "line1", "line2", "city", "state", "zipCode" }) @Generated(value = "com.sun.tools.xjc.Driver", date = "2015-07-12T08:33:24+02:00", comments = "JAXB RI v2.2.11") public class AddressType { .... }jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/markdown/filters.md000066400000000000000000000230641351100213400260720ustar00rootroot00000000000000# Filters and Filtering > **Note**: This documentation pertains to the 2.x version of the plugin. Frequently, we would like exclude some files from being used as sources for XJC or SchemaGen. For example, if all Java Sources placed under `src/main/java` *except one* should be used to distill the XSD files by SchemaGen we must configure the SchemaGen mojo to exclude that particular file. This type of operation is done with a Filter, which - in this case - identifies Files to exclude from the normal operation. The Java world sports several projects that define Filters, such as [the filter definitions in Apache ANT](https://ant.apache.org/manual/Tasks/filter.html), the [LambdaJ](https://code.google.com/p/lambdaj/) from Google or the JDK 8 `java.util.stream` collection filtering. Most of these implementations, however, work in slightly different ways which tends to complicate the life of us programmers quite a bit. Just remembering the exact syntax to create a Filter from one of these projects can be somewhat problematic. Moreover, the JDK 8 mechanics cannot be used as the jaxb2-maven-plugin must be binary compatible with JDK 1.6+. ## Filters in the JAXB2 Maven Plugin Filters used by the JAXB2 Maven plugin are visitors, similar in structure to the well-known `java.io.FileFilter`. As shown in the listing below, the Filters used by the Jaxb2 Maven Plugin sport 2 methods: 1. `initialize`: Injects the active Maven Log into the Filter, to enable proper logging from within the Filter. 2. `accept`: The actual filter method which returns `true` if the given candidate is accepted and `false` otherwise. public interface Filter { /** * Initializes this Filter, and assigns the supplied Log for use by this Filter. * * @param log The non-null Log which should be used by this Filter to emit log messages. */ void initialize(Log log); /** * @return {@code true} if this Filter has been properly initialized (by a call to * the {@code initialize} method). */ boolean isInitialized(); /** *

Method that is invoked to determine if a candidate instance should be accepted or not. * Implementing classes should be prepared to handle {@code null} candidate objects.

* * @param candidate The candidate that should be tested for acceptance by this Filter. * @return {@code true} if the candidate is accepted by this Filter and {@code false} otherwise. * @throws java.lang.IllegalStateException if this Filter is not initialized by a call to the * initialize method before calling this matchAtLeastOnce method. */ boolean accept(T candidate) throws IllegalStateException; } While this Filter implementation is simple enough to be implemented directly, the jaxb2-maven-plugin codebase contains implementations intended to simplify creating custom Filters - and indeed some concrete implementations as well. The inheritance hierarchy contains several types, as shown in the image below: The Filter types are described below: 1. `AbstractFilter`: abstract Filter implementation. Handles separating *null* candidate values from non-null ones, and delegates processing to concrete subclass implementations. 2. `AbstractPatternFilter`: subclass to AbstractFilter, which contains a List of `java.util.regex.Pattern` objects used to match/accept a candidate or reject it. Since java regexp Patterns work primarily on Strings, each AbstractPatternFilter has a `StringConverter` which converts candidate objects to strings for matching. The jaxb2-maven-plugin also contains two concrete Filter implementations, directly usable in the plugin's configuration: 1. `PatternFileFilter`: An AbstractPatternFilter implementation which matches `java.io.File`s. By default, the PatternFileFilter has a StringConverter which submits the full path of each File for matching. You can change the implementation by setting the `converter` property to a custom converter which uses another algorithm for converting each candidate File to a String for matching. 2. `PatternURLFilter`: An AbstractPatternFilter implementation which matches `java.io.URL`s. Unless overridden, the PatternURLFilter uses a normalized string form of each submitted URL for matching. (Normalizing a URL is done in the following manner: `anURL.toURI().normalize().toURL().toString()`). A slightly more detailed class diagram than the one above is shown below: ## Filter examples: PatternFileFilter Excluding some files from processing is a straightforward task. Create a PatternFileFilter instance and populate it with some pattern strings from which it should create `java.util.regexp.Patterns`. A PatternFileFilter which matches any file whose full path end with `.xsd` or `.foo` is defined as follows: \.xsd \.foo But ... wait a second. If the patterns supplied in the configuration snippet above are intended to match the full path of the file `/some/path/to/src/main/xsd/blah.xsd`, the pattern specification above is clearly not sufficient. The PatternFileFilter must prepend some other string to create a Pattern able to match the given file path. The string prepended to the supplied patterns is given by the configuration property `patternPrefix`, which defaults to the value `(\\p{javaLetterOrDigit}|\\p{Punct})+`. Therefore, each pattern string in the configuration above is prepended to yield the two effective patterns: 1. `(\\p{javaLetterOrDigit}|\\p{Punct})+\.xsd`, and 2. `(\\p{javaLetterOrDigit}|\\p{Punct})+\.foo` These two patterns are sufficient for matching the fully qualified path of the file `/some/path/to/src/main/xsd/blah.xsd`. For clarity, the effective pattern string used to compile the Patterns for matching files are also emitted when you run the jaxb2-maven-plugin with debug log settings. An example of typical output plugin debug logging is harvested from one of the integration tests in the jaxb2-maven-plugin itself. Note the two resulting regular expressions used by the PatternFileFilter: +=================== [Filtered sources] | | 1 Exclude patterns: | [1/1]: Filter [PatternFileFilter] | Processes nulls: [false] | Accept on match: [true] | 2 regularExpressions ... | [0/2]: (\p{javaLetterOrDigit}|\p{Punct})+\.xsd | [1/2]: (\p{javaLetterOrDigit}|\p{Punct})+\.foo | | 1 Standard Directories: | [1/1]: src/main/xsd | | 3 Results: | [1/3]: file:/Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-exclude-file-patterns/src/main/foo/gnat.txt | [2/3]: file:/Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-exclude-file-patterns/src/main/someOtherXsds/fooSchema.txt | [3/3]: file:/Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/it/xjc-exclude-file-patterns/src/main/someOtherXsds/some_schema.bar | +=================== [End Filtered sources] A maven configuration for creating a PatternFileFilter which excludes any source files whose full paths end in either `.xsd` or `.foo` is done as follows: \.xsd \.foo Filters can be used to identify files to be excluded from processing by XJC and SchemaGen. All configuration properties for Mojos within the jaxb2-maven-plugin use optional Filters to identify these ### Configuring a pattern filter For a fuller example of configuring a PatternFileFilter, refer to the [SchemaGen Basic Usage](./example_schemagen_basic.html) page. ## Creating custom Filter implementations Should you want to integrate another Filter implementation for pattern matching into the jaxb2-maven-plugin configuration, you can simply implement and configure new Filter. In this case, we recommend that your implementation extend the `AbstractFilter` class (or any of its subclasses) to reuse the default lifecycle implemented there. When implemented, configure the jaxb2-maven-plugin to use your Filter - and do not forget to add the fully qualified class name of your custom Filter class: ... Configuration properties for your Filter implementation here ... Feel free to submit well-documented Filter implementations to the jaxb2-maven-plugin team if you feel they ought to be included within the standard distribution.jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/markdown/index.md000066400000000000000000000113711351100213400255270ustar00rootroot00000000000000# What is the JAXB2 Maven Plugin? This plugin uses the Java API for XML Binding (JAXB), version 2+, to generate Java classes from XML Schemas (and optionally binding files) and to create XML Schemas from annotated Java classes. The plugin delegates most of its work to either of the two JDK-supplied tools XJC and Schemagen, through its [JAXB implementation dependencies](./dependencies.html). > **Note**: This documentation is released with and valid for its corresponding > plugin version as indicated in the top right corner of each documentation page. > Care is taken to make the plugin valid for all 2.x versions of the plugin, but > the plugin configuration is *not backwards compatible with versions 1.x*. ### Upgrading from version 1.x The jaxb2-maven-plugin was completely reimplemented for version 2, which means that some/most parameters work differently from the 1.x versions of the plugin. The plugin's configuration is therefore not backwards compatible with the 1.x versions. The usage examples below provide guides to configuring the 2.x version of the plugin. In most cases, only the source properties (which can contain several paths in the 2.x version) should need your attention unless you use a nonstandard project layout; most default settings from the 1.x versions of the plugin have been preserved. Another source of information can be found in the integration tests of the plugin itself. ## Goals Overview The jaxb2-maven-plugin has four main goals, listed below. Detailed information about each goal can be found on their respective documentation page. 1. [jaxb2:schemagen](./schemagen-mojo.html) Creates XML Schema Definition (XSD) file(s) from annotated Java sources. 2. [jaxb2:testSchemagen](./testSchemagen-mojo.html) Creates XML Schema Definition (XSD) file(s) from annotated Java test sources. 3. [jaxb2:xjc](./xjc-mojo.html) Generates Java sources from XML Schema(s). 4. [jaxb2:testXjc](./testXjc-mojo.html) Generates Java test sources from XML Schema(s). ## Usage examples A set of usage examples are found within the following pages:
Example page Description
XJC: Basic Examples General usage and basic plugin configuration examples.
SchemaGen: Basic Examples General usage and basic plugin configuration examples.
SchemaGen: Post-processing Postprocessing of generated schema, such as namespace prefix changes or copying JavaDoc to annotations within generated XSDs.
Filters and Filtering Defining Filters to exclude (some) files from processing. These constructs can be used by all Mojos (for all goals).
### If you still have questions ... Two sets of documentation may give you better insight in the tools used by this jaxb2-maven-plugin: 1. The [JAXB Reference Implementation](https://jaxb.java.net/) holds documentation about JAXB and the XJC compiler. 2. The [SchemaGen Documentation](http://docs.oracle.com/javase/8/docs/technotes/tools/unix/schemagen.html) gives a brief overview on the SchemaGen (in this case for Java SE 8; compensate if you use an earlier Java version). In case you still have questions regarding the plugin's usage, please feel free to contact the [user mailing list](./mail-lists.html). The posts to the mailing list are archived and could already contain the answer to your question as part of an older thread. Hence, it is also worth browsing/searching the [mail archive](./mail-lists.html). The jaxb2-maven-plugin is compatible with [m2e](http://eclipse.org/m2e/) and integrates with the Eclipse build, providing incremental build support in the IDE. This requires m2e v1.1 or later. ### Defects? If you feel like the plugin is missing a feature or has a defect, you can fill a feature request or bug report in our [issue tracker](./issue-tracking.html). When creating a new issue, please provide a comprehensive description of your concern, preferably along with a patch. If you do not supply a patch for the problem, it is important that the developers can reproduce your problem. For this reason, entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated. Contributors can check out the project from our [source repository](./source-repository.html) and will find supplementary information in the [guide to helping with Maven](http://maven.apache.org/guides/development/guide-helping.html).jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/puml/000077500000000000000000000000001351100213400232265ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/puml/detailedFilterHierarchy.puml000066400000000000000000000020011351100213400306760ustar00rootroot00000000000000@startuml interface Filter { void initialize(Log log); boolean isInitialized(); boolean accept(T candidate); } abstract class AbstractFilter implements Filter { Log log; boolean processNullValues; + boolean onNullCandidate(); + boolean accept(T candidate); # boolean onCandidate(final T nonNullCandidate) } note left of AbstractFilter: Provides standard lifecycle\nimplementation and null awareness abstract class AbstractPatternFilter extends AbstractFilter { boolean acceptCandidateOnPatternMatch; StringConverter converter; List patterns; # boolean onCandidate(final T nonNullCandidate) } note left of AbstractPatternFilter: Provides property setters for\nMaven plugin configuration class PatternFileFilter extends AbstractPatternFilter implements java.io.FileFilter { } note left of PatternFileFilter: Provides defaults for\nMaven plugin configuration class PatternURLFilter extends AbstractPatternFilter { } @endumljaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/puml/postProcessing.puml000066400000000000000000000006211351100213400271460ustar00rootroot00000000000000@startuml |SchemaGenerator| start :Execute SchemaGenerator; |#AntiqueWhite|Post-Processing| :**XsdAnnotationProcessor** Add XSD annotations containing JavaDoc from source files; :**ChangeNamespacePrefixProcessor** Change schemagen-generated XML namespace prefixes ("ns1", "ns2", ...); :**ChangeFilenameProcessor** Change schemagen-generated file names ("schema1.xsd", "schema2.xsd", ...); stop @endumljaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/puml/sourceAndExcludeFilter.puml000066400000000000000000000020301351100213400305230ustar00rootroot00000000000000@startuml |Find Source Files| start while (for each source) :Add all source files; endwhile note left **Sources** configuration may contain several directories and/or explicit files, such as: src/main/xsd src/main/foobar src/someExplicit.myFile end note |#AntiqueWhite|Filter Found Source Files| while (exclude filters remaining?) :Remove file if matched by an **exclude Filter**; note right **Exclude Filters** configuration may contain several directories and/or explicit files, such as: \.xsd \.foo end note endwhile :Include file into XJC / JXC compilation; stop @endumljaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/resources/000077500000000000000000000000001351100213400242635ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/resources/images/000077500000000000000000000000001351100213400255305ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/site/resources/images/FilterHierarchy.png000066400000000000000000004575251351100213400313440ustar00rootroot00000000000000PNG  IHDRBT% iCCPICC ProfileHWXS[R -)7AzދtĐTȢkAEEEW@\ ]}*o|o}sϜs?7=K B } ILҟ$@j ##?UKI pDlk\]Po0;W VB&Z"R(_ SY,a P*jDFCt:h! -Gнh#z^G{З 0ya3E`IX*&bXVc-__z~N83x_okF?oA`Ap%iل"Ba70\QD"A4!:H #$n%6ۈAA "H,R.ttKH'm$2\@.#!#_!?#)ɹEqʭ%"wYWnL1Sb(%rJ=孼ybrgPͩiT1uFM}Kьi^$Z.mvQ`QXPШpEᕢ |2Ń䔌|XJ *(TT+(G(g+Tޣ|N IX_RSc:F7]S^Ujjj>N55{89jjGzØbf``|={w܊q㮌>^K^ޠ~]S_#ScF}M\\slJSUǻg/`-T\+JkNZ:ځM'u:^::uu=tyu`1Yrfs@OK/HOCSoHD?V@A `Aduw䌜ҍ61`lbo̸III=Sii53YV.s<ݼjhj=0eBՄTKo<:ˇV 0&W '&M\;oYֻڨ؄شؼ5eV^-k{moaϵ@w̡᫣бޱ)iMgUHg].>.\Z]>:p-mI&vMzrH|e;{+ka |0@bNXB f8,Fn}f& kNnpp~xSXq?$2'))S*<u&=3zO1wcMcűqqj>ŗ$LLXp!Q3؜DJKڝ48ꆩM1dfhȚqtL̃Ʉ=_X*`Jpʖ/{#%Njur>OsO[֗^mؖ!3":s8+>!}wҙ5gVBP$qِ3 !\UxԹ(6"~Wqvs\k>wgכd v,D,l_dpQ5K(K2\*.(-x4~iKvǿRWP$,mٶrv+6V)>_b]RVe%{_m~-uxUՎ+X빶T43asee6R677o2ܴfӗ雯WT4lڲbˇW**io+y;o;vw|+nיߜݭdj~uOMTMGSm=:q]i{kh(=Bt>XЖōHƁ#!G[ZaGu^kQQ>|M"wO&1T詳N<}Y\9|Ƌ_rtӱ.IǮx^9qk.\}#ƭnz~;;yw.GW|_~UsË}~ɗ§et>}bޗCE)C{}q ao5V>9}5>|rtsgC5-۽aKȒ0TT@Kgx(_RAdwF)ew48P@b6#-9~xn(V o1o U8< 1090 904 ;*@IDATx ]EOk6@* $uEEE _u@7 *2 0l JU"=tNU{^:!NWnթ|uթukh  @ @ƌ  @ $B @ @5H&P@ @Hp@ @ 0j5KM @  @ @` 2j@!@ @ =@ @!@"d,5B @ @"{ @ QCDȨYj @ @D @ @Q @ @@ @F !f  @ ! @ $BFR( @ @$B @ @5H&P@ @Hp@ @ 0j5KM @ &pwnj ̙3gX$ @h'~? @ @`D(ZlBH'0gJEj+MYD}qz>S:fVͫ}8=q:>e_+O-wߒe7ewyo / iVk@ l4$B6ZCK>w^TCB}*WږQHWQ@ڊ'XƊי; 5 @x1Hj́6 x "A!P;0Q֖t 4O򖊪\H$Fְ)ԦOGtfssQJ<6ϻMsl1vT g>Ӏ @F&@"d#F= *`LL) I[^)%B[etdIL ~ żvHuyܒ"ᄇg:J|ACH  =6yisiA @`X VF 'Jb&|J>7%R* _gqTᄋijon'lT @n$B8 *ȈEvr/KDؼ|-=.>ogb,`%$o 1?bj+աhwWco67c:=1>d.% @~$B9!BzhJ<&T6O0%6Ggʉ,'8hG-`o{ymR墾xɖh&Nj/XJ=1RY#Ωub%\GX޼VVWT'T lshA @` qXWcF|i`:eEBF_ /<$=1"bI}+eAi&,M"cF?;≅NIz.k㚕:u-}Y_g~y#8^:kgT]n  @aGA@7~y>z5ɱB,1kL,ݭ*͖Pk*k'zW•ɒ+E^7 ٲmBU6~ Ȉ_9IV[4H=e}Q*.ZLfWޮmo~҉)lto@  ;!Î@}GcB-yx[,/?y7K%$@ftPUs -M&&q+eҿɢKnçRv~6LIhluƫ:Q,뵍jg}flNOE ?3A  @6!:&!z|7~[ީ4I[2&;gQ^ߩ yt۳2Srӳ9kA^l%,/r/rmEzzdk-oZ_!_a#_T8sG c@6G&etJòh&@ MIDȦm@#zVt~Q%Iۣ$q`z.lLTn1k[lcN[Sa^k6pi,{aY%mͪohBlq˷Ϯ^NDd _ L9—P3@zj]6 O_O$TO'*&AleH}-rktws*_'tibi(&){ߊ%ǫZ;Eν7&;*%UI˾|pϮ@֙ 'R'`L@ MADȦM@&ۼBzLG1'`' HmBڝ#?Ym.&jr-m%qx #npeس/$3Ҁ%z>'m9_6'?5՚Є͔ڎI޿\[9}rVh=Y.!8稯|F^Wh'CʭiG}Z޹GgJڤS&YXmO^G|C @` ~XdgBL!9P̰CJӲ3Nidm\Feq߽6Qo{Oo~^*DU6t$_h}/f6y.[;4DvYAvLJSsGlk JftcdxIo?stxLpz$W8!20d  @BDȰ` $B8  qc_H[BYZĄ Qj]Pln6̖?wTJv%Dѳ+KK{[ٟ%D,$=&UyMw4$>{jYuOp)9{JKrYδeW[&2c[1IOB?V8/]RA @` IcE H芽pTCE~&5Y_Y'BhoӤq떮%m2>":*͚hIID(擂а UɛBi&Jݖ\*uu 5atȁɮݱgV?"m{e\C @`.؁%NTQz_SN+Mtw j$ O`m^ӿF&쀦e ~;' RY目JVcY[2=aHui$)DidQqWʁ[Pxs$ LYNah]NnL\Gπ~ц @0 210); 6)`pKZ--M,[L!c&6\?f,]\V1[£ eCfm}tnaBr6c]뿼67:(&gū]i!~gzc$[][\A:Ts"߻NKcG_k%+,_gf?6\ƮuIK@ l2$B6z Cei Vl=oۘ7=wv-.yNMRZ[Zuݻ77K:7p^S1 滝g8r"!n!'_r|Insim9ȝ}8Kx}7S.]ZFX*UXp>YOTYk@  2<x nk}Ll2^yzb9-ޥQcs^le:Sy *}}n-W)--:Gy~ sD?r%5 QGV}{/~KTd'B2kX3X \@ @`(6;3vmOLOO$V/_.}HVd|gS%wr,]LX&vq;cg6;o[]]~'~.^"}->S&veilhq|Wޕ:iyO߮:$ կB}i/@  ؀։@|Ahmlǝmĭxmcv0Yv„K˗ʲ+S::eLVY{11rʖTHv#i LDMԀM-˯Wzzcq4ke'=tT9:rǃHO+S? @O`" %`S /d|k*nyㄽO}+ K4iw诿" cۚZe3/Ĥ4Bm> E/ g 0{^۴b{]6Lݞ?/Av)U}M{/:*\@ @`>X!'}Az:r^%utfu6_ 'ulQJV9~JR\SjM : @ 0<H g@@`!V]:<r{EBF6]Wn?k=\NY ]v!B ZK*l@( @4HlXjݾ̂e; فb3aLums[]2!}DSK{sɡSZ0q{&!U}LXd]NnKS!ߍVY @BDȰ` .›9ҳa߭m 卾' 69~FމrAeQڙ4p_fbAgtBw%сQFJ @&!@"d`( P쫍ykK4_8I&}'VԎ9qA3&Bm:LDu;) }kWg}ŤGh$ hzt'v @& @"d@$ P@pdD)Qoڋ'A{.Yۓ1-BBGS&Xm%V>Ĭ oxXP'`bJi @EDp (2 :Ayy}4żvœmBՠ*d.3U8J2W26 H734 @ 0|H k,ADH{B?iw 4keZalk{]yug @ 0H /oAk!n0_jۈnF>ZWuꪪɋNRvle}Nz'<œW%rYC @f$B8 få#!}QCEVgj^[ruj-Zա.fƨ&.[(_Tms=^[w=`BuG6m&UYlQm+@  !3Nvz"c%l6TYm6rr!1 u&`GLtԗYB!&:$:Bų>gcxj+^q^1طێj%nVԴ?!@ 04H G@C@` @ * @ '0# @ @`"k= I`Μ9 /!i@ @qp"q O!@ @@MB& Tt@X?w>}w0g^7i@ @E 1xݵo ~t @:! A@CGN\-A92tl@ !k D_)\lg4 @ BDFR@ O ԟ @ 0H Et@XN[B @HD:B P(q q @ظHl\h PE`m'?6V @ @E 1wĵp*IPC @` آ@u9.2UJ @֋…0 G` S!N @I2 @ 0(!"BX nS!N @COD3E# */NjSe @ @&!5 @`hiʩ'A @ %@"dhy @ 9ٱ!s @PЀ 0^iS!N @CGDбD *Cqc(tT9 @F9! |@` B5 @@U$Pr @ B$BF2 q iS!N @NDȆ3D *Y4 @%H&L@`x iS!N @FDȆc6 *] @، 4Ul a%`e )4oz״uC @MDHm.BMs;3{ @h'1 ~@ @("@"d-6B @F;! ~@ @("@"d-6B @F;! ~@ @("@"d-6B @F;! ~@ @("@"d-6B @F;! ~@ @("@"d-6B @F;!lJ;nJ؆ @#T2&`@ @F%N @ ID\w @ J$BF4 0RB @Heu0 @ 4ieI@ @@ @X&6WO-ZC @X P@ @ZZh @ @` 2 @ @Z$B' @ @H5@ @6@ @F0!#xqp  @ %@"dhy  @ LD^\ @ @`h Zh @ @` 2 @ @Z-Cm >wN]qd!@ $TѲ:@ @42$ @ @CADPPD @ @ ADHC,NB+?-@ @Cw g@Iin|Yjgj @  -N -OA @ 0 k @  -!Cm @ `$BF @ @CKDD @ @#8@ @ 2<@ @&@"d/A @ 0H -OA @ 0 k @  -U6@X;8 @hh@L @ @ A! L8 @9s6~C  =2L@ @%0%0g{⭩Iɷ&Ѷfn{H·έ=p~V 3=DWX%fwuo.Pvi廊k@ JD]܂ϫ.qצ'.F߆Um(d:eb>uu'!~U.:A^WbuW, @H5Cx ">͒ iV;dck년 xBwH>)oF $6`32IHln.jSBqUiyдi.3f ${ξ|r2…4b|Q #UL]4!@Z.ZTycfsOM4lSN4UM ,sTmӶ7}杷}ܒ"!;]!Ƭ˨I#ۃakLb|6-@ F#@"V !P@xY34^Dy;E6:g$W¾ۡV4֦zG!JWi2eYmI@ ЀH42Wmꏗɾ!Nub^IGBm򃎛Aۄd?u$( rEyo[ҤաCb$^1a-U1Пۆ?R]GAa< ? @@# ҈Ao89t&HƾL`BEĎ >٤9QaEOdةsN>W_})͗/_1r\U;8?o @ iUg$`ZY"qO>*oןun{ʉ4χ3߼:~xlf `p͎3exne_@sj>(u:IM!@F[1@]~*7qT߄jrRwxmӅw#*KV-1"e뎭ȶZd֔&e늉 mO oy|$[沩pm { 'nU%1럯&-@ F#@"V !P@՘C SV$k+dE&uۮC۪_hzxfV;볆gGLlc>ַx]?Lwݙ>j+'Xb|]_kՄ= h{R @\7q[w}bY^|d%2f%mҜ;M+v"=keo/ܿ\~yV!oO B{c0G_lÊz_/]y;e{lm'g26zyL Xt&mRKЂ @h $Bc@ O4mn|'2oʚ5!Nwu4Y/M??T[B.k{2Qt&Ӂ i<UO[G}\dlgɉJWzJ[ɡl9[Ü^g]f$  @i5c!ĸz᭶bg?|zHrD}57DfE:[3^ܳR!2{(SWmxOҴ7SCv/;[:z@Q~ߗodp'O^M{h׋m[>Zxp:b:=_tjmܧ좺V[gΗ˿|]==2-@)f;o-eco=`}l(ͥVY_0%?M z5M @hXw; C`wgU5_(VOKE_ S'Oz HslS5z6J[o9mUg%MFp$sz<bu?)',W6ϊY}|Q~ڱ'mV7~B"ꬸ2UlIe/R ?9x{ﶼX\vgB6< ɏλPAS_e*yww+'Ȟ.S5Afe?y_0p-;WZ{^o"?o{"  @Q iT&B4jzu_{Ȕ-&5 ҡIqaX&!1`-ZezoM.TDG&+m[Gb;\=$HJI@LDUI^ dlb>f{i4CfbMi6ԗ@{ښڟ8=L vlR`Wx*UgއEp'~59g,Z2E9}5JF @Ap"A 7!0hF9yH<Ŀȇ1=3aw_ŨRzIOXmb[­uݔNygZei}Unw2O r>k;iW}:y!'G癴@Vn?1==#/ Ԣxonx_%c-~dR g@*WtEvuyD`=zc#b$!ruDN kxb  {U?91j@ #@" !P=hem0bZŒ $ȽJY&CmL==.SdV{I?l{'kJ<'W~){OAz@IDATwO~Xܦؼ( ' +6s봑F=ZxZ~x#rĉKvTP)R{:'ڋ'ϭ^\r>"}&zWKdǎ|,wjjfW_\,],ԟ#?浅N=m5AJw@dm se!@43jMm.m&8m2RhWy[>-W}߈I\Z'}LwiUqn/g]>G2I[z2OZtrI}rao ~|\h?(JuU>}䃇+U穻W9 ~xuYvh] U! ly:E]D dͼWdټm97<uEI3r?j2)A>|1Bw'e!~99v8?\6O_^9ǏXycc:Z @A hL.nCLޅaӰA-Զy T+.YTOTW'AǘGX7{p]i2$Hql{zfMtzoۚvWv7m,~l)e)RP$]%oTUfϞT3 b_v: I(-씄_-^|$q2YI_>p_.TJmz5]%AdF=`EYX^n_{sQ3qG9몇BosǠ7uz̟BM-,O&|,?Y{$MEq>2WT$$LGMzC[c@ 4.kmPQK",%m}t7h1Bرb~w*[D17,{$b-Eɖ%+G.i~vmťcdOd1z\+qO|ƇSI_656f+Hi3Nsuy׾Z>>W&prȓ~'WpJcs~9&z*爦̖!9$q}!qg{tH}/ȁ j#rɩsg$Pʥ_'} t\+5T>~D~s>yvxT'.cnUwl [qH/}C!Mvks֧HO[xM˵rȩW& Z^V@{rAJsr3vC}6ORtCZO(b5@ $@"! !Pn0}#GmgWm(:U_9GZ+mr`yZ:j]XIlCc;2Q@. u|;h2c.7uk(ga~@aX:b3xEg?9'm/;{r3*+8%|wϞAs/y?J˞ʞ)өSTsz'&!쮴}o}Ԅ2˭=4Yf]/S.+[Oz17)n$d|ڷ]#>v @EDHcB`/~j+aSӍgo9 0Q=Z--mcØq/aV{?hEL,k8!|_+U1Q zb1 .~6xe21/}[|Yl#QG! Ы.d.~J(mW)/KVJ?l<>q=RbM8˵H6ȵ!9@~ᥢn#%>awBܛUTPۖr?Vi|i\45 ѷ$Jv%}r-]_;gIM]Xpw͟<~2o?a/iY.i++-mC"rY|C_[  Tp꧎r'?T ?TOŀ  @@qO!Z_HxmlW|ي\}˸^&˟޿(zײ)\;ɕdNܐrq5Ō[Э;\.u^uG_Icy z-i1OO|ȇn4[-fw?9yuia?)oo밉UE)p)xrAk_Wv2q9h^Uzem7^/W]qXF)Hյ%G ͒$cm~bU|;h$vҪhbOpG18LFV0RԿr<1޼χS3-F&\ɾ]OYV+kf @@6  $G|g=ގ%/7FOzVvur噻ntMFڷز,]seY/3jԦ'MDvDR+?ZwgQ5)FjEo8IѵQߎS="9?w|픽C2 soݬxخҩqٌpbvm˿sGA>Y;S?r;h'P|5 "džOqON~?Ou/>?!Ҕ`G뭓'|tp+@} '%Ev<:<P[V&ʄME?_)oۣ[VsAέU3}_ymx6^*#vj*>Y%վÁrS? y'[@tNI.xݶن8 dB-mS1^M.U>9J~i1[K~׫x<{/Rw EVd&]x keSM5hM1?_ INdzm"]F|V}[% Ǎ]_V\_}~ u˄HJ^ -嵧- /9]\P{/e+l'Yݬ{L:B6 y)n=ސ'A8U~_[Ms $mp#w*֙jk|`1y]O=l>Y;+5ձX=yVtM=fo[??\n/J,յ}.;u1V1su;SSw!. @F2!#yu E67Tm5Ia=̴_ny}5ɜSΒ>r ˿A+ 2cC3l/^9/מu&_zi 3Rȃrw*q/zrf;{bkߧ'-)/S߹g.~De5Ɛ{d"/ȼ' ǜ5c,{.;"GᵲSSY?6C_*o~OX_zr8RY)OwWgC:_U6=~`33XCf-u&0֓ύ8GJx^ 4OE?rԻ^}qrޏzd]ɇ-'^:n1qb=~! gVv @ !1 T8 (xmMmPT~=^xnLn]nj%=AqjcI G&?{pN~2;p/L'Wcn<2gG5GOCԊm Y7zctV%ɟH^$Ԫ\ԗ1z{/)ԋMM^\{%s'`|;!Mjl?r\f&\wӹ.mqՅGn/]{vFVЄɧ 9=B&u97OVEns?r[&6hU+T(}r+ WrG&N__ec?"&OS%r%?-d^}MGS<>vv{h:ӼdʺӶ|ȝ~8KԊwפx]v=#Zv)o[_()x7 @@Э <n܌oƿl&?qMm[%oڹ_zn deT^|{0]s˶FxA=uz0?*>$zh!+ iͬQlSbhIţ8O~9wKdáq韖_<{y+ Aw.M>}jr }R8q[&8ZNF+mH>3YfNVv!TtfxmM.Cסs-_.Z_g{K'oVgQ}R]Gf:ͫ[av# @ $BF*_Hk[;m0V+w, xS*'&*d%=NuT|,ۋZx4?*|'sY+~%k㷁bğ ^❁Ew#yuj@ #@" !P'B|-`uxb)ebmXQWWnl?4e um :+6V;+ N1yOo: @#<8!}2 庼|0 ڶ.$v0U|-r[I9JA'+`RuV[) 26Ñ/3-@ @"1 /!0(}Uj,IwsiߙA`y[mx'qM(o\ W]ykǭYlpxB;ӳįlXz[  @ iEe"Pg]R^[B(M %NLHuWtq_9>)ʇOٰSVGOrELU5x{®}9"_c|M` R'C,|A h$BF֝@Y)Mu4msjOصz]쳶o ;dK;eAXmŤ]XА zj+*$*~,E X 4#~?O~C @qiS B ?ʄ̂nR"bDݠKXq)zL '>!d."XeӁen.z HbgKUo5^SɹXK@ !@"A 7!08Moiq}"L+1JLCWqk#N¥ʦi(&Gѯ?8L3{`xlF?gcW<}(Rh{/@ F$@"W !P@^W76^[# YLFMF)\kڊ:Ӂdmg؜x3.o }4&Wsn $}3/*) z=ă05#>[c _ 5@ АH44jDCWpD;ERi RՇ"a;͎yW6e{1eQ8qbvL6 93+Ү_U` Ѳ-AflmÐothA 4!b :MOոWyۈZ봑 ֮~yiΪx"ngc]PZhƴGA0o.Uf`!-p@ АH44?uy X"BGb% ߞz…yYw3ug5m._TJxmv ulV⺼b{ƨ&.[(_Tms=^[w=`BuG6톎:D @Z,\Tvq_g-3f7V[ ٵW{R76gm[]+fCqbS[O{o@ F#@"V !P& @oPC @ ͝'B6&͞9sB^xf+B @PṖ @ @a4 egL(f2LV$H@$(&AD!@d?' A}$($A%,{B< J$@}If,NUΝ"_3k9uη;]Vo6/?      p#$ νIc|&? U     p;BAJ O@v~*c+$c@6t!!G!  Dj}_HV(89!@@ Ly]     $GH'A  *Bb89|!@":QYD@@@@@! A@kQ)$#Gȡc  !Й.#KP@@ *Bb8494\!@"ӣ+u#@@@@@ '8Br"B80 `W@     !)$@؟6Nq     ! @^+DI K@@ B@vvHۈ8@@. Z`W@     !%$@q0dD$! 0@8 v(     pprp8B D̝SVDI@ A  ZbW@     Ng  !p(vp q     !GHBfs 5v(     p`90~h  rơ1      R> TRGAS~SSթz     @qluTom@@@@@ hLG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dp$ya;$! p       I&GHG@       dI6M> @@@@E !QX<_~9-y   pzꩇN8$+w;:x7`GȻA]S*OC>U@g -Pi.X=o{77hu.}X>sʋ7Wݜq}VYa??BƯ9iqNy^n~_W$L#y!ze5kjq5-R?8̑mjcjw$ Ym]4u-~~5bӱ Si,#i9ALMOMMH۹oL?o'!>A@@!6Y߂BNk|!Z'(5n% +WW^oFaq=fv=I.)"ImDdzB&(@mu$ ʲu&L?\}K9׃- % buR{d"sʧ濃Ss7iu(6٤9MBpf$@@@!y5j;>c2&8By徸4Cs?}T򴢋YsAڨ,)b 3F+X%0j?0v5HL] ưdfG\lDNgK',C}@@@ o#pK[nv]>H n=MyMY"#1 QYфҷz>"oa?_& GfNps皿2tqna8^3#SN\ hu\H/AB3iO<#GH h6s %6]~o)7~Pneh_ugn]SǴ \yoDb *C>hK5ujg\x}+/t~K?J    yEΎQGԊQ t) wLKҡaK׿pOW_J!E0F8q.Oc5& qp |dJy翹g/(|#GHh{RȰ3pnnpo Ҏ ]8/fwTHI~&S .ߺZ\΋k%FYݤGrsFh釰,;s,Vpr:BuJr5\op3-ሻ   oɷj=\ ^!ap $ǾƲ]%&"{4G!zDVPz 8 -9G6\8p 8Bbs!;]wt ඼1_ֹƐ$g 0uBjB6-+֕]6TWHjF_׽!:y|M[N[v~7ae?\zmϊ3R   G28B)Vz.؝2"~$E͔ôP's8$i%h06FzV=Vgid\-R*DwF'5`Bx@F@@@ o7Cq荝8$*\:,WHtutVia_N udH/ҏ3۶Ac8ROHӸ~p\ceu|~^Bp8jLB.4v^hmoEOmx[Lˢ"*)-Ғ*aoH+/6Һkj+ C*TȫZj=L O:ҧB}*Wc؟c d<4_Lg|58r8 HѱX <ƶ<~PHT^:ȓ^{Nc;&#GP税b#!GuUm{[mqYz&mtrKGQaa!tʊ2*.. Dt+Gavi;wt %ԷRJ^]tc%֕XB\?F_˲U9qyVjo9WS؎θ[51}O?yNԋmѴ͋&~'t.H,!hJh[7pۈf'\hI]tdeKg ^ݕ @#$cSt` Eo㛟xyH=Ӧq+mh䦨5;WRN'8M!Y~(رnc=m/o)㫭 4XҸERMR&r}KlBZ4&ZitSrYǶ:R~Vy?dγ4yDS#pu Qm.~N`cSq/   yB 6O!yGc'7A;\F}N n^[q#LОUTVPc5T6'-\fDW-)ܷnQnн&XԄ?~vi*GOa|$u$H=;޿}'Gf_3:p8ڹdhZcӮfɋTO;ޚ_/lU9`=oزzyeqY)=p(:vq.t#b6 :aS=9w޳.븦W:Ԟԗ}ˎ:/uFU\/~]#г/X/ϗc?io@޲'H@IDATcٛXBWUg^bIA}-e?uNzޡ fM u}x6Y\jI Y}SPIp͑'Y u7=s=K ܔ?/)ԑ}I[ TM2˲MZbGqڭ`KW_2DOML S46LJMW9}tm7e|l_#~C_F@zIkд+79 Aә}7VONs}tyPRI[}= WYt$eٴos_{Mߒy    #$G5Mt{d1L2NBw<ŨRlNuH,\Oڣ;4р2һVnK FjY`GKG3n4<}8uwuŁw;J2âScc9a<9-ؖu~iU FV4{$:1VZq ЙDM<H{]ǔ蚻V#~gFX# H ?GfNhTя~.9mX/yKj%1OIjOlznG G@#$_F2q[y1=!7:5S'H> z l}[SԔۍMf}w1=xgbii3zɦ&zz ۶oL_~bT ikvdx})ԶXrOl06Fzz:_R9g C׾;qܛ~uik}ΑEr`͝>1k^SMݏ>4u:wi^Z'EFRNWX>iZwE8*ۯUVtq54|8ˈ|CNOm>ni`)9mwΟm2ypeA@@@w:51Xœ]ٴ,?^1ښ[U_1Nݨ&*,Q}iԇϤ'rv\^d+/*ުoy{# 6Դ {BߓWQd7!xt<vVU|q|$챴Nf8n>a&C1λfh1ݑbإ!ޟ9~G1@ӬAV &Y1s‹_2r90T$?T]0w VӘnbE +1^0Ǽn߮\oMr4g"3~N.ftV_氅IUk44V~ +܃ӞXwLoZnJKiРnԛ_4ƥt:w;N6X(.*ns:Ia9,[Jo.m-Կ5 3oo5o6*)<>#F"Rs^Ɣ6ü[]!SAUԿ;ot@ 4{nex2z<#HwlC>Dr~j-\k]9+i*,d:֩F~ÒG2XwOQ{(=\/Z635ַđUfҶ~wP^$cFoq#}pE,{wu. e?Վ @@@!6Yo;q]1Db>c|a 񢨄~'H9PūDSAWcRM X|yyVZDe(_[[*hZb mo0G| [{ocaREvm4^=g:p-2E+YE~?L󶼐iiYӖӵ6Н0: qHض\3r\ٓ޺~j:V}z<)WC4HE_e=RmFMq!WϞ+sLBĠ{аqtw--0M=||΍"YIAX׹%Dž:qHm[(<91#?saiUv&X9YYKol(kk?N Z.UB?e$Mz;Wkhw8}j8=v骕s>J'%4qyn9'͜2>" v릕<=@žwiFO~Gt@C8:g˳˫x}y뜥nEc^SMc^Ӯđ`dw`8Xv䍿Ep01'iNpr!y<^Z'us͓"#GHiF"}-w:@n8 o1RW0)jv Ȩ,@Ei1lE#//oY`hl]p٫w"؂nt{MM>l>q~-T,bgD[_;E?zEџ{ 9B[9V^`c-w}'3+ʷ{;`{-T(fL/ߒ/q;Ph]mCs<ެs{=s;)    oɷb,.sdzpƾ y{}YyVH 0-먰+zGHia7*)B(SztXR~䢎ץ\*uC,bBiYк]O:/ X>~B?:kk~z򳾞(N%Xntǫz݂КIgWN_?Vgڴ5P}Mtͳ̺0r<[a*.cEr/*ַC:!z+}T85ܐ!fy=B`ZygO5wsEIJ 1]wr[ReưߝoӿbO3eGƀuQE{qlUn"PuAЇS3묊whбbgt nWP1=?׎'~׍*#oӎ"zqZ7wWl߯C :Vb9dW8`4?Ek6^!Wb_Gf]ȼ7>>u+ü"k=e|4)K/.._Zn_OBjsؑ]lfn44~+gE/Ku0'{ -g4,J~ׇ'_K'ТQ(}y/+] A_ׁGT{Xg?<= fӵT5?{'S%|CjׄQim jlkzLIgE7ѣ/5}joiOT/ zs?[_Bci"ڳP#TdFA\փ̬~.gWUo$/YvljGrk>kiUq&z{鎏bdq/qԝU饩#0\FҾw7k t`SʂJ'[ppI .]q^`^;^Fy-1o^K=@@@!y6߾ʷԏH \߅ &ܦ{ڳ};6"EK Y?x~RK5+䥟#Cc PpOisfv-.q7ү6 }枂T%" kӯɗ/l*:g?S\BOOETLcǤBo嗫|G }QS0ٯ A҇>!h=o N=%As[Ї[ф?Wf)kz^Yfq|?*ȯ=0Ӂ}+h؈*:E_>*GoynצcC^<^B, 2Q7xyݑ8G깎4/7Ls{<~|uy2 jE7sλc=cl# ;灎/ i!$XY̹{EiE璧W{>Zi0y=fzv"G뫨ר1\N. 2hc}RUqh%~Jܴr }'b4x]0c_n?wVb_Yٱ#,}ӥ7ҔR?z4Mz|l#=6GEc*؆ pSFU*Œ[\SEgt1#uӪ:vzF b0,ͧ}Eo$^Ҍ%N]W[V\kWT]Ni!h]4$.';ILKtROB q*oѿ{| iQD b$HO' xŕYlWÃް;2UBr|]'Rք;;qԴy1n&^ȕCS>L[gZ=q7{W1*9SvϪr?'NYдNuO:.ՑDGُ߽.9m=J.GogHv~fՈmEt͛y90",%tQ1J~}k@vŮ]O߿s~xry7>Y"Ze)mL";2w*UҶM i5,LS/:VGs*!e qǯv.:~a*xɈeo{S{15h[ݓ>_\j{Ivܟ_Of >:奬Hx)R쒐nW 'cXCm,av?iaW\.ܸhl1Kꝰ_9m/rSg- je{؆XeٱLZx{D {V5vlp;:$A@@!3Z+7f1n.NBAnG4/Qo݇FMWZ:/w SQY[O{nڡ1T(Rg#7 = +fc'MGSLat!uKqvGnvJJ3vr"~+=9 Q%l^YX`]q(5ǚ oXA7>M>)EO8f/n_q1r{gwz:LIOWA ;^\3f\Q҆^`?C#ߛ;pHLoZOzO#"L('>Ɣ:C2fWL7/y!/?sV5fܹQ0?sNQ63ȋ3 s+s(<%J,ϗ`9 ƺ_զȼۯ,$`Z1+乜_Ɓ9sM%?OfgD(>PKyISYjZjTtMpA:EӖs]'ip 8Bf(sqU?-5s{ %I9(VFl`= iX^Qud;t'jhyqEUtn9tқnGoPwb_y(O\0VGV_PC0Jُh+}Uny7&7r m:Aq?6F0bi_7!?=o-%d[yޤ*XdWn ?s/}nc"뽕`"7ETYJOsy9muG,a,˟ڧimIg)mLŒ/yq~G Q/1ZϕoμDxO=ΨBmeX19iS1h~ Nu~dƟs}t$&q29 i [ E/#c.D4}   w‡4% 7.d% X-loL?8_fʋ5QV)6.M|ЩM#:c4:9>>k;)B~,6_7}U|H꺯îhTw:Щ:Wޤw=kOzyHʹn,} /7/l]j*{&|\ƍe{Z&uO i5F&ӯm_YnZc?w꽏bdcơVcURT? "6f m}iC1kw|59!>uv0oumo^M%@G=#y嚖ɳq8~ZEQX![8{6/;qx9=^a^׻zT~F߼d9 -~.R5mطOumOQ[5/itLS?˜p!VyZO@6ghZcӕoiE5RʼB]#!GXr֩B?wX#|I-]N\O_gh#_B) y/op&][p~-ģ^:NqL}%\"~M0z+~;$pUGǏe;&yT {Q|Q)=4Kw aE\_#ljƽٳwZ~bG7jG˫}? '%:%DH)*1Ow+빅s옹#lE=b+_zAw*>e9 *{7o8 * kJ,h8S0}3 8S!Ꚇswcq<ګK6';nyXqeZ&nz؄,\8Se}qq2U+O'"ގmߣ#X |J/aj9b~#GcnHdHf4\,[R-D-kώlxNkl 'm_e"Kd)3jlmߙ~vgvuǴPFֲ*O;YX}xH_ gם=t}.ۯI׎pTд뎦{2 +iDD2,ɧʛ?`;(JUIʫOz骚B_zеDB쐑NK+Пn_@kJ"f'7;^ew8C#W=կlhOC&mDP_W\^%]ɼk,7z3I2\b XЊzgOoԌ(ɔjZ;XS)Ii/EK^ib# Nد:⌸R7cӘOc-){-Μ;2_|ts0Mg/8 ra,ȹ#DoY,(d[.,u/uw"KYeYN;Vw+iXZ?K:(zKg~Z e?`g?8$/c   Qhx/H^H5 ]%ӔzUkմ]Ta,;Z"Mcbn^o::naw1cc86ݱnD2x ߲O;؜3N^bA`Y.'@]-Zy   ?ɟ~Uj,Ywf z#,jP!f1K=?ɴgT. ?\vF}Z-e{AY 0Μz˜Wn3xgp0ELH:_^E}d/\~zzw8Bkk4SMs2))Ir?K#{a79@@@!5٭#p2;̲A $>R*xYU%6E.q"*?[b ҋ`2;}n'ރV8Ts1:dBh r׏K#pkϾ^    oɷbO-]ĻXb:5IC]߷Uǥ/E$#m\-#A8.-~i-"qmorjk\A@@XpC5#;Bbw5^_9Ȏn~pȓX}غ>:ݧ'~: p G^|0\*>c6pKZ'ǸX曟ο?.   G&8Bq/B ay#oiZe-tMn|J,AB\U^<7o/29.eNl|2 ׿:|]5   F|, >!K A@@r<   yB0O        !9@#$_Fv$GHND       /ɗ       9 * 8Be$a@N9kxRm_B;7-ԾR")AkH H.9<"՞u5{[XXHETX`7کvok4kR!U4 *(Cd(      GH@Mܻ/ECUTխJ 3H6}ȮP4ScS#m^YO7{PUOL 80Xome3yuqt{J*.K!9fco)*)bjm;|a}r=4@×!ؼmYLk_mkѽ;U;?:8LzUE{w]i?vQ{kw;BP@Bu5=| ZKH)ӐhŻ2:A .1uPm^MB#GqV_o4/FJ)\r0DȔJ  ph:&: j>A7}$9v/sci΂궬NIa!MOPEty   G0Rȕ_*gؼ1Nnbbjlv4dq4QLaMgxKGҤ 7wޡrAa>G,.oI^t{GTq4o~gfDUz1j:ٕ־elC:Vq@:שC:[C!(8LԞx!j1q~jׅo/7}Jj҄DTGO䱟/|(Էx],.jzPCk=t9m%}Tct,;NZI `rQЀ#ioD;MOF5[J'"UަkOIeoNh$qd2mnjU]-xCyvSSYk>5mR.oӢB^QI9]n@qRR׎6iʜԖ`)Sӧ +ѓV4ƺjYzfSSwbp5>_&ۤԢ ׆L-7- tf ){6-M}Ǟ=cqb1x(E1!m$B=+_ACϼ{yar.?oGX+ɱtOwO--^+_* ؟OeػsK(dg_iSB]5S']N^~9]_$\3a=]xqӴYshCF7ipheMySi9z4:JSt t^l{D4Y/xx7o,Oh-WkOLw'NDD+H&/I,Ҭ[f^DO*i=zg]e"Zv˳@IDAT!:)z-'f,>խ\FWFvu]f3gVgw;Up^:}=_N–> nn1],X_d;&[wAK= &b8H*I޷imzVL/H-oDuDm;B.yCn[O6#k;/Fn=nݼP;lYa;bEf "GwUKPÖLCxNhOaQ굮gb~k}k1 \jׁD:Alniz:tUs.9GҹޗWG;M#vw!q X8yҩG5}Qytcp>s%4vœyQ}b^# +G[ϥcn9g(^vuJd>u'Z;}=>>H.?>]{y.lw(!o~y燻hCM~!jiwQ{{;Uv-yGD1 -ש˞Q%>6uݣ1%@'u87nXx|LԫqOFGȸO>'fJ^}ԸpQu.]rP/f208qtwЫ-;h3Ȯi+'Ѩ4WV8i Ђ3d{URWPN2^7嵐']AGO̸)|N06oXF{Tғw]»?Gӵ-4o 4:   #pVow#ՑQRB B̘'K&ځH5Gk*eZ7Ѽ>InZ[g.P }m`WHsdV d-X8NsP^=*Ѣ[]tMCe5gR~yH@B tT \r8a|γ_nj`Ӗ-Xb Wj'屲_,r~4*6,~\6a3ۤ"*K~b4n-wLA uܥ8B!yP=T޳T@i2:"@z]а t,bo=bt:($7;P;cQt¬ӱ<%gZk۪6JmĎa.e.W7%ikj~َ/]H揀5/kF' ]8HuSВQhc ٞ 4N_u?&\ ꖸ%oF:Q_Y&ҧ`z n`wiՄF@#ԇ+,MÝ(8FAA*B\CmM-GlOYG]7ƶg}wєdz,VBXw  Gc)=P~Qn^0ŬkOOYũl'yk%U_l?C\r-&%2 v`tz)XH)З"!! rS."aaaFEe{r&:}lt$7 $K3tpF@_i46u4wFc,S %1z2-~(yk ̒9+YchӞh4F@#hCE ƶ=.-6aa +jjkPMw.ɋBN9d@#hZ2U啖0pDbwƒH)7`/֓"OƼpEu@Jb~?GeI3A@fZ F{4125CՉkPTӒʪJ4q0-F:*^Fsۦ{:+a?1Yֆdh=t |.vnۄ g`TNI>ijZz쵢Ԫh4 =BG#Fv_s4F@#"cșVT^u_uW6íU.ٳfe;ȐGdn6ެA]ػ,F5ˀ6\uCY.:h4@A`58&x<k [OwefTUQl@3黑S.H!МѣGQ\ShZ)))h׮]PՆ6%}2Vk \>M h=FLƚmd^.!IFWܾ&}3 }zw';<*+i)6}th m m!} Fto:~F@#4OS?WzL) %E ^߾=6 %`B19i@+?yy_"???0|pѣIӆ&S3h4F@#ЄmALͪQ4"Gmί 1_Ւ1D; YIbPK5]9!9Ǡ {oH&РX6W|S 1xq;L8Μ9۝} ! fh4F@#\ jQ05IqYC$@AyME ܶXq :!Wv\5LT/ꊔc+_"6hlI6ju 6&vǿ)s%!l4F@#h4# !r~&^Z7Ieq]uCN$PQ6Tumg4ؗ)昃[\FuASߗ DE#!&ᩰS1cƨ Z !AV3h4F@#h2 (K1VsNՆ>xoÁ*lŖ4Sy_k.b*}lP¼c*-8_>,jx#n2kj(Ms,QI _~EbOBGaK?cxcLxpe7o)%ʷ6VT#h4F@#hz  ! Ͷ,W|,4ȶC4㻉/!4F@#h4 !F 01l4&CHὡ@M%APT,QsP96!_35ȅ7ITSuX%>fFڰsjƿE6 ZІAk4F@#X[)@f7YG>& Ɛ1S AT䆡ByRʓ/ABK,d~Repzbnif+ }IF2ӖKoPrƿ~!4F@#\ \=N8> ّ{p(7U**Bjt]-e=7P# 4(c_˴ܧC˴91VFC6 CH}kA q,"ǸG+Ch!x9q#qU1/hn+mx 5F@#h4MaȜ~vD*; ;?Xuc#oLZ[*Us=ͮfheYN!}U娮KqANkQ)ǎ pWW!*"#p8B=!jEƐbJI%ʰā GS y,ڿDhH#|v!/1Ŵj2p=C]d]UW*-c_ҙk4WPlk#> BŃTc+JnϏ?)5> NJBkVU(@h33b1>( -a6@cݻǏG`LY, S[aU ><iK6IhE-,$ m#h/P c3=RԞKm!!ݘaG܆EjJ8Fӓ5Fl4r&grc0bQh=% SJ*ΣՒL Omǥ/I GѸ'kBX_+jltzftXJNgTO}h8"䏝]a!{t 2OE4 */g hj+F@#hZ EEEM^y1 DLL+$޼y3Ξ=={.z᪓9GRG݊ TY9{5Y vy&1&1mhAlיç$D258Q%X!!,F3"gee50go}>.iG؋G۟Ğa!ҙ3T<+}eszh\@ԵiA]D rsuіɄ^=0Gۿ3M93O6X|_/ڇ?_#UIIK9ϙ@/G3LABGW$$#& !`$c ΅\r?>O<cF#\pٿ7Y-zqHt' swak_uv4M>0>t]3#Dx@=B^܅ B[fa^R;ux~ze˖-=܃|+~:C#Z`oxqAΝ;1i$k׮j ښxs8ŘݩIUFxxF%F9`! o gK 4W,iƿnrv)'Y9b>FAu!zzP>s De n:AuooLS\햬tه;JF{-lM6V1)Jsl>0Y%+ų*1 !ߗeåԟcW>Mܦ=47#}e>VƳ$ >F ÃUj1 TX b <,nz KFTYY?O]oxgq7n[AjZ :t9scSl3f F{x tqܫt<=:2O:w@_q>x/Ǒy!T/"m#QVQ#SmbWk1cyBBfuMpON wAAl0, џe4">/?g,;7ڒ&zŽ &q44곞Ohgo /Cmɸuh"$|>s/U8|!dg,) >!4\Ty1Omh ~oE@#ng_&޿>>cGAGl2(w3pOXp"J(),4ga.ӯRg;v +V8.oz lz{ ^{-c8rHu" d40cJ3ͩ,3<ѴG(9VOD|4"Q@ya)Bi?m`#Auhhk*.[I#*_H˪Sm$.Ty--{iTlyD$>*-(r}q:aϺX< #ѥk,62_6 YPċ?U96VG7Sr|CWDjJY^?UmϮHuϯ 9"X(X%=ʛ_23 Z p.1jtT (\Mh*\(w:߲hK@!^z|\tl\;t }~ʘ`7m1$.7=W(##}b|wE!2EjO1Zv]Q MU^9Q8sg5Ӱn+H\7)MJ[0s{),2,=}y/Au5~ _}#kkr@E 66V,6lX.sIW 7QQq`NhV'<6xxIɊ3('o8/u]}E +k.1W… oaݘ0a暺gZePϨ^1]kU7HMH50蚅 3 N('BzkIm8WUJԪLc<˭Ej)Nǂ[SZZ)Gcq*nW*:nC$"6dhGm"W+YO(:uEj{|AQ9OkNˆ*ΕKodsy%8x,&P}ۇ ~g^LZѣ޽{7[G#p:)2Ç_WqR-))4Y3'zTi9/ &flp$I?1/r\6HyʅYBL YX|nJy]ϸcv7l s[FrCk#D'ROܥC%r[{`Gf:wNhG eCeraąd>׵ŽoϷ>0=IW6vp`]i)pΫdryV'Dϼ8r1QEF󒈿+_aنbs/U6w F ^#韚7Xу0E66/73Q9(~?>|ڦR˫'b#{]G<3fh dq66l@y.}#Qz1޾E;33SxSݨbQ+,oC|Ⳬ]#&еSr;tw{b4̛p[7w坣tƣcT{%CoU屉H5uZYXQ90w?>'51kz]RH` о#+/x'`^dܜ#*BߵHR3<l UŌHšjvKy^dSX?d<`T%jJTxxT 1i b',cF$O |e3ҜU/2zp9UG:4v,{1y|Wn"dQK_}^z;`P”v l>oA [R{$sܲݮpȃ_w…H}KdВ,X䙾d>+ ;z[I-ֹxS_(c2vqAB<I8#PVT%8#ȅu ҵcZnDqm"1NpaKoʋN޾y;7`Ldur4Ft!,\lAOY~2 y4|w"͘ѥxnnWUE6elb{bQ||TL?$XL9OFR w? >hyqiB6 GƂxn:96 #5ɍ ̆]ʣn%q1Ax,_@/-TѸ~&H2G#l=X=MY)QM]W%7"+7V+ SGFخ/&z{ ᯯnʙӗÌI s1cnra> 㽿mSKi?wp;;C3&`D8,(%B~{뭷gy- ]FUmuC|^_j}.ֆCc4hz7xCo|Œ:jWI%JRiJ$`"']򭺚yS_YuOi0 2/jYP.-{:cA_7ݿIܵ7b= ލT;/ϝ$O]$O_UKx.ϓ46[`mySEE?cn@oYTVZ;]mb׺͡.%%L1ΛUUW6gÃH|u ɧ'=HsoNůg34\9/N&4\@3d'9`5kzEP,@a ֛yi9Xn>捐%Ht.:E9YqbXlN |ku[@3 [mWc;]hːv&zgw1w=}KnT(dg}4e' Cg'o٦7QL+Jl m4 >no.cq; 0&&Ħ`ڏg.}Z$ }iCVaɦN*|.v?:h4@^^8v? z/(K/ .O9CkSE O aPQBn ӵt#ǖ`\,}I/GnHrUGd̺xdyb9[wD,7chs{' ѷ=+/@FxTOAoTr߻Bee1'jye_ i:c|rgz&~RUBf8pX)|u0 (>< I'H(k" L(a's̐3wWpzu9 ꕏb*`ş 0~]+É̑ n*xƼ!}Ix2,^_\*Q_BBﯩuD:zxһobp}^gƳⒿ+O)~~YK&X7v*7Cx|K?P}b{!$0{ӱb1:F WQS͂oa6xEh.gs7AMO$ =~FQr քm̑(݇'S͘bHo7 G3OT}2>= o<1+ZFAw"mX BgKYce<UA?N"םbN:ؘ0c5vc݄X=o'wɮϮxa fVgaN(`naC(qH+!`D#C07ژ ~A0}}v/V& r>=}"duw߮G>&Wz # >ZC=6Û؁0o }Vƶ?<3m{q^J^!2=  ףl=vڙ!ԵG[i}WsB:|.88lk'Ƴ\;UFN$"Cd g/hB5 n=DhV)>}eKZs)0-)=j&lkןRtR~8&MF@5ʃEFߘTDթe3W'"E0&_GyN= &QlT:$K!>yH{TO`~ v49Vt)Z%;A=0]tb=4ڋFp KRKo@0Co2~#?*8$ah\5m)kRsϯhwk=eL<ܕ(!хa6MJW.62'teT '&˛('-fnghTɋ!8O^"*?4?w%CH?8z݂uSiٲ5b²Qd6/ |~.7IO31ps1yZ<<]Ǧi_k3͘1 .C{dz;o0ݏ=de܃Gy{H!/OxM[z"8l+>5̕mdWO6l=Ec5?l,d]\:Qr1Nqu,\̝ v짷S Zg2q+lΛx@X%X>-y>4>vyUWaԘ_Z1dff&$}FBxǏ jqL~\~ +IR=3#bZyijDMBiő7ċ1'|qcz l@IDAT+*ݮO2~DLzGp˲L< PG-r E".U>Qq8d5.dtڊopF`|h4_h jڢBb>V$!Lxc7sVb"d}7V,׶%;CNe(TӉ*FT' Q H;% &Wr uV}ƴ~ *^dq"ӬSu >ZP*K>z0o?a3Dž3q|i )(6P_.$PY$H<"KՐtD}SFQ/Q64@y[G>$k0TP(BTNȥ~R2??}NSk|UbE9:b^d^-eQU"S0fy"E~vvU[ \HybI9{+{"cx"c1d,Y'2LC%/,q3cq+`t5Hcibö=ۤ R4XfpuȉdnIђ_b@pEmj^&'N̙3B:]iU\.lܸO=01|o{h3$|J+ו?U9y >sdAI8O'1ts* ­Zt?M>7_;>OF_MrP ζl^MG yIY <#?mŮs8)Y%lsMƬ5f0:e$8e)}V1NF:4F4aMעCH"C2 mվF8MjY? 3mXy\9&,bѥ?3[5f_Y|9dل i\jBUD0gjSZawČ x ++o]㵝/83yh߮;5=`;RMa ~sL݄nr4T3t׎^q.VNKVJ,`~uO9/sl! n.4̽:YU#s۵oȗ^>Qi bLZq?F6U|5ܾyc?~.:_?ۍJ;vbqb9ڰs!: "1~e;6k^%Bb}}'KPf?oG,emkܒ|a[xlҰ{͟E9kԨQ۷/^x:8OΝ;r 4W:|,5TL{8Gرc 18SztUePkt%v}\!"ZVb:`ǰr( vfYC{o2B +ˁ'VU]QH/0(IVr&OOmyB W )Yij\Ex[= )aM%wg46gN*$,^?uNҾ>? 先ev f5CxksG?@}(ߞ猦MhP6FU̚9s`ci0:pp| .,Qkr0e> /CiHoKށg-m3Ҁ1W{7.i͐:潈kL{Kb1B7Y?h4xt,:'MȘ)7= 0w>/q@XΛy~0{~D$&lAh̛qnܽI %yMkD#2:Zw<R.]`޼yxVRw2==ƍnj]hW_}{5=zwމK8 &42'ƜgL5剘 +]#lU -(w?(ҩ* `HF:"6C-єUM»FEƱAbUW;:ᩱqHMz/E;DۦIiMɞ㫿X" :c͓N995h|)Bl$0aԧK`!II“;oL2х<"X.!x$3[+ |cawSd*:dU['h4-"i ˳ґQx>[.g~pRL%>-k<4˯\%ϸ<ތv"ީ#6xMu!"A'cA^Fա׆\>ezHAZzkoQcEHMm zIZxˢbKP\h Åگ_!TPei?ޓHh. 7,o#$f"$–E-,ܒk+'YcYmM pVO/Iڃa v<:f"ۯOr1ul1}dذ WTۥv$4I',YOǐ.rpDӍvHrmo]pY 1Ma> )_׸i&8pD-)x] T/>O^吗bI 4HlڧO{Ha…⇌θ8|0/_-[#Ȑ!Cco<RP~0Ui 5yQ]bਠ z9WVDTQ]. Ĥz OLaʨ࿃#xGbǖGȵI'q)f5z0IFǼ8=?i'ћ|ǰb8A^&X 2OTmx~)?7 /ҩE[;`gњR{a>J"I2 9YVEcgokmiZ<[,Č;'Hx4navJ{yݡ 65:oLC\b@{zƊ-{dɬF]e$,YJŲ)܃{C¹iyՆx;]4C OkM,ܴ_kH2~K6>zK=#XͷMyB6ƆȅK TW\~h6a2->Lq3ᓪ|u5d A|#LNt2ӗo|:o<  ^M6"!!foy]>Xۍ`I5~|饗OɓG:u*5&[ꁔrm00 z;-n䧂 "")ԐD2^2dcy)D^Wem'{ɽ 6M庢>ә߮ â7J[۸GDb`yXu }X5!cp\|[ Ni=h(B#P5=":s)B:u+fϯ/]IEh]W]<7?FGǃKbwc Rӆr?j/r+'/\ÙdTaLJ^GR#ae [/?$-B!R/zc CtZ4)RQafmb3Xx(ĥa+r]%ǔ$l+RF1sG(@ ˍqHLkUb1uAl9ѿ}$6EoCQh; iϑ^- }q,clf^ܼ.dd:|ͼ MXl\@oࡇ£> vA#p%#b0r-!œ( 'S+1YQ5q4\JTD.pU&6jcދ (dprN$6X#:%1DZĻs1gXOљPtO7&G2ɉ!aC{_p=ծchW [âx-C2Y#GFJcb9]E󼖅(UXsu=n#R}G1yV'曑lڔp,w/Ll/kDfm7Hvxnx!3APΌS@ J#KoƄ]0tͺ3 Zn3{EG}9xhh\fb,<۳0:-KH>Əoul|I-zz-Y8vP^~gwS#X!!ㆎVtŇn,gV@#p~ o&JJJлwoL4 ;v@nT%A$C"eE#ϵ/7\@Ƕ~3rIlhe(M~N@55n2ջd0$!2qQڨ~"7ƸqcoGXBS G1iafXCǿ7ڷd-VdN0!юp' QPPJ6EdugKkRF@Un^0%`մK2} ^V骔~|l7ccُmm(R3RM1&Vf*|T^$gGGԁf'yk%UVׄ_㣍K&* c d3{r/iKv<丱UttϲAI1iLRm4DΗӗ"a!KnvE0tPdA1* }DYrCӝF}Z: stA8I5MÁ8QxqʲH߿?FyJN#d}=l<%($Nx<D^U:x_ڜ)'(V¯=46 ,آghR1U1XJg@G.r=876̥cȮjnz,)q.9 H6jĴ1F&lM4h]Rx'39 4|.oyzҘSեȫ.O)\5ּVZK'ЋA2$E3] &66F~siҏ|U`--Gg(QWv*9[9G`Fw}ujj~~ 4sG+o JO Kżѿ_u.z`ET|"}Pr7^B$mA !Ȋ A B 38B[Fطs׾ea׆%B85Ƌ&dυ}5f؄M'4ւv*L}&Ƽ 4#adN{YQKFdϫkkBh m~ :JF/ P(1̄O}YY ~GO#`ZZZF@#YͶ PؚED<;DuζM4q-ַc 7a 戲j龜(6bs QZ$ 5 %k*)E+%xޙSɳF(K SNB&YKhy&CWFoS*rH*4 MSM_:R0o/mizL[5G6lK VVN#p"9KMG4yPLd/YwAAGh4@"1`*&ʹwM}[ͱ|c_3kcBL116bt@\ING_Fz=[Uk)XK>(OgJD͑AGz &Z1՘7z{߉o"fgpuL ՗Qg'2KzGNeUG_Yn5B?5ʧLjuxw{ !$HjF@#h4#g\3SgŬk<}>gbÁ ʽ^l9ic. !Vu-^Ebnǻ=ʨ3oqWðPiaZ%!0q"U2\_m©vT|Igy H+}B)k, Sَh4F@#h@UEQ7n^l0qĒdJ2洨bB `aK :Վ DAj7)ɶY!-B&.:/xV-0VEkkмjuҦpݿFVv]B+܊.B x!e83sΜ0?p>sƹ)ӍyʑG0`j"@ D O~u u=`~7'^6ʑ+ ȩ ~mTP0TR5h^r 9t`('|Ao`m |)J+*fB܏(Wōl[W%M— T.I뱃.,E4 cTN+'7M31x+J D"@E W;NkѢu'W?.n0^-߻Ս?_4~.GD>_ԁ \w CNuMfJb ),! ֙Rō}0Ͱm̟,-y7q.%ARD"@ D{7@4(\]l^_Y{7OS -|X.dGYAG9q(mɂ ކyި wcM q^Ƣ2~Ui*@7]H۸M+$|]>Ώ@O D"@p?AݍMatX *PEo^rCoP 81Pxx~fxۦ q^ϱ mo> 8?OY{l꫈._">}ϟDž PQQl̅$~-y(((mzUUU!࿞sbcF~~>ѭ[R>hUIҪKI"@ D"CՄa KIf~!։#󛐐k PzYnCBGHRD!i5[a.\|tZYFf([f}:!4}PkaQD"@ ^AC*.#S17;;_|9 UxLp\ ;ԄK.^݅)5 @D""3\s6$wqRZ_Uó ^7Jh7V|NP /P D"@ U&$`NE+㜱|3 -蘁ٌs=E`?ˣ=_|42@?[[b|7;3g6[F]k׮U-}Q4J|AuQ @XMj? =Pv+sZ!L9ƮQsZNVҹ rkJPm"@ Dxc[f#aANrrW(xqMC<֣ ~ -gqChi]gԧ~Z)ݻG !Fn7$7So[q'{d-N.-~6=ifNmۖ!azUf^^627aZŴVEݐ@ RD\>W_}%Nq 0@N2;nڴ uuun7Sxw}޽{E<&&F+!^D^hjcCG.qS. ]pڎ;|;9^bQJkG5s21)!0+uuC=o-a =aӍY4Xe6h)s!tZs"@#WbǎQ6;L:U͋&+4yqa-Qffx"ֹoVU>UҮ ak!Xk#Kj+7)ـO 6 >n%NF{ecC[O3FIs$Wj.1x71;D}춙zb쎌J^:ʺ8sfpPlQjTs "NL+Ow_"IU1/!jTh /b;Da1Yd Oԡ933!v0Mr(*%?:tˆKՆ~Cl5 sQ Fסmؖk|Ņt?*`Mpr7mdI²;Qlv4R}G7G`gJ9CDe'd/Etx0&J9Z|ލH`1цqL|&o+j6\,a  ˶̈/) Q6b$tb ַF\"74lc#7Q 8́w ; o\ZWmR} /u E6.nŸ?Cx<4lUmo%@Ä>XHNp"&^ ðzQ+ªFMr,h9Uw"z#ȍc LnqUqvM v!Q=M5>𼓛u`yʕq>%IK AJsV3*f/+V ??_l=|BwX u9;7),,IL׮㎰/  &4[O?eVK|||ltI¶턐P쭴юBb 2i =tbv,:AZ.߄L`7nZ_/ X9X݈+W(B|ߎ`& LNCXn-+&"P 0sȑw\}6$6zM R]O៩j1,<߈6 %.ĆG kRpGOƛK%8 +Oǿ0&>ƁG6O8xc6eɑ9!:<. +t/)iס b|4"~.Ndc&Ր9w.Ƴ]1 eم]Vh@$OOdս>}س#U$dVl=mݎ<COS'sRGȥcX$MhGgsC|"@:87\tI)<3C^\2)++ëhoV)Ne@'$:0JH;_"\YO fIg֮.Y(n6HgmT> xB⟴eJ?>C佘Ȱ 3 yZ:'$#1M*e%r։yRFUfU R*O Lmi6K= :R^Z0Ӣ*iӸfP:۠cO )nVJ-,2OFĕ*ժ6kLZd'Qښg"eYAkr=ЬQ#i2gCn6dVN7:!mXhvʬS*<ؓ疺uyV#i iOjJe @IDATi{Tj>*\~?8,Hl|rСC(Ӻq~N]LT]*L:*AB38C#;GB[οO~b1@d]< E|pHHuH:3i4DČǛ[>l~7)$ r!)^Ґ6$yAS:gb U0I`GGʞ2jT g `Ͷ f6<Vi׭*LT'yY!l`Uvϳ޸dfvL­=MOc'2OϾCŒ1BvJ@G'wL;|grׯp4:p@9#GgP-ÇxA+7[éTtTo u4/TdnCJ"Wj=N|{a<⽏_Ftgp="Z¤ @C#E/hl`]_)P$)z?(&vi"8::崕8j{AB$-'ϗvH]`ŬXٹHڜ"̹!y9] >fMIç?D }TOat|4K%5d9t6\Pzi&Lwhl GA)s4e"?^@٣ ´iХK67)_Gqq酛pa[ntYvTwmYM!N)5- CT p2Wj*ĶkmH.5f}}a]Dd? oz TUue`*JwGk/ȴ-Ty%گMAHqalѱԪf[bfnZsGbDf_!+2'cvN'D!ig!X,r aΝ| D sw IrKؚ(:yFA,K3.GsD9GeφLzqᗿPhC3g~Kv|W}P D@!t%>L!5łg(v>N|(t( }% Q'<_:^uƭ6&ax*ڴ-@%X۵yWYuT+nrOx o!J"ԕ8Ա3C̣̅ ]CNRH: { 9QYLbXmygZΜ~aƛ{+salkdGVb݌XgDc|{YUUU,o~ 2DIk{bǎ`~LMvq2gi Ecjhv@8 G3Y"Gf]VHp^OV}fbxse$DA,6QܪDP4œm؏ S/6:T. bƐ>;˶x4R|`'CS*q0UZPζM1d.]vZ)bDC`[,r HZ. +T2lKyNvrbGFwמx;Z ly8uUGq4 '~4"@Gx뭷 ;;\ NJ+0|pu聖ֶӟ z3g΄:&ˋ_=>}g_j "ΩWKmmn[Ͽh-t5u\0N]8K`Rs/FP\q^i&5}׋[9>x9Î1<7sZ9ip!5=qiqd(cb"˄aV3U"0S$٩q8lklˡ%aF;6Z<,.$>\S1.Kpg5v BO8{,l(|51cCQ_Ma^yTV, /s hO "m܉m:Wksp釃^eHH'HSZ,ozExڳA旈bE"6zDhr1ɯ#'cE=L?quJS KnyhIg3ϻVCRe>Ѳ5 Sѭk֞g+֚ Hf~x}1?'rytJ hZ(/ @l}{w[n߲e O)̼yp׻j xkXD(׌\w@JBWEP@0yK'I#V*'7q&HPzC 1,K1He9Vl h9Qy7^yׄ8xӤ?g|n4`"@Xjd;+)nH C9D5 p cǎaΝ矕 99Y8BUal޼EEEb¬8@'@k4fמSJ<ǫE D'b?N&]kIC#3)V%PUU||嗸t;7`L:}ixÇw^i7@@!@4;haH oyv0Q2 Dk ČŒb=s:DAш ^{q bر'OTԳgOtMb{_>I.y'1|pe!Dm AHXEb& P DF "j "@QVV *,,L8 "|7\"v\wŋ _'a~4" (͇"@ D\C$?vڅW*#>5j"yyyxw) ߎ)St@%@41"@ D"zZ-233q@TT&OL+{荛<W UrT"@ DkM^~_Gݺup)+/9rSΝ;w҄@G$@4'"@ D"a\!݋:HHHIQZb,))K/hz뭘6me1:'D  AH^ D"@hkۇĉ5@qqq{p:/m{11ovB"q$8b"@ DoO?Ş={P[[+&7t~ӧ}OcָB LaGD AH] D"@hllT7ѣQ#Gp599Y QK"@!ް4G"@ D"g HQQRW2uTq c|WAPP,X~)L(B@$@n4j"@ D"v\7JKKn FhD(8wyWq1ˮ]]a;ijD{ {֚fJ D"@l\̙3J>DIHAA6mڤ s-׿̜H BgiD"@ D@!Ѐ<|8w޻woL<C QҼ%`$>>[O$^C!^4Q"@ D"\t T_Ǝ0äjvZGDD=tu,hD VH D"N8!_#T9c^C|<~86nE.#FO®]D׎y0p@[E)LL;cjOJ!.BhSbS0?kCPY^-g||O9=1,j"@ D>|}z`_ccc1qDujyqt:_gΜYI%KjYΉ$Evu'jqJaҕ>?o L\×Ѩ7B%[L8Y kw6N^2`7`ͣ0b jq_i@_wS_yMBF<2i{P>!>ڿـf L5JwSw}^ɞLDXx68/ԍ(E0.u| u`E.VlM菹)0Sc*Uv`d.FVSF_~ 6|paHΙ¼e̼y얧 "@:>Rug3"D:vExtn{8'*݉gk)ρq39 QvHuz',p9o1Ɂ_"@5^Mbr'bnrTTn]? ]u9o؅ۛ۷O3ϸj8Kgff_V޽{cΜ9ٓLw)F< M6 F,FDxG_ wOABѡJKD A8Mn*ӥ ._mP/%qzŻ#z#/2bmSڞ LtC'1lza oLS1;5U{8WGI Фea˒*~Tn]l ؜WYlu6.yxd^=>[6A%Et 4E%P^^ =zT+p _IbMaCTςC"@^+"m.!V65ګ}b7%@E6iECqHYQ=*/9}{LjPS1\4SMj߫EYk4>6,;n )=kgCt‹j4 Ck PUQsYR f9MQ FWò'ƒU -ƄTkio%M:vء؎}#GɓDff~ b M~*JiDx)xۛ67][r†TsDC݄8q:ٵWz~w(ƍn]{YuǶuUkޖPWmhVfɈ21C1jxZŹ&`;B:(q2  >Zf7.b-ldeF'[I80cEa4ӆCarQqGLg`g*eG:ZmoR5qcAY8 }iDY <9ӝ-"I%%%زe Ξ=tq[RO ++ ~(N2z CW`{|P &ĞAl 5B,?rSgqk5f*bˎQ}1m766EQe8/&^oVIfY+3OB" x*2͞GNHKv1YG/ RU^ a%ОB)&UNKQbFMJD)W;wTj8MTbf*-ю-@"*QXnRSS!HDDfϞիW-B]?OB&QfͫocjEjp`CIJJԈEd3VD/ozD;o@c8}*!Q~X "u()E%YwAAшC(*%`FaDlկ,UBkN?#GZM^CO߿X;굲I 6=z4NJh iD 03L8䢔Y*9 ;h'$YWʜW#"{nYoqK 4'C2\4IiYv84ì&M:Qo^lدqWj8;YQV(˔NUYV;'elI*yfڟ!h-rYyLK mHIT0vUu"KZhcjƉ$QU:u9Vs=sz)CbtNncy猭U4.ؾE3|=oQ:[qlGl][׵My &6?6xU[nD5_>#?^_h1<Aᅆ { ;w[2 2" 98=cKBH &Lءȸ$&Q7 ~΃/vc'?*snk264O*R2'm3233n`*;g닶 A4)ڟYHa+rX:yڑi`9>ÀjX0n0gL;2mXzJz$5zj.*p_ # ȹsغR&}:]{P3, )']XPUWх/*3{75cy}1”gtZjJ0Ĝ^/f1}ƙ AXٌ7f|?\Zl6A25*a $~)fM4d0`Rgg'O^>7Mcg C9+B6\vH~n'ŊDD-442_$_~~C|֣0_tV|84:Tym%N !WU*z|a Uh %2qm9:*4:mj3d ecX' GW`&DI QJDw 3qLdqϗ 溴z1`pbm¯d(6ɲ]/f k]cy n}K1;qY+$b|m<k0./l=@%P2- ,_s=5u<7~ tzwv.!ݵWW@"Z/ r1>\dmr`&; n˔wSuXtlٹ8a0I|$JH xӆ4M_V! _MlUjцjLaCa3mg;'>ƘYG_a;˶Z`'CF[ugJ}^<9lf*b?+LŪ/&bHI~gVQXfjEPVĿNOEK]:]O-Tj0)"⧬y3siKˮ1)oDM8; Xg:0p*UE oVk%z/A+Ckqrw?sӽ3sޞ5o'pkXt)ߏj >VBx|{wBSN-kj"@THр>}g_2f?>nFUL„GJNkXWV[?N{Eݦ8/G.V<ŀfw;V~kqL`&#&blL`wK-E.R'%_ v`+7,}'Z;wb;V1i%.TƸȉXq=LBxtfwLLfm>"ܴ`E/l#$nvID:ݢ'NcbR>әg2O˰l[(ED\iϥ:.-^bMyT=1->#0qDݘ-TRSN13OEk8v3sӝs7=*E(--K/?8~8.$~;^yEWk%.hNQN;!jJJp4۲6 DG٥rs%A[|_-tR:V:EꤜRG u\V3:&j=4=.G.-IΖdHLl36)s0ҲN(uȉ9v&헋礭)ux?>Yw4rLc1ƪLkb_#87HUhυa8.\/iRfc׏kΆ]`ޖR#3 b9|=Z]TGWJ)sKLOͺ;TsQ?{)8pvm3cKC:uJzw~Z0m>qIIxb[o%1{f¾QQ&ԹQ~VJ16_Yfy+!5J? ˜j!jx묛´>\2֥) 9X5 'Jhxߪ.pWo+V09 "‘*XM A)\/%.قs9ؼru Ca@Ay=6MR9[}tue- tXJuJ|=L;NadutyCWj70u=ݙ禚K ij&VUa^ݮv)0k;؇~?x嗑+?F)4?X+;MMMeZZaj5q׽5"@,BAJСCbj7|KS,gU aGpp{XG:-0O D1}u ZfȢ?"6(+e3WkQ_WjJ #(, aA{s<[~L!o37/]t~~(cw.V'aM84p嬎'"L-& TWkFA3VpWiGW̺8x4M_3B-s|[}ۦiogM<&o3}j<3թl;#PYY _f||nMKlܸ`,X}uoG D޼lԢ$!]"Pt5i@G׎ӪFVQO[$VLeh}^*[S-Sđ>N&mȜm4HTh w:j#]3bȏ]s=0+VN<ͷסmfλw̐ʦ/.MѡP%"#pyYFv;B{ D5Ӧ5(>)ˈ q6_B …" > F l\.~Lāb9&> D"N?ŋb̘1x,CW_}>@8Zƿկp=#j"4L !ԸtgK zfb`n}? @L)F D\Cd/ݻqUe$|2>j(%"'Ma6mڄc a߿;  AH3(ۜ:#D"@@#g>L\|Y`TT0:NǕRq.xzwQXX(0`.\|ޝ Ap BgE%@מSL>.4"@ #PQQ!v}ٵks^-? S[nZK_a !7?뮻0~x)"H" ѬÞl wIE DpnIIRD2vXa…!O?);tYIHx0r,>,Zo D $q%D"@h})w~444po<+m믊G466{կp_"@C迆C D"@@k[rS Y111b[oCpS-ÇE*~뮻NUDI!ms]hTD"@Jb;C偿dr-뮻RjjjW ' 7Z:  B*arC+ D"@"̛7Oli;#"@\#@!qZD8@ "x?hāTZ*6mbB DW ;wN8@ʿq1cƀWTWz7WzW^zCPPg;։ D!!D/oʵ 5{PoBnz%1kʊv.4p"@;F@yy9+>b~~~ǤIȡf;?m۶1^t q 6̀Jp B\F8q2,0r,P*\9gDh?:e(MNP9h7|ұg߱fW]]-̙򐐐iӦ! 7;JlG!P: 6 p=?d n14E=n[DaCOga;"r2tb|Ǘ#GF~:;Ը kkN2/;diVD;Hb %"`MӕxboK3Hcӆ;w^1J'Dz*v؁\,OٳѵkW9?O|7b?{gWE( ..)+ٛZYe[5˥Mr+KqWD5pQ bO633_'̭[Rw]F}s.1O_OAkjVyNjI@%Ν;+W*B,;;;:uR#Dy@%KW_EÆ,_H@?h^R(4/'c» X(sjL`,I"*@"G^[̕1j$cHJt+?^OA@$^;vK1dԯ__cGD(7|xY'''̘1C6riS#JM$@KH@V ŴO|`^ A-r|y ܅$k. $&&?Μ9w-[m۶C`*U))BA :uJ%›FUiy? !N*C'Jh YtV24aQߟ %4"}n®Ճ0#1(>QQQXn.\QBxxxFQBMDi+V@AD(+www}(G-HH R09 聀[}|vDD(ZeKv!I( !'0?>زblmKr( #G`HH|ȹ?Q Mrruu $@E@TNIz Я{-R?:ƍL7FP3=% jVJt:O$Gߗs!%%E @͕1vA 44Tyv\GyaHHLAjO>3$@$$Hŧ ao'{y+c1r`=T)Իph}o^=%l~$F'$p# 88X)*^:5krK%֮]YUaU( =BԻ7TC iw?ߏm~$ /L,T#P$>vmW6>\̉r޽[!/nnnxQ\9sa6 ׂ +,L:m6O%((B J_ ޿ >;aR4{;&K ⺦ c2[Ka0]WG_O*ex$(r ܃BL2hڴ) &@-*2,, K.U]HF$@${4$x@[ַ.>H }(2G'c*UEn-{)9@uׯOOO# _{Ua^z%4kLJS; (4TNIz'p5)DVs폽q 8.;Ul ?JR1FY@&(QJ$_cӦMrLZZ F ggge}oE(˗e0c s b\Fït*ˈ2τQ 1k[#j#HT54KK tj]pv-*u5z uDUHaHƍXn#[ڵ1b<3!uL%KPƍIQu2U# "'@CH#$/'®aź0Dxkr<RS9PY'V.$J$QSyѹ&Db U'}HpDGGPDx`J.mQDM$3f Zhs =B1W ]xۓƺZ֡UU4ևïJm)wyJB$'Hr* cǓC(BTC?.]_Ydt}_-5y{ar5 q3}t8:>9  (aOqHr±5$mr^O':B@xM)<2~G'\:b!NjH)D胯/D5c9 VZx4 ALx /^zgϞf=$ !4 h@z=4Q7xmu#e%"ob Rސ*w//qMҡC9!T{ $ŭYy $@$P^p95 g0W_l'ըK r~=Rx !y͞@\\֮]3gHaN"At fܽ{ .ŋeW7|`a$@&!@`"$m 7RQJH !h/}A _'v6_Ԝ@ <<\UD˖-1d>y? ,ܰaCL8΁¦J@y8rls玢H|:bT 3DEEᅦx^DkР^u3&BIHh1=sH!;v싆]YK|4f䦠EO@)Y\æ쭋~Q@*%  Ⱦ} VT)4jÇCaT*:21-[ȡRb%JGM,# ! c ܻw| VX  Lc{=) m=M6ڵk QS.+r> #1:u.EB$@$@'@CsEV/5քҴvs ![vbZ\ ڵ }"0/...;$ ܸq˗/#@ի7xC @`UI@P \KHŽ1GmUKኇ@dMuY r9U)~NpUSHMMņ pad&~ 6 kI#Ǝe@;@$@'@C@x?<.,[pu8Y) .}=]1oqFa gJ/%vϞ= Q<@J.]G7;v`ͲsHԩ$@$4hd(& @x<ҶɌ6Xkh@fQ"_H)TaR_غu+BCC%KʹKlLmFϐ QE+S\9R  S!T }1;\כ3Ue¢zwu"m$uرcrySqh۶boo˙x9t.\ԭ[&M0 !JE&'b]BNţ3e0զ&_ j(+ !>!dk͵%7U$@5&[XXȞGfy (#QPAãs  "%@CH$ yA_j/XjCpJ ;ր"UJA'[UE!HaǏK)DۣR hZa߿gΜDo6D9e6  #JHEN`1߳Ee1/`yyM_ Rݻq-EҧOkNcrC@TXB1Ԯ]oCarא J$P\.‚ˋrµJ# !. !y닂{"+Wߊ<l$WX|9PlY;|^9z (n4p}(f~fȞ mW.fiV î R{R& ^j];w ((H.{MYa_|*Tкڒ%K.S^~e+W$@$@%@CHA ~0_şZzi=5MFU;UkjH\={ׯߊ*X Ν;E63"TbF6<==2". 6 }$P(?(;u|STcBjƓ1 !fFT, ALJּ;7kԨ^zaÆ;$~~~ذaR_~޽{~=$@$@*"PB$k EQH33y*UEK+kUr]F9urK޽soJG1p@4iҤx' Ba/^,elmm1ydTVMQ  >$`RfoIƒ97RʅM@kWȖhܠba/ @F"N @ph,JZ[ۡ3ZϺՆH\OI3jtDFb$}!z2*7s M]Nf{%zlǧȞxg"y REFI/Hz*;)͖ptuݧ+ʕ:Y%#SD)3 pU̟?_IR-J`㱳4$THtGnK ;KFa:wb"7DB>ECHn5H-elf$] r| ~ٮޝ"OH 4hrǜ&9 !!GQ_*:=:Vy׎Tlz7|$I`?&O< Bq >}OSYyGdqbOo'1:L=ztƒX ?ɘ;!0?7?1 #ҷ_-U`arFCfxVE },˘|U{} ~f+Ej:غ X6#?!Ǡr0z߼!l:m*Šh5.l. Y"q^wL?/?SK9~HGlPd ppGJL9?sѤ\DhJc?2ƗUăU*@Iw鏻a[$0@YeHb܍c8zlRv|)1tXa㼙GYKlqueN0H1@.x7Nb3X5 =>?&m4i74[ٳgܗ`Xaд'}Ah0K*[3c`HOzx`8{/y<%ɰXh]<;cg8'c`[m#H gnܹ4Ƥ2d)gCqk> @ߦ +E:ΜK4 &Ln4nNdH3LP^6gex,(Ydyhgd,L6oRÚ5k SN4~H'<<^6E=l.CCWOKwFz*f2c#QSWJO@ReF#d0zbxeyfG=+lg0a,8&Lz22/ˀdxcܫj9h҉eȟ]e'2<˓>Ƨ;;<=! (,.kFB`T.Wԉ4u]Emib"!HnIqP_NPMq6}Sy4ymnHrH)Q:2$ #HLLĒ%K0c > p0VX?DؗKS뇐@d m1ry̒GN`)d?&cD) Kl=ː‘`%oGf= kBHHXd>ڈHHxɩt%$HHh2*v)(OÍ?QHonݒN +N "r M"0weCle(P;iOEx՗&eMla=9ֿ䍣Qu6 }_$ܿ_.sy7$$$ YHa4, >Ag`8V-TcC>D7yr0CFc  =1 3HJ=U/χTڿ%rlЃ+҉.X>*>U6w̬#u6CSg2/9۞npSnnnҟ:RՌ҈=_t)RUv`iwugn{8{ y ?4q>: !ƫy$ (,4IC*%p#_|{DnGRRثtt%1O=])"eJ ?h܆,%\1 ɚ{^VKOOGPP>3ʷիWrD vt,]!Z6IWOI\X49~/th <x XC5:BHx>8i8y$~Y !ɒ1GP@$@y!7$A&7³Cu\SPd-hܠ"W)ظ9E4#])8{gnǐ/`uC ~{M>Y^!bO^y~ch"HyCGGG[6̜95,jNƯp8d4Y^Xs25'PubHpLjtMƚ0j<^h)ϩPdq?#Mڷo=R/ BrV G&`S(QjPn0z0+̞c3,ILOG.B=g.͔KmYiK"u⁔)SN\$%%!}t f͂Cz eDIH 3g@I@wINIc_u,R5oņXig6FP$\jbF5}!O~ O"};MTo7C@cHFLYI KCI2'DBD]BP8VD'iW@ @TMp6mCEҥnqDN,eX rؠd`yZ+e'`Zy҅yIp<'ၔRx y~6}),\z =t_`ȌѵkWԭ[Wط/#o9HNl+eaz (ci)@ x{A3xRlWfz ,$@$@I!Is $%~{c`D@dcפo2eXX[}&J?~tRhYLtAca([}|kȑ#UҳiD}Тe+z 8' 3'@C?T_f~?EU)H4Gu85? u4'9 ,lر~~~HI!+OYq&\Q9b*#b @'F_] QHH@e 8$P.+S|!%-<}aٲ< !HfF/S.qR!"p |GD^3fƆImkO. h !Z1KO! vcYJOHtvws`_na!aSWbڵPJȈ#*y)ʕ+0.]hO5' !$x @x<ҶɌ6/:NU.$+hۼPaaaذabccDAV0x`XY1b' "'h90aׯ_rQ  !D{{FI כsG 'Q=e14Nd-/Vw.~Mɓصk+VC {9eP 3g~1gMǎ1l0G9HH4JoK8MFyA_מF#UETŨ&J!27PrOܼy^^^8weUE[QFW\Jz-va矲TR?~F:Qv  u!D@)H ظh#?yx# %R,г c&Ҥ( .+,JkH89fT`0\]Y+D̈́7cwW!@LL: 򍖖hٲ\WT`#a/[dI?AF">$ 0zhx(yH9 +?v4cY8~mGG&bߗѹM5bJm J[z 777$ £I 3f@a#  S! "?EtL2*`"ZNe"}a,d"͛w*6hDʕ1vH@+N>YiӦM5J+SN  `hN6jwncѮy(N-uE ezq)P)-'$[Ǐr*U(c쐀+WE0ƍCƍe%  zd#yZ4ǖR6* Ξ)y$H2L)6ҥKXv-};VP1"ƍ/K^|yL6 L$@$4f+ NJuarr/g׻O,,J ~+zB"""([[[}ׯ?:8^h~ų L뎺8;$E0HkQ|"44T\rݻ7ڵkCZ%xTX Ucd'& =!DOI]tK{g$'VKİ@5`ii+"ؚ" pY\zUYSw.5̟?2sLZo*G$@$4hg(HOY_xjk8/f(JmVRŘp1zp}]2ׯ_ǚ5k.yvI]R:v( .][3 hx' 5kLNIe(4 n ۭbz!rRz1~dCE=HՒ !wӭ!DX~=D~cyZn!C0 {ʺD/777]l(  `\o.U>2en$Ŧeг$deXJxXY lٲ7nPt^]vE=1vH@D(̂ peYL>F$@$@j$@5 e">H6tXF>#P*D5 AN54cFFn*'@M 8p 4ibtC@$]x Ӹqc꫺я !Wj XDѹtԁFT%U6lҬ!$-- G_76 >U2@xwϞ=^"fԨQhժB$@$@#)5 ~/oŽ}ј8E'ZQ Iȱ+h? ;l9O$b߾}s,xlԨ &'CU E޽{شibeM''|ǛHHHbj\rA`bogIEcg8W( /DȈP'NJ5jK.hڴ)})_$$$_Etth-Z`̘17 bj\{1jm&(Qx5"Ǩݻw֭[ W^U2 蕀 @jj1n806  BcW~4NIku{LXRAyB!D fKU9?DC) +W /zJ^ CEA@$]p!.^(O߰aC DTBb#  -!DFuK )9 A]QP6%qU\ruuxyy!44T +uň#Pb H@ "##?(dĉZ2  D4۷WȔHHE|aM$Px f,;/l$`I1"c+8{WxlRammCDXt)N:%]lYL:*;ќJ$@DsmJ+օ!T!\ƍqUE +++dPH\ ܸq˗/# #l$@$@$WO;K4At|) @OW,$|v˗!D8vV^-%NSwvv / ۭ CfJ ##~-Ν;'_>Ǝ F$@$@@`RGPwR{طn66) }&4iPSRR$MLL5u# $y \xQ.**̪0zxG$@$=Br$`:~2o]AL+@6P%^09OkԧseoELvRT H (yf%ܹ3 !출 cW3* H uItXwDJIS0qtǢ9rB]6<==ѰaC~Pa  ;%!jҥ0< Y!,J7N58\TEO7"f7۷o޽{!Bax$$p%9[.&M%K -BvxqXsA!WP-yyquI@z{JJ ׯGpp0D2Tc^: $@޽6mRBa lWK$@$@Iwj]LRf9gveI.K%P-Z7}aDcop#!F~[XXȕ_DT*AH |9?"""d)D(o*UT\HHC%1 ~> 1pwC@cHy']Egx=~KKKi y;̅@rr2,YhYe;7DR\I$@$3$P(幾omH@! B_BBBp yLǤ‹IIP*ױC$xdHJJ5z%'~%  F#@IDAT%@C=571ĭ߽$@$@$ 4/!/LnUx/ h͛7O%MlllЩS'^whYvVH@śpN7>P /ŋ#,,LW|&O QRHHH x @z=r|S[:sFuQYFq:8::ʮZ=0hiY=;,ǼJ!$P^...ri\V)tԜHH@hR'8{&r _ J@& /wƕ+WUCVZؿuH1!D !h cݺuJ(ңGMHHH RH9! d/="ՇDdCz&kŋ7n])RS!R/f]WU0K,Ahhy뭷PF +G HHHR йyd!ܐ^ܺu]\Ciji9a˗G.]ТE 9r"r6hߢ `Ǿh lg$m;w.nݺ%+RfM9RۊQz  (F4#|._ XoG*J̚@`` mۆ$C2e wzzz*c1"RP_Kl2ҫW/[K*PV  P%BT-Jޙ{ 0!{ա$Ȁ$--MX" F)c銙bhsu_0(9 (a#Ĩl$@$@$@'@CHrA`م_xj h‰'3"QJP: 9GbѩMB_Z8&BX3F9HHH@-hQNP]V<@僷Zby[]E%̗͛7!*UJd%K6 "MTDlch1qQ8 ^ +R$^Vš$  5(a,$eK~;> 8{4JjYn[1X[[cǎӧfJ<\ǰ!1\LB`ҥǕX &MSiEHHH@'O@d~,Ȝ:R[B A`Νسgn߾-]D [nŚMg`'2j;C;B#pu|HNNZ*M&C'-%"  }!DH-T@ZB*:=j@"@#*=rD2TckٲQ|' R{yb%L ((wG~e'  M!DD!N܅nqYy\ev֮]p$Hz0b}v%B|vGaڄfOO#/رc"7@4kn#)0 & mj#~cYJj@Xn._ČdȐ!uS XZZ`p,nʡ2쐀FPoh9xHHHLCp*:&p(wDm)|2ru՚WM|, /]vpW{+kRuy\_"S>Aŋ)q   (r49b.g"`r3_o*e.u QԩSؽ{7 *T 5nXBl"ѥ!D ;F~z9yPn]iIHHLHsMKrPLj%=mmh[.kS[n ptrQVTbW%BeXZhN2 Lk֬ѣGe۷o^xAzv- u%  U[h;x^fmA{5&&FNz9EIѹsgmVyjVGq2:Š[쐀Xj\#GDӦM&&!  #@Cm9.,s Flmh-i9 x~|K.ݻ7,,,qwH1Y !D뻩_/_`YAY9s&*V_ hCc4YU=.^Ns]W!=[7mWVpĬp76{{{!\P"_֣ID2⯿Θ>}:lmm5E'  }GژsFa}b"\&@ZZ/:tHNhgrJcU*% uVܸqCQIx5Ṟ١uU\|Ts >"H>ڸ?yIbz (iZ۩Q$/[L ر# Ix5 br\PRf@w®VU*&!?HڼystUVU̹S]W6*79P!bޏHgGƴ7 r^ZSZǏG|HH bNE`GqAJVc0; b/ U장zꋗ;|,֮Y&իJͬO ͻ]KOG=ߣ&5o25k(@jԨ7xeʔ[yHHH@%hQFP us aGXXPE*]czޅ_>'g.ҕ8˗vZDFF*YXXaÆDe{<ޞ.oESlOIӨ]|.hc6bp=q6n܈xXYYa0[¡YHHHt[Xs% hAܺkKj֤࢟\2=ͮ '3>}Z."^ڵkP<@hְ"BN%pyu,.v,+M⒣p?p@fx3@f#  BgcWbj/g7[.' >T(""c^=z@NC<@ndCCCH.<akõkDS2&Oy1 !JB|4u]T(iEj0?oujBrvK7hٽ;v@hh(.]$/hii Q^B+|F{TKU\N:_~"hm۶ȑ#KK$@$@$PHh)$F6</LnO%MhVMwxy](aMDM>WU)+r2U*$'/(Y$^y M EC =2P㩭`o]4 iyVy;w֭ŋEK.ӧ7[銟~?͒W !\g0| {ʗ/iӦ$@$@z$@Cw: W7Q#ƏlX(sr}8|06o blgϞR! 0H# ![_tXw;ȉR5o=c۶mطoRRR}п4o\chxҶpt"sK )[4 qV]Ν;e/&MZg*G$@$@JsyT?iֱ:zvqy" 2!p}Yoذ{쑥y}F-[>"HHHO15Iw {J.^ÿݺ} ϟ.\$g6mTStie9}\$9~>^aA2Ҩ =+55U|,Hh75ћz)믿"::sިQ#?)w 9G9:u 3|9 :{._ʕ+fJ6m0p@)!2Ύ1< !ڧj#rKxx...O'IHH̓ !Z"r}Ge1u|32 l߾IIIFe˖EѵkWeQS./y|%%ɡ2ՖaɏE^ 4.=   xBD&pN:>*3~wֆ-oH"cT  x4lоee1o]3=~zPnZ* F_7W_*BvGav)ϩ/\D4QjԩɐHHHH ?h5ޣIk|+pP\:Xf Μ9 ,_>F'''s@ @`/̹D)TƱf$p ,[L1^u˜r !:T(ԻADdF-cE)Vw^(KKKj X7HDH\.] qNE$@$@$@hᓠkC+JYY,X\-]v-,,,иqc 6L` @_)tue#kN}pcc#u] /Pwwwqԩw&NYITR\@ϼ:m[eȃZ?ϲ}@+iΜ9Z'0 C0v4-4t ^ CO}QZ`|#K/TC V8 i'N?>d}6)nW_}Uؗ'> 4ihx!`!#d! nJc"u?F,bxGgyN:$ oA7.Bk0 C0 E!{j=O˩o0r K.^x!g͛7u 8qbbE+\h˗G|GI]tuQQ% NF?scJݱ>]WWG]]]U(|jw#FmuiO?])v6h C0 C"`twg_qGq+ӁD#>lTg{̜9S"/a>֌3.RYQU!p#pFW!>uAwh gL gMGyڜv]uU{!`!p0Gȁ[@sRoxa` B 0}tyK/xC`AӦ3'QsKo)c%Vm7 C0 C`@ `L"oַվްO4&+sISٱyk =C+WRCC^5f=z^ʆ!`!` $2aDp6=*+s ;vЃ>OD1c}v  ![ `AEMC0 C#d_h<+yZϮs~mk3oK_˹K7 F3 =4!⳹-~&!`!00GPgӖ&ƭϊV.iX|9=ުp'ĉ7 FO"Z6Z~`Otoݺu9D'O+V0 C0 9BEL8./;=6m͜93ү eeetn57 (**O" 1b[}-Ncن!`!0(wwwSWWnQ;m2w'[J4Loy[N9Ö-[hڵnݺ语GQ>l*))xSAAA[!0Pc~}2\}-!ǚ\!`!7wGĩ E`00z衴i&S iԩH}}=m۶-WfpWUUѾh2*9s9.5x8/OvV5xexf7p𲺆!`!` $#$TvO-m,`4sb5@ Sjoo3tKHy6ylϐ)zǴk<|iV)۬[u+MfZP[.Zp1a+.+^|lFG3!8/ NK/Ǝ+utl C0 C87Gk!=Ѣn)$sQ+Z}p.;*8\jTE :EQ_4;[d}v,gaG?!ǽYtQ;;}ꠓ=-)SsΑ3wRq C0 C9")bccK:HMC@嗐96hsPX虫ҧr!Dei0j'h@^4H_S Rb@m3"V1{ 8(By\K4i|`!,YBcah#paD6, ӧO'b0 C07/4b \*xSAӑyR.CP̘yy[K6(}Ęw]z-8BJ~J.ĩ/Dy)KfO`skkk9BiM+C`1tV0 C8#PEw` gZdpi+oĎ4^I$Fd bY@eե'zn_y8|:9(7Sx9Ppu!eOߟ_1s$\oiUS]]=6l@4zuuu0 C0a3~E.L$y@&A ;Iڕ+m+፵wH(ڥ/-rO$ޑ!UW߭2Wp0\ {t,i<4hG N3&X7<`!mLW}w}Zg[(H0 ^]]| Z0 C0 @9BPǁ$\P'b]3-bn}z O$O4'T<95 =XU]4N(x›Js}lGg?e|cHg= q@%pWL\UY`&Z8W"2b+fX!`!` {h$ #tև4o(F #G f :dښaILu{ j:Zђfuo鄳əՙ`{<[:)|ܕ\weG4+dӺ1|}Ǹr&gUYrkjH+{UȒ7ʎ2Oicx<>j8ԙivZv5 C0 @:Bt=MA'y_;-[9'H$ ^]1qCz Ifh.xtgHN7ҫ/N&eiW{~C5?˜mBU߹j} F3F\N\Y}fĐi)O-}=nO"'ɰ!4JJtb$)]fLD% j{[i@AyJ~f~jĂ!`!` 6AC8pICpJ79pN`%(%u~  B{wuUX6iV߼T&_eBe٫BzM#F0 7/CC !`!08GGt J360<xK.(WLa^~%O^B*EHNZ~1By,L‹ C? hHgϣC??|ViZb0 2aN ᗢ׺^luPCZ_9"v2WG4?8;5/W{YL: 'ڮ9]/oD@_0 C0 Y6Ca{ۏ1(X3Ywe ^yb _.Ouy)vwwvEsTOp>sG,5/O(}[gl܇} j!`~s Z u4 Ll'Z3CZ:yW /-UtXM?c9:bCՊ L<}'f nM6wqN 0JjڋsJFuϿ?{IW-3/ݿc>g<` ?O6~N _QL'tQ|[UnY+L ds0ZRPQ*`LwVv~`R?s[C0 C#$:F85wt_7f襭]jPqi@!MۻiZ)C5tB:fL"|BРʩ1(sy)~A J Ψ=X#mGcCLKL"McJ'>#tE;Ge!zߊ7o>[q Wa 0w3g9<,CG,EӺ>Ftd;axFo?hVOˮ!`!08 9<n, y^t'\YMPC{ h]YDETK>:ŠNۚ<:gz>eLjd@>?5>꿧.1LnDŽēO .iO\Z _01BGGs/m;ƿπ Qz.w%h,sm\-C5KKM ӭ1ԳV`N)!` D_!:Xו4 xQ tu7&WL㥭zd&(eTVGPJcLXb]QD mezg mk^3aõ5|e+&~Uӈ$bGyBɍq}=C{kpxθqaߕ:#Vp84M'7\pE>jzߍ%;By>=1H^gfO6 ;C0 C,#ȓh-t:wCv^\E4iHf5\40<}[1Lw| Zq-y#JcKqvt_[etme䯸b M~JLRî0ShlMU^E?G>򅿬,_,v8CSi\!5io@5.NaWSsZIhsE]Iu.V#&%eyҊ.I?ܺƟ/YNr"bR:u̻+A/}{HFswHZ.\_y=M# p+ZpDUg"_;o>W1H]6Y hu{=J UOAo(;5L*"qj"/ozu!|/7SŒG z dqZ?X)9׾ɇzWWر֗q]gKr&wl!Zy_.ΓBWK]\jh 6Н;:vgN^=roB{NcPJGyHj3|4Z(?5b#\xyVq87{E!`!08}^詎GV0ԁdY S;/,hc*VnnѻGcr &8R|t=+XVe2UX;LUUgi/?N\ N84>W"'.@@yМu,}ֳ?dPxp7{ZҬsŴEŻ,:s{=|0S>{nɧwcy% @+.ULq;:U$N8#^BۄkbB\->9FTR-oԳ Vbo9꠭ mxK;-Κp2IcѲSe½U>44$hۈs4i~N.NşTg4b{fQ7ޓ+].!`!0GG:pH6Ȑ?ƠnEBKgݚO-DjxaR76sƱ'[pf/"'ڟ5:;K6.F?zP[d-]{B{\\ܓִ v+#?{M'պ>VZ5;؅?/5l4(H$TK{ptTXf@IDATY;hYPhC9 . mjX>97hI7G_jmA>|k$|#+R?EP!-@&%ڃ7F.}Lc,-Q x{WDե4*&<g!Z½FQӮZ7f贩ypuUu[(5:7Gʼ\J1 Ӹi\(}I"?{ hWA+)$yJ1s"reYsrO h#zzv 9M8-)ғ#kyܵP>+^^[X"&SYh]GJ|n>=氣搡}k[M7BpĎhB;\ĤHNDm%6<^5N)'DG3Q,<;Gy 8[s iGM;5]g~-Qż Q һ; Uqrg砜urEi_h^|n&!Ve>Re_e}7'UQqB Td|50EiWc>.`tC0T鳊yO@ b /WJ_?|[bV~^\ѝmDr HciZN5 m;⟒'ApE_p!^+w^z;; '+\+~ tϰ8.(zl)j!rjW;!m}%p?~+zv9&u>דԜu!|ѨJv(S%KyrQu[l:iXq'ʆ۹e3}6SkO[Jcjcj}Rl!1qG ..(" $ڎڎƚڶʛk6T2m,]}* S;,^g#?^2NVXe:W?^EKi GMq!1N:j|Gҿ~մQtŇ$vp re:ޏ^4ĩtٱ¦'nDo58L1I5ʽ^hi^kSӗ۫A{f*#w1Xaڈ{Q? ?!M=2pyjeuL9 Lڝy󨴺pi@"g<^EPlre{9gKIxD[u!P,40WSSGf.Rnvj -gqU0^"c׿–Nf>ݺFif[' v"FC&#O|QT>rq[{nR+ǐTT t[5>"[SM]Ow+arx23:#GH^ozB|#ЧN8J>JF Jy^^3l3>aD IK^J[cF(aA۹=Ep|e ]vY:oImWC0 C0x8_gN?h49L۪B.ok|O dsSt&nn]98^.Lw|9]3=ZR}%VO 5:"{t~Ytln>@J Fs;=PcΠ+ObC4҅;`YVtѝש|E|QxY;U3[g[cCUDd)D(C_tϯ[cnw6e;'HhmL=yIL*ogyDub7j -{'gJ{+}9IH;Z>hlU cGpS} =%~ @\cM>v+/RÍGeǠo;t",?{H/rIX9O#4-xzɹ 笤IF(j_j$mkÓ?3 !SHjWn^EuoHD}>|Y_ OR_6, v":g| ѓhg:xOz5f5͋lr3 \'$Wu,6 C0 A@9B0dpNhh,S`b(/. ^ͧ^TjgG;m[*ИCe=&|)y!o[hcxA,Ժ\>pi#y!l]v6:Z7~W˂ t: |qB :$Y :l #IyNUyYJ/2EW܋`U@O} f7?"+CܠN ١嶥T9j.oV0 UtSk鰔D+^9/Ӌ7'wrE9LR,4KzxwC>K=6ޞc]gc,O!=y T^jvRX 4&r \EŰckݢhx&9ЈIru^๣袣FguyUs/>"r!f>teVZpFo3~4r=t'/\u$ ː$)%rvWW\Uϲ%J.wdʫटppck҉\L^Jpwoݿ\Nz1Ӭ\;>\SDtg҉Ukqh^:=Wqz;Herܺa0_54!`!` "!L'iƐ bЛdK% J˄6ɥowz]+B%n,ƃ:n mў 9K7 f%0>0'~_Щ3K?o_;K&)muѲGI}^EO]&#_O[W1]5@:)Iܚ_uxd^1mX&'?HNGvř#h̶yO'C}6wgϞ3omE>}I=u\ͽu-jYVPy,p\ȟ{aP8lqغqp`.j!cq n3Gs wmyպ2~Gy8H8EwohY?çg"H'V (>F:ކQT%qܵu_P4b!mP{s\uu96x(/-%8hv|lawÆwGTMs珡ZD^MM1C*W /Oo췎2_pq<7=m/%AҾL< BW$b \]\ .B\]Pr_g\|'qZOƗ<]JfsVӬɒ=&E |95'%;nKs{ߵ\LG@;4eSx9'&?4ņ!`!0GGny [&~ d2D頼I v*UX?^.ǝ0K># #FV7N9x~ 7.O/wN|Itϯmo$N&pĸc:M* .9Eo4B>tDvT0l>dh`;7gMiXC-jn8.݆yMGJ 'UW̠NI8fՏn褩_[?XN?Ϫ1ɝER>4<'rӪzƁq҉Cn"/KcΛBGY<ɧF.Ssۓu=uiΟ=2tC PdOnu|+؞EtlߪPC'܊y *KpuD@y'gzwƪ^Ϩ /~?<v|>c&]Ϸ(gߗ6Q!a$*d旭]t%c$xmqڭtfKGeڀ7&+J%-2]KZ888n\/'s|PV ٞgwdqP{J=G橜N(+Wr8 h".)C|se VhAʚ瞒~㬣3P>fAp's dU*]mο)OD.ߞ9D29N_og]@rJr 1_$k_Y.ϮNZ;v]f_ՠBANZ6J `syB̹?,sc}ur"Ӧ;i+ 3ǍU{g3~)evnC7sW W_#r$i14GpAcDڂ݊(I?/\α ]!3@=(Z qGqUJ*&oܫt0rEml lw>y` o<Kݻ;hz+lSGcmNb*JTB`!`-D= ٥%4$? '@`,+OMA;L[WƟΝ1Nr^ou~kMZ8t;x4c'aMDI=fgS+v:un"-DPYu5Ddd,m 29\A0G;I2kk6@46E'y'(]Y䀕?̸-x<LwPXş_?;[iGQ"\|p:)q|h' j C9`U"1$yC"?붝>"zr-/P`_d*!ct(j('ߝ+Olz@y\EZ" h-泎 @\c[ [Qxwᶿ":bJm}y#}MX|G'Oa'Qy1*%L8<wx?0AA|Ae=S%>w<N%kiIM߿#C_z%8p"y4xtolG҇2;ڿk愃vT&8a}dpÃp:YT9M l#Zu@'gWP>jnQy>8r[ |pLOye0 /ݙy'Ov烥y4T9XZPK!`B!na0p[М 2I7Oqhc1CfAnu&V8|)ԏJLn|8<~p:Wi_dRWQD' F]\ 8>n;'@#o;N9[iVYYaME ":ܸ Ra/>Ir\A*W4N$uұ'8PFuN=蟶 cPrlrʖA+=56O>]kW&R 97-WۖQPQ<oko}b9{0Ii}ݭYoWG/c>Wh5N?Ӹn,ui9+fr'ѵ6 >k_S3+ߠ]u6H-@²,ԯARګTYMwKn-m 'sߐgs\O(qt5 8n .@|S3v^]*W獐K[#}ejw@YgkK{&㴑bwbn׭x,{CjK!``CGl۾R^%46`LhuyҢ#$Uc&ӌ3Fwv2/*zjTGRǟJ]yWϓB޿?~r# :YxГL qhk<4%?˥;9z5sF}c(k< GTmD@3\ 8l|8 tޞ_ aЬ9UF}[39bsI)(udk 4*nPe m:bt;b'^Sވx[9(D]G>:Q Ĩ#oݙ.dĠ/ʈ@c=QY>P 4ٞ/'{_nb  I`?'#ч2݂-](([R$@u$eiZE2[v>1?)YJ7eh!ztVǣ&P)at]{+7w<31hM%EtmLz;G=pk7$'+q6_ls"tj:'ЬB?Y,\H w+\&%AT YFNSRݳ>Zo?MଡoSb)W#*-,i E Ɋo:}PAdw)NnV^NoڌƑU͘t4w wvuls~2ZJPd|Εw sr 0 C0#;{>7a48ҁa  SoŴ? D(*HUJ;V/<WT2]ݴS*[yA !c,akYn燱Dן "yJQO8 ӵ;xL@1aNz.Wq?nWZIstX7V (:,ѳ(5'|"*!?K2$Q>knC 鯬Z܇rz*ƞ |.v$UBϰ=fE4h'$@~ewK=-ơz(v:g{7]'Xc:`JՈ/gڞ9HQI2L򜷰ɳiԸTԩ?<:mz\hI+QPSMW_Q7[XCq1AOC>t<׽)I3]n{ fa -f4;V߫hμWPJ?ygm?JfΩ?~~}:plQ/'>U_%Im+g/5%ݖd]'3<~CLK=(XC;1g{F~5oWz4{l0(yEnc {{I{baү jW#& t=k胑Q56ؕf!Vz`!`~u 2B)4v,!5|oGU]+c&sߕ\]&&y6eԀp{Cc/^NU/7}g0~&D .z|D%0< M7BUИyt:5BFg}qx?9~@uO͠˝j0?V2D]2uM8\{Z e9cBigrBko?!mIuqTrx]\*ۃ=+Ya {yZ8's&ӵ-#z#O҃(g!ի&?"$aª|ނ+CIhӋO{vx#ۨO[<z%s*"˷q>tr6U>g5K&/?_Ko#ޕ* N3KЦ+޸$8ukV\gegj6?CͬوU`ZD7_=*L~y|Gs7r=4/:(vXs+]6ĶXs}D*9'|=_~4y]e i#Y34|dF8-w\@!t"ӛ,W+$-PtF M׼&"ҋ+rϴB!`C!2s i?2&ZPD[,m/{n}km8 mdRhD#5n,F"w熯vxN]JZ~^5S|fb=t.N쉟W\Mnp'y!/-^qaHtuurUl){.ۅ=UV< ELgvBqWrU6-|Qy# 5iӢhţYG:++|'EߎʼN%qO~'[DVÏm_>lh?ZpWYd݃ TiSe_5O'Wmo'(x%thl*&ma52 2 8z^yër@[9oRBAKtsCFb?'N_ov ` 1>xC)ߕq4eY>ԋCLJxELb8DҾ[v_vog_HNo壟-|RK!` B keԸc^l1>Pް|@/{Bswpg hsw +WWtTC ]-1BfT>x_k':JhYMy5 `bhn훩z::9hz2gTdsPh _jdb+zR5u?ʇV>'ѯC$aܪ [,i,'3+/gßy oI:wdlAbE$8t4V] F+(R!# RJO]GԱ *BtNs]4.(fNy!ud|#,l`kT QC'ClX[cԈKdB&;C0 C$ Ul}<؉KVrb b'Ǎ*j^0JrYMx,o wPI^'qL .U:ၐFcuYׇQ7^sPsk ~=ʏ=.OVX ,(m3ݲ" u/OTN@T}=9Y邫ӌ'YOu| Ӈg|tv#k/oM>[G7ki|*g BlO+χu׫Q0}pȵ\=0}!/ }q~OL}aWe鯣wH&mB6)pvlwwwp綧Bdw(s8BlxDŽM ahtTӫNpGݏ$yw羰mzGEdߪuxn A'/G^[C(9'簏gi?Wa rqS%IbWC0 Cl#>2@nbc8R4yÛ-yzko(Fghh zWp.'#*3_uP x NeAM9MgvksEo#3v(>}ߖ:M oԛ\Oog}:9ʐ,;K?An,/wq+],f?֞^1۬|Ov~utvё#;6N?U6-i]ĭ+_ /LӼƄl*tDx N;@}a stpLǫV'nOt84ǚ3$!oiXE?,W~c2$]H/0o?hV3Cw"r35)x̂f3wSݗ\τh׋JN*gwV=Y-{'OG:h:y)tCcgwg:w4Fn,]Oۣ= C0 C` #oo l1.tCeNAG>Fg^NRMw6)/I|!'cP[yBQJgœ17ͣhT);%<Dhʍ Z/ pZ^dr NaY>J-Ң<3ϿX{LxrPiU!3?-ܔ5ҠBq#e9zGG:F08y\;W[8YL#yɢrCv&ǸGPÈqpiѽ 'VQWWcy7N^6: O-mOXȨ?q?ޫ@=CM+t,<˃$$&rsbI35Ж:%UL̏V3%OE:j8;$|8t([:kء+ANpq ?W~!MA2cG]ehp6Mlsx+ V{aæfZ]{z!|[߬ eS~wӺv-7ogOCHae{$,VȇVHZH-͟TL:?Gu-NV]4AǗ2yrnocXE_2~qtXd<">ܿxV;;tL j'\:)B~9_iVtУFeTJ;.FCwݱn{ }pI-e9W4v/g":]Oo_*të.+,3Z*\ʢEDv8Os)}S']ʹQiae+:a~><܋\Y .{ɍ/ns2ta)Q2I9ggxk9fT~zAwCņ!`!0X?G|th_Գ3eLAGMWF+ȓjw1fqec%l)uWp: R ۵GUuьfD ~0w0!-BT.xoOOYE !rZME;SNĆZ&ѯk\NǏj峎Jh&Pgggngwt[iJ =l ˓Pq=;I!.ԍg4UEs;K+}YV j*3x_1=qoᮽ,1c6E+uGN3F+U/kI%PCAJ8)kG[s'=np- h;e>\Ttٍt>\D2+/(cqʥqt2tǥlDHݹFgMr*{(TBZ$ؽ!`!` xQX'@ `TM15?tXo@3H%N%?(FOeA,|bH^柔i"Wd]mӑh)bzkڦ+!ӪJ ~A4b;`igr Lxř [S̭yz:ZF+᳁vM:¹'f^ ~Nkd,0QX > |oG:ef׮͍O=}"ݛD9Ǵ#cJ,%-0f:jLA~63 -4N/> {t(:t)3v4t>Qyeq>;k W?v&A@ @Vs"1.]:}f-}9;ǎdn^U$8natun-U!&a4^SNH;z[~]SN\vOw}4} C0 C`0!2mF+W:ido/'Ӛk/^W_4톜iӵ %W)Rn 5ÞVn7kG|~v}+#FD.:m0tҨ^NWOg쁼d6B>vN>礦gBgX]LJ4wQ)4䓉3{\ѝ)BFfaYX^ >OQ)YtyOmX(>>?" v6 ĹR'#FH}o1'=ؽ-Q=gvT]i!btˍoh,;iʹ|rz{Cq]K!`F xOoMWs鱈I)]/Γ cűkAyfӻƵ\W]UW_Pqh~R<wAlcH]@WRvz]ʃ*O:b.f؁gʍÇw*zm)]qkQ!`!` B"\& Vh_qE'seIPz+Jz2#_52QPiB4F~:LeY*G T[/;bH wзy ?[PD9.C 9y]4Cؙ2Wu[SGxg Zgl/6>CO7x )e4W<ZwM\&|x < Oȏ9g!Pf}h^=ŨeHAmkIDATo@Dž/ƠiPx!F_=rqVWZ"c=|ͥ+-:x'f}~=mUHeϳ;.BvdD9| MRG cՉcdJC:*W:=L> ( ~}WxJsM} tE~o҆!`!0GG$~3e'ɃnFdX=ۓAy>:-&:af32H1eL?Bq"$P*uzxXLyR!p] C0 C`!oԱm72]jģE۰Ngh,-$I;,rt(_HhCDS*A %몮[?ء=}S~99Lb;BvцJ2MG>~Fc}@I1xidDMX`MbS<fIC0 C<#D~#gM ~ C<"~X trX^qU6v'tѓmc=ovƱ qp e%Vh'It7Z*ϗՖqϮLr:lnrYז57Z8A=a>D=Q6u-M /܅}g|x< @%pwXhwHq^ޅP4z< ѫr، >~l"/R}^6ȓ'I#%'uGݗkK/?`bn|א~vKA9^8]S(y| _#ٮoeٝPɂĸ6Ce΅O󰧧4i&&@C!`AaVbּo4z/YFږ㻧vS|s<(r=ڂF;Ϋʯxt>Һ7]Zu'kR0)F;r1Y.Nu^5w=M>_ D9 ._HKѺOvZT]i,-@؎|/ #vDRO)Aޞvkw*/ƿwyoX @@Hiz3]~*˷)"x {F_ZP[ZKGsrs۞z=8,+וϾ[s9Y,pq߮/-Gf′lK[zj#kJfr } b\,w/sw] ֔ uvs\8; |/C\yʼ6cWon&_e|#vr>d%6տʯ5DW"Y|us?y_"')KuoW*sgW9WnyZ+_,I|oCX2۷uGYQM#zڼ1ʫ䵯YqZ{xpX>Tml/h87; ѹh/Z?CV2[-4ҪC Jոn7/(K/'Knj\K K=%R7qҺn;SS%,TM{ @ @H4,?E=C(M&@3cmFѶ=N[!}ۂ<< mc#%9̼|y i4ݓy=hq_իKDo|ys/sN)uT>]YdC @Y @Hj[!os_ʱn'S7(EB>}zx)hn,/]g!ӌu֘Bm~7]ntqk gT~}}'۳߾yLrY&r=XnYƟ=>ϛ\\4y3v-CBN^B  p?l!@ @\Bu䴛;x۷oW^> S|'#po߾-ɓ''J"@!{Bѣ~Ç+JE?U 68{号oOI/_;-$>Ӈ}r8ìE!*B83,fQXyeEș (=*kB^OA\) 0@ HR3?!tx\ ˰Vňlr.9L1J4<["x5ŸfXs`c!`b81h~ 9㞸P\ O GN)b38 c .pK }gw3pn7>Vpj9HF#d#PUs"Pƕ>\-pϏy#~a <֌5&vk.aG<6(lxOqWMXy  +O<]"3ngE\QLgG'~ƅo=<00p.rup re?ᗢe 3r0Dx&: :i`&J@XV`3vh8.+: Jx z;Џ  !tD1F,;D$ER4$!2d&2)CʑV9@#m!ҍA>JEQCzhNB3ѩh]E=h=z^G;їh0U`'¢T,`Rj&O_:#N85OT|6_SU!ދ%;7MH&dJ:itDъbqq q#qN|L#Hz$;/)!JHH{HI.UcgPTJJnc**Td 79#O'/#o'7/MŗOɢ̣RNSQުzWU]_CՏT--EHQRwR[oi4%-J˧-UN>j<9jjjjՋ+_V kXj485*5kӤk:iFkj.ܭy^IR+D@kItnFgѹ.m6[;KL{vvNNNQNưd9eO# GX##KGy555aAapI#QQ*cFtc?c*/:@fs-$Dfդͤ4t}3Y*V^scq3kX-<-k,ZL\h`J׊mUdUcuϚfo=պ &f[V`[i{smkE5J4jM{}}}CCCCëSG}vWG7w:;59qu:W:_sqityjwzˍ6m[ww{{Gڞ1KOnclԗշӏůğ_(,#YM`VWAA,o,VK0\>AihfhMho[،pBxDlC6]1vSԈ"m#%Mqcǭw/"J +XL928>f|N3c{,nu,5Q=qbbuɳ/SSI;R&LX=kĒ7&YM*t~GOL9FHKJ۝ͩ7rY5ܗ*^7ߗ_Q<7sef_P!녯³6gώޙ=/W%7-HK-:gW.;zO]=W!!E}If-Eôi 5 EN_/.ӯkXmMˉEo_\q+W1W{+\+6\q>^Toomv͟ʲbq[;v|)ٹ+vשjՠ5=\־v>ƾ`l~q @Aσ,mו#{ )nmi;pdgIsQˎQ-86px_DǭSZL>ySm#N;zk>} /_rTumm=.7^>XljW\c_x=znNywۯ;^} T_:;> ~xQܣ_>>ܵ)i3gϝ7wv_y1EK?5աԛZz͒zowwk_L߃wߗ~dz>=y/M_#s$Q Nh)ЯL!> XyS;%?Z=<>..mP.J_Txc!|xk /_`o2Uy'UN¹7xr"A pHYs  iTXtXML:com.adobe.xmp 1440 1818 1 3@IDATx]u?~޴U^V @!ё(6 D)`s$)M0ӫa@  j}go}e }ofΜsΝ9w|x<G#x<G#x<G#x<G#x<G#x<G#x<G#0FYcp<%oG#x< Njaѱ i4x<GX@nС G#x5[xrN'[x<G#p#p\8ǺzwwRoG#x<c>V#aבxfG#x<#pDXr0GÖ9(=G#x<F)  D8ϑad,SbG&;}G#x< pL8#hQmt[pљFBx<G#@`$|5H-rVnγz<G# :W*򃎏9ɖ/ F4G#x< ǙV6[>YS9غ)l˦lxG#x<##fgxli)}$֑ T&=cG#x<#3oʏ9xG*~ϧ=G#xR#㚎o4\*?N`t):@I+`O=G#|?UHѣO;7kh9M7zo eG#x<?$uPSEѳ(ttؤwΏT|QtlixS7{<G##04o=Z6<q|LH;ˆ,X@I)SJK*tww?B'y<G#8ĿcisnnnDVPPпqF]L(T4w˳ΏT<.=e~+n+b!J+i*фMMMIZ:^RRүi-s㶶:C\~x<G#p 0?j1c=Dc+++r{~2 *)ݎ#HlDdJo|qtYMaŜ|eYYƜ1 i qiPi3Za$G֑M:J`hv*EӲ#o(6/2G+]I۠H;\}*ưOi:lx+l.ҕE懫H摐#16ӥͣ4آi;樹7~?n|;yVOcJvːG %;Sy2C{2G4;iaMz@o}\xW8}"=6xYG#x< sas;ojܹ3f׿vlԥN6MmѴ,J]64}GqF۴cK.3wucƬhnl&~{G7< Zz*i7envn^@zl>Dld:Ce4viv=Qhڧʺy[.SZeevMj5oLW}6ݥ kTFiQTBnݺm^l.KySU@!^UFG\2fΫCe;-Ӽdt65VV;oQUƍmMF6-|,U- ,]^/]ʧqoTY͖.y֣4G+Q(CSZ}E^?7 rq؍UE懣 Vh6ۖc #iO6ueÓ3Xo5|2#?Nϼ69 ]inne)rivB+j+zw_7o-+֪&;%x# n SWe : ]\_`G6CA`ݒ EpζN ;\N =``0 {R)zhONˮ`qe}#=0:pNo*[}^} @u~0iZU(M'QkZyt7o)7mLrifUpdFAގop**(3ZSŅTR\BB>8x췶RGGG8 %31|7A@/ȧ!-=t4(Z @)c{b&mq} le;.pҡ=|aƮJog[6O{!ç=U4b(,⹪$Uwy[ESs& {-~ YO7=#=A>EE2fOfH} `w&FŹTyMkz4on:!h1Z;(dv* : S>fn&&ٔ"'{n^.Ռ WSdM!!HR})CUUW&}>FEEEt`&^ E%EK*}i( U~V7slm^L(QAa߷u/_ $V{&?=5G̲m01p)-{xgOC=!"STEʪg+!w /"=BLlآ㥎u`"ǁ}FT>1C_ʜ֟͸b/Dڃ]S]S\֣݊ڨy7V{d^Ct =FT"H+}+| pO%Nr d!uS_/GH9SNg>\ tpH%q ?|皟iNHv>v"6x `aq}7LͰՇSYuSv@WRj >V:N_[`0O <Ɣ[ V[x! #*8arh7.RB$|=zU@ݍ~zGm?)Kzԃ N;9bY>ؓ؄ 5urn{;wNTO=h{>aۇ]U$S&U2@+(Kcp:)GuؚШm\wjDbxImJDڠC'Dm q,zriimI3U*Mu$T9D'c*hI23GhP`iLu}:U"mM?3I;W :HpXH`W<:6͜%~ ).:F#qy~5 y]//s(x՞PeßSmz734i$AJ/Gՙ\+ <᣶,`n=FU9:HVU4&iAu-4x|-SN+B[M9"N넜b)'G >vKi`Ӑ%S\03E^yݴTX %E`XyƁҀѶ#sѿPUmmv֥D#$N[EJQDR;9U? vSyCZiWLO{c /匙3c,{8K[x\7/&@`RoA,V^؃m6#:$ ߗL2f!V2a1 J [oE?hΜ9>C`0k]u" +uM0o>1WA@vmGlb8G=j6bȫML}E.x^Ҍ Ȧ (iZc0e`tuB;y)͎tT_!Ifdx9 pɿi.'D(j< <5Գ,ʛ=\WhRhԈ>8E8zmCQN^aəH=URN5tD8X^hA㍆ RsT߷_kshv\l3Ꙋ"m-}m&K' :"ǟx\\p8] vNQ,q?_t`ݻZZi挙 6i:9#zqbhHOnl+cUdqe@~\5}N-XZ0;|٘KKԚ>I9"ajR3q{[hÆ tŗx3OӅ\(`a8Qezl{l:~T܍65k˯,s(6@E,Kx i@`OC1BxAX]!|A#^%PkڎCF4y*)ڮiӠi^cEA ?|%G7t|'8(ӍԳ9ʿ?(m wk3u(Lv|/^Ee R#*u-tpH^طnk4 E~K&za+lS:eCIrҰ=rp4>I<'hO,Ƒiu*HK(rK.͜51|; $ ͧu ʓ'DȒIUtJ F.[[bJ=fpH֭_GyyD7b O>6fLAA0~qGGh|^RQ/=?-9Pu0/;y/:+_M+܃m!9TXohwj.HU,߇-$LG,`wޢ_6ƖN"y(,K[MҸ4b&uv*kR'sD8fjӥ3rO>$ae岃'/<,~u1 'sq Xֺ5N/S˴ 1:T`Iyʅm/ Ҡ#g{Gvjك3FB//C]E{ЦM7^h @׮^/,V&ۃ2 [lGyJq`z!(Zr٪ /ys$VױMc>0NY9:-;d̪g'nٲer{Kvڰ::~xzꩧ$ŕW\=V|2ҏڱs:vi ~S&O,΀:#|;t0Iwp~h!g8sXnH扴~mh̩|ш"W,^(蒇fl߼݈U#0Gip ', ]xi\db=^U>sv{WY+/_)O>'TWW88 +Ori4(oyS`>3~'"SJo guǎry³'w;dc慅^( _! q4 蘌jNc"tn|slj6v,<##>B}3&K70a1hvc N1XCU<ѱV';ٔ20ΆgEֹV#-ȤͧXiPtOoS |Ō7SPs :R>}x=:\Y?;pyPڴzN7n1Eƀ{xxŻM}.;@멷Y% ~e=[{ yu{(B!j*8Ho4JS˦C*q//rp{@6t=i^oQ8L(f`fT' ̄63޵M&N7 ":p"!H4 `]&S q1>/ F~,OAҖrC[XuǪl)_`e^u5s> `K}^ ϲ!HP؁xf괩DE I'Dw=xfr`G-\aX'4}ulNX mhc\s8X/VP0!r,FTa i !=7W SF!z,]I?AQD+oi;|AZlCZr9> ({\aG1V"LX7j3qjx[@dfM&UϽ@йg-m\_*&L;W$\T8A<<Tв/iLe-_o޽9ZNSGg/O֯4n"|-G OK~V="唌z'9 mzz vѲeP^ *]{.蓿Q_ WԼƉ1tб8|0XG{>s2NϖS _FCcK&{ gܕv%Ks l` @>~⃺Ts`W{^Ȫ42逦 l;A=~.Yu栦Z`X՘MFN=+>:Fg*RYVs~aOc|g9`K8W Pc>vqT0NdǜW>@Ӏ4hl4sOo75|No2 R$AaF 6$IcvO|B6sBpm3V[MN_Hpp` 8?vBesHdևqDcɊ5>AO'lta& bk8R+U HN:$YŠV0%.fS;px]٠m,V1`?:G} c`ՁOh3 #+2ZAe؆ǚ ˉ'(va`u"o&0fD$6dݴv#|\~ǩҜ 0u]:UBIc}үxhӦMr3w'nTUSMgok7a<_WF[6nK>v};ՏFϿvo~F)Oy-_h6*!󇩨^}vp: xRw~@uvr}aN__STuxY~xxM/?CKOخko{NCC'Q? WNoYgAooqa,fu.JX#]*#z]!!ǘɁr]uBd>EFS v<_1;;bΛ,Pa`Sclq~j<1}t;;:D\^Qx'T@i3f͒ k+@t#D٣" htnGNC ;f̘!vޤygPb({RNK:ьO@y|LgUld]ljk֏ּ S`@z (}v _NP;GA2%E|2z=a:9;}Εy%p Ĭ t(6[62ХMܢ@/d$@/m tK}RP`k(R:-6 ]˔OCIX1Me-] ^/NЊuuXƶ lsEJ1 WW~X)-KU5Й=Z'ʢ]nk58*>5FI=t"d! V-5BOX2#\)f(y0&7ێ-\o<.ZB{^]M/V.[9]wٯ"jZ4>m.*^ĪWhL7]%:;o||o+}st1OOHݼ}΅VSAajEe啔cZ_HŅ|  mv ݩEW;| '>IWKS/}J*SC=oCgғ-t Wu4k2:c:f)a}cI} !MKRiFmwIji ŃF؁Ogvc@bA<'Qq~ I꿠L08x?0< ]w%  , +)1B,1)>~M [=bUTk̅=A>/\!1.7MCl ai\{ObˎC}VBؔ*Huaob WW( rI4܎aFҹbgtMk,5ʃ{`"A^{y+~i^=Vȹ3aպoO'YIJ׈g+&~=i|et$V.rxUcfx.M̝L4SUxktx,NaV7I:w@c\աjgE+خqu~3qJ/ыXO\UB\!2Mu>ΏUPܶ3 NȄΐ!Pе pcu@'WG `*9bMJ> Hy` ;ur҇ $q6QfХLoւ&m/.o X ۠X]~D8ؓF~إRc, }|$ \ tFx.F)EVȱΈz>q`iyMk3,:2"& ` ${ cOVQtnq i޸UY~U*`!_xCAyZ9"KY>mt\uJN%ݓVvJK&^BLÊ1mEŰ$̅41Ti#)ܮS!2Uf~4Z-zO0_YGAgqL?yvS Pc1m+;-=w7/SeC5*ȡgWEw*DvM?"]vTkW/9V=[+'zMszg%/+~Ujg~¢3_60{eZΉX~Kp'q!w_p+ 3r2:Y㲢 &|k8ۈ9 =x𪫮:ځy7$g(Yեeʏp[ܦAy4Ƣ+b W- t`^S=0b1ă>UވAgcWL?$F[|Q!'1mD1(wU.]+1oŌlм<>@׏toiy/`7V '\xՙ TAIS'^v[ `N{ MGW\K^fg8ЂX~ uQo#`C{yZq`c%y4%iWFML=k1]UQ.+?&n&qR؝00W"`@v+a@bhUR9vlqjZ%kxx 'lTjn [;ȯÃX6"Ī0ʰ;L)WMTxC=N" Γ zgثi9/`b04ҠNp֭bKp^{WNPQq;s-}p, V1Ƴ:K ! Bs8BʊJyP/X7*i4>U=i:dG`A*HKO[D{>Lz󟻙_WK^zڊg-U?ihT5~͚:Z>-:y̓4s蟿34*WO=X Zw?J34sb%v&Ѥ**.y&ц7Q98zw39ᷠ P?\ʋ{>nd&q>/]_;freKӼ:۟TtO X <]I"6_uMԵs'B(Dg>V6PS/MQ{f9$<= Os(4x=L(J'rnZ7@*fT͡R\yFmjtv &MD'EhsF , VWW',NGS8eI| !*+VW"퀶 83I' =ki[O1Q}GcVp^a;l ;uiv]+$  p aۇ` 0Ə\{ݵ 0Dp44 lX_9a'P9 عyqm-[nh1LGIc@]#V<ꆜlѕkO1I1! 5AGv4*tͻ6=Lgrt$B}ǹ# nSN)24c:8ѽK<(=p'}%,`IaP??ΐc v'E:R+`pvZ^['&LE@TPt|o~S̯ÊGilj'? ZN% d;*Ʈڎk.d2`KhzX8XإG0M%ǞC`A ;VH<~Q>y/kF3ΐU%l6^\8-\Ph [ulڂx#h8l#f `)GgQ.NEf2~0>忣sxEdxvpqԮzq,zN.`20}q^;}L1ߝEuSt].+!J'obx:iLzG yKtqb%,V8V`lCs^29?< Y5Y|q>F G믓x 37j_*V}Z֘h+Jxc=Vx!t,>Qk֩z #eQE^Q*Q7{Bs>=ܻc;0/oXkRŦTӤDJ&tεT|.yz tp5+mqڸ#*c5y<8f%,,aA# yՍqepsk~+P>1pB0AB4mp:aonoa:Ю؀=d%P!CgW:QGRܱP ˶ NPpz%1zXLco &&Y"؆xep?d?b%1E=pn<,qL% 8oA416Hh_=41=y#M7QCȏ9*0+XmÖ*z*OO_8#'WDt4F?tCwU3d1rxW V1w;`|Ţt`ÅA 22, AX9<=`(xx2#4gfOH0O]x~4ѽ & aI Q𰲦 ;9`#nZr''`n425E! #\(rۖ|=@eqѭ.& yXuy;嶬MӴ-ix"h#Uq8ŃP LD2`ϐ]켝vRA6i5uкUp0mi$`ly-Rc#me]lÕϦǭͻ?uF]teH# i@o7c8ȩ [RcӖ萓f>K*{\Y6Aa<::w> 蒏yQl`PCd u(ת4`i/pk**n^<kkHV[2M宬 էty[O\yCȫ֩?B?G#x<G󺨩_d;r\rhͿ"`rJ;5(;&@nu:QteʃXiG%x)KbKYJ;vkGx<G#Ȉ2l v}dfxM,omq_A+VJWZ]D/U/]}q8*ev?*+|ʏuuJ:^7RIn1MO;-5Xfy4m }p=ZcxOW`څ`䇧hcٶ6}GK :4G#].>@k:\ p 5S+2c~-.Hʫ@Y؊w0sq"1ҁ;ֲ(@*QrHe ; չ 2"S9dcTl s'#x<Cx<G!=W; \48p$$8A,LکE^"UoƴūvX)) iC`q6ԥeʯyC7 Z]3 %#4Jܼ6(sѲG<}$lW4|G#xFv7PKc8o>͡RY%YTϿ ԹViڍۀrB|uU)Hҕ2ٲ>x<G`T0{Z[JJKF|֖6*+-˪ϙ$$EnN?,Z[ua2@en^yc~[ {<G#0^K_+X!;Y &֗?9֝ "(*P38tahA#ӊhcM_CM|x<G``r {E_HcB>vtĩyE "55aل(>i =H˧_~DF`#0]X:9K6)N>x<G =:GqssFGiTXX\[EC*! +i:TxSSIVNNijp̅ͱlv-qArh6x<H#p,Y 50{$623=U1:s S56]Uخr㾾u:?G9|ߠ^s3Q8]=]l_)/n9]aFdM{ÆG#A!b"=#4:by|s/'Ca#uEJCt;mӌXC-&)*BeeX?I4(W.S2oPp3 Q>my*S;ޢ^+oߡ߻_Lq:->e>;qqɄ:OځAғ~WG#het'PO&Olai91䬕m9O@ʄ#y%s~U"x^ꦞ|hOy< ~'0H}*s=E'̚K9=4sn\4_Gd\C9>r4No^v۳cVReiԫjEi lDEҘhza<#fm!WP-8ZichiOm88h5egIt5+/o 39΢%g,39z߿}ZfA/m9R!srn*AgG[7yUpљL21:2_v_@qh9I*-+e0< =z+P[;BN6YUxl#CkG^%0+y`S.Lo^$=Sa#8BGp#$<1X:%/D?(ǯfaЩoFm|66% uL6Q=##x/ׄN^J9> 5uӇ/0͘\AW6DG=N:mk;D]+4<%Q[g{[XΤAE"͐xcWu~G/ڰebNùPl0wpRIdFs$=JgbTy-G2p]6̦K:PZT;2}ͣE P=ks!ͧvڻo;uRUm-Un,SGg7PcAjlijdg7vSC>j8HT[;򨛷PK['sǮfm-W[0?7RqA>>mQSsh b]VTg/vSCk#s Cm_=S%"R;8h4R7/ޗ)My@ 5I67G_c纬]tΚ<"+e^ƈ!x[a\ ~Xgyt 3X S  ؿz5GUhby5xdcGݹ|{qrc ^I<GF@d{Ŵ`)ҖD94}|5myMj7S/|~zuԪռKk8Cp|&V▬1CePV3oBoHv:d xP-4UmhH8ש!SY7$Q._a]yueta+{o譭N^N ]uGO[_q[Anl/_W1ϣ6zqcϋcWcU׬㨥y?=TXVZpyG\BEt/~+߼WE4or59ǩlݔ_^KW| :e,jkFw}4i\kvf?Gi:@GIsϦ+>t&d`$$9m=LOVz==1_7/Gϼ͚8fTPGO?T9W]Kծ=|EP@N2nM{(/䛩 KT^TWM00oYTITW;ڹ_4GMf}qpqh1T$M_r_Q>Jrh_vvsF.~{G#&RyUX_+/*p;Tsꦦ;Π_KASߥ?_uO;锩qgK/?ӫOV=cǷGg?5;J ״qb\nΗ鷻O-^.MEhji}sv}~v/.r\&ԌX|wh͚5KPgg'wy4i$)8+~;NVCVUQusm'cr@eP[*K=uqmoo75ӵ̿L?k8c~󫔛^|.&[^Ho=?1줹+?n-tƩs^IO?4m*:_~Lm_1`>y ٥԰N-*hoOS:utEgP]?/课e⋄ûњuЇV^B_Rz?5f Ө8K{vn7[VN㋉uLj(#x;9^ڲͺ.XtW5ЩҺс[*O_7:{ѧhA[==^j/NN]Q*>@xV!^U.9iwӧι6$i<_vZjf]w4V߱슿q9tߢ鳮k0Ã}>x<G `ˌN'pVN_t>UVWigEi{{I/Y:PJ9qm&E%żZ+ +h鼙~q bm"4 &mܼ[F~EtR1_x7kheTW56:MYx͜: >Nڐ p!{[RCg?7qv~~."Svq1m9ƚimhθZvEƭO|j/||u?M8V,zѯ{vzjS8Det޷gt+ѹ>C0^|z|ã|:*Kxٻ}zc}0[{ӾRETăe':@G#xE@16^..\6s-[wM}7hEEh^iUp֑O.܎TV9i˺y+}MsM]]N^Tꔂv^*MimxO6lVW2 8~yK7L> ]ve“vZ8BRa({5Gˎv쬳ҀjqIr+W_CsUg;RD^^M=_r.0@mn{.\r#ĻiTQQA/lVh= MUW/Sֶ]4[҆ߤTnD4vHݼ>FyHoo-GwwPil*ӶݛiWy_%4c8YWF,#x>3^kS#7cW?*袥}=zm,ڶ97j y%\yZM_o줕:zԾFE]8Zd./D杘b@Bxe<]e4}S'`a1rGIu_3_U"/ŦnN9ZpTdR}q77!K?kLW1. Cn౵\?q2M;nv\Zcuw=.TLXI*r&L}[v2U_iwS~m<4&m7~$efs}i;oӯ}:t ]y)|ʼn75;x@:ωS1>l#W-T7*lZ0"}I7 @azg;OP R{IH'Az~l>" |ݩ<3; BVVmَX*7[j2.r{pԞ.܇]D,wl#6 "QC}u6߸]u(A)%9Agڏo2 )&iVGDpԾ#g-miZ3 $?lmiK9H$##MQD 1ٷw,"0AGv;h4_%x7|9Lkn!6|#_F`DG 6nC|` NfTc(34d`rd-B#bp~֡! w<;~xPq )1[N%@#ge g |JŶ[#3p;sŐ\A!ҾyTfwMxTcExR9 rmV=5c#p-BiF&x s"*j0>GP^݈TIG1/yvb#͇\$2'Nl=)L;G BFRҾl޼k6T^Ŏ-LƯ{,{K|)=3Z{Hr,5["kPzEOhRVUd9Co +"|ܰa8왈ؙ;wN\<ߟ7-@r ڋ*TBbʸSH;X*|iz] wqٔ܁N1 ر+l,ڎ߅.&uL{F@#h,' AJj7'Ӆ&ـ8Z63qJ윮~C#Da(p}=?&''Jl(8Uhvbh?ȵ(.7Y#"1iUܼJ:)pa~LZ!($YG?=:ѧ[&!bUX1;$`bQj@Ld:$u9s%v`ڭwh#5% Aq wZ\\ӄ{aFsѿS7i ]]z#bjabv'ݷuF@#8"DULhJ )5d`{c{1z.c$Yr7dcM5?t#u%O3_3z[~fة8Ar4OE,c f6ϭG9o's;dKb/kty+j.?G]\I0eN:|`۴=2ҤEez ҟ ܀av# Yfߛs/>${ f&}3ʝ+hͲJ`jYX Oo?tRvnݐg֮ĭ兎]hj~R=% ~#*зBP^Q5g>!LC{R=SI,M_Hp9zq~TƓF 8:?BRe+{Gw$d405#6:waqp C5ɰ `,J[㙊i|VFlZILNTM7R!ĢZ›\0h(F½G0ԐlF`qeL"uMuR'F*YՕ&tՑ${$yS^O\^Rh|.FȢSSDX"B[eE$٪8ٙD$Z-kI*t,*h4}tr4'W™_NCىZ3@K:0i"U- [B )xBZ=MW8MANlrm2#QnGp%!5$풗ĭy7K $ T 'q`pX0Z!bBb։{4''1]lm_58=άsi:֣6b:3LQ%= 0"6BeAg'J "={}h4S 4lNCOf 7D[*dˮl&^B;I}6]*GiMRBBeZk6Lbג?Kc)S.'b'& WQQhWN]B93ǔ o˿-?ߊc[,'όF@#p"ʴӃé ]wzmJ=[~ gfkEF4k˵5Ee*1f3]Zsh869&q,_G=ڵa*b'm\>h4F52͝_FD```INB_ Iqzu6rEt1P[ qn޶;niTF 2D4F@#pD@ CƒQxwV_JvC@Rw/74<~*#vxuÝ\ zj9s6y [-F@#ȻTL=1 Ѩe=XXwA|]7gN,qȵUx}h4Ft 5Y憀v9bSm=&hXqN$5:?\flGҗokmtyX*nQX4m%8[{iq$n[~y4kO׌x43f\[pG#,Ӛ<7<7g:a[q_k:;m,1aU$ͱk+OQ)Cf:V5ޱέi:o kfc,DeƳxnix#a׎O*ɤr8^;q ^[M9 >gsND h}uGg_Hrj4F@#F}}+-Ĵٖ95\k4F@+tp6>wrzk61V:-h4Ӊ~WNuYSg69<\Lt\F@#h4g'֎\;[iy5F@#hX\es}Ƣh4F@#8+prݖYbF@#h4g,NCX`F@#h4;\뮠h4F@#8E8 6קu6F@#h4?NCtF@#h4!ק:F@#h4φ&?:cF@#h4 !l뚺F@#h!:X#h4نӐ볭at}5F@#hMʹF@#h4g(NCڃXF@#h48 6mO4F@#hP\i4F@#h4hr >h4F@#4\k:F@#h4ϏӐkmsw]F@#h4OCiONh4F@#Xh4F@#p 4Z\%=RWS#h4#4Z\;q/Ӣk4F@#8Kpr}F@#h4#ɵ7]#h4FBiȵ>:F#h4Fh\kOh4F@#Y8 >`h4F@#hF@1>F@#h4ӐkmsW'h4F@#88 6קW4F@#h~NCTt"F@#h4iD@.J#h4F׍ӐkmsvF@#h~ 8 6׿h4F׍Ӑ_w3i4F@#ЊF@#h4gNC_F@#h4@iȵ>F+ F@#h43!gZZF@#h41 F@#h4 4Z\LF@#h4NC/=tF@#h4'Ӑ듩h4F@#%@]h4F@#DiȵU?])F@#h4*ܝ6g͵ 6!GO.YZ/X r&??ɵx?Ĩ5J#h4?/NC^N6wd~MMMEN6ɊO D:) GmjW!D8Geh_U5ue4F G@@Bk58yMb-)lPe-چ҃(D}]=l$^^ Ap?#&bzU:F@#hN-NCINRW|jLBc#O 8U^Q$8.pEOǔNj̫gI swCe+jk0+ѫs\"Hؠ7âElJl߽$Cni8h0 )nN{t$h9ؽi > +Ѐ,BWQ#h\XaOBfD!Xu ?tM>ƒ $U{NlusCm!|x1kmhhh@ZftO#/ܧ &*-7Leyٿg'?x'pJ3C*B28X?{zNz]fyZԺcQҘr~p2ȗ%$kkOC|ԙSc]>"3_= ޽Rt /r^yǏw_ NDqrϞY'̼.fk>J67$m㘏c^ؔ}TUNkz_̀W}.)\#OLGۏc`{8F@#87NCkb-+AtdtޮY}3{ ƌ_9*r-Mҷf| c5c.D4H9m&iEPI"[PgB7( 'c ;$J<==XS ntquSة:˨N*m*+azѺ[|f^ V$*v_d*ks0(Kăc_;;6DLメc&svwe! ĠUTzu5m00Kh}>n,^55+p@.rpMB#G# YvI,+J">BHPBjT[P_)b& G*P P`,.BqAb_K-m(a>(;99+,Bm]=x.򪎨K.  RwlǮ={QgsCJ.l ?yͮ!6rTTlpUCWåހ[ROڳ ފAd{X5bmY*|6w@_?A̻ř265ԡ`)uM @#U8TFf?`)hD_ǃ,( ^e13Gs(:jSы&L /%}zPK"bXh 0Lw2j>ӝ|\z[5Rsvu'&'[Rg'[_#,ȓ' G~B'jDO#ˁ|/?y&?"(b4t/׍?Q/~GcjětT>GsUضN7tm}ojjҔ>^ɑm\|vg/E0MAFi ﰽl3U["m]~Yَ2ښmTn7>gۼv؂<Հ9nm=m|{ٔUII :Emv-c|sZ%{mɶ-\Wu晙OCa/gخl-CLpev畨v|Y+Gefe1Mm*|m]#]mLl7Ӗֻwo۰mSg 66ĤHm]s[\dP+l/f{ole XwUm'؄3^񭭲O=mAO;ޖ6hu6#'&Z{/l660#6'lq b/̴V7?Έ)%v,O= ۆ#m{Uķ{؆ې>]mm)T汲x+غd \%loY۸[[6zŶ7>vpmsf5g-ߟηUTz6>$鞞fp$[~e[UQWOS}W&M46g&U^slv@>>.m/mĶ8+"l>lc&_b{kL[_H saOHWl&lic{lmw=Ƹ#%2N8a3z(iӼ>Gg3OkӿHaڋӞsZ}rBp>ALW9h~ ϨQ(Kބ ?(|QxG'W )|SxOG ?*|UxWgMnkr]ʋM'kE PZ|يtlCEbMMoju$cؾsDBJj7,ªcx;ܸTӆ üo>w'^y Х[1犿nߕ+j0Ww^Aa׾Ey ХuW= (ܿ*\?`BfAfWc->cQ/{ V`|>{SxT{o ==j'$ي+<=\EMz旨dEImyW ,&EScW`8P$Uށ=zcYlY9WN ʎZeQkTd.wxyLpM*H Qp!’o`*L0*oB}yϲ8j4 ؚk*ApI蛑EĶmĄO!' 7z{R=3<*݅Wz9lٹOKk wmóE]yJC#<55cn۷(Έ e&?K'ѧ_AIUUPu1!x> *ˀL޸|>؟_}%g$nXoV`%BLqFq ,cywHfc[w3>lױ b%X=d{U\=Ԗa(:Xn<;TEsjv*s 4Z9>ZMrjr2?'߮YYj(܉\D ٟ:G>}9{6>j3ҏkk\rr8#w ܣ5>?q?}j۾-eٯO-6Wv(ߠ3X;w Z*g3Pd BA(qJGl^]#:P?G'$h1L-t27\ͅkPw | #oa4-jA;w/%_#{~|C:eP]QʗLO(޹>N{/<@o5.&f}GA鞕>N\{ŅZ.[G1b8̛2Ǜ> {7ݏ^GƒrNL7ѡ8RU⹿?GcZVs.+pԋ $i) 3xw?ƎKN`cOKo`ܸ1x{G[su7pq[ؿgճ]x>=1tPlk>%+pwƋh6920[`P_ t$a+kV暌Cy0dhQvw zyb-?\> wl-![5b,~uUϧ?ޘ3a J7MCpigCQxᱻo^&↍3HD5 AiSo^ݻ37Kɮ}uw[YCuVXJCGvらcIE{vy CMV01soA{%j&Wc?O 3By2GoJA4_{sHBa&razCK6/9EHD!]X:"h-H$cumcֹp_ :^ >j^ |I)5P]@hBxLg"0I}ók=>F^f~F\#`ֺY[Oc!>|c{A Z㚲8%8ui,qHoaR##xX)_620<Ǽmy[)Ggb!#%x{q+.}%ptX[?cn,x~Co0̿3֔u"jGOtp 1mV2Kv!׼3:ækE헹[8>{K socƢ-\Tt51rѷ/סo.4x1t\ь^ e7?$ob( BjL+m$ַ)<ԎˌhJ\p%f]=R@B(߱}>>t:D,zffh'`i=v fz4LE(*)@)ϒ˷.<{ zSzr>4wp-.@ɑ<QS+AI9;>z+T w  Cz6-'7yFŜg_W[ CG[L!]{ϣ5lz0q E:WϽkh{ t\qDv>ޞ8/y qSyKDRȗdjz5Kি܈:ŧ<kkPQ^QE 5@Ǥh'{r^,St~"P{`qxaL WsK&#>̿Gʊ¹vn#r͒yx׻;3C}ѓH:o91n .LV2rNrRCy|WbxHd7Xt%?%>^t`}:wN~ݣXZ^AI3O_!?\p- 0H#c1pdur~lݵ#r`,4bώM{P@g#FlۼEy-Y9E^S_$ۿG-קSήIgk&RTy s\A dwk.Yf~yyxm pOÅo@8Hؿ_mGp]m9[,`BX;IhʔLf4-x&&40I#$_knloK"[x8]"*K2ŘyU"&M{\(_7cȤ&RG]=06s >fs̼-ȡ4guvՖ뗐;C7C:tS/׫sB1P(GU"" A_y=iQsk6 ǭj.xtӺ(,0 㶆f}DAM~ߊXٷϿ ?z-Σv|d{;0\+A(1z,m3u ]yRlXM ]? x$)G!\^R[}K/BW;YNrO䳉r%oI!ُ7* *OxSENWυ5u5c"4`erUC?gRb Kpayؐ=vW.O 83/ 23} R K-$\Z[U2(bK;l]Ē0G$v \ #S+&)eGGjĪh7Ǯz0w~ ; ??B~[Q|y>]HSͨ2>af}[Wd;`za1!?ՏхDcJ*jI▇IU}rۍDxEa媵ȣ=y4bc:Ux";w0 }I&enԸN#EhbHL~.I̷;pfp tǪ-܃R+KsilgC^q0B<7H(Ed  %ۆbdȄKPh)@~Eܮ-0c:$'7#[W0s|Zq'Nhk.sǐUus['kq6/Q40;;/3d`ք嫳1*im%==D^tODe AH*kPjLL鼸x״^L"RvZVME*OG{t؍hSg⢡X} @6MC:+-qmOW/D9DٰB+ Dy#ߛv]~zϣڽ'2 f5(,ać޺?y vOm@1w FI_,2F^A$_b]AZpaGe5F&#Xa>#1<= 2Z-`lF"GǾLٱw5Vٌ}9w~@XDwLl Qss9\i\xbU~=;ф 55a!8I]~d֤='d_7;tCwn4A B.C=6mKvF-o823_Uzɿ-6ξUrˋK4)/aAYwl3۰p*L1̭ۤnŠ+enA6WX݇jїƝK&w b;cP!H Qʙnj8E_д,DJRf9fb39t8$r@bi?f'*M%aQGF]h+vnB8۽oJ*w^څE[V{pFFqX?};B~&,&TM <(EEW2_s0YhZ\t<^qѓQOSf\ůG"L#62EĈ70kI64oILw2nh,ډ0|I2_j$ۉ~]P,[pQ#!ke/׻tVw~'%-DYr"B,Z&OB|L-PTt,F Dz(j,DlGO~_LFPC11^]S늞212Si_{ v Uc!48˗AE;Z4EpŗꭊĤ$؃ܲzE͂쥭 H7sJC#F3|;o&]070ĶJ\^5Q.xO"K ! dQF"շ/q Z*gDzl\yH5҂1&U.,&L =bx-YF y 80S$w~q+Mod?&VUʐ|'! />D+ ŲeGB7qI1rXX-IRhK8Co7=Uj4W! :\۵_9`䰁5墝DWaMS ~}l ذ{>zbh,4aYxkŇH^hy}KDw߼Z 7:JHʝ E~e OyXwL8ڇ UŅ<)1!(,ݍcBƻ*_K o(;mhnwmÖxu2ѧC&<켝i̵4jټ[FY8r8$7FȨ;Ֆe0YgJlV2Y(<_/6´a!Qw`2|]\ 7v~&(*܎=6 4 ^nX;|FeD(r]׿LE+`ޖؙG eFB&ܛc9Pwd*KG$aGzWQYӐkč74./ك>YC0nvLHo2i*|Q\; ArS{Ҏ o{љX}\j>${[s,, ܽHWi>5m>FIAx-ɭ%yЎ74 e٥p vgyƃq;*\ϿW<$4;^~bZOmxQYæS'<9 ;Fp?_cZ[,$Ƭ1ͩ`PQAf<: §9պݨ!jJn&aԄ à~ H ж)O]6"D`u(.-CpxTgPO8=`S$en=b!53fb=\#o,Z0nEUz&7"&9%Ts{cxQ"R1w1n7p(SR0kwKI"sz|{(㦇֘6rg|a]SK-8 h@+1eu؝sd,\p"EtD?5p !s9/aDtG$.Mk%)aԐ' OP3G8u`FG2]Wp@8c\>d2Rzyϑwe-Hx*hw8.x.2qD0^_-rJ&"CuK|Tz H :nNG+ډH_׷%GiFnb*tvVw"gqf`Ea>ߌbA%8?> /#cQsy4˖@j=^pݶ©A5crfp^(ʷX5"_h,Ɲ;~tOnxrvo%z4 4(#DP z4pGcظ>t&REGY ?ɹ +0ϼdO&v ި8;ޢoVݬH-a1?qpFn[$lQ^{/N'iNs:P#^K/%Ou\e9>iѲ</'C%JcC-8`dIـhr鐌~)ѡh4Q~7k нW_.!j4%ںSY\̸U7;p7H 0? ݏ&48oA `kiJ$k'PDEwÅ}/;Hwқf[E&IǺ̊ >XLo8FOasnū(n1_?w#>]6U6P $<Z2 y9Nqh`kM-_>:%fZ W.ND1]Ĕ= ml󳑚soζD1BC5 `GE9g̀l߷MEk;5 10) lVu>LkY!QI4(p)SOjP-BӺibcH0NVa9I>9r4ydݽޕW4YCXDOc0`,g}=[(J<;ly,]_hz%_Í OD:1=;ϔqW*A[w$߶oL3>j~hr} (aS >#C4RS-/0y8KEcq6O=ʣIoR;>q'ʫ#S,[H HtOO>|Aguh.<N҄RaILRVyK?_!fVE%_Id'N %ᒙǠ`l,]Uk=tz m~ +|YdqviX/Si#c#Upg~į Pm8M='y)YI*ze E_jRxrj7a&i52o+{3qd,/- 0/14+]u0%udnTE{7מF׾C{b\}RTY*xYtm܁JS"{c@ߞJ-ƍ/v@~-Z-[J7ZUH24FmծG%RmD߀8eʌU [ dSV~cDt.m/_o 프ۋ#0{!v';tԉ7ks;&{ TФ*=8;|ïƚؽgD"QŎ[+@TQlu43 ^KtHMݓ\@m׮@Qy1*Q\U*~ KwHKd(J2w! b, QY (0q3z-,Ȓ sydvEHJ[v.;>!WY5T˧~s')kGM0NԽJ/ĩY !;n*<< ܝe%8KVY<▍>-: se`>=}6r%O`+Ju1sVyj"wN N\UtvaIN gxl]BzWU п+nx8#VA@jn$=%g53B4Toj99ŶO1DTyHl7E! lJB'K qw;HԀpCM;َӐkg-{@4f %N{̓ LQ_M :kX灭_ߌKPSyCΝM`\T!.Ų 3 9}97pU`LVz 1'ڥ#͗TvC1 B% [בou\wT H[MFKԧd ydL\~ݍa5x0K=ԋ\IaEPy?ʬ$;w[h E+pЙ{ SH]w9vdDf|4ږDrR] o>"[opjxLr \s޿~L8qnӘxI+ hZ B祿˕qnK?G W!ҎB Мꉙx5(ٻE#mơE.!$Z=21[eǂE#i@.XJ|9YΏ%c)~?R%#5dYЃ3{UK9 Ed⦌jiɻb:&=w9Q[ʿW+W4ѼT믜HDoXEh[QǐXvJ(ld/t⇛m߰>fLЗ[ Q2{*1ȳFbۈlSuujt|k#zcxz$F[f$ظ quŤ UGQ!ZIiY$IvԄ@|]l*+^7`h|(IH'}ϻV}2M uuu ޻ "_g4/-~f8ޢ7PXJS Dr]ZR?~k  5=bw!}{$L}'cp ~'u#u/2ܨΔ?A|fpA[62q2Cm)zklg I S/-HsJQYLdo`G?{a-Nf1sy&HVr-I #xF '4r%FlDi5owZ'"W}=_➾-hQJ.w<{_^1MTɬsqwoUA| A90:Ͼ??5tuor1nX|;{ R $mZ>mj{}=Ɠ<'BZr _DTTƛ&s<-V&tŨs.č羋~$w˥ݨM.$GF˾љwMspc/bxAͷ" I>n*ϽHv5Z> F!q=S0?IdĽW`N/*bm7qHɗ'^- 6:}cEIVFJE(pJ zF*ǔ?Y[ɿc2p!__L%.&x_ֱ-VCcI6'\=Mo.MLd~Ti.) / FFZgš55jxQs[{W Uo@gpNUg$>>h|~7d^nf( 7jFe\yߓ8S2G1sšFi&> N-YOwGTX%.4m=I"3 j8C)uR|K)Ac:6kyz=9cd=܎_`@[0$/cNv*.00bA\{~2dp>ɡ;QBnM&pAh헨섻߁X~tƵ:Ɍ/EK{cV{;[i{DžҌX.(Nσ&P~EI[RnꉈHo#ǥ8SSؾ0=HѴ_D4d6LEq͞RR b͈c gYRb'p[jr<']yE8*nuVUd/@z;Hb[׆Z]uw,A7Dk g}D˽wʙ3̝{̙ A^nJ>,%$?Z J:4"ۖŦЖK46} 71|jjP]_j*F4U#gCl:呝V3N5kZP_jp`?za3UuRmڧُ~@ݵceW>NǍg6P7 oMy \{ |Tghp~) >z_ 3N۸?*7<{йKoG\py-1Gpd4oA<ʇsP?8eS۸%>~pّ_/?Q =ҒULMvU#r;׾X'LGXxro\ _x%h;nLjʋЀW߉߄` /)(Ɛy\`;Q$v.iy8}OS`$;0 q"əyGDS+ǝ< +p:MBAۤKnjGwViۨɕȸ4<':k|7%_{U$."&P/7'w?1 bHuʙG]z:=)lӉ!hNT4_\]I_"#pyk gޥ4! q`fm_u)V(\\mp7fP`vr$W`Y[X` j]LM!Dp]ZgHSµYV3ԉو@U^mj,#~]A!Oٰ}9g xB\ %M.$qٮv֣ۗI\ Cb|⇝+5c%+#q)*1\-Z`q6؇y$. ng,eSyREoSiβ"}!Vn;Tz6jiPS60憐zv ٽ/Fl ,e[j3{\p7||l?5ڟ5-s(4 ioW}]dPߞ JЂ{p GݹS9 Ƞ$`ݜƍFPCQbF___hagz~%1'J^7b TϜ9< 0\1uU┫H)qoPF}M>"x9W%DFՀ\%ʢ-Oi\I6-mr%{P^z;7>qJ<ҩaC };N)J:GT1>0g19<ă'E Qb\quf9},6!_H"WVb EwJ?Vڥ%E(T##ӿGJC"Db<)m?`S"Ws8iN|%:\79< :?.sW};oc`bDwRfôy,+?I0Y==Dyl({@K$/wO=26-Pr<ȃi&@l>l W9u[CͲ8zޚUE_23$R>ڞlCCbkkk^r{@q"{pOw4?(#ҖWJ/dă \qo1Gy l#I˔ ;?/IF[9Q+q /b.ƛ3`kt,˲l}mQv%oA> ]QbD{x-S8Qc_n-̂o@]%f,~kqO mW]Eg5f7ɤ8#/-eL*7i tN#DWZcHcf/;tWS҉wlo`EpvIk<ޫpEK!ZS5ݛ1=})P5g4o\65Ic RFy4(|Wi1 l :vA!Oݷ[ rpq$25F` ̪Z%:ŏN1GDʹk!jk־kyiI:Ӓx\^AiNC6ì[r"|XwzJ,yu >7L|,c͏Uqݿnpl CE = d2q4 ϖܛ|ז9V%77y?t-⵰|X-ɧ%q4W6xD{}m#SvAxba+V'~pLo|OsXqy4Op> /{lM~K+<ᎅ<}<\g:| i䤙fgc&JJmaFDK\d?없v6me:ZY̰r$ĞN iٗY?iz/m׫K,p=i9mͫ ^?M1ͯ@uy9sGx]&" tN?@ Yfh{Cmzubt3]fH^] j=13Ή İ9Չ4F@#h~CZpbJVpUɀx2|Lړhi[SK- 3yRtX[roO h a3Lwl%+5ܚWKh$HioMܽj5XBz+?R(ss4#p"X\{:MkZ'KhuرЇ-Ʃ>T?QNI{+]KxjIcs2fxhH/qO+Oog&8NZ5̶%Wk:Ҷ$=Qs$G?GWt_#27G9?"ÓLִ_=7&[BK91ZpQc{9D*ןT#h4@B'mOkRɾUUU'37So±_${396z8=Hb1Ch&n׼]3 ?VfHvxyȤx˼p|nc:Utrdoa-1n˞V6#m|sd3bc1bBM>ğHωN:^Nc@JG#~~t F@#h4@Z\7[S#h4F@hV4F@#hEr=5F@#h4 p ͊F@#h4@Fu74ͽF@#h4F6˨h4Fu#j ^#h4Fீ ˨h4F@# jkmsF@#h4I jkms}j4F@#&&2i`Y8558h7F@#h4|p}ud Mom9q Wg}{]t3b _k;lQi[sɲoq2 ׉ԃVh f뷆9^j0__4/)V>{yxwll_-i`:_F/@ّ]t䎝b̏}ix2Βx*Ա|kGKಖ']gy9i 'SǴjgGl &0g+/n0ɼQzPcڦDN#3;Cw`/p'5͵(/+0B}84331ۃirW^շ?Õ}:Tsr<,<<\#}#:ƥ^\=Ü]\P^\v!Sg{4Pc7&iPn:/?ѮY 7<ܶ4נ@..(޻7g{LF~19b/C̅Y>S<ʃqEsnh\M`n}8_8Wimi/YvꊢCظX>\1 cd#h1<'ѻGG8s&2cbe6! Ɨ?Vyf^fbi3qM[_h9-4UcADH%غkRӺǝm֎$#S< Mc&_֫gaMZ.|ʊzFv _闌!酶ĩ`ݴuxP8v)8/z>&F|v]\cHLދr2P:uBK6W[_~;6!;6`?]!TY;>F@#8IZ͂Ɠ,I%I"lݾo}7={u'ʇЅ?.W͟ 46eď?,Gc*aAuŤ77W\͇~e򗏨_EQZ\Q~Ek#2nVv":`%yn])!3]:% 死S܀L; 'eHJIE(;oc-xUNMU9HGnq%cbۮ- [.Cѽc<\/!CVV}}`JTXh6(AVn"Fl. a{wnC EJr2\˱`6"Ç'KIf`KW5cNrübmCf<J`Uw"6 v`s)8#c.Ը 59yv;v1 i*+VvCpO\a^6((EEy6o:vH]ŪtAQ^& ɩԴHyl.ep襰P3ALf7`zQkXMO7f"}NF ,n^ oK~>|K*W&8#55԰*"✰Z58*Lp0!.^M*9̨*ض % EZnQ9""ُC3Tv0_/TUV #H,Bg=6Ch*M(gvnۂjŋ_[y_9]i=u(BC:xV}c9\Ν;ͼbm*,gݥ <8@TU^[#@xo_P?/EO4[ncb6, :<loŻQaOfPro\ARbX8 zSNe"練kK] b^R73Zv͞k23s抌}{Pڅ?۝2ΰmڴ!m@#d#;GyQg[Rw#쏶؉:ű sAws ÒUgq}hN C<^>֫ܟO$Igʽ/66eucǎMILLpә<ϧ*ZhTaqēGn]yDw^'WR=7q#EC;]V9w—!)]XeJaؕQ${>f1H%=(E5ʿxl+rE](0&P~ 7,g>j*&?\1Y:``{mkwFAh&㎏^&} /j<ԘPL~YL[yfuޅt*{M$ OŏK#$ I=U<`C ;xgGӱfj]a@@Yo)dloLib܏q/!C8fLzj-%5nxX8G*V 7~;J#m([5~q%QiEyé0ij0oƗ6k!܃p#`3Qu-VsE&JLe/J{e>HD܃ZY4 +c@ߎX5ND5KW!! 'vQ[Ɓ7W ߭ڃG Bсt{sBya^ :R^|X5xa1r7B@ޝkO@,`د<8<_.݃][w" |0hA}u &^d>U%9pñ`$4~~UvA7{ /W^=C`Ex*’Ep»B7mpϸѾ0 GށkY y{qW`O>ļ%+E\ͩ?>wߌ7g$s;P:<8hqX%%3o3팯|6d̩^ze )3>z~n2#WMD>"91< *uLxi=qטL{n[.AsmiQmۤ.ImcwW3}~]z,{7XvןECXw3?<KZ6Q_MO{1촞8 W_v5#GՏ6dvx>Z~:0 ցDh~o|cǎ%'OJ9ЕroGDf$)sFs͎"Cfӗf:?u+"WW 09eO͏FRt'Ͽ)>  {'P]D B`0m!.<k~/U_\[Ow-6lݏp7wY7M( iq9a!dxp7?M{#Be1wK1foo'Cwb8GtctjCz&MB|MCA!ZcvDuc/֊둿q-.v+c|=:N@Ce =RW^r%v\5B1<~]`}- 5GAI9Q^W_{(xKq_y{f@<1BWP 7]|^oU+ O~3_ UsquڸlqcOqSHCMرs/B\r;`K{>; r?ub|}c&mdMu%yYxw6ͤꍮQIͪ8c8<,#0K,|%|L|z{b”U@]{Qzߴ~gWc7W"anXn o~€Xt›#"L<{߱=n^/Z|r+"1ʶ+BpΨXgMi-V"@$DwGL`2m¿t7C7]ArQ\39p݈WޏδY4% 0zh,eiaW# W(G8ETWaƠkqqڕPן[N#54q3q\hQ$r*D\O3ԕfQЮp}}VN;bOxp*Ճ*UVrO$tL f-ys!+]wwgjcݳ[Jھ#.Bls@}pMM-< u쀊Ȣ=u⎟g ȲcNEBgw5EkνFR׽@ O<QߠŷlM?IJsR[%n,=.}YP)5NK`-]C#c pk놉>E3:lظe8c[okq j@+qh:.,AZ0lX3:=]F:vǍUU X ^{]x>wIRQIp$˫a#1m_2m3R{/^*W@._.tN%˝+/fcP>1X0K#}jh;F Bl`kSp(ѽGkZC9惁ayI=~YIgzscbdpD&O0zkxύйkwyYjQmD9]hv6~,\\u2͢qַGEZRA*]ޓBm_MM5ܨEQ.mSN!>ӽ1I8XwML-\~lC/IV3IC3 Ƙoxe全 L QQALo /7(+g\%0ذaߩ GE.DKPPTbߢI;f_do;x6)Ud>2+^>³ɛ๜rcLyJ [‘7|x/VUQP(`rO~iīg=lD FMN1E!~È.;gvDEI,_g> Ð&b]RZAz'f!(; ݃agQ0\p+!NȤp<:USceh/MƓ>jeAgg"<\n62p`X7jKglZY1OD ܳ70F B)5Y()7 o9p`2-Ss`R YyŬ UE%& voEH5rܭ2$հnE* Ή2\Y^NXO rR΃̶iKP]FǮ=1װM4.o3ޟ4 z :ԇMkf8zPM~9uO>j |:Tg`!gjvjx/ f.glZawC-oYt*k'(H K+9Pu;ٗQphM~}%> 3*ϝ؇9q@.rdz/j)s|q?O^m|!eCx޻0{0vXotŜUŤ;.F#|!\)Ziśgw5`jɝA>SۮWC!SΝk+?sV~?]s;OyirD\D!F@#5h5 ;kǯQ*-7YW̕6.Kdn͕2ŅAQ$N>2~ZXtnq/Q5JCM6m.XR.\6T1ҢlTXq;]K_%>>zE$E"|aX:*Qr|ezM۰3<уvOoGSfsa>s@ tqý VoGhx$bc:E-G(<\]:}~X8 Q|4uQ޶!28'I]- 裴i.* z;nvm۶h*҅3/ŇN.j'wVf;?Ͼ49Xl?ÎbJ8o@o:pa(mE](0QO Ɖ (@TPFN¸m''#C׀Ap}\IKB3b|4cU RPUBNiQ+->&6111,@ 9NE[TV/+~Ppf:Ž7ͷC$kMCG6coM7yq@f1"砆™8gdqm!.bs,A엝"<` KduM+}/{+£.u>{o=93W^9X`r_.lܟSI vn ^عa-XνЦl_r!bf|&YIaWb'E2// ¸G> ⌕l<"cj“,p,f!N Y=߄E?MxAl+~ȣك q}-6`w5zg`4811*]VZ-k֣mDj(,/;Vof_@aSf/`wfJꄻ\چm<U@ +7) ɻJnو[ϬXyr P_.Xνvq텾5|0 \﹙ۑǁ}5ߡ̽;~ /2Iؘrm͆hpj4B j+Sgz/W9Ӑw[H~茝 8"N?F%Ridw tJSNoz+wHM墡)_`KQΩ ̕"*H#T.\\܏ F!6+5pgO,Z !~aG . LT;Qt9 ?ἑgsh -_v)T#V“wLSZi8i956%W_n]ӏBUn̚>EC!9LXҎ6(]@,Y0?Z .0 B}R{Pw J33G]ywG4wH0N1󽅫7;Sh4,\\/.;4Fce<,^ uHC^b_BZ,;U{&X4d30շݎ4*¢j s۩K},a1Izns`K_^Q[@IDATjƠ3xCfz$v9\ëPV넎&W2T~~l;L'F\j/9 4uK1hgwA}M񯛩/DXrp]>s7ŤF8=w3 eTOMHƀAftl{ >H ||:Rn0u$K^HHz*'a%=1jH_;3_`qy `̺0h} G1l[rOzC_"*v#F.Xz̙9AyaP /由7q]ʇ(F-mK9EǏrr=[^UJUZc.S44TO%x@Bfd0Jm㢱aI``dţ nTi{_ڥۘ*y7כsMt^Ø(.S|"C_GZ9X:Ƕgϸ◟"% %XYy5]3P}:4pGy/Tsf6f&P8UrEݨ #Fж>_<;҇N驦]I*'klR=e d˟|z;Yf=6jԨÇXpɔWs?*֟Е]­WůDT=?>AZSlU:v3kVP aQE:3ŊDX~DDqW5Lyɵ1gӌ4"\ea֙4q)dL"8)X[_^0>p;u{)R dB."тLLj:j0 ~Mz|l n ~D62k!fy>fv$g͇yLcO3?[G۽u阫J 1 ƒ83/B?>J#8NטiJPڄ)X;S*[F4zXn2z^Κkk-M"}nx kibݜ;2df"k[.Y1ciSH Mqæ;KkWSmQ8QW@2{~#07ƈp[էDӤo#h ia8ȷj`mz3_h4~ 0yo}s?rFW >܍#?-BovԎ<ϻMeljӍڔ.ǚsSxf#qf|ItdqøcMmoC=7]S>.}éiդ!t{_~̴gK{ZMMgf?ҰXc>g f\:ǚ5ho5ק>)̥?~ pyv6'3Wj1F1%3\H{ٜ64Y%O>bٮn2bNLYi.>\yIczOmt0=qwqP }:4v*Իb㍝e$#GӔ]8if9RGwGHهlfo5  =|<+}$Ir@3>CƳ .6Y:O*ȈM$3RËo­NKz`g?qf|;@@ *Kmmd,G Qä`0әgUI֠A&~Se D&[Usi9U+$Aebۮ ,*UsɈ-ך2.THŖ8uhi[6x>){Nl9E2\0hϏQfuV{93cVV"-%;p?nL<2 cn#grdlab߮%EuY!O\^af;@;F@#I]:;]9R7S %ոk1i}xwPC ŠLgD2E(S"QC- eJe+83-!@ZV?n_tB) Y[ERJ㽙Πov~Ug>Ոo "2*2^3^3+At,|v4xQg }%٥5zCYzuUu>xm̘BYvuh_ns6'gؗ[Jc_bHve1JV:ئ ܛD|.>#‡jcf՚FmgH?I+?ADJnIkbÇ~w V|%w[SF@#hl C+Dزj)&>jy3Ŵɯ Э"P_4})aJT7p˺dTsdS۽y.n!J_iUruy1lIGIRR;"4G+*RoMIՈALHjCغc'yrRr2}C/J syVnN;Zu F"5Uc_qptgmKOG) )n1piw[w6*@tײݹu 2xC/f:#֭X ;7p<97܇q7_$&&qjw_ .Ða>Xvn1Y<1 1eEغmOtBOr G X0oR@@4xs_gS;q`'.)rH,´5,SRGД"'J:bx,{T4jhEؖ:,Ʉ)>ߨllݾ'ӹr )7 c.ޟp$%%K H'XlݹH)ylS5غu+ ʪ>&…U$`/8oEU bі'D{q@޽v*~=O Iܲ Jg ۢ),,s&AD?T#qs/cbVYZģ},.=o§vF@# `SS6[&>֫ܟO$6Igʽ/66euH+xb`x-uƐݸ!w=Bc1o/M%g}&,›h6LF}H4uxhMX-5xi`xV܃lZ:g纂=xx8ya6m<^&؅Nꍛ#ܓx/Ix'|)8$!-1 ;z~l}l]9O oC9)A k-& 2S&g"CQť^ԑ ֙O7.kXwX)m}1sX|ѣ{'_< O<oMH'L|>lήDεx)HNkP\ۀnB u 9ӱ~. xw|D\>Y)%[ƤY5x 4'b1sQ/-Du2 dVfK/Ag(rvQqGщ <{k0عf1{9BK:%DןÌ[Tn"]ųejdo_>>OS<幸3 o<4ue]ѩKwF_Wߊ A*d܉|~ذpϸqCq`KNCMs~Z2 +zB{5f|gjT G`f>v6}"(;o^ (unW^ eޏC{-<5'`CMy}ڤ\Czwj(WhE@.)ݙqq>60ib$*,,O<1b/?;?n7^{-W}G^osvxObo3ķx IB7/ ]zl؃[IbPS24?_ܝ $Ā^Pw}K]). r޹ >ZfwGΜfg] ?z ޮ@ PDNF]}^naw?7?Y+sj?7k^{_6ԇ^cPrn)8w#Z⛛fbz(96b`q8۷~-Xo^n-mPD{FWy<="}Ѳ*TЧ:~/90ND }mXH§O0'Xs qpÀ/(#GСTx$#yWL$ݣ!l}BM8ti.ԓcAWVU( @!W])i_92Mji0ˉLYa8sY _;`N\xѫM32⑞V@sPIdkv(!7Jk{\W4zퟅfJUy§NA& ?fv3>H.!1xXx8jbR##"ܚT'fK_ysEu@7ۅa3z#5!F}T(Ѿ&v\ 8aou{iÇ 7kK.XE_rYtӭ ֤Oۺe+>&>} >SNi({!df"tܽWPʒ|r1q%VX|Xժ5:wfM`{{[Z ?]HgXLD6o&C3#>36㣘݄U9\4KcZط~:v큡C"iK4"g?7ŁÅ4ekE%$ UFğm%5 Խzx.F7xprq <~ҋl0u$#X.>M#"]Z&tAze8pu#Q B@!pYPD7ګ}gt]hG_LBnQ8}Zkv>4CvpF>ѳMMC|b*6@,}ێHdB:bɰ&L$16wW^@_ؒK*b䴻1fk9~r}H/Y5cҰ^bEN*`YTjocx oa`B Q\Ýȩ|y33QF;,|7<< u"ejOdH_ztk7=4Mv=̀1#g>56`jnO_ftvٙHn5ij 2+ps氣5ADN9}x{{C<>h:c@`"2{+46߬[ C)@EVMrm½d-EFr[Gwklޭ3/ࡇf7=BX9|ȝ-; WN%i"M!4ƟƻoW"օ0 gЇAHoK>HM%](JiĤ4z\g!t0{ H$)`%R42 ?q0VP<0BXS( 5}W}cFl^ -=G'Tƫd#>=:JNQNKu €{h6(JĜ`AY>V6:wéibY1[:riYlO'_G^NlY;*+ B8{{nؼy;ʉI Ɋ:y4\W1HJLR"(I:s4\|{|ƜO?O)U<,gF FF^)2l_7u:b_gdRl޾žݻ8|p>B~d=;_!+3̶ػj%V.w p>lsI'q":1&|I&0NDN-;QHAyAv6>}r.RR˜o!Q!"]{NAk.+qZ 'b%s[!;wǞ[Wjǚ_!>59s N9vo d^sq-,,Mh$ed`kx"*2\hPr=}7?D4j zEZ[-lȖ|b\'b[ѩU(2;(mZA,vF@?ja__n@zN1Lzm?M3dra4 DDx(l d =GNŠ^B̰q$ˤK JA~}%,L:%9IkÆ !8H4 +Y]aeضk/NSO:vN;D݊w#`x͛U_PaproCaKMرnV y !Anf>-Z]Њ\iƌ bw`sZcȍGpT,~'H.#UkǑD6:wBS/ZHbp7/DԳQ}ltJ۳pbc[Qk'OKc ?N:I;r6x0?*fxL؁B~ѧKkz aA2lM u]gZ=EWy9 n`O~_*l@e[tD_J09_#QS B@![Ù3gΛ7/:44Ԗx [dVՍr[=v,Sj }1g)RMՓ)B,H`o<}*N!P(ok֬yuԨQ qFfdҺ6&ocˍq=%t}9NU#BI>G9pZ]A/[Dٝ[HYA2w׉cMbEI&ql"4vDPx)W֣b0WBzKdK { &Ckx!hIbksEWP LGǠـT&V,Æ\@)#$:]7ِ5oID?(?TH$H V"KUQY[Yϸ5ʘ>Ě^"ެ#8HxId./2-2VHksbu,åFIſ '52B@!P\CGW}_}eU&!ZLVdkVy2'2S||q^9tAD>1) =|2vzhnqA_/?x„(ROO(B@_jUb"pĞ\_e>#-krTqaben,qGgG}(h5X1Gk0pW) B |0&Muk&UUUFPQ'+epe kP<6A2Td[ B@!h84rMdEr+nYi u(&^66ptrI1;_\ ~ ECAOkgL*QRR* vpqhE2* B#`FIN4/j*4Fd499mԩ#Ez+ݚ~ e(#l-XWUV U$֖@ نt|w. {wLM[V( BG@K"i,L J6ܓ١9}- 3P*j,sj˹sYg]z4jEYlI]HlI,K3`wcѦ 댧z>njyuREhkk+;{1Y:m&n:\y [zʀ ~ "M;lz䯷B) B@!p9h0䚈}\,(ڴ nftkFa-ũǰqZ{ؒkq#zr:2dPd~&$HɿoeKI'$#yfbnT@?AoY6E@ҩXW,KR<29NJ W?`3<>l0$%ڷ19v\OqX eNYzsYP B@!4rMAgWZu2k<۸qhw:cZJn"s{j&&~uD?{_b'Q%&VL$%(IkL}u9X"[D#|&h:ԉ$zD*/$pzlm=%f?ckknC5IեX/)퓾uOd^!ӂ2zْG#Kv2esZxR삨n8'n&66OEKQ6nɲn7rD۩ \w ÷ՑF(Gk묾*^!P(? :h,B8M^xwQ]ú6>v9cud ND $!1)ym卦!h/$̀d qg")%;͚ \iQWNuz!׋&"$QeAA0f&#+7vN FiAN<\hֶ"GFޖ1"L4Q\b;GE!|Odap*'c@@o ""PI%HNM#i i\ظRѢ%š6 rHKKG1雖#N~AcN^E~#;7$֞H _ry9+@"o(rSRqm_`jF2e4ؘoz`BYiT_H2Aq(EF(+!yI0U?>HG̙-(#EEd(lHOP?X??ՙooB%2=^JS( ff:ޘfG=m4 }'\hsgyƬ·6_ؤؘ&J[8mi miD[}իWB76X"V1i)i'VYYUr^% 'N+X= ;YZ N%{}2-LCN9mjC}+7t4m-ZY(&$ߧ e9)thىǵÚ YϽf0X"n]6o߮{ZzFK :T[qJ&E9)7uYƱN'f2! jޞڂ+,GiAzksȖdj-tKڹ֩s_`X=[nr<ߎj/^띦޾N ouMڥֺ}l-=T+>c`SwjFcAe~n4EiOg5=?5No^4vl] ۡA:>nV`(e8'ȴRCDZZJ^Kx%'həIZRF"mIZbFk.-˙#yk)9Z)BdgkNkVDէP(]? 4Ƽ!D?2d>ɼ%L;2e>ʼ)T[2e>+互ޒqXiۈ:[DGMW#!mu! ѺFZai 1'O =Pw_^dд1Aƪ4kV,Ův3j} f&gsֈ>ڣ4/K b=mWmôQ}>њ iiϪ%l#J/H|>}u8TcԖ"|k8q1,\3C68uhř1Q'DdqJѫO>AȞv*4I/G#A亴_}_ 30oGGƚwn83bT cqU`5^ظ%1M|]qd]ÓX1j;h¿ z6Axx/<o>0|ٯptsc*_v8s+%{ # kM~h4rvC–bXٸ_Qض'mM+YnMqQ_vJn%"1S*gtݿ\sט N'Ǫ%6z6Y&ܙ- B@!)M!7%N-vѽBUe [9iw}DŽ[B;e%òuYVlz+#ǯ,/Rne?]o/nR)ז@sIq_)  Р-B v!wO~ $dú XۢyD4 -mkg]ȣώ|)\d/NsE\hZCyM"i[LgGkkw=~DE i9"/q24Mq;30'Ȭ{'FvAL;gA;-6l܂S1CBoVH_0De@ dfS{{| 3ſY/>" /چ=fL GƎGmk0H5M;ldg;}Ǚm -՗_Ƈ_|id:Кe,@ 5ӕQ$ 4q͍2Q)^W% Qصe=QF\!~Q ݉k{4 -wއےsYƎ5BذixKXB>p( \XS- Թp E~sV.~ML7˜SQA:g*QPӈKO@\2Z0(_TZZZ"(6Ew|Gϡ$_32 tr)PPb0J1qVLre{R rAz۟AoXx7 ZOgIܞsTY3ۤ g Ց rK~s>NoG\P(7dByQ@iر7z47!w "UB{k"m:b؉v+l8x9yT`Ϻcܘ#MB8lLt<ؤ5Mc")+oPQ 0ae'Z۝X!&Ζ&uK x iIqg]|䠜>BCj#/hNp>ӱqbr;w+fnr7&'g4iEvsljҪ%BEy9})ĂI>YE< p+&^y0DC!܄m{x=LX S7f*ɍE+81<?wvBRMzɩ$Gk/vlÙtm"\id?tuW!j`pwW)*1a9E+/фChnP895RJ "z=FBH*m0d"10~;y}`%ؙS&6_gS_PP㻍B#wihi`VP( \Mnp$ce%H.8։E:wƤwfMtH,-H+Gj8$E \QV4''NaaăW2\ puZL]"aOu]$q %eX݆ 'i߫O|#x,TO#RUB!5Dv9p&cm3OL{:q1eYwS?}݇س}Eأ3 zNgyځ,GrZyT\uҭX:ыuggOKn^>55Z)1PPĂL hVk}2f,MW4SqJ:Upn{ۿrk'?5/lz,+X*pV BAk99sfWDrX!+%:+6 =%S$}˲qfFK^8s̙r׽F.IjD҉FLrI&Y_9yU" }0b,YrD"NF܌ 4&)H"]suM,_jD4lY904hܴB;TΔHbkڒhZ&r<(FVX2Yy^)"_aOX@riGps!=0Uи$SKSgjށ[o@V0]wQWtz |P^^@du:t(9gd]mؑջİ^y5cJb6Of,O"+[)'7#z-7( (cWdKx7ǣk8O&<]=YJFEj M$V4i >.c"ٍ=CzAn 7 HOW}4 T!]Q( Cξ:v5`:ZL0BYl LF7ZՃY;c؊[ Id=G8v.h[ {zzmđ L>w1hl{FU_^FnXIM+p^Y/Srp[A/mo(9o/,8'h'c%pcL14A'ZjU2JrYxYX|[E™|c1eiع[Q'[-1 N2 ?lCcijr=pp٦4l3y{^`XD#<Ʃ;@XՂu'{9v h҆Vq%KzJ&Nx W k$$fÓƑ]#mFk@IVrY_I@fmEϗ,#7b,И }48ZzHdXa9p=~ázEcƞ*5.*CC}'#V*LGL1u#! >>|gZ"7 [ "-<ɏ>ޢTY9 &n'r텑P%H+:GH µ&v*( "Sϫ`-&U +/-ʟgwD.3>}|c ߎb4f:k I~ q9/ y. Fc1Ml Ɖ̡?:wNb-}{;?Lɷ<np!?plgKc.l gW"HOs?CϤwoZP>8tGz "bM2YnhP7DݮŢh6n=A+Rrk,ލDЄsij:RE`Or:3"&ron B@!4rM7κW[ \,bz%6=9[67]mN|2 o,i'c.XZ ;fSYg&ŷ_~әznjw;acB,LEdiM=`bAz}D6ڒ <oڈc`"Vȧ͟*jH%5gSoANA\rq8l)~ ڷ N4Cxc]t61)E=NQ2W/yld 67,f#_έw=T,9\e_vq]6Vhw6KI'#C{Hkf]#}]ԙVpqwlZcrl$K%G ZLA#]aId6Bvp)a|3n,4$k"!'C=ۈ >o+U =WCxqr2ecsr|Aң>{dX,Y F| Si +~Μ=BwȠ8{6; vh[}h\ FI3`o3;1tp-H2;k4Ms^PY~[8A/Sl<8|`BAFV.K3m~^u2EZ]ح%! +Y9xW_ ;|Pk}X3 bl[+$ 3BѷOo$Dch'h +CO<ܒ5ڴmQz_MHK͝1p Ф+ݎoys=墳w~0?pCL@KyoNqzK#xV ȅBX9EwnMc_돨&K[|WA,BWk 澲uFf]JկaRW@X| *I~l,8 .1ċV:&WG!f+vw#='eOo6eMdo` Zq$Fzz z힏g /d²0~n-Ȋ.0P B@!p"`C0_}zu=]10_&®L@|DBӖ{_o>[<w6Cd1 hϗGoO\YoYՅЩXsؕG(#I7߃CMXcZgq)Xx!VD/() [+RL,z9IӬ|^f KiE3"Uh_.ߍ~]w^~V? F%h#zh9d)+&>,Nk}NF?Ė[(7:Bmdf*3/8_r1zѺL}poc}Oah?"K래Vd1H7 |YI><zX w96-oi:#NGn> @=̀&1.)G=G-22e~&d&JAVT7жqִ YzA4o3'[VPe=̣5*:󶾏ѝfф#5=ls(uKm@ߴjL V8H&H:"+Oi06rG&moʐKi7jIN]eGNeyN#i 6+Dkz/L@BQ1n{']PVdn2B XP(5Z,垏؜#&Gqm6l07Ǐ9yJw2Ww5|xkk7r6n 'zr39()NXR's:>TA˯s4y/4H9G&Z*HeX,8q6c n;ZȾz-T !Uϣ`:x^'Q_NOD}a($Ȕlh""ɬKEi1bbb7"͛}gٺh$KJ! 6|ISl YN|Qif_bVس4N_`0׭2ZG:3V?""I:V gq6!YSAhxЇ+II%L#)5F-| аpDlcA֮ h ЭԀ1GZ^{'7ovISe!F>e\aAiDZHLх B"*V r<>z8Aq.*-?ZPz_\Z Kͫ?UN9ƒDS 4;74b]ϥ k&aoJ.#1Z/%7M;R)>ڒI4BKOZI٩4yP?Y#C iJ6 ԜTK;Eu(8V0O.b B7H6@d|e{1&D-4!9|<ӫ EKP֤w]edlYLv-H.'2P-:1m0dQϣ?hzEO,:edGʙB_/ ɲ܄ Szkg:uuaA'wL9}:ʶs~<iFNpӞ!?9`pTol:F~FdSZ;n#xe4نZ"D|]eӸIk~xvs8HcNT"-&ꠊE=)ɇGj*%5eTP( s_^(.I,U9T[&ұLg2`de~r3y0e_\D>ׇ…Juc>2d1DLG`Ť$Xho%_zLuW{_]N'tf>> MTM wmg˸5ڶr#(&w{& Lv__>|~~9i1Vޭ./]Rfu{Z_!zمCLu#QpLYN BD@뫤MRչrRL /u](MOkܿ&K1f"iml^bG_길pں>gꊫ$ϘCĴ:Ԗ BEk4p2I&bB&:f̧ BCkJX!pPr@՗E%C!P\k4 = B@!P(\_{}ZP( B@!ph0Z\_U( B@!h V>ݧ*B@!P( B+V!P( B@!p(r}P B@!P( #`ȵpGTB@!P( +@!B@!P( h0P B@!P( +"W B@!P( \+kdĩf( B@!m(mS> ЪՊ .]L Qi B@!Ps4rAjR\^QfL̹4KR-ILIS( Br#FTS@@CqQ!JammCDZC;;NVm +5G2.-)F pVlND[ZIi"lLd~*%-s B@!P\: \ӍꥷVPS\>nGF7EGDR5E8[VprZPb4s&e(+K 2]UQCI)lhoN,Gqq RPIϬ.N"::R( Bh0ۥ+,fk{{&˝1utJovm YawX68z[oǘݩh>sr031p|T{: B$dWM5gy q:> J[ pBt%&N z,Wv Ba#u?Պg}`?nXd%êek ȡ{<o{G7c8;F́=lf^B\w(ڹ=C2}(5L{/^ug^[;W#N܇ܱ 2݁E64#'iTo`_JP( uC%cCl&M9|Wxg0f#ѵ 0/0(5Sݱ{tN8;%FgCn^{Avz* *8$m.;cٷߥ ̃W0j6\s~݌2z" EP( @\_>ljϯU4ɍOtӥYMϥ^]PѤF 14kp[>mV4c`cO>JT(dg Gf&%cst&;g*{7r+V":: Ϳ3:z5RS`gc֮] tT_=-Vz}Y\?-s*0_Stm!y [^uqcg :N4o>%`Vu5ϿS 5XtmpEb5=y ڪ-DC5wXi1tl]u9.1)ô?$g0gP 5Z[֧Oommjz뫌گkciS|%1]P7fj&R)L^xmQ#kt`ky#Օ&j+֋-eȼɱ?kqə"B2W 5˴M;LŜܗ2z/뮎"Gf13t̼!D?2d>ɼ%L;2e>ʼ)T[2e>+互ޒqXIU=qgXYᇗ!l!2 a{e5=Ujdc3YMc}l3e|yx;"=8\#Pbൊ.f!ů*ȏDvua:]*>d/.6uYD?k>f!;yzҦ(oɊeKlcĞC"[Yh+x6E?( WonkR^!*+U"xOпkvoXoƟSaǖm %bauvbk2Mq..1`(.s5~؅ʼnCȪ̆i^R2U!x1NvؿiO.dZ4?|*mVg)+kz#D8ȍڳ,^G0ydD5_o6V kPTw4 ̓`ĺ uw|%^H׳3]o{iӥVѽ'5UQN/~#P(_C'dI9};»wM|Lb~\7ˠ*k_}/6}w;`nЗ i㻵[ʧ&Vntog;hmg yhm gGSyݎeY9Ar8L8@zK(NN #)'D3`@N ǒEKЈ$gm7pv&1˴3qƛ۪_CּRM[GZه6!w#l[ %b1<_9ogr_+8ymL+=`'ы:h0n۝^G{ٓ1}ϐg݇h;£:7ӣX.n>p.$a(JłkѶ ̼eZ ->wCѫC tҦ3~GXT7xª3J$:WKID$~ثK멖CON>k)=A+<]pBmaR`$*c64k7nE+=hŴ`_;VȌ;14u29Xp{EXLItfDђV.b C:탕#B[vS6ǃ=fXW8a)/Blj>;  kT8,?ǐ,Zە71R 4Ž3ߔYr}`'|  vXhV݀2k 67\o7e$wc g*:w !w.š(Җ FRo)^X`AĈ (T݅sΞٙ={~}0nr%r7vnWN5CEt>we.~q HOU˰bJ=ѣ h!gc(_AT= oK̞V6pT]ܜPQkthY;,b:_X-kC[T ^rwZ,_+bRPv b¹M6.;BJ0l([b@0jRr]u.*'Qkn!͚q6{JB(l2S⌯kao5O"?f1(m\k <ǨyhVX㴁-5<e_7~x#7%7/yݍ;0غJm[7Ϫ{z=/2RO=Oq/3&''?_XhC [|&$rhH~~ۥTd `Tt_Qi¯+wcn;je?-\b|yd?nЄƥSok|? mqeXFƻ)e&0]%cǍ}4.2޸k3ʓ1xゥ+o+/ޠ5nؽ{7cݍ;Sq Ri.ۮWl=hܾf?v1T1qиAQqP.FTho|+¸mF1>j,ܺX ݤiȞ}Y)x#m>k<)ݦGxvoG0pw5ްlalvuث 4&ei|ZEwAu+/6gz^f_W4?{+NF` yj7?-23uo7hqҟؖݧSG۰sq"m>}<2Sq 対i^ Ӎ.8o\p\~jHKK ]j>.v"f;.) ݿ̄pEd[hqwDŽ /b \vQE2%>~['㧫[w"">⮣€LqKWB 3hڠ6]dJ)׋bCHHɀ?h5p:-˖Gd`!~4Kz;U?=EpӄR ˲;͒}p.mBqػ[.Z.{LוJ+ی @4x(WgΕ\E[RF& np߸7\^G`kF'a7o")_͙Zlk!^Od!#MMsG5bGs;Lu39lS6K68VT!ؓIpu?lp=2Q؞ZNuA*Q_-;L 1eeg`3x(zum 74' 'k6ŜiottYxN2WqB I-ѨUgLn %'`cpơF5+&ȱcz![> •q`B&n_ڽ/JB4}T>٠q4ea@RGar7l}][le>^C Xdz=[gFْugqFn\:w^ahз#'!,t'@6$%epjAK'h 2pH63 Ր .#y,HG@cqDll*˃6)W+_eObގ[%᧘߹3b91?Zukر ʕ* ,Yx: Fc_8lV&.sPjMUNcܳ|>m5wRjgϮ,e ??/ߦ0u L-;LVN|;c׶MxiЮ9' _uT^{JH)7D@Al8p2rW.Z ,dc͗^ ِ-!GN`u~ή<3  hѾ Z5;pq Mۢؼrr WOcW[уQ\QFv][bmZ B=!X^zWI˜?Ѿ$rijd$%xu_l2m]10ڿ!:奙֣OqƠɟ>\]9j5cv'1WvZZ"0 TL#?NAMlM `_){kGF>E}0uT7ԯQI+*n.g{.йC{vxcL-x:`+|c3i=WZұy}qS`] A IRV(ZdYػf/݇Fu2*?| :7fMcǮydV;t B\yǡ5 і? k+ѫ]2t4LB P.0ӈ^t(A/Q.D^fYúHBg2My8Vv#AZ{󬾹`/ZIKT~?I!U9:ʰV 7o_4/׾~GOƨ 4hZ$.bdhk}n\TiȱFN}hߨ:jT-'~2-)&\^/,'0~ozxkę^_ӦMmvܙANmڴd80?jv.?I _??GF_;E7<\AlYbѭ[7xئcX(޾hgpҶ | x!.chB PՋG:;RT4߆dҺ˹2p59y€k!!ONWim9V;VQ;Lq)("hQEK갶sՃ<%o~ќ r<dL7G"h  E--a/Y:-_u'r^t6-eԜGݭ ,yɗ,Pu:ċ"O򁋓=b"d9L&p*Z nLD3+% *ndo=y=;9V䃾΀%+ԤDֶNtͱ'NyۡHP}OJlM+⣖tq!l*\A'5ozm۶k)Qmě^'O]Z7г=wjߛ^A?g=^LjywP?;vd>M5ac>Ѡ"gѠ}_<Yw $* ի^=tI(_A̓/1(ĉӍ:\EWlC[ {L4qӝP09!dC5QXd6T?ZSZhTvh+n|.K9Z@7F$7E::h|=կJ[i_SpI?~{30a׺*n+c0_uI~?٣<|%{?Ae9_çk|8SϢpmv $ ֚ĕCX=@IDATwApm*.VDEd* T3X޳I%:CwroO|D&L깯 TEkyL4% cҷSQhP4.,ތqS^E~[>ji̹Wds^W nXM j``0C+^L^lRr5%I%; _€Ơ%] >l6l>Jۏ%d&Fb  E^/*wLJ辰C1dS@}Qv4~8̝]O!./<y%q1b7fWLCAon|O_}gU8t#bן*Fc5GMiO1{4Ҫ|4|zR~ :44ޖ{oUe#=jƉjpYls}-w/QOkZzNP-M󛖡>%yrۥ7W.˗4_*բojI}å/\kxфl`c_5|#7?SY W”S@W0_ >ɻ`Zطm1\ w޼xUå:'҇P;巟v@\8Kxa:ˆO֠.O簌mrpޗxN;<ڦ=pD &ՑGfI_~r ޸ȣu!"] Pnj30cgFsMIl7J:̅'1 ƈqPK/^#e9ξw <ɷ&{ЪV ݻ=uQͬ j#!܏8Sc.A1ՏG$8YӞVԾJfZnj30cόpO4\Ěk(V"wCPx <<5ٻPѽ`!_nl$0x[GZu_A ^d u_CG׫WA,F3ՙ<3=π_lPakƀf 1`f?k1I6%nNv ?TE< ax/?OI/oTz_*QxPU0UEǭ꾾00s˳䱰<3Yǚmd=i Y?M`xL@ƇśVUfyGo:*z"OpU|iUpIVo<ڿֿQ}u>G[4? ?~!q;=.l~@_ǼVs0c30c3xf?A:0c30c3 <3n!O(>4y/?y4&w+x\Q’G R}D=(`I *I=-:<#ˈݗG^~}z9ܱ##_|@ጒr䗟/ *YYqR]pu[[ۨf 9D\E ț1J+y*N-b`̬L*U5NV'Q27UQG#;MҿR*7>wa(%`q)8 x :}HA g䴖:T9gnRF,_[JaҠAmsi8Ka/[ϤO\Ji eWǣ Wmn0䶛e˘ %!?Q4.eUa .lmS 6RN ?,K+p8yp{&Qã%R?¡p>&vv›rHY,[lɇ{p[?VOU#)VC5$~g 2*+8ni '0Itz(-64̋j=?-9#EЅg,UI)I؅YU(d"!% nfeVzRJK7kp\Q/ |IoڎM+qApQX9::(=ڿ{BE;Q:I>s w6X2g8A)XqML.'\Vf:8wٳ, i`@`I3ra ]2x` 7|!=-+0kRǿ%Q(HIJ@FV\ "& dt oBOۘ #,}.@Ed-B=>W[t[7`o/5 ;{{-JyD\`77:}*9Yj E҆mJMNDZf6\`CZ`zj RN2vdC?9!B!;Kѩ#Ƕg Pɉ`ɕ DXR:X ,CEmN4Nc:~,-Iq$[Ұ3QfEf}MO3iRfFEBςO%S=i R:,ra"HH? )cQ֪ lEnsl11;&~W4NIKp"NF5 L!1qp 4[$mq"ZRbrrg _k#4zxh$3# OJt }J^C77ww* fCey!̷ChHdEh2FҤ):WoHLa<+! : \aO&!1ҦR2ʂ-6>䑎v"嶁`*rZ{G=31 U22OӺɭWUWAOծCx^O:)7ɋgVpH:3,Jyo#s/ǐ,Iy%iMUϹ^$gF&ǃ+DkAom{ڼ222(SKBPD!A^&^I5Kp艡:RMU !aeHLςG!e+m:yP,N ]{%ZqUkN0'wH+F_ ir!BͻOk& .a a!K՟>F!QB#IYdcٷԴ =WL&M^[4oQ`N3z:UhP k]I{tm r<[;jMs2fُj@8O4ly2/\H)8G]CN`X8|F-4i.m!4aHܯA\HOWB"ޥ/9~YU_ ^iN#wHo "i¨a^,Z^l=RPV+T tKaaŋ=ZJ`~sf? ޓ^ؿ8wd6콌&b5ذ('KT= ǕB2G6ڂ KB+Q ǒe"BO}ߢ]ze\MFǞ}ЄjLƎq!l o[ؿ݈ |Jb@(Vw]ŋHqF~QzyGbF5pV-ǑWFVЩM[f6bٚ-3 3ʐekh_Kwj"WvsBD%5.܉'助qmKA41&>c8+Ķ P}5B- VV\/ (z(+ cv5WF}wŒ 2} ̝ᱰv %  ɯe Bʵ 'eMɂ7 %FVSva1I7ڀ%#-# ek4ƀ^],0>5-5|@ޭxy uizPp'^-TZ, c@疔EXPt#O&T]k!⭐&< VDnD(SE&^v%!lu+djZ؊%u^v 3Fޜ76QL)Mm-"L;>ЪUJ+4jn6Bǂ6 ĆGgN<ħf+z6)]T<)Gx4)eK2Iy^-qf=HiC-rp i ~O& n#he}HOB(`o5'P^-ぴt.kA-8V %m3Ga@g"QbET"0sJ۴#Q+Z5 S(B\ѺV4ڟ4eOb4 woY2 Y9󑐖e. jaAA4qC2DjR809y^aFN:qq1ePp嚊ye)*WdlK8jQ)RfO& m@i4jA+\ud Dzm0"BwB.SW =bE5 w2fm uB?5]Vqlw^CPbm7%⺅?^6 W?DA0V;7ty}%` 8z!H]+̾#v݁ߟC&*Р`Cp:u*$L GwEOWc؉7y|K 5d`5xW1ᕷQM2y!V^? ZtBҋpyXn',]PyKtݺus6>]ޞnЧo ztj݈4jBJ^ϣshR2־?ҙ= Cԩ3ڷj+W Hk'[EBVq/4ms7D$ `;0`L7}G+"$tՁ7qѤ:ebw^Eja3_I~(|.wjd6RH]8eS^Fr4ܺҷ.:NbwcD K}۠ S^՝v& Xxnfb믣e"xK_ Drn@JzbJ-Zp|8CRx[}BH8~|3^!z ~ => 5Ɉ:rSq`Zt:Ј<|sJ,x2BzgV݇"J5ĩɜd҄%=œ׹+)}cB(hbAԻtͧfے$S!Sk_GTHZ{UfF&WRbSޘ8mN?,'aLdT\?M!D%LFDحp p'cNb?'kjեX!8j 2o`Wѹxc ͸Лp)TG!)ޕWpDWjVM pV qAs(g]B fǎrBA^Ѽ^ܼx .EBcCQÈU[(\ R HfůxU>4E[Ƶ[yP4ZŠ٫x!8G|=, fk˝8]ЍdؚbuB يE>pCvN 'MsR^0dPo{$jښ8$!vA<;te@w 13 +~Ki㋆kpNU$'[[G"dŸz!IMLAC 뎀B> l@ jFD!_z ͚eQ(f"^дP)Wƒl@7ﴆᝏ5`( v@TYQX5?;~"\pMZd/W0kp ,EK} /;ء^۱ڤK`|*Q,a_`E3оECp `<էri] ժg]0qU '`jjw&gϝ[F|@/?cg_:}Q>+)H 9;IIb僧;vқpRtM_P<97gan8x,?~߷t]G26BBc%L|#;}p#]FЈLv8L= hm!勭[#7WЏ.bty?&"Ѷ{tl- jsШa='+XD4] ĸ#s7'dEaVQ$P>-ƝTk4>-]=#q#"~z<1`T8{v˘ Rғy#"-X~SU<;gkP3N+ _ ,eK p o6f lG?"ݸi @(Z&m QGQd{ EsՉY(@ |\ap`e@Pa/tmTJ3/NOqjV􃷳 BE,I,KDZ@j@2\#K=|2Ysؽ7X7e\ԫql\NPT{ORr%-I*XWG[vnR ?߃WW8aYw?Vdލ+sR@Ko,}`-hUWZqvxS-lTY?9 ͺČ7a,mWxIH؉P: ?ކ,#T԰]P;u<^ֽRÖ0EoWrr:#Z ?"o_[vCK1d&%ټ#IS^N+h#EE/:Je98s+PP0LuѼݤ*NލI#pj+E.z0jj7j}nHֈ$h3DmɯR 0Qތ8ruW)[|V]жAU:9拚UJ(8{i>kѾ2~&?VH[ĵJBw%X'QZU%/Y|hWPji&D0ޙVYY 69i5_z*t0SC_L qWؽ ܸ+ \`W$["]BPJ=ėW`E U#"$5iZ-;c‹c}} >>鹂1G3[ {E/Y/4ըR&H_B_A@ֶԮ#WoVD l}%$b(5ͤ+ŭ+q7:Asvl;'4m/vOfG@WmG@7\% PHMC՛0QƍH@Ѽ7z}T:M[oU8L'QΈ҅s1sƛ>b,ٙxBuVj.}mq H׵Zz`1H8ޢ*\ *7!>1 1aԮƷs>'wnDi,^s9Ui0`tǚ)l&Fo1o]]tcb,׹:5o>_:woMٛMZHw|w 1&/YXw_[}'$.SGZ ”7>ĭt8fD!4,Jx766CdemrQ!L>G}2ѬhS0n]w@=18;-L OY4lXk<"vXgoMl~i^}T&-EN&֯^>MtiV|8j)&&<"g_&5pE t %q 5Ƅq KwDQ`(X ;+[nU2|hs.BN‹oa8 Z=qJ4}1n-.[ۗƉӡ8|%ZY ▩m.SiᵦJr߹rӖ_DjAӱereQ(^iܵǨ.Q=Zy(RL[fRc],C"l۸,:wG 솱>9QJQַ3YϮ+H!h* v]j:tA7.SW c1SUX~ SPO* (;7`ҋCۗv7_m$*]YWrw)f\,` pl2My폗o2O)WFWXJZױ1\m[LseZt.{_|zTAOj`c%=lXtOոuX8bOкQMCFV(Z0퍰fnBck/}lmS{Юv :uLC 8cr#s`*i/N[ӌ䈦mbގ;Ǒ=[C;Wan [jgWCiL~/ͫImԣo 9Q$pt=.>C>GG8p>?f:n}F aςzSIiкY 4@.q-9 _۸+Zi o$Ƅcly:+N!%!+JԠPRuj/RPh4IW/L0 ⑦6^DKb'2$5(xCW iU6B}r0T lpA"3lV1P?Q>;i8+Zts ܫvG xϤey~j(FfPC]8)U€Njb:r8al]]GIjdc˜wtV8:J*ש%JheWB-ihhÍAuEnܹv7bHJÓL8\ :i|Rq7\z۠x4(OERA(cG`|8OgvS tNzQ 9.>8d CxV>ؠzp^nqş>G*5Ѣ&ゼSJشb.*Wt./av(Y(6G"McZ\܈o1{ODվ3,R"\Ys#**5eDe+jɳ="XfgP p{FxF<b(y: 5Òu8dE~M̩h:f*'?!K7(__ZMV-]Kwsj8i)Ƽ)8ۖoAbpq5{hRqSǻv"~ = ~xo/xbq.m)hڠ4宮Ei!:W#2aի _sh8z7F*وEn Em+?i\TkL+c*|j {CNuy'38!xTjR~3i-_}|ÿ7 7ot-UomMiB!V\DSFi jG73D=G ޻sl↶*Y(@S&I&- طe 5G(|Ip'ZnZ !L{u&y;' Y48dS^+]U7Oܰ7.d^KWAѧ\ ܹU]@3^l=Imuޜ%Qhۤ^8)0_rK+JF `xy;ݚc-|| \Zhj? MؾajQQ^|%Ņ̉DpGLKU[s˦&^Cr{7G `.Ob1M^Pe2}!13Z]xtΞ")4Jp~D_ Î P)_܏!! % z+ BnptW+#O@oW/u >HSWT.W%Ƕf#7 iӱ<SGՠ= eC ZtĞp{,H@<͂?9 E+# KX5 no0?K%c`Zk%: w_+ nP8$}]L@~A ʞmbS(QIRСFѤL,-a[6ѐVwָ;Ь$g4M(/e|xQ;~8'>IdTᢧbطvRg')˧ tB 5Λ\K/w&D=WgE%M49(Fpz:5ĵF^Ҥl޷ {9Q^p!^rltI6gѰDX*7[n| ȑmt,KHZ6܋kCKh?ar|DhKM:¤RgƋsR| ]$0I!8Yg/ >X̭ouE݈X}(HU C|gv]J^S[J3;O] 8.E)2QMލkp16},W09Aʑ KS}ϣgpHŜw_E1y`qdui~vMjWHhw<CU&\81Ɇ,K ~I xBƵQ8@,_t  d+'׎ /T?"iB X4XQܼv n(Ʋ/[|8m\j))ƅǚ}B(o@@b)3zOy3LJ|- 1eirڶ͈;Σr9դ 5p ʔD3 |>Go~/[ܯ@I!*<pYS)qţ)#bj)Ơ/ΠM*6܌_6ם?o/?CҲ m!L>ؙNM`OmFNSг9]lZȓ K|0 t a;p`锷,Kth@|2S]F ]mXvfB&$)7w %O 7G3=-Sp4)Ĉ 1 ";tAxPvz4.;e -Fw{"QU R%pQT9"oq# yTrPa+xgRtƎv]t¶0bKΛgǏŝ/RG-Hdwr:ɵ]1XJۂCblWl;֓!bfL#/&?cn*NS[cG1l MY69PE?3?`7HB{pvʨdZrk'%DJ>vaG%nC`3sYC=u OF-)<.-9+7p@3I,Is2c):s`>yO< l?wޙ\Nu+|th;Na7В{oƬǟB;Z؉?y @Hm8}5RRr󟽲 @pcGkh =S7a${&Lwɉ'WHs6ݛcsx7i )'>8EEAѣ+'"1b CpS(/Mƥȋ9ƍ8oeb7 Yُ?VXa{usAd,qK=7&ǞC~> !" /0 IƜgܛPe^g#I! ī 1VoO"WnnGPgL{e*M-Hw"FE6#"OhK,_}>~gw"6"NeXL +_)Kwkg75ɥG1w>ԡ[ѴR [+mŠj1{ŸFơ=_懑݃x:Iepb&v=6h[ o>= AΎ⫯VbW/90$YYDqB~WJrU_?W Yz~h,6E{87+E*ar:͹WC氍^MFv-b~Ŧ9x@.ˤ: m^MkQ;gWvXk}KęW^lnZnݺ!%2pP?9#T$bkkQ_ybܠ8[Yğ';r$'%N& Gb[)< NfyHNɀ_P(B"dqrDhq`uxjo*n rOnyPk3;Pj? .fhn./ڞDȢRcS7X^Q^wv);a*D]R;CNYjI,S 9ўKe|:s[$&%Z׭^%%p3}Dݼ\zN*p\4?e;O)e@e`oiF $>!ZSIYNOM"A4j#&.N>,gKt뱲wf|Iex఺Ck$rRTš< y2L Z",X\v8Q7 Ig] V@jF.BhmI.28a6Iĵz*^yL#- ?LK  h+xOه!A]e$)|͋.\GȄH;a"&\ʥbMzŸ]Rarwy?sY: 8 u|_>ԛz(K M^H$>~\iRmͣ!,q9-C_̽7A\1ʧrZF:dixUU'_KM$Ӗ2R).&ߘDq[*bV!IxyBZ3y 'e;ړ$ds"t;+~t w7JdFxG6(P͢WļXee.,&YC,r+-Ų &G ruF=y4 Wpq9W!#},ϓ6`#o"#ba8Iau˴g{p&1 ^%BD%ۥ*X ^yAtWml:xōwѿ0L:,2`K%*714fw?n!4 tO>DpXW.c2K…4U焲uǜ>WCWc9.ÒYsz l *WBZ|ӫ$miE.*2/QeRon-7xmk$|iv G>D&\)h$-TJեtMՀ,]Jj"T)oѢT-'%7d0T?4*;:>Bo!nUi3Q$%!4'dfLLǠTn8eρڧ@4G_S)WlQ.%m")~&pQ͘^feVzh+*m'VN(K&uVb4NQ [^A_kl Jߓl'+U:Ju yywU1V*$'U CxI4![`U5)S䚩~jsi;S!ySkL+nx' Mj`İ$ߴ#PtzLqDN8)[LevPs>Kϋ6$H4L/E WH^ߣς)dWOy'^h\Xy Gw>|ND0q0FWQ0$^%t/qH0?q5P+(iIïK³:fmk&* i kj71d r%}]HIDڈ ʾeojU*K/mcĩ_BGG^'^+?tH5d3*|"J|BeTO<ؒ:]e z5v0 OƼlsI  NxEҙw'}9+yA`}(߀g1J2{FpYҘgeL|*TW!|T#JYTud.zRLl%8(T=S0\=vRKW'cyLe>%ʶ")q*Y?ikaڌŘ\*p_ :V5г1a+8V/iJLZg-1K E\dC(tԳ꿊6/JN^ Z?@)CNTQkHS2snܦIЪlU-LhD ߊ7?W76˯Ww85x_ʝ"<#Iy5+P)g58Nl^aڠ2 (Ƭ2WwUXuk^ƻ`%mxWWy5B0|͋V1_-tz+vBkUpkS _2UҼ?#ZSFyEೡ\ojjUʸ_o*<&8PMٮ]M㯧|Wlz0a)ϵ 2ps2yYzwWC=q|[S_xʺs\ +7k̟k̜&JoּAX~(yJ1KT{+ kk!ȈJ,&)ƭ6; DpE.驔V3][ DmZ R@-j)R_\SQ3VVAr]YtMV+S{J9,s@-j)PKZ R௧@qm @-j)PKZ RQ| jMZ}[KZ R@-1 䍆?ƍ)-Z6IG<&Ř_/^oJ[{הe|7y9$yהx'pWig<͍ޛ5՟$^g5|-Hkֻ-<޼>5)z򚧩~=p+l|U[׊^^kպr( >4:Hg1[כx5)zY5=_oMg^c{s5=I{5n4`Ǚ77Ospng<}G#yhn?{֔k|xד:UyonM^+zy՟?FZRj} זYKZ {/k뿗޵R0j}-)P+^k뿷ijK@-j)PKZ RQ[L>*_-qe%sT{K [yt~I>G^-%|U~.$V}.SVMp~+^OԔG; }H/OKaK3ܸd:xX#3U½:^.ˮ,Yh`Cp2udW˽yaT7:Q}r8r4bjxUWiyWOEIZ,X"VcB&XZIk1R4|i|1_irwFXu뢅F |H70oWF!m_\/Pġ9o:?+(f Ei;4K~o6~fDHkR`sjVLր(Zj1E+5;IzBawRʄIv夦xi7CYrub«Qp4ta8_QҟL2JDÒب6RXWwFy wR?kЧ: j>WG(zhX@ yt*Jijq uc ЀAe1KKYFyzZx>VA+K^z+dt%Mzz:U!xepz0W,+>s%$5AB&ׂq#*ͫ+"Gәw5Xq5S_Rs79(,.U -L+V _^0UrO%RdgeXfWiVQa!b+ADZHh%H0cAZ)P/R.3*ς%EꝴMjR<S%VUI@ 0ȱrΤQ|l ҳNI qHI4!|"W*yP^VEoE"&xeС:-P\Ak+(<2ڀ6.FDKPer_VRb*gC~%p^w 5^aۥ@o,J0-!yHGFv9E&nkLld`nyy92 PXÐ:+:~g58?z_Sa?2(HW!d(p5n)ĝ?>Ipɓ'^'re4h%$H/ʉXD\HP45n:]r׋J ޝ[B+O-'ѭN[Eقnƍ^8ب7uk()Šobǡo逢d9oN6gBb|lWx.4a,R1v,4 ;uF3ĤYq.,\= G`CL0!nJYzy>k<ڰ޸wx?կ2͢/p:*O.PZ/PJŤ{;p]l[oVG!Qs;͘Wp>f]d.+bhx9Yiiu=Ѯ 6XU*u {౗»To,^[=ڔ~B18+~'P7U3RqY)x͏0arĆaՖ}(G9l)l؀_4nw ?VصG|n -ނe?XpXx /#K/ĩKIlcѻ[ҫ~\*ع@ VtXi9&&MTWK>Gʰ@*|` ,[%T1޷bl1cU o8Tʁd*6+q+N&lv`ČK=_X-;uEVLsl&->W'݄{*"}@ FUU ;nWO_>;5}svp@f~)1wc:+U xc_W6R2N"LxN7xU>qPÎB*ZKhZ4}>n Q+E,}̠Dd쬢C%ڛ릀]ȸdO.Qeˎ=/y9rˍ//^>x+W8zj«9Vлw.mnݺyd>#@-Xe3ǵ+B򹴴^n($OOje&ژwRRO͘ ˍ`hrSOWZAaS^),.#KoyVnJ(+l 8VϔQuYڴ1#U2zFFK阯˴Ǵ8ZYJI=pJޡMͭh:2}j망8Y;rֽa=m۱szAʂ @A)-w͢uXZMm/4U$F]G־a}0o6/4'd7JyUK_h2giwLŧi;|52LKvRk-2&A; Xh#㵜KZo+m#ZJB~;7r>wW5$#K gOj{N9_TLvЧyZLE6imښXF`tkTy7jӢ/""/R-EmϞ=ډ=i[VBU菅ZQiGO9JJ]>J;]>{Pk_>Ju켖^[wӶC؋ѝEjlpWmŖ}n{N_:C\-6)E۾viڅ#[ vEՇ9i"ϤhczԖ߭fh̺G{ pؠhie&M g z(׾|힙/iiٹځ-?hza07$شXg&:?4RO+WD9h$*8ΰ\*+H_NR[)![cⵑϮOӲs OozۤeU*% #c'+Bp+5* LЊL}Md'w#,u7ux\.qUe( ` 9k'cE6Uh'iU22z *8VEk׫WPCE_QG#ERK3ESOCETSSE_UWcE5t[C5t_5׋AԆI:E+y Al"K8vk]Bf?%Y Xvdx V᭴($D51>89ms?MS1אEw'7YV,ȓiQZhݥmpp>PwðгSs$\׫-rIg%a>ZΦ]JͲS.cɢE:٠cЫs F_}|͒W@PW{xؼ ?t gΧaԹFxiz;qX hHJx`n\.DHL~$䙏c՗~o'be-;ŌG,_,=gVj,6m݂`r,aniTEKii!w/>}b1`]ԫ3>(J\.WZ&0ŴbvW[1ny ~V] =7*a~axɴ8^C!d3rRqq!4 a[O3j#ЮMk8Yc+á=;ffX5ā֍ЩQ ~+U',=|tj^_O_3'/ B)s 6e]Ѹ{K7.߅Y}a=#݌oWuvcG•5Xr=\|Cl KPhYؾm~zB}]ko ~^㞙vMBPHw7N w9niiOaoDZ'XUNJ>M4}s%bS{ O~ %u̇pX-77XqL|,l9V\h$vnxhLRޟ^3ͺOp 9Xp!GÆr~7+tYgnEU`ێx:]Pn7\2Nڻ$hW.-$/J..^2rP$VH5Wl1q`s!"{6PGD`Xpy NqGuqGP8u "3Ir\HGp7\łі 'WgL_یݑ))G7V VӃ} ȓcgb|)\İ^*ؑ}%];6DJ8XQp"|XrE\8Ggaގ\B&loo775l r (>\dYb dSH.B_vY"C;bHD`Sثҳ`Q8xVJd;-MgQPR 7 Cni-fbG٤7jUGڻErټ1I:_;=Mʗ4h>0+6lү>ƅ"g4Gyi/ -:ģgBٌ?\:09J:#~^Zv\ThLB[3wbދoll탷>]I 矟:ONlD޹1tY- Ͽ#3ۃ%?m\.Θ\ ̘$V"Pp,9}tZ f?QP)!5iMON.a"t(ґwB1m=9Xu+q)) 9ɘ 6GgDon1U>:[;yϢQLZ7 ˱)}<ճo0w[9 9 ړW7Vi&RG<-8Ȥ8l],ӟAD2p Nݍ(/G6OJ/N\Fqyݷ^@.g tƣtsS~iᅣg[0o\l惯,G/8;냳-xjxhߓQ:<߽k:ShTs|臒+4h ɷMF~N;!N3?wK1; AۘD؉'ZߪD /}!Z95+C\nZj /N8b.!.["m)@*έ؛ NvrR2yY'>J ;6sf=g_ ֛.%nќPoYzYWP/ QcKHqn3Ocqbryq#>^]Z`ŋBaIΓ@˺}{NU1һG]_.(@1ħ+GD\ztB#n%.72Z,mh%x2LPc˨O,e>urZwAvY|=>aSTFlHv7A=y|Ƕ4D%-vWh,ϬkE-k~xL7aq2.۷GșL5VW6Hſ~}*'^DH:Bh:⭻{1tm-Ador/|V'-rG>lbRM, %ܴF :G>'bۑ}M&cx`,\'*9iTl ߀`e+qϥR<'.EQ+#0PCF#, 668P_:xiD|?>8;{11}-|㾵SCls5ݒTGbղ1va*AUʂuv^+r|2{{ mc{/7>7hnE7eiIo728}9 Ѣp D݆·ӈ8'f=z!\߼mjjRu&/J<0!wj/;oDQI OYaWô wq ЧbO_\'<=-J!^JEN U96rx@l8y#ya p@ZJ&WKY^OB8'$o oM8.2 lōܸP]Vqz-,XrDZbʰV,A2ԁ-`[AŜVc]*N.oC]ѧS=1g ?='y+"e "R% bTFayۆ8Q ,fg:xr4?܀M HX3mѲA{Zg"1{oVxʤ{GoZ齝&uOfq?!pIЙUcNrMeW|o^꾬TN <4l {nX.|5,LK0!` w29I|$-3ϸX pYQ{Gg8Pqe__q`pApQy5M}8JWC;Ɔ×jН*1jy8t hT7Q;sIHM,K@3潱{ mfC<FhԬ5,\ ݨ\[p0ῧ?'t=A+'.MU 1 {_)!np` py3;Ygгgwpr$l9Ȑ|]"2.6؋.N?rRoHg-M>r:;з#iL{ٖTBbT&˜P܅x| f}2~~]yJF!i텵U .\ȇh8TDwsexhkd ɓH,ՉK 'yOӪI#MC,4@IDAT u\8댸ذ"^ zdMh")EvzqN \VvrY1e\ <=t,?OѬ,g>Fnz.xIf oYxz9.p~xbl܏ zwrK+}%j1i+jC?u~Sr\9ylj2BZt 9FI%P<<=ao>d}X/.1P8TSdb NNhqتIMiuFP;\JЊF\r'tj'n˲5nj\I{cpu>ʁDn^xah5ޠM9x8ldd,bADtz4=[Y̍,8sL)RVsG;"ɳHدwfk9J5/$Î㔜"z!E.2y䑜\ؑ 'NԬ(v,Cr‘!sUeKD@'Ġ J1 |Tj\epxf> a]O}w u 9Zػ>1Vڱw \F/)P̮P0N`n\P"mۜt͹'ޏAUr\34Χ N )WO?Tz1cD3*ip`]d 6Kʅ+~#1zj9ՂV#!SXS//Z{&\W8aEGhȋ8˙ ~3\' DDҲQ43V@ 5#qio{ >]GcδjF_P 8Y .DO֢ig(/#6?d~ 㱇C8qNOƙK'MÎKq׽S0_/;!&9 n^`ˮ*sWX3D$~}8ɱhؘ?~^E 6Tϝ=CY/ԭ-t4yåp7ٓ"QVK$Q'S.yb”0o/uI*3䒔TLt^/N(ny= ط'lފVmf _/WDDW >6z?K"bZH?j/->cw 2Ik]:ExΝB ")}zCaggNE|-98S`ݪ^ qKgO&t`N-qsAU0O{s_/ZK9*E0lܱG$lX ueذ~2)"}6Yp|ݶok9zQZ<%&}¹qSHx!)W4vLD>+ 㻟 tZ9Ciضf5'Тp`N 䠞c{ÓVh69z4uoϽ=T ={ #zIRk mEԒ|ݷUOJ+~o$JQowGѝ@Kp($N"k T,|dS>>͂8AAȞƒsq:Ep-SB8w%K:jC85GSv\*@SO=֔J4Ũ h l-[u_fZqB _|'&7GqnPmYvf\FrV}2ƿy\,O}(TENdu|DǗ uĤĭ7@LתE8FkAH.DA;XBXBVQг 2}yp-ѹ:2"Tsyʪ^DѧZ{D#{<9^U@&nD_q@,[YA]>Xkx:  /Fu8=/;GM.N^(ڲo rX ~9JӢъm\~ٍlF4j} N8qM!2e̒'mW]x17w=>X5G8MמgŨs'nXE6-f]~NrjgT*1%iCQ(2i&:i xg<ݚ=xOy<'>$ݬ}A{axbhѬϟFVJ Dr0 N#H!0Rt}S;x[AbRl='gpsm+1G1ix$X7^(b,GZ&9!?Z`ā93Hلy|)v{G\PH%ׄ4Y; `֬=7ڳ=ʷǓ/n8xt3;6pKN8ۻ {gк{7yĎxxGIݺ݋s3F {:71m}F_OUeM{wE3Oݱ/vÛ&+$}L) ;wL|pW!.?THǁ{ 'A(]Wl>?+0ְ}颯{s;&ݽKo(w}EdAn°|r<80t`."mON5]Z7A;nظa53{CS[yp!bHNê }Bb:iצ'VTK)K aԄix YEV+Qt+m Q-rz sx^YHI4Ҡ+cCD-ܴ)3瞢 \:mG~x$ǣ^p-%Zv`ʃSѭyVۉo1L:gMQ}ܡY;;cSDn*.Q_nlkEW`Z Hr;u_Bl^-OOMNǠMo{'?{c57-\)Ji޴=ص{*P<($:ᮥ!/V LgϦ"BM *PY%8yY3p?? o} !\=~67nk7F >߅~z.FG]NJG ?e?!7qF'7pǫ?ùn¿Y[2v㨌Bb ^R1yX;bsXh`]$P2;Ѣe~p/ᑔoBOƢyXct #Q˖ǃ5ecInn|~Brc(Jڸm ,H׆RZ$ٸ7]"-x~ɔVW^6[n-,C KMJ*G/?60vR0:\599\VT cAÉl$s#_P('Hi$Bˍ3 ,-BLlٿ/7nrpr?bĜ0Q'83DX ,)cח;iUJE2 Zt.zҢˎVoZ~'xٞaq:'w D6 ܔ4͉ 2Ӓp9>dӒ->ϖE8Ows6|\X|b|$YoaL?b;`waiS@@,BJAAxv*HIJw7l{<;p~w̙3gΜsf>bœIbKMPj# R&?er2RI!ܒ~iaaG̈J*@줦SG7V-䨗7ς)P@DL x~A D6Ҳ URcx:{#NɲKsG QX΃qO!D_jk+>''0:oxO ?ns b&}gm?yxb]\ Jgal&VX(ˤ(Ci NOM6{:|į x>YOeH%\ WQэ,.yPJJ*7!&+-QѤiM%˃ILz-FB݀2QPwE+7cK0,c R.r7"NhiuuKPjjhuvs0].>][ Vji/Ad:$_ o+2ܶA됸H:_WyN15ܢU>t1OL"ok_Oxș$Zj]<3֊ܒ _Y+}EnpmZxPOo[`4{ھ<$pŃnOͦKKy*toHXi (ܜ$Q+]JR*ݮӍ͋Dq $t'?%\\iӃa+.4 XF6mzo߾(Qݺ0j>C⍿#G皾ҍMk-q:Lo[k˳GP⌿ڇ\[o߾oIpKNc]Os TР1 J5N'8nҔDe"S-G^R!p>ؿSs q}Sфn?|=1:WU$ }Nc\&5)&o}+uԔW`LF 5(m,^) )l&䠒o__E&bfֺ&*AIv ykWq$fz|W n[R Hly7t>Zk7G S$E^ƫF6 "ޜn7˘_cCMi5i5ږ~L`U,c=^f`Va,ِ) F1_-M B+U=N+X-ZfܨI{Gp+e v!ިnVo4m\YFl7Ve 7}v ,c 8' f[#u WKB+- b610IG&+8xSP6|o4yI=iobq~b_* \H:jZ1 yHh a 4vն^%ؿ.G%`ܗЮM3U= [0 &ApD?HTmXqLCN{ A3`5GǫQVqCC ˿ sA׃/9U cSPޮ7mC̞V"pK^cإn5N!ސ_Q崹iuuڽ cX4ZPpV5µL5m:o4$mI`װ3ĩDóq 4o\8S7;gFZyD^G~2/ii6iBmPDz10C H[eҏJ$٘EiWeTr}R?`]QZ Wݤn)!)G_z 5-Uj G6TݦGgsMU֖֊} `!!j.eWoW1N( P[A oں2LLaU C7ҎUO3ULUiyߦƿxӴd&TH1!dR-"'`fZ(CJP=~%~`0$VO>.zwvLj?Vϛz|Wn j2z=F\XBg5P՚6=FQѴO7W+~6knCSjܐVs]UV_|Uܴ^9nK܆T*ԓ1_1N25ORfQs]zK7f W U5OqP0Gl\4q.8P6LLdjWڪ=I}T^_MTJUmZ1*qiU٪?S=J~Uk(x n(рpMʈl~k0¿ /ڞx>hD Iy}32c30c&8fZ .T#fe\ٌ30c31Pe2`ƀf 1`ƀf 1`k kf 1`ƀf 1`_[ϵ!P%!s[f 1`ƀf 1`9w׊myzϵu"\קf 1`ƀf 1`u5_>(1_щDjScFsf 1`ƀf 1?]fFzro|-7g6c30c3?@s]WmoQf 1`ƀf 1`?QP5Ư'Mp3mIWKW߮C{A̿ZGp|?n55 BO#iQ5iC{oK9yI`36˪# Z.I^櫞QGQn+!<1RS?$fWYɛVM߬=^ϧa_Wst,5~c_t+d[u*4j_ڑ>0WK=px?7¯T}k^{ꨪ?W`_\NErFSU !4TlEyJ7J=VtAiY)r#%KYwyMSx{ ,xeee\I}+ ˉ[ĵ,rZ 7q5avhU/pi2ޖ2VwPRJHs0Tӿ5D^14!let9M2vUj`4dBScE%'~An x=d ‚bz}WO`!L}BBηQg<5P쇩J*>PwK,A\j,m1thkP !2"WyI>6nX-NHA ChP~]Yف4l{.]\ðQcp{[fؔcˆ5F\N0^pc0-G V,Ysqp&: cQL8XaW"yWET"D@,ǏKVs ʘ@ٵ+wEaִ8(lñXJ3Ъ(tjQ_~~a|8fOY1_!56q(i9X[\N#̖(p}@0_?~,YBx7 K B2ftl^ZW.NaH<_/SV %*V,[+q[6@>(/ ?bޣJjئ F9m-w7f$}5 ߓ9@ %8|.v:joJGC X-RտeJKk#7@ȡfA^LiO<0MC\+Q4>BmQ 7clhsQ;2Ӟnj9_) r!uOc/›vChe KQ kOxVN`A:-6/}p"$!=N RkƯDz҆Xagc(y4hߒ_)kn=R ]TY` ~h0ٳPPᄶ-꠸rN*ʘZRf)!=m{Z}1{t{:7াLXdN` Q ƔN  'r k8i4A!̬l&X+"W E\HDSARRj221Q->>M`֬'`}|Ynu!]!Kb)5h!#O.$m'+uV"%8bT6 h21P~Kv&W&*(ք^R^Wjj7bEQ3Q ԃ4T~MGa3qghP˟L[蔫>ePBLDCbKia6>}iD#OΞNM1mKf{g9aJ'~وAӾIŲ&cJփdyH@s:7ĴB|Z.lW kݵ-ǘ #ųY%8 xC#o8'ŏO*\ő)(rr 3.)4҂9-hjsN ވG'fba\MOz ϭ:NԵѣ3pQ9ClaiҶʠUj/ SӬ ~j.ڥݯGn1w c5LWsHm*lѨE 4A>x(='0X|8{ Rp{FOLľ_B*DSyT hTc)h}f=J"amX㗧г >5pO6bxnB\JRsMx vù[Q!a'7ǏC$55܉RR |YD{= %`qO`Ck^"ra,F 4RߌW^xϡHB&ԭxElC,z%pr(j{$\ƼCZ~D&>eܔxdCKT^~i)H'FWc̚= ̓1c[H/E!v;Zy؀(4I4>/^g;@{;4S}6}[$ 39LpL,z)2wKS;7ƌ_EJN>܋~qcKbH%\z ŜYQ߬I>i諂~/k=7\iYg_x /ؔ\Zc!vDi!4'P̟6s&Cm)7&}>> <u\fZ,-uU V= jݒIkGX> q[Z cC>/cIt-0q*Z~[Ѫes% ! \7rYE05O,%#.'wcx-MpZKk[*u(5CY`%1e-1?kXG,_6`2E|Z-zN?#OM(aLWݢ||7SaIݽ;-ԷPzds$xR~*񧏄:1`= sD%2,VHs;J Ê%wݸ=Ǝ7bD!x~F⽏1?kWo{QHK`L~~fr ѻb{ɷ(\.D87y܉رb9{ n7;z8>1O`*Xc' ԽBMh'.Ěq/5)˥8q_&OQXzj7* 4ڵlDL/EcPʜ\PBM!ЁCR;`ҍHFܔ 6. ?7Si-QL(jP4wk U.POYwhQ;@JƸ}||qJ\0 a\(mЦMkBb Jq4V#ۣ36i\\A둭h( 7EpCgͣ¥3|ٮafP0~w>jº#54ˑ':H m,]1xՈ 6 yvF.¥CNаn9[q'Œ$^ -f̓57 QBkO.?u[R(-op|PO/Ol\Etl l^FMovYC6F(A'I(/vbҊP^D6uh<.ɼW9(POݏ+נpNTPǕKSV6)UʜPZ~ⓥ#+%Wx7 +4]?6ZGJ 0y(ЄՋ'bQjZl?2=ws%v4jցuI ‘1nYSA-oW  v<bQ%faP =F͋gSJy4k]wu:uenJ9,Y Its`_7MleL䛵tﴆoq&Gz]]Æk9+E;ʊ9쎠_Դoݎ͇)Ljčв&-7L톆˴ԃ=".^\yp{=X[1q$yNEOeN6ػk/"1{ ؼ?X]cX8}0\) ǸwNiץo=ݝ|s/zgfgQ7كwCQ <1׮a ).6T -B]=tg{ EcͮEk乓8 љ֮!pb(@^84py 1}`U\ˬln%# Gd<6B|qyOpܶ>@(]gzX`U6%#p@/;y[uxLh<9sj7iMĪg2 SK3ox=% iwtOpKpR dhcsoX0., ;(`ƬuģS#&_ %dbzx7Tv1sѼsO<1 ]-[f,gpiΟBtR](.ah{PL8ٗ%.a Q̓sf!I{L{1$Y-OQ`G_4vd/f hZ(+&cY 4AA1jr+WVq.n3u!Rj1c\`طk 2ӝBCi:{i0^>n#' bMH>YX1vX_jSSrR?2gG`+Kx=#( KOaޔahg5PEzϾ 'lTE'^]dfCFVnNd1nԺv#X4g*^Y}ZvOŢnL%6-ŃF']+aS;¤bp>t_=}:>CJFǪ"޸ m6n؏O-ss(K֦ )L<{~xҥ)2"~HJo:bw—( Z:"5WjG g,6 n_}G3Z}?g9_LѠ^˗aQ΍}C+6~`;/ϛɳ_@ OGڇZhݼ. 0L\*>B`hX '+Pq<3)s&onxA>j*Zg#ܼwG_p:"smL$7֜woosxfT?)OdZxr{_xfl#<5wpǹɫl؞M1k1=u#3N".1UȔxN[ 6 r5b !Rp>w25t36:Q i Ey;<я!$4-|{gZ1?1nvgxaB< $tj ?҃x'(0vLj~qJZk1EZDPDKh C2G7P`#g9e8f`[SX@Wڸ!z7\߀^xz`&EbHZA1ʵX;l5 ̱]jV<TzlDkL þsj HD#/VRZQwFfW.֡7bn\GY㾢kE;Nn]{SqBs%RHƓ[ھ6F\2L49Wc&'7=#~/ SHExzz;bҳ tlꏖukCPsdkСy/y?EuFh̍LSag#t}f&nP3mnYQ#bXd]KO }&?")7!KL~!JMӅ3ݐ~1qWPno ZO|_u۟WzIC_Ah싸 㷰r)>xs+Ӛp=2t..6up(Bq{PN(N8‰(PD\4ؖo0^71TI߬kQԖ{C >> ܅_WtՎ'pw)зo/qłPt!ǔ1HN D#(l",GWOOD^A]B?fӈtb0`9Ր缂ߡ z۷oG)]vBz!0IqXs~|[t|HNTpӛ"ؾ󞜊>S^F6 PVӂ7XL*&eKk+ #2$0PwCo[ 8-AF(GO1y^6GԚ5xڙ@IDAT7nW#pe4 ֘$7TM/| w6pwwe`Uh9m H$?STid_p/|k.Ue<@_}CryӖR o]kf@{؄'}X]Sp9 uѫo9vMcXOHE|UDD#ߝ2-F|WS8qiׁ1ёND߻Ú~{h|7| ,и >}ˈH\Z[ g/<'b`er+@S2qĠaCi:Gqʲmh^9%X8d ?.+=xa"-A?&-B_6 ?-CKn8L6M`hwOCA(-iރ8~1M; +@i wc][ o=1wC#{Scα3&x,㚖*:S1K͛7|W#.êW1/=c"Ř}bc0y%*-|2yn3UOa`oj#W⋟#ѻjowo P+}Q;7Ͽa>Xެ@vs$q&-xi."_9r2_GC=<^^~>DoL|I<>7؂rojɯD)!N{3 GNҦ/:KGEg/_b~*YH?a0_K\Bm6.;cV ~8= ;W0nDڍ)^S8{:]ytk#t<=xj xs_6uP˾ GFm G?j@^!z󳆓Zow a\\fɻIA ~^~9OD+S90GK,ntotPàF+N Pxkt5b2vmS&3gp:'hYm:zdQ䗚RpUE?ؕʓPxWa쌶hF#H!2*-1klˎ\A0wh'ˍHtj/8 C}a _Z'ʱaZs2p)Rl9sRBh8  {P/ӹS!~]Z0?JA{{6KTԧR˪9G.v:5`#\sBQ| = j֒%@_ ug4(v !@.EGuX&m$5rA.$spMgzj~]}++ֹԦdvd$]  3-7kӧmz"=O 8&@5jnѣȶG D;gwWZOP0~sSiw6orK [ 19fq9Чԅ5AAE|бu?Z|t mx[Jw@&%*_K|P,x؂ ̑ т%9xwBs ޤ.0Ԙ XD{\˾OjbyJXH@L?yݷ B: r#HQn:~eckX&tlݔn5%~wYzq3oZ@FtࡥGv8fwX8)X ,obn6miIn<@/=)s`K򐅩Ze8!. . :z%6>hݢ%j<κұ!‚f)D8o'•t[X/?A]qDл{8qu&Z/EYt1I+*}1z2! Eha,x+9w .^~x靏p*]t\H/ޜ5۾6i:=24ѕ!]EqWܱ-H8c{88s݇Sp'a˺HvbMx-~w6tp 穌-+JS{{SՇ& -mNpk+;.ǢuSjaVCF")$i(K rw Wecc8|9}qlڶ^ֹ6{rX˚76,nQgR8nμÙ qӊx be6|җ_o%k۫~y!}W78Zbaظ4ҍi#غ:CMЙcҙ|zIy8}OH .y\)@M1NCi\Okl{v0ZxE60S]@/q>ý}Wc.^rwxP*N4sl'Yź%_hx9X/!?}M4ZS6BK-7(.rᚙG7RgOthZ}ac'a@>rB"sR5B#|Lzd[v@=`U=0n{6ť<.pԄ )!8rb= 4Gmmgn(fSݦ1؅M#/%w4n@mFt{ա=8r,D]G.)94\c@ k-B tŗtI♅Bygf|yV>ײcfʔ ePHx;rZ ٖJ\K\ ymW-gogj!bk?Fs]yhh,)ȵFn dH(Ł-[p"M9a];`K<ɳ'|a-xەcx}bhRhHHz;a0V[9,gO\1f pI,`<LǧcM׉K@lokϽV-y`58ON|]$͇?>]yqu7WxnspƾGjt9舵_?sf E%\MZk\vP$#8oR⢰k:lx0mǐt&xGN ֯i))H5L#vKmhHm͞e"~lYwz6ƻo\DǬ#M}a3v-]@1`݊y1Mx]:PF>![,~#B<`xWs)C࡮];<Vx;eQ=cgi_`Eu}? gΥ1. ʢr]G9{MLÔ/h[R.+}FةEyyZsxШY&/q[wًжSSsΜ9~fE sR;^ԆR' pԎWn€Ƞ/4tnxwBx}-8oJshIέx(\ 'r;p ldyؙ>e= 7 ?^WZ?X9зr,yErΦz>a ?.K|{yd#8no0K\F9=U)%ql<(d݆)櫼"1^`0hԃ G`_S huxYsͲ҃.=a럍÷ĉl_N೯e)"Sx`7 9! ]}ӒfIxSh-˅wۀʄ'>|юǾ?w?NcݻwٱcGƍKaPVYEpo1 c /]'i.Er\Os}hjJ+@bݧ$')8iǖ]tN#<;,*>r媧2iE\+RaJ h͇ԨDz=XO&X9y"TެESj9Hf?'`黕|4,^Ķ+qmѴW| yW[ I Nڬ#K?SWW&% 6!/П׎WBU( 3 _kOӆ^d4qًWYQgfGo/jar-\VD.q*p bQE r'_J-XTow7ToQSAm(h`p0)L PN[ X <'aϭJd|ů2Oh)24yREz)2/'GMCIaUHh Gy&j`` AŝwI; ~QQvVR/)~9b5s!~W#bbHpb2n1Ѽ-ڌmY>_Cc "K΁%_P OyQ iE4b恩xRhjHGrnEDF!!,G%.c)Dх,s[=#:*+B@p(y𖙕6+.6.Xk9(8!kզЍ!y]^!s ;<52QIF^#f?es^ j,ػIعx",679n8⯧̄,0g&֑v@HXd(cFSs0!TeAÓdyB6E zѐR&^hIn]^EUX;׋0} unҞKMJ=#BCC&C4f,k]T5dpZ`P#mFGܪ=ɷ]Dd*lOZ 7(ƧJ8o*)eBb bBBYx^sǡprHN2"5>쥠 qq\W/q\le''"&>IDx/jK~Dm oDP[1EP/e-)ۘ;Y\e]Y}ޢO9x/,/]JK0]|.YdÅ"?3-O(RFDs~ 󦖿8{?. dyz Q#b#wuYqm@a%[?R|$N*Et곪z^=[kǛ ֦B`V=za $qM)#~Sr?!zpfWD IZczM"CM_ k%lPh`O2ݪ 0K{S&T-*H8Q^Px7L}ך_yݶ%IF##SА}caTJ|3.SH :e#x 0J? C1oE-/{;9z.)L]eRָza͈x|)۽) .V[EGťBUzB[ْ%`s$^3Й+AH*Rd p):eG茤LзKrvBZPZ d~ɼ1:N/Buߪ |}2l аCceҎ^HQA"dgtZS9@<)\},_杜-_񓺨ѓSs75#~M [.}LbniO6_d@hA`W/ux#o$ORGn>YuȎNYm. 1%4Sq1е̼2r@k_ 56eQPc|閾-kh H@Ѫ6u)Wc,/«Ƌ߂_c:`*4GDZj_e5]QI iච`<۞P٠ʽ2Da#/a%MƱ~%8@ }Z(/|rީPӳ1i[7tJcYG.$*m ~6<mijʤ|HzJ!󣀇.2Gͦ֜rfJe_Pi[`;E+nY䍟,&u˸X2ug;sHnІ}YNqGK6N}9$7'w;B\y7;E~RgBw2G䍼 Fj\4k8ɫ!"' |D}, iPŰt“ *Aޜ?Kq344yVY iJ6P80+CB.7"&P[WmկBa hѡ[[<.!,7Q6Op!‡OxpQNOIv]pa\+Ǫ%0( @˳ ՗ZND D78>0~M{\?vo~\/+ЬВ&fdQAEB$_ehOU`@M7@RҮ|$hh7|1 5zR^ޤm gܮR(xE-$+!K_ʉ 0I&CJq\3j>I~6߂b~P9 ' '~dC&!sVƩ rdxCT#"A$%q|%r%HG62l4DHԃގ>z|kUzqەtjHWo_/#RNk_'eC!z;/kiy3:VZ]RVBU2^q~Uz VwL\owz+e"ъUmL:AO)VTWǧ$uW-iRl>U_/]ʡ:|e] TzXAIOZT뚪WʫLTj0JHyɫo\W r<:5Tzt ߕ0 ו!4 -Ɔ<-/T傮QVN|-IRiZQzM6}6m\ěLzY2/5^Ԉj}Z}>s_5 'ZbV5Ɲ^GUY~UK7Tkػ^I{W"E@zUTD,(>}X DTPQ@A,"!H&7{&'  -؀M+=̌k+em+kc2e l)K*g\ MW1~%U\ dxSEMeL9WP)0;2z\eΕv.ei턊YQ03n2o2x53,sڅƟf`K˶PU3s}67mc-S,[-gl|5 }=2<4 }ʻ9qoPQّ 709KdX0^څ.J.t Jպ¢v¨ \J (;0/tvFFuJ[uҁ_/\67E`:pPA*J`IeA=ˊmeG \qcѱWP+Ǯ 29P9O T\,,86C>LTu)p%8? +.MP/%*C.TOVKI+Ues׺IjF՜)cf:sjjMƩ:]_{.WsKxئx?:]_u\maI6RvrL4NW{i8}o/9M5ΕW1_%)oW9|pݛaUm^󳾗PQ{t^]^:_M7?+/OWsyNWs^뫤IG_|+*c|WsZE$9.kVT\Nߛ8[X<|:fΣmm׬2/t$^^%~lݚ-\A<6DWl0?˽#\Ec]v0'pPApPAG[=8pPZO2|+ <u8(?Gʐ %*r&r}hA.m $uT頀!*KU.TW FsŰpPApPA{j4^ >(剈C؋-q" k*zVgY~iQw$;e/T *E?Vds' 6}!6>[mfm?[U>!c\u64$)8:|3iVeuTώ>~}[/m3FYVhWy]i՗Y!T O,Wl#Q!=F) 犗r:8U.iiBه%a7.D>1Oi<#.!IIuSw避 zJ$oyQ5bj1E)UskSO$hsMiΫFb[jx4SϹb& S窿4Q:Μ?gH,H(p`j,qtIvz>lsAۧH}j-o I۫CKi^I-kPe))@J-,{<؎wzlƝ+K=̇ޝ [XH;t[4 }5Kmk7?~r䋼/íb@vk^ƧF[Qq#E_W'A{s>XrfUMs8QIHGn~bhaZ$O3\`|Yf)LU\Tt%V 1RÖSˊ\oiXitVۡq{f^RlATPdٯ,+.Qī'3ڌcJ'jf&C Ys |"O/6(TYT( E _8yy(8\,U鉽0? %ES|$껂"+ %]GLuf#FI3&Ǽ_ q%Nt*6udKQ!)GRnk*73 ǎG^n1rrr}XXa$hmeQA>6RJ9h$_n^a>Sm+ıHIN8骜Y2/X&]Iv|&Y/*MZKM B ZY± gRͶ?y>B|5Jee"53Oop- Rr[P6UX\%(Ym%Z cPK1X(3Rَlծ\UXѺ^#m2 [xo}"q55\ ^~Sc#m qe|<[E{p5iErΕ1xEa4aP f&ѷKSCY>^t q8nCXX%Gn'>Gzn#1vԭQ2p{Vz5ZU^__RϚbE2 Gդn/:,1 +{Шzmj[F`r6*b61pH⨟SN?3pБcжi8Yq' ijzb~g.L0&RןØw_ =mbH?iiiƩ71a2bB}b"Vm_ fE즨-1vPxv7ؑ CzÅ}ts|ϰ  nplkzI=i'Y 1ɨB%_ j B;\zEf⑝xy,5QԪT,Y?&΢c^˃yvOY:3ư{(4?',鯜D8Pg6(0?/[`] m|/xxÍ\; ^gDJ.3CnjEuQ7Cڪy2|6[PӼn3qʥ 9nN9t ݰ{JrXGxF%'a6Hb\<1b8iT i/f*#k  WK8vܶUK0}>>y^A󞷣c|D|2_~BJ 7"Cxt/>d6NQqвaMcT\G w/`Ɉ ~[UyZB=諟! 4͇(Pc("ŀ.m9&-. p hpۓsŬOz^yUUPu.n|ѧH._ƌFz Ɵۮs]ٟby_\0ִO;Wߞq 3zjğH Y4.q ‡D& lZa^2J?.ߊy{Q-C)"/= ƿ'\kkhTpd+3cO2ޣb} uUFֺuB "h1ᐙr?|3SǾSZqU]|'XKډ2G?+gUwf04>F`%xp#ԭ9> vcOKX$H_''bW{'`ʹ<|e^yuR$aUPd(JQ61[0x`4]/dA·x/V<ԑTb9$oŒ,M;{GDTyH0,v^ao  qv)'ǯXI{IlWSf"l\-M{wA.cpT&RwqS1p}x'wrN8J` 7 ?8?܍t]g4~ 0G ~U棗=x]^CF^b&n3mU*RP>Xw$QIeOdII[\[/f2!M (mf~4 31;~9dֵv_ q뭷䟅sgIݥHҏ"WL⽄¼l>BFVu qoqϩ)DҲKŶ2N`e$ᇯ_5bws1nƋ 5Ӌ"rZdbIŋF5 b7@bg01n0>NC^ZVلAa}H|S;}fHF xK c:`朣QfU<4=5Xe;+W c AE* MgTk<5{ !($2)Ϟ x,* !&lsL q8nl#bfƄDZ.Mw-R453;4"7 *ʫ(kdu>fN)wg4|Y.EmZmqӠ!zV+:HHNB-T 6Džc'S~.wr(A?Iq{j,\qU8q0|8͜Oh;@KN1bws"<'BAZ^}# {;BFy㵤#H84Up!BgߎuX`붽hޡ "ݰq:`qڮ18Hr^#߉ؠ|w 5U=?i6OD6ڭ0(H9D3';&AlUX3+p.iB<5ĝwފ`77yqbu\&„$* sBJp D^H>о-qpw?7j$"B# /) FP?>_tD5Ԑr|:d܂ 0QHL`_IA('8\m0r):Jڻ UzNGpT<9{5􃫋3Bᙩ =צ#*<Q7 Ƥb#P@yF܃[vBg*}mG*yϛ.mm4u/?KxhJm"q21TG$Nb@z(Ɔ2.0[׮o9\blc UC[?|hIIヌT( h[/_9N ~v$ObgTN~^~nt<|ЪM;Ij^)OL+N:NF"<$-ZBԷ[7iv4=~{L cߛ݀O/EU=]zb&s1Z?DL]q^SwܹO=|>?ބNj31/'\\̚=EAO=VcX7F0/zbw+%j9?Bo̜s'չn~CUTz+y7H@IDAT.Nqcqg?W.oȫUb{o"74]1zkZDžcvo"*3 ir3%J9zh_l;,x /?]qoN oB 釟"sDԋDηaЈBYߡ5f*#J{k;fajEya "~ OpO\,E`(T bg0 "Dy+= 1s +Yɿak}p٬QrwwMi?."ጓ ؙXB8~۴ipNp>qh<9ah:L9놁⏕;tW_Zk`;wyK%,8x*ժb  Ӆ+au& m]/-}1]5l޼ K1i ̹d.ߋӹ حUƼcۺCcZ mk#؞\gYЩqedc4xbtܵƑC寇9;44wo |AX;u"gL)ig Ҹ^WiTÀ5v>*%;1[-$s,B̃7N @@/nPZ9H|Ӌzڴ*i3 O8ܑw6 ,RqdZ|O?1L{.lKB1fop0uaUٟIۮxh]ޙ ߪsӕb ϟ_zM#D .:ғp}wF.T*pǽSѵy^B۹#~e{ ha8G\t!~7 \Mȓ^Ѹi門XQVGdqCyxp޵ov5nTp_rNE!wmAܩd$'Դ=9{c?(nB>Dj| zp ~+*Hb)[>U3O(ENW._T Vy%3w`;7º 4n*I3(g\1\#R##Ģ&Jop86x J*e*337UøUh LEiC E:R1^;|2pQz;-2dͿ'bŬW#;(}oßCzx{0c>tiVݷ+LPLf1h-Mp2p&Vu?W[sл[-Ov`{g >]qw!}qM1t#\cxg1z@'xj&rN]qq_|] ɩ\HSDhE sL\n4Oq^.3]ENHEPT-bbg$Rh "<3rx{Ы [wŸ7"n6ѻth1qJ<^]OEߞł;Vy*NNnވ G>>T8DV0 6+y!qX> /71uT{Dʝ;u AMѹK4k\α+ӏ| F!V1E~EƓS^¼y_a̛M?(?Cn oZ]p+Řz=:~ZX;x]ޏ뛅mSq*+Hûo}!uIgZ%X?_Jޝƅ۽+X8l֍jnVzԬ6vA3ftgz b=g_7u |л'm7 {9ʸ?؎_B[1gW}p7ơc1aJSPuG+(=*vx"KuaPdgWFxxd+XRR۶Dߤ5I08G.Zy>ص >ݘni)}_`dfoPq 6a;$+&e"nr+AV5c']h:l3gƏ{كligosKktmñ,pOlJMQ&A0s3,\7Ǿ3l{&^[#2b}ȤE#w l&%xEm UСarBhD5Ѩ-^x4'wbɠy6‚Ѹa;t }^NOMs|״P0q3mbhG3{S)In g7L}u9a]w~J+MKDb ۋc Ip!J4UwO:زe-3qH>Ep;{<{stE>7'p&1H wo<=@ A2.t|6)şR*bQ\3Ɋa8QEivruo20gi\^(fD_YAS4 .Z"'[..^jkۅ>c'?a#& {FׅcHq6OWFJb<IΒ_7)^#@!\H [΅jG^BtN'&*rэZl>-~NNܩ>qe%7>_`#hu tC{>,ݦSˌQѽbt.\KХ-q'pՏCiQ5Ou:عz֝û,k722wZM.mTlqa.؎wE5}?lݲ'եowO&7WNZ-xɈpƋF׊<{06r昨۸-:_}WZ%?:.߇]i n ӝoAddktMo<[4ĘA7bpԡ=h(.:[_^Ͼγ13FܑJy{00o:]wђe꘷4\bkuLGqv2G6C^^bqVjU6FDt 0hSn);kѫSk;&c͞hQ?]/reLIX ^ꆩnnnu!c<*ZTºݽ <]"}(gQ@U}[; 7!=l'Oe?DXN*tb=AuѹE>-Ba,t%z7ΔyDim9k7E"~&i-7ؽZ,QXw],dG7#<1B8]TA2Qt= ?,s9[GaHzc}[ @(?M񤑨*lKN+ 11uG:UQ='1sjYM{ptb҇"E5ܑlZd(YXq5(p(TV+WKP;q>:ԯ1zq |-XD d~ ɉ}?GMƢoWyo9z->~TK+\ ʉ;'bnZҗG\ PA=~,¦ QHwD8r=|gN/&][ .۫O-M_e~~ںF~T` o*I2P&vιF?S"a _0N1ʪPJƻR#K*.ztAJA<#lrV/U:"AQL`8#1n/^xi4gxWk<.UZ ,iZēnyc ubzm4~+""T za"5+;mthv8T*~Yo;gJ,\J2PFJOXQQʿ5?撷q:[߆VlBx~P0hBO|TleFB՚0Q8Jʵx8>KҷTԹ فP 5j kͻs Vm܂OY:♅?~UEzP(TaA25 ; owsʂ.]Kb_IhѦZbͪXd9Dr'׵1O7tbtHFu뚏(FۇJV0D _ $6\ecǓ2a9m7cyYH² Zo}ѰFYHЅFLñvuBEw#eYvŵB}_X76 a~-.8":A:8CA5W0l"W9˱=. ]Đҕ\9sZOܛ.P*&yXM7f$Gf >cn5".hذ.8 oɐWmI7ak4;\EU_|8Ew^CM|;1-kŲI|{F*>c~ uaDjz䵎tsx!hР!֢vڴEs*D]7*{G7'NS'͛ШHDU oNI#6>֌ŏK~FRvq>~_ j5CwxwN+ؿkp> a%:EF"Ws~۰EGVt86nCqhƒk/Gpxiܝk| Jӷ6^¡]K'f H\6=7^zdgQrV-yxbZ?9 ~Bt}KePyͷ|o<|YI5 w`]G&ny ErǤjT ĪGk6+q8ɢ .j 裞]bG1λѫ{ 7Ú7ʌh[7> ;w,>J~/IN-Ygݷ_!mkؤ6x6Hd"s) Gv W+'Ԥu#t'~pOnAxE:ƒnvl7_E4e2euNNzv#k?<(a8.p!Uy8ɸcH*8*B\o;it"H/+|T.j@ 8!k$hѾH'GcPvC,, zA~_uAoSFgSAΔæA#*/9Bj}k:s;;U9_q>"(VYkEq9Wlԯeݪ-\!<{Kڴk,˃O~Qa|*G(xnψOH@ۆÇ'dFգ3ǔ*eBCxfF`]zۿ6nÚ-{ix`.ZPCl&Lx7kW /³|H:[ \:zDCW/VAGa f~_|oz:]~ \7j,O7KG٤Q=Zv~T3% XxZߴ,@kh8æ6ڋqT܃jGCkXKxre-gvTbQ,piW_  'ASo3=;~av彴#ї7#ӧ='_6+ݥvnwqWM6cؽzL݈=?Z!.u rWk9Iy|yމ jJJ/cx0 -q R$k!ӠRp7ik >4 mV;<_ٺ^8@=܏7_G\ acرql} AZBbj?%;#iGӏ4B +,&Ck :Fc)Z|^MX0y26y6\s 4Oţ7:-^~1[03oH\_s~ T`;;_sv:rmh,!)ϽBWr;Y޿XyQM瞹GnC摭hُLЍ !ۄYhL ZoU[p8c0GMC *x]2e}N=1|&<ķ4 axI$Qw'ͿFrw :jZT8i5l~ >M<"k#? +qMܽ W q+ FW^ތ@^xoǘ]A;bI»`&; |K?]gUǤ;'ԣ(8ס{Rn!;ߚhNRh% ;7Ķ9؇IT(݂jQ!]d"Q]2y`lDZJBYFpq;7欅7w&*iyW<,,t >X"lK.x0-^RY|Hga\ZU8ًE-[SP%isf!K!Ln|QBh!&ˁYR f3J[!F&J0eEJׂ%/yty3+##{B{ QFI<ʅRNs!rwW6ތ7_ N9i(!-ܜhI"JOpPnS+LZI)jNy9!Zc`@-BKa!j{ M@<-bP*EpbQ?6p@y \2?0$Lm] 9k?'Se.]׬mIc[IN@nZ(/V*2Ŕq&~ܦOufbj7,I:CZTMEo G-XbjYɋZΓQô XL| A4y%ŏx 0#RVf*-G .Aj*pф,-%8oHbbjO8v<>Qoa#<'q0,N!=IO 2sST fCwe"]')[CH7;ƭi_Ԋ;-fZ7dp+;;!9ڎΒ;\A-?Ùsي<_9Þ!U:w rQd;4`zyNǎ9p ;8>n3JTHהLʑp/ O5J 䳎 'Z5cT{(HMN`̉=qwNdtE> O;O )KYC G"  QW!}"Pzr |9nObbbvcη%,X!HPv:xm;#*Z64ʔZy?駯_ (nTq i:wE+7S*!i)-exYЅB+JZ2qkŞ" 'y_m).bސ[ӒS7 WHb}V*徸Hݚ.))[zOyC]3t ;7PQC &*P)/8w(ߪ_Y?}s8>8 ]0ƒiNm 2vN !ĥ:]ΊOm?͠&.pt8(TNI"5FS{Z{t| twk8?{dg&0t CS94,Yl޽A=P#°'BW7 \8}odn{8quwj)W'bY˽(g}?4/]!!n}F b>m˘ P! _p9Yx˜riVvv>PFL(gb~K؝߀[|`0wy}hCA7 #oTL(s+ )_rTG+8O2.Mӥouq|l:/'lC(ЪnaRm2K/ךBb6c4olUnW[oO)0l, 265|۲϶{I,RR4}չYYo'laWs>m>{ OvEt\ͽ#0{t6m[Ɯ\m2J3 #4s6I0Rjo96̏[#2;U YP[zIi*z k{d4}y>EƱڿ HAb` yI3q8S[|Z8m e4 ISѤmVMB%x ^"xAߵ?;+uU#EIWYt:)jg|HT]gXf=%`BVMT B_V0 ܠm4#i6j$.s re4%8B1r)j[<4:]{!_M%цKy(vHyg) `ERU{umN? F~I301-n]DY[ߗWt}F[qp Xe"Mge![x83⥌wYMcJ3ۺ[Dt{+F;~' &:4݌>qaU<1dmYXs.{I<݌<:xR XJUj_ףcIn~YdgN3 *#ܐ7'exA ~,X*S$5xXǑ\"`d2qUYo=/뽽*ͨ~%F0dƥ,VS꜎= 8k{T9gux9k7nYSS6۠4l“i*/aٖ7?ޛp$6^IJ Qm>*֬h<Ӭl A1ƥ"J-vX b)ElKT}Iʞ=Q\ϕ&f oKK?8UNr-rxlq15eb1es~^0mq\RtN܉P!ܒnS^{SvLYA/hj+ʤΫ._e.cߜVQ[msř17ǫʺϜ' 猷 ,ҶriEųIQAPcr}PQSvǭWrMB^I"i.T '@A#t1~ "%G=G.pPAjk*XviV\Rm&Ry2u;(ࠀ 8(ࠀeV.G  8(ࠀ 8(ࠀ OS\Owq 8(ࠀ 8(ࠀ$+ZVa|"G] 8(ࠀ 8(Oq8W k9\Wu{> "&/[>D*jcEfj\ʶKU4[_*$Ϊʋ :U6~/M@I"MYۋ!nETZs9W{yW{mC[UxAa[{kAj/s(W+ ȅVHEm(\yVa.rR{:BR!qVEW^ѩ2зuEl6yU.Y[*9gQi:\iU؋%C'cDӓm9SߺxAa Us՟8(ࠀ 8(ࠀ \F \5s}Q 8(ࠀ 8(U@-JןyK(N%Tb"'o| IBq~4-brdeqPfWbT{wVfYi3u9sYuVXKx:^xn{߈s۳5>]lc`3wo=앵w:nmmƌU9]F9-m(޶0>m~5be|(W*QRlA dm"K͓!]\" PBv'+*I n+T"9\Pp'IkE,,vv&-]]Pl)nq\U|QQ*KҟYqpOY>ʢJ]AfŻ8*{Yd:Z,m,Vt-f:m(e~ʑ'/;??/`Ap\l >_xms#I%Ս鬞-[qqiWśz+40(8G4MKɌ33F1 E,_uƩtx_&Ԙ =E~ ?qltqS2>$ B; ')hIW1g~Xɣ EI+/e|_2hWwd<H9O!3Z޳Rj1XwyVE-q0 ,6`"Wppn0ڦ˼q*r )PϛT2#-%.ůlrF?[<233 _1&!5)fܨ` =;pCaAY_^/3g7RQ˳ruYR^^,BRSRQTXVteJEʺyzN2ePѥi(Y 󑒔 /_? <3G@(,vB@?.pTVk;O`Crz<}eŁHu](J~xA5Wٙ+r2[`@B*n(*#/+~%$W[5K0j'儖8籟O)p%H A_5?xlM3xSՂprD/۔OXg^:p?sOEjᘛ6nT JKsw%i9WpD1D>ö[+3B' !deeDn^MY 3^,#0d* #/ Pɸ8YOHId\|Y)pSHe/JPN6j8H?e~psAMhYl2 ZQpP|\5'P}v|a*"8'U Li3hj)}o;J:YJα(H>'r,ʂO'R+1NhJg B7<]"|QФ>?OxVV@ڕ~r22ihJIˇ'e(~B n&%uK$}UHzf"EjzjT)ƘoxRC/4h[k\$NWRx8H~6jN1ݛ W7Bs[$Fm,TϢNᦌ"{/5+½8i< FemBu\PQ4㟍fsrvkI>6-&LAT[M +~%0?%VNH.8s#f}6^A=zԌRB[3%BILNrgC‰ R!Sr:5Pe20J5ȰLxv./Dd#J_{=o浢QLzXMR?X,yv3tlu"L"Mʹ6`Χp,)e(o^p Lޖ,;|lM;\!7?H諁;ǜٳC\}pˈ1h״.\ᐇ?_Xq!{pи\ԕ,a_:`W߫1v3~ qdV|9wΤcnݼl*>p򖞔nG[:jևش?>n*r'Q`,[8WmFpp RRr0h(tlP%_}><\]Zv1EaI3ƚ(B{ Wj ?DavPF..@WJ>ssj^X}}Gcއ{0󍗐| o6, EؾW̙-X`7fb"Cx*BZB>Q.O܉Y>r6U-li/: #<#2"+ǣK~݁mP3K-gLύmB\srJ1 k`%1 3/8%^Yr2 ~y)͈p Z#_ lCΰȏZ "ʘ%^xOƤZ1̕N$wcU1Zص/%h \-mi!bM'Ѹa5yᭅq5ѡ~rd|44ނ %#5 Ǐ] Zݤ++:.?^ӆС[?4r%cfN`!3P`! T2s|WxҪ~&3&Ep0it=)s uUBQD8 e6%8s ZH3sr90-CޖpHE.;7_meBlkѝ0/)il'M LLeXr0sp7}#y Mh!b*'-F[h3weqJKPBGJIr(TMho!)qq) yG_D|rpUBB?vÈb؉2i<~6,_]YDy ܈C@ONC0Cfyð*k<1YqP`*U,tmѪLz٩(M՜1w]`UE;H " ( bEAPbe]]ۺ]AT:H-@νoBQ;w̙o=s̼eJa`%a%{x84 E91qqť#$"k\]WQ"+~O?p'XHNv;w8s7o ۛIvNNE:Vp" dw$uL:=R̸cmot1|yl- ݜ_Nk~\`J=*ʐCy%hysp1CP<7lGRǁpgI9;f<&MߋU?ewbD=qο|sf_fvPTB!;?[7Ai`k\3ꚉ\v'"Y:^Ӧ1]Qhۯ"r!Py_~Cj\=zq&%dyYR)˺b^,Yog| &% %?k'/KIﭷ'w qP7 aEbL̿ ă;_0.' 'jw $o,\ K?57r+^'`%VLk =)[aa 1*|4@\ OT2 e@ID@LKcGa]և:0%cqB |5J+`ԄIm/?/1,=%AaMעڨnbs4/ӟnm+hY~=iR}Q)6lڎnB^XJ+1jҿ;{}e8C\h^rx4oI㮚-K@V=0PϾKm'v'#Nέ[ZȊ|5+ż%/CZz*tMD0?ٱz!%cȡ}oC`ݒ§Q"l/<9 1gb U;ѤygL-:1kdC/FLӦq1[dD,YV]Iqk0bpjk9⨟𮏓oLd/1"<j~> qԌضظfnu/c0|`_0>; {D = 斻ع+ qh:]r3g"v`@ΈoUX˗Jͱkb5@nSm׾MvAڻnbi_b[E jhB мeGLRK8HDPJM'~\{| hCB^Z>}lOɤVz"viMd7>#g#2#1U:}Pֺ~ `'ain>ϟApѸ^\,b+ pMo P?s>^}j܌$صwv/+~)XW']tt9\4A@ AHs^= ISӟ,c!=Z?@6?!DH -ðu|(j̅P$CsǸs?ꭺkBG ˋ1vLͶtcy3e'Nmco?Y8Rq_1wr_"PՆniRdIû‹ 'ߥL.s+qЎw"~ْ1seQm6,y;7Y}]ؙ_ q:PEmc4g.[k1i8WoOm;PHA81|@k ڌ}v;JW7&_-fVݟ4n~4lHڏ]{aՏ#&:.sR>]tfoJY_AQm,~츽WUV_alӥ/Bi)3hl-ɘ~Tv; O=_,ߍ8ރol_<8O הAg~%[_'ɧbv2|i3jԸ˖h7ńc_fC{׳ô鷡pOxo8@֡hrӒf17CrF62~Cs19b7H̢&qnq;aaogd3 ZBoj("q$~m<*d8ߞBx0Jd9D=uSDX5"2)s[ZY}4ŝݏí2,{ndGDGJm!V7aB Q1P2de6'HUG$5V ?余VT,[Xp>yṶ𔚼/<; ~`<?,f%vuXe7i|qsq 8K;cVV/=-|)Nvzص;|cYqzK<[ؓ?z>xh#ufk<ض3;oᑇ͓a !ܽ7Eh~]=z мuG\?Jf¿ #/cF wU( jfaԀxgLMb{ŗ^#Gq*Тm/Lvb`"++I7>i̻!ԎϱcZu¥c.aC8>Zsp=oᒫn-MO_8V=_1#YZg\xFEpږ. pfG##+B5-5 O}=º #* o1($%ÏnC܃ yܸJ۴/><3KΧ%I(>/>v?\0~"慄N>}5̚0Vޕo7|ѫh^L6 膷}Ͳ9-.GPx8 9p:z/غi7>XFa;bg|Lquha,ߙcUK9 ɱޝ[U۴;a/t-#;RQ݁\_s!ዛ/3[/6qWrwiKe?1DbB&`9 76r m?̹9[ѵ{<MJϯ;qoٍ*o\{QWtnTwݍ`~;z]Tck],s02=ރ-{ нSSDSAv&aw15)7| Q+ڟWl!U)X^1wᥟsB]4cmkk),y WgB#㬭ѻnŶL 뗠o}x[vd¹{[w*iƥdpV¿Q}}Zt"F=~L<ᖙW&|EQ%&4szţݘ7 jl|17,^ MC1ZC'Uƨyƒ[Tb\K7Oo-e7XJ^XnY55YX`X'$ ƍ&M̛.Ʈ#9)g4 A3 ]zqA0oMv'/.'}l9_0. ߗ¾@r:e~?h؉ZӄP _{ WF#sJt{Q#ڵW/yފ4|gMզ)z9̠ g>Am'wDǵƕ`h\54\;? jvMHN"Ix4pju92w'1b P+%ؑ0Otmߒ>sӫGPpu}-x IYƅ/qaKAk @Zq4 [vɽJ jsyeaqxL2 ۵g#DP6K-~qش @vk} o?s/wv2+l)g &^)[Bq"eR\=qD~~j*ͳ@ MԌCԈVT8Estchd[V󈪰n(Lܹ"³!c8\wQ'KVQp#J̓:<5O{64rc$D_?zȇƇNlC9_\9l[V, (S(V{PP#K0|mhR O(R(  ,l o#RS£!ܥܾ-;L>͚xH8|5BX{o*Z6j>Xj-ySuw<3i*( q~֬]̯K9%vmi!W *5򹥟{w&`[e+ѵgOsHuf?L-ݗ ?yt :/57bݩS }3?@*w|"%2 Ժr'YY}ޛOhRi",ݖO9ßmk)˧ @.v[@\N@k0GDYg<* w& ն'zŵD帘vg K˩/H ݰh\7PloCH/÷W@8MXG3Axؓok)Z?#_L&-܇ ЋPV̂8]Re,hDs(;I PFO)Anw;DS Ϫb6sE-46>̺6z<}?]{!QWHI[,*yÓ4>\7n=n>0dE;rLr<Ơep))Gfp1£_@W>$Ѵ_Z[DgXjzi8WN@ǸPv˃IԴ:6dBͣ(F_+F~4r$SkBfcBFP`m*"~?,GU!4Ʒ34,*6-Z+_&2”i46_v9.t8 !KqFӇX&9Dcԁ6`oN>bw"uPf|0Ɠ.ChbÒ^  uA@vm'!=\~6ZlbYZ9p/#)oeX4m~nExP֨9;ޥX Vܶ ЩO?W.9i~q cG/\ފ,B(* d.cZl-pܮXDxT&iUC|K.f)ŷ˙gSHjn>uo2)r+ZvFqbӜP`Cy%}V;|*& ͸`8Y mrC<y~梇~{i4<2nf4ڷ}gxDFpK>1qOiN,En45Y}` 1Z,Kࡹ4Uxx$'?L*R8⡭N]z`3/AӰtz"e eԌGCX 2vmÜ븻 1Ԝ\We]{"2)ź- R,c!V#eKyKx((ď_ M_8:r>yJǝ761hLPsߪe+%QücXrp֡h,ThT| ryJ Dn~!܅_12w_4}ET,\̫ Bmc*tE;CSh { zthFJjEpi$Ff72A+t|zt-{ʢLɃY$θbH;Tn? "S lAC<XLlz|>"/V i_>i .1sr}g21R˯B[9|pfm6R*'xU ,76,f\tc/.+i;[:R6d5ziog_zBC ''@DKIL>וQcC-9k EsЪm7ҾY#O,P6nѩCڂ]ly)ܐCfI\|U5rчZ{9Q+ ^zz+2x ;%{*^sx~lqˬ[Iu`}DIAC%uBkǽ3F8]Axt CVA3ԪpjGʷO8c^jÃdC.y?bisոpmS E?G0eU] 5OQsW^=cDly+K Q0.nv?4Ү5ξ|HXђ H+,0vEƞ=7U/ފ*/ÐygIP[rG t"w?1eX/N(:'`3=ܫn\5ZEbXZQW^U9 .ZULqL&!l`kLqΙxh]Ye.TEASDS*Tz 665o^'+݀& [Em]3smu4_(dž*<٫kԚ"ݔ縉Qf7jn=EL5"|yAvIwk1g7bνؘ Ok36!1nvmOEb*/*= NKjQ Z5^q$k\Z~wEd#\V"g[J2'_7s6wMh^^]Z n+5<Aw1^qGFH9ʯ?ꟈ*\dIZ`Aɏ?x\0`䪧_`V>yt+m[yhQxPCxj܏ۡ„Bu>5ow52drڢ݇`롦;32iKh׭},cme[6+# )iP4 7 ر# <`ؘk/T3Q>PmC-bnNʩy 㖮eO6zrE V/DL - RpڔS) )ԀdulmVqN"v!\NXѲvh?LM?G x;1157K2H;&2i_ڱdјq=852݉h2c=!x:(ԬyxB+.Ť(7+<FsE쓉(Ԯ5ᢩj /'|ydMO݃tjR(vQ ͞Lm۴y;P;M۟ʃi< VK?A&49Wn.srY8jìu MM]u )l0?[?7%x=!m[İ|Vh봴}< ͛Y[r7༏?4ͣ1 ZA hrZvܚS@3W%EPj3ir1oɀ\WFdoQaf&Vyiq4}rj{&'";?Q54a  `"WEŴnF+rm %39yxX6B])t ýTY4rvS?GؐtsytذaPȏȯaO:+L_'|埄)'xw.av-4ȬH]]Y.TK\-Zs9/=%k2;LO` 2(e;r_n}58U|4E(wl;\kN-  (O:"8jgdyY+)Ӳ~qnM br ]E'u&ߗo?%q;Cxˀ ];7qE%AzfL& t{Ax-2IKI* 1 SM"92NUFkeLefydѤ~R[2Էs|T-Fl'Zc@o_8y}a.*?d"B=$oǸR7F~$pzyVHTXIYXcYu"R>vkՌ8CQNRd#Qv냯k\r[]rNƖ8d᮷}~v?.qɡ.zZ3ol~hǼcMܣ~EƄUN2@mfHU^?ikYTav;Ii/UGT[H 'kNcw˂ةDvCvrAR>}hϹr_zjOwr0sU-myC?\m`! aGZwVy?降`:m@1cC@:Q |M^og}䃮5Ƞ"tp37D(NmA\fcz"*XxW[?X(jWϺp'bVXeQ#l󬝷ЊNuu]+k"[%_%QƃR* r&y;vYTo!ZP^I_ũxA٢`,0*o+M9LUnjQ#Vy%NpyWoB'}Hvr[]!r Ǟ:!TE($QB+~)C ͲȚ<gyN1r|`v*o-9\42t^VU V5!#S6rJ6#eSt^..m2UvQWhTo{$Ɓ $oI>29겒x`RqÅh{;CD℟8K(a&AiJDcz8H_K-l0QQ6yW"jɊv8O9)N. 9X)/4'U~acuwa a8-iwk1R0Z0tY?m+DŶ]G>vn3FvFҧdܾG_d`kd@NqStuxtߝJ/O ws&#Qs/&ۦ=4AiYB06?{5ߔvacTSЁ]u򻬇#9]8:aD-IJ_W l%p$ #,zilb縺>pC-j'TR{1O[/z-_JA'N ]9M<.IF/q]m9{?/zWNWaǓFO__?cw,p]t_9QW _wSc~;5U#xߑN4Ml³.ںCӋx88'uW^Ǔƙ|?U?+𭫬G wHiM߆@]!J:z5Zu W= SyɻәJ{4x?ViV_zg>z:s.ZL֙^ww$ފ^/U֕_K8)_]4B)S(3+zJ_O=W4*^_s=/N}]OEzqz?Z)ՙ%J0/|UzsUq*\O'z8Nhss_~<*ʻxW*M]Oz*:qBSSqW4zy]h+Og~HOgv~WtS튟=[siUlOW}Nc_BڬN|:ԻJ!类*N=42ԔWQlLS寞5KQ񊟢UgMM%ؼC.klwI)TZ6g|*DQ~걶߮PS-}xys5K⪞;.jq~.>W^8N•W!|Sc]Oq]ѩo3?V=%|{M90RmR(l8_ yJI=Us n?U۪PIeIe?UNꢳT:隇9*\*D=558$*Ou\ql84u_pӜSSuMѫgݔOMStpwuNWWNuѺ ;8|xO=k/MMcWNSL A `04a cRA `0G8^6 ħn A `094QZs0\ A `0fY&{A `0 @\ `2 A `0?cy 6Y A `0 FT56Ӽ&A `0 @Cn0?"Wt jُǓ `0 AOGׄX Ԏ[{%o%qw?\RVB_N[8)yA `0 &NpM$TUV^D!7yyYZ(=ݽwE%pE`vwx*jSAܽ(,)\Ez M5Z `0 AAbmxϵ(+=?X nk{"<(BpB0T{$B>=rxyx!`֬ـhMBΒ;)o߼n~ֱ**JAޒF|T`݆ELP^EɷanVvEd A `8EpPh\>rfRH/]w܄>4Jo`U%נ_FqIV.Zb{ I ){38, mSKOClTRb->hO! !PZxwCzVuhƁꆼtؑR -[ydrv=';C־عn>hӮ-BinR*c0 AA)Rh)8p2v 1/Gsb̥Ð6oK&%m*ẛ&!sF޻k/j!!3n4>ĉӰxx/hKOKR\/x,7]6_n^.7_O `ߞ-ieUX'x,axo(KiܱlgzjفKlOISޜC4OM]tm0 A p,4ɶٹhY3ѧM+V)7<K}s 2Eƹ\=Z`%hcYmpǫ0^Hh.9g<: <I6ax??B/8O;\ j0r:glµƞ\ ]X-́*(}|ʿbc ht1WX(r+c0 ATA\*-qA^~cC9X-M/Q0F"x5Aa{'aպۯ'DfuCN>D?}wniѲ=&8 {Kgo/%Aҫ.i{Rw5:Ơ0q; 6 yUHXD C@)h’ t783o'7Z "k(8A `0 I08Ky/*5Ҷ#{7>+6&boޝK[XK@Z;(lnxQ ZE8oBVHCL0ʐo<)&޾L@i3`)׈Љ<|ǰ1xEp8g@Kf̳|}h+8PRV_> .y.ܼY&1 A `/E!wk^^>^aqzVi]Z`WcЈ k ZK;T%ؗ@|CgP^H:7Jo~]ݧb֥ */iHۮݐ=g&>{$Ļz!жU 2SPJqbBrd;(hVϿd? s?6nºտg" [ +H\KĞ"Уeÿ8 ~ ֮YC`yFm< XmH;4 A/CVXUM7Ŵhۿ SS$:ʯ?%x_k{N_ϕW>3ƍ03=o@1:jF݇V㏿q&%U%.ZZ_(?"?"EbD,f+.*.ȯc8w^%=ʬ_j,6ϺUH^'7('˻o))796yӛw\62f"lşt,Gy A p*"Pp˪G_Kr7rVnppOo ן)\”ՓVtz0w UQЬ:OZE4.(뽂mSTQlivuZ,-Yt|7QQv}U Ď`Lݛpmռo׋,G`m1wԸ,B%uo5oSǺ '%{nٝda A `8EPS,"Q4r\|HhhrqO˯0mXD~SZqL.Yn-hVvʿzq#AX|N8;zV%fc ˒Fxj![jA `0 '#\;дd|$ hw/4B Er )N㊧3W4[=4A `0 l: j+hQniiݠk0 `0 @)6EՎ"`ץy7 A PhHrkS/P:P A `heOUZ@Sg A `0 '?%O?NvSI ,^N6$A `0 )@]ra]r_^SA>Îo;e[dh0 A7lU~2ߌѩ \ d^ "A `0 :.H#mGk!S!A `0 (O=]p$Hq.XK uƄ A `0R_!\o%J<[ `0 Ap:@LUX}μꛮtp-q`v$`tz_PYBA `0 ",V?9ˎU˘N2a*ڹppw)MA `0 @@@iar_»]dEµsE]*FEA `0 F<*Nbį0ye]ULUȹ*\=x bTR4 A `o@YZ򡣮x9ӟ!\U*mUq{gW,Lw7]HwEx8k7S.P]\/U_jLه7ͷ{o}NSIGǢ@Q D(^aW&fӳ}g?ݐA ~֖B{׫9x5 {_q>ړ/>;G?}ww=o+GW7w٦Eԑy_3׵]֋:ҹۿyMO[lY5OwPl`~>kl>0^Փ^Ų>zTX1#N=K-$w^,Q]彾Kܵ^Z]859{<9S1L55Gǚ|wg_>{]SœO.>_Oy/Ϧ?q?@aXpo]yW^kkNΖ▞5KTK?}/|{=7?[/b ^$w/NF~ +Q D(}R`H»w*W1=~֣|ɳi?x41swǏOpOȽUggh_h`w^Kw[y4)85+Ǽ0^{F1<i &ùKEE?|"u~*Iy]>T/-Z_)PW_CZ;1z^Ǚ7}ꋮ]_vw7zXfirk1skɜ'v/,S[w J.zx xDkk'Yp2qn5&O5^O)p߿cl_3Xlt}XgxF`yDXNښgӣM z튏庻.c^_9Kxe HqjfPSq3:0 D(@UKyx'.U8x`;bq2fgvS/zBYs5K"ԚsTWD|W^q2|ŻdG(@Q+s`K {abv13nF Ck%CG%|rt9K^x% M98 j.0z+Wc:Ty꣮xZՏj}&5.̮u%v佗*h^ozQy 8uwsG+|ԑ`9&cX55?.9b(+ryqg<-aE%㥞ܩCep| KX{|*G|Ls2Q>@Q D(p?Ю1F}8+K 9b[S/׺/]<%/G>Z+桎X^F ޑW<Xweww_7{?zޢ:)&;`G2=,yCމ{=jFZ_|᪞%VS z9_^&C.Q D(}U@`]Y`] yZ:pg\WdeXFY5k90> D(@Yb΋sX[+G;yn{&|W_TI@lqSmx'v?]/a0͌E(@Q({ny-yuS2Z:d%*,nY}v;',S_g# @Q Dh?;' 5=#|scۺ\- ׁ; 3O-VjzQ;/N]h8G(@Q>+h#s] ?.Ԝ!ݙ sK泇u[)ͮ Kt- q9\W&Q D(W`i'9bN}ԝʣ,O-5]5wzХX8+M[Ý0{Tg-%@Q DWC{a8%L޽=Yp5VIT˵.dui8'1<}gF9wbŘfŢ@Q D(({s_Gy v/i[=\,`Qq7y.烣@Q D(gίaYõzZr2 xgj/WK=51qpWdm@Q Dh%﹊rR]#v_qØOo(Լ-k9a=ssĿQ D(Q`\Vc5`)]윰9zs-qEqF`yǺ[e̬x,y(@Q t˦skXyj:K\+s-Ų-k}5&/XWqmFX9?;#|ӾѼQ D(@8/Ww}|3p)sjYzk5L_kKzbK9 Q D(CT`iѬ9;Ӈ}r8ìE!*B83,fQXyeEș (=*kB^OA\) 0@ HR3?!tx\ ˰Vňlr.9L1J4<["x5ŸfXs`c!`b81h~ 9㞸P\ O GN)b38 c .pK }gw3pn7>Vpj9HF#d#PUs"Pƕ>\-pϏy#~a <֌5&vk.aG<6(lxOqWMXy  +O<]"3ngE\QLgG'~ƅo=<00p.rup re?ᗢe 3r0Dx&: :i`&J@XV`3vh8.+: Jx z;Џ  !tD1F,;D$ER4$!2d&2)CʑV9@#m!ҍA>JEQCzhNB3ѩh]E=h=z^G;їh0U`'¢T,`Rj&O_:#N85OT|6_SU!ދ%;7MH&dJ:itDъbqq q#qN|L#Hz$;/)!JHH{HI.UcgPTJJnc**Td 79#O'/#o'7/MŗOɢ̣RNSQުzWU]_CՏT--EHQRwR[oi4%-J˧-UN>j<9jjjjՋ+_V kXj485*5kӤk:iFkj.ܭy^IR+D@kItnFgѹ.m6[;KL{vvNNNQNưd9eO# GX##KGy555aAapI#QQ*cFtc?c*/:@fs-$Dfդͤ4t}3Y*V^scq3kX-<-k,ZL\h`J׊mUdUcuϚfo=պ &f[V`[i{smkE5J4jM{}}}CCCCëSG}vWG7w:;59qu:W:_sqityjwzˍ6m[ww{{Gڞ1KOnclԗշӏůğ_(,#YM`VWAA,o,VK0\>AihfhMho[،pBxDlC6]1vSԈ"m#%Mqcǭw/"J +XL928>f|N3c{,nu,5Q=qbbuɳ/SSI;R&LX=kĒ7&YM*t~GOL9FHKJ۝ͩ7rY5ܗ*^7ߗ_Q<7sef_P!녯³6gώޙ=/W%7-HK-:gW.;zO]=W!!E}If-Eôi 5 EN_/.ӯkXmMˉEo_\q+W1W{+\+6\q>^Toomv͟ʲbq[;v|)ٹ+vשjՠ5=\־v>ƾ`l~q @Aσ,mו#{ )nmi;pdgIsQˎQ-86px_DǭSZL>ySm#N;zk>} /_rTumm=.7^>XljW\c_x=znNywۯ;^} T_:;> ~xQܣ_>>ܵ)i3gϝ7wv_y1EK?5աԛZz͒zowwk_L߃wߗ~dz>=y/M_#s$Q Nh)ЯL!> XyS;%?Z=<>..mP.J_Txc!|xk /_`o2Uy'UN¹7xr"A pHYs%%IR$iTXtXML:com.adobe.xmp 972 172 X/iDOTV(VVEc@IDATx XUי DB!hWT.%4F21̃ҡAMfJ4*1O`{ы>c+b'jGGM%$A]|}8s@wkoz_. ! B@! ~" <@! B@! " Y~B@! B@! $ ! B@! ta߁B@! B@~.`v`"B@! B@! O/f!! B@! p ގD0;@C! B@! ~17n(BE! @qՑJB@!# ̭R*B@ȃLctB@xJ@O Jygf, ! @@@*/LaB@!f`$#"='BD07B@w`viy! h"[T".`vF=" #|RX! K@ssII>! pfwIx,9v᝻ި xztV" GOTcL;~~~MI ! pW08-ȯBEq&$q/Ag#$hw3͡y<̵$0싀h:],;>Fim<գ={.ms! pW0s0ߞnjt)+)Ɯ=`H,.] fg|7Ӝ;X0WVVxigc2ez2ЅvN!]ݻ7mG! ޽{xf3%9{9! hw3͡y<`}D2i:&GCu]*pd-S:u=k4*;:NJl:zR{t2 |<|>/.ҚswTTO]J-P(֏ޥB@=3ep},tMQOc ;_+uV NeB jxf02tUsPTuEY@ )z B |= d~VGb,fsYɍϜU1[&iduڶS*<R ڒ` ϏlIqвEfT">ޚr\[dddKE` nP;  t\[x`l912:A9' 6`hE`Ft Y]C1F4vL!p:k7XPyq#H'+o& kfi:XjV8rlPHF!  iiiH 0SNE߾}qs><̾2Θ1jr!qO~ ז$Ym-ٹ31yiη`puDm YkٜLʸs[O6>+k2]dʬПU5 .lyZk>JfnU4zvwn fnEm xfV3kNjhs-G{Kw7o?~#_con8AcƌALL U<̿:[.㻋`n_BYP?yFGGcĉkȣ?D08SCcFm~1lCxZ6,U0%μX3l>n5+۪`>ӂ!tKb"ٲ 2!4wm>GJ+6%;3aVVWl)#crւ%bnm7%R@O:'-G(*.e{v ŀ FxwҵTmDAp8OŅKzR/Q0gkU)_ %z }Ĺi8=$Vufm>~B(t2do^(#jKU1PKCU| *(CMM >C6z|#1x`ZIP|\`(E幫pl;(mQ߼rJ/7zoJqc舑A%p֦d2):kosY3=eEpʷc{Ѐ>8<.s%J`ipEշ<2T"/ƌ|eIJ(dPH?Me.WN%oU1;%IJQ0[W^Ckos'ge4^hϿ=ӫ滔L=#9);YƥbcѵCbÊoʑ<DͲ\̜UJ,Vsfa(zMzV'Kq=:Nc0NY4װ*}XlsY*:\mupsŕ}@i/qa$ >Wذ#KP#1)M,K *[O[nҘ!>]-%b3SY`JDlZ"&-†W#Aërr4s-U}7oo|Ұ2~cm!9I#vhE+ph4Y7{ ۼ1067Q_߉Y/#ߝ+l++@hKuiq&G ʂ3x;eu}v" 2 rSfaVo: 2dL׾o GMIrSm]I`Snڮy";8c/i90HWqc%x47ر0.߁i^lEk.91s5ѻ%rӍX5n~04'|]0(dm8YY`^I*˱v.[9gl=y͂7&V|sw`Nx[fWѵHڪ -FNsHFQGr+v~2WV(V[B0x3k'b\i`V;b>x e^z3Pig=qr2?g$~Fֱ"E=:W]0b=`D8ۨ3ʿ9WxlVL9U\~ k[jNG& ll]/?GW@p SloJ* `}#s%bT14F׮E$;k8ީ]$^"Arqo v./@So8P˓O>7`ՙeIQ,̕\)N]\%%FY>3bt@K} \M,JOu4'ٟ&>VBY g(f*cJ@WLYܾ9}o=Ll3MF!u <1Hs-Ik5FnMd/&Mn]q wYȐu]xm@opɶLZyvr96^,+v!5ZRU[,m܌( g؁qCѵ{7c~E-fc9J>dA~'E;c${2$\$tfhp֮Y*k#-3X6x^@"VU%$Xd#usW[o^™ ߡL`x 1':l;UgsjbDsSp^9Iob!e ~#f!cxKrOɵ9lȁg.Xu,AݢV85usNy鋕+4`e: l}?_BOZپ-HSls{Z"Ǎ52Τ<`.??}CB?al4b~#(c&`OsWa *<-fu#a0 t$t4?=*/ga̳Lid`0\HB%y„ `u7=_]ҸJ 5//KDU$tPt }0+ayh6Vk57[)Bx$z^ 曗r?ZWϕ9̱Ջ-' U$tʳ b~tbřشd-Kw-N[Y:~. Z Z. qqE݂$a~5`݌Kҹe;s;vT"Y4+sЭZ]j4d1wٺ{ҷ%LܜY-} f]$u{k o};s[CK}2^Q::3;>ظ]ƙ5?`,@p,s|MKwh.yDAq.`飘kZ7o^@2$i7L_*'}ZTHo|{{={ /oU3E[FAјRKAn[l=ý}^g J0w 7r= D0y.yL_LS k٘i[ -.zA(y \h.sqpх -Ǎ@.oA! Z+N4 cjSX\]Š8LE쬝9N!='q%4'6'lZ>Ԛ! ah.e fX5X/[9ue9z 2bnݼ%7nG1YtEkEs=ʇXhڭm+v DQYS['6izh\76=g^A $@EbzcϴriyVg`sSRwDN\s!vSFf`N AFu ռhGz?yNܱH߇Uwh.L P֝.%G=+OERf酥5:,ub2ZjT 7xCE^WT4p}ws~=zhܫkWi N0y"f3k'>ꆅY%q7/z=ԛƬ`09̍<|T?JG8'` SD(@;p~=~x+ɛ<̝kŧL)%JuBˇmdUJ8 ˭~ئ5!:~7d&6whydl*g6[t{a_cw* au$r\?2oyЬY]+͂ȷ$_h=lLu;0gxmZ/-Gs]Xu⏄y H3 ͳ֠hM蕶gxnr־w-D0kS{_b1bDx"ל.̚>r N0Iʤ9VײWc,J0ӻ`\)NZEj{ ZMK2k7bruͰBsnVC!N^gbሌlq+<̝jѓэ944мU>IS{hjX2)eɅes !T#fk|^0_cC,dbYIݩ٭-,Y a,qkif=MZ=ڸēNljWCiR1z: lrEc*⦆.kLHM;g@ jH 4ƭ{B̙+i90f؂Q#=g6췞q2Yݨq}e4)pɕ' oGݣu_ 37pdDrr2odXD,[FѺZ޴̵7Oy*B1TL(̷Bo7`YM,YL!qq~˚\70kS mq&鈖 fe$zGO|]1>ۿwZϸu੡e2[#P K'k~Uţ ia[;BQ k)ǖ_vG331H trZ:.n(|52MYimKIǬ4qښb&>#b=خH3mqobv|]0\ hc&0QB5$v}E4 faδOɪNĶ*Ci~[M0$|킎.bGl6DQڗIt-ax`}ֻ;oxlj\)zch3,$./RH? UƯLEii,k!s 5b߲9.(l9c /婠{ݓE-N}Qsj.k\SymZ#Zr_OnWaȯQ.x0 %Ӝ,eMmooHwMz|]ƙW& h`v(S$ƻյrqd}NYu$s(bjAsBN ! :,OsggPv.Q6ے8c-cr'rm^R媸D]Ĝ2d̎)? 4Y\6h9{,V31UfMaOE1ӗ VEʜWmXs7?:篯\` ^7a myoO⥤$nn7uOqh^>M-EwNV AK6eMv7٨e;2lz'.-l)"7R[BƨغNw_*(nZ~,T2țQ]0v=w6kAVz_&ZNm ͨhY/<֣rw^H4{!~>+͢j/թ$0QNdP 9j64+byoFB@CUdI^L0jz)NHV2Qj8lNH0AvEZ>|b>n< h~GntWg OlZ_Zr5^iqfsK0sW^>/'oU}CoVzϰ%?.LShZ \yg-V02mN? fS}.L(lGb`} ! '33Gir||Jk/$9iX 5oS -K5w-Gѩ0-خlTƟ#y)qlcAȜR[E0oA݂%Ooʥ0]\>&PTݱs%rӮDI-_iSNtb]z_bTuf=m|KT_Ek[#+omh$jQ|\޽)x fR/wxC nY Go7wKU*yھr z91f-@\(Og:Δ.'ܘl@R2;sheW]0Á1V.B3Wj`G$Kp%_}%]! x";8߁ǂ#}_sQNG=OVO `uj z$hoR9)WUM=cZT1hulLU|:_=v!捝@ָ/cQWSc.9O`n4]c޾_eZ5*s3mnͅ7T*>O]̫15o48ӝ"LNz1Ng;ͪȹ`nVQ$" f_gx,kߺL!KJ 7^300zRti06^66p>EYqw8hdDYX+g%0ϿocObPPjC>Wg@ys o!,,DhW|3 !8"lB@#`=Rr-!S%`$B@.̭SjB@#Fr:D0GE!  @rZ! <" #|R.HB@.̭SjB@#Fr:cifH-B@!A{XO!оdi_zuڳr_B@F@d:XHs^F@/r;";HGH3N@dK@ƙW=+%`Au4G!ed #t4C!A{XO!оdi_zuڳr_B@F@d:XHs^F@/r;";HGH3Nzw 'PQs?Z G ~~~ގRO! q IfJB@!>ȘfMtxHwoXWTsă!})>E@v"jB s=E gc2e%I)Ӂ,]h+J0sD mrB@$ v}e\B! wd޹ (eѱ?P]WDt -@-Ykꔸ$t=k4*;:NJl:zR!C-?^! @'! L'NL̝äB@JOL,l\& LbX& Ȝ5huLѴϮ*?K UWVGit(B@!С 8ӂ)C|cgXQOc ;_ *jڙC 3g[jb/a"O!%Bm \zyyy6l"##[|1gTblvyHB9\0 #韰9E!H;Ӈfݟd\E!fF*B>Xf*%'k׮sdqFEVCc6?V e{- SJāYLj,Zk|; mep|,$Լ GۮwD0w ! g2eڭ,HԲH,ìL\Ei6C%Ւ0a+ 4yr+A͖hV^^ fs .y wjTO#! Ѱ/׷PCEƀF T_F z /*)B@v&(իКgsR C/g6w)O/rVߘb=p1}%]T)+53qʑ<~SaZGH;v;4| UiJ4cF:^N ! @AfgwЫwe f7lҳ>YIqt|ȢU1Vbyh}?L0_͖zGBn:w"er$^Nl0 exIm>p2Hٽs'xEW ! ڔ+lc=ܴH$:|e);Q+s),9ţy)8vL+bUݺlYrfbjurS;0cgu0Vq2MOۺcL0OP'[#:}O! @G"lmc%KL $%l!~Dґ{ J bu']޽3k,飋[)ie\%ES%Q! Z'2>}TleX&Q[E/`<7ٟsՔL,kH5ʜ5oluVsY,W$ݹ]fOE;gV̗31YĴv% d<-& T -%pEZ;c07_FgJî%p9J<ɁB#h`0a&Ol g)#c,,r^sֻc7{r9,e lY e,,[߰t䬋k0wa"D!ꆅtf n6+kJ[YYR\y?:~gD˳y8{8n Swiu}! @"(z*WPPi}gӢ)@O>L%JnMNV?lZ4@QxU^Ƥ)v1wlkqܪ@[ؤB@'2'|c3 eu$r\d,Y@<-2q0Y}Bnܼ%X'H@]Mag6y<$I؁Y`*aqHpy'ൕ{k4WM! 8c. *-exXbZ:.nrxjoZMMJ:f ʫmj;3"jC-܎]~f]IDATh{ *a)Zn-wtV1-ظV+."T/OdM<4`m|t.t\Cb9[YM7 bƼ)wmN}JVu<$UJ+2a{ʳ8fzsE9b}.ERVgL됷+QFZlZ\L!=lB@o'k㌵?e C,9Ë.1ض.vh\J8]llx>{d4O"='{B@!ІjZ$Efe;S=b0u%7-ldl=9+sR! c&;wԿtpI΁ӧ)ȘXjT-h52δJHG@ ! @pAr-MRfYۮ֚).]Uײ ! @G' LG>̝ߤB@NGNw`! h2δ vfbA! @ 2B@o% ㌷lޗ/WB@ y񙮖B@ g_TwܠBc ! q[{}Ks ! |ZFkjn/̾}(G N܏*p7]o|l0&j2 1ꕒE@ (|ug*~%[^[WnFcO kpJOȎ8z峤í=>`B6:4^Cj#"AE @yX jIj\);1 Ey'd&a #Lc$gϬ$8:Sqm)`Ivoq1*Y_f[h!hNК;g\WPc !kњ #^PR `N50?>[hs$œsM晇oOB\5#*ڳYW mxc$՛AnPK bҘyиPl8aM䵶#k1b&_w3Jسzy 6{P#$AA 8œxE Ge:YI4umNccVf`5$gf2lXWfLBk%&MnEYʮ g&̥j;UMʱtc~?h̸#z%P(TUT6l+n\"ѿ#:Obݧ~$6QۋzRM ḣO :8'F`thbHr?g00^m: ;2:jK.) W*?7-T;k fF.5b{*bI>ewd,*,E~{K'쨞_vsw,hL ˅6D} *Yk<[qU{ 0dY4c ÆR IĈTK,83=E 6=1 6Dž[`jY;W|-y|:ǣyBțլB{iY `}z >!QIԘc0{v9e 1B#jf|O-[1<\+lz{fyK/õoo?yދ8=4Ŗ%=q+QPSc>]aNO NbbEWx9l~Qxce %TUL|分T|}#=̓ORpkǺA%ImxOx6!w[?d%obpݝ.HKSXӖ7$ f7,òDz2!K?.iyf7OmWcUsutX9y*܍0{0"1Kx|Ghݷjuϧr3U9=8Da$"'s)T4Es/  p  aI"rKxD.;bNWIp2]/L_,=f;gdLYwm8c#Ӹ㎮x]R}07$!@S?(D!¼r<fz]Dlg)b;x08DQik,CbGrqeZػm7RSlbi{7u-f-Ӥk1"ܲxJm   a0%ZT ,^k/_Mc̈UF4L\MIY\dr(FWrkl~u!u*_MHo6"bC.4L=EB1z\6k~;dJ/>r }tChkb<԰_[$5I`ɶX7j ]9oylG|&);z?#av /Y%sds0n68220t%lcz:e?a|썄&0d4I+7CVKސEn6E9y{]~|M晅:Dȸ_#svaA-ۨd;dA1YZ>M0и"woF˜f3U# aHEIB`ӟ4jcX%AfLd9K;3K2򠭕8N5̤]嘔_x[uf"w^<Ջ}Օ)J x$*IGH ?1 rL/OhR 9:@@bˮǏa=$O] nhcȓ*fkh'|6{pa)s%^qFO>D)"2e~ߛ^{kP~Vod;A-h av+ X%B0yKm2ҳcՊDqm(M`FA@0^2,]+K4O_&lƶ,LpZ;Xivbb5{˔NLWRKSN.]$R._&rGji?ARTe;ٻiRt=!x\WR]]1f(lp>6:(0UWҭ6chSuHVt^q&;rH͎4Em-S_{6h,4;:}S@"a泙CN>?[w# a~ m2o,I p}0[KxaeU9}WxgOy3PYskH-;+E!Z)Ƃ]"o(,r'O eOEȝ1 Sxn(:,M q`II]fL_Vk5BGwܥg+g`0)*,߰$Swz̒g`;%/a&Cq5^|ldae? #g/`yCeFKLcyrb+cEx00[-H. Z&i&J.2ƾm|- guyO'Vl=m!^dd܏(حe۾|yʫQp%?ҫmǂ:/Y|.2^~"nR=!KvM%8a SF`'Er䯛MsaF:c{0O\hԍY+T¤;t\ZL!#9E$@0y}ޫ76+'^LeNckfyaaL33pEpS@y&QXtܙ|g9S(?%в Qr9zjM,^J}Kg(FCw^]U߳)9{=Z0/q};uJKGtQ\K.x -+w%f? y0 {䡞Cc^*¼6ggCɒyb:oy ,qפ"=/L5̴) ]onYۆ#h7ɵɞ]=wV#anwzVK dCׁ2*Ip-Der$,q$ˁժR2U1)i2E2fF͒i%lZX!y\)9#V'kTjBM[*m5;>=5~| Ͻ3:IpK*NͅՇ^d~fĔa=IמF_M^Gllkچkx>rδNQFd=PѶOl8x0CAC߉SWx Pս[I [~g̸ ׎%㵇R @K37*F" 9X @v!ʧNBlS'555ZlDbb"v$,  p })))J*,Y.))QͬͶ-FK u\NYDoZWdmwI)ZVVbI$X꼒EVPobAN%Bt~w2t%-l‘ղ9au*]UQҲrԐT6c\GI䚾)0Pi̸*ˌ* wmH8ֹWB# 1A@ BFJ'ǎCFFU'|K,vuΙ[JҼLL__6tFh?`?q*If -lGތ ,MZbوoZ#kqιb_*C yFWН.qY8XLH&2]"2cBM¬ʷ `Fg0*AyX2"m(bNrFjpfrFq0"$1v8jI"Nj,}̊YL2i#3ضrd:+IShZdM6>i9X:.ģMfmO,݄#-~ҚeǾE5RY{f X5%( pS#<;jAwMu 5;{V `U텻+ÊDLy|.ηz'̹D1aN'¼ٶcGLUsˬ\~xzܚJ݂@"<Ä刊E86dvb+KĘUYUkWSʣq=KSTDvDMj; ks[1yҳ'wǥC[joja\|mon1V*VuRa8+oʝbyov NO 0@C ЅޣJ;qj`@'16 $QULt6AY'άg5ĸh5Dy/&GHr>QI·j[N-IA/3L +RE'3$t}UwJ̶˜$adÙUA`3E(U;W=َMs2`ߴx<҂4fڤ$}%l8aM62g2g_w3Jسzy W$I 0PnA@̌@ "*^ZY% :as*<}-o{t@sq9\'ͼ`b촴48B"]/_:K_r"Ja4h@Op(yN蜊8I&ӐJ0,F! )2/ŻAVF6]/G)m*=bA|ol0Ja%'`G8jTGCm@VlLZ YƯĦǿ ^θ|1gKFz1ٹSToWɳ `g4lCL\"L#2IvìDȤ}MqAQcG1X ə 3UvII[jDskX4c F9a;L[ =Ex!3 kuf/ќ IMbMy{^X(&tʑGUЅ87M[z[z0O GeB}GCA@L@ e#l\QV.?w_ kM8HtAye:G:> SH .5kmr`'No߾A\zd59ZE#6TK6|JڛXGJZ] }xbTlvɽL%e?Ūu'-E6]T;d\]KɁ/zO. 9s.ra΢:̹9xyv"ĬNF, Z1%kl7@̅xgT\ [_řwB@$ita¼'$*i0aIR$r\q<_?Jd)4?2ifV̕K1沌+n|\v |l;#&م:*ڱYsT``zLl/A?qH_}1jV|*7SS:K9̏&Q!af.ŁuAmX9cU0;I3FQɮ%EAt!w>|e,$W6ΨDDSI^BYe':&&+^?_?3?hoE*mHEݒVc$ 11@]Ż06sKM+k:vsFLVdNf="}vm{je݃)CÑ-t* fWҧdzW. ,$;6ۣA۫nꏛn<~&_VRA ttQ}W0I2eg^̂iQcS8.Kz/3d3amDΎs>WZi | 7a"::zM,9읁=όSx8ڬȢ]/F\nƒP>}\QܳP a;)) ]M#̶8skv"YCTYOd -J"Lg$/Wan␚ z|=|0 p}ejXp a?ỹ@ e[1)XFi@-$5c(Jdbl&LYg&O=4M7ɯ<\ӯ]Dlg)b뽱I͑2>L}2ӱ&mn\ҎԜB6ۏX藍{+Iinp`k#j ^h$AAW'_|/|k%F"ĘiabC]y4o^u[& @箷իCa /u eܡ7xm['b۱B"'J]=fGSEyI$\*nEQX"F(ځ9ZlBH!6eiصqML˜ރy.=wN /\R9vmda.rlEVOUI=ϥN $}8V㲌u"l?- 'ODV>>4JvxIA@ BF5yaJ\"v$]NE%ڇW+$3=8sK5Vb1A9Eq$-9Lo}= &̴ zԣI]E lF)fؗk' ݊؇R 5ym=p:0{HOA;؂ʍFPs <Ä/ҵ"qeE#>^"TÉ蒠X(J{0+by27Vg5ӕԔ-4.S a6nԲIt~=լQ|#Ynb3p7} 4Qd6Yp_<vi%{&uo)I25ޜ+6̍!$邀 -@ qy/~_4 U<"aX#OVl\{?{*im;*!? Ю];&a^La֝\=$l[Wq4fOYwnl$ԼReF=XOl@0a؂ʍ&dB@&Of&Z&{eVgȘ5é1T\ճYƢer>.϶Ѭ͞ϟ' L5F9v![;Zț3 \D|~_d_|h0Fߍ7 anIA@h1]G"2#l uL* ]KGy~=7:-\ul D anIA@0'.d a4u#/E "q=g&$ns)/eAz{;n{o7l<~5Gl#.h'kZQ5OFl<>gc=^e5dC/0{* j:0a^A!썍ʉ,UD|LS"Ȝ"); }5 3aùȴ ڟ e9ks" 3TJ(%>GA9kRnvt2imHxcWմ,[9|Ф 窺`=w"%L^[V^d/d{˃ `zg g0ߪDµl{K-5ff Z"E Ls^di40gnL+4Z7 ݽ0S%Ie悆n:;LC;OsFiCe1P&g<)0{GZCҠQ4{Ce&*EL  @ 1nKk{P gl"aQJM-pi^,qՈeΘUHOaBlթfB0SLg+G/ߵH ߽NҤ#G6n6mnV{H-{Oި}}uk̞[VUO:y߾5nIA%-Y$_M@"F>$p$%Dvs`ujV&Lx( 4m g̤KYձX<ţ{Gɩ֎G0u 7m=Wφ1f s09(2d۪*$>R[Qͅc~ί1HiZ6X;\ss \:7z,.yԏ), T]#̜VCgy\,V{4u6 J#ѥC-*HMFN6$Uoڵ+y*U2zum)jqظ{G~Ivr93 EȣEw{yXt2̾ (ɯ4-d>ǖm.* {< JyjCbaD`JݬݴFU˷ ʶ;;?ݤ:f{>-Œ/k cX=| cXe?&mϽ&g7 /[1yjajXԹz$A@QgyqWIu11M/DXUwWreؕĊyF[-p>cRo˪+X|q,n 3Přj(;w?4'>ߤCƺjیIDAT: 7b,U,\--S=.twI OIR;z2VqO^QBA@B Ѕޟ3ʄ<'WzYRSh !1Y,oߞvzum)Ui ?8l(GJ$Rw]x4РÆRRERRS[?ဝ> kN>,҂ xt㕏 !+bb%O+aRMS]u\=MR~ SV1J(m]iǵEx m vtDvH핎6alA.  `F]Gbz,m.//fCeeJA||:>ʾj O>AmSA@3ULtIVdp9h.cޜeKDJ7 true mojohaus/jaxb2-maven-plugin right gray jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/000077500000000000000000000000001351100213400222645ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/000077500000000000000000000000001351100213400232055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/000077500000000000000000000000001351100213400237745ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/000077500000000000000000000000001351100213400255675ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/000077500000000000000000000000001351100213400265335ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/000077500000000000000000000000001351100213400275415ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/BufferingLog.java000066400000000000000000000130541351100213400327600ustar00rootroot00000000000000package org.codehaus.mojo.jaxb2; import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.jaxb2.shared.Validate; import java.text.NumberFormat; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; /** * Trivial Maven Log implementation which stores all logged messages * within a SortedMap for later retrieval. * * @author Lennart Jörelid, jGuru Europe AB */ public class BufferingLog implements Log { public enum LogLevel { DEBUG, INFO, WARN, ERROR, NONE } // Internal state private static final NumberFormat INTEGER_FORMAT = NumberFormat.getIntegerInstance(); private LogLevel minLevel; private final Object lock = new Object(); private SortedMap logBuffer; static { setMinimumIntegerDigits(3); } public BufferingLog() { this(LogLevel.INFO); } public BufferingLog(final LogLevel minLevel) { // Check sanity Validate.notNull(minLevel, "minLevel"); // Assign internal state logBuffer = new TreeMap(); this.minLevel = minLevel; } /** * @return The minimum LogLevel for which this BufferingLog will record log events. */ public LogLevel getMinimumLogLevel() { return minLevel; } /** * @return The LogBuffer holding all log messages, and their corresponding (optional) Throwable. */ public SortedMap getLogBuffer() { return logBuffer; } /** * Retrieves the current LogBuffer, and resets the internal state of this BufferingLog. * * @return The LogBuffer holding all log messages, and their corresponding (optional) Throwable. */ public SortedMap getAndResetLogBuffer() { final SortedMap toReturn = logBuffer; synchronized (lock) { this.logBuffer = new TreeMap(); } return toReturn; } /** * Assigns the minimum number of Integer digits in the Log format. * * @param minimumIntegerDigits the minimum number of Integer digits in the Log format. */ public static void setMinimumIntegerDigits(final int minimumIntegerDigits) { INTEGER_FORMAT.setMinimumIntegerDigits(minimumIntegerDigits); } /** * @return A Pretty-printed version of the log buffer. */ public String getPrettyPrintedLog() { final StringBuilder builder = new StringBuilder(); for (Map.Entry current : logBuffer.entrySet()) { builder.append("\n").append(current.getKey()); final Throwable error = current.getValue(); if (error != null) { builder.append(" [" + error.getMessage() + "]: " + error.getClass().getSimpleName()); } } // All done. return builder.toString(); } /** * {@inheritDoc} */ public void debug(CharSequence content, Throwable error) { addLogEntry(LogLevel.DEBUG, content, error); } /** * {@inheritDoc} */ public void debug(CharSequence content) { debug(content, null); } /** * {@inheritDoc} */ public void debug(Throwable error) { debug("", error); } /** * {@inheritDoc} */ public void info(CharSequence content, Throwable error) { addLogEntry(LogLevel.INFO, content, error); } /** * {@inheritDoc} */ public void info(CharSequence content) { info(content, null); } /** * {@inheritDoc} */ public void info(Throwable error) { info("", error); } /** * {@inheritDoc} */ public void warn(CharSequence content, Throwable error) { addLogEntry(LogLevel.WARN, content, error); } /** * {@inheritDoc} */ public void warn(CharSequence content) { warn(content, null); } /** * {@inheritDoc} */ public void warn(Throwable error) { warn("", error); } /** * {@inheritDoc} */ public void error(final CharSequence content, final Throwable error) { addLogEntry(LogLevel.ERROR, content, error); } /** * {@inheritDoc} */ public void error(CharSequence content) { error(content, null); } /** * {@inheritDoc} */ public void error(final Throwable error) { error("", error); } /** * {@inheritDoc} */ public boolean isDebugEnabled() { return isLogEnabledFor(LogLevel.DEBUG); } /** * {@inheritDoc} */ public boolean isInfoEnabled() { return isLogEnabledFor(LogLevel.INFO); } /** * {@inheritDoc} */ public boolean isWarnEnabled() { return isLogEnabledFor(LogLevel.WARN); } /** * {@inheritDoc} */ public boolean isErrorEnabled() { return isLogEnabledFor(LogLevel.ERROR); } // // Private helpers // private void addLogEntry(final LogLevel level, final CharSequence message, final Throwable throwable) { synchronized (lock) { if (isLogEnabledFor(level)) { final int index = logBuffer.size(); final String logMessage = "" + INTEGER_FORMAT.format(index) + ": (" + level + ") " + message; logBuffer.put(logMessage, throwable); } } } private boolean isLogEnabledFor(final LogLevel level) { return level.compareTo(minLevel) >= 0; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/000077500000000000000000000000001351100213400330555ustar00rootroot00000000000000postprocessing/000077500000000000000000000000001351100213400360605ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemagenerationAbstractJavadocExtractorTest.java000066400000000000000000000067341351100213400445240ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocExtractor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SearchableDocumentation; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.junit.Assert; import org.junit.Before; import org.w3c.dom.Document; import se.jguru.shared.algorithms.api.resources.PropertyResources; import java.io.File; import java.io.StringReader; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @author Lennart Jörelid, jGuru Europe AB */ public abstract class AbstractJavadocExtractorTest { // Shared state protected List sourceRootDirectories; protected BufferingLog log; protected JavaDocExtractor extractor; protected List> javaSourceExcludeFilter; @Before public void setupSharedState() { sourceRootDirectories = new ArrayList(); log = new BufferingLog(); extractor = new JavaDocExtractor(log); javaSourceExcludeFilter = new ArrayList>(); javaSourceExcludeFilter.add(new PatternFileFilter(Collections.singletonList("\\.java"), false)); } /** * Adds a source root directory. * * @param resourcePath A non-null resource path. */ protected void addSourceRootDirectory(final String resourcePath) { // Check sanity Validate.notEmpty(resourcePath, "resourcePath"); final String effectiveResourcePath = resourcePath.charAt(0) == '/' ? resourcePath : "/" + resourcePath; final URL resource = Thread.currentThread().getContextClassLoader().getResource(effectiveResourcePath); Assert.assertNotNull("Effective resourcePath [" + resourcePath + "] could not be found.", resource); final File toAdd = new File(resource.getPath()); final boolean exists = toAdd.exists(); final boolean isDirectory = toAdd.isDirectory(); Assert.assertTrue("Resource [" + toAdd.getAbsolutePath() + "] was nonexistent.", exists); Assert.assertTrue("Resource [" + toAdd.getAbsolutePath() + "] was not a directory.", isDirectory); sourceRootDirectories.add(toAdd); } protected SearchableDocumentation processSources() { // First, add all sources to the extractor for (File current : sourceRootDirectories) { final List currentFiles = FileSystemUtilities.filterFiles(current, null, "", log, "JavaSources", javaSourceExcludeFilter); // Add All source files found. extractor.addSourceFiles(currentFiles); } // All Done. return extractor.process(); } protected Document createDocumentFrom(final String resource) { // Check sanity Validate.notEmpty(resource, "resource"); // Read data, and convert into a Document. final String xmlData = PropertyResources.readFully(resource); return XsdGeneratorHelper.parseXmlStream(new StringReader(xmlData)); } } DebugNodeProcessor.java000066400000000000000000000024451351100213400424640ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing; import org.w3c.dom.Node; import java.util.ArrayList; import java.util.List; /** * @author Lennart Jörelid */ public class DebugNodeProcessor implements NodeProcessor { // Internal state private NodeProcessor delegate; private List acceptedNodes = new ArrayList(); /** * Creates a new DebugNodeProcessor, delegating all calls to the provided NodeProcessor. * * @param delegate The NodeProcessor to which all calls to this NodeProcessor * will be delegated. */ public DebugNodeProcessor(NodeProcessor delegate) { this.delegate = delegate; } /** * {@inheritDoc} */ public boolean accept(Node aNode) { final boolean accepted = delegate.accept(aNode); if (accepted) { acceptedNodes.add(aNode); } return accepted; } /** * {@inheritDoc} */ public void process(Node aNode) { delegate.process(aNode); } /** * @return The ordered List of Nodes accepted by the delegate NodeProcessor. */ public List getAcceptedNodes() { return acceptedNodes; } }XsdGeneratorHelperTest.java000066400000000000000000000456671351100213400433520ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing; import org.apache.maven.plugin.MojoExecutionException; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.AbstractSourceCodeAwareNodeProcessingTest; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocExtractor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.NoAuthorJavaDocRenderer; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SearchableDocumentation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdAnnotationProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdEnumerationAnnotationProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.ChangeNamespacePrefixProcessor; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.TransformSchema; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier; import org.custommonkey.xmlunit.XMLAssert; import org.custommonkey.xmlunit.XMLUnit; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.w3c.dom.Document; import se.jguru.shared.algorithms.api.resources.PropertyResources; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerFactory; import java.io.File; import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import java.security.CodeSource; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; /** * @author Lennart Jörelid */ public class XsdGeneratorHelperTest { private static TransformerFactory factory; @BeforeClass public static void setupSharedState() { // Configure XMLUnit. XMLUnit.setIgnoreWhitespace( true ); XMLUnit.setIgnoreAttributeOrder( true ); // Configure the TransformerFactory try { factory = TransformerFactory.newInstance(); final CodeSource codeSource = factory.getClass().getProtectionDomain().getCodeSource(); System.out.println( "-- Found TransformerFactory of type [" + factory.getClass().getName() + "] loaded from [" + codeSource.getLocation().toString() + "]" ); } catch ( Exception ex ) { ex.printStackTrace(); } } @Test( expected = MojoExecutionException.class ) public void validateExceptionThrownOnDuplicateURIs() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo" ); final TransformSchema transformSchema2 = new TransformSchema( "foo", "bar", "bar" ); final List transformSchemas = new ArrayList(); transformSchemas.add( transformSchema1 ); transformSchemas.add( transformSchema2 ); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas ); Assert.fail( "Two schemas with same URIs should yield a MojoExecutionException." ); } @Test( expected = MojoExecutionException.class ) public void validateExceptionThrownOnDuplicatePrefixes() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo" ); final TransformSchema transformSchema2 = new TransformSchema( "bar", "foo", "bar" ); final List transformSchemas = new ArrayList(); transformSchemas.add( transformSchema1 ); transformSchemas.add( transformSchema2 ); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas ); Assert.fail( "Two schemas with same Prefixes should yield a MojoExecutionException." ); } @Test public void validateNoExceptionThrownOnDuplicateNullPrefixes() { // Assemble final TransformSchema transformSchema1 = new TransformSchema( "foo", null, "foo" ); final TransformSchema transformSchema2 = new TransformSchema( "bar", null, "bar" ); final List transformSchemas = new ArrayList(); transformSchemas.add( transformSchema1 ); transformSchemas.add( transformSchema2 ); // Act & Assert try { XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas ); } catch ( MojoExecutionException e ) { Assert.fail( "Two schemas with null Prefix should not yield a MojoExecutionException." ); } } @Test public void validateExceptionThrownOnDuplicateFiles() { // Assemble final TransformSchema transformSchema1 = new TransformSchema( "foo", "foo", "foo.xsd" ); final TransformSchema transformSchema2 = new TransformSchema( "bar", "bar", "foo.xsd" ); final List transformSchemas = new ArrayList(); transformSchemas.add( transformSchema1 ); transformSchemas.add( transformSchema2 ); // Act & Assert try { XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas ); Assert.fail( "Two schemas with same Files should yield a MojoExecutionException." ); } catch ( MojoExecutionException e ) { // Validate the error message. String expectedMessage = "Misconfiguration detected: Duplicate 'file' property with value [foo.xsd] " + "found in plugin configuration. Correct schema elements index (0) and (1), " + "to ensure that all 'file' values are unique."; Assert.assertEquals( expectedMessage, e.getLocalizedMessage() ); } } @Test( expected = MojoExecutionException.class ) public void validateExceptionThrownOnOnlyUriGiven() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema( "foo", null, "" ); final List transformSchemas = new ArrayList(); transformSchemas.add( transformSchema1 ); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas ); Assert.fail( "A schema definition with no prefix or file should yield a MojoExecutionException." ); } @Test( expected = MojoExecutionException.class ) public void validateExceptionThrownOnNullUri() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema( null, "foo", "bar" ); final List transformSchemas = new ArrayList(); transformSchemas.add( transformSchema1 ); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas ); Assert.fail( "A schema definition with null URI should yield a MojoExecutionException." ); } @Test( expected = MojoExecutionException.class ) public void validateExceptionThrownOnEmptyUri() throws MojoExecutionException { // Assemble final TransformSchema transformSchema1 = new TransformSchema( "", "foo", "bar" ); final List transformSchemas = new ArrayList(); transformSchemas.add( transformSchema1 ); // Act & Assert XsdGeneratorHelper.validateSchemasInPluginConfiguration( transformSchemas ); Assert.fail( "A schema definition with empty URI should yield a MojoExecutionException." ); } @Test public void validateProcessingNodes() { // Assemble final String newPrefix = "changedFoo"; final String oldPrefix = "foo"; final String originalXml = getXmlDocumentSample( oldPrefix ); final String changedXml = getXmlDocumentSample( newPrefix ); final NodeProcessor changeNamespacePrefixProcessor = new ChangeNamespacePrefixProcessor( oldPrefix, newPrefix ); // Act final Document processedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( originalXml ) ); XsdGeneratorHelper.process( processedDocument.getFirstChild(), true, changeNamespacePrefixProcessor ); // Assert final Document expectedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( changedXml ) ); final Diff diff = new Diff( expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier() ); diff.overrideElementQualifier( new ElementNameAndAttributeQualifier() ); XMLAssert.assertXMLEqual( processedDocument, expectedDocument ); } @Test public void validateProcessingXSDsWithEnumerations() throws Exception { // Assemble final BufferingLog log = new BufferingLog(); final JavaDocExtractor extractor = new JavaDocExtractor( log ); extractor.setEncoding( "UTF-8" ); final String parentPath = "testdata/schemageneration/javadoc/enums/"; final URL parentPathURL = getClass().getClassLoader().getResource( parentPath ); Assert.assertNotNull( parentPathURL ); final File parentDir = new File( parentPathURL.getPath() ); Assert.assertTrue( parentDir.exists() && parentDir.isDirectory() ); final List> excludeFilesMatching = new ArrayList>(); excludeFilesMatching.add( new PatternFileFilter( Collections.singletonList( "\\.xsd" ) ) ); Filters.initialize( log, excludeFilesMatching ); final List allSourceFiles = FileSystemUtilities.filterFiles( parentDir, null, parentDir.getAbsolutePath(), log, "allJavaFiles", excludeFilesMatching ); Assert.assertEquals( 3, allSourceFiles.size() ); final List urls = new ArrayList(); for ( File current : allSourceFiles ) { try { urls.add( current.toURI().toURL() ); } catch ( MalformedURLException e ) { throw new IllegalArgumentException( "Could not convert file [" + current.getAbsolutePath() + "] to a URL", e ); } } Assert.assertEquals( 3, urls.size() ); extractor.addSourceURLs( urls ); final SearchableDocumentation docs = extractor.process(); // #1) The raw / un-processed XSD (containing the 'before' state) // #2) The processed XSD (containing the 'expected' state) final String rawEnumSchema = PropertyResources.readFully( parentPath + "rawEnumSchema.xsd" ); final String processedEnumSchema = PropertyResources.readFully( parentPath + "processedEnumSchema.xsd" ); final NodeProcessor enumProcessor = new XsdEnumerationAnnotationProcessor( docs, new NoAuthorJavaDocRenderer() ); // Act final Document processedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( rawEnumSchema ) ); XsdGeneratorHelper.process( processedDocument.getFirstChild(), true, enumProcessor ); // System.out.println("Got: " + AbstractSourceCodeAwareNodeProcessingTest.printDocument(processedDocument)); // Assert final Document expectedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( processedEnumSchema ) ); final Diff diff = new Diff( expectedDocument, processedDocument, null, new ElementNameAndAttributeQualifier() ); diff.overrideElementQualifier( new ElementNameAndAttributeQualifier() ); XMLAssert.assertXMLEqual( processedDocument, expectedDocument ); } @Test public void validateXmlDocumentationForWrappers() throws Exception { // Assemble final BufferingLog log = new BufferingLog(); final JavaDocExtractor extractor = new JavaDocExtractor( log ); extractor.setEncoding( "UTF-8" ); final String parentPath = "testdata/schemageneration/javadoc/xmlwrappers/"; final URL parentPathURL = getClass().getClassLoader().getResource( parentPath ); Assert.assertNotNull( parentPathURL ); final String schemaGenCreatedSchema = PropertyResources.readFully( parentPath + "expectedRawXmlWrappers.xsd" ); final File parentDir = new File( parentPathURL.getPath() ); Assert.assertTrue( parentDir.exists() && parentDir.isDirectory() ); final List> excludeFilesMatching = new ArrayList>(); excludeFilesMatching.add( new PatternFileFilter( Collections.singletonList( "\\.xsd" ) ) ); Filters.initialize( log, excludeFilesMatching ); final List allSourceFiles = FileSystemUtilities.filterFiles( parentDir, null, parentDir.getAbsolutePath(), log, "allJavaFiles", excludeFilesMatching ); Assert.assertEquals( 2, allSourceFiles.size() ); final List urls = new ArrayList(); for ( File current : allSourceFiles ) { try { urls.add( current.toURI().toURL() ); } catch ( MalformedURLException e ) { throw new IllegalArgumentException( "Could not convert file [" + current.getAbsolutePath() + "] to a URL", e ); } } Assert.assertEquals( 2, urls.size() ); // Act extractor.addSourceURLs( urls ); final SearchableDocumentation docs = extractor.process(); final XsdAnnotationProcessor processor = new XsdAnnotationProcessor( docs, new NoAuthorJavaDocRenderer() ); final Document schemaGenCreatedDocument = XsdGeneratorHelper.parseXmlStream( new StringReader( schemaGenCreatedSchema ) ); XsdGeneratorHelper.process( schemaGenCreatedDocument.getFirstChild(), true, processor ); System.out.println( "Got: " + AbstractSourceCodeAwareNodeProcessingTest.printDocument( schemaGenCreatedDocument ) ); // Assert } @Test public void validateAcquiringFilenameToResolverMap() throws MojoExecutionException { // Assemble final String[] expectedFilenames = {"schema1.xsd", "schema2.xsd", "schema3.xsd"}; final URL tmpUrl = getClass().getClassLoader().getResource( "generated/schema/schema1.xsd" ); final File directory = new File( tmpUrl.getFile() ).getParentFile(); // Act final Map fileNameToResolverMap = XsdGeneratorHelper.getFileNameToResolverMap( directory ); // Assert Assert.assertEquals( 3, fileNameToResolverMap.size() ); for ( String current : expectedFilenames ) { Assert.assertTrue( fileNameToResolverMap.keySet().contains( current ) ); } SimpleNamespaceResolver schema1Resolver = fileNameToResolverMap.get( "schema1.xsd" ); Assert.assertEquals( "http://yet/another/namespace", schema1Resolver.getLocalNamespaceURI() ); Assert.assertEquals( "schema1.xsd", schema1Resolver.getSourceFilename() ); final Map schema1NamespaceURI2PrefixMap = schema1Resolver.getNamespaceURI2PrefixMap(); Assert.assertEquals( 1, schema1NamespaceURI2PrefixMap.size() ); Assert.assertEquals( "xs", schema1NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) ); SimpleNamespaceResolver schema2Resolver = fileNameToResolverMap.get( "schema2.xsd" ); Assert.assertEquals( "http://some/namespace", schema2Resolver.getLocalNamespaceURI() ); Assert.assertEquals( "schema2.xsd", schema2Resolver.getSourceFilename() ); final Map schema2NamespaceURI2PrefixMap = schema2Resolver.getNamespaceURI2PrefixMap(); Assert.assertEquals( 2, schema2NamespaceURI2PrefixMap.size() ); Assert.assertEquals( "ns1", schema2NamespaceURI2PrefixMap.get( "http://another/namespace" ) ); Assert.assertEquals( "xs", schema2NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) ); SimpleNamespaceResolver schema3Resolver = fileNameToResolverMap.get( "schema3.xsd" ); Assert.assertEquals( "http://another/namespace", schema3Resolver.getLocalNamespaceURI() ); Assert.assertEquals( "schema3.xsd", schema3Resolver.getSourceFilename() ); final Map schema3NamespaceURI2PrefixMap = schema3Resolver.getNamespaceURI2PrefixMap(); Assert.assertEquals( 3, schema3NamespaceURI2PrefixMap.size() ); Assert.assertEquals( "ns2", schema3NamespaceURI2PrefixMap.get( "http://yet/another/namespace" ) ); Assert.assertEquals( "ns1", schema3NamespaceURI2PrefixMap.get( "http://some/namespace" ) ); Assert.assertEquals( "xs", schema3NamespaceURI2PrefixMap.get( "http://www.w3.org/2001/XMLSchema" ) ); } // // Private helpers // private static DocumentBuilderFactory getDocumentBuilderFactory() { final DocumentBuilderFactory toReturn = DocumentBuilderFactory.newInstance(); toReturn.setNamespaceAware( true ); return toReturn; } private static DocumentBuilder getDocumentBuilder() { try { return getDocumentBuilderFactory().newDocumentBuilder(); } catch ( ParserConfigurationException e ) { throw new IllegalStateException( "Could not create DocumentBuilder", e ); } } private static Document createEmptyDocument( final DocumentBuilder builder ) { return builder.newDocument(); } private String getXmlDocumentSample( final String namespace ) { return "\n" + "\n" + " \n" + " <" + namespace + ":aBar name=\"aFooElement\" />\n" + "\n"; } }javadoc/000077500000000000000000000000001351100213400374675ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingAbstractSourceCodeAwareNodeProcessingTest.java000066400000000000000000000356101351100213400505410ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.NodeProcessor; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.Validate; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.XMLUnit; import org.junit.Assert; import org.junit.Before; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.xml.bind.JAXBContext; import javax.xml.bind.SchemaOutputResolver; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public abstract class AbstractSourceCodeAwareNodeProcessingTest { /** * Default systemId for the empty namespace. */ public static final String DEFAULT_EMPTY_NAMESPACE_SYSTEM_ID = "emptyNamespaceSystemId.xsd"; // Shared state protected BufferingLog log; protected SearchableDocumentation docs; protected SortedMap namespace2GeneratedSchemaMap; protected SortedMap namespace2DocumentMap; protected Map namespace2SystemIdMap; protected List xsdGenerationWarnings; protected final File basedir; protected final File testJavaDir; protected JAXBContext jaxbContext; protected SortedMap xsdGenerationLog; // Internal state private List> jaxbClasses; public AbstractSourceCodeAwareNodeProcessingTest() { // Setup the basic directories. basedir = getBasedir(); testJavaDir = new File(basedir, "src/test/java"); Assert.assertTrue(testJavaDir.exists() && testJavaDir.isDirectory()); } @Before public final void setupSharedState() throws Exception { log = new BufferingLog(BufferingLog.LogLevel.DEBUG); // Create internal state for the generated structures. namespace2SystemIdMap = new TreeMap(); xsdGenerationWarnings = new ArrayList(); namespace2DocumentMap = new TreeMap(); namespace2GeneratedSchemaMap = new TreeMap(); // Pre-populate the namespace2SystemIdMap namespace2SystemIdMap.put(SomewhatNamedPerson.NAMESPACE, "somewhatNamedPerson.xsd"); namespace2SystemIdMap.put("http://jaxb.mojohaus.org/wrappers", "wrapperExample.xsd"); namespace2SystemIdMap.put("http://gnat.west.se/foods", "anotherExample.xsd"); namespace2SystemIdMap.put("", DEFAULT_EMPTY_NAMESPACE_SYSTEM_ID); // Create the JAXBContext jaxbClasses = getJaxbAnnotatedClassesForJaxbContext(); Assert.assertNotNull("getJaxbAnnotatedClassesForJaxbContext() should not return a null List.", jaxbClasses); final Class[] classArray = jaxbClasses.toArray(new Class[jaxbClasses.size()]); jaxbContext = JAXBContext.newInstance(classArray); // Generate the vanilla XSD from JAXB final SortedMap tmpSchemaMap = new TreeMap(); try { jaxbContext.generateSchema(new SchemaOutputResolver() { @Override public Result createOutput(final String namespaceUri, final String suggestedFileName) throws IOException { // As put in the XmlBinding JAXB implementation of Nazgul Core: // // "The types should really be annotated with @XmlType(namespace = "... something ...") // to avoid using the default ("") namespace". if (namespaceUri.isEmpty()) { xsdGenerationWarnings.add("Got empty namespaceUri for suggestedFileName [" + suggestedFileName + "]."); } // Create the result Writer final StringWriter out = new StringWriter(); final StreamResult toReturn = new StreamResult(out); // The systemId *must* be non-null, even in this case where we // do not write the XSD to a file. final String effectiveSystemId = namespace2SystemIdMap.get(namespaceUri) == null ? suggestedFileName : namespace2SystemIdMap.get(namespaceUri); toReturn.setSystemId(effectiveSystemId); // Map the namespaceUri to the schemaResult. tmpSchemaMap.put(namespaceUri, out); // All done. return toReturn; } }); } catch (IOException e) { throw new IllegalArgumentException("Could not acquire Schema snippets.", e); } // Store all generated XSDs for (Map.Entry current : tmpSchemaMap.entrySet()) { namespace2GeneratedSchemaMap.put(current.getKey(), current.getValue().toString()); } // Create XML Documents for all generated Schemas for (Map.Entry current : namespace2GeneratedSchemaMap.entrySet()) { final Document document = createDocument(current.getValue()); namespace2DocumentMap.put(current.getKey(), document); } // Create the SearchableDocumentation final JavaDocExtractor extractor = new JavaDocExtractor(log); extractor.addSourceFiles(resolveSourceFiles()); docs = extractor.process(); // Stash and clear the log buffer. xsdGenerationLog = log.getAndResetLogBuffer(); } /** * @return A List containing all classes which should be part of the JAXBContext. */ protected abstract List> getJaxbAnnotatedClassesForJaxbContext(); /** * @return The basedir directory, corresponding to the root of this project. */ protected File getBasedir() { // Use the system property if available. String basedirPath = System.getProperty("basedir"); if (basedirPath == null) { basedirPath = new File("").getAbsolutePath(); } final File toReturn = new File(basedirPath); Assert.assertNotNull("Could not find 'basedir'. Please set the system property 'basedir'.", toReturn); Assert.assertTrue("'basedir' must be an existing directory. ", toReturn.exists() && toReturn.isDirectory()); // All done. return toReturn; } /** * Creates a DOM Document from the supplied XML. * * @param xmlContent The non-empty XML which should be converted into a Document. * @return The Document created from the supplied XML Content. */ protected final Document createDocument(final String xmlContent) { // Check sanity Validate.notEmpty(xmlContent, "xmlContent"); // Build a DOM model of the provided xmlFileStream. final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); try { return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xmlContent))); } catch (Exception e) { throw new IllegalArgumentException("Could not create DOM Document", e); } } /** * Drives the supplied visitor to process the provided Node and all its children, should the recurseToChildren flag * be set to true. All attributes of the current node are processed before recursing to children (i.e. * breadth first recursion). * * @param node The Node to process. * @param recurseToChildren if true, processes all children of the supplied node recursively. * @param visitor The NodeProcessor instance which should process the nodes. */ public final void process(final Node node, final boolean recurseToChildren, final NodeProcessor visitor) { // Process the current Node, if the NodeProcessor accepts it. if (visitor.accept(node)) { onAcceptedNode(node); visitor.process(node); } NamedNodeMap attributes = node.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node attribute = attributes.item(i); // Process the current attribute, if the NodeProcessor accepts it. if (visitor.accept(attribute)) { onAcceptedAttribute(attribute); visitor.process(attribute); } } if (recurseToChildren) { NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); // Recurse to Element children. if (child.getNodeType() == Node.ELEMENT_NODE) { process(child, true, visitor); } } } } /** * Event callback when a nodeProcessor has accepted a Node. * * @param aNode the accepted Node */ protected void onAcceptedNode(final Node aNode) { // name="firstName" final Node nameAttribute = aNode.getAttributes().getNamedItem("name"); if(nameAttribute != null) { final String nodeName = nameAttribute.getNodeValue(); log.info("Accepted node [" + aNode.getNodeName() + "] " + nodeName); } } /** * Event callback when a nodeProcessor has accepted an Attribute. * * @param anAttribute the accepted attribute. */ protected void onAcceptedAttribute(final Node anAttribute) { log.info("Accepted attribute [" + anAttribute.getNodeName() + "]"); } // // Private helpers // /** * Utility method to read all (string formatted) data from the given classpath-relative * file and return the data as a string. * * @param path The classpath-relative file path. * @return The content of the supplied file. */ protected static String readFully(final String path) { final StringBuilder toReturn = new StringBuilder(50); try { // Will produce a NPE if the path was not directed to a file. final InputStream resource = AbstractSourceCodeAwareNodeProcessingTest .class .getClassLoader() .getResourceAsStream(path); final BufferedReader tmp = new BufferedReader(new InputStreamReader(resource)); for (String line = tmp.readLine(); line != null; line = tmp.readLine()) { toReturn.append(line).append(AbstractJaxbMojo.NEWLINE); } } catch (final Exception e) { throw new IllegalArgumentException("Resource [" + path + "] not readable."); } // All done. return toReturn.toString(); } /** * Compares XML documents provided by the two Readers. * * @param expected The expected document data. * @param actual The actual document data. * @return A DetailedDiff object, describing all differences in documents supplied. * @throws org.xml.sax.SAXException If a SAXException was raised during parsing of the two Documents. * @throws IOException If an I/O-related exception was raised while acquiring the data from the Readers. */ protected static Diff compareXmlIgnoringWhitespace(final String expected, final String actual) throws SAXException, IOException { // Check sanity Validate.notNull(expected, "Cannot handle null expected argument."); Validate.notNull(actual, "Cannot handle null actual argument."); // Ignore whitespace - and also normalize the Documents. XMLUnit.setNormalize(true); XMLUnit.setIgnoreWhitespace(true); XMLUnit.setNormalize(true); // Compare and return return XMLUnit.compareXML(expected, actual); } private List resolveSourceFiles() { final List sourceDirs = Arrays.asList(new File(basedir, "src/main/java"), testJavaDir); final List candidates = FileSystemUtilities.resolveRecursively(sourceDirs, null, log); final List toReturn = new ArrayList(); for (File current : candidates) { for (Class currentClass : jaxbClasses) { final String expectedFileName = currentClass.getSimpleName() + ".java"; if (expectedFileName.equalsIgnoreCase(current.getName())) { final String transmutedCanonicalPath = FileSystemUtilities.getCanonicalPath(current) .replace("/", ".") .replace(File.separator, "."); if (transmutedCanonicalPath.contains(currentClass.getPackage().getName())) { toReturn.add(current); } } } } // All done. return toReturn; } /** * Prints the content of the supplied DOM Document as a string. * * @param doc A non-null DOM Document. * @return A String holding the pretty-printed version of the supplied doc. */ public static String printDocument(final Document doc) { try { // Create the Unity-Transformer final TransformerFactory tf = TransformerFactory.newInstance(); final Transformer transformer = tf.newTransformer(); // Make it pretty print stuff. transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); // Harvest the result, and return. final StringWriter out = new StringWriter(); transformer.transform(new DOMSource(doc), new StreamResult(out)); return out.toString(); } catch (Exception e) { throw new IllegalArgumentException("Could not print document", e); } } } DomHelperTest.java000066400000000000000000000062121351100213400430520ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper; import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import se.jguru.shared.algorithms.api.resources.PropertyResources; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public class DomHelperTest { @Test public void validateDomHelperAccessors() throws Exception { // Assemble final String xsd = PropertyResources.readFully("testdata/schemageneration/javadoc/enums/rawEnumSchema.xsd"); final Document document = XsdGeneratorHelper.parseXmlStream(new StringReader(xsd)); final Element schemaElement = document.getDocumentElement(); final Element simpleTypeElement = getChildOf(schemaElement, "simpleType", "foodPreference"); final Element restrictionElement = getChildOf(simpleTypeElement, "restriction", null); // Act final List enumElements = new ArrayList(); final NodeList childNodes = restrictionElement.getChildNodes(); for(int i = 0; i < childNodes.getLength(); i++) { final Node current = childNodes.item(i); if(current.getNodeType() == Node.ELEMENT_NODE && current.getLocalName().equals("enumeration")) { enumElements.add((Element) current); } } final Map xpath2ValueMap = new TreeMap(); for(Element current : enumElements) { final String currentXPath = DomHelper.getXPathFor(current); xpath2ValueMap.put(currentXPath, DomHelper.getValueAttribute(current)); } // Assert Assert.assertNotNull(xpath2ValueMap); Assert.assertEquals(3, xpath2ValueMap.size()); final String prefix ="#document/xs:schema/xs:simpleType[@name='foodPreference']/" + "xs:restriction/xs:enumeration[@value='"; Assert.assertEquals("LACTO_VEGETARIAN", xpath2ValueMap.get(prefix + "LACTO_VEGETARIAN']")); Assert.assertEquals("NONE", xpath2ValueMap.get(prefix + "NONE']")); Assert.assertEquals("VEGAN", xpath2ValueMap.get(prefix + "VEGAN']")); } // // private helpers // private Element getChildOf(final Element parent, final String localName, final String name) { final NodeList children = parent.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node current = children.item(i); if (current.getNodeType() == Node.ELEMENT_NODE) { final String currentLocalName = current.getLocalName(); final String nameAttribute = DomHelper.getNameAttribute(current); if(currentLocalName.equals(localName) && (name == null || name.equals(nameAttribute))) { return (Element) current; } } } return null; } } FieldLocationTest.java000066400000000000000000000062121351100213400437070ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.FieldLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.XmlNameAnnotatedClassWithFieldAccess; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; import java.lang.reflect.Field; import java.util.Map; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public class FieldLocationTest { private Class theClass; private Map fieldName2MethodMap; @Before public void setupSharedState() { fieldName2MethodMap = new TreeMap(); theClass = XmlNameAnnotatedClassWithFieldAccess.class; for(Field current : theClass.getDeclaredFields()) { final String currentName = current.getName(); fieldName2MethodMap.put(currentName, current); } } @Test public void validateFieldLocationWithXmlName() throws Exception { // Assemble final String packageName = theClass.getPackage().getName(); final String classXmlName = theClass.getAnnotation(XmlType.class).name(); // @XmlType(name = "AnnotatedXmlNameAnnotatedClassWithFieldAccessTypeName") final Field integerField = fieldName2MethodMap.get("integerField"); final Field stringField = fieldName2MethodMap.get("stringField"); final String integerFieldXmlName = integerField.getAnnotation(XmlAttribute.class).name(); final String stringFieldXmlName = stringField.getAnnotation(XmlElement.class).name(); final String expectedIntegerFieldPath = packageName + "." + classXmlName + "#" + integerFieldXmlName; final String expectedStringFieldPath = packageName + "." + classXmlName + "#" + stringFieldXmlName; final String expectedIntegerFieldToString = packageName + "." + classXmlName + " (from: " + theClass.getSimpleName() + ")#" + integerFieldXmlName + " (from: " + integerField.getName() + ")"; // Act final FieldLocation integerFieldLocation = new FieldLocation( packageName, theClass.getSimpleName(), classXmlName, integerField.getName(), integerFieldXmlName); final FieldLocation stringFieldLocation = new FieldLocation( packageName, theClass.getSimpleName(), classXmlName, stringField.getName(), stringFieldXmlName); // Assert Assert.assertEquals(expectedIntegerFieldPath, integerFieldLocation.getPath()); Assert.assertEquals(expectedStringFieldPath, stringFieldLocation.getPath()); Assert.assertEquals(expectedIntegerFieldToString, integerFieldLocation.toString()); Assert.assertEquals(integerFieldXmlName, integerFieldLocation.getMemberName()); } } JavaDocExtractorTest.java000066400000000000000000000552561351100213400444120ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.ClassLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.FieldLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.MethodLocation; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.location.PackageLocation; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.Validate; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public class JavaDocExtractorTest { // Shared state private File javaDocBasicDir; private File javaDocAnnotatedDir; private File javaDocEnumsDir; private File javaDocXmlWrappersDir; private BufferingLog log; @Before public void setupSharedState() { log = new BufferingLog(BufferingLog.LogLevel.DEBUG); // Find the desired directory final URL dirURL = getClass() .getClassLoader() .getResource("testdata/schemageneration/javadoc/basic"); this.javaDocBasicDir = new File(dirURL.getPath()); Assert.assertTrue(javaDocBasicDir.exists() && javaDocBasicDir.isDirectory()); final URL annotatedDirURL = getClass() .getClassLoader() .getResource("testdata/schemageneration/javadoc/annotated"); this.javaDocAnnotatedDir = new File(annotatedDirURL.getPath()); Assert.assertTrue(javaDocAnnotatedDir.exists() && javaDocAnnotatedDir.isDirectory()); final URL enumsDirURL = getClass() .getClassLoader() .getResource("testdata/schemageneration/javadoc/enums"); this.javaDocEnumsDir = new File(enumsDirURL.getPath()); Assert.assertTrue(javaDocEnumsDir.exists() && javaDocEnumsDir.isDirectory()); final URL wrappersDirURL = getClass() .getClassLoader() .getResource("testdata/schemageneration/javadoc/xmlwrappers"); this.javaDocXmlWrappersDir = new File(wrappersDirURL.getPath()); Assert.assertTrue(javaDocXmlWrappersDir.exists() && javaDocXmlWrappersDir.isDirectory()); } @Test public void validateLogStatementsDuringProcessing() { // Assemble final JavaDocExtractor unitUnderTest = new JavaDocExtractor(log); final List sourceDirs = Arrays.asList(javaDocBasicDir); final List sourceFiles = FileSystemUtilities.resolveRecursively(sourceDirs, null, log); // Act unitUnderTest.addSourceFiles(sourceFiles); final SearchableDocumentation ignoredResult = unitUnderTest.process(); // Assert final SortedMap logBuffer = log.getLogBuffer(); final List keys = new ArrayList(logBuffer.keySet()); /* * 000: (DEBUG) Accepted file [/Users/lj/Development/Projects/Codehaus/github_jaxb2_plugin/target/test-classes/testdata/schemageneration/javadoc/basic/NodeProcessor.java], * 001: (INFO) Processing [1] java sources., * 002: (DEBUG) Added package-level JavaDoc for [basic], * 003: (DEBUG) Added class-level JavaDoc for [basic.NodeProcessor], * 004: (DEBUG) Added method-level JavaDoc for [basic.NodeProcessor#accept(org.w3c.dom.Node)], * 005: (DEBUG) Added method-level JavaDoc for [basic.NodeProcessor#process(org.w3c.dom.Node)]] */ Assert.assertEquals(6, keys.size()); Assert.assertEquals("001: (INFO) Processing [1] java sources.", keys.get(1)); Assert.assertEquals("002: (DEBUG) Added package-level JavaDoc for [basic]", keys.get(2)); Assert.assertEquals("003: (DEBUG) Added class-level JavaDoc for [basic.NodeProcessor]", keys.get(3)); Assert.assertEquals("004: (DEBUG) Added method-level JavaDoc for [basic.NodeProcessor#accept(org.w3c.dom.Node)]", keys.get(4)); Assert.assertEquals("005: (DEBUG) Added method-level JavaDoc for [basic.NodeProcessor#process(org.w3c.dom.Node)]", keys.get(5)); } @Test public void validateExtractingXmlAnnotatedName() throws Exception { // Assemble final JavaDocExtractor unitUnderTest = new JavaDocExtractor(log); // Act final SearchableDocumentation result = getSearchableDocumentationFor(unitUnderTest, 2, javaDocAnnotatedDir); // Assert final String prefix = "testdata.schemageneration.javadoc.annotated."; final String fieldAccessPrefix = prefix + "AnnotatedXmlNameAnnotatedClassWithFieldAccessTypeName#"; final String methodAccessPrefix = prefix + "AnnotatedXmlNameAnnotatedClassWithMethodAccessTypeName#"; // First, check the field-annotated class. final SortableLocation stringFieldLocation = result.getLocation(fieldAccessPrefix + "annotatedStringField"); final SortableLocation integerFieldLocation = result.getLocation(fieldAccessPrefix + "annotatedIntegerField"); final SortableLocation stringMethodLocation = result.getLocation(fieldAccessPrefix + "getStringField()"); final SortableLocation integerMethodLocation = result.getLocation(fieldAccessPrefix + "getIntegerField()"); Assert.assertTrue(stringFieldLocation instanceof FieldLocation); Assert.assertTrue(integerFieldLocation instanceof FieldLocation); Assert.assertTrue(stringMethodLocation instanceof MethodLocation); Assert.assertTrue(integerMethodLocation instanceof MethodLocation); Assert.assertNull(stringMethodLocation.getAnnotationRenamedTo()); Assert.assertNull(integerMethodLocation.getAnnotationRenamedTo()); Assert.assertEquals("annotatedStringField", stringFieldLocation.getAnnotationRenamedTo()); Assert.assertEquals("annotatedIntegerField", integerFieldLocation.getAnnotationRenamedTo()); Assert.assertEquals(JavaDocData.NO_COMMENT, result.getJavaDoc(stringMethodLocation.getPath()).getComment()); Assert.assertEquals(JavaDocData.NO_COMMENT, result.getJavaDoc(integerMethodLocation.getPath()).getComment()); Assert.assertEquals("This is a string field.", result.getJavaDoc(stringFieldLocation.getPath()).getComment()); Assert.assertEquals("This is an integer field.", result.getJavaDoc(integerFieldLocation.getPath()).getComment()); // Secondly, check the method-annotated class. final SortableLocation stringFieldLocation2 = result.getLocation(methodAccessPrefix + "stringField"); final SortableLocation integerFieldLocation2 = result.getLocation(methodAccessPrefix + "integerField"); final SortableLocation stringMethodLocation2 = result.getLocation(methodAccessPrefix + "annotatedStringMethod()"); final SortableLocation integerMethodLocation2 = result.getLocation(methodAccessPrefix + "annotatedIntegerMethod()"); Assert.assertTrue(stringFieldLocation2 instanceof FieldLocation); Assert.assertTrue(integerFieldLocation2 instanceof FieldLocation); Assert.assertTrue(stringMethodLocation2 instanceof MethodLocation); Assert.assertTrue(integerMethodLocation2 instanceof MethodLocation); Assert.assertNull(stringFieldLocation2.getAnnotationRenamedTo()); Assert.assertNull(integerFieldLocation2.getAnnotationRenamedTo()); Assert.assertEquals("annotatedStringMethod", stringMethodLocation2.getAnnotationRenamedTo()); Assert.assertEquals("annotatedIntegerMethod", integerMethodLocation2.getAnnotationRenamedTo()); Assert.assertEquals("Getter for the stringField.", result.getJavaDoc(stringMethodLocation2.getPath()).getComment()); Assert.assertEquals("Getter for the integerField.", result.getJavaDoc(integerMethodLocation2.getPath()).getComment()); Assert.assertEquals(JavaDocData.NO_COMMENT, result.getJavaDoc(stringFieldLocation2.getPath()).getComment()); Assert.assertEquals(JavaDocData.NO_COMMENT, result.getJavaDoc(integerFieldLocation2.getPath()).getComment()); } @Test public void validateJavaDocsForXmlEnumsAreCorrectlyApplied() { // Assemble final JavaDocExtractor unitUnderTest = new JavaDocExtractor(log); // Act final SearchableDocumentation result = getSearchableDocumentationFor(unitUnderTest, 3, javaDocEnumsDir); final MapWrapper mapWrapper = new MapWrapper(result); // Assert Assert.assertEquals(21, mapWrapper.sortableLocations2JavaDocDataMap.size()); final List paths = Arrays.asList( "enums", "enums.AmericanCoin", "enums.AmericanCoin#1", "enums.AmericanCoin#5", "enums.AmericanCoin#10", "enums.AmericanCoin#25", "enums.AmericanCoin#getValue()", "enums.AmericanCoin#value", "enums.ExampleEnumHolder", "enums.ExampleEnumHolder#coins", "enums.ExampleEnumHolder#foodPreferences", "enums.ExampleEnumHolder#getCoins()", "enums.ExampleEnumHolder#getFoodPreferences()", "enums.FoodPreference", "enums.FoodPreference#LACTO_VEGETARIAN", "enums.FoodPreference#NONE", "enums.FoodPreference#VEGAN", "enums.FoodPreference#isMeatEater()", "enums.FoodPreference#isMilkDrinker()", "enums.FoodPreference#meatEater", "enums.FoodPreference#milkDrinker"); for (String current : paths) { Assert.assertTrue("Required path [" + current + "] not found.", mapWrapper.path2LocationMap.keySet().contains(current.trim())); } // Finally, validate that the injected XML document comments // match the expected/corresponding JavaDoc comments. mapWrapper.validateJavaDocCommentText( "Simple enumeration example defining some Food preferences.", "enums.FoodPreference"); mapWrapper.validateJavaDocCommentText( "No special food preferences; eats everything.", "enums.FoodPreference#NONE"); mapWrapper.validateJavaDocCommentText( "Vegan who will neither eat meats nor drink milk.", "enums.FoodPreference#VEGAN"); mapWrapper.validateJavaDocCommentText( "Vegetarian who will not eat meats, but drinks milk.", "enums.FoodPreference#LACTO_VEGETARIAN"); mapWrapper.validateJavaDocCommentText( "A Penny, worth 1 cent.", "enums.AmericanCoin#1"); mapWrapper.validateJavaDocCommentText( "A Nickel, worth 5 cents.", "enums.AmericanCoin#5"); mapWrapper.validateJavaDocCommentText( "A Dime, worth 10 cents.", "enums.AmericanCoin#10"); mapWrapper.validateJavaDocCommentText( "A Quarter, worth 25 cents.", "enums.AmericanCoin#25"); } @Test public void validateJavaDocsForXmlWrapperAnnotatedFieldsAndMethodsAreCorrectlyApplied() throws Exception { // Assemble final JavaDocExtractor unitUnderTest = new JavaDocExtractor(log); // Act final SearchableDocumentation result = getSearchableDocumentationFor(unitUnderTest, 2, javaDocXmlWrappersDir); final MapWrapper mapWrapper = new MapWrapper(result); // Assert Assert.assertEquals(11, mapWrapper.sortableLocations2JavaDocDataMap.size()); final String packagePrefix = "org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers"; final List paths = new ArrayList(); for (String current : Arrays.asList("", ".ExampleXmlWrapperUsingFieldAccess", ".ExampleXmlWrapperUsingFieldAccess#foobar", ".ExampleXmlWrapperUsingFieldAccess#getIntegerSet()", ".ExampleXmlWrapperUsingFieldAccess#getStrings()", ".ExampleXmlWrapperUsingFieldAccess#integerSet", ".ExampleXmlWrapperUsingMethodAccess", ".ExampleXmlWrapperUsingMethodAccess#foobar()", ".ExampleXmlWrapperUsingMethodAccess#getMethodIntegerSet()", ".ExampleXmlWrapperUsingMethodAccess#methodIntegerSet", ".ExampleXmlWrapperUsingMethodAccess#methodStrings")) { paths.add(packagePrefix + current); } for (String current : paths) { Assert.assertTrue("Required path [" + current + "] not found.", mapWrapper.path2LocationMap.keySet().contains(current.trim())); } mapWrapper.validateJavaDocCommentText("List containing some strings.", packagePrefix + ".ExampleXmlWrapperUsingFieldAccess#foobar"); mapWrapper.validateJavaDocCommentText("SortedSet containing Integers.", packagePrefix + ".ExampleXmlWrapperUsingFieldAccess#integerSet"); mapWrapper.validateJavaDocCommentText("List containing some methodStrings.", packagePrefix + ".ExampleXmlWrapperUsingMethodAccess#foobar()"); mapWrapper.validateJavaDocCommentText("SortedSet containing Integers.", packagePrefix + ".ExampleXmlWrapperUsingMethodAccess#getMethodIntegerSet()"); } @Test public void validatePathsFromProcessing() { // Assemble final JavaDocExtractor unitUnderTest = new JavaDocExtractor(log); // Act final SearchableDocumentation result = getSearchableDocumentationFor(unitUnderTest, 1, javaDocBasicDir); // Assert final ArrayList sortableLocations = new ArrayList(result.getAll().keySet()); Assert.assertEquals(4, sortableLocations.size()); final List paths = new ArrayList(result.getPaths()); Assert.assertEquals(4, paths.size()); Assert.assertEquals("basic", paths.get(0)); Assert.assertEquals("basic.NodeProcessor", paths.get(1)); Assert.assertEquals("basic.NodeProcessor#accept(org.w3c.dom.Node)", paths.get(2)); Assert.assertEquals("basic.NodeProcessor#process(org.w3c.dom.Node)", paths.get(3)); } @Test public void validateJavaDocDataFromProcessing() { // Assemble final String basicPackagePath = "basic"; final String nodeProcessorClassPath = "basic.NodeProcessor"; final String acceptMethodPath = "basic.NodeProcessor#accept(org.w3c.dom.Node)"; final String processMethodPath = "basic.NodeProcessor#process(org.w3c.dom.Node)"; final JavaDocExtractor unitUnderTest = new JavaDocExtractor(log); final List sourceDirs = Collections.singletonList(javaDocBasicDir); final List sourceFiles = FileSystemUtilities.resolveRecursively(sourceDirs, null, log); // Act unitUnderTest.addSourceFiles(sourceFiles); final SearchableDocumentation result = unitUnderTest.process(); // Assert /* +================= | Comment: | No JavaDoc tags. +================= */ final SortableLocation packageLocation = result.getLocation(basicPackagePath); final JavaDocData basicPackageJavaDoc = result.getJavaDoc(basicPackagePath); Assert.assertTrue(packageLocation instanceof PackageLocation); final PackageLocation castPackageLocation = (PackageLocation) packageLocation; Assert.assertEquals("basic", castPackageLocation.getPackageName()); Assert.assertEquals(JavaDocData.NO_COMMENT, basicPackageJavaDoc.getComment()); Assert.assertEquals(0, basicPackageJavaDoc.getTag2ValueMap().size()); /* +================= | Comment: Processor/visitor pattern specification for DOM Nodes. | 2 JavaDoc tags ... | author: Lennart Jörelid, Mr. Foo | see: org.w3c.dom.Node +================= */ final SortableLocation classLocation = result.getLocation(nodeProcessorClassPath); final JavaDocData nodeProcessorClassJavaDoc = result.getJavaDoc(nodeProcessorClassPath); Assert.assertTrue(classLocation instanceof ClassLocation); final ClassLocation castClassLocation = (ClassLocation) classLocation; Assert.assertEquals("basic", castClassLocation.getPackageName()); Assert.assertEquals("NodeProcessor", castClassLocation.getClassName()); Assert.assertEquals("Processor/visitor pattern specification for DOM Nodes.", nodeProcessorClassJavaDoc.getComment()); final SortedMap classTag2ValueMap = nodeProcessorClassJavaDoc.getTag2ValueMap(); Assert.assertEquals(2, classTag2ValueMap.size()); Assert.assertEquals("org.w3c.dom.Node", classTag2ValueMap.get("see")); Assert.assertEquals("Lennart Jörelid, Mr. Foo", classTag2ValueMap.get("author")); /* +================= | Comment: Defines if this visitor should process the provided node. | 2 JavaDoc tags ... | param: aNode The DOM node to process. | return: true if the provided Node should be processed by this NodeProcessor. +================= */ final SortableLocation acceptMethodLocation = result.getLocation(acceptMethodPath); final JavaDocData acceptMethodClassJavaDoc = result.getJavaDoc(acceptMethodPath); Assert.assertTrue(acceptMethodLocation instanceof MethodLocation); final MethodLocation castMethodLocation = (MethodLocation) acceptMethodLocation; Assert.assertEquals("basic", castMethodLocation.getPackageName()); Assert.assertEquals("NodeProcessor", castMethodLocation.getClassName()); Assert.assertEquals("(org.w3c.dom.Node)", castMethodLocation.getParametersAsString()); Assert.assertEquals("Defines if this visitor should process the provided node.", acceptMethodClassJavaDoc.getComment()); final SortedMap methodTag2ValueMap = acceptMethodClassJavaDoc.getTag2ValueMap(); Assert.assertEquals(2, methodTag2ValueMap.size()); Assert.assertEquals("aNode The DOM node to process.", methodTag2ValueMap.get("param")); Assert.assertEquals("true if the provided Node should be processed by this NodeProcessor.", methodTag2ValueMap.get("return")); } // // Private helpers // /** * Simple helper class wrapping the path2LocationMap and the sortableLocations2JavaDocDataMap. */ class MapWrapper { SortedMap path2LocationMap; SortedMap sortableLocations2JavaDocDataMap; /** * Creates a MapWrapper using the data retrieved from a SearchableDocumentation * * @param searchableDocumentation A non-null SearchableDocumentation instance. */ public MapWrapper(final SearchableDocumentation searchableDocumentation) { // Check sanity Validate.notNull(searchableDocumentation, "searchableDocumentation"); // Assign state this.sortableLocations2JavaDocDataMap = searchableDocumentation.getAll(); this.path2LocationMap = new TreeMap(); for (Map.Entry current : sortableLocations2JavaDocDataMap.entrySet()) { path2LocationMap.put(current.getKey().getPath(), current.getKey()); } } /** * Validates that the JavaDoc found at the supplied SortableLocation path equals the expected value. * * @param expected The expected JavaDoc comment text. * @param path The SortableLocation path where the text was expected. * @see SortableLocation#getPath() */ public void validateJavaDocCommentText(final String expected, final String path) { final SortableLocation sortableLocation = path2LocationMap.get(path); final JavaDocData xmlWrapperJavaDocData = sortableLocations2JavaDocDataMap.get(sortableLocation); // All Done. Assert.assertEquals(expected, xmlWrapperJavaDocData.getComment()); } } private void validateJavaDocCommentText( final MapWrapper wrapper, final String expected, final String path) { final SortableLocation sortableLocation = wrapper.path2LocationMap.get(path); final JavaDocData xmlWrapperJavaDocData = wrapper.sortableLocations2JavaDocDataMap.get(sortableLocation); // All Done. Assert.assertEquals(expected, xmlWrapperJavaDocData.getComment()); } private SearchableDocumentation getSearchableDocumentationFor(final JavaDocExtractor unitUnderTest, final int expectedNumberOfFiles, final File... sourceFileDirectories) { // Ensure that the encoding is correctly set unitUnderTest.setEncoding("UTF-8"); // Convert the supplied directory Files to a List final List sourceDirs = new ArrayList(); Collections.addAll(sourceDirs, sourceFileDirectories); // Exclude any ".xsd" files found within the source directory files given final List> excludeFilesMatching = new ArrayList>(); excludeFilesMatching.add(new PatternFileFilter(Collections.singletonList("\\.xsd"))); Filters.initialize(log, excludeFilesMatching); // Find all normal Files not being ".xsd" files below the supplied sourceDirs final List sourceFiles = FileSystemUtilities.resolveRecursively(sourceDirs, excludeFilesMatching, log); Assert.assertEquals(expectedNumberOfFiles, sourceFiles.size()); // Add the found files as source files unitUnderTest.addSourceFiles(sourceFiles); // Launch the JavaDocExtractor and find // the resulting SearchableDocumentation. return unitUnderTest.process(); } } SemiDocumentedClass.java000066400000000000000000000040261351100213400442270ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * This is a JAXB-annotated class where not all properties are JavaDoc'ed. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement @XmlType(namespace = SomewhatNamedPerson.NAMESPACE, propOrder = {"documented", "unDocumented"}) @XmlAccessorType(XmlAccessType.FIELD) public class SemiDocumentedClass { /** * The XML namespace of this SomewhatNamedPerson. */ public static final String NAMESPACE = "http://some/namespace"; /** * This is a documented property. */ @XmlElement(nillable = true, required = false) private String documented; @XmlElement(nillable = false, required = true) private String unDocumented; /** * JAXB-friendly constructor. */ public SemiDocumentedClass() { } public String getDocumented() { return documented; } public String getUnDocumented() { return unDocumented; } } SomewhatNamedPerson.java000066400000000000000000000075551351100213400442710ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.codehaus.mojo.jaxb2.shared.Validate; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * Definition of a person with lastName and age, and optionally a firstName as well... * * @author Lennart Jörelid, jGuru Europe AB * @since Some version. */ @XmlRootElement @XmlType(namespace = SomewhatNamedPerson.NAMESPACE, propOrder = {"firstName", "lastName", "age"}) @XmlAccessorType(XmlAccessType.FIELD) public class SomewhatNamedPerson { /** * The XML namespace of this SomewhatNamedPerson. */ public static final String NAMESPACE = "http://some/namespace"; /** * The first name of the SomewhatNamedPerson. */ @XmlElement(nillable = true, required = false) private String firstName; /** * The last name of the SomewhatNamedPerson. */ @XmlElement(nillable = false, required = true) private String lastName; /** * The age of the SomewhatNamedPerson. Must be positive. */ @XmlAttribute(required = true) private int age; /** * JAXB-friendly constructor. */ public SomewhatNamedPerson() { } /** * Creates a SomewhatNamedPerson wrapping the supplied data. * * @param firstName The first name of the SomewhatNamedPerson. * @param lastName The last name of the SomewhatNamedPerson. Cannot be null. * @param age The age of the SomewhatNamedPerson. Must be positive. */ public SomewhatNamedPerson(final String firstName, final String lastName, final int age) { // Check sanity Validate.notNull(lastName, "lastName"); Validate.isTrue(age >= 0, "Cannot handle negative 'age' argument."); // Assign internal state this.firstName = firstName; this.lastName = lastName; this.age = age; } /** * Retrieves the first name of this SomewhatNamedPerson. * * @return The first name of this SomewhatNamedPerson, converting {@code null} values to empty strings. */ public String getFirstName() { return getFirstName(true); } /** * Retrieves the first name of this SomewhatNamedPerson. * * @param replaceNull indicates if this method should replace null firstName values with an empty string. * @return The first name of this SomewhatNamedPerson, optionally converting {@code null} values to empty strings. */ public String getFirstName(final boolean replaceNull) { return firstName == null && replaceNull ? "" : firstName; } /** * @return The last name of this SomewhatNamedPerson. Never null. */ public String getLastName() { return lastName; } /** * @return The age of this SomewhatNamedPerson. */ public int getAge() { return age; } } XsdAnnotationProcessorSemiDocumentedTest.java000066400000000000000000000027311351100213400505140ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import java.util.Arrays; import java.util.List; /** * @author Lennart Jörelid, jGuru Europe AB */ public class XsdAnnotationProcessorSemiDocumentedTest extends AbstractSourceCodeAwareNodeProcessingTest { // Shared state private JavaDocRenderer renderer = new DefaultJavaDocRenderer(); @Test public void validateProcessingNodesInVanillaXSD() throws Exception { // Assemble final String path = "testdata/schemageneration/javadoc/expectedSemiDocumentedClass.xml"; final String expected = readFully(path); final Document document = namespace2DocumentMap.get(SomewhatNamedPerson.NAMESPACE); final Node rootNode = document.getFirstChild(); final XsdAnnotationProcessor unitUnderTest = new XsdAnnotationProcessor(docs, renderer); // Act process(rootNode, true, unitUnderTest); // Assert final String processed = printDocument(document); // System.out.println("Got: " + processed); Assert.assertTrue(compareXmlIgnoringWhitespace(expected, processed).identical()); } /** * {@inheritDoc} */ @Override protected List> getJaxbAnnotatedClassesForJaxbContext() { return Arrays.>asList(SemiDocumentedClass.class); } } XsdAnnotationProcessorTest.java000066400000000000000000000031221351100213400456610ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers.ExampleXmlWrapper; import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import java.util.Arrays; import java.util.List; /** * @author Lennart Jörelid, jGuru Europe AB */ public class XsdAnnotationProcessorTest extends AbstractSourceCodeAwareNodeProcessingTest { // Shared state private JavaDocRenderer renderer = new DefaultJavaDocRenderer(); @Test public void validateProcessingNodesInVanillaXSD() throws Exception { // Assemble final String path = "testdata/schemageneration/javadoc/expectedTransformedSomewhatNamedPerson.xml"; final String expected = readFully(path); final Document document = namespace2DocumentMap.get(SomewhatNamedPerson.NAMESPACE); final Node rootNode = document.getFirstChild(); final XsdAnnotationProcessor unitUnderTest = new XsdAnnotationProcessor(docs, renderer); // Act process(rootNode, true, unitUnderTest); // Assert final String processed = printDocument(document); // System.out.println("Got: " + processed); Assert.assertTrue(compareXmlIgnoringWhitespace(expected, processed).identical()); } /** * {@inheritDoc} */ @Override protected List> getJaxbAnnotatedClassesForJaxbContext() { return Arrays.>asList(SomewhatNamedPerson.class, ExampleXmlWrapper.class); } } XsdEnumerationAnnotationProcessorTest.java000066400000000000000000000036111351100213400500730ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums.AmericanCoin; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums.ExampleEnumHolder; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums.FoodPreference; import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import java.util.Arrays; import java.util.List; /** * @author Lennart Jörelid, jGuru Europe AB */ public class XsdEnumerationAnnotationProcessorTest extends AbstractSourceCodeAwareNodeProcessingTest { // Shared state private JavaDocRenderer renderer = new DefaultJavaDocRenderer(); @Test public void validateProcessingNodesInVanillaXSD() throws Exception { // Assemble final String path = "testdata/schemageneration/javadoc/enums/expectedTransformedExampleEnumHolder.xsd"; final String expected = readFully(path); final Document xsdGeneratedFromClassesInMethod = namespace2DocumentMap.get(SomewhatNamedPerson.NAMESPACE); final Node rootNode = xsdGeneratedFromClassesInMethod.getFirstChild(); final XsdEnumerationAnnotationProcessor unitUnderTest = new XsdEnumerationAnnotationProcessor(docs, renderer); // Act process(rootNode, true, unitUnderTest); // Assert final String processed = printDocument(xsdGeneratedFromClassesInMethod); // System.out.println("Got: " + processed); Assert.assertTrue(compareXmlIgnoringWhitespace(expected, processed).identical()); } /** * {@inheritDoc} */ @Override protected List> getJaxbAnnotatedClassesForJaxbContext() { return Arrays.>asList(ExampleEnumHolder.class, AmericanCoin.class, FoodPreference.class); } } enums/000077500000000000000000000000001351100213400406165ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocAmericanCoin.java000066400000000000000000000023711351100213400440140ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/enumspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SomewhatNamedPerson; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlType; /** * Simple enumeration example defining standard US coins. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlType(namespace = SomewhatNamedPerson.NAMESPACE) @XmlEnum(Integer.class) @XmlAccessorType(XmlAccessType.FIELD) public enum AmericanCoin { /** * A Penny, worth 1 cent. */ @XmlEnumValue("1") PENNY(1), /** * A Nickel, worth 5 cents. */ @XmlEnumValue("5") NICKEL(5), /** * A Nickel, worth 5 cents. */ @XmlEnumValue("10") DIME(10), @XmlEnumValue("25") QUARTER(25); // Internal state private int value; AmericanCoin(final int value) { this.value = value; } /** * The value - in cents - of this coin. * * @return the value - in cents - of this coin. */ public int getValue() { return value; } } County.java000066400000000000000000000100031351100213400427340ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/enumspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SomewhatNamedPerson; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; /** * Swedish County ("län") enumeration. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlType(namespace = SomewhatNamedPerson.NAMESPACE) @XmlEnum public enum County implements Serializable { @XmlEnumValue("1")stockholm(1, "AB", true, "Stockholm"), @XmlEnumValue("3")uppsala(3, "C", false, "Uppsala"), @XmlEnumValue("4")sodermanland(4, "D", true, "Södermanland"), @XmlEnumValue("5")ostergotland(5, "E", true, "Östergötland"), @XmlEnumValue("6")jonkoping(6, "F", true, "Jönköping"), @XmlEnumValue("7")kronoberg(7, "G", true, "Kronoberg"), @XmlEnumValue("8")kalmar(8, "H", false, "Kalmar"), @XmlEnumValue("9")gotland(9, "I", true, "Gotland"), @XmlEnumValue("10")blekinge(10, "K", false, "Blekinge"), @XmlEnumValue("12")skane(12, "M", false, "Skåne"), @XmlEnumValue("13")halland(13, "N", true, "Halland"), @XmlEnumValue("14")vastra_gotaland(14, "O", true, "Västra Götaland"), @XmlEnumValue("17")varmland(17, "S", true, "Värmland"), @XmlEnumValue("18")orebro(18, "T", false, "Örebro"), @XmlEnumValue("19")vastmanland(19, "U", true, "Västmanland"), @XmlEnumValue("20")dalarna(20, "W", true, "Dalarna"), @XmlEnumValue("21")gavleborg(21, "X", true, "Gävleborg"), @XmlEnumValue("22")vasternorrland(22, "Y", true, "Västernorrland"), @XmlEnumValue("23")jamtland(23, "Z", true, "Jämtland"), @XmlEnumValue("24")vasterbotten(24, "AC", true, "Västerbotten"), @XmlEnumValue("25")norrbotten(25, "BD", true, "Norrbotten"); // Internal state private int countyId; private boolean injectFormalNameS; private String countyName; private String letterCode; /** * Make the constructor private for Enum types. * * @param countyId The ID of this County. * @param letterCode The letter code of this County. * @param injectFormalNameS {@code true} if the formal name should contain an 's' after the name of this County. * (I.e. Name: {@code Stockholm} yields County formal name: * {@code Stockholms län} (note the extra 's')). * @param countyName The name of this County. */ County(final int countyId, final String letterCode, final boolean injectFormalNameS, final String countyName) { this.letterCode = letterCode; this.countyId = countyId; this.injectFormalNameS = injectFormalNameS; this.countyName = countyName; } /** * @return Retrieves the County ID. */ public int getCountyId() { return countyId; } /** * @return The name of this County. */ public String getName() { return countyName; } /** * @return The letter code of this County. */ public String getLetterCode() { return letterCode; } /** * @return The formal name of the county, which is typical in listings. * (I.e. {@code Stockholms län} and equivalent). */ public String getFormalName() { return getName() + (injectFormalNameS ? "s" : "") + " län"; } /** * Retrieves the County with the supplied ID. * * @param countyId The id of the County to retrieve. * @return The County with the supplied countyId. * @throws IllegalArgumentException if no County had the supplied countyId. */ public static County getCountyById(final int countyId) { for (County current : values()) { if (current.getCountyId() == countyId) { return current; } } throw new IllegalArgumentException("No County had countyID [" + countyId + "]"); } }ExampleEnumHolder.java000066400000000000000000000032371351100213400450440ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/enumspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SomewhatNamedPerson; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * Trivial transport object type for Enums with different representations. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(namespace = SomewhatNamedPerson.NAMESPACE) @XmlType(namespace = SomewhatNamedPerson.NAMESPACE, propOrder = {"coins", "foodPreferences"}) @XmlAccessorType(XmlAccessType.FIELD) public class ExampleEnumHolder implements Serializable { /** * List containing all AmericanCoin objects. */ @XmlElementWrapper @XmlElement(name = "coin") private List coins; /** * SortedSet containing the FoodPreference objects collected. */ @XmlElementWrapper @XmlElement(name = "preference") private SortedSet foodPreferences; public ExampleEnumHolder() { this.coins = new ArrayList(); this.foodPreferences = new TreeSet(); } public List getCoins() { return coins; } public SortedSet getFoodPreferences() { return foodPreferences; } } FoodPreference.java000066400000000000000000000030601351100213400443460ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/enumspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SomewhatNamedPerson; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlType; /** * Simple enumeration example defining some Food preferences. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlType(namespace = SomewhatNamedPerson.NAMESPACE) @XmlEnum(String.class) @XmlAccessorType(XmlAccessType.FIELD) public enum FoodPreference { /** * No special food preferences; eats everything. */ NONE(true, true), /** * Vegetarian who will not eat meats, but drinks milk. */ LACTO_VEGETARIAN(false, true), /** * Vegan who will neither eat meats nor drink milk. */ VEGAN(false, false); /** * Boolean value indicating if this {@link FoodPreference} eats meats. */ @XmlAttribute private boolean meatEater; /** * Boolean value indicating if this {@link FoodPreference} drinks milk. */ @XmlAttribute boolean milkDrinker; private FoodPreference(final boolean meatEater, final boolean milkDrinker) { this.meatEater = meatEater; this.milkDrinker = milkDrinker; } public boolean isMeatEater() { return meatEater; } public boolean isMilkDrinker() { return milkDrinker; } } Municipality.java000066400000000000000000000474671351100213400441520ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/enumspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums; import org.codehaus.mojo.jaxb2.shared.Validate; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.text.DecimalFormat; import java.util.SortedSet; import java.util.TreeSet; /** *

Enumeration of Swedish Municipalities. The enumeration name of each municipality is synthesized from the * lower-case name of the municipality by replacing each scandinavian character with the corresponding ASCII * character and replacing whitespace and punctuation with underscore. For example, this implies that "Järfälla" * municipality has the enum constant "jarfalla", and that "Östra Göinge" has the enum constant "ostra_goinge".

*

A special case exists for the two municipalities "Håbo" in Uppsala county and "Habo" in Jönköping county. * Since the enum constant for both these municipalities would be "habo", the county name is appended yielding the * two constants {@code habo_uppsala} and {@code habo_jonkoping}.

* * @author Lennart Jörelid, jGuru Europe AB */ @XmlType(namespace = "http://sweden.is.amazing") @XmlEnum @XmlSeeAlso(County.class) public enum Municipality implements Serializable { // Stockholm municipalities @XmlEnumValue("0114")upplands_vasby(1, 114, "Upplands Väsby"), @XmlEnumValue("0115")vallentuna(1, 115, "Vallentuna"), @XmlEnumValue("0117")osteraker(1, 117, "Österåker"), @XmlEnumValue("0120")varmdo(1, 120, "Värmdö"), @XmlEnumValue("0123")jarfalla(1, 123, "Järfälla"), @XmlEnumValue("0125")ekero(1, 125, "Ekerö"), @XmlEnumValue("0126")huddinge(1, 126, "Huddinge"), @XmlEnumValue("0127")botkyrka(1, 127, "Botkyrka"), @XmlEnumValue("0128")salem(1, 128, "Salem"), @XmlEnumValue("0136")haninge(1, 136, "Haninge"), @XmlEnumValue("0138")tyreso(1, 138, "Tyresö"), @XmlEnumValue("0139")upplands_bro(1, 139, "Upplands-Bro"), @XmlEnumValue("0140")nykvarn(1, 140, "Nykvarn"), @XmlEnumValue("0160")taby(1, 160, "Täby"), @XmlEnumValue("0162")danderyd(1, 162, "Danderyd"), @XmlEnumValue("0163")sollentuna(1, 163, "Sollentuna"), @XmlEnumValue("0180")stockholm(1, 180, "Stockholm"), @XmlEnumValue("0181")sodertalje(1, 181, "Södertälje"), @XmlEnumValue("0182")nacka(1, 182, "Nacka"), @XmlEnumValue("0183")sundbyberg(1, 183, "Sundbyberg"), @XmlEnumValue("0184")solna(1, 184, "Solna"), @XmlEnumValue("0186")lidingo(1, 186, "Lidingö"), @XmlEnumValue("0187")vaxholm(1, 187, "Vaxholm"), @XmlEnumValue("0188")norrtalje(1, 188, "Norrtälje"), @XmlEnumValue("0191")sigtuna(1, 191, "Sigtuna"), @XmlEnumValue("0192")nynashamn(1, 192, "Nynäshamn"), // Uppsala municipalities @XmlEnumValue("0305")habo_uppsala(3, 305, "Håbo"), @XmlEnumValue("0319")alvkarleby(3, 319, "Älvkarleby"), @XmlEnumValue("0330")knivsta(3, 330, "Knivsta"), @XmlEnumValue("0331")heby(3, 331, "Heby"), @XmlEnumValue("0360")tierp(3, 360, "Tierp"), @XmlEnumValue("0380")uppsala(3, 380, "Uppsala"), @XmlEnumValue("0381")enkoping(3, 381, "Enköping"), @XmlEnumValue("0382")osthammar(3, 382, "Östhammar"), // Södermanland municipalities @XmlEnumValue("0428")vingaker(4, 428, "Vingåker"), @XmlEnumValue("0461")gnesta(4, 461, "Gnesta"), @XmlEnumValue("0480")nykoping(4, 480, "Nyköping"), @XmlEnumValue("0481")oxelosund(4, 481, "Oxelösund"), @XmlEnumValue("0482")flen(4, 482, "Flen"), @XmlEnumValue("0483")katrineholm(4, 483, "Katrineholm"), @XmlEnumValue("0484")eskilstuna(4, 484, "Eskilstuna"), @XmlEnumValue("0486")strangnas(4, 486, "Strängnäs"), @XmlEnumValue("0488")trosa(4, 488, "Trosa"), // Östergötland municipalities @XmlEnumValue("0509")odeshog(5, 509, "Ödeshög"), @XmlEnumValue("0512")ydre(5, 512, "Ydre"), @XmlEnumValue("0513")kinda(5, 513, "Kinda"), @XmlEnumValue("0560")boxholm(5, 560, "Boxholm"), @XmlEnumValue("0561")atvidaberg(5, 561, "Åtvidaberg"), @XmlEnumValue("0562")finspang(5, 562, "Finspång"), @XmlEnumValue("0563")valdemarsvik(5, 563, "Valdemarsvik"), @XmlEnumValue("0580")linkoping(5, 580, "Linköping"), @XmlEnumValue("0581")norrkoping(5, 581, "Norrköping"), @XmlEnumValue("0582")soderkoping(5, 582, "Söderköping"), @XmlEnumValue("0583")motala(5, 583, "Motala"), @XmlEnumValue("0584")vadstena(5, 584, "Vadstena"), @XmlEnumValue("0586")mjolby(5, 586, "Mjölby"), // Jönköping municipalities @XmlEnumValue("0604")aneby(6, 604, "Aneby"), @XmlEnumValue("0617")gnosjo(6, 617, "Gnosjö"), @XmlEnumValue("0642")mullsjo(6, 642, "Mullsjö"), @XmlEnumValue("0643")habo_jonkoping(6, 643, "Habo"), @XmlEnumValue("0662")gislaved(6, 662, "Gislaved"), @XmlEnumValue("0665")vaggeryd(6, 665, "Vaggeryd"), @XmlEnumValue("0680")jonkoping(6, 680, "Jönköping"), @XmlEnumValue("0682")nassjo(6, 682, "Nässjö"), @XmlEnumValue("0683")varnamo(6, 683, "Värnamo"), @XmlEnumValue("0684")savsjo(6, 684, "Sävsjö"), @XmlEnumValue("0685")vetlanda(6, 685, "Vetlanda"), @XmlEnumValue("0686")eksjo(6, 686, "Eksjö"), @XmlEnumValue("0687")tranas(6, 687, "Tranås"), // Kronoberg municipalities @XmlEnumValue("0760")uppvidinge(7, 760, "Uppvidinge"), @XmlEnumValue("0761")lessebo(7, 761, "Lessebo"), @XmlEnumValue("0763")tingsryd(7, 763, "Tingsryd"), @XmlEnumValue("0764")alvesta(7, 764, "Alvesta"), @XmlEnumValue("0765")almhult(7, 765, "Älmhult"), @XmlEnumValue("0767")markaryd(7, 767, "Markaryd"), @XmlEnumValue("0780")vaxjo(7, 780, "Växjö"), @XmlEnumValue("0781")ljungby(7, 781, "Ljungby"), // Kalmar municipalities @XmlEnumValue("0821")hogsby(8, 821, "Högsby"), @XmlEnumValue("0834")torsas(8, 834, "Torsås"), @XmlEnumValue("0830")morbylanga(8, 840, "Mörbylånga"), @XmlEnumValue("0860")hultsfred(8, 860, "Hultsfred"), @XmlEnumValue("0861")monsteras(8, 861, "Mönsterås"), @XmlEnumValue("0862")emmaboda(8, 862, "Emmaboda"), @XmlEnumValue("0880")kalmar(8, 880, "Kalmar"), @XmlEnumValue("0881")nybro(8, 881, "Nybro"), @XmlEnumValue("0882")oskarshamn(8, 882, "Oskarshamn"), @XmlEnumValue("0883")vastervik(8, 883, "Västervik"), @XmlEnumValue("0884")vimmerby(8, 884, "Vimmerby"), @XmlEnumValue("0885")borgholm(8, 885, "Borgholm"), // Gotland municipality @XmlEnumValue("0980")gotland(9, 980, "Gotland"), // Blekinge municipalities @XmlEnumValue("1060")olofstrom(10, 1060, "Olofström"), @XmlEnumValue("1080")karlskrona(10, 1080, "Karlskrona"), @XmlEnumValue("1081")ronneby(10, 1081, "Ronneby"), @XmlEnumValue("1082")karlshamn(10, 1082, "Karlshamn"), @XmlEnumValue("1083")solvesborg(10, 1083, "Sölvesborg"), // Skåne municipalities @XmlEnumValue("1214")svalov(12, 1214, "Svalöv"), @XmlEnumValue("1230")staffanstorp(12, 1230, "Staffanstorp"), @XmlEnumValue("1231")bjurlov(12, 1231, "Burlöv"), @XmlEnumValue("1233")vellinge(12, 1233, "Vellinge"), @XmlEnumValue("1256")ostra_goinge(12, 1256, "Östra Göinge"), @XmlEnumValue("1257")orkelljunga(12, 1257, "Örkelljunga"), @XmlEnumValue("1260")bjuv(12, 1260, "Bjuv"), @XmlEnumValue("1261")kavlinge(12, 1261, "Kävlinge"), @XmlEnumValue("1262")lomma(12, 1262, "Lomma"), @XmlEnumValue("1263")svedala(12, 1263, "Svedala"), @XmlEnumValue("1264")skurup(12, 1264, "Skurup"), @XmlEnumValue("1265")sjobo(12, 1265, "Sjöbo"), @XmlEnumValue("1266")horby(12, 1266, "Hörby"), @XmlEnumValue("1267")hoor(12, 1267, "Höör"), @XmlEnumValue("1270")tomelilla(12, 1270, "Tomelilla"), @XmlEnumValue("1272")bromolla(12, 1272, "Bromölla"), @XmlEnumValue("1273")osby(12, 1273, "Osby"), @XmlEnumValue("1275")perstorp(12, 1275, "Perstorp"), @XmlEnumValue("1276")klippan(12, 1276, "Klippan"), @XmlEnumValue("1277")astorp(12, 1277, "Åstorp"), @XmlEnumValue("1278")bastad(12, 1278, "Båstad"), @XmlEnumValue("1280")malmo(12, 1280, "Malmö"), @XmlEnumValue("1281")lund(12, 1281, "Lund"), @XmlEnumValue("1282")landskrona(12, 1282, "Landskrona"), @XmlEnumValue("1283")helsingborg(12, 1283, "Helsingborg"), @XmlEnumValue("1284")hoganas(12, 1284, "Höganäs"), @XmlEnumValue("1285")eslov(12, 1285, "Eslöv"), @XmlEnumValue("1286")ystad(12, 1286, "Ystad"), @XmlEnumValue("1287")trelleborg(12, 1287, "Trelleborg"), @XmlEnumValue("1290")kristianstad(12, 1290, "Kristianstad"), @XmlEnumValue("1291")simrishamn(12, 1291, "Simrishamn"), @XmlEnumValue("1292")angelholm(12, 1292, "Ängelholm"), @XmlEnumValue("1293")hassleholm(12, 1293, "Hässleholm"), // Halland municipalities @XmlEnumValue("1315")hylte(13, 1315, "Hylte"), @XmlEnumValue("1380")halmstad(13, 1380, "Halmstad"), @XmlEnumValue("1381")laholm(13, 1381, "Laholm"), @XmlEnumValue("1382")falkenberg(13, 1382, "Falkenberg"), @XmlEnumValue("1383")varberg(13, 1383, "Varberg"), @XmlEnumValue("1384")kungsbacka(13, 1384, "Kungsbacka"), // Västra Götaland municipalities @XmlEnumValue("1401")harryda(14, 1401, "Härryda"), @XmlEnumValue("1402")partille(14, 1402, "Partille"), @XmlEnumValue("1407")ockero(14, 1407, "Öckerö"), @XmlEnumValue("1415")stenungsund(14, 1415, "Stenungsund"), @XmlEnumValue("1419")tjorn(14, 1419, "Tjörn"), @XmlEnumValue("1421")orust(14, 1421, "Orust"), @XmlEnumValue("1427")sotenas(14, 1427, "Sotenäs"), @XmlEnumValue("1430")munkedal(14, 1430, "Munkedal"), @XmlEnumValue("1435")tanum(14, 1435, "Tanum"), @XmlEnumValue("1438")dals_ed(14, 1438, "Dals-Ed"), @XmlEnumValue("1439")fargelanda(14, 1439, "Färgelanda"), @XmlEnumValue("1440")ale(14, 1440, "Ale"), @XmlEnumValue("1441")lerum(14, 1441, "Lerum"), @XmlEnumValue("1442")vargarda(14, 1442, "Vårgårda"), @XmlEnumValue("1443")bollebygd(14, 1443, "Bollebygd"), @XmlEnumValue("1444")grastorp(14, 1444, "Grästorp"), @XmlEnumValue("1445")essunga(14, 1445, "Essunga"), @XmlEnumValue("1446")karlsborg(14, 1446, "Karlsborg"), @XmlEnumValue("1447")gullspang(14, 1447, "Gullspång"), @XmlEnumValue("1452")tranemo(14, 1452, "Tranemo"), @XmlEnumValue("1460")bengtsfors(14, 1460, "Bengtsfors"), @XmlEnumValue("1461")mellerud(14, 1461, "Mellerud"), @XmlEnumValue("1462")lilla_edet(14, 1462, "Lilla Edet"), @XmlEnumValue("1463")mark(14, 1463, "Mark"), @XmlEnumValue("1465")svenljunga(14, 1465, "Svenljunga"), @XmlEnumValue("1466")herrljunga(14, 1466, "Herrljunga"), @XmlEnumValue("1470")vara(14, 1470, "Vara"), @XmlEnumValue("1471")gotene(14, 1471, "Götene"), @XmlEnumValue("1472")tibro(14, 1472, "Tibro"), @XmlEnumValue("1473")toreboda(14, 1473, "Töreboda"), @XmlEnumValue("1480")goteborg(14, 1480, "Göteborg"), @XmlEnumValue("1481")molndal(14, 1481, "Mölndal"), @XmlEnumValue("1482")kungalv(14, 1482, "Kungälv"), @XmlEnumValue("1484")lysekil(14, 1484, "Lysekil"), @XmlEnumValue("1485")uddevalla(14, 1485, "Uddevalla"), @XmlEnumValue("1486")stromstad(14, 1486, "Strömstad"), @XmlEnumValue("1487")vanersborg(14, 1487, "Vänersborg"), @XmlEnumValue("1488")trollhattan(14, 1488, "Trollhättan"), @XmlEnumValue("1489")alingsas(14, 1489, "Alingsås"), @XmlEnumValue("1490")boras(14, 1490, "Borås"), @XmlEnumValue("1491")ulricehamn(14, 1491, "Ulricehamn"), @XmlEnumValue("1492")amal(14, 1492, "Åmål"), @XmlEnumValue("1493")mariestad(14, 1493, "Mariestad"), @XmlEnumValue("1494")lidkoping(14, 1494, "Lidköping"), @XmlEnumValue("1495")skara(14, 1495, "Skara"), @XmlEnumValue("1496")skovde(14, 1496, "Skövde"), @XmlEnumValue("1497")hjo(14, 1497, "Hjo"), @XmlEnumValue("1498")tidaholm(14, 1498, "Tidaholm"), @XmlEnumValue("1499")falkoping(14, 1499, "Falköping"), // Värmland municipalities @XmlEnumValue("1715")kil(17, 1715, "Kil"), @XmlEnumValue("1730")eda(17, 1730, "Eda"), @XmlEnumValue("1737")torsby(17, 1737, "Torsby"), @XmlEnumValue("1760")storfors(17, 1760, "Storfors"), @XmlEnumValue("1761")hammaro(17, 1761, "Hammarö"), @XmlEnumValue("1762")munkfors(17, 1762, "Munkfors"), @XmlEnumValue("1763")forshaga(17, 1763, "Forshaga"), @XmlEnumValue("1764")grums(17, 1764, "Grums"), @XmlEnumValue("1765")arjang(17, 1765, "Årjäng"), @XmlEnumValue("1766")sunne(17, 1766, "Sunne"), @XmlEnumValue("1780")karlstad(17, 1780, "Karlstad"), @XmlEnumValue("1781")kristinehamn(17, 1781, "Kristinehamn"), @XmlEnumValue("1782")filipstad(17, 1782, "Filipstad"), @XmlEnumValue("1783")hagfors(17, 1783, "Hagfors"), @XmlEnumValue("1784")arvika(17, 1784, "Arvika"), @XmlEnumValue("1785")saffle(17, 1785, "Säffle"), // Örebro municipalities @XmlEnumValue("1814")lekeberg(18, 1814, "Lekeberg"), @XmlEnumValue("1860")laxa(18, 1860, "Laxå"), @XmlEnumValue("1861")hallsberg(18, 1861, "Hallsberg"), @XmlEnumValue("1862")degerfors(18, 1862, "Degerfors"), @XmlEnumValue("1863")hallefors(18, 1863, "Hällefors"), @XmlEnumValue("1864")ljusnarsberg(18, 1864, "Ljusnarsberg"), @XmlEnumValue("1880")orebro(18, 1880, "Örebro"), @XmlEnumValue("1881")kumla(18, 1881, "Kumla"), @XmlEnumValue("1882")askersund(18, 1882, "Askersund"), @XmlEnumValue("1883")karlskoga(18, 1883, "Karlskoga"), @XmlEnumValue("1884")nora(18, 1884, "Nora"), @XmlEnumValue("1885")lindesberg(18, 1885, "Lindesberg"), // Västmanland municipalities @XmlEnumValue("1904")skinskatteberg(19, 1904, "Skinnskatteberg"), @XmlEnumValue("1907")surahammar(19, 1907, "Surahammar"), @XmlEnumValue("1960")kungsor(19, 1960, "Kungsör"), @XmlEnumValue("1961")hallstahammar(19, 1961, "Hallstahammar"), @XmlEnumValue("1962")norberg(19, 1962, "Norberg"), @XmlEnumValue("1980")vasteras(19, 1980, "Västerås"), @XmlEnumValue("1981")sala(19, 1981, "Sala"), @XmlEnumValue("1982")fagersta(19, 1982, "Fagersta"), @XmlEnumValue("1983")koping(19, 1983, "Köping"), @XmlEnumValue("1984")arboga(19, 1984, "Arboga"), // Dalarna municipalities @XmlEnumValue("2021")vansbro(20, 2021, "Vansbro"), @XmlEnumValue("2023")malung_salen(20, 2023, "Malung-Sälen"), @XmlEnumValue("2026")gagnef(20, 2026, "Gagnef"), @XmlEnumValue("2029")leksand(20, 2029, "Leksand"), @XmlEnumValue("2031")rattvik(20, 2031, "Rättvik"), @XmlEnumValue("2034")orsa(20, 2034, "Orsa"), @XmlEnumValue("2039")alvdalen(20, 2039, "Älvdalen"), @XmlEnumValue("2061")smedjebacken(20, 2061, "Smedjebacken"), @XmlEnumValue("2062")mora(20, 2062, "Mora"), @XmlEnumValue("2080")falun(20, 2080, "Falun"), @XmlEnumValue("2081")borlange(20, 2081, "Borlänge"), @XmlEnumValue("2082")sater(20, 2082, "Säter"), @XmlEnumValue("2083")hedemora(20, 2083, "Hedemora"), @XmlEnumValue("2084")avesta(20, 2084, "Avesta"), @XmlEnumValue("2085")ludvika(20, 2085, "Ludvika"), // Gävleborg municipalities @XmlEnumValue("2101")ockelbo(21, 2101, "Ockelbo"), @XmlEnumValue("2104")hofors(21, 2104, "Hofors"), @XmlEnumValue("2121")ovanaker(21, 2121, "Ovanåker"), @XmlEnumValue("2132")nordanstig(21, 2132, "Nordanstig"), @XmlEnumValue("2161")ljusdal(21, 2161, "Ljusdal"), @XmlEnumValue("2180")gavle(21, 2180, "Gävle"), @XmlEnumValue("2181")sandviken(21, 2181, "Sandviken"), @XmlEnumValue("2182")soderhamn(21, 2182, "Söderhamn"), @XmlEnumValue("2183")bollnas(21, 2183, "Bollnäs"), @XmlEnumValue("2184")hudiksvall(21, 2184, "Hudiksvall"), // Västernorrland municipalities @XmlEnumValue("2260")ange(22, 2260, "Ånge"), @XmlEnumValue("2262")timra(22, 2262, "Timrå"), @XmlEnumValue("2280")harnosand(22, 2280, "Härnösand"), @XmlEnumValue("2280")sundsvall(22, 2281, "Sundsvall"), @XmlEnumValue("2282")kramfors(22, 2282, "Kramfors"), @XmlEnumValue("2283")solleftea(22, 2283, "Sollefteå"), @XmlEnumValue("2283")ornskoldsvik(22, 2284, "Örnsköldsvik"), // Jämtland municipalities @XmlEnumValue("2303")ragunda(23, 2303, "Ragunda"), @XmlEnumValue("2305")bracke(23, 2305, "Bräcke"), @XmlEnumValue("2319")krokom(23, 2309, "Krokom"), @XmlEnumValue("2313")stromsund(23, 2313, "Strömsund"), @XmlEnumValue("2321")are(23, 2321, "Åre"), @XmlEnumValue("2326")berg(23, 2326, "Berg"), @XmlEnumValue("2361")harjedalen(23, 2361, "Härjedalen"), @XmlEnumValue("2380")ostersund(23, 2380, "Östersund"), // Västerbotten municipalities @XmlEnumValue("2401")nordmaling(24, 2401, "Nordmaling"), @XmlEnumValue("2403")bjurholm(24, 2403, "Bjurholm"), @XmlEnumValue("2404")vindeln(24, 2404, "Vindeln"), @XmlEnumValue("2409")robertsfors(24, 2409, "Robertsfors"), @XmlEnumValue("2417")nordsjo(24, 2417, "Norsjö"), @XmlEnumValue("2418")mala(24, 2418, "Malå"), @XmlEnumValue("2421")storuman(24, 2421, "Storuman"), @XmlEnumValue("2422")sorsele(24, 2422, "Sorsele"), @XmlEnumValue("2425")dorotea(24, 2425, "Dorotea"), @XmlEnumValue("2460")vannas(24, 2460, "Vännäs"), @XmlEnumValue("2462")vilhelmina(24, 2462, "Vilhelmina"), @XmlEnumValue("2463")asele(24, 2463, "Åsele"), @XmlEnumValue("2480")umea(24, 2480, "Umeå"), @XmlEnumValue("2481")lycksele(24, 2481, "Lycksele"), @XmlEnumValue("2482")skelleftea(24, 2482, "Skellefteå"), // Norrbotten municipalities @XmlEnumValue("2505")arvidsjaur(25, 2505, "Arvidsjaur"), @XmlEnumValue("2506")arjeplog(25, 2506, "Arjeplog"), @XmlEnumValue("2510")jokkmokk(25, 2510, "Jokkmokk"), @XmlEnumValue("2513")overkalix(25, 2513, "Överkalix"), @XmlEnumValue("2514")kalix(25, 2514, "Kalix"), @XmlEnumValue("2518")overtornea(25, 2518, "Övertorneå"), @XmlEnumValue("2521")pajala(25, 2521, "Pajala"), @XmlEnumValue("2523")gallivare(25, 2523, "Gällivare"), @XmlEnumValue("2560")alvsbyn(25, 2560, "Älvsbyn"), @XmlEnumValue("2580")lulea(25, 2580, "Luleå"), @XmlEnumValue("2581")pitea(25, 2581, "Piteå"), @XmlEnumValue("2582")boden(25, 2582, "Boden"), @XmlEnumValue("2583")haparanda(25, 2583, "Haparanda"), @XmlEnumValue("2584")kiruna(25, 2584, "Kiruna"); // Internal state private static final DecimalFormat FOUR_DIGIT_FORMAT = new DecimalFormat("####"); private int municipalityId; private County county; private String municipalityName; Municipality(final int countyId, final int municipalityId, final String municipalityName) { // Assign internal state this.municipalityId = municipalityId; this.municipalityName = municipalityName; // Synthesize derived state this.county = County.getCountyById(countyId); } /** * @return The county of this Municipality. */ public County getCounty() { return county; } /** * @return The name of this Municipality. */ public String getMunicipalityName() { return municipalityName; } /** * @return The Municipality ID of this Municipality. */ public int getMunicipalityId() { return municipalityId; } /** * @return The 4-digit municipality ID as a String. */ public String get4DigitMunicipalityId() { return FOUR_DIGIT_FORMAT.format(municipalityId); } /** * Acquires all municipalities within the supplied County. * * @param county The non-null county for which all Municipalities should be retrieved. * @return A SortedSet containing the Municipalities within the supplied County. */ public static SortedSet getMunicipalitiesIn(final County county) { // Check sanity Validate.notNull(county, "Cannot handle null 'county' argument."); // Find all Municipalities within the supplied county. final SortedSet toReturn = new TreeSet(); for (Municipality current : values()) { if (current.getCounty() == county) { toReturn.add(current); } } // All done. return toReturn; } }Regions.java000066400000000000000000000024401351100213400430670ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/enumspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SomewhatNamedPerson; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.util.Set; import java.util.TreeSet; /** * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(namespace = SomewhatNamedPerson.NAMESPACE) @XmlType(namespace = SomewhatNamedPerson.NAMESPACE, propOrder = {"counties", "municipalities"}) @XmlAccessorType(XmlAccessType.FIELD) public class Regions { @XmlElementWrapper @XmlElement(name = "county") private Set counties; @XmlElementWrapper @XmlElement(name = "municipality") private Set municipalities; public Regions() { this.counties = new TreeSet(); this.municipalities = new TreeSet(); } public Set getCounties() { return counties; } public Set getMunicipalities() { return municipalities; } } XsdAnnotationProcessorAndEnumsTest.java000066400000000000000000000070121351100213400504450ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/enumspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.enums; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.AbstractSourceCodeAwareNodeProcessingTest; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.JavaDocRenderer; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.NoAuthorJavaDocRenderer; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.SomewhatNamedPerson; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.XsdAnnotationProcessor; import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xmlunit.builder.DiffBuilder; import org.xmlunit.diff.Diff; import se.jguru.shared.algorithms.api.resources.PropertyResources; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author Lennart Jörelid, jGuru Europe AB */ public class XsdAnnotationProcessorAndEnumsTest extends AbstractSourceCodeAwareNodeProcessingTest { // Shared state private JavaDocRenderer renderer = new NoAuthorJavaDocRenderer(); @Test public void validateGeneratedXmlForEnums() throws Exception { // Assemble final String expected = PropertyResources.readFully( "testdata/schemageneration/javadoc/expectedRawExampleEnumHolder.xml" ); final ExampleEnumHolder exampleEnumHolder = new ExampleEnumHolder(); exampleEnumHolder.getCoins().addAll( Arrays.asList( AmericanCoin.values() ) ); exampleEnumHolder.getFoodPreferences().addAll( Arrays.asList( FoodPreference.values() ) ); final StringWriter out = new StringWriter(); // Act final JAXBContext context = JAXBContext.newInstance( FoodPreference.class, ExampleEnumHolder.class ); final Marshaller marshaller = context.createMarshaller(); marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true ); marshaller.setProperty( Marshaller.JAXB_ENCODING, "UTF-8" ); marshaller.marshal( exampleEnumHolder, out ); out.close(); // Assert final Diff diff = DiffBuilder.compare( expected ).withTest( out.toString() ).ignoreWhitespace().ignoreComments().build(); Assert.assertFalse( diff.hasDifferences() ); // XmlTestUtils.compareXmlIgnoringWhitespace( expected, out.toString() ); } @Test public void validateHandlingXmlElementWrapperDocumentation() throws Exception { // Assmeble final Document document = namespace2DocumentMap.get( SomewhatNamedPerson.NAMESPACE ); final Node rootNode = document.getFirstChild(); final XsdAnnotationProcessor unitUnderTest = new XsdAnnotationProcessor( docs, renderer ); // Act process( rootNode, true, unitUnderTest ); // Assert final String processed = printDocument( document ); System.out.println( "Got: " + processed ); // Act // Assert } /** * {@inheritDoc} */ @SuppressWarnings( "unchecked" ) @Override protected List> getJaxbAnnotatedClassesForJaxbContext() { final List> toReturn = new ArrayList>(); for ( Class current : Arrays.asList( FoodPreference.class, ExampleEnumHolder.class, AmericanCoin.class ) ) { toReturn.add( current ); } return toReturn; } } wrappers/000077500000000000000000000000001351100213400413325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadocExampleXmlWapperUsingJavaBeanAccessors.java000066400000000000000000000022101351100213400516670ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/wrapperspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * @author Lennart Jörelid, jGuru Europe AB */ public class ExampleXmlWapperUsingJavaBeanAccessors implements Serializable { private List strings; private SortedSet integerSet; public ExampleXmlWapperUsingJavaBeanAccessors() { this.strings = new ArrayList(); this.integerSet = new TreeSet(); } /** * JavaBean getter for a List containing some strings. */ @XmlElementWrapper(name = "foobar") @XmlElement(name = "aString") public List getStrings() { return strings; } /** * JavaBean getter for a SortedSet containing Integers. */ @XmlElementWrapper @XmlElement(name = "anInteger") public SortedSet getIntegerSet() { return integerSet; } } ExampleXmlWrapper.java000066400000000000000000000027551351100213400456230ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/javadoc/wrapperspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * Trivial transport object type for collections. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(namespace = "http://jaxb.mojohaus.org/wrappers") @XmlType(namespace = "http://jaxb.mojohaus.org/wrappers", propOrder = {"strings", "integerSet"}) @XmlAccessorType(XmlAccessType.FIELD) public class ExampleXmlWrapper implements Serializable { /** * List containing some strings. */ @XmlElementWrapper(name = "foobar") @XmlElement(name = "aString") private List strings; /** * SortedSet containing Integers. */ @XmlElementWrapper @XmlElement(name = "anInteger") private SortedSet integerSet; public ExampleXmlWrapper() { this.strings = new ArrayList(); this.integerSet = new TreeSet(); } public List getStrings() { return strings; } public SortedSet getIntegerSet() { return integerSet; } } schemaenhancement/000077500000000000000000000000001351100213400415265ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessingChangeFilenameProcessorTest.java000066400000000000000000000063111351100213400477600ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.DebugNodeProcessor; import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import java.io.StringReader; import java.util.List; import java.util.Map; import java.util.TreeMap; /** @author Lennart Jörelid */ public class ChangeFilenameProcessorTest { @Test public void validateAcceptCriteria() { // Assemble final String oldFileName = "foo"; final String newFileName = "bar"; final String xmlStream = getXmlDocumentSample(oldFileName); final String namespaceToBeRelocated = "http://another/namespace"; final Map namespaceUriToNewFilenameMap = new TreeMap(); namespaceUriToNewFilenameMap.put(namespaceToBeRelocated, newFileName); final ChangeFilenameProcessor unitUnderTest = new ChangeFilenameProcessor(namespaceUriToNewFilenameMap); final DebugNodeProcessor debugNodeProcessor = new DebugNodeProcessor(unitUnderTest); // Act final Document document = XsdGeneratorHelper.parseXmlStream(new StringReader(xmlStream)); XsdGeneratorHelper.process(document.getFirstChild(), true, debugNodeProcessor); // Assert final List acceptedNodes = debugNodeProcessor.getAcceptedNodes(); Assert.assertEquals(1, acceptedNodes.size()); Assert.assertEquals("schemaLocation", acceptedNodes.get(0).getNodeName()); Assert.assertEquals(newFileName, acceptedNodes.get(0).getNodeValue()); } // // Private helpers // private String getXmlDocumentSample(String fileName) { return "\n" + "\n" + "\n" + " \n" + " \n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; } }ChangeNamespacePrefixProcessorTest.java000066400000000000000000000104771351100213400513220ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; import org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper; import org.codehaus.mojo.jaxb2.schemageneration.postprocessing.DebugNodeProcessor; import org.junit.Assert; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import java.io.StringReader; import java.util.List; /** * @author Lennart Jörelid */ public class ChangeNamespacePrefixProcessorTest { @Test public void validateAcceptCriteria() { // Assemble final String oldNamespacePrefix = "oldNamespacePrefix"; final String newNamespacePrefix = "newNamespacePrefix"; final String namespaceURI = "http://another/namespace"; final String xmlStream = getXmlDocumentSample( oldNamespacePrefix, namespaceURI ); final ChangeNamespacePrefixProcessor unitUnderTest = new ChangeNamespacePrefixProcessor( oldNamespacePrefix, newNamespacePrefix ); final DebugNodeProcessor debugNodeProcessor = new DebugNodeProcessor( unitUnderTest ); // Act final Document document = XsdGeneratorHelper.parseXmlStream(new StringReader(xmlStream)); XsdGeneratorHelper.process(document.getFirstChild(), true, debugNodeProcessor); // Assert final List acceptedNodes = debugNodeProcessor.getAcceptedNodes(); Assert.assertEquals( 3, acceptedNodes.size() ); // Note that the DebugNodeProcessor acquires the node *before* it is actually // processed - implying that the nodeName is not yet changed. Node namespaceDefinitionAttribute = acceptedNodes.get( 0 ); Assert.assertEquals( "xmlns:" + oldNamespacePrefix, namespaceDefinitionAttribute.getNodeName() ); Assert.assertEquals( namespaceURI, namespaceDefinitionAttribute.getNodeValue() ); Node elementReferenceAttribute = acceptedNodes.get( 1 ); Assert.assertEquals( "ref", elementReferenceAttribute.getNodeName() ); Assert.assertEquals( newNamespacePrefix + ":aRequiredElementInAnotherNamespace", elementReferenceAttribute.getNodeValue() ); Node extensionAttribute = acceptedNodes.get( 2 ); Assert.assertEquals( "base", extensionAttribute.getNodeName() ); Assert.assertEquals( newNamespacePrefix + ":aBaseType", extensionAttribute.getNodeValue() ); } // // Private helpers // private String getXmlDocumentSample( String namespacePrefix, String namespaceURI ) { return "\n" + "\n" + "\n" + " \n" + "\n" + " \n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; } }SimpleNamespaceResolverTest.java000066400000000000000000000142431351100213400500250ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; import org.codehaus.plexus.util.FileUtils; import org.junit.Assert; import org.junit.Test; import javax.xml.XMLConstants; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @author Lennart Jörelid */ public class SimpleNamespaceResolverTest { public static final String SCHEMA_DIR = "/org/codehaus/mojo/jaxb2/helpers/"; private File getSchemaFile(String resource) { return FileUtils.toFile(this.getClass().getResource(resource)); } @Test public void validateCollectingSchemaInfoForSingleNamespaceSchemaFile() { // Assemble final String schemaFile = "yetAnotherSchema.xsd"; final File resolvedSchemaFile = getSchemaFile(SCHEMA_DIR + schemaFile); final SimpleNamespaceResolver unitUnderTest = new SimpleNamespaceResolver(resolvedSchemaFile); // Act final Map namespaceURI2PrefixMap = unitUnderTest.getNamespaceURI2PrefixMap(); // Assert Assert.assertEquals(schemaFile, unitUnderTest.getSourceFilename()); Assert.assertEquals("http://yet/another/namespace", unitUnderTest.getLocalNamespaceURI()); Assert.assertEquals(1, namespaceURI2PrefixMap.size()); Assert.assertEquals("xs", namespaceURI2PrefixMap.get(XMLConstants.W3C_XML_SCHEMA_NS_URI)); Assert.assertEquals(XMLConstants.W3C_XML_SCHEMA_NS_URI, unitUnderTest.getNamespaceURI("xs")); } @Test public void validateCollectingSchemaInfoForMultipleNamespaceSchemaFile() { // Assemble final String schemaFile = "anotherSchema.xsd"; final SimpleNamespaceResolver unitUnderTest = new SimpleNamespaceResolver(getSchemaFile(SCHEMA_DIR + schemaFile)); // Act final Map namespaceURI2PrefixMap = unitUnderTest.getNamespaceURI2PrefixMap(); // Assert Assert.assertEquals(schemaFile, unitUnderTest.getSourceFilename()); Assert.assertEquals("http://another/namespace", unitUnderTest.getLocalNamespaceURI()); Assert.assertEquals(3, namespaceURI2PrefixMap.size()); Assert.assertEquals("xs", namespaceURI2PrefixMap.get(XMLConstants.W3C_XML_SCHEMA_NS_URI)); Assert.assertEquals("yetAnother", namespaceURI2PrefixMap.get("http://yet/another/namespace")); Assert.assertEquals("some", namespaceURI2PrefixMap.get("http://some/namespace")); for (String current : namespaceURI2PrefixMap.keySet()) { final String currentPrefix = namespaceURI2PrefixMap.get(current); Assert.assertEquals(currentPrefix, unitUnderTest.getPrefix(current)); } } @Test(expected = IllegalArgumentException.class) public void validateExceptionOnEmptyRelativePathToXmlFile() { // Assemble final String incorrectEmpty = ""; // Act & Assert new SimpleNamespaceResolver(getSchemaFile(incorrectEmpty)); Assert.fail( "Creating a SimpleNamespaceResolver with empty argument " + "should yield an IllegalArgumentException."); } @Test public void validateExceptionOnNonexistentXmlSchemaFile() { // Assemble final String nonExistentPath = "this/file/does/not/exist.xml"; final File nonExistent = new File(nonExistentPath); // Act & Assert try { new SimpleNamespaceResolver(nonExistent); Assert.fail("Creating a SimpleNamespaceResolver connected to a nonexistent file " + "should yield an IllegalArgumentException."); } catch (IllegalArgumentException e) { // Expected } catch (Exception e) { Assert.fail("Expected IllegalArgumentException, but received [" + e.getClass().getName() + "]"); } } @Test public void validateJaxbNamespaceResolverComplianceInThrowingExceptionOnNullNamespaceResolverArguments() { // Assemble final String schemaFile = "yetAnotherSchema.xsd"; final SimpleNamespaceResolver unitUnderTest = new SimpleNamespaceResolver(getSchemaFile(SCHEMA_DIR + schemaFile)); final String incorrectNull = null; // Act & Assert try { unitUnderTest.getPrefix(incorrectNull); Assert.fail("Running getPrefix with a null argument should yield an IllegalArgumentException."); } catch (IllegalArgumentException e) { // Expected } catch (Exception e) { Assert.fail("Expected IllegalArgumentException, but received [" + e.getClass().getName() + "]"); } try { unitUnderTest.getNamespaceURI(incorrectNull); Assert.fail("Running getNamespaceURI with a null argument should yield an IllegalArgumentException."); } catch (IllegalArgumentException e) { // Expected } catch (Exception e) { Assert.fail("Expected IllegalArgumentException, but received [" + e.getClass().getName() + "]"); } try { unitUnderTest.getPrefixes(incorrectNull); Assert.fail("Running getPrefixes with a null argument should yield an IllegalArgumentException."); } catch (IllegalArgumentException e) { // Expected } catch (Exception e) { Assert.fail("Expected IllegalArgumentException, but received [" + e.getClass().getName() + "]"); } } @Test public void validatePrefixesIterator() { // Assemble final String schemaFile = "yetAnotherSchema.xsd"; final SimpleNamespaceResolver unitUnderTest = new SimpleNamespaceResolver(getSchemaFile(SCHEMA_DIR + schemaFile)); // Act List prefixesList = new ArrayList(); for (Iterator it = unitUnderTest.getPrefixes(XMLConstants.W3C_XML_SCHEMA_NS_URI); it.hasNext(); ) { prefixesList.add(it.next()); } // Assert Assert.assertEquals(1, prefixesList.size()); Assert.assertEquals("xs", prefixesList.get(0)); } }TransformSchemaTest.java000066400000000000000000000020431351100213400463240ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; import org.junit.Test; /** * @author Lennart Jörelid */ public class TransformSchemaTest { // Shared state private static final String URI = "http://www.mithlond.se/foo/bar"; private static final String PREFIX = "bar"; private static final String FILENAME = "mithlondBar"; private static final TransformSchema unitUnderTest = new TransformSchema(URI, PREFIX, FILENAME); @Test(expected = IllegalArgumentException.class) public void validateExceptionOnEmptyToFileArgument() { // Act & Assert unitUnderTest.setToFile(""); } @Test(expected = IllegalArgumentException.class) public void validateExceptionOnEmptyToPrefixArgument() { // Act & Assert unitUnderTest.setToPrefix(""); } @Test(expected = IllegalArgumentException.class) public void validateExceptionOnEmptyUriArgument() { // Act & Assert unitUnderTest.setUri(""); } } XmlNameAnnotatedClassWithFieldAccess.java000066400000000000000000000025251351100213400515040ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/schemageneration/postprocessing/schemaenhancementpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * This is a XmlType and name-switched class using Field access. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement @XmlType(name = "AnnotatedXmlNameAnnotatedClassWithFieldAccessTypeName") @XmlAccessorType(XmlAccessType.FIELD) public class XmlNameAnnotatedClassWithFieldAccess { /** * This is a string field. */ @XmlElement(name = "annotatedStringField") private String stringField; /** * This is an integer field. */ @XmlAttribute(name = "annotatedIntegerField") private Integer integerField; public XmlNameAnnotatedClassWithFieldAccess() { } public XmlNameAnnotatedClassWithFieldAccess(final String stringField, final Integer integerField) { this.stringField = stringField; this.integerField = integerField; } public String getStringField() { return stringField; } public Integer getIntegerField() { return integerField; } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/000077500000000000000000000000001351100213400310075ustar00rootroot00000000000000FileSystemUtilitiesTest.java000066400000000000000000000473621351100213400364270ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/sharedpackage org.codehaus.mojo.jaxb2.shared; import org.codehaus.mojo.jaxb2.AbstractJaxbMojo; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.shared.filters.Filter; import org.codehaus.mojo.jaxb2.shared.filters.Filters; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import se.jguru.shared.algorithms.api.resources.PropertyResources; import java.io.File; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB * @since 2.0 */ public class FileSystemUtilitiesTest { // Shared state private File fsUtilitiesDirectory; private File canonicalsDirectory; private File testFile1; private File testFile2; private File srcTestResources; private BufferingLog log; @Before public void setupSharedState() { this.log = new BufferingLog( BufferingLog.LogLevel.DEBUG ); final URL fsUtilitiesDirUrl = getClass().getClassLoader().getResource( "testdata/shared/filesystemutilities" ); fsUtilitiesDirectory = new File( fsUtilitiesDirUrl.getPath() ); canonicalsDirectory = new File( fsUtilitiesDirectory, "canonicals" ); Assert.assertTrue( FileSystemUtilities.EXISTING_DIRECTORY.accept( fsUtilitiesDirectory ) ); Assert.assertTrue( FileSystemUtilities.EXISTING_DIRECTORY.accept( canonicalsDirectory ) ); testFile2 = new File( fsUtilitiesDirectory, "TestFile2.txt" ); testFile1 = new File( canonicalsDirectory, "TestFile1.txt" ); Assert.assertTrue( FileSystemUtilities.EXISTING_FILE.accept( testFile1 ) ); Assert.assertTrue( FileSystemUtilities.EXISTING_FILE.accept( testFile2 ) ); final URL testdataDir = getClass().getClassLoader().getResource( "testdata" ); srcTestResources = new File( testdataDir.getPath() ).getParentFile(); Assert.assertTrue( FileSystemUtilities.EXISTING_DIRECTORY.accept( srcTestResources ) ); } @Test public void validateGettingUrlForFile() { // Assemble final String relativePath = "testdata/shared/filesystemutilities/canonicals/TestFile1.txt"; final URL expected = getClass().getClassLoader().getResource( relativePath ); // Act final URL result = FileSystemUtilities.getUrlFor( testFile1 ); // Assert Assert.assertEquals( expected, result ); } @Test public void validateCanonicalFileAndPath() { // Assemble final File unitUnderTest = new File( canonicalsDirectory, "../TestFile2.txt" ); // Act final String cPath1 = FileSystemUtilities.getCanonicalPath( unitUnderTest ); final String cPath2 = FileSystemUtilities.getCanonicalPath( testFile2 ); final File cFile1 = FileSystemUtilities.getCanonicalFile( unitUnderTest ); final File cFile2 = FileSystemUtilities.getCanonicalFile( testFile2 ); // Assert Assert.assertEquals( cPath1, cPath2 ); Assert.assertEquals( cFile1, cFile2 ); } @Test( expected = NullPointerException.class ) public void validateExceptionOnGettingExistingFileWithRelativePathAndNullBasedir() { // Assemble final String relativePath = "testdata/shared/filesystemutilities/TestFile2.txt"; final File incorrectNullBaseDir = null; // Act & Assert FileSystemUtilities.getExistingFile( relativePath, incorrectNullBaseDir ); } @Test public void validateSimplifiedFileExistenceRetrieval() { // Assemble final String absolutePath = FileSystemUtilities.getCanonicalPath( testFile2 ); final String aNonExistentAbsolutePath = new File( canonicalsDirectory, "nonExistent.txt" ).getAbsolutePath(); final String relativePath = "canonicals/TestFile1.txt"; final String aNonExistentRelativePath = "canonicals/doesNotExist.pdf"; // Act final File absoluteFile = FileSystemUtilities.getExistingFile( absolutePath, null ); final File nonExistentAbsoluteFile = FileSystemUtilities.getExistingFile( aNonExistentAbsolutePath, null ); final File relativeFile = FileSystemUtilities.getExistingFile( relativePath, fsUtilitiesDirectory ); final File nonExistentRelativeFile = FileSystemUtilities.getExistingFile( aNonExistentRelativePath, fsUtilitiesDirectory ); // Assert Assert.assertNotNull( absoluteFile ); Assert.assertNull( nonExistentAbsoluteFile ); Assert.assertNotNull( relativeFile ); Assert.assertNull( nonExistentRelativeFile ); } @Test( expected = NullPointerException.class ) public void validateExceptionOnNullFileListWhenResolvingFilesAndRemovingExclusions() { // Assemble final List incorrectNullFileList = null; // Act & Assert FileSystemUtilities.resolveRecursively( incorrectNullFileList, null, log ); } @Test public void validateFilteredDirectoryListingUsingIncludeFilters() { // Assemble final URL aDirURL = getClass().getClassLoader().getResource( "testdata/shared/filefilter/exclusion" ); final File dir = new File( aDirURL.getPath() ); final List> textFiles = PatternFileFilter.createIncludeFilterList( log, "\\.txt" ); final List> xmlFiles = PatternFileFilter.createIncludeFilterList( log, "\\.xml" ); final List> allFiles = PatternFileFilter.createIncludeFilterList( log, "\\.*" ); // Act & Assert Assert.assertEquals( 2, FileSystemUtilities.listFiles( dir, allFiles, log ).size() ); final List textFilesList = FileSystemUtilities.listFiles( dir, textFiles, log ); Assert.assertEquals( 1, textFilesList.size() ); Assert.assertEquals( "TextFile.txt", textFilesList.get( 0 ).getName() ); final List xmlFilesList = FileSystemUtilities.listFiles( dir, xmlFiles, log ); Assert.assertEquals( 1, xmlFilesList.size() ); Assert.assertEquals( "AnXmlFile.xml", xmlFilesList.get( 0 ).getName() ); } @Test @SuppressWarnings( "all" ) public void validateFilteredDirectoryListingUsingExcludeFilters() { // Assemble final URL aDirURL = getClass().getClassLoader().getResource( "testdata/shared/filefilter/exclusion" ); final File exclusionDir = new File( aDirURL.getPath() ); final List> noTextFiles = PatternFileFilter.createExcludeFilterList( log, "\\.txt" ); final List> noXmlFiles = PatternFileFilter.createExcludeFilterList( log, "\\.xml" ); final List> noFiles = PatternFileFilter.createExcludeFilterList( log, "\\.*" ); // Act & Assert Assert.assertEquals( 0, FileSystemUtilities.listFiles( exclusionDir, noFiles, log ).size() ); final List noXmlFilesList = FileSystemUtilities.listFiles( exclusionDir, noXmlFiles, log ); Assert.assertEquals( 1, noXmlFilesList.size() ); Assert.assertEquals( "TextFile.txt", noXmlFilesList.get( 0 ).getName() ); final List noTextFilesList = FileSystemUtilities.listFiles( exclusionDir, noTextFiles, log ); Assert.assertEquals( 1, noTextFilesList.size() ); Assert.assertEquals( "AnXmlFile.xml", noTextFilesList.get( 0 ).getName() ); } @Test public void validateResolveRecursively() { // Assemble final URL fileFilterDirUrl = getClass().getClassLoader().getResource( "testdata/shared/filefilter" ); final File fileFilterDir = new File( fileFilterDirUrl.getPath() ); final List fileList = new ArrayList(); fileList.add( fsUtilitiesDirectory ); fileList.add( fileFilterDir ); final List> noTextFilesPattern = PatternFileFilter.createIncludeFilterList( log, "\\.txt" ); // Act final List result = FileSystemUtilities.resolveRecursively( fileList, noTextFilesPattern, log ); // Assert Assert.assertEquals( 1, result.size() ); Assert.assertEquals( "AnXmlFile.xml", result.get( 0 ).getName() ); } @Test public void validateDefaultExclusionsIncludeDotDirectories() { // Assemble final URL fileFilterDirUrl = getClass().getClassLoader().getResource( "testdata/shared/standard/exclusions" ); final File fileFilterDir = new File( fileFilterDirUrl.getPath() ); final List fileList = new ArrayList(); fileList.add( fileFilterDir ); final List> standardExcludeFilters = AbstractJaxbMojo.STANDARD_EXCLUDE_FILTERS; Filters.initialize( log, standardExcludeFilters ); // Act final List result = FileSystemUtilities.resolveRecursively( fileList, standardExcludeFilters, log ); // Assert final StringBuilder builder = new StringBuilder(); for ( File current : result ) { builder.append( current.getPath() + ", " ); } Assert.assertEquals( 1, result.size() ); Assert.assertEquals( "someFile.log", result.get( 0 ).getName() ); } @Test public void validateResolvingFilesAndRemovingExclusions() { // Assemble final URL fileFilterDirUrl = getClass().getClassLoader().getResource( "testdata/shared/filefilter" ); final File fileFilterDir = new File( fileFilterDirUrl.getPath() ); final File depsPropertiesFile = new File( fileFilterDir.getParentFile(), "deps1.properties" ); final List fileList = new ArrayList(); fileList.add( fsUtilitiesDirectory ); fileList.add( fileFilterDir ); fileList.add( depsPropertiesFile ); final List> matchTextFiles = PatternFileFilter.createIncludeFilterList( log, "\\.txt" ); final List> matchXmlFiles = PatternFileFilter.createIncludeFilterList( log, "\\.xml" ); final List> matchNonexistentFiles = PatternFileFilter.createIncludeFilterList( log, "\\.nonexistent" ); // Act final List noTextFiles = FileSystemUtilities.resolveRecursively( fileList, matchTextFiles, log ); final List noXmlFiles = FileSystemUtilities.resolveRecursively( fileList, matchXmlFiles, log ); final List allFiles = FileSystemUtilities.resolveRecursively( fileList, matchNonexistentFiles, log ); final List noFilterFiles = FileSystemUtilities.resolveRecursively( fileList, null, log ); // Assert Assert.assertEquals( 2, noTextFiles.size() ); Assert.assertEquals( 4, noXmlFiles.size() ); Assert.assertEquals( 5, allFiles.size() ); Assert.assertEquals( 5, noFilterFiles.size() ); final List canonicalPathsForExplicitlyAddedFiles = getRelativeCanonicalPaths( noFilterFiles, depsPropertiesFile.getParentFile() ); Assert.assertTrue( canonicalPathsForExplicitlyAddedFiles.contains( "/deps1.properties" ) ); final List canonicalPathsForNoTextFiles = getRelativeCanonicalPaths( noTextFiles, depsPropertiesFile.getParentFile() ); Assert.assertTrue( canonicalPathsForNoTextFiles.contains( "/deps1.properties" ) ); Assert.assertTrue( canonicalPathsForNoTextFiles.contains( "/filefilter/exclusion/AnXmlFile.xml" ) ); final List canonicalPathsForNoXmlFiles = getRelativeCanonicalPaths( noXmlFiles, depsPropertiesFile.getParentFile() ); Assert.assertTrue( canonicalPathsForNoXmlFiles.contains( "/deps1.properties" ) ); Assert.assertTrue( canonicalPathsForNoXmlFiles.contains( "/filefilter/exclusion/TextFile.txt" ) ); Assert.assertTrue( canonicalPathsForNoXmlFiles.contains( "/filesystemutilities/TestFile2.txt" ) ); Assert.assertTrue( canonicalPathsForNoXmlFiles.contains( "/filesystemutilities/canonicals/TestFile1.txt" ) ); final List canonicalPathsForAllFiles = getRelativeCanonicalPaths( allFiles, depsPropertiesFile.getParentFile() ); Assert.assertTrue( canonicalPathsForAllFiles.contains( "/deps1.properties" ) ); Assert.assertTrue( canonicalPathsForAllFiles.contains( "/filefilter/exclusion/TextFile.txt" ) ); Assert.assertTrue( canonicalPathsForAllFiles.contains( "/filesystemutilities/TestFile2.txt" ) ); Assert.assertTrue( canonicalPathsForAllFiles.contains( "/filesystemutilities/canonicals/TestFile1.txt" ) ); Assert.assertTrue( canonicalPathsForAllFiles.contains( "/filefilter/exclusion/AnXmlFile.xml" ) ); } @Test public void validateBufferingLog() { // Assemble final BufferingLog log = new BufferingLog( BufferingLog.LogLevel.INFO ); // Act log.debug( "debug" ); log.info( "info", new NullPointerException( "Blah!" ) ); log.warn( "warn" ); log.error( new IllegalArgumentException( "Gnat" ) ); // Assert final SortedMap logBuffer = log.getLogBuffer(); final List keys = new ArrayList( logBuffer.keySet() ); Assert.assertEquals( 3, keys.size() ); Assert.assertEquals( "000: (INFO) info", keys.get( 0 ) ); Assert.assertEquals( "001: (WARN) warn", keys.get( 1 ) ); Assert.assertEquals( "002: (ERROR) ", keys.get( 2 ) ); Assert.assertEquals( "Blah!", logBuffer.get( keys.get( 0 ) ).getMessage() ); Assert.assertNull( logBuffer.get( keys.get( 1 ) ) ); Assert.assertTrue( logBuffer.get( keys.get( 2 ) ) instanceof IllegalArgumentException ); } @Test public void validateFilteringFiles() { // Assemble final BufferingLog log = new BufferingLog( BufferingLog.LogLevel.DEBUG ); final URL sharedDirUrl = getClass().getClassLoader().getResource( "testdata/shared" ); final File basedir = new File( sharedDirUrl.getPath() ); final List> excludeTextFiles = PatternFileFilter.createIncludeFilterList( log, "txt" ); // Act final List result = FileSystemUtilities.filterFiles( basedir, null, "filefilter/exclusion", log, "testFiles", excludeTextFiles ); // Assert Assert.assertEquals( 1, result.size() ); final File theFile = result.get( 0 ); Assert.assertEquals( "AnXmlFile.xml", theFile.getName() ); } @Test public void validateFilterFilesWithSuppliedSourcesAndExcludePatterns() { // Assemble final BufferingLog log = new BufferingLog( BufferingLog.LogLevel.DEBUG ); final List sources = Arrays.asList( "filefilter/exclusion/AnXmlFile.xml", "filefilter/exclusion/TextFile.txt" ); final URL sharedDirUrl = getClass().getClassLoader().getResource( "testdata/shared" ); final File basedir = new File( sharedDirUrl.getPath() ); final List> excludeTextFiles = PatternFileFilter.createIncludeFilterList( log, "\\.txt" ); // Act final List result = FileSystemUtilities.filterFiles( basedir, sources, "filefilter/exclusion", log, "testFiles", excludeTextFiles ); // Assert Assert.assertEquals( 1, result.size() ); final File theFile = result.get( 0 ); Assert.assertEquals( "AnXmlFile.xml", theFile.getName() ); } @Test public void validateGettingFileForJar() { // Assemble final String jarPath = "testdata/shared/nazgul-tools-validation-aspect-4.0.1.jar"; final URL resource = getClass().getClassLoader().getResource( jarPath ); Assert.assertNotNull( resource ); // Act final File jarFile = FileSystemUtilities.getFileFor( resource, "UTF-8" ); final String relativized = FileSystemUtilities.relativize( jarFile.getPath(), srcTestResources, true ); // Assert Assert.assertTrue( jarFile.exists() ); Assert.assertTrue( jarFile.isFile() ); Assert.assertEquals( jarPath.replace( "/", File.separator ), relativized ); } @Test public void validateGettingFileForClassURL() { // Assemble final URL streamingDhURL = PropertyResources.class.getProtectionDomain().getCodeSource().getLocation(); Assert.assertNotNull( streamingDhURL ); // Act final File jarFile = FileSystemUtilities.getFileFor( streamingDhURL, "UTF-8" ); // Assert Assert.assertTrue( jarFile.exists() ); Assert.assertTrue( jarFile.isFile() ); } @Test public void validateGettingFileForClassResourceURL() { // Assemble final String classResource = PropertyResources.class.getName().replace( ".", "/" ) + ".class"; final URL resource = getClass().getClassLoader().getResource( classResource ); Assert.assertNotNull( resource ); // Act final File jarFile = FileSystemUtilities.getFileFor( resource, "UTF-8" ); // Assert Assert.assertTrue( jarFile.exists() ); Assert.assertTrue( jarFile.isFile() ); } @Test public void validateUrlEncodingAndDecoding() throws Exception { // Assemble final String resourcePath = "testdata/shared/urlhandling/file with spaces.txt"; final URL dirUrl = getClass().getClassLoader().getResource( resourcePath ); Assert.assertNotNull( dirUrl ); // Act final String normalizedPath = dirUrl.toURI().normalize().toURL().getPath(); final String decoded = URLDecoder.decode( normalizedPath, "UTF-8" ); // Assert Assert.assertTrue( normalizedPath.endsWith( "file%20with%20spaces.txt" ) ); Assert.assertTrue( decoded.endsWith( "file with spaces.txt" ) ); } @Test public void validateRelativizingPaths() throws Exception { // Assemble final String path = "/project/backend/foobar/my-schema.xsd"; final SortedMap parentDir2Expected = new TreeMap<>(); parentDir2Expected.put( "/", "project/backend/foobar/my-schema.xsd" ); parentDir2Expected.put( "", "project/backend/foobar/my-schema.xsd" ); parentDir2Expected.put( "/project", "backend/foobar/my-schema.xsd" ); parentDir2Expected.put( "/not/a/path", "project/backend/foobar/my-schema.xsd" ); parentDir2Expected.put( "/project/", "backend/foobar/my-schema.xsd" ); // Act & Assert for ( Map.Entry current : parentDir2Expected.entrySet() ) { final String expectedMessage = "Given parent dir [" + current.getKey() + "], expected [" + current.getValue() + "] from [" + path + "] but found: "; final String result = FileSystemUtilities.relativize( path, new File( current.getKey() ), true ); Assert.assertEquals( expectedMessage + result, current.getValue(), result ); } } // // Private helpers // private List getRelativeCanonicalPaths( final List fileList, final File cutoff ) { final String cutoffPath = FileSystemUtilities.getCanonicalPath( cutoff ).replace( File.separator, "/" ); final List toReturn = new ArrayList(); for ( File current : fileList ) { final String canPath = FileSystemUtilities.getCanonicalPath( current ).replace( File.separator, "/" ); if ( !canPath.startsWith( cutoffPath ) ) { throw new IllegalArgumentException( "Illegal cutoff provided. Cutoff: [" + cutoffPath + "] must be a parent to CanonicalPath [" + canPath + "]" ); } toReturn.add( canPath.substring( cutoffPath.length() ) ); } Collections.sort( toReturn ); return toReturn; } } ValidateTest.java000066400000000000000000000041151351100213400341650ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/sharedpackage org.codehaus.mojo.jaxb2.shared; import org.junit.Assert; import org.junit.Test; /** * @author Lennart Jörelid */ public class ValidateTest { @Test public void validateErrorMessageOnSuppliedArgumentName() { // Assemble final String argumentName = "fooBar"; final String expectedMsg = "Cannot handle empty 'fooBar' argument."; // Act & Assert try { Validate.notEmpty("", argumentName); } catch (IllegalArgumentException expected) { Assert.assertEquals(expectedMsg, expected.getMessage()); } catch (Exception e) { Assert.fail("Expected IllegalArgumentException, but got " + e); } } @Test public void validateErrorMessageOnNullArgumentName() { // Act & Assert try { Validate.notEmpty("", null); } catch (IllegalArgumentException expected) { Assert.assertEquals("Cannot handle empty argument.", expected.getMessage()); } catch (Exception e) { Assert.fail("Expected IllegalArgumentException, but got " + e); } } @Test public void validateErrorMessageOnNullArgument() { // Assemble final String argumentName = "fooBar"; final String expectedMsg = "Cannot handle null 'fooBar' argument."; // Act & Assert try { Validate.notNull(null, argumentName); } catch (NullPointerException expected) { Assert.assertEquals(expectedMsg, expected.getMessage()); } catch (Exception e) { Assert.fail("Expected IllegalArgumentException, but got " + e); } } @Test public void validateErrorMessageOnNullArgumentWithNullName() { // Act & Assert try { Validate.notNull(null, null); } catch (NullPointerException expected) { Assert.assertEquals("Cannot handle null argument.", expected.getMessage()); } catch (Exception e) { Assert.fail("Expected IllegalArgumentException, but got " + e); } } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/arguments/000077500000000000000000000000001351100213400330145ustar00rootroot00000000000000ArgumentBuilderTest.java000066400000000000000000000046761351100213400375460ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/argumentspackage org.codehaus.mojo.jaxb2.shared.arguments; import org.junit.Assert; import org.junit.Test; /** * @author Lennart Jörelid */ public class ArgumentBuilderTest { @Test(expected = IllegalArgumentException.class) public void validateExceptionOnAddingAllWhitespaceFlag() { // Assemble final ArgumentBuilder unitUnderTest = new ArgumentBuilder(); // Act & Assert unitUnderTest.withFlag(true, " "); } @Test(expected = IllegalArgumentException.class) public void validateExceptionOnAddingFlagContainingWhitespace() { // Assemble final ArgumentBuilder unitUnderTest = new ArgumentBuilder(); // Act & Assert unitUnderTest.withFlag(true, "foo bar"); } @Test(expected = NullPointerException.class) public void validateExceptionOnAddingNullFlag() { // Assemble final ArgumentBuilder unitUnderTest = new ArgumentBuilder(); // Act & Assert unitUnderTest.withFlag(true, null); } @Test(expected = NullPointerException.class) public void validateExceptionOnAddingNullNamedArgument() { // Assemble final ArgumentBuilder unitUnderTest = new ArgumentBuilder(); // Act & Assert unitUnderTest.withNamedArgument(null, "irrelevant"); } @Test public void validateArgumentOrder() { // Assemble final ArgumentBuilder unitUnderTest = new ArgumentBuilder(); // Act final String[] result = unitUnderTest .withFlag(true, "flag1") .withFlag(true, "-flag2") .build(); // Assert Assert.assertEquals(2, result.length); Assert.assertEquals("-flag1", result[0]); Assert.assertEquals("-flag2", result[1]); } @Test public void validateMixedArguments() { // Assemble final ArgumentBuilder unitUnderTest = new ArgumentBuilder(); // Act final String[] result = unitUnderTest .withNamedArgument(true, "name1", "value1") .withFlag(true, "flag2") .withNamedArgument(false, "name3", "value3") .withFlag(false, "flag4") .build(); // Assert Assert.assertEquals(3, result.length); Assert.assertEquals("-name1", result[0]); Assert.assertEquals("value1", result[1]); Assert.assertEquals("-flag2", result[2]); } } classloader/000077500000000000000000000000001351100213400332245ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/sharedThreadContextClassLoaderBuilderTest.java000066400000000000000000000174301351100213400431340ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/classloaderpackage org.codehaus.mojo.jaxb2.shared.classloader; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.JavaVersion; import org.codehaus.mojo.jaxb2.shared.environment.classloading.ThreadContextClassLoaderBuilder; import org.codehaus.mojo.jaxb2.shared.environment.classloading.ThreadContextClassLoaderHolder; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.io.File; import java.net.URL; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * @author Lennart Jörelid, jGuru Europe AB */ public class ThreadContextClassLoaderBuilderTest { // Shared state private ThreadContextClassLoaderHolder holder; private URL extraClassLoaderDirURL; private File extraClassLoaderDirFile; private BufferingLog log; private ClassLoader originalClassLoader; private String encoding = "UTF-8"; @Before public void setupSharedState() { log = new BufferingLog( BufferingLog.LogLevel.DEBUG ); final String extraPath = "testdata/shared/classloader"; extraClassLoaderDirURL = getClass().getClassLoader().getResource( extraPath ); Assert.assertNotNull( extraClassLoaderDirURL ); extraClassLoaderDirFile = new File( extraClassLoaderDirURL.getPath() ); Assert.assertTrue( extraClassLoaderDirFile.exists() && extraClassLoaderDirFile.isDirectory() ); // Stash the original ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); } @After public void teardownSharedState() { if ( holder != null ) { holder.restoreClassLoaderAndReleaseThread(); } else { Thread.currentThread().setContextClassLoader( originalClassLoader ); } } @Test public void validateAddingURLsToThreadContextClassLoader() throws Exception { // Assemble final int numExpectedResources = JavaVersion.isJdk8OrLower() ? 3 : 6; holder = ThreadContextClassLoaderBuilder.createFor( originalClassLoader, log, encoding ).addURL( extraClassLoaderDirURL ).buildAndSet(); // Act final ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); final List resources = Collections.list( ctxClassLoader.getResources( "" ) ); for ( int i = 0; i < resources.size(); i++ ) { System.out.println( " Resource [" + i + "]: " + resources.get( i ).toString() ); } /* * Expected result for JDK 8: * ========================== * Resource [0]: file:[pathToJaxbProject]/target/test-classes/ * Resource [1]: file:[pathToJaxbProject]/target/classes/ * Resource [2]: file:[pathToJaxbProject]/target/test-classes/testdata/shared/classloader/ * * Expected result for JDK 11 (assuming jakarta.xml.bind-api version 2.3.2): * ========================================================================= * Resource [0]: file:[pathToJaxbProject]/target/test-classes/ * Resource [1]: file:[pathToJaxbProject]/target/classes/ * Resource [2]: jar:file:[pathToM2Repo]/jakarta/xml/bind/jakarta.xml.bind-api/2.3.2/jakarta.xml.bind-api-2.3.2.jar!/META-INF/versions/9/ * Resource [3]: jar:file:[pathToM2Repo]/repository/org/glassfish/jaxb/jaxb-xjc/2.3.2/jaxb-xjc-2.3.2.jar!/META-INF/versions/9/ * Resource [4]: jar:file:[pathToM2Repo]/repository/org/glassfish/jaxb/jaxb-jxc/2.3.2/jaxb-jxc-2.3.2.jar!/META-INF/versions/9/ * Resource [5]: file:[pathToJaxbProject]/target/test-classes/testdata/shared/classloader/ */ /* * [3]: jar:file:/Users/lj/.m2/repository/jakarta/xml/bind/jakarta.xml.bind-api/2.3.2/jakarta.xml.bind-api-2.3.2.jar!/META-INF/versions/9/ * [5]: jar:file:/Users/lj/.m2/repository/javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar!/META-INF/versions/9/ */ // Assert Assert.assertEquals( "Expected [" + numExpectedResources + "] resources but got [" + resources.size() + "]: " + getNewLineSeparated( resources ), numExpectedResources, resources.size() ); // validateContains(resources, "target/classes"); validateContains( resources, "target/test-classes" ); validateContains( resources, "target/test-classes/testdata/shared/classloader" ); for ( URL current : resources ) { if ( current.getProtocol().equalsIgnoreCase( "file" ) ) { final File aFile = new File( current.getPath() ); Assert.assertTrue( aFile.exists() && aFile.isDirectory() ); } else if ( current.getProtocol().equalsIgnoreCase( "jar" ) ) { // This happens in JDK 9 Assert.assertTrue( current.toString().contains( "!/META-INF/versions/" ) ); } } } @Test public void validateResourceAccessInAugmentedClassLoader() { // Assemble holder = ThreadContextClassLoaderBuilder.createFor( originalClassLoader, log, encoding ).addURL( extraClassLoaderDirURL ).buildAndSet(); // Act final ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); final URL immediateResource = ctxClassLoader.getResource( "ImmediateTestResource.txt" ); final URL subResource = ctxClassLoader.getResource( "subdirectory/SubdirectoryTestResource.txt" ); // Assert Assert.assertNotNull( immediateResource ); Assert.assertNotNull( subResource ); final File immediateFile = new File( immediateResource.getPath() ); final File subFile = new File( subResource.getPath() ); Assert.assertTrue( immediateFile.exists() && immediateFile.isFile() ); Assert.assertTrue( subFile.exists() && subFile.isFile() ); } @Test public void validateLoadingResourcesInJars() { // Assemble final File theJar = new File( extraClassLoaderDirFile, "jarSubDirectory/aJarWithResources.jar" ); holder = ThreadContextClassLoaderBuilder.createFor( originalClassLoader, log, encoding ).addPath( FileSystemUtilities.getCanonicalPath( theJar ) ).buildAndSet(); // Act final ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); final URL containedTopLevelResource = ctxClassLoader.getResource( "ContainedFileResource.txt" ); final URL containedSubLevelResource = ctxClassLoader.getResource( "internalSubDir/SubContainedResource.txt" ); // Assert Assert.assertNotNull( containedTopLevelResource ); Assert.assertNotNull( containedSubLevelResource ); } // // Private helpers // private String getNewLineSeparated( final List resources ) { final StringBuilder toReturn = new StringBuilder(); final AtomicInteger index = new AtomicInteger(); for ( URL current : resources ) { final String urlIndex = "[" + index.getAndIncrement() + "]: "; toReturn.append(urlIndex).append( current.toString() ).append( "\n" ); } // All Done. final String fullString = toReturn.toString(); return fullString.substring( 0, fullString.length() - 2 ); } private void validateContains( final List resources, final String snippet ) { for ( URL current : resources ) { if ( current.toString().contains( snippet ) ) { return; } } Assert.fail( "Snippet [" + snippet + "] was not found within URL resources." ); } } environment/000077500000000000000000000000001351100213400332745ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/sharedlocale/000077500000000000000000000000001351100213400345335ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/environmentLocaleFacetTest.java000066400000000000000000000053331351100213400404040ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/environment/localepackage org.codehaus.mojo.jaxb2.shared.environment.locale; import org.apache.maven.plugin.MojoExecutionException; import org.codehaus.mojo.jaxb2.BufferingLog; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.util.Locale; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public class LocaleFacetTest { // Shared state private static final Locale FRENCH_LOCALE = Locale.FRENCH; private Locale defaultLocale; private BufferingLog log; @Before public void setupSharedState() { this.log = new BufferingLog(BufferingLog.LogLevel.DEBUG); defaultLocale = Locale.getDefault(); } @Test public void validateLocaleParsing() throws MojoExecutionException { // Assemble final String frenchLocaleString = "fr"; // Act & Assert final LocaleFacet facet = LocaleFacet.createFor(frenchLocaleString, log); Assert.assertEquals(defaultLocale, Locale.getDefault()); facet.setup(); Assert.assertEquals(FRENCH_LOCALE.toString(), Locale.getDefault().toString()); facet.restore(); Assert.assertEquals(defaultLocale.toString(), Locale.getDefault().toString()); } @Test public void validateOptimalLocaleFindingIgnoringScripts() throws MojoExecutionException { // Assemble final SortedMap lang2Locale = new TreeMap(); for (Locale current : Locale.getAvailableLocales()) { lang2Locale.put(current.toLanguageTag(), current); } // Act & Assert for (Map.Entry current : lang2Locale.entrySet()) { final String language = current.getValue().getLanguage(); final String country = current.getValue().getCountry(); final String variant = current.getValue().getVariant(); final String script = current.getValue().getScript(); // Ignore Locales with Scripts. if (script == null) { Assert.assertSame(Locale.forLanguageTag(current.getValue().toLanguageTag()), LocaleFacet.findOptimumLocale(language, country, variant)); } } } @Test(expected = MojoExecutionException.class) public void validateExceptionOnIncorrectLocaleString() throws MojoExecutionException { // Act & Assert LocaleFacet.createFor("not,a,properly,formatted,locale_string", log); } @Test public void validateNoExceptionOnUnknownLocaleString() throws MojoExecutionException { // Act & Assert LocaleFacet.createFor("thisIsAnUnknownLocale", log); } } sysprops/000077500000000000000000000000001351100213400351765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/environmentSystemPropertySaveEnvironmentFacetTest.java000066400000000000000000000065501351100213400457470ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/environment/syspropspackage org.codehaus.mojo.jaxb2.shared.environment.sysprops; import static org.junit.Assert.assertEquals; import org.codehaus.mojo.jaxb2.BufferingLog; import org.junit.Test; public class SystemPropertySaveEnvironmentFacetTest { private static final String PROPERTY_KEY_NOT_SAVED = "some.other.property"; private static final String PROPERTY_KEY_SAVED = "http.proxyHost"; private SystemPropertySaveEnvironmentFacet createAndSetupFacet() { final BufferingLog log = new BufferingLog(BufferingLog.LogLevel.DEBUG); final SystemPropertySaveEnvironmentFacet facet = new SystemPropertySaveEnvironmentFacet(PROPERTY_KEY_SAVED, log); facet.setup(); return facet; } @Test public void onRestoreAfterChangeOriginalOtherPropertyValueIsNotRestored() { // Given: System.setProperty(PROPERTY_KEY_NOT_SAVED, "originalValue"); final SystemPropertySaveEnvironmentFacet facet = createAndSetupFacet(); // When: System.setProperty(PROPERTY_KEY_NOT_SAVED, "changedValue"); facet.restore(); // Then: assertEquals("changedValue", System.getProperty(PROPERTY_KEY_NOT_SAVED)); } @Test public void onRestoreAfterChangeOriginalSavedPropertyValueIsRestored() { // Given: System.setProperty(PROPERTY_KEY_SAVED, "originalValue"); final SystemPropertySaveEnvironmentFacet facet = createAndSetupFacet(); // When: System.setProperty(PROPERTY_KEY_SAVED, "changedValue"); facet.restore(); // Then: assertEquals("originalValue", System.getProperty(PROPERTY_KEY_SAVED)); } @Test public void onRestoreAfterClearOriginalOtherPropertyValueIsNotRestored() { // Given: System.setProperty(PROPERTY_KEY_NOT_SAVED, "originalValue"); final SystemPropertySaveEnvironmentFacet facet = createAndSetupFacet(); // When: System.clearProperty(PROPERTY_KEY_NOT_SAVED); facet.restore(); // Then: assertEquals(null, System.getProperty(PROPERTY_KEY_NOT_SAVED)); } @Test public void onRestoreAfterClearOriginalSavedPropertyValueIsRestored() { // Given: System.setProperty(PROPERTY_KEY_SAVED, "originalValue"); final SystemPropertySaveEnvironmentFacet facet = createAndSetupFacet(); // When: System.clearProperty(PROPERTY_KEY_SAVED); facet.restore(); // Then: assertEquals("originalValue", System.getProperty(PROPERTY_KEY_SAVED)); } @Test public void onRestoreAfterSetOriginallyUnsetOtherPropertyIsNotCleared() { // Given: System.clearProperty(PROPERTY_KEY_NOT_SAVED); final SystemPropertySaveEnvironmentFacet facet = createAndSetupFacet(); // When: System.setProperty(PROPERTY_KEY_NOT_SAVED, "changedValue"); facet.restore(); // Then: assertEquals("changedValue", System.getProperty(PROPERTY_KEY_NOT_SAVED)); } @Test public void onRestoreAfterSetOriginallyUnsetSavedPropertyIsCleared() { // Given: System.clearProperty(PROPERTY_KEY_SAVED); final SystemPropertySaveEnvironmentFacet facet = createAndSetupFacet(); // When: System.setProperty(PROPERTY_KEY_SAVED, "changedValue"); facet.restore(); // Then: assertEquals(null, System.getProperty(PROPERTY_KEY_SAVED)); } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filters/000077500000000000000000000000001351100213400324575ustar00rootroot00000000000000DebugFilter.java000066400000000000000000000020021351100213400354310ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filterspackage org.codehaus.mojo.jaxb2.shared.filters; import java.util.SortedMap; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public class DebugFilter extends AbstractFilter { // Shared state private final Object lock = new Object(); public SortedMap invocations = new TreeMap(); public DebugFilter(final boolean processNullValues) { super(); setProcessNullValues(processNullValues); } @Override protected boolean onNullCandidate() { addInvocation(null); return super.onNullCandidate(); } @Override protected boolean onCandidate(final String nonNullCandidate) { addInvocation(nonNullCandidate); return false; } // // Internal state // private void addInvocation(final String candidate) { synchronized (lock) { invocations.put(1 + invocations.size(), candidate); } } } FiltersTest.java000066400000000000000000000075771351100213400355330ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filterspackage org.codehaus.mojo.jaxb2.shared.filters; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * @author Lennart Jörelid, jGuru Europe AB */ public class FiltersTest { // Shared data private File exclusionDir; private File anXmlFile; private File aTextFile; @Before public void setupSharedState() { final String dirPath = "testdata/shared/filefilter/exclusion"; final URL resource = getClass().getClassLoader().getResource(dirPath); exclusionDir = new File(resource.getPath()); // Create files this.anXmlFile = new File(exclusionDir, "AnXmlFile.xml"); this.aTextFile = new File(exclusionDir, "TextFile.txt"); Assert.assertTrue(anXmlFile.exists() && anXmlFile.isFile()); Assert.assertTrue(aTextFile.exists() && aTextFile.isFile()); } @Test public void validateMatchAtLeastOnce() { // Assemble final BufferingLog log = new BufferingLog(BufferingLog.LogLevel.DEBUG); final List> excludeFilters = PatternFileFilter.createExcludeFilterList(log, "txt"); final List> includeFilters = PatternFileFilter.createIncludeFilterList(log, "txt"); final List> noFilters = new ArrayList>(); // Act & Assert Assert.assertFalse(Filters.matchAtLeastOnce(anXmlFile, noFilters)); Assert.assertFalse(Filters.matchAtLeastOnce(aTextFile, noFilters)); Assert.assertTrue(Filters.matchAtLeastOnce(anXmlFile, excludeFilters)); Assert.assertFalse(Filters.matchAtLeastOnce(aTextFile, excludeFilters)); Assert.assertFalse(Filters.matchAtLeastOnce(anXmlFile, includeFilters)); Assert.assertTrue(Filters.matchAtLeastOnce(aTextFile, includeFilters)); } @Test public void validateNoMatches() { // Assemble final BufferingLog log = new BufferingLog(BufferingLog.LogLevel.DEBUG); final List> excludeFilters = PatternFileFilter.createExcludeFilterList(log, "txt"); final List> includeFilters = PatternFileFilter.createIncludeFilterList(log, "txt"); final List> noFilters = new ArrayList>(); // Act & Assert Assert.assertTrue(Filters.noFilterMatches(anXmlFile, noFilters)); Assert.assertTrue(Filters.noFilterMatches(aTextFile, noFilters)); Assert.assertFalse(Filters.noFilterMatches(anXmlFile, excludeFilters)); Assert.assertTrue(Filters.noFilterMatches(aTextFile, excludeFilters)); Assert.assertTrue(Filters.noFilterMatches(anXmlFile, includeFilters)); Assert.assertFalse(Filters.noFilterMatches(aTextFile, includeFilters)); } @Test public void validateRejectIfMatchedAtLeastOnce() { // Assemble final BufferingLog log = new BufferingLog(BufferingLog.LogLevel.DEBUG); final List> excludeFilters = PatternFileFilter.createExcludeFilterList(log, "txt"); final List> includeFilters = PatternFileFilter.createIncludeFilterList(log, "txt"); final List> noFilters = new ArrayList>(); // Act & Assert Assert.assertFalse(Filters.rejectAtLeastOnce(anXmlFile, noFilters)); Assert.assertFalse(Filters.rejectAtLeastOnce(aTextFile, noFilters)); Assert.assertFalse(Filters.rejectAtLeastOnce(anXmlFile, excludeFilters)); Assert.assertTrue(Filters.rejectAtLeastOnce(aTextFile, excludeFilters)); Assert.assertTrue(Filters.rejectAtLeastOnce(anXmlFile, includeFilters)); Assert.assertFalse(Filters.rejectAtLeastOnce(aTextFile, includeFilters)); } } PackageFilterInclusionTest.java000066400000000000000000000110261351100213400404700ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filterspackage org.codehaus.mojo.jaxb2.shared.filters; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.codehaus.mojo.jaxb2.shared.filters.pattern.FileFilterAdapter; import org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; import static java.io.File.separator; /** * @author Lennart Jörelid, jGuru Europe AB */ public class PackageFilterInclusionTest { // Shared state private File baseDirectory; private File srcMainJavaDir; private BufferingLog log; private String contextRoot; @Before public void setupSharedState() { log = new BufferingLog(BufferingLog.LogLevel.DEBUG); String basedir = System.getProperty("basedir"); if (basedir == null) { baseDirectory = new File(getClass().getClassLoader().getResource("logback-test.xml").getPath()) .getParentFile() .getParentFile() .getParentFile(); } else { baseDirectory = new File(basedir); } Assert.assertTrue(baseDirectory.exists() && baseDirectory.isDirectory()); // Find all source files under the src/main/java directory. srcMainJavaDir = new File(basedir, "src/main/java"); Assert.assertTrue(srcMainJavaDir.exists() && srcMainJavaDir.isDirectory()); contextRoot = FileSystemUtilities.relativize(srcMainJavaDir.getPath(), baseDirectory, true); } @Test public void validateExcludingPackageInfoFiles() { // Assemble final String rootPackagePath = contextRoot + separator + "org" + separator + "codehaus" + separator + "mojo" + separator + "jaxb2"; final String excludeFilenamePattern = "package-info\\.java"; final List> excludedFilesIdentifierFilter = PatternFileFilter .createIncludeFilterList(log, excludeFilenamePattern); // Act final List sourceFiles = FileSystemUtilities.resolveRecursively(Collections.singletonList(srcMainJavaDir), excludedFilesIdentifierFilter, log); final SortedMap path2FileMap = mapFiles(sourceFiles); // Assert for (String current : path2FileMap.keySet()) { final String relativePath = current.startsWith(baseDirectory.getPath()) ? current.substring(baseDirectory.getPath().length() + 1) : current; Assert.assertTrue("Path " + relativePath + " did not start with the root package path " + rootPackagePath, relativePath.startsWith(rootPackagePath)); Assert.assertTrue("Path " + current + " was a package-info.java file.", !current.contains("package-info")); } } @Test public void validateIncludingSubTrees() { // Assemble final String locationPackageDirName = separator + "location" + separator; final FileFilterAdapter includeFilter = new FileFilterAdapter(new FileFilter() { @Override public boolean accept(final File pathname) { return pathname.getPath().contains(locationPackageDirName); } }); includeFilter.initialize(log); final List allSourceFiles = FileSystemUtilities.resolveRecursively( Collections.singletonList(srcMainJavaDir), new ArrayList>(), log); // Act final List result = FileSystemUtilities.filterFiles(allSourceFiles, includeFilter, log); final SortedMap path2FileMap = mapFiles(result); // Assert Assert.assertTrue(result.size() > 1); for (String current : path2FileMap.keySet()) { Assert.assertTrue("Path " + current + " contained disallowed pattern " + locationPackageDirName, current.contains(locationPackageDirName)); } } // // Private helpers // private SortedMap mapFiles(final List files) { final SortedMap toReturn = new TreeMap(); for (File current : files) { toReturn.put(current.getPath(), current); } return toReturn; } } T_AbstractFilterTest.java000066400000000000000000000037231351100213400373040ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filterspackage org.codehaus.mojo.jaxb2.shared.filters; import org.codehaus.mojo.jaxb2.BufferingLog; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.util.SortedMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public class T_AbstractFilterTest { // Shared state private BufferingLog log; @Before public void setupSharedState() { log = new BufferingLog(); } @Test(expected = IllegalStateException.class) public void validateExceptionOnNotInitializingFilterBeforeFirstCall() { // Assemble final DebugFilter unitUnderTest = new DebugFilter(false); // Act & Assert unitUnderTest.accept("foobar!"); } @Test public void validateCallOrderIfNotProcessingNulls() { // Assemble final DebugFilter unitUnderTest = new DebugFilter(false); // Act unitUnderTest.initialize(log); unitUnderTest.accept("first"); unitUnderTest.accept(null); unitUnderTest.accept("third"); // Assert final SortedMap invocations = unitUnderTest.invocations; Assert.assertEquals(2, invocations.size()); Assert.assertEquals("first", invocations.get(1)); Assert.assertEquals("third", invocations.get(2)); } @Test public void validateCallOrderIfProcessingNulls() { // Assemble final DebugFilter unitUnderTest = new DebugFilter(true); // Act unitUnderTest.initialize(log); unitUnderTest.accept("first"); unitUnderTest.accept(null); unitUnderTest.accept("third"); // Assert final SortedMap invocations = unitUnderTest.invocations; Assert.assertEquals(3, invocations.size()); Assert.assertEquals("first", invocations.get(1)); Assert.assertEquals(null, invocations.get(2)); Assert.assertEquals("third", invocations.get(3)); } } pattern/000077500000000000000000000000001351100213400340555ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filtersAbstractPatternFilterTest.java000066400000000000000000000041101351100213400420230ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; import org.codehaus.mojo.jaxb2.BufferingLog; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.junit.Assert; import org.junit.Before; import java.io.File; import java.net.URL; import java.util.Map; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public abstract class AbstractPatternFilterTest { // Shared state protected File exclusionDirectory; protected File[] fileList; protected BufferingLog log; private String defaultExclusionDirectory; public AbstractPatternFilterTest(final String defaultExclusionDirectory) { this.defaultExclusionDirectory = defaultExclusionDirectory; } public AbstractPatternFilterTest() { this("testdata/shared/filefilter/exclusion"); } @Before @SuppressWarnings("all") public void setupSharedState() { log = new BufferingLog(BufferingLog.LogLevel.DEBUG); final URL exclusionDirUrl = getClass().getClassLoader().getResource(defaultExclusionDirectory); exclusionDirectory = new File(exclusionDirUrl.getPath()); Assert.assertTrue(FileSystemUtilities.EXISTING_DIRECTORY.accept(exclusionDirectory)); fileList = exclusionDirectory.listFiles(); for (File current : fileList) { Assert.assertTrue(FileSystemUtilities.EXISTING_FILE.accept(current)); } // Delegate onSetup(); } protected void onSetup() { // Do nothing } protected Map applyFilterAndRetrieveResults(final AbstractPatternFilter unitUnderTest, final T[] candidates, final StringConverter converter) { Map toReturn = new TreeMap(); for (T current : candidates) { toReturn.put(converter.convert(current), unitUnderTest.accept(current)); } return toReturn; } } DebugPatternFilter.java000066400000000000000000000033511351100213400404540ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public class DebugPatternFilter extends AbstractPatternFilter { // Shared state private final Object lock = new Object(); public SortedMap invocations = new TreeMap(); public DebugPatternFilter(final List patterns, final boolean acceptCandidateOnPatternMatch) { super(); setPatterns(patterns); setAcceptCandidateOnPatternMatch(acceptCandidateOnPatternMatch); } public DebugPatternFilter(final boolean processNullValues, final List patterns, final StringConverter converter, final boolean acceptCandidateOnPatternMatch) { super(); setProcessNullValues(processNullValues); setPatterns(patterns); setConverter(converter); setAcceptCandidateOnPatternMatch(acceptCandidateOnPatternMatch); } @Override protected boolean onCandidate(final String nonNullCandidate) { boolean toReturn = super.onCandidate(nonNullCandidate); addInvocation(nonNullCandidate, toReturn); return toReturn; } // // Internal state // private void addInvocation(final String candidate, final boolean result) { synchronized (lock) { final String[] resultStruct = new String[2]; resultStruct[0] = candidate; resultStruct[1] = "" + result; invocations.put(1 + invocations.size(), resultStruct); } } } PatternFileFilterTest.java000066400000000000000000000065531351100213400411540ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; import org.junit.Assert; import org.junit.Test; import java.io.File; import java.util.Arrays; import java.util.List; import java.util.Map; /** * @author Lennart Jörelid, jGuru Europe AB */ public class PatternFileFilterTest extends AbstractPatternFilterTest { // Shared state public static final StringConverter FILENAME_CONVERTER = new StringConverter() { @Override public String convert(final File toConvert) { return toConvert.getName(); } }; /* * fileList contains 2 files: * * testdata/shared/filefilter/exclusion/ATextFile.txt * testdata/shared/filefilter/exclusion/AnXmlFile.xml */ @Test public void validateAcceptNothingOnNullPatterns() { // Assemble final PatternFileFilter unitUnderTest = new PatternFileFilter(null, true); // Act unitUnderTest.initialize(log); final Map result = applyFilterAndRetrieveResults(unitUnderTest, fileList, FILENAME_CONVERTER); // Assert for (Map.Entry current : result.entrySet()) { Assert.assertFalse(current.getValue()); } } @Test public void validateAcceptAllOnNullPatternsForExcludeOperation() { // Assemble final PatternFileFilter unitUnderTest = new PatternFileFilter(false, null, null, FILENAME_CONVERTER, false); // Act unitUnderTest.initialize(log); final Map result = applyFilterAndRetrieveResults(unitUnderTest, fileList, FILENAME_CONVERTER); // Assert for (Map.Entry current : result.entrySet()) { Assert.assertTrue(current.getValue()); } } @Test public void validateExcludingMatchingFiles() { // Assemble final List txtFileSuffixExclusion = Arrays.asList("\\.txt"); final PatternFileFilter unitUnderTest = new PatternFileFilter(txtFileSuffixExclusion, false); unitUnderTest.initialize(log); // Act final Map result = applyFilterAndRetrieveResults(unitUnderTest, fileList, FILENAME_CONVERTER); // Assert Assert.assertTrue(result.get("AnXmlFile.xml")); Assert.assertFalse(result.get("TextFile.txt")); } @Test public void validateExcludingNoFilesOnNonMatchingPattern() { // Assemble final PatternFileFilter unitUnderTest = new PatternFileFilter(Arrays.asList("\\.nonexistent"), false); unitUnderTest.initialize(log); // Act final Map result = applyFilterAndRetrieveResults(unitUnderTest, fileList, FILENAME_CONVERTER); // Assert Assert.assertTrue(result.get("AnXmlFile.xml")); Assert.assertTrue(result.get("TextFile.txt")); } @Test public void validatePatternMatchExclusion() { // Assemble final PatternFileFilter unitUnderTest = new PatternFileFilter(Arrays.asList("\\.*File\\..*"), false); unitUnderTest.initialize(log); // Act final Map result = applyFilterAndRetrieveResults(unitUnderTest, fileList, FILENAME_CONVERTER); // Assert Assert.assertFalse(result.get("AnXmlFile.xml")); Assert.assertFalse(result.get("TextFile.txt")); } } PatternURLFilterTest.java000066400000000000000000000054711351100213400407350ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; import org.codehaus.mojo.jaxb2.shared.FileSystemUtilities; import org.junit.Assert; import org.junit.Test; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.List; import java.util.Map; /** * @author Lennart Jörelid, jGuru Europe AB */ public class PatternURLFilterTest extends AbstractPatternFilterTest { // Shared state private URL[] urlList; /** * {@inheritDoc} */ @Override protected void onSetup() { urlList = new URL[fileList.length]; for (int i = 0; i < fileList.length; i++) { Assert.assertTrue(FileSystemUtilities.EXISTING_FILE.accept(fileList[i])); try { urlList[i] = fileList[i].toURI().normalize().toURL(); } catch (MalformedURLException e) { throw new IllegalStateException("Could not populate urlList", e); } } } @Test(expected = IllegalStateException.class) public void validateExceptionOnNotInitializingFilterBeforeUse() { // Assemble final PatternURLFilter unitUnderTest = new PatternURLFilter(null); // Act & Assert unitUnderTest.accept(urlList[0]); } @Test public void validateAcceptNothingOnNullPatterns() { // Assemble final PatternURLFilter unitUnderTest = new PatternURLFilter(null); // Act unitUnderTest.initialize(log); final Map result = applyFilterAndRetrieveResults(unitUnderTest, urlList, PatternURLFilter.NORMALIZED_URL_CONVERTER); // Assert for (Map.Entry current : result.entrySet()) { Assert.assertFalse(current.getValue()); } } @Test public void validateExcludingMatchingURLs() { // Assemble final String urlProtocol = "file"; final List txtFileSuffixExclusion = Arrays.asList(urlProtocol + ":/" + PatternFileFilter.PATTERN_LETTER_DIGIT_PUNCT + "\\.txt"); final PatternURLFilter unitUnderTest = new PatternURLFilter(txtFileSuffixExclusion); unitUnderTest.setAcceptCandidateOnPatternMatch(false); unitUnderTest.initialize(log); // Act final Map result = applyFilterAndRetrieveResults( unitUnderTest, urlList, PatternURLFilter.NORMALIZED_URL_CONVERTER); // Assert for (Map.Entry current : result.entrySet()) { if (current.getKey().endsWith("xml")) { Assert.assertTrue(result.get(current.getKey())); } else { Assert.assertFalse(result.get(current.getKey())); } } } } T_AbstractPatternFilterTest.java000066400000000000000000000065461351100213400423250ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/filters/patternpackage org.codehaus.mojo.jaxb2.shared.filters.pattern; import org.codehaus.mojo.jaxb2.BufferingLog; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.util.Arrays; import java.util.List; import java.util.SortedMap; /** * @author Lennart Jörelid, jGuru Europe AB */ public class T_AbstractPatternFilterTest { private static final StringConverter UNITY_STRING_CONVERTER = new StringConverter() { @Override public String convert(final String toConvert) { return toConvert; } }; // Shared state private BufferingLog log; @Before public void setupSharedState() { log = new BufferingLog(BufferingLog.LogLevel.DEBUG); } @Test(expected = NullPointerException.class) public void validateExceptionOnNullStringConverter() { // Assemble final boolean processNullValues = false; final List patterns = null; final boolean acceptCandidateOnPatternMatch = true; // Act & Assert new DebugPatternFilter(processNullValues, patterns, null, acceptCandidateOnPatternMatch); } @Test public void validateNoAcceptedResultsWhenProcessingMessagesOnNullFilters() { // Assemble final boolean processNullValues = false; final List patterns = null; final boolean acceptCandidateOnPatternMatch = true; final DebugPatternFilter unitUnderTest = new DebugPatternFilter( processNullValues, patterns, UNITY_STRING_CONVERTER, acceptCandidateOnPatternMatch); // Act unitUnderTest.initialize(log); unitUnderTest.accept("first"); unitUnderTest.accept(null); unitUnderTest.accept("third"); // Assert final SortedMap invocations = unitUnderTest.invocations; Assert.assertEquals(2, invocations.size()); Assert.assertEquals("first", invocations.get(1)[0]); Assert.assertEquals(false, Boolean.parseBoolean(invocations.get(1)[1])); Assert.assertEquals("third", invocations.get(2)[0]); Assert.assertEquals(false, Boolean.parseBoolean(invocations.get(2)[1])); } @Test public void validateAcceptingFilterMessages() { // Assemble final boolean processNullValues = false; final boolean acceptCandidateOnPatternMatch = true; final List patterns = Arrays.asList("f.*t"); // Should match 'first' but not 'third' final DebugPatternFilter unitUnderTest = new DebugPatternFilter( processNullValues, patterns, UNITY_STRING_CONVERTER, acceptCandidateOnPatternMatch); // Act unitUnderTest.initialize(log); unitUnderTest.accept("first"); unitUnderTest.accept(null); unitUnderTest.accept("third"); // Assert final SortedMap invocations = unitUnderTest.invocations; Assert.assertEquals(2, invocations.size()); Assert.assertEquals("first", invocations.get(1)[0]); Assert.assertEquals(true, Boolean.parseBoolean(invocations.get(1)[1])); Assert.assertEquals("third", invocations.get(2)[0]); Assert.assertEquals(false, Boolean.parseBoolean(invocations.get(2)[1])); } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/version/000077500000000000000000000000001351100213400324745ustar00rootroot00000000000000DependencyFileParserTest.java000066400000000000000000000146751351100213400401700ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/java/org/codehaus/mojo/jaxb2/shared/versionpackage org.codehaus.mojo.jaxb2.shared.version; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.net.URL; import java.net.URLClassLoader; import java.util.Collections; import java.util.List; import java.util.SortedMap; /** * @author Lennart Jörelid */ public class DependencyFileParserTest { // Internal state private URL urlToTestJar; private static final String DEPS1_PROPERTYFILE = "/testdata/shared/deps1.properties"; private ClassLoader originalThreadContextClassLoader; @Before public void setupSharedState() throws Exception { // Stash the original ClassLoader originalThreadContextClassLoader = Thread.currentThread().getContextClassLoader(); // Add the local test JAR to the ClassLoader path final String jarPath = "testdata/shared/nazgul-tools-validation-aspect-4.0.1.jar"; final URL extraURL = getClass().getClassLoader().getResource(jarPath); Assert.assertNotNull("No resource found for path [" + jarPath + "]", extraURL); final URLClassLoader decoratedClassLoader = new URLClassLoader( new URL[]{extraURL}, originalThreadContextClassLoader); Assert.assertNotNull("Could not create decorated ClassLoader", decoratedClassLoader); Thread.currentThread().setContextClassLoader(decoratedClassLoader); // Assert that the decorated ClassLoader can load resource within the extraURL JAR. final String internalResourcePath = "META-INF/maven/se.jguru.nazgul.tools.validation.aspect/" + "nazgul-tools-validation-aspect/pom.properties"; final List resourceList = Collections.list(decoratedClassLoader.getResources(internalResourcePath)); Assert.assertNotNull(resourceList); Assert.assertNotEquals(0, resourceList.size()); for (URL current : resourceList) { if (current.getPath().contains("testdata")) { urlToTestJar = current; break; } } Assert.assertNotNull( "Expected resource not found for internal resource path [" + internalResourcePath + "] ", urlToTestJar); } @After public void teardownSharedState() { // Restore the original ClassLoader Thread.currentThread().setContextClassLoader(originalThreadContextClassLoader); } @Test public void validateParsingDependencyPropertiesFile() { // Assemble final URL depsPropResource = getClass().getResource(DEPS1_PROPERTYFILE); // Act final SortedMap versionMap = DependsFileParser.getVersionMap(depsPropResource); // Assert Assert.assertEquals("Wed Nov 19 20:11:15 CET 2014", versionMap.get(DependsFileParser.BUILDTIME_KEY)); Assert.assertEquals("compile", versionMap.get("javax.xml.bind/jaxb-api/scope")); Assert.assertEquals("jar", versionMap.get("javax.xml.bind/jaxb-api/type")); Assert.assertEquals("2.2.11", versionMap.get("javax.xml.bind/jaxb-api/version")); /* for(Map.Entry current : versionMap.entrySet()) { System.out.println(" [" + current.getKey() + "]: " + current.getValue()); } */ } @Test public void validateCreatingDependencyInformationMapFromDependencyPropertiesFile() { // Assemble final String jaxbApiKey = "javax.xml.bind/jaxb-api"; final URL depsPropResource = getClass().getResource(DEPS1_PROPERTYFILE); // Act final SortedMap versionMap = DependsFileParser.getVersionMap(depsPropResource); final SortedMap diMap = DependsFileParser.createDependencyInfoMap(versionMap); // Assert final DependencyInfo dependencyInfo = diMap.get(jaxbApiKey); Assert.assertNotNull(dependencyInfo); Assert.assertEquals("javax.xml.bind", dependencyInfo.getGroupId()); Assert.assertEquals("jaxb-api", dependencyInfo.getArtifactId()); Assert.assertEquals("2.2.11", dependencyInfo.getVersion()); Assert.assertEquals("jar", dependencyInfo.getType()); Assert.assertEquals("compile", dependencyInfo.getScope()); /* for(Map.Entry current : diMap.entrySet()) { System.out.println(" [" + current.getKey() + "]: " + current.getValue()); } */ } @Test public void validateParsingDependencyInformationPackagedInJarFileInClassPath() { // Assemble final String artifactId = "nazgul-tools-validation-aspect"; final String groupId = "se.jguru.nazgul.tools.validation.aspect"; final String slf4jApiKey = "org.slf4j/slf4j-api"; // Act final SortedMap versionMap = DependsFileParser.getVersionMap(artifactId); final SortedMap diMap = DependsFileParser.createDependencyInfoMap(versionMap); // Assert Assert.assertEquals("Mon Oct 06 07:51:23 CEST 2014", versionMap.get(DependsFileParser.BUILDTIME_KEY)); Assert.assertEquals(groupId, versionMap.get(DependsFileParser.OWN_GROUPID_KEY)); Assert.assertEquals(artifactId, versionMap.get(DependsFileParser.OWN_ARTIFACTID_KEY)); Assert.assertEquals("4.0.1", versionMap.get(DependsFileParser.OWN_VERSION_KEY)); final DependencyInfo dependencyInfo = diMap.get(slf4jApiKey); Assert.assertNotNull(dependencyInfo); Assert.assertEquals("org.slf4j", dependencyInfo.getGroupId()); Assert.assertEquals("slf4j-api", dependencyInfo.getArtifactId()); Assert.assertEquals("1.7.7", dependencyInfo.getVersion()); Assert.assertEquals("jar", dependencyInfo.getType()); Assert.assertEquals("compile", dependencyInfo.getScope()); /* for(Map.Entry current : diMap.entrySet()) { System.out.println(" [" + current.getKey() + "]: " + current.getValue()); } */ } @Test(expected = IllegalArgumentException.class) public void validateExceptionOnAttemptingToParseIncorrectlyFormedPropertiesFile() { // Assemble final String resourcePath = "testdata/shared/not_a_dependency.properties"; final URL incorrectResource = Thread.currentThread().getContextClassLoader().getResource(resourcePath); // Act & Assert DependsFileParser.getVersionMap(incorrectResource); } } jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/000077500000000000000000000000001351100213400242765ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/generated/000077500000000000000000000000001351100213400262345ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/generated/schema/000077500000000000000000000000001351100213400274745ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/generated/schema/schema1.xsd000066400000000000000000000004221351100213400315330ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/generated/schema/schema2.xsd000066400000000000000000000016501351100213400315400ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/generated/schema/schema3.xsd000066400000000000000000000020601351100213400315350ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/logback-test.xml000066400000000000000000000012041351100213400273740ustar00rootroot00000000000000 [%c{1}::%M]: %msg%n jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/org/000077500000000000000000000000001351100213400250655ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/org/codehaus/000077500000000000000000000000001351100213400266605ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/org/codehaus/mojo/000077500000000000000000000000001351100213400276245ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/org/codehaus/mojo/jaxb2/000077500000000000000000000000001351100213400306325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/org/codehaus/mojo/jaxb2/helpers/000077500000000000000000000000001351100213400322745ustar00rootroot00000000000000anotherSchema.xsd000066400000000000000000000021601351100213400355150ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/org/codehaus/mojo/jaxb2/helpers someSchema.xsd000066400000000000000000000016441351100213400350260ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/org/codehaus/mojo/jaxb2/helpers yetAnotherSchema.xsd000066400000000000000000000004501351100213400361770ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/org/codehaus/mojo/jaxb2/helpers jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/000077500000000000000000000000001351100213400261075ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/000077500000000000000000000000001351100213400314235ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/000077500000000000000000000000001351100213400330325ustar00rootroot00000000000000annotated/000077500000000000000000000000001351100213400347305ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadocXmlNameAnnotatedClassWithFieldAccess.java000066400000000000000000000024671351100213400447130ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/annotatedpackage testdata.schemageneration.javadoc.annotated; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * This is a XmlType and name-switched class using Field access. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement @XmlType(name = "AnnotatedXmlNameAnnotatedClassWithFieldAccessTypeName") @XmlAccessorType(XmlAccessType.FIELD) public class XmlNameAnnotatedClassWithFieldAccess { /** * This is a string field. */ @XmlElement(name = "annotatedStringField") private String stringField; /** * This is an integer field. */ @XmlAttribute(name = "annotatedIntegerField") private Integer integerField; public XmlNameAnnotatedClassWithFieldAccess() { } public XmlNameAnnotatedClassWithFieldAccess(final String stringField, final Integer integerField) { this.stringField = stringField; this.integerField = integerField; } public String getStringField() { return stringField; } public Integer getIntegerField() { return integerField; } } XmlNameAnnotatedClassWithMethodAccess.java000066400000000000000000000026461351100213400451070ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/annotatedpackage testdata.schemageneration.javadoc.annotated; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * This is a XmlType and name-switched class using Method access. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement @XmlType(name = "AnnotatedXmlNameAnnotatedClassWithMethodAccessTypeName") @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) public class XmlNameAnnotatedClassWithMethodAccess { private String stringField; private Integer integerField; public XmlNameAnnotatedClassWithMethodAccess() { } public XmlNameAnnotatedClassWithMethodAccess(final String stringField, final Integer integerField) { this.stringField = stringField; this.integerField = integerField; } /** * Getter for the stringField. * * @return the stringField value */ @XmlElement(name = "annotatedStringMethod") public String getStringField() { return stringField; } /** * Getter for the integerField. * * @return the integerField value */ @XmlAttribute(name = "annotatedIntegerMethod") public Integer getIntegerField() { return integerField; } } basic/000077500000000000000000000000001351100213400340345ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadocNodeProcessor.java000066400000000000000000000027471351100213400374760ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/basicpackage basic; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.w3c.dom.Node; /** * Processor/visitor pattern specification for DOM Nodes. * * @author Lennart Jörelid * @author Mr. Foo * @see org.w3c.dom.Node */ public interface NodeProcessor { /** * Defines if this visitor should process the provided node. * * @param aNode The DOM node to process. * @return true if the provided Node should be processed by this NodeProcessor. */ boolean accept(Node aNode); /** * Processes the provided DOM Node. * * @param aNode The DOM Node to process. */ void process(Node aNode); }enums/000077500000000000000000000000001351100213400341025ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadocAmericanCoin.java000066400000000000000000000022141351100213400372740ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/enumspackage enums; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlType; /** * Simple enumeration example defining standard US coins. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlType(namespace = "http://gnat.west.se/foods") @XmlEnum(Integer.class) @XmlAccessorType(XmlAccessType.FIELD) public enum AmericanCoin { /** * A Penny, worth 1 cent. */ @XmlEnumValue("1") PENNY(1), /** * A Nickel, worth 5 cents. */ @XmlEnumValue("5") NICKEL(5), /** * A Dime, worth 10 cents. */ @XmlEnumValue("10") DIME(10), /** * A Quarter, worth 25 cents. */ @XmlEnumValue("25") QUARTER(25); // Internal state private int value; AmericanCoin(final int value) { this.value = value; } /** * The value - in cents - of this coin. * * @return the value - in cents - of this coin. */ public int getValue() { return value; } } ExampleEnumHolder.java000066400000000000000000000027761351100213400403370ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/enumspackage enums; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * Trivial transport object type for Enums with different representations. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(namespace = "http://gnat.west.se/foods") @XmlType(namespace = "http://gnat.west.se/foods", propOrder = {"coins", "foodPreferences"}) @XmlAccessorType(XmlAccessType.FIELD) public class ExampleEnumHolder implements Serializable { /** * List containing all AmericanCoin objects. */ @XmlElementWrapper @XmlElement(name = "coin") private List coins; /** * SortedSet containing the FoodPreference objects collected. */ @XmlElementWrapper @XmlElement(name = "preference") private SortedSet foodPreferences; public ExampleEnumHolder() { this.coins = new ArrayList(); this.foodPreferences = new TreeSet(); } public List getCoins() { return coins; } public SortedSet getFoodPreferences() { return foodPreferences; } } FoodPreference.java000066400000000000000000000024651351100213400376420ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/enumspackage enums; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlEnum; /** * Simple enumeration example defining some Food preferences. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlEnum(String.class) @XmlAccessorType(XmlAccessType.FIELD) public enum FoodPreference { /** * No special food preferences; eats everything. */ NONE(true, true), /** * Vegetarian who will not eat meats, but drinks milk. */ LACTO_VEGETARIAN(false, true), /** * Vegan who will neither eat meats nor drink milk. */ VEGAN(false, false); /** * Boolean value indicating if this {@link FoodPreference} eats meats. */ @XmlAttribute private boolean meatEater; /** * Boolean value indicating if this {@link FoodPreference} drinks milk. */ @XmlAttribute boolean milkDrinker; private FoodPreference(final boolean meatEater, final boolean milkDrinker) { this.meatEater = meatEater; this.milkDrinker = milkDrinker; } public boolean isMeatEater() { return meatEater; } public boolean isMilkDrinker() { return milkDrinker; } } expectedTransformedExampleEnumHolder.xsd000066400000000000000000000063521351100213400441350ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/enums Lennart Jörelid, jGuru Europe AB]]> Lennart Jörelid, jGuru Europe AB]]> processedEnumSchema.xsd000066400000000000000000000063331351100213400405640ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/enums rawEnumSchema.xsd000066400000000000000000000031321351100213400373600ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/enums expectedRawExampleEnumHolder.xml000066400000000000000000000006551351100213400412550ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc 1 5 10 25 NONE LACTO_VEGETARIAN VEGAN expectedSemiDocumentedClass.xml000066400000000000000000000015641351100213400411200ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc Lennart Jörelid, jGuru Europe AB]]> expectedTransformedSomewhatNamedPerson.xml000066400000000000000000000025561351100213400433570ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc Lennart Jörelid, jGuru Europe AB (since): Some version.]]> methodbased/000077500000000000000000000000001351100213400352325ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadocExampleXmlWrapperUsingMethodAccess.java000066400000000000000000000027651351100213400450150ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/methodbasedpackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * Another trivial transport object type for collections. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(namespace = "http://jaxb.mojohaus.org/wrappers") @XmlType(namespace = "http://jaxb.mojohaus.org/wrappers", propOrder = {"strings", "integerSet"}) public class ExampleXmlWrapperUsingMethodAccess implements Serializable { private List strings2; private SortedSet integerSet2; public ExampleXmlWrapperUsingMethodAccess() { this.strings2 = new ArrayList(); this.integerSet2 = new TreeSet(); } /** * List containing some strings. */ @XmlElementWrapper(name = "foobar") @XmlElement(name = "aString") public List getStrings() { return strings; } /** * SortedSet containing Integers. */ @XmlElementWrapper @XmlElement(name = "anInteger") public SortedSet getIntegerSet() { return integerSet; } } xmlwrappers/000077500000000000000000000000001351100213400353375ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadocExampleXmlWrapperUsingFieldAccess.java000066400000000000000000000030151351100213400447120ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/xmlwrapperspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * Trivial transport object type for collections. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(namespace = "http://jaxb.mojohaus.org/wrappers") @XmlType(namespace = "http://jaxb.mojohaus.org/wrappers", propOrder = {"strings", "integerSet"}) @XmlAccessorType(XmlAccessType.FIELD) public class ExampleXmlWrapperUsingFieldAccess implements Serializable { /** * List containing some strings. */ @XmlElementWrapper(name = "foobar") @XmlElement(name = "aString") private List strings; /** * SortedSet containing Integers. */ @XmlElementWrapper @XmlElement(name = "anInteger") private SortedSet integerSet; public ExampleXmlWrapperUsingFieldAccess() { this.strings = new ArrayList(); this.integerSet = new TreeSet(); } public List getStrings() { return strings; } public SortedSet getIntegerSet() { return integerSet; } } ExampleXmlWrapperUsingMethodAccess.java000066400000000000000000000030631351100213400451120ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/xmlwrapperspackage org.codehaus.mojo.jaxb2.schemageneration.postprocessing.javadoc.wrappers; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * Another trivial transport object type for collections. * * @author Lennart Jörelid, jGuru Europe AB */ @XmlRootElement(namespace = "http://jaxb.mojohaus.org/wrappers") @XmlType(namespace = "http://jaxb.mojohaus.org/wrappers", propOrder = {"methodStrings", "methodIntegerSet"}) public class ExampleXmlWrapperUsingMethodAccess implements Serializable { private List methodStrings; private SortedSet methodIntegerSet; public ExampleXmlWrapperUsingMethodAccess() { this.methodStrings = new ArrayList(); this.methodIntegerSet = new TreeSet(); } /** * List containing some methodStrings. */ @XmlElementWrapper(name = "foobar") @XmlElement(name = "aString") public List getMethodStrings() { return methodStrings; } /** * SortedSet containing Integers. */ @XmlElementWrapper @XmlElement(name = "anInteger") public SortedSet getMethodIntegerSet() { return methodIntegerSet; } } expectedJavaDocXmlWrappersSchema.xsd000066400000000000000000000056221351100213400444430ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/xmlwrappers expectedRawXmlWrappers.xsd000066400000000000000000000033051351100213400425400ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/schemageneration/javadoc/xmlwrappers jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/000077500000000000000000000000001351100213400273555ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/classloader/000077500000000000000000000000001351100213400316515ustar00rootroot00000000000000ImmediateTestResource.txt000066400000000000000000000000241351100213400365750ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/classloaderThis is a test text.jarSubDirectory/000077500000000000000000000000001351100213400347055ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/classloaderaJarWithResources.jar000066400000000000000000000015121351100213400410060ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/classloader/jarSubDirectoryPKrw$F META-INF/PKPKrw$FMETA-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu ě*h%&*8%krrPK XCDPK-w$FContainedFileResource.txt ,VJ-/-JNUJ3RS3K22PK L((PK ]w$FinternalSubDir/PK]w$F'internalSubDir/SubContainedResource.txt ,V.M J-/-JNUrJ3RS3K22PK2M++PKrw$F META-INF/PKrw$F XCD=META-INF/MANIFEST.MFPK-w$F L((ContainedFileResource.txtPK ]w$F1internalSubDir/PK]w$F2M++'^internalSubDir/SubContainedResource.txtPKVsubdirectory/000077500000000000000000000000001351100213400343105ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/classloaderSubdirectoryTestResource.txt000066400000000000000000000000521351100213400420740ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/classloader/subdirectoryThis is a Subdirectory test text resource.jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/deps1.properties000066400000000000000000000223651351100213400325170ustar00rootroot00000000000000# Project dependencies generated by the Apache ServiceMix Maven Plugin # Generated at: Wed Nov 19 20:11:15 CET 2014 groupId = org.codehaus.mojo artifactId = jaxb2-maven-plugin version = 1.7-SNAPSHOT org.codehaus.mojo/jaxb2-maven-plugin/version = 1.7-SNAPSHOT # dependencies backport-util-concurrent/backport-util-concurrent/version = 3.1 backport-util-concurrent/backport-util-concurrent/type = jar backport-util-concurrent/backport-util-concurrent/scope = compile classworlds/classworlds/version = 1.1 classworlds/classworlds/type = jar classworlds/classworlds/scope = compile com.jcraft/jsch/version = 0.1.38 com.jcraft/jsch/type = jar com.jcraft/jsch/scope = compile com.sun.istack/istack-commons-runtime/version = 2.21 com.sun.istack/istack-commons-runtime/type = jar com.sun.istack/istack-commons-runtime/scope = compile com.sun.xml.fastinfoset/FastInfoset/version = 1.2.13 com.sun.xml.fastinfoset/FastInfoset/type = jar com.sun.xml.fastinfoset/FastInfoset/scope = compile commons-cli/commons-cli/version = 1.2 commons-cli/commons-cli/type = jar commons-cli/commons-cli/scope = compile commons-codec/commons-codec/version = 1.2 commons-codec/commons-codec/type = jar commons-codec/commons-codec/scope = runtime commons-httpclient/commons-httpclient/version = 3.0 commons-httpclient/commons-httpclient/type = jar commons-httpclient/commons-httpclient/scope = runtime javax.xml.bind/jaxb-api/version = 2.2.11 javax.xml.bind/jaxb-api/type = jar javax.xml.bind/jaxb-api/scope = compile junit/junit/version = 4.11 junit/junit/type = jar junit/junit/scope = test nekohtml/nekohtml/version = 1.9.6.2 nekohtml/nekohtml/type = jar nekohtml/nekohtml/scope = compile nekohtml/xercesMinimal/version = 1.9.6.2 nekohtml/xercesMinimal/type = jar nekohtml/xercesMinimal/scope = compile org.apache.jackrabbit/jackrabbit-jcr-commons/version = 1.5.0 org.apache.jackrabbit/jackrabbit-jcr-commons/type = jar org.apache.jackrabbit/jackrabbit-jcr-commons/scope = runtime org.apache.jackrabbit/jackrabbit-webdav/version = 1.5.0 org.apache.jackrabbit/jackrabbit-webdav/type = jar org.apache.jackrabbit/jackrabbit-webdav/scope = runtime org.apache.maven/maven-artifact/version = 2.2.1 org.apache.maven/maven-artifact/type = jar org.apache.maven/maven-artifact/scope = compile org.apache.maven/maven-artifact-manager/version = 2.2.1 org.apache.maven/maven-artifact-manager/type = jar org.apache.maven/maven-artifact-manager/scope = compile org.apache.maven/maven-core/version = 2.2.1 org.apache.maven/maven-core/type = jar org.apache.maven/maven-core/scope = compile org.apache.maven/maven-error-diagnostics/version = 2.2.1 org.apache.maven/maven-error-diagnostics/type = jar org.apache.maven/maven-error-diagnostics/scope = compile org.apache.maven/maven-model/version = 2.2.1 org.apache.maven/maven-model/type = jar org.apache.maven/maven-model/scope = compile org.apache.maven/maven-monitor/version = 2.2.1 org.apache.maven/maven-monitor/type = jar org.apache.maven/maven-monitor/scope = compile org.apache.maven/maven-plugin-api/version = 2.2.1 org.apache.maven/maven-plugin-api/type = jar org.apache.maven/maven-plugin-api/scope = compile org.apache.maven/maven-plugin-descriptor/version = 2.2.1 org.apache.maven/maven-plugin-descriptor/type = jar org.apache.maven/maven-plugin-descriptor/scope = compile org.apache.maven/maven-plugin-parameter-documenter/version = 2.2.1 org.apache.maven/maven-plugin-parameter-documenter/type = jar org.apache.maven/maven-plugin-parameter-documenter/scope = compile org.apache.maven/maven-plugin-registry/version = 2.2.1 org.apache.maven/maven-plugin-registry/type = jar org.apache.maven/maven-plugin-registry/scope = compile org.apache.maven/maven-profile/version = 2.2.1 org.apache.maven/maven-profile/type = jar org.apache.maven/maven-profile/scope = compile org.apache.maven/maven-project/version = 2.2.1 org.apache.maven/maven-project/type = jar org.apache.maven/maven-project/scope = compile org.apache.maven/maven-repository-metadata/version = 2.2.1 org.apache.maven/maven-repository-metadata/type = jar org.apache.maven/maven-repository-metadata/scope = compile org.apache.maven/maven-settings/version = 2.2.1 org.apache.maven/maven-settings/type = jar org.apache.maven/maven-settings/scope = compile org.apache.maven.doxia/doxia-logging-api/version = 1.1 org.apache.maven.doxia/doxia-logging-api/type = jar org.apache.maven.doxia/doxia-logging-api/scope = compile org.apache.maven.doxia/doxia-sink-api/version = 1.1 org.apache.maven.doxia/doxia-sink-api/type = jar org.apache.maven.doxia/doxia-sink-api/scope = compile org.apache.maven.plugin-testing/maven-plugin-testing-harness/version = 1.3 org.apache.maven.plugin-testing/maven-plugin-testing-harness/type = jar org.apache.maven.plugin-testing/maven-plugin-testing-harness/scope = test org.apache.maven.plugin-tools/maven-plugin-annotations/version = 3.3 org.apache.maven.plugin-tools/maven-plugin-annotations/type = jar org.apache.maven.plugin-tools/maven-plugin-annotations/scope = provided org.apache.maven.reporting/maven-reporting-api/version = 2.2.1 org.apache.maven.reporting/maven-reporting-api/type = jar org.apache.maven.reporting/maven-reporting-api/scope = compile org.apache.maven.wagon/wagon-file/version = 1.0-beta-6 org.apache.maven.wagon/wagon-file/type = jar org.apache.maven.wagon/wagon-file/scope = runtime org.apache.maven.wagon/wagon-http/version = 1.0-beta-6 org.apache.maven.wagon/wagon-http/type = jar org.apache.maven.wagon/wagon-http/scope = compile org.apache.maven.wagon/wagon-http-lightweight/version = 1.0-beta-6 org.apache.maven.wagon/wagon-http-lightweight/type = jar org.apache.maven.wagon/wagon-http-lightweight/scope = compile org.apache.maven.wagon/wagon-http-shared/version = 1.0-beta-6 org.apache.maven.wagon/wagon-http-shared/type = jar org.apache.maven.wagon/wagon-http-shared/scope = compile org.apache.maven.wagon/wagon-provider-api/version = 1.0-beta-6 org.apache.maven.wagon/wagon-provider-api/type = jar org.apache.maven.wagon/wagon-provider-api/scope = compile org.apache.maven.wagon/wagon-ssh/version = 1.0-beta-6 org.apache.maven.wagon/wagon-ssh/type = jar org.apache.maven.wagon/wagon-ssh/scope = compile org.apache.maven.wagon/wagon-ssh-common/version = 1.0-beta-6 org.apache.maven.wagon/wagon-ssh-common/type = jar org.apache.maven.wagon/wagon-ssh-common/scope = compile org.apache.maven.wagon/wagon-ssh-external/version = 1.0-beta-6 org.apache.maven.wagon/wagon-ssh-external/type = jar org.apache.maven.wagon/wagon-ssh-external/scope = runtime org.apache.maven.wagon/wagon-webdav-jackrabbit/version = 1.0-beta-6 org.apache.maven.wagon/wagon-webdav-jackrabbit/type = jar org.apache.maven.wagon/wagon-webdav-jackrabbit/scope = runtime org.codehaus.plexus/plexus-archiver/version = 2.2 org.codehaus.plexus/plexus-archiver/type = jar org.codehaus.plexus/plexus-archiver/scope = test org.codehaus.plexus/plexus-compiler-api/version = 2.4 org.codehaus.plexus/plexus-compiler-api/type = jar org.codehaus.plexus/plexus-compiler-api/scope = compile org.codehaus.plexus/plexus-container-default/version = 1.0-alpha-9-stable-1 org.codehaus.plexus/plexus-container-default/type = jar org.codehaus.plexus/plexus-container-default/scope = compile org.codehaus.plexus/plexus-interactivity-api/version = 1.0-alpha-4 org.codehaus.plexus/plexus-interactivity-api/type = jar org.codehaus.plexus/plexus-interactivity-api/scope = compile org.codehaus.plexus/plexus-interpolation/version = 1.11 org.codehaus.plexus/plexus-interpolation/type = jar org.codehaus.plexus/plexus-interpolation/scope = compile org.codehaus.plexus/plexus-io/version = 2.0.4 org.codehaus.plexus/plexus-io/type = jar org.codehaus.plexus/plexus-io/scope = test org.codehaus.plexus/plexus-utils/version = 3.0.20 org.codehaus.plexus/plexus-utils/type = jar org.codehaus.plexus/plexus-utils/scope = compile org.glassfish.jaxb/jaxb-core/version = 2.2.11 org.glassfish.jaxb/jaxb-core/type = jar org.glassfish.jaxb/jaxb-core/scope = compile org.glassfish.jaxb/jaxb-runtime/version = 2.2.11 org.glassfish.jaxb/jaxb-runtime/type = jar org.glassfish.jaxb/jaxb-runtime/scope = compile org.glassfish.jaxb/txw2/version = 2.2.11 org.glassfish.jaxb/txw2/type = jar org.glassfish.jaxb/txw2/scope = compile org.hamcrest/hamcrest-core/version = 1.3 org.hamcrest/hamcrest-core/type = jar org.hamcrest/hamcrest-core/scope = test org.jvnet.staxex/stax-ex/version = 1.7.6 org.jvnet.staxex/stax-ex/type = jar org.jvnet.staxex/stax-ex/scope = compile org.slf4j/jcl-over-slf4j/version = 1.5.6 org.slf4j/jcl-over-slf4j/type = jar org.slf4j/jcl-over-slf4j/scope = runtime org.slf4j/slf4j-api/version = 1.5.6 org.slf4j/slf4j-api/type = jar org.slf4j/slf4j-api/scope = runtime org.slf4j/slf4j-jdk14/version = 1.5.6 org.slf4j/slf4j-jdk14/type = jar org.slf4j/slf4j-jdk14/scope = runtime org.slf4j/slf4j-nop/version = 1.5.3 org.slf4j/slf4j-nop/type = jar org.slf4j/slf4j-nop/scope = runtime org.sonatype.plexus/plexus-build-api/version = 0.0.7 org.sonatype.plexus/plexus-build-api/type = jar org.sonatype.plexus/plexus-build-api/scope = compile org.sonatype.plexus/plexus-cipher/version = 1.4 org.sonatype.plexus/plexus-cipher/type = jar org.sonatype.plexus/plexus-cipher/scope = compile org.sonatype.plexus/plexus-sec-dispatcher/version = 1.3 org.sonatype.plexus/plexus-sec-dispatcher/type = jar org.sonatype.plexus/plexus-sec-dispatcher/scope = compile xmlunit/xmlunit/version = 1.5 xmlunit/xmlunit/type = jar xmlunit/xmlunit/scope = test jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/dirwith space/000077500000000000000000000000001351100213400321035ustar00rootroot00000000000000somefile.txt000066400000000000000000000000231351100213400343630ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/dirwith spaceThis is a resource.jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/filefilter/000077500000000000000000000000001351100213400315025ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/filefilter/exclusion/000077500000000000000000000000001351100213400335135ustar00rootroot00000000000000AnXmlFile.xml000066400000000000000000000001211351100213400357670ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/filefilter/exclusion This is a Bar! TextFile.txt000066400000000000000000000000241351100213400357150ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/filefilter/exclusionThis is a Text File.jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/filesystemutilities/000077500000000000000000000000001351100213400334755ustar00rootroot00000000000000TestFile2.txt000066400000000000000000000000321351100213400357530ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/filesystemutilitiesThis is another test file.canonicals/000077500000000000000000000000001351100213400355305ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/filesystemutilitiesTestFile1.txt000066400000000000000000000000241351100213400400650ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/filesystemutilities/canonicalsThis is a test file.nazgul-tools-validation-aspect-4.0.1.jar000066400000000000000000000276551351100213400365140ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/sharedPK m>FE META-INF/PK l>FEEР5META-INF/MANIFEST.MFTn@[?8TA‹M TF MDCgf]w@jOg73;3c& @dD*Sz?"b\T4*% ]0fF ܀5ӵuT066@ zA+(bޢ,_ O s.7|=#2ע1|w]ig,IDJ=vz^YϜk.YI1P4vֿa 6_l h^0E-D^`4$Fx\ZgRl݊3GakF<iP,j6@SN,,J1 S $|Վt|?L+J\ `XqyMYd,~2f d!\VGDHyy]h{Nf3v,10haSv*xU>߀a~/W_|0\Fn5Zo읅=$fhC^9v}Uџu:~ul"`uPK l>FEse/PK l>FE se/jguru/PK l>FEse/jguru/nazgul/PK l>FEse/jguru/nazgul/tools/PK l>FE!se/jguru/nazgul/tools/validation/PK l>FE(se/jguru/nazgul/tools/validation/aspect/PK l>FEMETA-INF/maven/PK l>FE5T3 builddef.lstRMO0 8l&nH!4!MJN_O]%x~A]wH'|b3b(5 Jr-ZoHSduM)k|s:iȆ )0NYQ'>ѾN-y>P,<mHg/1(N;Uua ֫o^HBAOՑh$ ߶т%&8L|AiqeUB [ D`ZM5PK l>FEĬ9.. LICENSE.TXTZms_rSiL;n6'ْ亙L>w8w_gGR;V'1b/>'_(FkJ6vk3xk;tZy?u^̟W݋ϟ0l_>{撷z3;qq})^\_.7wͭxwU۫w7_?u]zO߰RsxY8L:QxPvQDkU[k m^N4%܋;U{!_A5j-L=nT?eb^av*aBXo/9bXA`ӕXد`BbGJ=WB,%j3 Vo tV+]i۱o6郤a ⍱vD#bUãfAʌę>KN ){J FN[Jh_7X%vkLJy_ɲK4Eihqk%InaͭBB7x> 7*%BR0BʉB8gXKK6yH(#Pvh89|[BcҌksi[Ze--[#m1$gUtndS Eo鍦GgaG<֦c ?Poj;ҩ>n"UwGk?kC ѓ2Ӆjz H2\8 @D/#9>w7R my~<d(r >#%7]8F6;bTR2L f ޼fag8$7[쌅v_kVaOHγ.d7; $o2^JņGx] Yj2Ӫͮ(iB ?ADpsMAU9)l}LIez{rc<8Nҿ ֣hcjX:JˑBvclUyd--'ܨt HTELF=RL<?́~ɀ!b-MzO8D$mëcWER [wݸv5gB*FG"zgEITy{1[qe^ҙfA HuH@kya);u=U6ip9Yl)JUY' hqJ iEJTݠ6pQQ F'yViI&֣*;n/K0=kGmu=!y7~$賙Eʥ^Ed$Xͮao)\ώS_c ]SqsXCB<2*Fr(]ЩFOGֱak7 Y&}ނ`AKddU +|QP(0Yu&}n 2FIi7v%-'kPgPԉ`etކq0@~dv`ɚt mZ:$\J;2,v\B6|ɓ*߰ANj?n:Aܸxp;I{gXA)!a(|{.z7H:17lY'*mTB(BhB!mjȇQ+BAǝp^+i`eRZ?RwNZ[j;\s!;ӫPMS eat\|\YO,D5=9m+\I]e꒺,k{ʦcf$ψ ):s訝Zy: |fsفW܅KSg㱢'6ܳ@'H9%B&Ŗ3` ?_jJ)Lދ-], WC%BM _ŭ*Ȝ}FC|r㦿%@` qD7M(=tUn :jܚݱgz^FE\Oz-V/;OUje9Ms/1{.=/7UQ$Ǐ,I>\=A` iICCy9ӝbg$X;b}"4:<\q0DEk"@l1誠CNp6?:Ob}7 V1ڠ 1=IC.l$S5Wa@]/^_͐|7]؃b2 8)GeB‡ʐN4+!&#?bN[]9 SQc]ׄ%9[0QMu̶Dߕ`> 2Hی3T2W7:\w.ڃLaLbgAm!7=Mj;p  %\ܯ}?NulLP%{T[X-M*i|OηBJT=XK2֧<w4j7&ID`,qEd%gx0`4QJ'#$$TXkɂO1<=qyiOhSiylU))Xޘ;G*6*08 R's)L 7CNxwԬ{Ü!,*KEcb3szib5"%ARu1-V"7/yZewY3ҕ f4 '= vq'w3nqaq{~qu'nn4nވ?ח;ڿ 'k$q)9xb.#N䲩:ȣ<_ܿ`맋7~ďWo?qY__I.wpw7wW{cB-6|wt+ wŽXႌǷk /3|=O08,3NNxl6٦Q-̸91ZvHubN|ofdtԬ!ju<7^ړMXƤK^/޽#$/qoʎo~_ /L VdE>ĩF;VqAI 9Y>LjĨK)9Rhs:AQ[zJW{X9O9iDq~ ofnc1K_^KbZ8r<& QށנHMNof4Ci5!_Fǟ_Ϭ7FE^Q#>se/jguru/nazgul/tools/validation/aspect/ValidationAspect.classXwg=f3@y)X`i],D0$ %4,uf6i@U[_jkRϱ_z$4rIoxgf'Mc7gޞw}& ~+ḣe]ΘBȸe8ys[fFuJZL+bABΫC5 "2D :jمc3V} {I蠕h6 2CZa5ZT\oACuT&0C#ÎQs3}Q14acV5&U[bc0:d!NVpbACE␖Wˆ;hkg /MW&uG'iv GM ܴVՀxHl-u*I(kԒOvVC=H`8qlWӤY•i42^ צJ[zPK2َM=EZVu8Kb[")8A742G+x~xci>&Cm̵эG2q?~&7V;C{'gW?; ?N*r ;̦Y޼R'~dU"wtnwyd8Itrz:MWFVт6\D;]4a|%2.(-2X]/MvYI $)͋#*{l-#a||}P[a{O8 xJ 'Qt[k|*k4up P{hR6ղiR;в0.cSOE_2N.2j2VlzVp>RUDvW|1%"Z+ cW3,cDr hz#a $lwWHuX1:9N;!BUM;%rUn'dM")ڃ\ӸD+wr3ĕ%IyY"n|~O1t_P0A7q9%'͓!J@f+"MisV7JxϺeh|BQ.2H(EeD_y$DiEM-ܼϡToͻ_hVKEvuф_ _V bb#gH۷qsI1KxEE|I@s|uq@%xA, *P{%?zh#gyqq6mӱ Iy#<=gѰg}ןE0LhVy)~藣:Ym@q4&8,Mx}|KQox%,б)k2֔aу mh`nfv֛[3a9Yg,Fte~2 ; 3F_ [yVpSkG'c~lPK l>FE4g&META-INF/maven/dependencies.propertiesN0y&^S`Lgxa1^,./pVXk-v)A 9w Yj!$eq4$E,&d'v1 u.Y@,Erݐ sP gh>LhyVEbfi *;-J CK<˕`rm_lڸONiH#oFpl-nؖ~*CJ>:L15#n9:6=D*Ԣ](--l+Z[v-S ձLvJ Ʈ {Vs.S,ޟFE7META-INF/maven/se.jguru.nazgul.tools.validation.aspect/PK m>FEVMETA-INF/maven/se.jguru.nazgul.tools.validation.aspect/nazgul-tools-validation-aspect/PK =FEU`M]META-INF/maven/se.jguru.nazgul.tools.validation.aspect/nazgul-tools-validation-aspect/pom.xmlYms6_4sI$m'w)8so9m)XˤI(ˉڹ$xvXiT*&C1y}azÓyi!ݒED#d̮?}jNDv'Y<9g~^_,"pNtB gAY{0!Hh qXރpD).4JϘ)K(eH3m0HRX0=}31iRe8@t/Q, A G'g3*3PLP,@H !F_S Z>SZIV.ECh1¡<ѸoǣWow/oFgcz'W%ity/LPPf,K#kFSb*P*!qNb xdTL*=a)6}ܫ@a7ȤPWGRrKOlBE7aGK*^0%JA*Ŏ<oAb"7YgBj&E he4G>%ະ!*[+n`'b)l э.[\m3APbVTDj6%FrAm}Et[ (+ yK }?FɻrZZ-tZV<-;W䂰瀓\$Z2욃2A1ol%@gܗ D*TLFfTբ FqibҌb!AF5v g53@~]ݰA5)u$u]u rܝAT*ouq"F);ꒅ+-д%ج 7f99gNt*3™P~" ?m!c„`sJKK,AorD6.0W$%_v,֕p/(`MH,>1c#kܛ G\\_yq/v/ w+rҗ5U"2,_<|@IwM) tm8^^u-:l6O^3M iƩ|mi5H[’\҆/+&Cpw'{ |]#Yp}qowCP%9%ۄ} y0KڍI1w";Db4_1c[5s&g+X䡍`V-m(8VQ3yq*אNqkwM> 4w2h|sSh eOVݞG7ok.W|S݂'9]@iQDk꧅-3!wg3D$27T`c-{*xřɍ$5n` "D(ZQ9Z$Nۖ1U`4|8W 0m]U9 Eްmd_.Y3U|j7yO7^h43)/_.LUbB;yA8֙^ޘhUn+]2 K+Wbrthuj0esUnTi4v)ղ Ӛ+N.(XW,"sX4W'ⵎlY$1$M$nބf05,a {PK m>FETdMETA-INF/maven/se.jguru.nazgul.tools.validation.aspect/nazgul-tools-validation-aspect/pom.propertiesE˱ 0=_q9GZZB')P,Я^qdǁ'=aNwp̾mʶj_PVC\j4X9.2>:zɢxo#fDq(,we+_?R7PK m>FE AMETA-INF/PK l>FEEР5'META-INF/MANIFEST.MFPK l>FEAse/PK l>FE Ase/jguru/PK l>FEAse/jguru/nazgul/PK l>FEAse/jguru/nazgul/tools/PK l>FE!A8se/jguru/nazgul/tools/validation/PK l>FE(Awse/jguru/nazgul/tools/validation/aspect/PK l>FEAMETA-INF/maven/PK l>FE5T3 builddef.lstPK l>FEĬ9.. GLICENSE.TXTPK l>FE^Q#>se/jguru/nazgul/tools/validation/aspect/ValidationAspect.classPK l>FE4g&~META-INF/maven/dependencies.propertiesPK m>FE7I META-INF/maven/se.jguru.nazgul.tools.validation.aspect/PK m>FEV META-INF/maven/se.jguru.nazgul.tools.validation.aspect/nazgul-tools-validation-aspect/PK =FEU`M]!META-INF/maven/se.jguru.nazgul.tools.validation.aspect/nazgul-tools-validation-aspect/pom.xmlPK m>FETd)META-INF/maven/se.jguru.nazgul.tools.validation.aspect/nazgul-tools-validation-aspect/pom.propertiesPK~*not_a_dependency.properties000066400000000000000000000001041351100213400347050ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared# This is not a correctly formed dependency.properties file ... foo=jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/000077500000000000000000000000001351100213400311555ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/exclusions/000077500000000000000000000000001351100213400333515ustar00rootroot00000000000000.hg/000077500000000000000000000000001351100213400337465ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/exclusionssomeHgFile.txt000066400000000000000000000000261351100213400365270ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/exclusions/.hgDont remove this file .svn/000077500000000000000000000000001351100213400341565ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/exclusionssomeSvnFile.txt000066400000000000000000000000261351100213400371470ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/exclusions/.svnDont remove this file CVS/000077500000000000000000000000001351100213400337255ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/exclusionssomeCvsFile.txt000066400000000000000000000000261351100213400367030ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/exclusions/CVSDont remove this file someFile.log000066400000000000000000000000261351100213400355360ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/standard/exclusionsDont remove this file jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/urlhandling/000077500000000000000000000000001351100213400316645ustar00rootroot00000000000000file with spaces.txt000066400000000000000000000000471351100213400354610ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testdata/shared/urlhandlingThis is a file with spaces in its name.jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testschemas/000077500000000000000000000000001351100213400266215ustar00rootroot00000000000000jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testschemas/address.xsd000066400000000000000000000010411351100213400307620ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testschemas/address2.xsd000066400000000000000000000010441351100213400310470ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testschemas/address3.xsd000066400000000000000000000010441351100213400310500ustar00rootroot00000000000000 jaxb2-maven-plugin-jaxb2-maven-plugin-2.5.0/src/test/resources/testschemas/address4.xsd000066400000000000000000000005071351100213400310540ustar00rootroot00000000000000