From a396aa07f68368d5a40dba071008bdec4e1a46ca Mon Sep 17 00:00:00 2001 From: lresende Date: Mon, 9 Mar 2009 22:39:04 +0000 Subject: 2.0-M1 Final Release Tag git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@751885 13f79535-47bb-0310-9956-ffa450edef68 --- .../2.0-M1/tools/maven/maven-ant-generator/LICENSE | 205 +++ .../2.0-M1/tools/maven/maven-ant-generator/NOTICE | 6 + .../2.0-M1/tools/maven/maven-ant-generator/pom.xml | 64 + .../ant/generator/plugin/AntGeneratorMojo.java | 534 +++++++ .../2.0-M1/tools/maven/maven-bundle-plugin/LICENSE | 205 +++ .../2.0-M1/tools/maven/maven-bundle-plugin/NOTICE | 6 + .../2.0-M1/tools/maven/maven-bundle-plugin/pom.xml | 81 + .../plugin/eclipse/AbstractIdeSupportMojo.java | 1136 ++++++++++++++ .../plugin/eclipse/EclipseClasspathWriter.java | 530 +++++++ .../sca/maven/plugin/eclipse/EclipseCleanMojo.java | 231 +++ .../sca/maven/plugin/eclipse/EclipsePlugin.java | 1556 ++++++++++++++++++++ .../maven/plugin/eclipse/EclipseProjectWriter.java | 351 +++++ .../tuscany/sca/maven/plugin/eclipse/Messages.java | 68 + .../tools/bundle/plugin/ArtifactAggregation.java | 73 + .../sca/tools/bundle/plugin/ArtifactMember.java | 61 + .../sca/tools/bundle/plugin/BundleUtil.java | 387 +++++ .../bundle/plugin/ModuleBundlesBuildMojo.java | 828 +++++++++++ .../bundle/plugin/ThirdPartyBundleBuildMojo.java | 152 ++ .../sca/maven/plugin/eclipse/messages.properties | 78 + .../tuscany/sca/tools/bundle/plugin/LICENSE.txt | 205 +++ .../tuscany/sca/tools/bundle/plugin/NOTICE.txt | 5 + .../tools/maven/maven-dependency-lister/LICENSE | 205 +++ .../tools/maven/maven-dependency-lister/NOTICE | 6 + .../tools/maven/maven-dependency-lister/README | 46 + .../tools/maven/maven-dependency-lister/pom.xml | 71 + .../lister/plugin/DependencyListerMojo.java | 198 +++ .../tools/maven/maven-eclipse-compiler/LICENSE | 205 +++ .../tools/maven/maven-eclipse-compiler/NOTICE | 6 + .../tools/maven/maven-eclipse-compiler/pom.xml | 304 ++++ .../maven/compiler/ClassLoaderNameEnvironment.java | 195 +++ .../tools/maven/compiler/CompilerRequestor.java | 114 ++ .../tools/maven/compiler/FileCompilationUnit.java | 88 ++ .../sca/tools/maven/compiler/JavaCompiler.java | 212 +++ .../tools/maven/compiler/osgi/BundleResolver.java | 490 ++++++ .../sca/tools/maven/compiler/osgi/BundleUtil.java | 618 ++++++++ .../main/resources/META-INF/plexus/components.xml | 28 + .../tools/maven/maven-incremental-build/LICENSE | 205 +++ .../tools/maven/maven-incremental-build/NOTICE | 6 + .../tools/maven/maven-incremental-build/pom.xml | 108 ++ .../build/plugin/IncrementalBuildMojo.java | 415 ++++++ .../sca/2.0-M1/tools/maven/maven-java2wsdl/LICENSE | 205 +++ .../sca/2.0-M1/tools/maven/maven-java2wsdl/NOTICE | 6 + .../sca/2.0-M1/tools/maven/maven-java2wsdl/pom.xml | 45 + .../java2wsdl/plugin/Java2WSDLGeneratorMojo.java | 153 ++ .../2.0-M1/tools/maven/maven-osgi-junit/LICENSE | 205 +++ .../sca/2.0-M1/tools/maven/maven-osgi-junit/NOTICE | 6 + .../2.0-M1/tools/maven/maven-osgi-junit/pom.xml | 70 + .../maven/plugin/surefire/ForkConfiguration.java | 239 +++ .../maven/plugin/surefire/OSGiSurefireBooter.java | 984 +++++++++++++ .../maven/plugin/surefire/OSGiSurefirePlugin.java | 1306 ++++++++++++++++ .../sca/2.0-M1/tools/maven/maven-web-junit/LICENSE | 205 +++ .../sca/2.0-M1/tools/maven/maven-web-junit/NOTICE | 6 + .../sca/2.0-M1/tools/maven/maven-web-junit/pom.xml | 52 + .../web/junit/plugin/WebJUnitGeneratorMojo.java | 181 +++ .../tools/sca/web/junit/plugin/WebJUnitMojo.java | 205 +++ .../sca/2.0-M1/tools/maven/maven-wsdl2java/LICENSE | 205 +++ .../sca/2.0-M1/tools/maven/maven-wsdl2java/NOTICE | 6 + .../sca/2.0-M1/tools/maven/maven-wsdl2java/pom.xml | 45 + .../wsdl2java/plugin/WSDL2JavaGeneratorMojo.java | 152 ++ .../tools/wsdl2java/plugin/WSDLFileOption.java | 92 ++ tags/java/sca/2.0-M1/tools/maven/pom.xml | 62 + 61 files changed, 14712 insertions(+) create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/src/main/java/org/apache/tuscany/sca/tools/ant/generator/plugin/AntGeneratorMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/AbstractIdeSupportMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseClasspathWriter.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseCleanMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipsePlugin.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseProjectWriter.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/Messages.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ArtifactAggregation.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ArtifactMember.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/BundleUtil.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ModuleBundlesBuildMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ThirdPartyBundleBuildMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/maven/plugin/eclipse/messages.properties create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/tools/bundle/plugin/LICENSE.txt create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/tools/bundle/plugin/NOTICE.txt create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/README create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/src/main/java/org/apache/tuscany/tools/sca/dependency/lister/plugin/DependencyListerMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/ClassLoaderNameEnvironment.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/CompilerRequestor.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/FileCompilationUnit.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/JavaCompiler.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/osgi/BundleResolver.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/osgi/BundleUtil.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/resources/META-INF/plexus/components.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/src/main/java/org/apache/tuscany/tools/java2wsdl/plugin/Java2WSDLGeneratorMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefirePlugin.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-web-junit/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-web-junit/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-web-junit/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-web-junit/src/main/java/org/apache/tuscany/tools/sca/web/junit/plugin/WebJUnitGeneratorMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-web-junit/src/main/java/org/apache/tuscany/tools/sca/web/junit/plugin/WebJUnitMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/LICENSE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/NOTICE create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/pom.xml create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/src/main/java/org/apache/tuscany/tools/wsdl2java/plugin/WSDL2JavaGeneratorMojo.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/src/main/java/org/apache/tuscany/tools/wsdl2java/plugin/WSDLFileOption.java create mode 100644 tags/java/sca/2.0-M1/tools/maven/pom.xml (limited to 'tags/java/sca/2.0-M1/tools/maven') diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/NOTICE new file mode 100644 index 0000000000..25bb89c9b2 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/pom.xml new file mode 100644 index 0000000000..b46c3125e1 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/pom.xml @@ -0,0 +1,64 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 2.0-M1 + ../pom.xml + + tuscany-maven-ant-generator + maven-plugin + Apache Tuscany SCA Ant Build Generator Maven Plugin + + + + org.apache.maven + maven-plugin-api + 2.0.5 + + + + org.apache.maven + maven-project + 2.0.5 + + + + org.apache.maven + maven-settings + 2.0.5 + + + + org.apache.maven + maven-artifact + 2.0.5 + + + + org.apache.maven + maven-model + 2.0.5 + + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/src/main/java/org/apache/tuscany/sca/tools/ant/generator/plugin/AntGeneratorMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/src/main/java/org/apache/tuscany/sca/tools/ant/generator/plugin/AntGeneratorMojo.java new file mode 100644 index 0000000000..d7b80bd67c --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-ant-generator/src/main/java/org/apache/tuscany/sca/tools/ant/generator/plugin/AntGeneratorMojo.java @@ -0,0 +1,534 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.tools.ant.generator.plugin; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.model.FileSet; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginExecution; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Settings; +import org.codehaus.plexus.util.xml.Xpp3Dom; + +/** + * A Maven plugin that generates an Ant build.xml file for Tuscany SCA samples. + * + * Build dependencies and additional build steps like WSDL2Java for example are + * automatically determined from the pom.xml file describing the module's Maven build. + * + * @version $Rev$ $Date$ + * @goal generate + * @phase generate-sources + * @requiresDependencyResolution test + * @description Generate Ant build script for an SCA project + */ +public class AntGeneratorMojo extends AbstractMojo { + + /** + * The project to generate an Ant build for. + * + * @parameter expression="${project}" + * @required + */ + private MavenProject project; + + /** + * Used for resolving artifacts + * + * @component + */ + private ArtifactResolver resolver; + + /** + * Factory for creating artifact objects + * + * @component + */ + private ArtifactFactory factory; + + /** + * The local repository where the artifacts are located + * + * @parameter expression="${localRepository}" + * @required + */ + private ArtifactRepository localRepository; + + /** + * The remote repositories where artifacts are located + * + * @parameter expression="${project.remoteArtifactRepositories}" + */ + private List remoteRepositories; + + /** + * The current user system settings for use in Maven. + * + * @parameter expression="${settings}" + * @required + * @readonly + */ + private Settings settings; + + /** + * The main class name. + * @parameter + */ + private String mainClass; + + /** + * If set true then only the dependency file is created. The dependency + * file can then be included in a hand generated build.xml file + * @parameter + */ + private Boolean buildDependencyFileOnly; + + /** + * The build.xml file to generate. + * @parameter expression="${basedir}/build.xml" + */ + private String buildFile; + + /** + * The build-dependency.xml file to generate. + * @parameter expression="${basedir}/build-dependency.xml" + */ + private String buildDependencyFile; + + public void execute() throws MojoExecutionException { + if ((buildDependencyFileOnly != null) && + (buildDependencyFileOnly == true)){ + generateBuildDependencyFile(); + } else { + generateBuildFile(); + } + } + + /** + * Generate Ant build dependency XML file + */ + private void generateBuildDependencyFile() throws MojoExecutionException { + + getLog().info("Generating " + buildDependencyFile); + + // Open the target build-dependency.xml file + File targetFile = new File(buildDependencyFile); + PrintWriter pw; + try { + pw = new PrintWriter(new FileOutputStream(targetFile)); + } catch (FileNotFoundException e) { + throw new MojoExecutionException(e.toString()); + } + + // Generate the Apache license header + generateLicenseHeader(pw); + + // Generate Ant filesets representing the build dependencies + generateBuildDependencies(pw); + + pw.close(); + } + + /** + * Generate Ant build XML file + */ + private void generateBuildFile() throws MojoExecutionException { + + getLog().info("Generating " + buildFile); + + // Open the target build.xml file + File targetFile = new File(buildFile); + PrintWriter pw; + try { + pw = new PrintWriter(new FileOutputStream(targetFile)); + } catch (FileNotFoundException e) { + throw new MojoExecutionException(e.toString()); + } + + // Determine the project packaging + String packaging = project.getPackaging().toLowerCase(); + + // Generate the Apache license header + generateLicenseHeader(pw); + + pw.println(""); + pw.println(); + + // Generate the compile target + int base = project.getBasedir().toString().length() + 1; + pw.println(" "); + pw.println(" "); + + // Generate any pre-compilation tasks + generatePreCompileTasks(pw); + + // Generate the compile task + pw.println(" "); + for (String source: (List)project.getCompileSourceRoots()) { + if (source.length() > base) { + source = source.substring(base); + } else { + source = "."; + } + pw.println(" "); + } + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + for (FileSet resource: (List)project.getResources()) { + String source = resource.getDirectory(); + if (source.length() > base) { + source = source.substring(base); + + if (source.equals(".")){ + pw.println(" "); + } else { + pw.println(" "); + } + } else { + if (project.getResources().size() > 1) { + break; + } + pw.println(" "); + source = "."; + } + } + pw.println(" "); + + // Build a JAR + if (packaging.equals("jar")) { + pw.println(" "); + pw.println(" "); + if (mainClass != null) { + pw.println(" "); + } + pw.println(" "); + pw.println(" "); + + } else if (packaging.equals("war")) { + + // Build a WAR + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + } + pw.println(" "); + pw.println(); + + + // Generate a package target alongside the compile target + // Tuscany SCA samples use "package" as the target for webapps + pw.println(" "); + pw.println(); + + // Generate the run target + if (mainClass != null) { + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(); + } + + // Generate the clean target + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(); + + // Generate Ant filesets representing the build dependencies + generateBuildDependencies(pw); + + pw.println(""); + pw.close(); + } + + /** + * Generate Ant filesets representing the build dependencies. + * @param pw PrintWriter to write to + */ + private void generateBuildDependencies(PrintWriter pw) { + + // Determine the module dependencies + List tuscanyModules = new ArrayList(); + List otherModules = new ArrayList(); + for (Artifact artifact: (List)project.getRuntimeArtifacts()) { + if (artifact.getGroupId().startsWith("org.apache.tuscany.sca")) { + tuscanyModules.add(artifact.getFile().getName()); + } else { + otherModules.add(artifact.getFile().getName()); + } + } + + // Sort lists of modules, making output deterministic + Collections.sort(tuscanyModules); + Collections.sort(otherModules); + + // Generate filesets for the tuscany and 3rd party dependencies + pw.println(" "); + for (String name: tuscanyModules) { + pw.println(" "); + } + pw.println(" "); + pw.println(" "); + for (String name: otherModules) { + pw.println(" "); + } + pw.println(" "); + pw.println(); + } + + /** + * Extract plugin execution configurations out of the Maven model. This handles + * nested configurations with a base configuration and a collection of nested + * configuration elements, for example: + * + * + * + * x.wsdl + * + * + * y.wsdl + * + * + * true + * + * + * @param execution Maven plugin execution model + * @return a list of maps containing the plugin configuration key value pairs + */ + private static List> pluginConfigurations(PluginExecution execution) { + List> configurations = new ArrayList>(); + Map topConfiguration = new HashMap(); + + Xpp3Dom dom = (Xpp3Dom)execution.getConfiguration(); + for (Xpp3Dom element: dom.getChildren()) { + if (element.getChildCount() != 0) { + // Handle nested configuration element, create a child configuration + // for each + for (Xpp3Dom childConfigurationElement: element.getChildren()) { + Map childConfiguration = new HashMap(); + for (Xpp3Dom childElement: childConfigurationElement.getChildren()) { + childConfiguration.put(childElement.getName(), childElement.getValue()); + } + configurations.add(childConfiguration); + } + } else { + // Handle top level key value pair element + topConfiguration.put(element.getName(), element.getValue()); + } + } + // Return the top configuration or the child configurations merged + // with the top one + if (configurations.isEmpty()) { + configurations.add(topConfiguration); + } else { + for (Map configuration: configurations) { + configuration.putAll(topConfiguration); + } + } + return configurations; + } + + /** + * Generate Ant tasks for the pre-compilation generation plugins + * used in the Maven module. + * @param pw PrintWriter to write to + * @return list of directories containing generated source to compile + */ + private void generatePreCompileTasks(PrintWriter pw) { + String baseDir = project.getBasedir().getAbsolutePath() + '/'; + + List plugins = (List)project.getBuildPlugins(); + for (Plugin plugin: plugins) { + + // Generate Ant task equivalent to the Tuscany SDO plugin + if ("org.apache.tuscany.sdo".equals(plugin.getGroupId()) && "tuscany-sdo-plugin".equals(plugin.getArtifactId())) { + for (PluginExecution execution: (List)plugin.getExecutions()) { + for (Map configuration: pluginConfigurations(execution)) { + + pw.println(" "); + + // Generate the various code generation options + for (Map.Entry element: configuration.entrySet()) { + String key = element.getKey(); + String value = element.getValue(); + if (key.equals("schemaNamespace")) { + pw.println(" "); + pw.println(" "); + } + if (key.equals("javaPackage")) { + pw.println(" "); + pw.println(" "); + } + if (key.equals("prefix")) { + pw.println(" "); + pw.println(" "); + } + if (key.equals("noInterfaces") && "true".equals(value)) { + pw.println(" "); + } + if (key.equals("noNotification") && "true".equals(value)) { + pw.println(" "); + } + if (key.equals("noContainer") && "true".equals(value)) { + pw.println(" "); + } + if (key.equals("noUnsettable") && "true".equals(value)) { + pw.println(" "); + } + } + + // Generate target directory parameter + String targetDirectory = configuration.get("targetDirectory"); + if (targetDirectory == null) { + targetDirectory = "target/sdo-source"; + } else if (targetDirectory.startsWith(baseDir)) { + targetDirectory = targetDirectory.substring(baseDir.length()); + } + pw.println(" "); + pw.println(" "); + + // Generate schema file parameter + String schemaFile = configuration.get("schemaFile"); + if (schemaFile == null) { + schemaFile = configuration.get("fileName"); + } + if (schemaFile != null) { + if (schemaFile.startsWith(baseDir)) { + schemaFile = schemaFile.substring(baseDir.length()); + } + pw.println(" "); + } + + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + } + } + } + + // Generate Ant task equivalent to the Tuscany WSDL2Java plugin + else if ("org.apache.tuscany.sca".equals(plugin.getGroupId()) && "tuscany-maven-wsdl2java".equals(plugin.getArtifactId())) { + for (PluginExecution execution: (List)plugin.getExecutions()) { + for (Map configuration: pluginConfigurations(execution)) { + + pw.println(" "); + + // Generate the various code generation options + for (Map.Entry element: configuration.entrySet()) { + String key = element.getKey(); + String value = element.getValue(); + if (key.equals("javaPackage")) { + pw.println(" "); + pw.println(" "); + } + } + + // Generate target directory parameter + String targetDirectory = configuration.get("targetDirectory"); + if (targetDirectory == null) { + targetDirectory = "target/wsdl2java-source"; + } else if (targetDirectory.startsWith(baseDir)) { + targetDirectory = targetDirectory.substring(baseDir.length()); + } + pw.println(" "); + pw.println(" "); + + // Generate WSDL file parameter + String wsdlFile = configuration.get("wsdlFile"); + if (wsdlFile == null) { + wsdlFile = configuration.get("fileName"); + } + if (wsdlFile != null) { + if (wsdlFile.startsWith(baseDir)) { + wsdlFile = wsdlFile.substring(baseDir.length()); + } + pw.println(" "); + } + + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + } + } + } + } + } + + /** + * Generate license header. + * + * @param pw PrintWriter to write to + */ + private void generateLicenseHeader(PrintWriter pw) { + pw.println(""); + pw.println(); + } + +} \ No newline at end of file diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/NOTICE new file mode 100644 index 0000000000..25bb89c9b2 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/pom.xml new file mode 100644 index 0000000000..8c3a9576c9 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/pom.xml @@ -0,0 +1,81 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 2.0-M1 + ../pom.xml + + tuscany-maven-bundle-plugin + maven-plugin + Apache Tuscany SCA Maven OSGi Bundle Plugin + + + + org.apache.maven + maven-plugin-api + 2.0.8 + + + + org.apache.maven + maven-project + 2.0.8 + + + + org.apache.maven + maven-settings + 2.0.8 + + + + org.apache.maven + maven-artifact + 2.0.8 + + + + org.apache.maven + maven-model + 2.0.8 + + + + org.apache.maven.shared + maven-dependency-tree + 1.1 + + + + org.apache.felix + maven-bundle-plugin + 1.4.3 + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.5.1 + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/AbstractIdeSupportMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/AbstractIdeSupportMojo.java new file mode 100644 index 0000000000..8d2663a8b9 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/AbstractIdeSupportMojo.java @@ -0,0 +1,1136 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.maven.plugin.eclipse; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TreeSet; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.zip.ZipFile; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactCollector; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.artifact.resolver.DebugResolutionListener; +import org.apache.maven.artifact.resolver.ResolutionNode; +import org.apache.maven.artifact.resolver.WarningResolutionListener; +import org.apache.maven.artifact.resolver.filter.ArtifactFilter; +import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.DependencyManagement; +import org.apache.maven.model.Exclusion; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.eclipse.Constants; +import org.apache.maven.plugin.ide.IdeDependency; +import org.apache.maven.plugin.ide.IdeUtils; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.logging.LogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.IOUtil; + +/** + * Abstract base plugin which takes care of the common stuff usually needed by maven IDE plugins. A plugin extending + * AbstractIdeSupportMojo should implement the setup() and writeConfiguration() methods, + * plus the getters needed to get the various configuration flags and required components. The lifecycle: + * + *
+ *       *** calls setup() where you can configure your specific stuff and stop the mojo from execute if appropriate ***
+ *       - manually resolve project dependencies, NOT failing if a dependency is missing
+ *       - compute project references (reactor projects) if the getUseProjectReferences() flag is set
+ *       - download sources/javadocs if the getDownloadSources() flag is set
+ *       *** calls writeConfiguration(), passing the list of resolved referenced dependencies ***
+ *       - report the list of missing sources or just tell how to turn this feature on if the flag was disabled
+ * 
+ * + * @author Fabrizio Giustina + * @version $Id: AbstractIdeSupportMojo.java 628794 2008-02-18 16:09:11Z aheritier $ + */ +public abstract class AbstractIdeSupportMojo + extends AbstractMojo + implements LogEnabled +{ + /** + * Is it an PDE project? If yes, the plugin adds the necessary natures and build commands to the .project file. + * Additionally it copies all libraries to a project local directory and references them instead of referencing the + * files in the local Maven repository. It also ensured that the "Bundle-Classpath" in META-INF/MANIFEST.MF is + * synchronized. + * + * @parameter expression="${eclipse.pde}" default-value="true" + */ + protected boolean pde; + + /** + * The project whose project files to create. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + protected MavenProject project; + + // [rfeng] Change it to use the current project + /** + * The currently executed project (can be a reactor project). + * + * @parameter expression="${executedProject}" + * @readonly + */ + protected MavenProject executedProject; + + /** + * The project packaging. + * + * @parameter expression="${project.packaging}" + */ + protected String packaging; + + /** + * Artifact factory, needed to download source jars for inclusion in classpath. + * + * @component role="org.apache.maven.artifact.factory.ArtifactFactory" + * @required + * @readonly + */ + protected ArtifactFactory artifactFactory; + + /** + * Artifact resolver, needed to download source jars for inclusion in classpath. + * + * @component role="org.apache.maven.artifact.resolver.ArtifactResolver" + * @required + * @readonly + */ + protected ArtifactResolver artifactResolver; + + /** + * Artifact collector, needed to resolve dependencies. + * + * @component role="org.apache.maven.artifact.resolver.ArtifactCollector" + * @required + * @readonly + */ + protected ArtifactCollector artifactCollector; + + /** + * @component role="org.apache.maven.artifact.metadata.ArtifactMetadataSource" hint="maven" + */ + protected ArtifactMetadataSource artifactMetadataSource; + + /** + * Remote repositories which will be searched for source attachments. + * + * @parameter expression="${project.remoteArtifactRepositories}" + * @required + * @readonly + */ + protected List remoteArtifactRepositories; + + /** + * Local maven repository. + * + * @parameter expression="${localRepository}" + * @required + * @readonly + */ + protected ArtifactRepository localRepository; + + /** + * If the executed project is a reactor project, this will contains the full list of projects in the reactor. + * + * @parameter expression="${reactorProjects}" + * @required + * @readonly + */ + protected List reactorProjects; + + /** + * Skip the operation when true. + * + * @parameter expression="${eclipse.skip}" default-value="false" + */ + private boolean skip; + + /** + * Enables/disables the downloading of source attachments. Defaults to false. When this flag is true + * remote repositories are checked for sources: in order to avoid repeated check for unavailable source archives, a + * status cache is mantained into the target dir of the root project. Run mvn:clean or delete the + * file mvn-eclipse-cache.properties in order to reset this cache. + * + * @parameter expression="${downloadSources}" + */ + protected boolean downloadSources; + + /** + * Enables/disables the downloading of javadoc attachments. Defaults to false. When this flag is true + * remote repositories are checked for javadocs: in order to avoid repeated check for unavailable javadoc archives, + * a status cache is mantained into the target dir of the root project. Run mvn:clean or delete the + * file mvn-eclipse-cache.properties in order to reset this cache. + * + * @parameter expression="${downloadJavadocs}" + */ + protected boolean downloadJavadocs; + + /** + * Plexus logger needed for debugging manual artifact resolution. + */ + protected Logger logger; + + /** + * Getter for artifactMetadataSource. + * + * @return Returns the artifactMetadataSource. + */ + public ArtifactMetadataSource getArtifactMetadataSource() + { + return artifactMetadataSource; + } + + /** + * Setter for artifactMetadataSource. + * + * @param artifactMetadataSource The artifactMetadataSource to set. + */ + public void setArtifactMetadataSource( ArtifactMetadataSource artifactMetadataSource ) + { + this.artifactMetadataSource = artifactMetadataSource; + } + + /** + * Getter for project. + * + * @return Returns the project. + */ + public MavenProject getProject() + { + return project; + } + + /** + * Setter for project. + * + * @param project The project to set. + */ + public void setProject( MavenProject project ) + { + this.project = project; + } + + /** + * Getter for reactorProjects. + * + * @return Returns the reactorProjects. + */ + public List getReactorProjects() + { + return reactorProjects; + } + + /** + * Setter for reactorProjects. + * + * @param reactorProjects The reactorProjects to set. + */ + public void setReactorProjects( List reactorProjects ) + { + this.reactorProjects = reactorProjects; + } + + /** + * Getter for remoteArtifactRepositories. + * + * @return Returns the remoteArtifactRepositories. + */ + public List getRemoteArtifactRepositories() + { + return remoteArtifactRepositories; + } + + /** + * Setter for remoteArtifactRepositories. + * + * @param remoteArtifactRepositories The remoteArtifactRepositories to set. + */ + public void setRemoteArtifactRepositories( List remoteArtifactRepositories ) + { + this.remoteArtifactRepositories = remoteArtifactRepositories; + } + + /** + * Getter for artifactFactory. + * + * @return Returns the artifactFactory. + */ + public ArtifactFactory getArtifactFactory() + { + return artifactFactory; + } + + /** + * Setter for artifactFactory. + * + * @param artifactFactory The artifactFactory to set. + */ + public void setArtifactFactory( ArtifactFactory artifactFactory ) + { + this.artifactFactory = artifactFactory; + } + + /** + * Getter for artifactResolver. + * + * @return Returns the artifactResolver. + */ + public ArtifactResolver getArtifactResolver() + { + return artifactResolver; + } + + /** + * Setter for artifactResolver. + * + * @param artifactResolver The artifactResolver to set. + */ + public void setArtifactResolver( ArtifactResolver artifactResolver ) + { + this.artifactResolver = artifactResolver; + } + + /** + * Getter for executedProject. + * + * @return Returns the executedProject. + */ + public MavenProject getExecutedProject() + { + return executedProject; + } + + /** + * Setter for executedProject. + * + * @param executedProject The executedProject to set. + */ + public void setExecutedProject( MavenProject executedProject ) + { + this.executedProject = executedProject; + } + + /** + * Getter for localRepository. + * + * @return Returns the localRepository. + */ + public ArtifactRepository getLocalRepository() + { + return localRepository; + } + + /** + * Setter for localRepository. + * + * @param localRepository The localRepository to set. + */ + public void setLocalRepository( ArtifactRepository localRepository ) + { + this.localRepository = localRepository; + } + + /** + * Getter for downloadJavadocs. + * + * @return Returns the downloadJavadocs. + */ + public boolean getDownloadJavadocs() + { + return downloadJavadocs; + } + + /** + * Setter for downloadJavadocs. + * + * @param downloadJavadocs The downloadJavadocs to set. + */ + public void setDownloadJavadocs( boolean downloadJavadoc ) + { + downloadJavadocs = downloadJavadoc; + } + + /** + * Getter for downloadSources. + * + * @return Returns the downloadSources. + */ + public boolean getDownloadSources() + { + return downloadSources; + } + + /** + * Setter for downloadSources. + * + * @param downloadSources The downloadSources to set. + */ + public void setDownloadSources( boolean downloadSources ) + { + this.downloadSources = downloadSources; + } + + protected void setResolveDependencies( boolean resolveDependencies ) + { + this.resolveDependencies = resolveDependencies; + } + + protected boolean isResolveDependencies() + { + return resolveDependencies; + } + + /** + * return false if projects available in a reactor build should be considered normal dependencies, + * true if referenced project will be linked and not need artifact resolution. + * + * @return true if referenced project will be linked and not need artifact resolution + */ + protected abstract boolean getUseProjectReferences(); + + /** + * Hook for preparation steps before the actual plugin execution. + * + * @return true if execution should continue or false if not. + * @throws MojoExecutionException generic mojo exception + */ + protected abstract boolean setup() + throws MojoExecutionException; + + /** + * Main plugin method where dependencies should be processed in order to generate IDE configuration files. + * + * @param deps list of IdeDependency objects, with artifacts, sources and javadocs already resolved + * @throws MojoExecutionException generic mojo exception + */ + protected abstract void writeConfiguration( IdeDependency[] deps ) + throws MojoExecutionException; + + /** + * Not a plugin parameter. Collect the list of dependencies with a missing source artifact for the final report. + */ + private List missingSourceDependencies = new ArrayList(); + + /** + * Not a plugin parameter. Collect the list of dependencies with a missing javadoc artifact for the final report. + */ + // TODO merge this with the missingSourceDependencies in a classifier based map? + private List missingJavadocDependencies = new ArrayList(); + + /** + * Cached array of resolved dependencies. + */ + private IdeDependency[] ideDeps; + + /** + * Flag for mojo implementations to control whether normal maven dependencies should be resolved. Default value is + * true. + */ + private boolean resolveDependencies = true; + + /** + * @see org.codehaus.plexus.logging.LogEnabled#enableLogging(org.codehaus.plexus.logging.Logger) + */ + public void enableLogging( Logger logger ) + { + this.logger = logger; + } + + /** + * @see org.apache.maven.plugin.Mojo#execute() + */ + public final void execute() + throws MojoExecutionException, MojoFailureException + { + if ( skip ) + { + return; + } + + boolean processProject = setup(); + if ( !processProject ) + { + return; + } + + // resolve artifacts + IdeDependency[] deps = doDependencyResolution(); + + resolveSourceAndJavadocArtifacts( deps ); + + writeConfiguration( deps ); + + reportMissingArtifacts(); + + } + + /** + * Resolve project dependencies. Manual resolution is needed in order to avoid resolution of multiproject artifacts + * (if projects will be linked each other an installed jar is not needed) and to avoid a failure when a jar is + * missing. + * + * @throws MojoExecutionException if dependencies can't be resolved + * @return resolved IDE dependencies, with attached jars for non-reactor dependencies + */ + protected IdeDependency[] doDependencyResolution() + throws MojoExecutionException + { + if ( ideDeps == null ) + { + if ( resolveDependencies ) + { + MavenProject project = getProject(); + ArtifactRepository localRepo = getLocalRepository(); + + List deps = getProject().getDependencies(); + + // Collect the list of resolved IdeDependencies. + List dependencies = new ArrayList(); + + if ( deps != null ) + { + Map managedVersions = + createManagedVersionMap( getArtifactFactory(), project.getId(), + project.getDependencyManagement() ); + + ArtifactResolutionResult artifactResolutionResult = null; + + try + { + + List listeners = new ArrayList(); + + if ( logger.isDebugEnabled() ) + { + listeners.add( new DebugResolutionListener( logger ) ); + } + + listeners.add( new WarningResolutionListener( logger ) ); + + artifactResolutionResult = + artifactCollector.collect( getProjectArtifacts(), project.getArtifact(), managedVersions, + localRepo, project.getRemoteArtifactRepositories(), + getArtifactMetadataSource(), null, listeners ); + } + catch ( ArtifactResolutionException e ) + { + getLog().debug( e.getMessage(), e ); + getLog().error( + Messages.getString( "artifactresolution", new Object[] { //$NON-NLS-1$ + e.getGroupId(), e.getArtifactId(), e.getVersion(), + e.getMessage() } ) ); + + // if we are here artifactResolutionResult is null, create a project without dependencies but + // don't fail + // (this could be a reactor projects, we don't want to fail everything) + // Causes MECLIPSE-185. Not sure if it should be handled this way?? + return new IdeDependency[0]; + } + + // keep track of added reactor projects in order to avoid duplicates + Set emittedReactorProjectId = new HashSet(); + + for ( Iterator i = artifactResolutionResult.getArtifactResolutionNodes().iterator(); i.hasNext(); ) + { + + ResolutionNode node = (ResolutionNode) i.next(); + int dependencyDepth = node.getDepth(); + Artifact art = node.getArtifact(); + // don't resolve jars for reactor projects + if ( hasToResolveJar( art ) ) + { + try + { + artifactResolver.resolve( art, node.getRemoteRepositories(), localRepository ); + } + catch ( ArtifactNotFoundException e ) + { + getLog().debug( e.getMessage(), e ); + getLog().warn( + Messages.getString( "artifactdownload", new Object[] { //$NON-NLS-1$ + e.getGroupId(), e.getArtifactId(), e.getVersion(), + e.getMessage() } ) ); + } + catch ( ArtifactResolutionException e ) + { + getLog().debug( e.getMessage(), e ); + getLog().warn( + Messages.getString( "artifactresolution", new Object[] { //$NON-NLS-1$ + e.getGroupId(), e.getArtifactId(), e.getVersion(), + e.getMessage() } ) ); + } + } + + boolean includeArtifact = true; + if ( getExcludes() != null ) + { + String artifactFullId = art.getGroupId() + ":" + art.getArtifactId(); + if ( getExcludes().contains( artifactFullId ) ) + { + getLog().info( "excluded: " + artifactFullId ); + includeArtifact = false; + } + } + + if ( includeArtifact && + ( !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) ) || emittedReactorProjectId.add( art.getGroupId() + + '-' + art.getArtifactId() ) ) ) + { + + // the following doesn't work: art.getArtifactHandler().getPackaging() always returns "jar" + // also + // if the packaging specified in pom.xml is different. + + // osgi-bundle packaging is provided by the felix osgi plugin + // eclipse-plugin packaging is provided by this eclipse plugin + // String packaging = art.getArtifactHandler().getPackaging(); + // boolean isOsgiBundle = "osgi-bundle".equals( packaging ) || "eclipse-plugin".equals( + // packaging ); + + // we need to check the manifest, if "Bundle-SymbolicName" is there the artifact can be + // considered + // an osgi bundle + boolean isOsgiBundle = false; + String osgiSymbolicName = null; + if ( art.getFile() != null ) + { + JarFile jarFile = null; + try + { + jarFile = new JarFile( art.getFile(), false, ZipFile.OPEN_READ ); + + Manifest manifest = jarFile.getManifest(); + if ( manifest != null ) + { + osgiSymbolicName = + manifest.getMainAttributes().getValue( + new Attributes.Name( + "Bundle-SymbolicName" ) ); + } + } + catch ( IOException e ) + { + getLog().info( "Unable to read jar manifest from " + art.getFile() ); + } + finally + { + if ( jarFile != null ) + { + try + { + jarFile.close(); + } + catch ( IOException e ) + { + // ignore + } + } + } + } + + isOsgiBundle = osgiSymbolicName != null; + + IdeDependency dep = + new IdeDependency( art.getGroupId(), art.getArtifactId(), art.getVersion(), + art.getClassifier(), useProjectReference( art ), + Artifact.SCOPE_TEST.equals( art.getScope() ), + Artifact.SCOPE_SYSTEM.equals( art.getScope() ), + Artifact.SCOPE_PROVIDED.equals( art.getScope() ), + art.getArtifactHandler().isAddedToClasspath(), art.getFile(), + art.getType(), isOsgiBundle, osgiSymbolicName, dependencyDepth, + getProjectNameForArifact( art ) ); + // no duplicate entries allowed. System paths can cause this problem. + if ( !dependencies.contains( dep ) ) + { + // [rfeng] Do not add compile/provided dependencies + if (!(pde && (Artifact.SCOPE_COMPILE.equals(art.getScope()) || Artifact.SCOPE_PROVIDED + .equals(art.getScope())))) { + dependencies.add( dep ); + } + } + } + + } + + // @todo a final report with the list of + // missingArtifacts? + + } + + ideDeps = (IdeDependency[]) dependencies.toArray( new IdeDependency[dependencies.size()] ); + } + else + { + ideDeps = new IdeDependency[0]; + } + } + + return ideDeps; + } + + /** + * Find the name of the project as used in eclipse. + * + * @param artifact The artifact to find the eclipse name for. + * @return The name os the eclipse project. + */ + abstract public String getProjectNameForArifact( Artifact artifact ); + + /** + * Returns the list of project artifacts. Also artifacts generated from referenced projects will be added, but with + * the resolved property set to true. + * + * @return list of projects artifacts + * @throws MojoExecutionException if unable to parse dependency versions + */ + private Set getProjectArtifacts() + throws MojoExecutionException + { + // keep it sorted, this should avoid random classpath order in tests + Set artifacts = new TreeSet(); + + for ( Iterator dependencies = getProject().getDependencies().iterator(); dependencies.hasNext(); ) + { + Dependency dependency = (Dependency) dependencies.next(); + + String groupId = dependency.getGroupId(); + String artifactId = dependency.getArtifactId(); + VersionRange versionRange; + try + { + versionRange = VersionRange.createFromVersionSpec( dependency.getVersion() ); + } + catch ( InvalidVersionSpecificationException e ) + { + throw new MojoExecutionException( + Messages.getString( + "unabletoparseversion", new Object[] { //$NON-NLS-1$ + dependency.getArtifactId(), + dependency.getVersion(), + dependency.getManagementKey(), e.getMessage() } ), + e ); + } + + String type = dependency.getType(); + if ( type == null ) + { + type = Constants.PROJECT_PACKAGING_JAR; + } + String classifier = dependency.getClassifier(); + boolean optional = dependency.isOptional(); + String scope = dependency.getScope(); + if ( scope == null ) + { + scope = Artifact.SCOPE_COMPILE; + } + + Artifact art = + getArtifactFactory().createDependencyArtifact( groupId, artifactId, versionRange, type, classifier, + scope, optional ); + + if ( scope.equalsIgnoreCase( Artifact.SCOPE_SYSTEM ) ) + { + art.setFile( new File( dependency.getSystemPath() ) ); + } + + List exclusions = new ArrayList(); + for ( Iterator j = dependency.getExclusions().iterator(); j.hasNext(); ) + { + Exclusion e = (Exclusion) j.next(); + exclusions.add( e.getGroupId() + ":" + e.getArtifactId() ); //$NON-NLS-1$ + } + + ArtifactFilter newFilter = new ExcludesArtifactFilter( exclusions ); + + art.setDependencyFilter( newFilter ); + + artifacts.add( art ); + } + + return artifacts; + } + + /** + * Utility method that locates a project producing the given artifact. + * + * @param artifact the artifact a project should produce. + * @return true if the artifact is produced by a reactor projectart. + */ + protected boolean isAvailableAsAReactorProject( Artifact artifact ) + { + if ( reactorProjects != null ) + { + for ( Iterator iter = reactorProjects.iterator(); iter.hasNext(); ) + { + MavenProject reactorProject = (MavenProject) iter.next(); + + if ( reactorProject.getGroupId().equals( artifact.getGroupId() ) && + reactorProject.getArtifactId().equals( artifact.getArtifactId() ) ) + { + if ( reactorProject.getVersion().equals( artifact.getVersion() ) ) + { + return true; + } + else + { + getLog().info( + "Artifact " + + artifact.getId() + + " already available as a reactor project, but with different version. Expected: " + + artifact.getVersion() + ", found: " + reactorProject.getVersion() ); + } + } + } + } + return false; + } + + /** + * @return an array with all dependencies avalaible in the workspace, to be implemented by the subclasses. + */ + protected IdeDependency[] getWorkspaceArtefacts() + { + return new IdeDependency[0]; + } + + private Map createManagedVersionMap( ArtifactFactory artifactFactory, String projectId, + DependencyManagement dependencyManagement ) + throws MojoExecutionException + { + Map map; + if ( dependencyManagement != null && dependencyManagement.getDependencies() != null ) + { + map = new HashMap(); + for ( Iterator i = dependencyManagement.getDependencies().iterator(); i.hasNext(); ) + { + Dependency d = (Dependency) i.next(); + + try + { + VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() ); + Artifact artifact = + artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange, + d.getType(), d.getClassifier(), d.getScope(), + d.isOptional() ); + map.put( d.getManagementKey(), artifact ); + } + catch ( InvalidVersionSpecificationException e ) + { + throw new MojoExecutionException( Messages.getString( "unabletoparseversion", new Object[] { //$NON-NLS-1$ + projectId, d.getVersion(), + d.getManagementKey(), e.getMessage() } ), + e ); + } + } + } + else + { + map = Collections.EMPTY_MAP; + } + return map; + } + + /** + * Find the reactor target dir. executedProject doesn't have the multiproject root dir set, and the only way to + * extract it is iterating on parent projects. + * + * @param prj current project + * @return the parent target dir. + */ + private File getReactorTargetDir( MavenProject prj ) + { + if ( prj.getParent() != null ) + { + if ( prj.getParent().getBasedir() != null && prj.getParent().getBasedir().exists() ) + { + return getReactorTargetDir( prj.getParent() ); + } + } + return new File( prj.getBuild().getDirectory() ); + } + + /** + * Resolve source artifacts and download them if downloadSources is true. Source and + * javadocs artifacts will be attached to the IdeDependency Resolve source and javadoc artifacts. The + * resolved artifacts will be downloaded based on the downloadSources and + * downloadJavadocs attributes. Source and + * + * @param deps resolved dependencies + */ + private void resolveSourceAndJavadocArtifacts( IdeDependency[] deps ) + { + + File reactorTargetDir = getReactorTargetDir( project ); + File unavailableArtifactsTmpFile = new File( reactorTargetDir, "mvn-eclipse-cache.properties" ); + + getLog().info( "Using source status cache: " + unavailableArtifactsTmpFile.getAbsolutePath() ); + + // create target dir if missing + if ( !unavailableArtifactsTmpFile.getParentFile().exists() ) + { + unavailableArtifactsTmpFile.getParentFile().mkdirs(); + } + + Properties unavailableArtifactsCache = new Properties(); + if ( unavailableArtifactsTmpFile.exists() ) + { + InputStream is = null; + try + { + is = new FileInputStream( unavailableArtifactsTmpFile ); + unavailableArtifactsCache.load( is ); + } + catch ( IOException e ) + { + getLog().warn( "Unable to read source status for reactor projects" ); + } + finally + { + IOUtil.close( is ); + } + + } + + final List missingSources = + resolveDependenciesWithClassifier( deps, "sources", getDownloadSources(), unavailableArtifactsCache ); + missingSourceDependencies.addAll( missingSources ); + + final List missingJavadocs = + resolveDependenciesWithClassifier( deps, "javadoc", getDownloadJavadocs(), unavailableArtifactsCache ); + missingJavadocDependencies.addAll( missingJavadocs ); + + FileOutputStream fos = null; + try + { + fos = new FileOutputStream( unavailableArtifactsTmpFile ); + unavailableArtifactsCache.store( fos, "Temporary index for unavailable sources and javadocs" ); + } + catch ( IOException e ) + { + getLog().warn( "Unable to cache source status for reactor projects" ); + } + finally + { + IOUtil.close( fos ); + } + + } + + /** + * Resolve the required artifacts for each of the dependency. sources or javadoc + * artifacts (depending on the classifier) are attached to the dependency. + * + * @param deps resolved dependencies + * @param inClassifier the classifier we are looking for (either sources or javadoc) + * @param includeRemoteRepositories flag whether we should search remote repositories for the artifacts or not + * @param unavailableArtifactsCache cache of unavailable artifacts + * @return the list of dependencies for which the required artifact was not found + */ + private List resolveDependenciesWithClassifier( IdeDependency[] deps, String inClassifier, + boolean includeRemoteRepositories, + Properties unavailableArtifactsCache ) + { + List missingClassifierDependencies = new ArrayList(); + + // if downloadSources is off, just check + // local repository for reporting missing source jars + List remoteRepos = includeRemoteRepositories ? getRemoteArtifactRepositories() : Collections.EMPTY_LIST; + + for ( int j = 0; j < deps.length; j++ ) + { + IdeDependency dependency = deps[j]; + + if ( dependency.isReferencedProject() || dependency.isSystemScoped() ) + { + // artifact not needed + continue; + } + + if ( getLog().isDebugEnabled() ) + { + getLog().debug( + "Searching for sources for " + dependency.getId() + ":" + dependency.getClassifier() + + " at " + dependency.getId() + ":" + inClassifier ); + } + + String key = + dependency.getClassifier() == null ? dependency.getId() + ":" + inClassifier : dependency.getId() + + ":" + inClassifier + ":" + dependency.getClassifier(); + + if ( !unavailableArtifactsCache.containsKey( key ) ) + { + Artifact artifact = + IdeUtils.resolveArtifactWithClassifier( dependency.getGroupId(), dependency.getArtifactId(), + dependency.getVersion(), dependency.getClassifier(), + inClassifier, localRepository, artifactResolver, + artifactFactory, remoteRepos, getLog() ); + if ( artifact.isResolved() ) + { + if ( "sources".equals( inClassifier ) ) + { + dependency.setSourceAttachment( artifact.getFile() ); + } + else if ( "javadoc".equals( inClassifier ) ) + { + dependency.setJavadocAttachment( artifact.getFile() ); + } + } + else + { + unavailableArtifactsCache.put( key, Boolean.TRUE.toString() ); + // add the dependencies to the list + // of those lacking the required + // artifact + missingClassifierDependencies.add( dependency ); + } + } + } + + // return the list of dependencies missing the + // required artifact + return missingClassifierDependencies; + + } + + /** + * Output a message with the list of missing dependencies and info on how turn download on if it was disabled. + */ + private void reportMissingArtifacts() + { + StringBuffer msg = new StringBuffer(); + + if ( !missingSourceDependencies.isEmpty() ) + { + if ( getDownloadSources() ) + { + msg.append( Messages.getString( "sourcesnotavailable" ) ); //$NON-NLS-1$ + } + else + { + msg.append( Messages.getString( "sourcesnotdownloaded" ) ); //$NON-NLS-1$ + } + + for ( Iterator it = missingSourceDependencies.iterator(); it.hasNext(); ) + { + IdeDependency art = (IdeDependency) it.next(); + msg.append( Messages.getString( "sourcesmissingitem", art.getId() ) ); //$NON-NLS-1$ + } + msg.append( "\n" ); //$NON-NLS-1$ + } + + if ( !missingJavadocDependencies.isEmpty() ) + { + if ( getDownloadJavadocs() ) + { + msg.append( Messages.getString( "javadocnotavailable" ) ); //$NON-NLS-1$ + } + else + { + msg.append( Messages.getString( "javadocnotdownloaded" ) ); //$NON-NLS-1$ + } + + for ( Iterator it = missingJavadocDependencies.iterator(); it.hasNext(); ) + { + IdeDependency art = (IdeDependency) it.next(); + msg.append( Messages.getString( "javadocmissingitem", art.getId() ) ); //$NON-NLS-1$ + } + msg.append( "\n" ); //$NON-NLS-1$ + } + getLog().info( msg ); + } + + /** + * @return List of dependencies to exclude from eclipse classpath. + * @since 2.5 + */ + public abstract List getExcludes(); + + /** + * Checks if jar has to be resolved for the given artifact + * + * @param art the artifact to check + * @return true if resolution should happen + */ + protected boolean hasToResolveJar( Artifact art ) + { + return !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) ); + } + + /** + * Checks if a projects reference has to be used for the given artifact + * + * @param art the artifact to check + * @return true if a project reference has to be used. + */ + protected boolean useProjectReference( Artifact art ) + { + return getUseProjectReferences() && isAvailableAsAReactorProject( art ); + } + + protected boolean isOSGiBundle() { + File base = project.getBasedir(); + File mf = new File(base, "META-INF/MANIFEST.MF"); + if (mf.isFile()) { + Manifest manifest = null; + try { + InputStream is = new FileInputStream(mf); + manifest = new Manifest(is); + is.close(); + } catch (IOException e) { + // Ignore + } + if (manifest != null) { + String bundleName = manifest.getMainAttributes().getValue("Bundle-SymbolicName"); + if (bundleName != null) { + return true; + } + } + } + return false; + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseClasspathWriter.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseClasspathWriter.java new file mode 100644 index 0000000000..88afd024db --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseClasspathWriter.java @@ -0,0 +1,530 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.maven.plugin.eclipse; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.eclipse.Constants; +import org.apache.maven.plugin.eclipse.EclipseSourceDir; +import org.apache.maven.plugin.eclipse.writers.AbstractEclipseWriter; +import org.apache.maven.plugin.ide.IdeDependency; +import org.apache.maven.plugin.ide.IdeUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * Writes eclipse .classpath file. + * + * @author Trygve Laugstøl + * @author Kenney Westerhof + * @author Fabrizio Giustina + * @version $Id: EclipseClasspathWriter.java 636955 2008-03-14 02:10:42Z aheritier $ + */ +public class EclipseClasspathWriter + extends AbstractEclipseWriter +{ + + /** + * Eclipse build path variable M2_REPO + */ + private static final String M2_REPO = "M2_REPO"; //$NON-NLS-1$ + + /** + * Attribute for sourcepath. + */ + private static final String ATTR_SOURCEPATH = "sourcepath"; //$NON-NLS-1$ + + /** + * Attribute for output. + */ + private static final String ATTR_OUTPUT = "output"; //$NON-NLS-1$ + + /** + * Attribute for path. + */ + private static final String ATTR_PATH = "path"; //$NON-NLS-1$ + + /** + * Attribute for kind - Container (con), Variable (var)..etc. + */ + private static final String ATTR_KIND = "kind"; //$NON-NLS-1$ + + /** + * Attribute value for kind: var + */ + private static final String ATTR_VAR = "var"; //$NON-NLS-1$ + + /** + * Attribute value for kind: lib + */ + private static final String ATTR_LIB = "lib"; //$NON-NLS-1$ + + /** + * Attribute value for kind: src + */ + private static final String ATTR_SRC = "src"; //$NON-NLS-1$ + + /** + * Attribute name for source file includes in a path. + */ + private static final String ATTR_INCLUDING = "including"; + + /** + * Attribute name for source file excludes in a path. + */ + private static final String ATTR_EXCLUDING = "excluding"; + + /** + * Element for classpathentry. + */ + private static final String ELT_CLASSPATHENTRY = "classpathentry"; //$NON-NLS-1$ + + /** + * Element for classpath. + */ + private static final String ELT_CLASSPATH = "classpath"; //$NON-NLS-1$ + + /** + * File name that stores project classpath settings. + */ + private static final String FILE_DOT_CLASSPATH = ".classpath"; //$NON-NLS-1$ + + /** + * @see org.apache.tuscany.sca.maven.plugin.eclipse.writers.EclipseWriter#write() + */ + public void write() + throws MojoExecutionException + { + + Writer w; + + try + { + w = + new OutputStreamWriter( new FileOutputStream( new File( config.getEclipseProjectDirectory(), + FILE_DOT_CLASSPATH ) ), "UTF-8" ); + } + catch ( IOException ex ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex ); //$NON-NLS-1$ + } + + XMLWriter writer = new PrettyPrintXMLWriter( w ); + + writer.startElement( ELT_CLASSPATH ); + + String defaultOutput = + IdeUtils.toRelativeAndFixSeparator( config.getProjectBaseDir(), config.getBuildOutputDirectory(), false ); + + // ---------------------------------------------------------------------- + // Source roots and resources + // ---------------------------------------------------------------------- + + // List + List specialSources = new ArrayList(); + + // Map> + Map byOutputDir = new HashMap(); + + for ( int j = 0; j < config.getSourceDirs().length; j++ ) + { + EclipseSourceDir dir = config.getSourceDirs()[j]; + + // List + List byOutputDirs = (List) byOutputDir.get( dir.getOutput() ); + if ( byOutputDirs == null ) + { + // ArrayList + byOutputDir.put( dir.getOutput() == null ? defaultOutput : dir.getOutput(), byOutputDirs = + new ArrayList() ); + } + byOutputDirs.add( dir ); + } + + for ( int j = 0; j < config.getSourceDirs().length; j++ ) + { + EclipseSourceDir dir = config.getSourceDirs()[j]; + + log.debug( "Processing " + ( dir.isResource() ? "re" : "" ) + "source " + dir.getPath() + ": output=" + + dir.getOutput() + "; default output=" + defaultOutput ); + + boolean isSpecial = false; + + // handle resource with nested output folders + if ( dir.isResource() ) + { + // Check if the output is a subdirectory of the default output, + // and if the default output has any sources that copy there. + + if ( dir.getOutput() != null // resource output dir is set + && + !dir.getOutput().equals( defaultOutput ) // output dir is not default target/classes + && dir.getOutput().startsWith( defaultOutput ) // ... but is nested + && byOutputDir.get( defaultOutput ) != null // ??? + && !( (List) byOutputDir.get( defaultOutput ) ).isEmpty() // ??? + ) + { + // do not specify as source since the output will be nested. Instead, mark + // it as a todo, and handle it with a custom build.xml file later. + + log.debug( "Marking as special to prevent output folder nesting: " + dir.getPath() + " (output=" + + dir.getOutput() + ")" ); + + isSpecial = true; + specialSources.add( dir ); + } + } + + writer.startElement( ELT_CLASSPATHENTRY ); + + writer.addAttribute( ATTR_KIND, "src" ); //$NON-NLS-1$ + writer.addAttribute( ATTR_PATH, dir.getPath() ); + + if ( !isSpecial && dir.getOutput() != null && !defaultOutput.equals( dir.getOutput() ) ) + { + writer.addAttribute( ATTR_OUTPUT, dir.getOutput() ); + } + + if ( StringUtils.isNotEmpty( dir.getInclude() ) ) + { + writer.addAttribute( ATTR_INCLUDING, dir.getInclude() ); + } + + String excludes = dir.getExclude(); + + if ( dir.isResource() ) + { + // automatically exclude java files: eclipse doesn't have the concept of resource directory so it will + // try to compile any java file found in maven resource dirs + excludes = StringUtils.isEmpty( excludes ) ? "**/*.java" : excludes + "|**/*.java"; + } + + if ( StringUtils.isNotEmpty( excludes ) ) + { + writer.addAttribute( ATTR_EXCLUDING, excludes ); + } + + writer.endElement(); + + } + + /* --------------- Commented out by rfeng + // handle the special sources. + if ( !specialSources.isEmpty() ) + { + log.info( "Creating maven-eclipse.xml Ant file to handle resources" ); + + try + { + Writer buildXmlWriter = + new OutputStreamWriter( new FileOutputStream( new File( config.getEclipseProjectDirectory(), + "maven-eclipse.xml" ) ), "UTF-8" ); + PrettyPrintXMLWriter buildXmlPrinter = new PrettyPrintXMLWriter( buildXmlWriter ); + + buildXmlPrinter.startElement( "project" ); + buildXmlPrinter.addAttribute( "default", "copy-resources" ); + + buildXmlPrinter.startElement( "target" ); + buildXmlPrinter.addAttribute( "name", "init" ); + // initialize filtering tokens here + buildXmlPrinter.endElement(); + + buildXmlPrinter.startElement( "target" ); + buildXmlPrinter.addAttribute( "name", "copy-resources" ); + buildXmlPrinter.addAttribute( "depends", "init" ); + + for ( Iterator it = specialSources.iterator(); it.hasNext(); ) + { + // TODO: merge source dirs on output path+filtering to reduce + // tags for speed. + EclipseSourceDir dir = (EclipseSourceDir) it.next(); + buildXmlPrinter.startElement( "copy" ); + buildXmlPrinter.addAttribute( "todir", dir.getOutput() ); + buildXmlPrinter.addAttribute( "filtering", "" + dir.isFiltering() ); + + buildXmlPrinter.startElement( "fileset" ); + buildXmlPrinter.addAttribute( "dir", dir.getPath() ); + if ( dir.getInclude() != null ) + { + buildXmlPrinter.addAttribute( "includes", dir.getInclude() ); + } + if ( dir.getExclude() != null ) + { + buildXmlPrinter.addAttribute( "excludes", dir.getExclude() ); + } + buildXmlPrinter.endElement(); + + buildXmlPrinter.endElement(); + } + + buildXmlPrinter.endElement(); + + buildXmlPrinter.endElement(); + + IOUtil.close( buildXmlWriter ); + } + catch ( IOException e ) + { + throw new MojoExecutionException( "Cannot create " + config.getEclipseProjectDirectory() + + "/maven-eclipse.xml", e ); + } + + log.info( "Creating external launcher file" ); + // now create the launcher + new EclipseAntExternalLaunchConfigurationWriter().init( log, config, "Maven_Ant_Builder.launch", + "maven-eclipse.xml" ).write(); + + // finally add it to the project writer. + + config.getBuildCommands().add( + new BuildCommand( + "org.eclipse.ui.externaltools.ExternalToolBuilder", + "LaunchConfigHandle", + "/" + + EclipseLaunchConfigurationWriter.FILE_DOT_EXTERNAL_TOOL_BUILDERS + + "Maven_Ant_Builder.launch" ) ); + } + */ + + // ---------------------------------------------------------------------- + // The default output + // ---------------------------------------------------------------------- + + writer.startElement( ELT_CLASSPATHENTRY ); + writer.addAttribute( ATTR_KIND, ATTR_OUTPUT ); + writer.addAttribute( ATTR_PATH, defaultOutput ); + writer.endElement(); + + // ---------------------------------------------------------------------- + // Container classpath entries + // ---------------------------------------------------------------------- + + for ( Iterator it = config.getClasspathContainers().iterator(); it.hasNext(); ) + { + writer.startElement( ELT_CLASSPATHENTRY ); + writer.addAttribute( ATTR_KIND, "con" ); //$NON-NLS-1$ + writer.addAttribute( ATTR_PATH, (String) it.next() ); + writer.endElement(); // name + } + + // ---------------------------------------------------------------------- + // The dependencies + // ---------------------------------------------------------------------- + Set addedDependencies = new HashSet(); + // TODO if (..magic property equals orderDependencies..) + IdeDependency[] depsToWrite = config.getDepsOrdered(); + for ( int j = 0; j < depsToWrite.length; j++ ) + { + IdeDependency dep = depsToWrite[j]; + + if ( dep.isAddedToClasspath() ) + { + String depId = + dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getClassifier() + ":" + dep.getVersion(); + /* avoid duplicates in the classpath for artifacts with different types (like ejbs) */ + if ( !addedDependencies.contains( depId ) ) + { + addDependency( writer, dep ); + addedDependencies.add( depId ); + } + } + } + + writer.endElement(); + + IOUtil.close( w ); + + } + + protected void addDependency( XMLWriter writer, IdeDependency dep ) + throws MojoExecutionException + { + + String path; + String kind; + String sourcepath = null; + String javadocpath = null; + // [rfeng] Force to non-PDE mode + boolean pdeMode = false; + + if ( dep.isReferencedProject() && !pdeMode ) + { + path = "/" + dep.getEclipseProjectName(); //$NON-NLS-1$ + kind = ATTR_SRC; + } + else if ( dep.isReferencedProject() && pdeMode ) + { + // don't do anything, referenced projects are automatically handled by eclipse in PDE builds + return; + } + else + { + File artifactPath = dep.getFile(); + + if ( artifactPath == null ) + { + log.error( Messages.getString( "EclipsePlugin.artifactpathisnull", dep.getId() ) ); //$NON-NLS-1$ + return; + } + + if ( dep.isSystemScoped() ) + { + path = IdeUtils.toRelativeAndFixSeparator( config.getEclipseProjectDirectory(), artifactPath, false ); + + if ( log.isDebugEnabled() ) + { + log.debug( Messages.getString( "EclipsePlugin.artifactissystemscoped", //$NON-NLS-1$ + new Object[] { dep.getArtifactId(), path } ) ); + } + + kind = ATTR_LIB; + } + else + { + File localRepositoryFile = new File( config.getLocalRepository().getBasedir() ); + + // if the dependency is not provided and the plugin runs in "pde mode", the dependency is + // added to the Bundle-Classpath: + if ( pdeMode && ( dep.isProvided() || dep.isOsgiBundle() ) ) + { + return; + } + else if ( pdeMode && !dep.isProvided() && !dep.isTestDependency() ) + { + // path for link created in .project, not to the actual file + path = dep.getFile().getName(); + + kind = ATTR_LIB; + } + // running in PDE mode and the dependency is provided means, that it is provided by + // the target platform. This case is covered by adding the plugin container + else + { + String fullPath = artifactPath.getPath(); + String relativePath = + IdeUtils.toRelativeAndFixSeparator( localRepositoryFile, new File( fullPath ), false ); + + if ( !new File( relativePath ).isAbsolute() ) + { + path = M2_REPO + "/" //$NON-NLS-1$ + + relativePath; + kind = ATTR_VAR; //$NON-NLS-1$ + } + else + { + path = relativePath; + kind = ATTR_LIB; + } + } + + if ( dep.getSourceAttachment() != null ) + { + if ( ATTR_VAR.equals( kind ) ) + { + sourcepath = + M2_REPO + + "/" //$NON-NLS-1$ + + + IdeUtils.toRelativeAndFixSeparator( localRepositoryFile, dep.getSourceAttachment(), + false ); + } + else + { + // source archive must be referenced with the full path, we can't mix a lib with a variable + sourcepath = IdeUtils.getCanonicalPath( dep.getSourceAttachment() ); + } + } + + if ( dep.getJavadocAttachment() != null ) + { + // NB eclipse (3.1) doesn't support variables in javadoc paths, so we need to add the + // full path for the maven repo + javadocpath = + StringUtils.replace( IdeUtils.getCanonicalPath( dep.getJavadocAttachment() ), "\\", "/" ); //$NON-NLS-1$ //$NON-NLS-2$ + } + + } + + } + + writer.startElement( ELT_CLASSPATHENTRY ); + writer.addAttribute( ATTR_KIND, kind ); + writer.addAttribute( ATTR_PATH, path ); + + if ( sourcepath != null ) + { + writer.addAttribute( ATTR_SOURCEPATH, sourcepath ); + } + + boolean attributeElemOpen = false; + + if ( javadocpath != null ) + { + if ( !attributeElemOpen ) + { + writer.startElement( "attributes" ); //$NON-NLS-1$ + attributeElemOpen = true; + } + + writer.startElement( "attribute" ); //$NON-NLS-1$ + writer.addAttribute( "value", "jar:" + new File( javadocpath ).toURI() + "!/" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + writer.addAttribute( "name", "javadoc_location" ); //$NON-NLS-1$ //$NON-NLS-2$ + writer.endElement(); + + } + + if ( Constants.PROJECT_PACKAGING_WAR.equals( this.config.getPackaging() ) && config.getWtpapplicationxml() && + kind.equals( ATTR_VAR ) && !dep.isTestDependency() && !dep.isProvided() && + !dep.isSystemScopedOutsideProject( this.config.getProject() ) ) + { + if ( !attributeElemOpen ) + { + writer.startElement( "attributes" ); //$NON-NLS-1$ + attributeElemOpen = true; + } + + writer.startElement( "attribute" ); //$NON-NLS-1$ + writer.addAttribute( "value", "/WEB-INF/lib" ); //$NON-NLS-1$ //$NON-NLS-2$ + writer.addAttribute( "name", "org.eclipse.jst.component.dependency" ); //$NON-NLS-1$ //$NON-NLS-2$ + writer.endElement(); + + } + + if ( attributeElemOpen ) + { + writer.endElement(); + } + writer.endElement(); + + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseCleanMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseCleanMojo.java new file mode 100644 index 0000000000..ac770c743c --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseCleanMojo.java @@ -0,0 +1,231 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.maven.plugin.eclipse; + +import java.io.File; +import java.io.IOException; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.eclipse.Constants; +import org.apache.maven.plugin.eclipse.EclipseConfigFile; +import org.codehaus.plexus.util.FileUtils; + +/** + * Deletes the .project, .classpath, .wtpmodules files and .settings folder used by Eclipse. + * + * @goal clean + */ +public class EclipseCleanMojo + extends AbstractMojo +{ + + /** + * Definition file for Eclipse Web Tools project. + */ + private static final String FILE_DOT_WTPMODULES = ".wtpmodules"; //$NON-NLS-1$ + + /** + * Classpath definition file for an Eclipse Java project. + */ + private static final String FILE_DOT_CLASSPATH = ".classpath"; //$NON-NLS-1$ + + /** + * Project definition file for an Eclipse Project. + */ + private static final String FILE_DOT_PROJECT = ".project"; //$NON-NLS-1$ + + /** + * Web Project definition file for Eclipse Web Tools Project (Release 1.0x). + */ + private static final String DIR_DOT_SETTINGS = ".settings"; //$NON-NLS-1$ + + /** + * File name where the WTP component settings will be stored - WTP 1.0 name. + */ + private static final String FILE_DOT_COMPONENT = ".settings/.component"; //$NON-NLS-1$ + + /** + * File name where the WTP component settings will be stored - WTP 1.5 name. + */ + private static final String FILE_DOT_COMPONENT_15 = ".settings/org.eclipse.wst.common.component"; //$NON-NLS-1$ + + /** + * File name where Eclipse Project's Facet configuration will be stored. + */ + private static final String FILE_FACET_CORE_XML = ".settings/org.eclipse.wst.common.project.facet.core.xml"; //$NON-NLS-1$ + + /** + * General project preferences. + */ + private static final String FILE_ECLIPSE_JDT_CORE_PREFS = ".settings/org.eclipse.jdt.core.prefs"; //$NON-NLS-1$ + + /** + * Packaging for the current project. + * + * @parameter expression="${project.packaging}" + */ + private String packaging; + + /** + * The root directory of the project + * + * @parameter expression="${basedir}" + */ + private File basedir; + + /** + * Skip the operation when true. + * + * @parameter expression="${eclipse.skip}" default-value="false" + */ + private boolean skip; + + /** + * additional generic configuration files for eclipse + * + * @parameter + */ + private EclipseConfigFile[] additionalConfig; + + /** + * @see org.apache.maven.plugin.AbstractMojo#execute() + */ + public void execute() + throws MojoExecutionException + { + if ( skip ) + { + return; + } + + if ( Constants.PROJECT_PACKAGING_POM.equals( this.packaging ) ) + { + return; + } + + delete( new File( basedir, FILE_DOT_PROJECT ) ); + delete( new File( basedir, FILE_DOT_CLASSPATH ) ); + delete( new File( basedir, FILE_DOT_WTPMODULES ) ); + + delete( new File( basedir, FILE_DOT_COMPONENT ) ); + delete( new File( basedir, FILE_DOT_COMPONENT_15 ) ); + delete( new File( basedir, FILE_FACET_CORE_XML ) ); + delete( new File( basedir, FILE_ECLIPSE_JDT_CORE_PREFS ) ); + + File settingsDir = new File( basedir, DIR_DOT_SETTINGS ); + if ( settingsDir.exists() && settingsDir.isDirectory() && settingsDir.list().length == 0 ) + { + delete( settingsDir ); + } + + if ( additionalConfig != null ) + { + for ( int i = 0; i < additionalConfig.length; i++ ) + { + delete( new File( basedir, additionalConfig[i].getName() ) ); + } + } + + cleanExtras(); + } + + protected void cleanExtras() + throws MojoExecutionException + { + // extension point. + } + + /** + * Delete a file, handling log messages and exceptions + * + * @param f File to be deleted + * @throws MojoExecutionException only if a file exists and can't be deleted + */ + protected void delete( File f ) + throws MojoExecutionException + { + if ( f.isDirectory() ) + { + getLog().info( Messages.getString( "EclipseCleanMojo.deletingDirectory", f.getName() ) ); //$NON-NLS-1$ + } + else + { + getLog().info( Messages.getString( "EclipseCleanMojo.deletingFile", f.getName() ) ); //$NON-NLS-1$ + } + + if ( f.exists() ) + { + if ( !f.delete() ) + { + try + { + FileUtils.forceDelete( f ); + } + catch ( IOException e ) + { + throw new MojoExecutionException( Messages.getString( "EclipseCleanMojo.failedtodelete", //$NON-NLS-1$ + new Object[] { f.getName(), + f.getAbsolutePath() } ) ); + } + } + } + else + { + getLog().debug( Messages.getString( "EclipseCleanMojo.nofilefound", f.getName() ) ); //$NON-NLS-1$ + } + } + + /** + * Getter for basedir. + * + * @return Returns the basedir. + */ + public File getBasedir() + { + return this.basedir; + } + + /** + * Setter for basedir. + * + * @param basedir The basedir to set. + */ + public void setBasedir( File basedir ) + { + this.basedir = basedir; + } + + /** + * @return the packaging + */ + public String getPackaging() + { + return this.packaging; + } + + /** + * @param packaging the packaging to set + */ + public void setPackaging( String packaging ) + { + this.packaging = packaging; + } + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipsePlugin.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipsePlugin.java new file mode 100644 index 0000000000..fccd64540b --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipsePlugin.java @@ -0,0 +1,1556 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.maven.plugin.eclipse; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.handler.ArtifactHandler; +import org.apache.maven.model.Resource; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.eclipse.BuildCommand; +import org.apache.maven.plugin.eclipse.Constants; +import org.apache.maven.plugin.eclipse.EclipseConfigFile; +import org.apache.maven.plugin.eclipse.EclipseSourceDir; +import org.apache.maven.plugin.eclipse.WorkspaceConfiguration; +import org.apache.maven.plugin.eclipse.reader.ReadWorkspaceLocations; +import org.apache.maven.plugin.eclipse.writers.EclipseManifestWriter; +import org.apache.maven.plugin.eclipse.writers.EclipseSettingsWriter; +import org.apache.maven.plugin.eclipse.writers.EclipseWriterConfig; +import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpApplicationXMLWriter; +import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpComponent15Writer; +import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpComponentWriter; +import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpFacetsWriter; +import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpmodulesWriter; +import org.apache.maven.plugin.ide.IdeDependency; +import org.apache.maven.plugin.ide.IdeUtils; +import org.apache.maven.plugin.ide.JeeUtils; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.resource.ResourceManager; +import org.codehaus.plexus.resource.loader.FileResourceLoader; +import org.codehaus.plexus.resource.loader.ResourceNotFoundException; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.Xpp3Dom; + +/** + * Generates the following eclipse configuration files: + *
    + *
  • .project and .classpath files
  • + *
  • .setting/org.eclipse.jdt.core.prefs with project specific compiler settings
  • + *
  • various configuration files for WTP (Web Tools Project), if the parameter wtpversion is set to a + * valid version (WTP configuration is not generated by default)
  • + *
+ * If this goal is run on a multiproject root, dependencies between modules will be configured as direct project + * dependencies in Eclipse (unless useProjectReferences is set to false). + * + * @author Trygve Laugstøl + * @author Fabrizio Giustina + * @version $Id: EclipsePlugin.java 641616 2008-03-26 22:42:42Z aheritier $ + * @goal eclipse + * @execute phase="generate-resources" + */ +public class EclipsePlugin + extends AbstractIdeSupportMojo +{ + + private static final String NATURE_WST_FACET_CORE_NATURE = "org.eclipse.wst.common.project.facet.core.nature"; //$NON-NLS-1$ + + private static final String BUILDER_WST_COMPONENT_STRUCTURAL_DEPENDENCY_RESOLVER = + "org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver"; //$NON-NLS-1$ + + protected static final String BUILDER_WST_VALIDATION = "org.eclipse.wst.validation.validationbuilder"; //$NON-NLS-1$ + + private static final String BUILDER_JDT_CORE_JAVA = "org.eclipse.jdt.core.javabuilder"; //$NON-NLS-1$ + + private static final String BUILDER_WST_COMPONENT_STRUCTURAL = + "org.eclipse.wst.common.modulecore.ComponentStructuralBuilder"; //$NON-NLS-1$ + + private static final String BUILDER_WST_FACET = "org.eclipse.wst.common.project.facet.core.builder"; //$NON-NLS-1$ + + private static final String BUILDER_PDE_MANIFEST = "org.eclipse.pde.ManifestBuilder"; //$NON-NLS-1$ + + private static final String BUILDER_PDE_SCHEMA = "org.eclipse.pde.SchemaBuilder"; //$NON-NLS-1$ + + private static final String NATURE_WST_MODULE_CORE_NATURE = "org.eclipse.wst.common.modulecore.ModuleCoreNature"; //$NON-NLS-1$ + + private static final String NATURE_JDT_CORE_JAVA = "org.eclipse.jdt.core.javanature"; //$NON-NLS-1$ + + private static final String NATURE_JEM_WORKBENCH_JAVA_EMF = "org.eclipse.jem.workbench.JavaEMFNature"; //$NON-NLS-1$ + + private static final String NATURE_PDE_PLUGIN = "org.eclipse.pde.PluginNature"; //$NON-NLS-1$ + + protected static final String COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER = "org.eclipse.jdt.launching.JRE_CONTAINER"; //$NON-NLS-1$ + + protected static final String REQUIRED_PLUGINS_CONTAINER = "org.eclipse.pde.core.requiredPlugins"; //$NON-NLS-1$ + + // warning, order is important for binary search + public static final String[] WTP_SUPPORTED_VERSIONS = new String[] { "1.0", "1.5", "2.0", "R7", "none" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + /** + * Constant for 'artifactId' element in POM.xml. + */ + private static final String POM_ELT_ARTIFACT_ID = "artifactId"; //$NON-NLS-1$ + + /** + * Constant for 'groupId' element in POM.xml. + */ + private static final String POM_ELT_GROUP_ID = "groupId"; //$NON-NLS-1$ + + /** + * List of eclipse project natures. By default the org.eclipse.jdt.core.javanature nature plus the + * needed WTP natures are added. Natures added using this property replace the default list. + * + *
+     * <projectnatures>
+     *    <projectnature>org.eclipse.jdt.core.javanature</projectnature>
+     *    <projectnature>org.eclipse.wst.common.modulecore.ModuleCoreNature</projectnature>
+     * </projectnatures>
+     * 
+ * + * @parameter + */ + private List projectnatures; + + /** + * List of artifact to exclude from eclipse classpath, beeing provided by some eclipse classPathContainer + * [MECLIPSE-79] + * + * @since 2.5 + * @parameter + */ + private List excludes; + + /** + * List of eclipse project natures to be added to the default ones. + * + *
+     * <additionalProjectnatures>
+     *    <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
+     * </additionalProjectnatures>
+     * 
+ * + * @parameter + */ + private List additionalProjectnatures; + + /** + * List of eclipse project facets to be added to the default ones. + * + *
+     * <additionalProjectFacets>
+     *    <jst.jsf>1.1<jst.jsf/>
+     * </additionalProjectFacets>
+     * 
+ * + * @parameter + */ + private Map additionalProjectFacets; + + /** + * List of eclipse build commands. By default the org.eclipse.jdt.core.javabuilder builder plus the + * needed WTP builders are added. If you specify any configuration for this parameter, only those buildcommands + * specified will be used; the defaults won't be added. Use the additionalBuildCommands parameter for + * that. Configuration example: Old style: + * + *
+     * <buildcommands>
+     *    <buildcommand>org.eclipse.wst.common.modulecore.ComponentStructuralBuilder</buildcommand>
+     *    <buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand>
+     *    <buildcommand>org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver</buildcommand>
+     * </buildcommands>
+     * 
+ * + * For new style, see additionalBuildCommands. + * + * @parameter + */ + private List buildcommands; + + /** + * List of eclipse build commands to be added to the default ones. Old style: + * + *
+     * <additionalBuildcommands>
+     *    <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
+     * </additionalBuildcommands>
+     * 
+ * + * New style: + * + *
+     * <additionalBuildcommands>
+     *    <buildCommand>
+     *      <name>org.ui.externaltools.ExternalToolBuilder</name>
+     *      <triggers>auto,full,incremental,</triggers>
+     *      <arguments>
+     *        <LaunchConfigHandle>&lt;project&gt;./externalToolBuilders/MavenBuilder.launch</LaunchConfighandle>
+     *      </arguments>
+     *    </buildCommand>
+     * </additionalBuildcommands>
+     * 
+ * + * Note the difference between buildcommand and + * buildCommand. You can mix and match old and new-style configuration entries. + * + * @parameter + */ + private List additionalBuildcommands; + + /** + * List of container classpath entries. By default the org.eclipse.jdt.launching.JRE_CONTAINER + * classpath container is added. Configuration example: + * + *
+     * <classpathContainers>
+     *    <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
+     *    <classpathContainer>org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v5.5</classpathContainer>
+     *    <classpathContainer>org.eclipse.jst.j2ee.internal.web.container/artifact</classpathContainer>
+     * </classpathContainers>
+     * 
+ * + * @parameter + */ + private List classpathContainers; + + /** + * Enables/disables the downloading of source attachments. Defaults to false. DEPRECATED - use downloadSources + * + * @parameter expression="${eclipse.downloadSources}" + * @deprecated use downloadSources + */ + private boolean eclipseDownloadSources; + + /** + * Eclipse workspace directory. + * + * @parameter expression="${eclipse.projectDir}" alias="outputDir" + */ + private File eclipseProjectDir; + + /** + * When set to false, the plugin will not create sub-projects and instead reference those sub-projects using the + * installed package in the local repository + * + * @parameter expression="${eclipse.useProjectReferences}" default-value="true" + * @required + */ + private boolean useProjectReferences; + + /** + * The default output directory + * + * @parameter expression="${outputDirectory}" alias="outputDirectory" + * default-value="${project.build.outputDirectory}" + * @required + */ + private File buildOutputDirectory; + + /** + * The version of WTP for which configuration files will be generated. The default value is "none" (don't generate + * WTP configuration), supported versions are "R7", "1.0", and "1.5" + * + * @parameter expression="${wtpversion}" default-value="none" + */ + private String wtpversion; + + /** + * JEE context name of the WTP module. ( ex. WEB context name ). + * + * @parameter expression="${wtpContextName}" + */ + private String wtpContextName; + + /** + * The relative path of the manifest file + * + * @parameter expression="${eclipse.manifest}" default-value="${basedir}/META-INF/MANIFEST.MF" + */ + private File manifest; + + /** + * Allow to configure additional generic configuration files for eclipse that will be written out to disk when + * running eclipse:eclipse. FOr each file you can specify the name and the text content. + * + *
+     * <plugin>
+     *  <groupId>org.apache.maven.plugins</groupId>
+     *  <artifactId>maven-eclipse-plugin</artifactId>
+     *  <configuration>
+     *   <additionalConfig>
+     *    <file>
+     *      <name>.checkstyle</name>
+     *      <content>
+     *        <![CDATA[<fileset-config file-format-version="1.2.0" simple-config="true">
+     *          <fileset name="all" enabled="true" check-config-name="acme corporate style" local="false">
+     *              <file-match-pattern match-pattern="." include-pattern="true"/>
+     *          </fileset>
+     *          <filter name="NonSrcDirs" enabled="true"/>
+     *        </fileset-config>]]>
+     *      </content>
+     *    </file>
+     *   </additionalConfig>
+     *  </configuration>
+     * </plugin>
+     * 
+ * + * Instead of the content you can also define (from version 2.5) an url to download the file : + * + *
+     * <plugin>
+     *  <groupId>org.apache.maven.plugins</groupId>
+     *  <artifactId>maven-eclipse-plugin</artifactId>
+     *  <configuration>
+     *   <additionalConfig>
+     *    <file>
+     *      <name>.checkstyle</name>
+     *      <url>http://some.place.org/path/to/file</url>
+     *    </file>
+     *   </additionalConfig>
+     *  </configuration>
+     * 
+ * + * or a location : + * + *
+     * <plugin>
+     *  <groupId>org.apache.maven.plugins</groupId>
+     *  <artifactId>maven-eclipse-plugin</artifactId>
+     *  <configuration>
+     *   <additionalConfig>
+     *    <file>
+     *     <name>.checkstyle</name>
+     *     <location>/checkstyle-config.xml</location>
+     *    </file>
+     *   </additionalConfig>
+     *  </configuration>
+     *  <dependencies>
+     *   <!-- The file defined in the location is stored in this dependency -->
+     *   <dependency>
+     *    <groupId>eclipsetest</groupId>
+     *    <artifactId>checkstyle-config</artifactId>
+     *    <version>1.0</version>
+     *   </dependency>
+     *  </dependencies>
+     * </plugin>
+     * 
+ * + * @parameter + */ + private EclipseConfigFile[] additionalConfig; + + /** + * If set to true, the version number of the artifact is appended to the name of the generated + * Eclipse project. See projectNameTemplate for other options. + * + * @parameter expression="${eclipse.addVersionToProjectName}" default-value="false" + */ + private boolean addVersionToProjectName; + + /** + * If set to true, the groupId of the artifact is appended to the name of the generated Eclipse + * project. See projectNameTemplate for other options. + * + * @parameter expression="${eclipse.addGroupIdToProjectName}" default-value="false" + */ + private boolean addGroupIdToProjectName; + + /** + * Allows configuring the name of the eclipse projects. This property if set wins over addVersionToProjectName and + * addGroupIdToProjectName You can use [groupId], [artifactId] and + * [version] variables. eg. [groupId].[artifactId]-[version] + * + * @parameter expression="${eclipse.projectNameTemplate}" + */ + private String projectNameTemplate; + + /** + * Parsed wtp version. + */ + private float wtpVersionFloat; + + /** + * Not a plugin parameter. Is this a java project? + */ + private boolean isJavaProject; + + /** + * Must the manifest files be written for java projects so that that the jee classpath for wtp is correct. + * + * @parameter expression="${eclipse.wtpmanifest}" default-value="false" + */ + private boolean wtpmanifest; + + /** + * Must the application files be written for ear projects in a separate directory. + * + * @parameter expression="${eclipse.wtpapplicationxml}" default-value="false" + */ + private boolean wtpapplicationxml; + + /** + * What WTP defined server to use for deployment informations. + * + * @parameter expression="${eclipse.wtpdefaultserver}" + */ + private String wtpdefaultserver; + + private WorkspaceConfiguration workspaceConfiguration; + + /** + * ResourceManager for getting additonalConfig files from resources + * + * @component + * @required + * @readonly + */ + private ResourceManager locator; + + /** + * This eclipse workspace is read and all artifacts detected there will be connected as eclipse projects and will + * not be linked to the jars in the local repository. Requirement is that it was created with the similar wtp + * settings as the reactor projects, but the project name template my differ. The pom's in the workspace projects + * may not contain variables in the artefactId, groupId and version tags. + * + * @since 2.5 + * @parameter expression="${eclipse.workspace}" + */ + protected String workspace; + + /** + * Limit the use of project references to the current workspace. No project references will be created to projects + * in the reactor when they are not available in the workspace. + * + * @parameter expression="${eclipse.limitProjectReferencesToWorkspace}" default-value="false" + */ + protected boolean limitProjectReferencesToWorkspace; + + protected boolean isJavaProject() + { + return isJavaProject; + } + + protected boolean isPdeProject() + { + return pde; + } + + /** + * Getter for buildcommands. + * + * @return Returns the buildcommands. + */ + public List getBuildcommands() + { + return buildcommands; + } + + /** + * Setter for buildcommands. + * + * @param buildcommands The buildcommands to set. + */ + public void setBuildcommands( List buildcommands ) + { + this.buildcommands = buildcommands; + } + + /** + * Getter for buildOutputDirectory. + * + * @return Returns the buildOutputDirectory. + */ + public File getBuildOutputDirectory() + { + return buildOutputDirectory; + } + + /** + * Setter for buildOutputDirectory. + * + * @param buildOutputDirectory The buildOutputDirectory to set. + */ + public void setBuildOutputDirectory( File buildOutputDirectory ) + { + this.buildOutputDirectory = buildOutputDirectory; + } + + /** + * Getter for classpathContainers. + * + * @return Returns the classpathContainers. + */ + public List getClasspathContainers() + { + return classpathContainers; + } + + /** + * Setter for classpathContainers. + * + * @param classpathContainers The classpathContainers to set. + */ + public void setClasspathContainers( List classpathContainers ) + { + this.classpathContainers = classpathContainers; + } + + /** + * Getter for eclipseProjectDir. + * + * @return Returns the eclipseProjectDir. + */ + public File getEclipseProjectDir() + { + return eclipseProjectDir; + } + + /** + * Setter for eclipseProjectDir. + * + * @param eclipseProjectDir The eclipseProjectDir to set. + */ + public void setEclipseProjectDir( File eclipseProjectDir ) + { + this.eclipseProjectDir = eclipseProjectDir; + } + + /** + * Getter for projectnatures. + * + * @return Returns the projectnatures. + */ + public List getProjectnatures() + { + return projectnatures; + } + + /** + * Setter for projectnatures. + * + * @param projectnatures The projectnatures to set. + */ + public void setProjectnatures( List projectnatures ) + { + this.projectnatures = projectnatures; + } + + /** + * Getter for useProjectReferences. + * + * @return Returns the useProjectReferences. + */ + public boolean getUseProjectReferences() + { + return useProjectReferences; + } + + /** + * Setter for useProjectReferences. + * + * @param useProjectReferences The useProjectReferences to set. + */ + public void setUseProjectReferences( boolean useProjectReferences ) + { + this.useProjectReferences = useProjectReferences; + } + + /** + * Getter for wtpversion. + * + * @return Returns the wtpversion. + */ + public String getWtpversion() + { + return wtpversion; + } + + /** + * Setter for wtpversion. + * + * @param wtpversion The wtpversion to set. + */ + public void setWtpversion( String wtpversion ) + { + this.wtpversion = wtpversion; + } + + /** + * Getter for additionalBuildcommands. + * + * @return Returns the additionalBuildcommands. + */ + public List getAdditionalBuildcommands() + { + return additionalBuildcommands; + } + + /** + * Setter for additionalBuildcommands. + * + * @param additionalBuildcommands The additionalBuildcommands to set. + */ + public void setAdditionalBuildcommands( List additionalBuildcommands ) + { + this.additionalBuildcommands = additionalBuildcommands; + } + + /** + * Getter for additionalProjectnatures. + * + * @return Returns the additionalProjectnatures. + */ + public List getAdditionalProjectnatures() + { + return additionalProjectnatures; + } + + /** + * Setter for additionalProjectnatures. + * + * @param additionalProjectnatures The additionalProjectnatures to set. + */ + public void setAdditionalProjectnatures( List additionalProjectnatures ) + { + this.additionalProjectnatures = additionalProjectnatures; + } + + /** + * Getter for addVersionToProjectName. + */ + public boolean isAddVersionToProjectName() + { + return addVersionToProjectName; + } + + /** + * Setter for addVersionToProjectName. + */ + public void setAddVersionToProjectName( boolean addVersionToProjectName ) + { + this.addVersionToProjectName = addVersionToProjectName; + } + + /** + * Getter for addGroupIdToProjectName. + */ + public boolean isAddGroupIdToProjectName() + { + return addGroupIdToProjectName; + } + + /** + * Setter for addGroupIdToProjectName. + */ + public void setAddGroupIdToProjectName( boolean addGroupIdToProjectName ) + { + this.addGroupIdToProjectName = addGroupIdToProjectName; + } + + public String getProjectNameTemplate() + { + return projectNameTemplate; + } + + public void setProjectNameTemplate( String projectNameTemplate ) + { + this.projectNameTemplate = projectNameTemplate; + } + + /** + * @see org.apache.maven.plugin.Mojo#execute() + */ + public boolean setup() + throws MojoExecutionException + { + boolean ready = true; + + checkDeprecations(); + + ready = validate(); + + // TODO: Why are we using project in some places, and executedProject in others?? + ArtifactHandler artifactHandler = project.getArtifact().getArtifactHandler(); + + // ear projects don't contain java sources + // pde projects are always java projects + isJavaProject = + pde || + ( Constants.LANGUAGE_JAVA.equals( artifactHandler.getLanguage() ) && !Constants.PROJECT_PACKAGING_EAR.equals( packaging ) ); + + setupExtras(); + + parseConfigurationOptions(); + + // defaults + if ( projectnatures == null ) + { + fillDefaultNatures( packaging ); + } + + if ( additionalProjectnatures != null ) + { + projectnatures.addAll( additionalProjectnatures ); + } + + if ( buildcommands == null ) + { + fillDefaultBuilders( packaging ); + } + else + { + convertBuildCommandList( buildcommands ); + } + + if ( additionalBuildcommands != null ) + { + convertBuildCommandList( additionalBuildcommands ); + buildcommands.addAll( additionalBuildcommands ); + } + + if ( classpathContainers == null ) + { + fillDefaultClasspathContainers( packaging ); + } + else + { + verifyClasspathContainerListIsComplete(); + } + locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() ); + locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) ); + + // ready to start + return ready; + } + + protected void convertBuildCommandList( List commands ) + { + if ( commands != null ) + { + for ( ListIterator i = commands.listIterator(); i.hasNext(); ) + { + Object command = i.next(); + + if ( command instanceof String ) + { + command = new BuildCommand( (String) command ); + i.set( command ); + } + } + } + } + + private void parseConfigurationOptions() + { + if ( "R7".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$ + { + wtpVersionFloat = 0.7f; + } + else if ( "1.0".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$ + { + wtpVersionFloat = 1.0f; + } + else if ( "1.5".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$ + { + wtpVersionFloat = 1.5f; + } + else if ( "2.0".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$ + { + wtpVersionFloat = 2.0f; + } + if ( !"none".equalsIgnoreCase( wtpversion ) ) + { + getLog().info( Messages.getString( "EclipsePlugin.wtpversion", wtpversion ) ); + } + } + + protected void setupExtras() + throws MojoExecutionException + { + // extension point. + } + + protected void verifyClasspathContainerListIsComplete() + { + boolean containsJREContainer = false; + // Check if classpathContainer contains a JRE (default, alternate or + // Execution Environment) + for ( Iterator iter = classpathContainers.iterator(); iter.hasNext(); ) + { + Object classPathContainer = iter.next(); + if ( classPathContainer != null && + classPathContainer.toString().startsWith( COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER ) ) + { + containsJREContainer = true; + break; + } + } + if ( !containsJREContainer ) + { + getLog().warn( Messages.getString( "EclipsePlugin.missingjrecontainer" ) ); //$NON-NLS-1$ + classpathContainers.add( 0, COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER ); + } + } + + private boolean validate() + throws MojoExecutionException + { + // validate sanity of the current m2 project + if ( Arrays.binarySearch( WTP_SUPPORTED_VERSIONS, wtpversion ) < 0 ) + { + throw new MojoExecutionException( + Messages.getString( "EclipsePlugin.unsupportedwtp", new Object[] { //$NON-NLS-1$ + wtpversion, + StringUtils.join( WTP_SUPPORTED_VERSIONS, " " ) } ) ); //$NON-NLS-1$ + } + + assertNotEmpty( executedProject.getGroupId(), POM_ELT_GROUP_ID ); + assertNotEmpty( executedProject.getArtifactId(), POM_ELT_ARTIFACT_ID ); + + if ( executedProject.getFile() == null || !executedProject.getFile().exists() ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.missingpom" ) ); //$NON-NLS-1$ + } + + if ( "pom".equals( packaging ) && eclipseProjectDir == null ) //$NON-NLS-1$ + { + getLog().info( Messages.getString( "EclipsePlugin.pompackaging" ) ); //$NON-NLS-1$ + return false; + } + + if ( "eclipse-plugin".equals( packaging ) ) + { + pde = true; + } + + // [rfeng] Set PDE to false if the project is not a bundle + if(!isOSGiBundle()) { + pde = false; + } + + if ( eclipseProjectDir == null ) + { + eclipseProjectDir = executedProject.getFile().getParentFile(); + } + + if ( !eclipseProjectDir.exists() && !eclipseProjectDir.mkdirs() ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantcreatedir", eclipseProjectDir ) ); //$NON-NLS-1$ + } + + if ( !eclipseProjectDir.equals( executedProject.getFile().getParentFile() ) ) + { + if ( !eclipseProjectDir.isDirectory() ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.notadir", eclipseProjectDir ) ); //$NON-NLS-1$ + } + eclipseProjectDir = new File( eclipseProjectDir, executedProject.getArtifactId() ); + if ( !eclipseProjectDir.isDirectory() && !eclipseProjectDir.mkdirs() ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantcreatedir", eclipseProjectDir ) ); //$NON-NLS-1$ + } + } + + validateExtras(); + + return true; + } + + protected void validateExtras() + { + // provided for extension. + } + + private void checkDeprecations() + { + if ( eclipseDownloadSources ) + { + // deprecated warning + getLog().warn( Messages.getString( "EclipsePlugin.deprecatedpar", new Object[] { //$NON-NLS-1$ + "eclipse.downloadSources", //$NON-NLS-1$ + "downloadSources" } ) ); //$NON-NLS-1$ + downloadSources = true; + } + + checkExtraDeprecations(); + } + + protected void checkExtraDeprecations() + { + // provided for extension. + } + + public void writeConfiguration( IdeDependency[] deps ) + throws MojoExecutionException + { + EclipseWriterConfig config = createEclipseWriterConfig( deps ); + + if ( wtpmanifest && isJavaProject() ) + { + EclipseManifestWriter.addManifestResource( getLog(), config ); + } + // NOTE: This could change the config! + writeExtraConfiguration( config ); + + if ( wtpVersionFloat == 0.7f ) + { + new EclipseWtpmodulesWriter().init( getLog(), config ).write(); + } + + if ( wtpVersionFloat >= 1.0f ) + { + new EclipseWtpFacetsWriter().init( getLog(), config ).write(); + } + if ( wtpVersionFloat == 1.0f ) + { + new EclipseWtpComponentWriter().init( getLog(), config ).write(); + } + if ( wtpVersionFloat >= 1.5 ) + { + new EclipseWtpComponent15Writer().init( getLog(), config ).write(); + } + + new EclipseSettingsWriter().init( getLog(), config ).write(); + + if ( isJavaProject ) + { + new EclipseClasspathWriter().init( getLog(), config ).write(); + } + + if ( wtpapplicationxml ) + { + new EclipseWtpApplicationXMLWriter().init( getLog(), config ).write(); + } + + // [rfeng] + /* + if ( pde ) + { + this.getLog().info( "The Maven Eclipse plugin runs in 'pde'-mode." ); + new EclipseOSGiManifestWriter().init( getLog(), config ).write(); + } + */ + // [rfeng] + + // NOTE: This one MUST be after EclipseClasspathwriter, and possibly others, + // since currently EclipseClasspathWriter does some magic to detect nested + // output folders and modifies the configuration by adding new (Ant) builders. + // So the .project file must be written AFTER those have run! + new EclipseProjectWriter().init( getLog(), config ).write(); + + writeAdditionalConfig(); + + getLog().info( Messages.getString( "EclipsePlugin.wrote", new Object[] { //$NON-NLS-1$ + config.getEclipseProjectName(), eclipseProjectDir.getAbsolutePath() } ) ); + } + + protected void writeAdditionalConfig() + throws MojoExecutionException + { + if ( additionalConfig != null ) + { + for ( int j = 0; j < additionalConfig.length; j++ ) + { + EclipseConfigFile file = additionalConfig[j]; + File projectRelativeFile = new File( eclipseProjectDir, file.getName() ); + if ( projectRelativeFile.isDirectory() ) + { + // just ignore? + getLog().warn( Messages.getString( "EclipsePlugin.foundadir", //$NON-NLS-1$ + projectRelativeFile.getAbsolutePath() ) ); + } + + try + { + projectRelativeFile.getParentFile().mkdirs(); + if ( file.getContent() == null ) + { + InputStream inStream; + if ( file.getLocation() != null ) + { + inStream = locator.getResourceAsInputStream( file.getLocation() ); + } + else + { + inStream = file.getURL().openConnection().getInputStream(); + } + OutputStream outStream = new FileOutputStream( projectRelativeFile ); + try + { + IOUtil.copy( inStream, outStream ); + } + finally + { + inStream.close(); + outStream.close(); + } + } + else + { + FileUtils.fileWrite( projectRelativeFile.getAbsolutePath(), file.getContent() ); + } + } + catch ( IOException e ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantwritetofile", //$NON-NLS-1$ + projectRelativeFile.getAbsolutePath() ) ); + } + catch ( ResourceNotFoundException e ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantfindresource", //$NON-NLS-1$ + file.getLocation() ) ); + } + + } + } + } + + protected EclipseWriterConfig createEclipseWriterConfig( IdeDependency[] deps ) + throws MojoExecutionException + { + File projectBaseDir = executedProject.getFile().getParentFile(); + + // build a list of UNIQUE source dirs (both src and resources) to be + // used in classpath and wtpmodules + EclipseSourceDir[] sourceDirs = buildDirectoryList( executedProject, eclipseProjectDir, buildOutputDirectory ); + + EclipseWriterConfig config = new EclipseWriterConfig(); + + config.setWorkspaceConfiguration( getWorkspaceConfiguration() ); + + config.setProjectNameTemplate( calculateProjectNameTemplate() ); + + String projectName = IdeUtils.getProjectName( config.getProjectNameTemplate(), project ); + + config.setEclipseProjectName( projectName ); + + config.setWtpapplicationxml( wtpapplicationxml ); + + config.setWtpVersion( wtpVersionFloat ); + + Set convertedBuildCommands = new LinkedHashSet(); + + if ( buildcommands != null ) + { + for ( Iterator it = buildcommands.iterator(); it.hasNext(); ) + { + Object cmd = it.next(); + + if ( cmd instanceof BuildCommand ) + { + convertedBuildCommands.add( cmd ); + } + else + { + convertedBuildCommands.add( new BuildCommand( (String) cmd ) ); + } + } + } + + config.setBuildCommands( new LinkedList( convertedBuildCommands ) ); + + config.setBuildOutputDirectory( buildOutputDirectory ); + config.setClasspathContainers( classpathContainers ); + config.setDeps( deps ); + config.setEclipseProjectDirectory( eclipseProjectDir ); + config.setLocalRepository( localRepository ); + config.setOSGIManifestFile( manifest ); + config.setPde( pde ); + config.setProject( project ); + config.setProjectBaseDir( projectBaseDir ); + config.setProjectnatures( projectnatures ); + config.setProjectFacets( additionalProjectFacets ); + config.setSourceDirs( sourceDirs ); + config.setAddVersionToProjectName( isAddVersionToProjectName() ); + config.setPackaging( packaging ); + + collectWarContextRootsFromReactorEarConfiguration( config ); + + return config; + } + + /** + * If this is a war module peek into the reactor an search for an ear module that defines the context root of this + * module. + * + * @param config config to save the context root. + */ + private void collectWarContextRootsFromReactorEarConfiguration( EclipseWriterConfig config ) + { + if ( reactorProjects != null && wtpContextName == null && + Constants.PROJECT_PACKAGING_WAR.equals( project.getPackaging() ) ) + { + for ( Iterator iter = reactorProjects.iterator(); iter.hasNext(); ) + { + MavenProject reactorProject = (MavenProject) iter.next(); + + if ( Constants.PROJECT_PACKAGING_EAR.equals( reactorProject.getPackaging() ) ) + { + Xpp3Dom[] warDefinitions = + IdeUtils.getPluginConfigurationDom( reactorProject, JeeUtils.ARTIFACT_MAVEN_EAR_PLUGIN, + new String[] { "modules", "webModule" } ); + for ( int index = 0; index < warDefinitions.length; index++ ) + { + Xpp3Dom groupId = warDefinitions[index].getChild( "groupId" ); + Xpp3Dom artifactId = warDefinitions[index].getChild( "artifactId" ); + Xpp3Dom contextRoot = warDefinitions[index].getChild( "contextRoot" ); + if ( groupId != null && artifactId != null && contextRoot != null && + groupId.getValue() != null && artifactId.getValue() != null && + contextRoot.getValue() != null ) + { + getLog().info( + "Found context root definition for " + groupId.getValue() + ":" + + artifactId.getValue() + " " + contextRoot.getValue() ); + if ( project.getArtifactId().equals( artifactId.getValue() ) && + project.getGroupId().equals( groupId.getValue() ) ) + { + config.setContextName( contextRoot.getValue() ); + } + } + else + { + getLog().info( + "Found incomplete ear configuration in " + reactorProject.getGroupId() + + ":" + reactorProject.getGroupId() + " found " + + warDefinitions[index].toString() ); + } + } + } + } + } + if ( config.getContextName() == null && Constants.PROJECT_PACKAGING_WAR.equals( project.getPackaging() ) ) + { + if ( wtpContextName == null ) + { + config.setContextName( project.getArtifactId() ); + } + else + { + config.setContextName( wtpContextName ); + } + } + } + + /** + * Write any extra configuration information for the Eclipse project. This is an extension point, called before the + * main configurations are written.
NOTE: This could change the config! + * + * @param config + * @throws MojoExecutionException + */ + protected void writeExtraConfiguration( EclipseWriterConfig config ) + throws MojoExecutionException + { + // extension point. + } + + private void assertNotEmpty( String string, String elementName ) + throws MojoExecutionException + { + if ( string == null ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.missingelement", elementName ) ); //$NON-NLS-1$ + } + } + + protected void fillDefaultNatures( String packaging ) + { + projectnatures = new ArrayList(); + + if ( wtpVersionFloat >= 1.0f ) + { + projectnatures.add( NATURE_WST_FACET_CORE_NATURE ); // WTP 1.0 nature + } + + if ( isJavaProject ) + { + projectnatures.add( NATURE_JDT_CORE_JAVA ); + } + + if ( wtpVersionFloat >= 0.7f ) + { + projectnatures.add( NATURE_WST_MODULE_CORE_NATURE ); // WTP 0.7/1.0 nature + + if ( isJavaProject ) + { + projectnatures.add( NATURE_JEM_WORKBENCH_JAVA_EMF ); // WTP 0.7/1.0 nature + } + } + + if ( pde ) + { + projectnatures.add( NATURE_PDE_PLUGIN ); + } + + } + + protected void fillDefaultClasspathContainers( String packaging ) + { + classpathContainers = new ArrayList(); + + if ( getWorkspaceConfiguration().getDefaultClasspathContainer() != null ) + { + getLog().info( + "Adding default classpath contaigner: " + + getWorkspaceConfiguration().getDefaultClasspathContainer() ); + classpathContainers.add( getWorkspaceConfiguration().getDefaultClasspathContainer() ); + } + if ( pde ) + { + classpathContainers.add( REQUIRED_PLUGINS_CONTAINER ); + } + } + + protected void fillDefaultBuilders( String packaging ) + { + buildcommands = new ArrayList(); + + if ( wtpVersionFloat == 0.7f ) + { + buildcommands.add( new BuildCommand( BUILDER_WST_COMPONENT_STRUCTURAL ) ); // WTP 0.7 builder + } + + if ( isJavaProject ) + { + buildcommands.add( new BuildCommand( BUILDER_JDT_CORE_JAVA ) ); + } + + if ( wtpVersionFloat >= 1.5f ) + { + buildcommands.add( new BuildCommand( BUILDER_WST_FACET ) ); // WTP 1.5 builder + } + + if ( wtpVersionFloat >= 0.7f ) + { + buildcommands.add( new BuildCommand( BUILDER_WST_VALIDATION ) ); // WTP 0.7/1.0 builder + } + + if ( wtpVersionFloat == 0.7f ) + { + // WTP 0.7 builder + buildcommands.add( new BuildCommand( BUILDER_WST_COMPONENT_STRUCTURAL_DEPENDENCY_RESOLVER ) ); + } + + if ( pde ) + { + buildcommands.add( new BuildCommand( BUILDER_PDE_MANIFEST ) ); + buildcommands.add( new BuildCommand( BUILDER_PDE_SCHEMA ) ); + } + } + + public EclipseSourceDir[] buildDirectoryList( MavenProject project, File basedir, File buildOutputDirectory ) + throws MojoExecutionException + { + File projectBaseDir = project.getFile().getParentFile(); + + // avoid duplicated entries + Set directories = new TreeSet(); + + extractSourceDirs( directories, project.getCompileSourceRoots(), basedir, projectBaseDir, false, null ); + + String relativeOutput = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, buildOutputDirectory, false ); + + extractResourceDirs( directories, project.getBuild().getResources(), project, basedir, projectBaseDir, false, + relativeOutput ); + + // If using the standard output location, don't mix the test output into it. + String testOutput = null; + boolean useStandardOutputDir = + buildOutputDirectory.equals( new File( project.getBuild().getOutputDirectory() ) ); + if ( useStandardOutputDir ) + { + getLog().debug( + "testOutput toRelativeAndFixSeparator " + projectBaseDir + " , " + + project.getBuild().getTestOutputDirectory() ); + testOutput = + IdeUtils.toRelativeAndFixSeparator( projectBaseDir, + new File( project.getBuild().getTestOutputDirectory() ), false ); + getLog().debug( "testOutput after toRelative : " + testOutput ); + } + + extractSourceDirs( directories, project.getTestCompileSourceRoots(), basedir, projectBaseDir, true, testOutput ); + + extractResourceDirs( directories, project.getBuild().getTestResources(), project, basedir, projectBaseDir, + true, testOutput ); + + return (EclipseSourceDir[]) directories.toArray( new EclipseSourceDir[directories.size()] ); + } + + private void extractSourceDirs( Set directories, List sourceRoots, File basedir, File projectBaseDir, boolean test, + String output ) + throws MojoExecutionException + { + for ( Iterator it = sourceRoots.iterator(); it.hasNext(); ) + { + + File sourceRootFile = new File( (String) it.next() ); + getLog().debug( "Processing source dir: " + sourceRootFile ); + + if ( sourceRootFile.isDirectory() ) + { + String sourceRoot = + IdeUtils.toRelativeAndFixSeparator( projectBaseDir, sourceRootFile, + !projectBaseDir.equals( basedir ) ); + + directories.add( new EclipseSourceDir( sourceRoot, output, false, test, null, null, false ) ); + } + } + } + + void extractResourceDirs( Set directories, List resources, MavenProject project, File basedir, + File workspaceProjectBaseDir, boolean test, final String output ) + throws MojoExecutionException + { + for ( Iterator it = resources.iterator(); it.hasNext(); ) + { + Resource resource = (Resource) it.next(); + + getLog().debug( "Processing resource dir: " + resource.getDirectory() ); + + String includePattern = null; + String excludePattern = null; + + if ( resource.getIncludes().size() != 0 ) + { + includePattern = StringUtils.join( resource.getIncludes().iterator(), "|" ); + } + + if ( resource.getExcludes().size() != 0 ) + { + excludePattern = StringUtils.join( resource.getExcludes().iterator(), "|" ); + } + + // TODO: figure out how to merge if the same dir is specified twice + // with different in/exclude patterns. + + File resourceDirectory = new File( /* basedir, */resource.getDirectory() ); + + if ( !resourceDirectory.exists() || !resourceDirectory.isDirectory() ) + { + getLog().debug( "Resource dir: " + resourceDirectory + " either missing or not a directory." ); + continue; + } + + String resourceDir = + IdeUtils.toRelativeAndFixSeparator( workspaceProjectBaseDir, resourceDirectory, + !workspaceProjectBaseDir.equals( basedir ) ); + String thisOutput = output; + if ( thisOutput != null ) + { + // sometimes thisOutput is already an absolute path + File outputFile = new File( thisOutput ); + if ( !outputFile.isAbsolute() ) + { + outputFile = new File( workspaceProjectBaseDir, thisOutput ); + } + // create output dir if it doesn't exist + outputFile.mkdirs(); + + if ( !StringUtils.isEmpty( resource.getTargetPath() ) ) + { + outputFile = new File( outputFile, resource.getTargetPath() ); + // create output dir if it doesn't exist + outputFile.mkdirs(); + } + + getLog().debug( + "Making relative and fixing separator: { " + workspaceProjectBaseDir + ", " + + outputFile + ", false }." ); + thisOutput = IdeUtils.toRelativeAndFixSeparator( workspaceProjectBaseDir, outputFile, false ); + } + + getLog().debug( + "Adding eclipse source dir: { " + resourceDir + ", " + thisOutput + ", true, " + test + + ", " + includePattern + ", " + excludePattern + " }." ); + + directories.add( new EclipseSourceDir( resourceDir, thisOutput, true, test, includePattern, excludePattern, + resource.isFiltering() ) ); + } + } + + /** + * Calculate the project name template from the fields {@link #projectNameTemplate}, + * {@link #addVersionToProjectName} and {@link #addGroupIdToProjectName} + * + * @return the project name template that should be used after considering the plugin configuration + */ + private String calculateProjectNameTemplate() + { + if ( getProjectNameTemplate() != null ) + { + if ( isAddVersionToProjectName() || isAddGroupIdToProjectName() ) + { + getLog().warn( + "projectNameTemplate definition overrides " + + "addVersionToProjectName or addGroupIdToProjectName" ); + } + return getProjectNameTemplate(); + } + else if ( isAddVersionToProjectName() && isAddGroupIdToProjectName() ) + { + return IdeUtils.PROJECT_NAME_WITH_GROUP_AND_VERSION_TEMPLATE; + } + else if ( isAddVersionToProjectName() ) + { + return IdeUtils.PROJECT_NAME_WITH_VERSION_TEMPLATE; + } + else if ( isAddGroupIdToProjectName() ) + { + return IdeUtils.PROJECT_NAME_WITH_GROUP_TEMPLATE; + } + return IdeUtils.PROJECT_NAME_DEFAULT_TEMPLATE; + } + + /** + * {@inheritDoc} + */ + public String getProjectNameForArifact( Artifact artifact ) + { + IdeDependency[] workspaceArtefacts = getWorkspaceArtefacts(); + for ( int index = 0; workspaceArtefacts != null && index < workspaceArtefacts.length; index++ ) + { + IdeDependency workspaceArtefact = workspaceArtefacts[index]; + if ( workspaceArtefact.isAddedToClasspath() && + workspaceArtefact.getGroupId().equals( artifact.getGroupId() ) && + workspaceArtefact.getArtifactId().equals( artifact.getArtifactId() ) ) + { + if ( workspaceArtefact.getVersion().equals( artifact.getVersion() ) ) + { + return workspaceArtefact.getEclipseProjectName(); + } + } + } + return IdeUtils.getProjectName( calculateProjectNameTemplate(), artifact ); + } + + /** + * {@inheritDoc} + */ + protected IdeDependency[] getWorkspaceArtefacts() + { + return getWorkspaceConfiguration().getWorkspaceArtefacts(); + } + + public WorkspaceConfiguration getWorkspaceConfiguration() + { + if ( workspaceConfiguration == null ) + { + workspaceConfiguration = new WorkspaceConfiguration(); + if ( workspace != null ) + { + workspaceConfiguration.setWorkspaceDirectory( new File( workspace ) ); + } + new ReadWorkspaceLocations().init( getLog(), workspaceConfiguration, project, wtpdefaultserver ); + } + return workspaceConfiguration; + } + + public List getExcludes() + { + return excludes; + } + + /** + * Utility method that locates a project in the workspace for the given artifact. + * + * @param artifact the artifact a project should produce. + * @return true if the artifact is produced by a reactor projectart. + */ + private boolean isAvailableAsAWorkspaceProject( Artifact artifact ) + { + IdeDependency[] workspaceArtefacts = getWorkspaceArtefacts(); + for ( int index = 0; workspaceArtefacts != null && index < workspaceArtefacts.length; index++ ) + { + IdeDependency workspaceArtefact = workspaceArtefacts[index]; + if ( workspaceArtefact.getGroupId().equals( artifact.getGroupId() ) && + workspaceArtefact.getArtifactId().equals( artifact.getArtifactId() ) ) + { + if ( workspaceArtefact.getVersion().equals( artifact.getVersion() ) ) + { + workspaceArtefact.setAddedToClasspath( true ); + getLog().debug( "Using workspace project: " + workspaceArtefact.getEclipseProjectName() ); + return true; + } + else + { + getLog().info( + "Artifact " + + artifact.getId() + + " already available as a workspace project, but with different version. Expected: " + + artifact.getVersion() + ", found: " + workspaceArtefact.getVersion() ); + } + } + } + return false; + } + + /* + * (non-Javadoc) + * + * @see org.apache.maven.plugin.ide.AbstractIdeSupportMojo#doDependencyResolution() + */ + protected IdeDependency[] doDependencyResolution() + throws MojoExecutionException + { + + return super.doDependencyResolution(); + } + + /** + * Checks if jar has to be resolved for the given artifact + * + * @param art the artifact to check + * @return true if resolution should happen + */ + protected boolean hasToResolveJar( Artifact art ) + { + return !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) ) || + ( limitProjectReferencesToWorkspace && !( getUseProjectReferences() && isAvailableAsAWorkspaceProject( art ) ) ); + } + + /** + * Checks if a projects reference has to be used for the given artifact + * + * @param art the artifact to check + * @return true if a project reference has to be used. + */ + protected boolean useProjectReference( Artifact art ) + { + boolean isReactorProject = getUseProjectReferences() && isAvailableAsAReactorProject( art ); + boolean isWorkspaceProject = getUseProjectReferences() && isAvailableAsAWorkspaceProject( art ); + return ( isReactorProject && !limitProjectReferencesToWorkspace ) || // default + ( limitProjectReferencesToWorkspace && isWorkspaceProject ) || // limitProjectReferencesToWorkspace + ( !isReactorProject && isWorkspaceProject ); // default + workspace projects + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseProjectWriter.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseProjectWriter.java new file mode 100644 index 0000000000..070b9b3e8b --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/EclipseProjectWriter.java @@ -0,0 +1,351 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.maven.plugin.eclipse; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.apache.maven.model.Resource; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.eclipse.BuildCommand; +import org.apache.maven.plugin.eclipse.writers.AbstractEclipseWriter; +import org.apache.maven.plugin.ide.IdeDependency; +import org.apache.maven.plugin.ide.IdeUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * Writes eclipse .project file. + * + * @author Trygve Laugstøl + * @author Kenney Westerhof + * @author Fabrizio Giustina + * @version $Id: EclipseProjectWriter.java 616816 2008-01-30 17:23:08Z aheritier $ + */ +public class EclipseProjectWriter + extends AbstractEclipseWriter +{ + private static final String ELT_NAME = "name"; //$NON-NLS-1$ + + private static final String ELT_BUILD_COMMAND = "buildCommand"; //$NON-NLS-1$ + + private static final String ELT_BUILD_SPEC = "buildSpec"; //$NON-NLS-1$ + + private static final String ELT_NATURE = "nature"; //$NON-NLS-1$ + + private static final String ELT_NATURES = "natures"; //$NON-NLS-1$ + + private static final String FILE_DOT_PROJECT = ".project"; //$NON-NLS-1$ + + /** + * Constant for links to files. + */ + private static final int LINK_TYPE_FILE = 1; + + /** + * Constant for links to directories. + */ + private static final int LINK_TYPE_DIRECTORY = 2; + + /** + * @see org.apache.tuscany.sca.maven.plugin.eclipse.writers.EclipseWriter#write() + */ + public void write() + throws MojoExecutionException + { + + Set projectnatures = new LinkedHashSet(); + Set buildCommands = new LinkedHashSet(); + + File dotProject = new File( config.getEclipseProjectDirectory(), FILE_DOT_PROJECT ); + + if ( dotProject.exists() ) + { + + log.info( Messages.getString( "EclipsePlugin.keepexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$ + + // parse existing file in order to keep manually-added entries + Reader reader = null; + try + { + reader = new InputStreamReader( new FileInputStream( dotProject ), "UTF-8" ); + Xpp3Dom dom = Xpp3DomBuilder.build( reader ); + + Xpp3Dom naturesElement = dom.getChild( ELT_NATURES ); + if ( naturesElement != null ) + { + Xpp3Dom[] existingNatures = naturesElement.getChildren( ELT_NATURE ); + for ( int j = 0; j < existingNatures.length; j++ ) + { + // adds all the existing natures + projectnatures.add( existingNatures[j].getValue() ); + } + } + + Xpp3Dom buildSpec = dom.getChild( ELT_BUILD_SPEC ); + if ( buildSpec != null ) + { + Xpp3Dom[] existingBuildCommands = buildSpec.getChildren( ELT_BUILD_COMMAND ); + for ( int j = 0; j < existingBuildCommands.length; j++ ) + { + Xpp3Dom buildCommandName = existingBuildCommands[j].getChild( ELT_NAME ); + if ( buildCommandName != null ) + { + buildCommands.add( new BuildCommand( existingBuildCommands[j] ) ); + } + } + } + } + catch ( XmlPullParserException e ) + { + log.warn( Messages.getString( "EclipsePlugin.cantparseexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$ + } + catch ( IOException e ) + { + log.warn( Messages.getString( "EclipsePlugin.cantparseexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$ + } + finally + { + IOUtil.close( reader ); + } + } + + // adds new entries after the existing ones + for ( Iterator iter = config.getProjectnatures().iterator(); iter.hasNext(); ) + { + projectnatures.add( iter.next() ); + } + + for ( Iterator iter = config.getBuildCommands().iterator(); iter.hasNext(); ) + { + buildCommands.add( (BuildCommand) iter.next() ); + } + + Writer w; + + try + { + w = new OutputStreamWriter( new FileOutputStream( dotProject ), "UTF-8" ); + } + catch ( IOException ex ) + { + throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex ); //$NON-NLS-1$ + } + + XMLWriter writer = new PrettyPrintXMLWriter( w ); + + writer.startElement( "projectDescription" ); //$NON-NLS-1$ + + writer.startElement( ELT_NAME ); + writer.writeText( config.getEclipseProjectName() ); + writer.endElement(); + + // TODO: this entire element might be dropped if the comment is null. + // but as the maven1 eclipse plugin does it, it's better to be safe than sorry + // A eclipse developer might want to look at this. + writer.startElement( "comment" ); //$NON-NLS-1$ + + if ( config.getProject().getDescription() != null ) + { + writer.writeText( config.getProject().getDescription() ); + } + + writer.endElement(); + + writer.startElement( "projects" ); //$NON-NLS-1$ + + // referenced projects should not be added for plugins + if ( !config.isPde() ) + { + for ( int j = 0; j < config.getDepsOrdered().length; j++ ) + { + IdeDependency dep = config.getDepsOrdered()[j]; + if ( dep.isReferencedProject() ) + { + writer.startElement( "project" ); //$NON-NLS-1$ + writer.writeText( dep.getEclipseProjectName() ); + writer.endElement(); + } + } + } + + writer.endElement(); // projects + + writer.startElement( ELT_BUILD_SPEC ); + + for ( Iterator it = buildCommands.iterator(); it.hasNext(); ) + { + ( (BuildCommand) it.next() ).print( writer ); + } + + writer.endElement(); // buildSpec + + writer.startElement( ELT_NATURES ); + + for ( Iterator it = projectnatures.iterator(); it.hasNext(); ) + { + writer.startElement( ELT_NATURE ); + writer.writeText( (String) it.next() ); + writer.endElement(); // name + } + + writer.endElement(); // natures + + /* + boolean addLinks = !config.getProjectBaseDir().equals( config.getEclipseProjectDirectory() ); + + if ( addLinks || ( config.isPde() && config.getDepsOrdered().length > 0 ) ) + { + writer.startElement( "linkedResources" ); //$NON-NLS-1$ + + if ( addLinks ) + { + + addFileLink( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(), + config.getProject().getFile() ); + + addSourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(), + config.getProject().getCompileSourceRoots() ); + addResourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(), + config.getProject().getBuild().getResources() ); + + addSourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(), + config.getProject().getTestCompileSourceRoots() ); + addResourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(), + config.getProject().getBuild().getTestResources() ); + + } + + if ( config.isPde() ) + { + for ( int j = 0; j < config.getDepsOrdered().length; j++ ) + { + IdeDependency dep = config.getDepsOrdered()[j]; + + if ( dep.isAddedToClasspath() && !dep.isProvided() && !dep.isReferencedProject() && + !dep.isTestDependency() && !dep.isOsgiBundle() ) + { + String name = dep.getFile().getName(); + addLink( writer, name, StringUtils.replace( IdeUtils.getCanonicalPath( dep.getFile() ), "\\", + "/" ), LINK_TYPE_FILE ); + } + } + } + + writer.endElement(); // linkedResources + } + */ + + writer.endElement(); // projectDescription + + IOUtil.close( w ); + } + + private void addFileLink( XMLWriter writer, File projectBaseDir, File basedir, File file ) + throws MojoExecutionException + { + if ( file.isFile() ) + { + String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, file, true ); + String location = IdeUtils.getCanonicalPath( file ).replaceAll( "\\\\", "/" ); //$NON-NLS-1$ //$NON-NLS-2$ + + addLink( writer, name, location, LINK_TYPE_FILE ); + } + else + { + log.warn( Messages.getString( "EclipseProjectWriter.notafile", file ) ); //$NON-NLS-1$ + } + } + + private void addSourceLinks( XMLWriter writer, File projectBaseDir, File basedir, List sourceRoots ) + throws MojoExecutionException + { + for ( Iterator it = sourceRoots.iterator(); it.hasNext(); ) + { + String sourceRootString = (String) it.next(); + File sourceRoot = new File( sourceRootString ); + + if ( sourceRoot.isDirectory() ) + { + String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, sourceRoot, true ); + String location = IdeUtils.getCanonicalPath( sourceRoot ).replaceAll( "\\\\", "/" ); //$NON-NLS-1$ //$NON-NLS-2$ + + addLink( writer, name, location, LINK_TYPE_DIRECTORY ); + } + } + } + + private void addResourceLinks( XMLWriter writer, File projectBaseDir, File basedir, List sourceRoots ) + throws MojoExecutionException + { + for ( Iterator it = sourceRoots.iterator(); it.hasNext(); ) + { + String resourceDirString = ( (Resource) it.next() ).getDirectory(); + File resourceDir = new File( resourceDirString ); + + if ( resourceDir.isDirectory() ) + { + String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, resourceDir, true ); + String location = IdeUtils.getCanonicalPath( resourceDir ).replaceAll( "\\\\", "/" ); //$NON-NLS-1$ //$NON-NLS-2$ + + addLink( writer, name, location, LINK_TYPE_DIRECTORY ); + } + } + } + + /** + * @param writer + * @param name + * @param location + */ + private void addLink( XMLWriter writer, String name, String location, int type ) + { + writer.startElement( "link" ); //$NON-NLS-1$ + + writer.startElement( ELT_NAME ); + writer.writeText( name ); + writer.endElement(); // name + + writer.startElement( "type" ); //$NON-NLS-1$ + writer.writeText( Integer.toString( type ) ); + writer.endElement(); // type + + writer.startElement( "location" ); //$NON-NLS-1$ + + writer.writeText( location ); + + writer.endElement(); // location + + writer.endElement(); // link + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/Messages.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/Messages.java new file mode 100644 index 0000000000..553cae6256 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/maven/plugin/eclipse/Messages.java @@ -0,0 +1,68 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.maven.plugin.eclipse; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * @author Fabrizio Giustina + * @version $Id: Messages.java 485864 2006-12-11 20:41:36Z fgiust $ + */ +public class Messages +{ + + private static final String BUNDLE_NAME = "org.apache.tuscany.sca.maven.plugin.eclipse.messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle( BUNDLE_NAME ); + + private Messages() + { + } + + public static String getString( String key ) + { + try + { + return RESOURCE_BUNDLE.getString( key ); + } + catch ( MissingResourceException e ) + { + return '!' + key + '!'; + } + } + + public static String getString( String key, Object[] params ) + { + try + { + return MessageFormat.format( RESOURCE_BUNDLE.getString( key ), params ); + } + catch ( MissingResourceException e ) + { + return '!' + key + '!'; + } + } + + public static String getString( String key, Object param ) + { + return getString( key, new Object[] { param } ); + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ArtifactAggregation.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ArtifactAggregation.java new file mode 100644 index 0000000000..062c935ad9 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ArtifactAggregation.java @@ -0,0 +1,73 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.tools.bundle.plugin; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.maven.artifact.Artifact; + + +public class ArtifactAggregation { + private String symbolicName; + private String version; + private List artifactMemebers = new ArrayList(); + private transient List artifacts = new ArrayList(); + + public List getArtifacts() { + return artifacts; + } + + public String getSymbolicName() { + return symbolicName; + } + + public void setSymbolicName(String symbolicName) { + this.symbolicName = symbolicName; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public List getArtifactMembers() { + return artifactMemebers; + } + + public void setArtifactMembers(List artifacts) { + this.artifactMemebers = artifacts; + } + + public String toString() { + return symbolicName + ";version=\"" + version + "\"\n" + artifactMemebers; + } + + public boolean matches(Artifact artifact) { + for(ArtifactMember m: artifactMemebers) { + if(m.matches(artifact)) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ArtifactMember.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ArtifactMember.java new file mode 100644 index 0000000000..19315aa19f --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ArtifactMember.java @@ -0,0 +1,61 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.tools.bundle.plugin; + +import org.apache.maven.artifact.Artifact; + +public class ArtifactMember { + private String groupId; + private String artifactId; + private String version; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String toString() { + return groupId + ":" + artifactId + ":" + version; + } + + public boolean matches(Artifact artifact) { + return groupId.equals(artifact.getGroupId()) && (artifactId == null || artifactId.equals("") + || artifactId.equals("*") || artifactId.equals(artifact.getArtifactId())) + && (version == null || version.equals("") || version.equals("*") || version.equals(artifact.getVersion())); + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/BundleUtil.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/BundleUtil.java new file mode 100644 index 0000000000..6c97a34676 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/BundleUtil.java @@ -0,0 +1,387 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.tools.bundle.plugin; + +import static org.osgi.framework.Constants.BUNDLE_CLASSPATH; +import static org.osgi.framework.Constants.BUNDLE_MANIFESTVERSION; +import static org.osgi.framework.Constants.BUNDLE_NAME; +import static org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME; +import static org.osgi.framework.Constants.BUNDLE_VERSION; +import static org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE; +import static org.osgi.framework.Constants.EXPORT_PACKAGE; +import static org.osgi.framework.Constants.IMPORT_PACKAGE; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.osgi.framework.Version; + +/** + * Common functions used by the plugin. + * + * @version $Rev$ $Date$ + */ +final class BundleUtil { + private final static Logger logger = Logger.getLogger(BundleUtil.class.getName()); + /** + * Returns the name of a bundle, or null if the given file is not a bundle. + * + * @param file + * @return + * @throws IOException + */ + static String getBundleSymbolicName(File file) throws IOException { + if (!file.exists()) { + return null; + } + String bundleName = null; + if (file.isDirectory()) { + File mf = new File(file, "META-INF/MANIFEST.MF"); + if (mf.isFile()) { + Manifest manifest = new Manifest(new FileInputStream(mf)); + bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + } + } else { + JarFile jar = new JarFile(file, false); + Manifest manifest = jar.getManifest(); + bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + jar.close(); + } + if (bundleName == null) { + return bundleName; + } + int sc = bundleName.indexOf(';'); + if (sc != -1) { + bundleName = bundleName.substring(0, sc); + } + return bundleName; + } + + /** + * Generate a Bundle manifest for a set of JAR files. + * + * @param jarFiles + * @param name + * @param symbolicName + * @param version + * @param dir + * @return + * @throws IllegalStateException + */ + static Manifest libraryManifest(Set jarFiles, String name, String symbolicName, String version, String dir) + throws IllegalStateException { + try { + + // List exported packages and bundle classpath entries + StringBuffer classpath = new StringBuffer(); + Set exportedPackages = new HashSet(); + for (File jarFile : jarFiles) { + addPackages(jarFile, exportedPackages, version); + if (dir != null) { + classpath.append(dir).append("/"); + } + classpath.append(jarFile.getName()); + classpath.append(","); + } + + // Generate export-package and import-package declarations + StringBuffer exports = new StringBuffer(); + StringBuffer imports = new StringBuffer(); + Set pkgs = new HashSet(); + for (String export : exportedPackages) { + String packageName = packageName(export); + if (!pkgs.contains(packageName)) { + // Add corresponding import declaration +// imports.append(export); +// imports.append(','); + pkgs.add(packageName); + exports.append(export); + exports.append(','); + } else { + logger.warning("Duplicate package skipped: " + export); + } + } + + // Create a manifest + Manifest manifest = new Manifest(); + Attributes attributes = manifest.getMainAttributes(); + attributes.putValue("Manifest-Version", "1.0"); + attributes.putValue(BUNDLE_MANIFESTVERSION, "2"); + attributes.putValue(BUNDLE_SYMBOLICNAME, symbolicName); + attributes.putValue(BUNDLE_NAME, name); + attributes.putValue(BUNDLE_VERSION, version); + attributes.putValue(DYNAMICIMPORT_PACKAGE, "*"); + if (exports.length() > 1) { + attributes.putValue(EXPORT_PACKAGE, exports.substring(0, exports.length() - 1)); + } + if (imports.length() > 1) { + attributes.putValue(IMPORT_PACKAGE, imports.substring(0, imports.length() - 1)); + } + if (classpath.length() > 1) { + attributes.putValue(BUNDLE_CLASSPATH, classpath.substring(0, classpath.length() - 1)); + } + + return manifest; + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Write a bundle manifest. + * + * @param manifest + * @param out + * @throws IOException + */ + static void write(Manifest manifest, OutputStream out) throws IOException { + DataOutputStream dos = new DataOutputStream(out); + Attributes attributes = manifest.getMainAttributes(); + write(attributes, "Manifest-Version", dos); + write(attributes, BUNDLE_MANIFESTVERSION, dos); + write(attributes, BUNDLE_SYMBOLICNAME, dos); + write(attributes, BUNDLE_NAME, dos); + write(attributes, BUNDLE_VERSION, dos); + write(attributes, DYNAMICIMPORT_PACKAGE, dos); + write(attributes, BUNDLE_CLASSPATH, dos); + write(attributes, IMPORT_PACKAGE, dos); + write(attributes, EXPORT_PACKAGE, dos); + dos.flush(); + } + + /** + * Add packages to be exported out of a JAR file. + * + * @param jarFile + * @param packages + * @throws IOException + */ + private static void addPackages(File jarFile, Set packages, String version) throws IOException { + if (getBundleSymbolicName(jarFile) == null) { + String ver = ";version=" + version; + addAllPackages(jarFile, packages, ver); + } else { + addExportedPackages(jarFile, packages); + } + } + + /** + * Write manifest attributes. + * + * @param attributes + * @param key + * @param dos + * @throws IOException + */ + private static void write(Attributes attributes, String key, DataOutputStream dos) throws IOException { + String value = attributes.getValue(key); + if (value == null) { + return; + } + StringBuffer line = new StringBuffer(); + line.append(key); + line.append(": "); + line.append(new String(value.getBytes("UTF8"))); + line.append("\r\n"); + int l = line.length(); + if (l > 72) { + for (int i = 70; i < l - 2;) { + line.insert(i, "\r\n "); + i += 72; + l += 3; + } + } + dos.writeBytes(line.toString()); + } + + /** + * Strip an OSGi export, only retain the package name and version. + * + * @param export + * @return + */ + private static String stripExport(String export) { + int sc = export.indexOf(';'); + if (sc == -1) { + return export; + } + String base = export.substring(0, sc); + int v = export.indexOf("version="); + if (v != -1) { + sc = export.indexOf(';', v + 1); + if (sc != -1) { + return base + ";" + export.substring(v, sc); + } else { + return base + ";" + export.substring(v); + } + } else { + return base; + } + } + + /** + * Add all the packages out of a JAR. + * + * @param jarFile + * @param packages + * @param version + * @throws IOException + */ + private static void addAllPackages(File jarFile, Set packages, String version) throws IOException { + ZipInputStream is = new ZipInputStream(new FileInputStream(jarFile)); + ZipEntry entry; + while ((entry = is.getNextEntry()) != null) { + String entryName = entry.getName(); + if (!entry.isDirectory() && entryName != null + && entryName.length() > 0 + && !entryName.startsWith(".") + && entryName.endsWith(".class") // Exclude resources from Export-Package + && entryName.lastIndexOf("/") > 0 + && Character.isJavaIdentifierStart(entryName.charAt(0))) { + String pkg = entryName.substring(0, entryName.lastIndexOf("/")).replace('/', '.'); + if (!pkg.endsWith(".enum")) { + packages.add(pkg + version); + } + } + } + is.close(); + } + + /** + * Returns the name of the exported package in the given export. + * @param export + * @return + */ + private static String packageName(String export) { + int sc = export.indexOf(';'); + if (sc != -1) { + export = export.substring(0, sc); + } + return export; + } + + /** + * Add the packages exported by a bundle. + * + * @param file + * @param packages + * @return + * @throws IOException + */ + private static void addExportedPackages(File file, Set packages) throws IOException { + if (!file.exists()) { + return; + } + + // Read the export-package declaration and get a list of the packages available in a JAR + Set existingPackages = null; + String exports = null; + if (file.isDirectory()) { + File mf = new File(file, "META-INF/MANIFEST.MF"); + if (mf.isFile()) { + Manifest manifest = new Manifest(new FileInputStream(mf)); + exports = manifest.getMainAttributes().getValue(EXPORT_PACKAGE); + } + } else { + JarFile jar = new JarFile(file, false); + Manifest manifest = jar.getManifest(); + exports = manifest.getMainAttributes().getValue(EXPORT_PACKAGE); + jar.close(); + existingPackages = new HashSet(); + addAllPackages(file, existingPackages, ""); + } + if (exports == null) { + return; + } + + // Parse the export-package declaration, and extract the individual packages + StringBuffer buffer = new StringBuffer(); + boolean q = false; + for (int i = 0, n = exports.length(); i < n; i++) { + char c = exports.charAt(i); + if (c == '\"') { + q = !q; + } + if (!q) { + if (c == ',') { + + // Add the exported package to the set, after making sure it really exists in + // the JAR + String export = buffer.toString(); + if (existingPackages == null || existingPackages.contains(packageName(export))) { + packages.add(stripExport(export)); + } + buffer = new StringBuffer(); + continue; + } + } + buffer.append(c); + } + if (buffer.length() != 0) { + + // Add the exported package to the set, after making sure it really exists in + // the JAR + String export = buffer.toString(); + if (existingPackages == null || existingPackages.contains(packageName(export))) { + packages.add(stripExport(export)); + } + } + } + + /** + * Convert the maven version into OSGi version + * @param mavenVersion + * @return + */ + static String osgiVersion(String mavenVersion) { + ArtifactVersion ver = new DefaultArtifactVersion(mavenVersion); + String qualifer = ver.getQualifier(); + if (qualifer != null) { + StringBuffer buf = new StringBuffer(qualifer); + for (int i = 0; i < buf.length(); i++) { + char c = buf.charAt(i); + if (Character.isLetterOrDigit(c) || c == '-' || c == '_') { + // Keep as-is + } else { + buf.setCharAt(i, '_'); + } + } + qualifer = buf.toString(); + } + Version osgiVersion = + new Version(ver.getMajorVersion(), ver.getMinorVersion(), ver.getIncrementalVersion(), qualifer); + String version = osgiVersion.toString(); + return version; + } + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ModuleBundlesBuildMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ModuleBundlesBuildMojo.java new file mode 100644 index 0000000000..bd6368aaa0 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ModuleBundlesBuildMojo.java @@ -0,0 +1,828 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.tools.bundle.plugin; + +import static org.apache.tuscany.sca.tools.bundle.plugin.BundleUtil.write; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.ArtifactUtils; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectBuilder; +import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.artifact.InvalidDependencyVersionException; + +/** + * A maven plugin that generates a modules directory containing OSGi bundles for all the project's module dependencies. + * + * @version $Rev$ $Date$ + * @goal generate-modules + * @phase generate-resources + * @requiresDependencyResolution test + * @description Generate a modules directory containing OSGi bundles for all the project's module dependencies. + */ +public class ModuleBundlesBuildMojo extends AbstractMojo { + + /** + * The project to create a distribution for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + /** + * Project builder -- builds a model from a pom.xml + * + * @component role="org.apache.maven.project.MavenProjectBuilder" + * @required + * @readonly + */ + private MavenProjectBuilder mavenProjectBuilder; + /** + * Used to look up Artifacts in the remote repository. + * + * @component + */ + private org.apache.maven.artifact.factory.ArtifactFactory factory; + + /** + * Used to look up Artifacts in the remote repository. + * + * @component + */ + private org.apache.maven.artifact.resolver.ArtifactResolver resolver; + + /** + * @component role="org.apache.maven.artifact.metadata.ArtifactMetadataSource" + * hint="maven" + * @required + * @readonly + */ + private ArtifactMetadataSource artifactMetadataSource; + + /** + * Location of the local repository. + * + * @parameter expression="${localRepository}" + * @readonly + * @required + */ + private org.apache.maven.artifact.repository.ArtifactRepository local; + + /** + * List of Remote Repositories used by the resolver + * + * @parameter expression="${project.remoteArtifactRepositories}" + * @readonly + * @required + */ + private java.util.List remoteRepos; + + /** + * Target directory. + * + * @parameter expression="${project.build.directory}/modules" + */ + private File targetDirectory; + + /** + * @parameter default-value="features" + */ + private String featuresName = "features"; + + /** + * Directories containing artifacts to exclude. + * + * @parameter + */ + private File[] excludeDirectories; + + /** + * Directories containing groupids to exclude. + * + * @parameter + */ + private String[] excludeGroupIds; + + /** + * Directories containing groupids to include. + * + * @parameter + */ + private String[] includeGroupIds; + + /** + * Set to true to generate configurations under a folder named as the distro + * + * @parameter default-value="true" + */ + private boolean useDistributionName = true; + + /** + * Set to true to generate a PDE target platform configuration. + * + * @parameter default-value="true" + */ + private boolean generateTargetPlatform = true; + + /** + * OSGi execution environment + */ + private String executionEnvironment; + + /** + * A list of Eclipse features to be added to the target definition + * @parameter + */ + private String[] eclipseFeatures; + + /** + * If we use the running eclipse as the default location for the target + * @parameter default-value="true" + */ + private boolean useDefaultLocation = true; + + /** + * Set to true to generate a plugin.xml. + * + * @parameter default-value="false" + */ + private boolean generatePlugin; + + /** + * Generate a configuration/config.ini for equinox + * @parameter default-value="true" + */ + private boolean generateConfig = true; + + /** + * @parameter default-value="true" + */ + private boolean generateBundleStart = true; + + /** + * Generete manifest.jar + * @parameter default-value="true" + */ + private boolean generateManifestJar = true; + + /** + * @parameter default-value="tuscany-sca-manifest.jar" + */ + private String manifestJarName = "tuscany-sca-manifest.jar"; + + /** + * @parameter default-value="tuscany-sca-equinox-manifest.jar" + */ + private String equinoxManifestJarName = "tuscany-sca-equinox-manifest.jar"; + + + /** + * @parameter default-value="true" + */ + private boolean generateAntScript = true; + + /** + * @parameter + */ + private ArtifactAggregation[] artifactAggregations; + + private static final String XML_PI = ""; + private static final String ASL_HEADER = + ""; + + /** + * Group the artifacts by distribution poms + */ + private class ProjectSet { + // Distribution projects + private Map projects; + // Key: the pom artifact id + // Value: the names for the artifacts + private Map> nameMap = new HashMap>(); + + private Map artifactToNameMap = new HashMap(); + + public ProjectSet(List projects) { + super(); + this.projects = new HashMap(); + for (MavenProject p : projects) { + this.projects.put(p.getArtifactId(), p); + } + } + + private MavenProject getProject(String artifactId) { + return projects.get(artifactId); + } + + private void add(Artifact artifact, String name) { + String key = ArtifactUtils.versionlessKey(artifact); + for (MavenProject p : projects.values()) { + Artifact a = (Artifact)p.getArtifactMap().get(key); + if (a != null) { + Set names = nameMap.get(p.getArtifactId()); + if (names == null) { + names = new HashSet(); + nameMap.put(p.getArtifactId(), names); + } + names.add(name); + } + } + artifactToNameMap.put(key, name); + } + } + + public void execute() throws MojoExecutionException { + Log log = getLog(); + + try { + + // Create the target directory + File root; + if (targetDirectory == null) { + root = new File(project.getBuild().getDirectory(), "plugins/"); + } else { + root = targetDirectory; + } + root.mkdirs(); + + // Build sets of exclude directories and included/excluded/groupids + Set excludedFileNames = new HashSet(); + if (excludeDirectories != null) { + for (File f : excludeDirectories) { + if (f.isDirectory()) { + for (String n : f.list()) { + excludedFileNames.add(n); + } + } + } + } + Set includedGroupIds = new HashSet(); + if (includeGroupIds != null) { + for (String g : includeGroupIds) { + includedGroupIds.add(g); + } + } + Set excludedGroupIds = new HashSet(); + if (excludeGroupIds != null) { + for (String g : excludeGroupIds) { + excludedGroupIds.add(g); + } + } + + // Find all the distribution poms + List poms = new ArrayList(); + poms.add(project); + if (useDistributionName) { + for (Object o : project.getArtifacts()) { + Artifact artifact = (Artifact)o; + if ("pom".equals(artifact.getType()) && artifact.getGroupId().equals(project.getGroupId()) + && artifact.getArtifactId().startsWith("tuscany-feature-")) { + log.info("Dependent distribution: " + artifact); + MavenProject pomProject = buildProject(artifact); + poms.add(pomProject); + // log.info(pomProject.getArtifactMap().toString()); + } + } + } + + // Process all the dependency artifacts + ProjectSet bundleSymbolicNames = new ProjectSet(poms); + ProjectSet bundleLocations = new ProjectSet(poms); + ProjectSet jarNames = new ProjectSet(poms); + for (Object o : project.getArtifacts()) { + Artifact artifact = (Artifact)o; + + // Only consider Compile and Runtime dependencies + if (!(Artifact.SCOPE_COMPILE.equals(artifact.getScope()) || Artifact.SCOPE_RUNTIME.equals(artifact + .getScope()) + || Artifact.SCOPE_PROVIDED.equals(artifact.getScope()) || (generateTargetPlatform && Artifact.SCOPE_TEST + .equals(artifact.getScope())))) { + log.info("Skipping artifact: " + artifact); + continue; + } + + // Only consider JAR and WAR files + if (!"jar".equals(artifact.getType()) && !"war".equals(artifact.getType())) { + continue; + } + + // Exclude artifact if its groupId is excluded or if it's not included + if (excludedGroupIds.contains(artifact.getGroupId())) { + log.debug("Artifact groupId is excluded: " + artifact); + continue; + } + if (!includedGroupIds.isEmpty()) { + if (!includedGroupIds.contains(artifact.getGroupId())) { + log.debug("Artifact groupId is not included: " + artifact); + continue; + } + } + + File artifactFile = artifact.getFile(); + if (!artifactFile.exists()) { + log.warn("Artifact doesn't exist: " + artifact); + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Processing artifact: " + artifact); + } + + // Get the bundle name if the artifact is an OSGi bundle + String bundleName = null; + try { + bundleName = BundleUtil.getBundleSymbolicName(artifact.getFile()); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + if (bundleName != null) { + + // Exclude artifact if its file name is excluded + if (excludedFileNames.contains(artifactFile.getName())) { + log.debug("Artifact file is excluded: " + artifact); + continue; + } + + // Copy an OSGi bundle as is + log.info("Adding OSGi bundle artifact: " + artifact); + copyFile(artifactFile, root); + bundleSymbolicNames.add(artifact, bundleName); + bundleLocations.add(artifact, artifactFile.getName()); + jarNames.add(artifact, artifactFile.getName()); + + } else if ("war".equals(artifact.getType())) { + + // Exclude artifact if its file name is excluded + if (excludedFileNames.contains(artifactFile.getName())) { + log.debug("Artifact file is excluded: " + artifact); + continue; + } + + // Copy a WAR as is + log.info("Adding WAR artifact: " + artifact); + copyFile(artifactFile, root); + + } else { + + // String version = BundleUtil.osgiVersion(artifact.getVersion()); + // String symbolicName = (artifact.getGroupId() + "." + artifact.getArtifactId()); + // String dirName = symbolicName + "_" + version; + + String dirName = artifactFile.getName().substring(0, artifactFile.getName().length() - 4); + File dir = new File(root, dirName); + + // Exclude artifact if its file name is excluded + if (excludedFileNames.contains(dir.getName())) { + log.debug("Artifact file is excluded: " + artifact); + continue; + } + + if (artifactAggregations != null) { + boolean aggregated = false; + for (ArtifactAggregation group : artifactAggregations) { + if (group.matches(artifact)) { + group.getArtifacts().add(artifact); + aggregated = true; + break; + } + } + if (aggregated) { + continue; + } + } + + // Create a bundle directory for a non-OSGi JAR + log.info("Adding JAR artifact: " + artifact); + String version = BundleUtil.osgiVersion(artifact.getVersion()); + + Set jarFiles = new HashSet(); + jarFiles.add(artifactFile); + String symbolicName = (artifact.getGroupId() + "." + artifact.getArtifactId()); + Manifest mf = BundleUtil.libraryManifest(jarFiles, symbolicName, symbolicName, version, null); + File file = new File(dir, "META-INF"); + file.mkdirs(); + file = new File(file, "MANIFEST.MF"); + + FileOutputStream fos = new FileOutputStream(file); + write(mf, fos); + fos.close(); + copyFile(artifactFile, dir); + bundleSymbolicNames.add(artifact, symbolicName); + bundleLocations.add(artifact, dir.getName()); + jarNames.add(artifact, dirName + "/" + artifactFile.getName()); + } + } + + if (artifactAggregations != null) { + for (ArtifactAggregation group : artifactAggregations) { + if (group.getArtifacts().isEmpty()) { + continue; + } + String symbolicName = group.getSymbolicName(); + String version = group.getVersion(); + File dir = new File(root, symbolicName + "-" + version); + dir.mkdir(); + Set jarFiles = new HashSet(); + Artifact artifact = null; + for (Artifact a : group.getArtifacts()) { + log.info("Aggragating JAR artifact: " + a); + artifact = a; + jarFiles.add(a.getFile()); + copyFile(a.getFile(), dir); + jarNames.add(a, symbolicName + "-" + version + "/" + a.getFile().getName()); + } + Manifest mf = BundleUtil.libraryManifest(jarFiles, symbolicName, symbolicName, version, null); + File file = new File(dir, "META-INF"); + file.mkdirs(); + file = new File(file, "MANIFEST.MF"); + + FileOutputStream fos = new FileOutputStream(file); + write(mf, fos); + fos.close(); + bundleSymbolicNames.add(artifact, symbolicName); + bundleLocations.add(artifact, dir.getName()); + } + } + + // Generate a PDE target + if (generateTargetPlatform) { + generatePDETarget(bundleSymbolicNames, root, log); + } + + // Generate a plugin.xml referencing the PDE target + if (generatePlugin) { + File pluginxml = new File(project.getBasedir(), "plugin.xml"); + FileOutputStream pluginXMLFile = new FileOutputStream(pluginxml); + writePluginXML(new PrintStream(pluginXMLFile)); + pluginXMLFile.close(); + } + + if (generateConfig) { + generateEquinoxConfig(bundleLocations, root, log); + } + + if (generateManifestJar) { + generateManifestJar(jarNames, root, log); + generateEquinoxLauncherManifestJar(jarNames, root, log); + } + + if (generateAntScript) { + generateANTPath(jarNames, root, log); + } + + } catch (Exception e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + } + + private void generateANTPath(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException { + for (Map.Entry> e : jarNames.nameMap.entrySet()) { + Set jars = e.getValue(); + File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? trim(e.getKey()) : "")); + feature.mkdirs(); + File antPath = new File(feature, "build-path.xml"); + log.info("Generating ANT build path: " + antPath.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(antPath); + PrintStream ps = new PrintStream(fos); + // ps.println(XML_PI); + ps.println(ASL_HEADER); + String name = trim(e.getKey()); + ps.println(""); + ps.println(" "); + ps.println(" "); + ps.println(" "); + ps.println(" "); + for (String jar : jars) { + ps.println(" "); + } + ps.println(" "); + ps.println(" "); + ps.println(""); + } + } + + private void generateManifestJar(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException { + for (Map.Entry> e : jarNames.nameMap.entrySet()) { + MavenProject pom = jarNames.getProject(e.getKey()); + Set jars = e.getValue(); + File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? trim(e.getKey()) : "")); + feature.mkdirs(); + File mfJar = new File(feature, manifestJarName); + log.info("Generating manifest jar: " + mfJar.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(mfJar); + Manifest mf = new Manifest(); + StringBuffer cp = new StringBuffer(); + String path = (useDistributionName ? "../../" : "../") + root.getName(); + for (String jar : jars) { + cp.append(path).append('/').append(jar).append(' '); + } + if (cp.length() > 0) { + cp.deleteCharAt(cp.length() - 1); + } + Attributes attrs = mf.getMainAttributes(); + attrs.putValue("Manifest-Version", "1.0"); + attrs.putValue("Implementation-Title", pom.getName()); + attrs.putValue("Implementation-Vendor", "The Apache Software Foundation"); + attrs.putValue("Implementation-Vendor-Id", "org.apache"); + attrs.putValue("Implementation-Version", pom.getVersion()); + attrs.putValue("Class-Path", cp.toString()); + attrs.putValue("Main-Class", "org.apache.tuscany.sca.node.launcher.NodeMain"); + JarOutputStream jos = new JarOutputStream(fos, mf); + addFileToJar(jos, "META-INF/LICENSE", getClass().getResource("LICENSE.txt")); + addFileToJar(jos, "META-INF/NOTICE", getClass().getResource("NOTICE.txt")); + jos.close(); + } + } + + private void generateEquinoxLauncherManifestJar(ProjectSet jarNames, File root, Log log) throws Exception { + String equinoxLauncher = "org.apache.tuscany.sca:tuscany-node-launcher-equinox"; + Artifact artifact = (Artifact)project.getArtifactMap().get(equinoxLauncher); + if (artifact == null) { + return; + } + Set artifacts = resolveTransitively(artifact).getArtifacts(); + File feature = new File(root, "../" + featuresName + "/"); + feature.mkdirs(); + File mfJar = new File(feature, equinoxManifestJarName); + log.info("Generating equinox manifest jar: " + mfJar.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(mfJar); + Manifest mf = new Manifest(); + StringBuffer cp = new StringBuffer(); + String path = "../" + root.getName(); + + for (Object o : artifacts) { + Artifact a = (Artifact)o; + if (!Artifact.SCOPE_TEST.equals(a.getScope())) { + String id = ArtifactUtils.versionlessKey(a); + String jar = jarNames.artifactToNameMap.get(id); + if (jar != null) { + cp.append(path).append('/').append(jar).append(' '); + } + } + } + if (cp.length() > 0) { + cp.deleteCharAt(cp.length() - 1); + } + Attributes attrs = mf.getMainAttributes(); + attrs.putValue("Manifest-Version", "1.0"); + attrs.putValue("Implementation-Title", artifact.getId()); + attrs.putValue("Implementation-Vendor", "The Apache Software Foundation"); + attrs.putValue("Implementation-Vendor-Id", "org.apache"); + attrs.putValue("Implementation-Version", artifact.getVersion()); + attrs.putValue("Class-Path", cp.toString()); + attrs.putValue("Main-Class", "org.apache.tuscany.sca.node.equinox.launcher.NodeMain"); + JarOutputStream jos = new JarOutputStream(fos, mf); + addFileToJar(jos, "META-INF/LICENSE", getClass().getResource("LICENSE.txt")); + addFileToJar(jos, "META-INF/NOTICE", getClass().getResource("NOTICE.txt")); + jos.close(); + } + + private void generateEquinoxConfig(ProjectSet bundleLocations, File root, Log log) throws IOException { + for (Map.Entry> e : bundleLocations.nameMap.entrySet()) { + Set locations = e.getValue(); + File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? trim(e.getKey()) : "")); + File config = new File(feature, "configuration"); + config.mkdirs(); + File ini = new File(config, "config.ini"); + log.info("Generating configuation: " + ini.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(ini); + PrintStream ps = new PrintStream(fos); + ps.print("osgi.bundles="); + for (String f : locations) { + ps.print(f); + if (generateBundleStart) { + ps.print("@:start,"); + } else { + ps.println(","); + } + } + ps.println(); + ps.println("eclipse.ignoreApp=true"); + // Do not shutdown + ps.println("osgi.noShutdown=true"); + // Start a default console + ps.println("osgi.console="); + ps.close(); + } + } + + private void generatePDETarget(ProjectSet bundleSymbolicNames, File root, Log log) throws FileNotFoundException, + IOException { + for (Map.Entry> e : bundleSymbolicNames.nameMap.entrySet()) { + Set bundles = e.getValue(); + String name = trim(e.getKey()); + File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? name : "")); + feature.mkdirs(); + File target = new File(feature, "tuscany.target"); + log.info("Generating target definition: " + target.getCanonicalPath()); + FileOutputStream targetFile = new FileOutputStream(target); + if (!bundles.contains("org.eclipse.osgi")) { + bundles.add("org.eclipse.osgi"); + } + writeTarget(new PrintStream(targetFile), name, bundles, eclipseFeatures); + targetFile.close(); + } + } + + private MavenProject buildProject(Artifact artifact) throws ProjectBuildingException, + InvalidDependencyVersionException, ArtifactResolutionException, ArtifactNotFoundException { + MavenProject pomProject = + mavenProjectBuilder.buildFromRepository(artifact, this.remoteRepos, this.local); + if (pomProject.getDependencyArtifacts() == null) { + pomProject.setDependencyArtifacts(pomProject + .createArtifacts(factory, + null, // Artifact.SCOPE_TEST, + new ScopeArtifactFilter(Artifact.SCOPE_TEST))); + } + ArtifactResolutionResult result = + resolver.resolveTransitively(pomProject.getDependencyArtifacts(), + pomProject.getArtifact(), + remoteRepos, + local, + artifactMetadataSource); + pomProject.setArtifacts(result.getArtifacts()); + return pomProject; + } + + private ArtifactResolutionResult resolveTransitively(Artifact artifact) throws ArtifactResolutionException, ArtifactNotFoundException { + Artifact originatingArtifact = factory.createBuildArtifact("dummy", "dummy", "1.0", "jar"); + + return resolver.resolveTransitively(Collections.singleton(artifact), + originatingArtifact, + local, + remoteRepos, + artifactMetadataSource, + null); + } + + /** + * Convert tuscany-feature-xyz to feature-xyz + * @param artifactId + * @return + */ + private String trim(String artifactId) { + if (artifactId.startsWith("tuscany-feature-")) { + return artifactId.substring("tuscany-feature-".length()); + } else { + return artifactId; + } + } + + private static void copyFile(File jar, File dir) throws FileNotFoundException, IOException { + byte[] buf = new byte[4096]; + File jarFile = new File(dir, jar.getName()); + FileInputStream in = new FileInputStream(jar); + FileOutputStream out = new FileOutputStream(jarFile); + for (;;) { + int len = in.read(buf); + if (len > 0) { + out.write(buf, 0, len); + } else { + break; + } + } + in.close(); + out.close(); + } + + private static void addFileToJar(JarOutputStream out, String entryName, URL file) throws FileNotFoundException, IOException { + byte[] buf = new byte[4096]; + InputStream in = file.openStream(); + out.putNextEntry(new ZipEntry(entryName)); + for (;;) { + int len = in.read(buf); + if (len > 0) { + out.write(buf, 0, len); + } else { + break; + } + } + in.close(); + out.closeEntry(); + } + + private void writeTarget(PrintStream ps, String pom, Set ids, String[] features) { + ps.println(XML_PI); + ps.println(""); + ps.println(ASL_HEADER); + + ps.println(""); + + if (executionEnvironment != null) { + ps.println(" "); + ps.println(" " + executionEnvironment + ""); + ps.println(" "); + } + + if (useDefaultLocation) { + ps.println(" "); + } else { + ps.println(" "); + } + + // ps.println(""); + ps.println(" "); + ps.println(" "); + for (String id : ids) { + ps.println(" "); + } + ps.println(" "); + ps.println(" "); + if (features != null) { + for (String f : features) { + ps.println(" "); + } + } + ps.println(" "); + if (useDefaultLocation) { + ps.println(" "); + // Not sure why the extra path needs to the plugins folder + ps.println(" "); + ps.println(" "); + } + ps.println(" "); + + ps.println(""); + + } + + private static void writePluginXML(PrintStream ps) { + ps.println(XML_PI); + ps.println(""); + ps.println(ASL_HEADER); + ps.println(""); + ps.println(""); + ps.println(""); + ps.println(""); + ps.println(""); + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ThirdPartyBundleBuildMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ThirdPartyBundleBuildMojo.java new file mode 100644 index 0000000000..e183e7e197 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/java/org/apache/tuscany/sca/tools/bundle/plugin/ThirdPartyBundleBuildMojo.java @@ -0,0 +1,152 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.tools.bundle.plugin; + +import static org.apache.tuscany.sca.tools.bundle.plugin.BundleUtil.write; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.Manifest; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; + +/** + * A Maven plugin that builds an OSGi bundle for the project's third-party dependencies. + * + * @version $Rev$ $Date$ + * @goal assemble-thirdparty-bundle + * @phase generate-resources + * @requiresDependencyResolution test + * @description Build an OSGi bundle for the project's third party dependencies + */ +public class ThirdPartyBundleBuildMojo extends AbstractMojo { + + /** + * The project to build the bundle for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + /** + * The bundle symbolic name + * + * @parameter + */ + private String symbolicName; + + public void execute() throws MojoExecutionException { + Log log = getLog(); + + String projectGroupId = project.getGroupId(); + Set jarFiles = new HashSet(); + for (Object o : project.getArtifacts()) { + Artifact artifact = (Artifact)o; + + if (!(Artifact.SCOPE_COMPILE.equals(artifact.getScope()) || Artifact.SCOPE_RUNTIME.equals(artifact + .getScope()))) { + if (log.isDebugEnabled()) { + log.debug("Skipping artifact: " + artifact); + } + continue; + } + if (!"jar".equals(artifact.getType())) { + continue; + } + if (projectGroupId.equals(artifact.getGroupId())) { + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Artifact: " + artifact); + } + String bundleName = null; + try { + bundleName = BundleUtil.getBundleSymbolicName(artifact.getFile()); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + if (bundleName == null || true) { + if (artifact.getFile().exists()) { + log.info("Adding third party jar: " + artifact); + jarFiles.add(artifact.getFile()); + } else { + log.warn("Third party jar not found: " + artifact); + } + } + } + + try { + String version = BundleUtil.osgiVersion(project.getVersion()); + + Manifest mf = BundleUtil.libraryManifest(jarFiles, project.getName(), symbolicName, version, "lib"); + File file = new File(project.getBasedir(), "META-INF"); + file.mkdir(); + file = new File(file, "MANIFEST.MF"); + if (log.isDebugEnabled()) { + log.debug("Generating " + file); + } + + FileOutputStream fos = new FileOutputStream(file); + write(mf, fos); + fos.close(); + + File lib = new File(project.getBasedir(), "lib"); + if (lib.isDirectory()) { + for (File c : lib.listFiles()) { + c.delete(); + } + } + lib.mkdir(); + byte[] buf = new byte[4096]; + for (File jar : jarFiles) { + File jarFile = new File(lib, jar.getName()); + if (log.isDebugEnabled()) { + log.debug("Copying " + jar + " to " + jarFile); + } + FileInputStream in = new FileInputStream(jar); + FileOutputStream out = new FileOutputStream(jarFile); + for (;;) { + int len = in.read(buf); + if (len > 0) { + out.write(buf, 0, len); + } else { + break; + } + } + in.close(); + out.close(); + } + } catch (Exception e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + } + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/maven/plugin/eclipse/messages.properties b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/maven/plugin/eclipse/messages.properties new file mode 100644 index 0000000000..b016c69065 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/maven/plugin/eclipse/messages.properties @@ -0,0 +1,78 @@ +# +# +# 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. +# +# +EclipsePlugin.missingpom=There must be a POM in the current working directory for the Eclipse plugin to work. +EclipsePlugin.pompackaging=Not running eclipse plugin goal for pom project +EclipsePlugin.notadir=Not a directory: "{0}" +EclipsePlugin.cantcreatedir=Can''t create directory "{0}" +EclipsePlugin.erroropeningfile=Exception while opening file. +EclipsePlugin.cantwritetofile=Unable to write to file: {0} +EclipsePlugin.cantfindresource=Unable to resolve resource location: {0} +EclipsePlugin.cantreadfile=Unable to read file: {0} +EclipsePlugin.keepexisting=File {0} already exists.\n Additional settings will be preserved, run mvn eclipse:clean if you want old settings to be removed. +EclipsePlugin.cantparseexisting=Unable to parse existing file: {0}. Settings will not be preserved. +EclipsePlugin.cantresolvesources=Cannot resolve source artifact. Artifact id: {0} (Message: {1}) +EclipsePlugin.wrote=Wrote Eclipse project for "{0}" to {1}. +EclipsePlugin.missingelement=Missing element from the project descriptor: "{0}" +EclipsePlugin.includenotsupported=This plugin currently doesn't support include patterns for resources. Adding the entire directory. +EclipsePlugin.excludenotsupported=This plugin currently doesn't support exclude patterns for resources. Adding the entire directory. +EclipsePlugin.artifactpathisnull=The artifact path was null. Artifact id: {0} +EclipsePlugin.artifactissystemscoped=The artifact has scope ''system''. Artifact id: {0}. System path: {1} +EclipsePlugin.unsupportedwtp=Unsupported WTP version: {0}. This plugin currently supports only the following versions: {1}. +EclipsePlugin.wtpversion=Adding support for WTP version {0}. +EclipsePlugin.missingjrecontainer=You did specify a list of classpath containers without the base org.eclipse.jdt.launching.JRE_CONTAINER.\n If you specify custom classpath containers you should also add org.eclipse.jdt.launching.JRE_CONTAINER to the list +EclipsePlugin.deprecatedpar=Plugin parameter "{0}" is deprecated, please use "{1}" +EclipsePlugin.cantcopyartifact=Can''t copy artifact "{0}". +EclipsePlugin.foundadir={0} is a directory, ignoring. + +EclipseSettingsWriter.wrotesettings=Wrote settings to {0} +EclipseSettingsWriter.cannotcreatesettings=Cannot create settings file +EclipseSettingsWriter.errorwritingsettings=Error writing settings file +EclipseSettingsWriter.usingdefaults=Not writing settings - defaults suffice + +EclipseClasspathWriter.lookingforsources=Looking for source archive for artifact {0} +EclipseClasspathWriter.sourcesavailable=Sources attachment for artifact {0} set to {1} + +EclipseProjectWriter.notafile=Not adding a file link to {0}; it is not a file + +EclipseCleanMojo.failedtodelete=Failed to delete {0} file: {0} +EclipseCleanMojo.nofilefound=No {0} file found +EclipseCleanMojo.deletingFile=Deleting file: {0} +EclipseCleanMojo.deletingDirectory=Deleting directory: {0} + +EclipseOSGiManifestWriter.nomanifestfile=The references manifest file doesn''t exist, plugin dependencies will not be updated: {0} + +IdeDependency.cantreadfile=Unable to read file: {0} + +Rad6LibCopier.cantdeletefile=Failed to delete file: {0} + +MyEclipseSpringBeansWriter.springVersionNotFound=Spring must be declared in the project's dependencies to generate .springBeans file. + +sourcesnotavailable=\n Sources for some artifacts are not available.\n List of artifacts without a source archive: +sourcesnotdownloaded=\n Sources for some artifacts are not available.\n Please run the same goal with the -DdownloadSources=true parameter in order to check remote repositories for sources.\n List of artifacts without a source archive: +sourcesmissingitem=\n o {0} +javadocnotavailable=\n Javadoc for some artifacts is not available.\n List of artifacts without a javadoc archive: +javadocnotdownloaded=\n Javadoc for some artifacts is not available.\n Please run the same goal with the -DdownloadJavadocs=true parameter in order to check remote repositories for javadoc.\n List of artifacts without a javadoc archive: +javadocmissingitem=\n o {0} +errorresolving=Error resolving {0} artifact. Artifact id: {1} (Message: {2}) +artifactresolution=An error occurred during dependency resolution of the following artifact:\n {0}:{1}:{2}\nCaused by: {3} +artifactdownload=An error occurred during dependency resolution.\n Failed to retrieve {0}:{1}-{2}\nCaused by: {3} +cantcanonicalize=Can''t canonicalize system path: {0} +unabletoparseversion={0}: unable to parse version ''{1}'' for dependency ''{2}'': {3} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/tools/bundle/plugin/LICENSE.txt b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/tools/bundle/plugin/LICENSE.txt new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/tools/bundle/plugin/LICENSE.txt @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/tools/bundle/plugin/NOTICE.txt b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/tools/bundle/plugin/NOTICE.txt new file mode 100644 index 0000000000..644a49d98b --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-bundle-plugin/src/main/resources/org/apache/tuscany/sca/tools/bundle/plugin/NOTICE.txt @@ -0,0 +1,5 @@ +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/NOTICE new file mode 100644 index 0000000000..51042eab05 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/README b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/README new file mode 100644 index 0000000000..d53760029f --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/README @@ -0,0 +1,46 @@ +Tuscany SCA Dependency Lister +============================= + +Makes use of the extension Maven dependency support to list out all of the +dependencis in the module where the plugin is used. The module is +analysed and a report (dependency.txt) is written into the modules directory including +each dependency and the path through the maven transitive dependencies that caused +the original dependency to be included. For example, Here is a line which lists +a a jar dependency, the phase in which it was found, the module being processed +and he path that causes the dependency + +DEPENDENCY PHASE MODULE PATH TO DEPENDENCY +jaxb-api-2.1.jar compile Apache Tuscany SCA Atom+RSS Feed Aggregator Sample Webapp tuscany-host-webapp-1.1-incubating-SNAPSHOT tuscany-host-embedded-1.1-incubating-SNAPSHOT tuscany-core-databinding-1.1-incubating-SNAPSHOT tuscany-databinding-jaxb-1.1-incubating-SNAPSHOT jaxb-api-2.1 + +It is often convenient to further analyse these entries using the spreadsheet of your +choice so the columns are tab separated to allow for easy conversion. + +The plugin can be included in a module using the following, + + + org.apache.tuscany.sca + tuscany-maven-dependency-lister + 1.1-incubating-SNAPSHOT + + + + execute + + + + + +If you include this at the top level of you project and have it run for each model you +will get a report for each model independently. For example, in the Tuscany SCA project +the plugin is included in the pom.xml files at the sca level under the profile +"dependecies" so to generate a dependencies report for the Tuscany SCA project: + +cd sca +mvn -o -Pdependencies -Dmaven.test.skip=true + +Once you have dependency.txt files in your modules +the you favourite command line tools can be used to concatenate and sort them +to get a full picture of the dependencies in you project, for example, with linux you +could do, + +find . -name dependency.txt -exec cat '{}' >> deptotal.txt \; diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/pom.xml new file mode 100644 index 0000000000..d5651a59fa --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/pom.xml @@ -0,0 +1,71 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 2.0-M1 + ../pom.xml + + tuscany-maven-dependency-lister + maven-plugin + Apache Tuscany SCA Dependency Lister Maven Plugin + + + + org.apache.maven + maven-plugin-api + 2.0.7 + + + + org.apache.maven + maven-project + 2.0.7 + + + + org.apache.maven + maven-settings + 2.0.7 + + + + org.apache.maven + maven-artifact + 2.0.7 + + + + org.apache.maven + maven-model + 2.0.7 + + + + org.apache.maven.shared + maven-dependency-tree + 1.0 + + + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/src/main/java/org/apache/tuscany/tools/sca/dependency/lister/plugin/DependencyListerMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/src/main/java/org/apache/tuscany/tools/sca/dependency/lister/plugin/DependencyListerMojo.java new file mode 100644 index 0000000000..b904ac4804 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-dependency-lister/src/main/java/org/apache/tuscany/tools/sca/dependency/lister/plugin/DependencyListerMojo.java @@ -0,0 +1,198 @@ +/* + * 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. + */ +package org.apache.tuscany.tools.sca.dependency.lister.plugin; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.Iterator; +import java.util.List; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactCollector; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectBuilder; +import org.apache.maven.settings.Settings; +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.shared.dependency.tree.DependencyTree; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException; + +/** + * @version $Rev: 588816 $ $Date: 2007-10-27 01:22:38 +0100 (Sat, 27 Oct 2007) $ + * @goal execute + * @phase generate-sources + * @requiresDependencyResolution test + * @description List dependencies for an SCA project + */ +public class DependencyListerMojo extends AbstractMojo { + /** + * The project to create a build for. + * + * @parameter expression="${project}" + * @required + */ + private MavenProject project; + + /** + * Used for resolving artifacts + * + * @component + */ + private ArtifactResolver artifactResolver; + + /** + * Factory for creating artifact objects + * + * @component + */ + private ArtifactFactory artifactFactory; + + /** + * @component + */ + private ArtifactMetadataSource artifactMetadataSource; + + /** + * @component + */ + private DependencyTreeBuilder dependencyTreeBuilder; + + /** + * @component + */ + private ArtifactCollector collector; + + /** + * @component + */ + private MavenProjectBuilder mavenProjectBuilder; + + /** + * The local repository where the artifacts are located + * + * @parameter expression="${localRepository}" + * @required + */ + private ArtifactRepository localRepository; + + /** + * The remote repositories where artifacts are located + * + * @parameter expression="${project.remoteArtifactRepositories}" + */ + private List remoteRepositories; + + /** + * The current user system settings for use in Maven. + * + * @parameter expression="${settings}" + * @required + * @readonly + */ + private Settings settings; + + + /** + * The build.xml file to generate. + * @parameter expression="${basedir}/target/dependency.txt" + */ + private String buildFile; + + public void execute() throws MojoExecutionException { + + System.out.println("Analysing " + buildFile); + + // Open the target build.xml file + File targetFile = new File(buildFile); + PrintWriter pw; + try { + pw = new PrintWriter(new FileOutputStream(targetFile)); + } catch (FileNotFoundException e) { + System.out.println(e.toString()); + return; + } + + DependencyTree dependencyTree; + + try + { + dependencyTree = dependencyTreeBuilder.buildDependencyTree( project, localRepository, artifactFactory, + artifactMetadataSource, collector ); + } + catch ( DependencyTreeBuilderException e ) + { + throw new MojoExecutionException( "Can't build dependency tree", e ); + } + + // processNode(dependencyTree.getRootNode(), "--", pw); + + for (Artifact artifact: (List)project.getTestArtifacts()) { + pw.println( artifact.getFile().getName() + "\t" + + artifact.getScope() + "\t" + + project.getName() + "\t" + + findArtifactPath(dependencyTree.getRootNode(), artifact)); + } + + pw.close(); + } + + private void processNode(DependencyNode node, String indent, PrintWriter pw){ + + pw.println(indent + node.getArtifact().getScope() + " " + node.getArtifact().toString()); + + Iterator it = node.getChildren().iterator(); + while ( it.hasNext() ) + { + DependencyNode child = (DependencyNode) it.next(); + + processNode(child, indent + "--", pw); + } + } + + private String findArtifactPath(DependencyNode node, Artifact artifact){ + String path = null; + + Iterator it = node.getChildren().iterator(); + while ( it.hasNext() && (path == null) ) + { + DependencyNode child = (DependencyNode) it.next(); + + if (child.getArtifact().getArtifactId().equals(artifact.getArtifactId())) { + path = child.getArtifact().getArtifactId() + "-" + child.getArtifact().getVersion(); + } else { + path = findArtifactPath(child, artifact); + + if (path != null){ + path = child.getArtifact().getArtifactId() + "-" + child.getArtifact().getVersion() + "\t" + path; + } + } + } + + return path; + } + +} \ No newline at end of file diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/NOTICE new file mode 100644 index 0000000000..25bb89c9b2 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/pom.xml new file mode 100644 index 0000000000..e2fae8c108 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/pom.xml @@ -0,0 +1,304 @@ + + + + 4.0.0 + + org.apache + apache + 4 + + + org.apache.tuscany.sca + tuscany-maven-eclipse-compiler + jar + Apache Tuscany SCA Eclipse Compiler Plugin + 2.0-M1 + + + + org.apache.maven + maven-plugin-api + 2.0.8 + + + + org.apache.maven + maven-project + 2.0.8 + + + junit + junit + + + + + + org.apache.maven + maven-settings + 2.0.8 + + + + org.apache.maven + maven-artifact + 2.0.8 + + + + org.apache.maven + maven-model + 2.0.8 + + + + org.codehaus.plexus + plexus-compiler-api + 1.5.1 + + + + org.eclipse.jdt + core + 3.3.0-v_771 + + + org.eclipse.core + resources + + + org.eclipse.core + runtime + + + org.eclipse.core + filesystem + + + org.eclipse + text + + + + + + org.eclipse + osgi + 3.3.0-v20070530 + compile + + + + + + + install + + + + src/main/resources + + + ${notice.dir} + META-INF + true + + LICENSE + NOTICE + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + 1.5 + 1.5 + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.1 + + + + ${project.artifactId} + ${name} + The Apache Software Foundation + ${version} + ${name} + org.apache + The Apache Software Foundation + ${version} + + + + + + + + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/ClassLoaderNameEnvironment.java b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/ClassLoaderNameEnvironment.java new file mode 100644 index 0000000000..4b3f84edf4 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/ClassLoaderNameEnvironment.java @@ -0,0 +1,195 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.tools.maven.compiler; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; + +/** + * An implementation of INameEnvironment based on a ClassLoader. + * + * @version $Rev: $ $Date: $ + */ +class ClassLoaderNameEnvironment implements INameEnvironment { + private final static char fileSeparator = System.getProperty("file.separator").charAt(0); + + private ClassLoader classLoader; + private List sourceLocations; + private Map sourceFiles; + + ClassLoaderNameEnvironment(ClassLoader classLoader, List sourceLocations) { + this.classLoader = classLoader; + this.sourceLocations = sourceLocations; + sourceFiles = new HashMap(); + } + + public NameEnvironmentAnswer findType(char[][] compoundTypeName) { + StringBuffer className = new StringBuffer(); + for (char[] name: compoundTypeName) { + if (className.length() != 0) { + className.append('.'); + } + className.append(name); + } + return nameAnswer(className.toString()); + } + + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { + StringBuffer className = new StringBuffer(); + for (char[] name: packageName) { + if (className.length() != 0) { + className.append('.'); + } + className.append(name); + } + if (className.length() != 0) { + className.append('.'); + } + className.append(typeName); + return nameAnswer(className.toString()); + } + + public boolean isPackage(char[][] parentPackageName, char[] packageName) { + StringBuffer fullPackageName = new StringBuffer(); + if (parentPackageName != null) { + for (char[] name: parentPackageName) { + if (fullPackageName.length() != 0) { + fullPackageName.append('.'); + } + fullPackageName.append(name); + } + } + if (fullPackageName.length() != 0) { + fullPackageName.append('.'); + } + fullPackageName.append(packageName); + return isPackage(fullPackageName.toString()); + } + + public void cleanup() { + } + + /** + * Returns the source file for the given class name. + * + * @param className + * @return + */ + private File sourceFile(String className) { + File sourceFile = (File)sourceFiles.get(className); + if (sourceFile != null) { + return sourceFile; + } + String sourceName = className.replace('.', fileSeparator) + ".java"; + sourceFile = sourceFileInSourceLocations(sourceName); + sourceFiles.put(className, sourceFile); + return sourceFile; + } + + /** + * Returns the source file for the given source path relative to the source locations. + * + * @param className + * @return + */ + private File sourceFileInSourceLocations(String relativePath) { + for (String sourceLocation : sourceLocations) { + File sourceFile = new File(sourceLocation, relativePath); + if (sourceFile.exists()) { + return sourceFile; + } + } + return null; + } + + /** + * Returns true if the given name is a package name. + * + * @param name + * @return + */ + private boolean isPackage(String name) { + if (sourceFile(name) != null) { + return false; + } + String resourceName = '/' + name.replace('.', '/') + ".class"; + InputStream is = classLoader.getResourceAsStream(resourceName); + if (is == null) { + return true; + } else { + try { + is.close(); + } catch (IOException e) {} + return false; + } + } + + /** + * Find the NameAnswer for by the given class name. + * + * @param className + * @return + */ + private NameEnvironmentAnswer nameAnswer(String className) { + try { + File sourceFile = sourceFile(className); + if (sourceFile != null) { + ICompilationUnit compilationUnit = new FileCompilationUnit(sourceFile.getAbsolutePath(), className); + return new NameEnvironmentAnswer(compilationUnit, null); + } + + String resourceName = className.replace('.', '/') + ".class"; + InputStream is = classLoader.getResourceAsStream(resourceName); + if (is == null) { + return null; + } + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] b = new byte[2048]; + for (;;) { + int n = is.read(b); + if (n <= 0) { + break; + } + bos.write(b, 0, n); + } + byte[] classBytes = bos.toByteArray(); + + ClassFileReader classFileReader = new ClassFileReader(classBytes, className.toCharArray(), true); + return new NameEnvironmentAnswer(classFileReader, null); + + } catch (IOException e) { + throw new IllegalArgumentException(e); + } catch (ClassFormatException e) { + throw new IllegalArgumentException(e); + } + } + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/CompilerRequestor.java b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/CompilerRequestor.java new file mode 100644 index 0000000000..3df4b4d602 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/CompilerRequestor.java @@ -0,0 +1,114 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.tools.maven.compiler; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +import org.codehaus.plexus.compiler.CompilerError; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.ClassFile; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.ICompilerRequestor; + +class CompilerRequestor implements ICompilerRequestor { + private String outputDirectory; + private boolean showWarnings; + private List compilerErrors; + + public CompilerRequestor(String outputDirectory, boolean showWarnings, List compilerErrors) { + this.outputDirectory = outputDirectory; + this.showWarnings = showWarnings; + this.compilerErrors = compilerErrors; + } + + public void acceptResult(CompilationResult result) { + boolean hasErrors = false; + if (result.hasProblems()) { + + // Convert JDT IProblems into plexus CompilerErrors + for (IProblem problem: result.getProblems()) { + if (problem.isWarning()) { + if (showWarnings) { + compilerErrors.add(new CompilerError(new String(problem.getOriginatingFileName()), + false, + problem.getSourceLineNumber(), + problem.getSourceStart(), + problem.getSourceLineNumber(), + problem.getSourceEnd(), + problem.getMessage())); + } + + } else if (problem.isError()) { + hasErrors = true; + compilerErrors.add(new CompilerError(new String(problem.getOriginatingFileName()), + true, + problem.getSourceLineNumber(), + problem.getSourceStart(), + problem.getSourceLineNumber(), + problem.getSourceEnd(), + problem.getMessage())); + + } + } + } + + // Write the class files + if (!hasErrors) { + ClassFile[] classFiles = result.getClassFiles(); + for (ClassFile classFile: classFiles) { + + // Create file and parent directories + StringBuffer className = new StringBuffer(); + for (char[] name: classFile.getCompoundName()) { + if (className.length() != 0) { + className.append('.'); + } + className.append(name); + } + File file = new File(outputDirectory, className.toString().replace('.', '/') + ".class"); + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + + // Write class file contents + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + fos.write(classFile.getBytes()); + } catch (FileNotFoundException e) { + throw new IllegalArgumentException(e); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) {} + } + } + } + } + } + +} \ No newline at end of file diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/FileCompilationUnit.java b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/FileCompilationUnit.java new file mode 100644 index 0000000000..08ed7f034e --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/FileCompilationUnit.java @@ -0,0 +1,88 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.tools.maven.compiler; + +import java.io.CharArrayWriter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; + +/** + * An implementation of ICompilationUnit that wraps a File. + * + * @version $Rev: $ $Date: $ + */ +class FileCompilationUnit implements ICompilationUnit { + private final static char fileSeparator = System.getProperty("file.separator").charAt(0); + private String className; + private String sourceFile; + + FileCompilationUnit(String sourceFile, String className) { + this.className = className; + this.sourceFile = sourceFile; + } + + public char[] getContents() { + try { + InputStreamReader reader = new InputStreamReader(new FileInputStream(sourceFile)); + CharArrayWriter writer = new CharArrayWriter(); + char[] b = new char[2048]; + for (;;) { + int n = reader.read(b); + if (n <= 0) { + break; + } + writer.write(b, 0, n); + } + return writer.toCharArray(); + + } catch (FileNotFoundException e) { + throw new IllegalArgumentException(e); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + public char[] getFileName() { + return (className.replace('.', fileSeparator) + ".java").toCharArray(); + } + + public char[] getMainTypeName() { + int dot = className.lastIndexOf('.'); + if (dot > 0) { + return className.substring(dot + 1).toCharArray(); + } + return className.toCharArray(); + } + + public char[][] getPackageName() { + StringTokenizer tokens = new StringTokenizer(className, "."); + char[][] packageName = new char[tokens.countTokens() - 1][]; + for (int i = 0; i < packageName.length; i++) { + String token = tokens.nextToken(); + packageName[i] = token.toCharArray(); + } + return packageName; + } +} \ No newline at end of file diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/JavaCompiler.java b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/JavaCompiler.java new file mode 100644 index 0000000000..f628a38e95 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/JavaCompiler.java @@ -0,0 +1,212 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.tools.maven.compiler; + +import static org.codehaus.plexus.compiler.CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE; +import static org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies.proceedWithAllProblems; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.GENERATE; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.IGNORE; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.OPTION_Encoding; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.OPTION_LineNumberAttribute; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.OPTION_LocalVariableAttribute; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.OPTION_ReportDeprecation; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.OPTION_Source; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.OPTION_SourceFileAttribute; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.OPTION_TargetPlatform; +import static org.eclipse.jdt.internal.compiler.impl.CompilerOptions.WARNING; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.tools.maven.compiler.osgi.BundleResolver; +import org.apache.tuscany.sca.tools.maven.compiler.osgi.BundleUtil; +import org.codehaus.plexus.compiler.AbstractCompiler; +import org.codehaus.plexus.compiler.CompilerConfiguration; +import org.codehaus.plexus.compiler.CompilerError; +import org.codehaus.plexus.compiler.CompilerException; +import org.eclipse.jdt.internal.compiler.Compiler; +import org.eclipse.jdt.internal.compiler.ICompilerRequestor; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.osgi.framework.BundleException; + +/** + * A custom Plexus Java compiler plugin that uses the Eclipse compiler. + * + * @version $Rev: $ $Date: $ + */ +public class JavaCompiler extends AbstractCompiler { + + public JavaCompiler() { + super(ONE_OUTPUT_FILE_PER_INPUT_FILE, ".java", ".class", null); + } + + public List compile(CompilerConfiguration configuration) throws CompilerException { + BundleResolver stateController = new BundleResolver(getLogger()); + + getLogger().info("Invoking Tuscany Eclipse JDT compiler"); + + List urls = new ArrayList(); + try { + for (String entry : (List)configuration.getClasspathEntries()) { + urls.add(new File(entry).toURI().toURL()); + } + } catch (MalformedURLException e) { + throw new CompilerException(e.getMessage(), e); + } + + ClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()])); + + // Determine compiler configuration + Map settings = new HashMap(); + String sourceVersion = configuration.getSourceVersion(); + if (sourceVersion != null && sourceVersion.length() != 0) { + settings.put(OPTION_Source, sourceVersion); + } + String targetVersion = configuration.getTargetVersion(); + if (targetVersion != null && targetVersion.length() != 0) { + settings.put(OPTION_TargetPlatform, targetVersion); + } + settings.put(OPTION_LineNumberAttribute, GENERATE); + settings.put(OPTION_SourceFileAttribute, GENERATE); + if (configuration.isDebug()) { + settings.put(OPTION_LocalVariableAttribute, GENERATE); + } + if (configuration.getSourceEncoding() != null && !(configuration.getSourceEncoding().length() == 0)) { + settings.put(OPTION_Encoding, configuration.getSourceEncoding()); + } + if (configuration.isShowDeprecation()) { + settings.put(OPTION_ReportDeprecation, WARNING); + } else { + settings.put(OPTION_ReportDeprecation, IGNORE); + } + + // Create a compiler + List compilerErrors = new ArrayList(); + INameEnvironment nameEnvironment = + new ClassLoaderNameEnvironment(classLoader, configuration.getSourceLocations()); + ICompilerRequestor requestor = + new CompilerRequestor(configuration.getOutputLocation(), configuration.isShowWarnings(), compilerErrors); + Compiler compiler = + new Compiler(nameEnvironment, proceedWithAllProblems(), new CompilerOptions(settings), requestor, + new DefaultProblemFactory(Locale.getDefault())); + + // Create compilation units for the source files + List compilationUnits = new ArrayList(); + + // Go over the input source locations + List sourceLocations = (List)configuration.getSourceLocations(); + for (String sourceLocation : sourceLocations) { + + // Exclude nested source locations + List excludeLocations = new ArrayList(); + for (String nestedLocation : sourceLocations) { + if (nestedLocation != sourceLocation && nestedLocation.startsWith(sourceLocation)) { + excludeLocations.add(nestedLocation); + } + } + + // List source files in each source location + for (String sourceFile : (Set)getSourceFilesForSourceRoot(configuration, sourceLocation)) { + + // Exclude files from excluded nested locations + boolean excluded = false; + for (String excludeLocation : excludeLocations) { + if (sourceFile.startsWith(excludeLocation)) { + excluded = true; + } + } + if (!excluded) { + + // Create a compilation unit for the source file + FileCompilationUnit compilationUnit = + new FileCompilationUnit(sourceFile, makeClassName(sourceFile, sourceLocation)); + compilationUnits.add(compilationUnit); + } + } + } + + // Compile all the compilation units + getLogger().info("Compiling " + compilationUnits.size() + " to " + configuration.getOutputLocation()); + compiler.compile((ICompilationUnit[])compilationUnits.toArray(new ICompilationUnit[compilationUnits.size()])); + + // getLogger().info(configuration.getCustomCompilerArguments().toString()); + boolean osgi = "true".equals(configuration.getCustomCompilerArguments().get("-osgi")); + File proj = new File(configuration.getOutputLocation()); + + String symbol = null; + try { + // Don't trigger the resolution for test-compile + if (!"test-classes".equals(proj.getName())) { + symbol = BundleUtil.getBundleSymbolicName(proj); + } + } catch (IOException e1) { + symbol = null; + } + + if (osgi && symbol != null) { + getLogger().info("Resolving OSGi bundle: "+symbol); + for (String entry : (List)configuration.getClasspathEntries()) { + try { + File cp = new File(entry); + if (cp.exists()) { + stateController.addBundle(cp); + } + } catch (BundleException e) { + getLogger().error(e.getMessage(), e); + } + } + + stateController.resolveState(); + BundleDescription b = stateController.getBundleDescription(proj); + if (b != null) { + try { + stateController.assertResolved(b); + getLogger().info("OSGi bundle is resolved: " + b.getSymbolicName()); + } catch (BundleException e) { + stateController.analyzeErrors(b); + if(getLogger().isDebugEnabled()) { + getLogger().debug(stateController.reportErrors(b)); + } + // FIXME: For now, only a warning is reported + // throw new CompilerException(e.getMessage(), e); + } + } + } + + return compilerErrors; + } + + public String[] createCommandLine(CompilerConfiguration config) throws CompilerException { + return null; + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/osgi/BundleResolver.java b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/osgi/BundleResolver.java new file mode 100644 index 0000000000..06f26f7e65 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/osgi/BundleResolver.java @@ -0,0 +1,490 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.tools.maven.compiler.osgi; + +import static org.eclipse.osgi.service.resolver.ResolverError.IMPORT_PACKAGE_USES_CONFLICT; +import static org.eclipse.osgi.service.resolver.ResolverError.MISSING_FRAGMENT_HOST; +import static org.eclipse.osgi.service.resolver.ResolverError.MISSING_IMPORT_PACKAGE; +import static org.eclipse.osgi.service.resolver.ResolverError.MISSING_REQUIRE_BUNDLE; +import static org.eclipse.osgi.service.resolver.ResolverError.REQUIRE_BUNDLE_USES_CONFLICT; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.logging.Logger; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.osgi.service.resolver.BundleSpecification; +import org.eclipse.osgi.service.resolver.ExportPackageDescription; +import org.eclipse.osgi.service.resolver.HostSpecification; +import org.eclipse.osgi.service.resolver.ImportPackageSpecification; +import org.eclipse.osgi.service.resolver.ResolverError; +import org.eclipse.osgi.service.resolver.State; +import org.eclipse.osgi.service.resolver.StateObjectFactory; +import org.eclipse.osgi.service.resolver.VersionConstraint; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; + +public class BundleResolver { + private static final String PROP_MAVEN_PROJECT = "MavenProject"; + private static final String PROP_MANIFEST = "BundleManifest"; + + private StateObjectFactory factory = StateObjectFactory.defaultFactory; + private State state; + private long id = 0; + private Logger logger; + + public static BundleDescription[] getDependentBundles(BundleDescription root) { + if (root == null) + return new BundleDescription[0]; + BundleDescription[] imported = getImportedBundles(root); + BundleDescription[] required = getRequiredBundles(root); + BundleDescription[] dependents = new BundleDescription[imported.length + required.length]; + System.arraycopy(imported, 0, dependents, 0, imported.length); + System.arraycopy(required, 0, dependents, imported.length, required.length); + return dependents; + } + + public static BundleDescription[] getImportedBundles(BundleDescription root) { + if (root == null) + return new BundleDescription[0]; + ExportPackageDescription[] packages = root.getResolvedImports(); + List resolvedImports = new ArrayList(packages.length); + for (int i = 0; i < packages.length; i++) + if (!root.getLocation().equals(packages[i].getExporter().getLocation()) && !resolvedImports + .contains(packages[i].getExporter())) + resolvedImports.add(packages[i].getExporter()); + return (BundleDescription[])resolvedImports.toArray(new BundleDescription[resolvedImports.size()]); + } + + public static BundleDescription[] getRequiredBundles(BundleDescription root) { + if (root == null) + return new BundleDescription[0]; + return root.getResolvedRequires(); + } + + public BundleResolver(Logger logger) { + this.logger = logger; + this.state = factory.createState(true); + Properties props = new Properties(); + props.putAll(System.getProperties()); + BundleUtil.loadVMProfile(props); + state.setPlatformProperties(props); + URL url = Bundle.class.getProtectionDomain().getCodeSource().getLocation(); + + File osgi = toFile(url); + try { + addBundle(osgi); + } catch (BundleException e) { + throw new IllegalArgumentException(e); + } + } + + private long getNextId() { + return ++id; + } + + public BundleDescription addBundle(File bundleLocation) throws BundleException { + return addBundle(bundleLocation, false); + } + + public BundleDescription addBundle(File bundleLocation, boolean override) throws BundleException { + if (bundleLocation == null || !bundleLocation.exists()) + throw new IllegalArgumentException("bundleLocation not found: " + bundleLocation); + Dictionary manifest = loadManifestAttributes(bundleLocation); + if (manifest == null) { + // throw new BundleException("manifest not found in " + bundleLocation); + return null; + } + return addBundle(manifest, bundleLocation, override); + } + + public BundleDescription addBundle(File manifestLocation, File bundleLocation, boolean override) + throws BundleException { + if (bundleLocation == null || !bundleLocation.exists()) + throw new IllegalArgumentException("bundleLocation not found: " + bundleLocation); + Dictionary manifest = loadManifestAttributes(manifestLocation); + if (manifest == null) + throw new IllegalArgumentException("manifest not found in " + manifestLocation); + return addBundle(manifest, bundleLocation, override); + } + + private Dictionary loadManifestAttributes(File bundleLocation) { + Manifest m = loadManifest(bundleLocation); + if (m == null) { + return null; + } + + return manifestToProperties(m.getMainAttributes()); + } + + public Manifest loadManifest(File bundleLocation) { + try { + return BundleUtil.getManifest(bundleLocation); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + private Properties manifestToProperties(Attributes d) { + Iterator iter = d.keySet().iterator(); + Properties result = new Properties(); + while (iter.hasNext()) { + Attributes.Name key = (Attributes.Name)iter.next(); + result.put(key.toString(), d.get(key)); + } + return result; + } + + private BundleDescription addBundle(Dictionary enhancedManifest, File bundleLocation, boolean override) + throws BundleException { + + BundleDescription descriptor = + factory.createBundleDescription(state, enhancedManifest, bundleLocation.getAbsolutePath(), getNextId()); + + setUserProperty(descriptor, PROP_MANIFEST, enhancedManifest); + if (override) { + BundleDescription[] conflicts = state.getBundles(descriptor.getSymbolicName()); + if (conflicts != null) { + for (BundleDescription conflict : conflicts) { + state.removeBundle(conflict); + logger + .warn(conflict.toString() + " has been replaced by another bundle with the same symbolic name " + + descriptor.toString()); + } + } + } + + state.addBundle(descriptor); + return descriptor; + } + + public BundleDescription getResolvedBundle(String bundleId) { + BundleDescription[] description = state.getBundles(bundleId); + if (description == null) + return null; + for (int i = 0; i < description.length; i++) { + if (description[i].isResolved()) + return description[i]; + } + return null; + } + + public void resolveState() { + state.resolve(false); + + if (logger.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Resolved OSGi state\n"); + for (BundleDescription bundle : state.getBundles()) { + if (!bundle.isResolved()) { + sb.append("[X] "); + } else { + sb.append("[V] "); + } + sb.append(bundle).append(": (").append(bundle.getLocation()); + sb.append(")\n"); + for (ResolverError error : state.getResolverErrors(bundle)) { + sb.append(" ").append(error.toString()).append('\n'); + } + } + logger.debug(sb.toString()); + } + } + + public State getState() { + return state; + } + + public BundleDescription[] getBundles() { + return state.getBundles(); + } + + public ResolverError[] getResolverErrors(BundleDescription bundle) { + Set errors = new LinkedHashSet(); + getRelevantErrors(errors, bundle); + return (ResolverError[])errors.toArray(new ResolverError[errors.size()]); + } + + private void getRelevantErrors(Set errors, BundleDescription bundle) { + ResolverError[] bundleErrors = state.getResolverErrors(bundle); + for (int j = 0; j < bundleErrors.length; j++) { + ResolverError error = bundleErrors[j]; + errors.add(error); + + VersionConstraint constraint = error.getUnsatisfiedConstraint(); + if (constraint instanceof BundleSpecification || constraint instanceof HostSpecification) { + BundleDescription[] requiredBundles = state.getBundles(constraint.getName()); + for (int i = 0; i < requiredBundles.length; i++) { + getRelevantErrors(errors, requiredBundles[i]); + } + } + } + } + + private void logError(BundleDescription bundle, int level, Object object) { + StringBuffer msg = new StringBuffer(); + for (int i = 0; i < level; i++) { + msg.append("--"); + } + msg.append("> [").append(bundle.getSymbolicName()).append("] "); + msg.append(object); + logger.error(msg.toString()); + } + + public void analyzeErrors(BundleDescription bundle) { + analyzeErrors(bundle, new HashSet(), 1); + } + + private void analyzeErrors(BundleDescription bundle, Set bundles, int level) { + if (bundles.contains(bundle)) { + return; + } + bundles.add(bundle); + ResolverError[] errors = state.getResolverErrors(bundle); + for (ResolverError error : errors) { + logError(bundle, level, error); + VersionConstraint constraint = error.getUnsatisfiedConstraint(); + switch (error.getType()) { + case MISSING_IMPORT_PACKAGE: + ImportPackageSpecification pkgSpec = (ImportPackageSpecification)constraint; + for (BundleDescription b : getBundles()) { + for (ExportPackageDescription pkg : b.getExportPackages()) { + if (pkg.getName().equals(pkgSpec.getName())) { + if (pkgSpec.getVersionRange().isIncluded(pkg.getVersion())) { + if (!pkg.getExporter().isResolved()) { + logError(b, level, "Bundle unresolved: " + pkg); + analyzeErrors(pkg.getExporter(), bundles, level + 1); + } + } else { + logError(b, level, "Version mismatch: " + pkgSpec + " " + pkg); + } + } + } + } + break; + case MISSING_REQUIRE_BUNDLE: + case MISSING_FRAGMENT_HOST: + // BundleSpecification bundleSpec = (BundleSpecification)constraint; + for (BundleDescription b : getBundles()) { + if (b == bundle) { + continue; + } + if (b.getSymbolicName().equals(constraint.getName())) { + if (constraint.getVersionRange().isIncluded(b.getVersion())) { + // There must be something wrong in the bundle + analyzeErrors(b, bundles, level); + } else { + logError(bundle, level, "Version mismatch: " + constraint + " " + b); + } + } + } + break; + case IMPORT_PACKAGE_USES_CONFLICT: + case REQUIRE_BUNDLE_USES_CONFLICT: + default: + logger.error(reportErrors(bundle)); + break; + } + } + + } + + public Set getAllErrors() { + BundleDescription[] bundles = state.getBundles(); + Set errors = new LinkedHashSet(); + for (int i = 0; i < bundles.length; i++) { + BundleDescription bundle = bundles[i]; + ResolverError[] bundleErrors = state.getResolverErrors(bundle); + if (bundleErrors != null) { + errors.addAll(Arrays.asList(bundleErrors)); + } + } + return errors; + } + + public List getDependencies(BundleDescription desc) { + Set bundleIds = new LinkedHashSet(); + addBundleAndDependencies(desc, bundleIds, true); + List dependencies = new ArrayList(); + for (long bundleId : bundleIds) { + if (desc.getBundleId() != bundleId) { + BundleDescription dependency = state.getBundle(bundleId); + BundleDescription supplier = dependency.getSupplier().getSupplier(); + HostSpecification host = supplier.getHost(); + if (host == null || !desc.equals(host.getSupplier())) { + dependencies.add(dependency); + } + } + } + return dependencies; + } + + /** + * Code below is copy&paste from org.eclipse.pde.internal.core.DependencyManager + * which seems to calculate runtime dependencies. In particular, it adds + * fragments' dependencies to the host bundle (see TychoTest#testFragment unit test). + * This may or may not cause problems... + * + * RequiredPluginsClasspathContainer#computePluginEntries has the logic to + * calculate compile-time dependencies in IDE. + * + * TODO find the code used by PDE/Build + */ + private static void addBundleAndDependencies(BundleDescription desc, Set bundleIds, boolean includeOptional) { + if (desc != null && bundleIds.add(new Long(desc.getBundleId()))) { + BundleSpecification[] required = desc.getRequiredBundles(); + for (int i = 0; i < required.length; i++) { + if (includeOptional || !required[i].isOptional()) + addBundleAndDependencies((BundleDescription)required[i].getSupplier(), bundleIds, includeOptional); + } + ImportPackageSpecification[] importedPkgs = desc.getImportPackages(); + for (int i = 0; i < importedPkgs.length; i++) { + ExportPackageDescription exporter = (ExportPackageDescription)importedPkgs[i].getSupplier(); + // Continue if the Imported Package is unresolved of the package is optional and don't want optional packages + if (exporter == null || (!includeOptional && Constants.RESOLUTION_OPTIONAL.equals(importedPkgs[i] + .getDirective(Constants.RESOLUTION_DIRECTIVE)))) + continue; + addBundleAndDependencies(exporter.getExporter(), bundleIds, includeOptional); + } + BundleDescription[] fragments = desc.getFragments(); + for (int i = 0; i < fragments.length; i++) { + if (!fragments[i].isResolved()) + continue; + String id = fragments[i].getSymbolicName(); + if (!"org.eclipse.ui.workbench.compatibility".equals(id)) //$NON-NLS-1$ + addBundleAndDependencies(fragments[i], bundleIds, includeOptional); + } + HostSpecification host = desc.getHost(); + if (host != null) + addBundleAndDependencies((BundleDescription)host.getSupplier(), bundleIds, includeOptional); + } + } + + public BundleDescription getBundleDescription(MavenProject project) { + String location = project.getFile().getParentFile().getAbsolutePath(); + return state.getBundleByLocation(location); + } + + public BundleDescription getBundleDescription(File location) { + String absolutePath = location.getAbsolutePath(); + return state.getBundleByLocation(absolutePath); + } + + private static void setUserProperty(BundleDescription desc, String name, Object value) { + Object userObject = desc.getUserObject(); + + if (userObject != null && !(userObject instanceof Map)) { + throw new IllegalStateException("Unexpected user object " + desc.toString()); + } + + Map props = (Map)userObject; + if (props == null) { + props = new HashMap(); + desc.setUserObject(props); + } + + props.put(name, value); + } + + private static Object getUserProperty(BundleDescription desc, String name) { + Object userObject = desc.getUserObject(); + if (userObject instanceof Map) { + return ((Map)userObject).get(name); + } + return null; + } + + public MavenProject getMavenProject(BundleDescription desc) { + return (MavenProject)getUserProperty(desc, PROP_MAVEN_PROJECT); + } + + public void assertResolved(BundleDescription desc) throws BundleException { + if (!desc.isResolved()) { + throw new BundleException("Bundle cannot be resolved: " + desc); + } + } + + public String reportErrors(BundleDescription desc) { + StringBuffer msg = new StringBuffer(); + msg.append("Bundle ").append(desc.getSymbolicName()).append(" cannot be resolved: \n"); + BundleDescription[] bundles = state.getBundles(); + int index = 0; + for (BundleDescription b : bundles) { + if (b.isResolved()) { + continue; + } + ResolverError[] errors = state.getResolverErrors(b); + if (errors.length > 0) { + msg.append(" ").append("[").append(index++).append("] ").append(b.getSymbolicName()).append("\n"); + } + for (int i = 0; i < errors.length; i++) { + ResolverError error = errors[i]; + msg.append(" -->").append(error).append("\n"); + } + } + return msg.toString(); + } + + public String getManifestAttribute(BundleDescription desc, String attr) { + Dictionary mf = (Dictionary)getUserProperty(desc, PROP_MANIFEST); + if (mf != null) { + return (String)mf.get(attr); + } + return null; + } + + private static File toFile(URL url) { + if (url.getProtocol().equals("file") == false) { + return null; + } else { + String filename = url.getFile().replace('/', File.separatorChar).replace("%20", " "); + return new File(filename); + } + } + + /* + public static void main(String[] args) throws Exception { + BundleResolver resolver = new BundleResolver(new ConsoleLogger(Logger.LEVEL_INFO, "tuscany")); + + String home = System.getProperty("user.home"); + File jar = + new File(new File(home), + ".m2/repository/org/apache/tuscany/sca/tuscany-sca-api/1.4-EQUINOX-SNAPSHOT/tuscany-sca-api-1.4-EQUINOX-SNAPSHOT.jar"); + BundleDescription bundle = resolver.addBundle(jar); + resolver.resolveState(); + resolver.assertResolved(bundle); + } + */ +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/osgi/BundleUtil.java b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/osgi/BundleUtil.java new file mode 100644 index 0000000000..be8ee92fb6 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/java/org/apache/tuscany/sca/tools/maven/compiler/osgi/BundleUtil.java @@ -0,0 +1,618 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.tools.maven.compiler.osgi; + +import static org.osgi.framework.Constants.BUNDLE_CLASSPATH; +import static org.osgi.framework.Constants.BUNDLE_MANIFESTVERSION; +import static org.osgi.framework.Constants.BUNDLE_NAME; +import static org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME; +import static org.osgi.framework.Constants.BUNDLE_VERSION; +import static org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE; +import static org.osgi.framework.Constants.EXPORT_PACKAGE; +import static org.osgi.framework.Constants.IMPORT_PACKAGE; + +import java.io.BufferedInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.eclipse.osgi.framework.internal.core.Constants; +import org.eclipse.osgi.framework.internal.core.FrameworkProperties; +import org.eclipse.osgi.util.ManifestElement; +import org.osgi.framework.Version; + +/** + * Common functions used by the plugin. + * + * @version $Rev$ $Date$ + */ +public final class BundleUtil { + + /** + * Returns the name of a bundle, or null if the given file is not a bundle. + * + * @param file + * @return + * @throws IOException + */ + public static String getBundleSymbolicName(File file) throws IOException { + if (!file.exists()) { + return null; + } + String bundleName = null; + if (file.isDirectory()) { + File mf = new File(file, JarFile.MANIFEST_NAME); + if (!mf.isFile()) { + mf = new File(file, "../../" + JarFile.MANIFEST_NAME); + } + if (mf.isFile()) { + Manifest manifest = new Manifest(new FileInputStream(mf)); + bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + } + } else { + JarFile jar = new JarFile(file, false); + Manifest manifest = jar.getManifest(); + bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + jar.close(); + } + if (bundleName == null) { + return bundleName; + } + int sc = bundleName.indexOf(';'); + if (sc != -1) { + bundleName = bundleName.substring(0, sc); + } + return bundleName; + } + + static Manifest getManifest(File file) throws IOException { + if (!file.exists()) { + return null; + } + Manifest manifest = null; + String bundleName = null; + if (file.isDirectory()) { + File mf = new File(file, JarFile.MANIFEST_NAME); + if (!mf.isFile()) { + mf = new File(file, "../../" + JarFile.MANIFEST_NAME); + } + if (mf.isFile()) { + manifest = new Manifest(new FileInputStream(mf)); + bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + } + } else { + JarFile jar = new JarFile(file, false); + manifest = jar.getManifest(); + bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + jar.close(); + } + if (bundleName != null) { + return manifest; + } + + if (file.isFile()) { + Set jars = new HashSet(); + jars.add(file); + String name = file.getName(); + manifest = libraryManifest(jars, name, name, jarVersion(name), null); + } + return manifest; + } + + /** + * Generate a Bundle manifest for a set of JAR files. + * + * @param jarFiles + * @param name + * @param symbolicName + * @param version + * @param dir + * @return + * @throws IllegalStateException + */ + static Manifest libraryManifest(Set jarFiles, String name, String symbolicName, String version, String dir) + throws IllegalStateException { + try { + + // List exported packages and bundle classpath entries + StringBuffer classpath = new StringBuffer(); + Set exportedPackages = new HashSet(); + for (File jarFile : jarFiles) { + addPackages(jarFile, exportedPackages, version); + if (dir != null) { + classpath.append(dir).append("/"); + classpath.append(jarFile.getName()); + } else { + classpath.append("\"external:"); + classpath.append(jarFile.getPath().replace(File.separatorChar, '/')); + classpath.append("\""); + } + classpath.append(","); + } + + // Generate export-package and import-package declarations + StringBuffer exports = new StringBuffer(); + StringBuffer imports = new StringBuffer(); + Set importedPackages = new HashSet(); + for (String export : exportedPackages) { + + // Add export declaration + exports.append(export); + exports.append(','); + + // Add corresponding import declaration + String packageName = packageName(export); + if (!importedPackages.contains(packageName)) { + importedPackages.add(packageName); + imports.append(packageName); + imports.append(','); + } + } + + // Create a manifest + Manifest manifest = new Manifest(); + Attributes attributes = manifest.getMainAttributes(); + attributes.putValue("Manifest-Version", "1.0"); + attributes.putValue(BUNDLE_MANIFESTVERSION, "2"); + attributes.putValue(BUNDLE_SYMBOLICNAME, symbolicName); + attributes.putValue(BUNDLE_NAME, name); + attributes.putValue(BUNDLE_VERSION, version); + attributes.putValue(DYNAMICIMPORT_PACKAGE, "*"); + if (exports.length() > 1) { + attributes.putValue(EXPORT_PACKAGE, exports.substring(0, exports.length() - 1)); + } + if (imports.length() > 1) { + attributes.putValue(IMPORT_PACKAGE, imports.substring(0, imports.length() - 1)); + } + if (classpath.length() > 1) { + attributes.putValue(BUNDLE_CLASSPATH, classpath.substring(0, classpath.length() - 1)); + } + + return manifest; + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Write a bundle manifest. + * + * @param manifest + * @param out + * @throws IOException + */ + static void write(Manifest manifest, OutputStream out) throws IOException { + DataOutputStream dos = new DataOutputStream(out); + Attributes attributes = manifest.getMainAttributes(); + write(attributes, "Manifest-Version", dos); + write(attributes, BUNDLE_MANIFESTVERSION, dos); + write(attributes, BUNDLE_SYMBOLICNAME, dos); + write(attributes, BUNDLE_NAME, dos); + write(attributes, BUNDLE_VERSION, dos); + write(attributes, DYNAMICIMPORT_PACKAGE, dos); + write(attributes, BUNDLE_CLASSPATH, dos); + write(attributes, IMPORT_PACKAGE, dos); + write(attributes, EXPORT_PACKAGE, dos); + dos.flush(); + } + + /** + * Add packages to be exported out of a JAR file. + * + * @param jarFile + * @param packages + * @throws IOException + */ + private static void addPackages(File jarFile, Set packages, String version) throws IOException { + if (getBundleSymbolicName(jarFile) == null) { + String ver = ";version=" + version; + addAllPackages(jarFile, packages, ver); + } else { + addExportedPackages(jarFile, packages); + } + } + + /** + * Write manifest attributes. + * + * @param attributes + * @param key + * @param dos + * @throws IOException + */ + private static void write(Attributes attributes, String key, DataOutputStream dos) throws IOException { + String value = attributes.getValue(key); + if (value == null) { + return; + } + StringBuffer line = new StringBuffer(); + line.append(key); + line.append(": "); + line.append(new String(value.getBytes("UTF8"))); + line.append("\r\n"); + int l = line.length(); + if (l > 72) { + for (int i = 70; i < l - 2;) { + line.insert(i, "\r\n "); + i += 72; + l += 3; + } + } + dos.writeBytes(line.toString()); + } + + /** + * Strip an OSGi export, only retain the package name and version. + * + * @param export + * @return + */ + private static String stripExport(String export) { + int sc = export.indexOf(';'); + if (sc == -1) { + return export; + } + String base = export.substring(0, sc); + int v = export.indexOf("version="); + if (v != -1) { + sc = export.indexOf(';', v + 1); + if (sc != -1) { + return base + ";" + export.substring(v, sc); + } else { + return base + ";" + export.substring(v); + } + } else { + return base; + } + } + + /** + * Add all the packages out of a JAR. + * + * @param jarFile + * @param packages + * @param version + * @throws IOException + */ + private static void addAllPackages(File jarFile, Set packages, String version) throws IOException { + ZipInputStream is = new ZipInputStream(new FileInputStream(jarFile)); + ZipEntry entry; + while ((entry = is.getNextEntry()) != null) { + String entryName = entry.getName(); + if (!entry.isDirectory() && entryName != null + && entryName.length() > 0 + && !entryName.startsWith(".") + && entryName.endsWith(".class") // Exclude resources from Export-Package + && entryName.lastIndexOf("/") > 0 + && Character.isJavaIdentifierStart(entryName.charAt(0))) { + String pkg = entryName.substring(0, entryName.lastIndexOf("/")).replace('/', '.'); + if (!pkg.endsWith(".enum")) { + packages.add(pkg + version); + } + } + } + is.close(); + } + + /** + * Returns the name of the exported package in the given export. + * @param export + * @return + */ + private static String packageName(String export) { + int sc = export.indexOf(';'); + if (sc != -1) { + export = export.substring(0, sc); + } + return export; + } + + /** + * Add the packages exported by a bundle. + * + * @param file + * @param packages + * @return + * @throws IOException + */ + private static void addExportedPackages(File file, Set packages) throws IOException { + if (!file.exists()) { + return; + } + + // Read the export-package declaration and get a list of the packages available in a JAR + Set existingPackages = null; + String exports = null; + if (file.isDirectory()) { + File mf = new File(file, "META-INF/MANIFEST.MF"); + if (mf.isFile()) { + Manifest manifest = new Manifest(new FileInputStream(mf)); + exports = manifest.getMainAttributes().getValue(EXPORT_PACKAGE); + } + } else { + JarFile jar = new JarFile(file, false); + Manifest manifest = jar.getManifest(); + exports = manifest.getMainAttributes().getValue(EXPORT_PACKAGE); + jar.close(); + existingPackages = new HashSet(); + addAllPackages(file, existingPackages, ""); + } + if (exports == null) { + return; + } + + // Parse the export-package declaration, and extract the individual packages + StringBuffer buffer = new StringBuffer(); + boolean q = false; + for (int i = 0, n = exports.length(); i < n; i++) { + char c = exports.charAt(i); + if (c == '\"') { + q = !q; + } + if (!q) { + if (c == ',') { + + // Add the exported package to the set, after making sure it really exists in + // the JAR + String export = buffer.toString(); + if (existingPackages == null || existingPackages.contains(packageName(export))) { + packages.add(stripExport(export)); + } + buffer = new StringBuffer(); + continue; + } + } + buffer.append(c); + } + if (buffer.length() != 0) { + + // Add the exported package to the set, after making sure it really exists in + // the JAR + String export = buffer.toString(); + if (existingPackages == null || existingPackages.contains(packageName(export))) { + packages.add(stripExport(export)); + } + } + } + + /** + * starting with -, then some digits, then . or - or _, then some digits again + * + */ + private static Pattern pattern = Pattern.compile("-(\\d)+((\\.|-|_)(\\d)+)*"); + + /** + * Returns the version number to use for the given JAR file. + * + * @param fileName + * @return + */ + static String jarVersion(String fileName) { + String name = fileName; + int index = name.lastIndexOf('.'); + if (index != -1) { + // Trim the extension + name = name.substring(0, index); + } + + Matcher matcher = pattern.matcher(name); + String version = "0.0.0"; + if (matcher.find()) { + version = matcher.group(); + version = version.substring(1); + } + return version; + } + + /** + * Convert the maven version into OSGi version + * @param mavenVersion + * @return + */ + static String osgiVersion(String mavenVersion) { + ArtifactVersion ver = new DefaultArtifactVersion(mavenVersion); + String qualifer = ver.getQualifier(); + if (qualifer != null) { + StringBuffer buf = new StringBuffer(qualifer); + for (int i = 0; i < buf.length(); i++) { + char c = buf.charAt(i); + if (Character.isLetterOrDigit(c) || c == '-' || c == '_') { + // Keep as-is + } else { + buf.setCharAt(i, '_'); + } + } + qualifer = buf.toString(); + } + Version osgiVersion = + new Version(ver.getMajorVersion(), ver.getMinorVersion(), ver.getIncrementalVersion(), qualifer); + String version = osgiVersion.toString(); + return version; + } + + private static String J2SE = "J2SE-"; + private static String JAVASE = "JavaSE-"; + private static String PROFILE_EXT = ".profile"; + + public static void loadVMProfile(Properties properties) { + Properties profileProps = findVMProfile(properties); + String systemExports = properties.getProperty(Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES); + // set the system exports property using the vm profile; only if the property is not already set + if (systemExports == null) { + systemExports = profileProps.getProperty(Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES); + if (systemExports != null) + properties.put(Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES, systemExports); + } + // set the org.osgi.framework.bootdelegation property according to the java profile + String type = properties.getProperty(Constants.OSGI_JAVA_PROFILE_BOOTDELEGATION); // a null value means ignore + String profileBootDelegation = profileProps.getProperty(Constants.OSGI_BOOTDELEGATION); + if (Constants.OSGI_BOOTDELEGATION_OVERRIDE.equals(type)) { + if (profileBootDelegation == null) + properties.remove(Constants.OSGI_BOOTDELEGATION); // override with a null value + else + properties.put(Constants.OSGI_BOOTDELEGATION, profileBootDelegation); // override with the profile value + } else if (Constants.OSGI_BOOTDELEGATION_NONE.equals(type)) + properties.remove(Constants.OSGI_BOOTDELEGATION); // remove the bootdelegation property in case it was set + // set the org.osgi.framework.executionenvironment property according to the java profile + if (properties.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT) == null) { + // get the ee from the java profile; if no ee is defined then try the java profile name + String ee = + profileProps.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, profileProps + .getProperty(Constants.OSGI_JAVA_PROFILE_NAME)); + if (ee != null) + properties.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, ee); + } + } + + private static Properties findVMProfile(Properties properties) { + Properties result = new Properties(); + // Find the VM profile name using J2ME properties + String j2meConfig = properties.getProperty(Constants.J2ME_MICROEDITION_CONFIGURATION); + String j2meProfiles = properties.getProperty(Constants.J2ME_MICROEDITION_PROFILES); + String vmProfile = null; + String javaEdition = null; + Version javaVersion = null; + if (j2meConfig != null && j2meConfig.length() > 0 && j2meProfiles != null && j2meProfiles.length() > 0) { + // save the vmProfile based off of the config and profile + // use the last profile; assuming that is the highest one + String[] j2meProfileList = ManifestElement.getArrayFromList(j2meProfiles, " "); + if (j2meProfileList != null && j2meProfileList.length > 0) + vmProfile = j2meConfig + '_' + j2meProfileList[j2meProfileList.length - 1]; + } else { + // No J2ME properties; use J2SE properties + // Note that the CDC spec appears not to require VM implementations to set the + // javax.microedition properties!! So we will try to fall back to the + // java.specification.name property, but this is pretty ridiculous!! + String javaSpecVersion = properties.getProperty("java.specification.version"); + // set the profile and EE based off of the java.specification.version + // TODO We assume J2ME Foundation and J2SE here. need to support other profiles J2EE ... + if (javaSpecVersion != null) { + StringTokenizer st = new StringTokenizer(javaSpecVersion, " _-"); + javaSpecVersion = st.nextToken(); + String javaSpecName = properties.getProperty("java.specification.name"); + if ("J2ME Foundation Specification".equals(javaSpecName)) + vmProfile = "CDC-" + javaSpecVersion + "_Foundation-" + javaSpecVersion; //$NON-NLS-2$ + else { + // look for JavaSE if 1.6 or greater; otherwise look for J2SE + Version v16 = new Version("1.6"); + javaEdition = J2SE; + try { + javaVersion = new Version(javaSpecVersion); + if (v16.compareTo(javaVersion) <= 0) + javaEdition = JAVASE; + } catch (IllegalArgumentException e) { + // do nothing + } + vmProfile = javaEdition + javaSpecVersion; + } + } + } + URL url = null; + // check for the java profile property for a url + String propJavaProfile = FrameworkProperties.getProperty(Constants.OSGI_JAVA_PROFILE); + if (propJavaProfile != null) + try { + // we assume a URL + url = new URL(propJavaProfile); + } catch (MalformedURLException e1) { + // try using a relative path in the system bundle + url = findInSystemBundle(propJavaProfile); + } + if (url == null && vmProfile != null) { + // look for a profile in the system bundle based on the vm profile + String javaProfile = vmProfile + PROFILE_EXT; + url = findInSystemBundle(javaProfile); + if (url == null) + url = getNextBestProfile(javaEdition, javaVersion); + } + if (url == null) + // the profile url is still null then use the osgi min profile in OSGi by default + url = findInSystemBundle("OSGi_Minimum-1.1.profile"); + if (url != null) { + InputStream in = null; + try { + in = url.openStream(); + result.load(new BufferedInputStream(in)); + } catch (IOException e) { + // TODO consider logging ... + } finally { + if (in != null) + try { + in.close(); + } catch (IOException ee) { + // do nothing + } + } + } + // set the profile name if it does not provide one + if (result.getProperty(Constants.OSGI_JAVA_PROFILE_NAME) == null) + if (vmProfile != null) + result.put(Constants.OSGI_JAVA_PROFILE_NAME, vmProfile.replace('_', '/')); + else + // last resort; default to the absolute minimum profile name for the framework + result.put(Constants.OSGI_JAVA_PROFILE_NAME, "OSGi/Minimum-1.1"); + return result; + } + + private static URL getNextBestProfile(String javaEdition, Version javaVersion) { + if (javaVersion == null || (javaEdition != J2SE && javaEdition != JAVASE)) + return null; // we cannot automatically choose the next best profile unless this is a J2SE or JavaSE vm + URL bestProfile = findNextBestProfile(javaEdition, javaVersion); + if (bestProfile == null && javaEdition == JAVASE) + // if this is a JavaSE VM then search for a lower J2SE profile + bestProfile = findNextBestProfile(J2SE, javaVersion); + return bestProfile; + } + + private static URL findNextBestProfile(String javaEdition, Version javaVersion) { + URL result = null; + int minor = javaVersion.getMinor(); + do { + result = findInSystemBundle(javaEdition + javaVersion.getMajor() + "." + minor + PROFILE_EXT); + minor = minor - 1; + } while (result == null && minor > 0); + return result; + } + + private static URL findInSystemBundle(String entry) { + ClassLoader loader = BundleUtil.class.getClassLoader(); + return loader == null ? ClassLoader.getSystemResource(entry) : loader.getResource(entry); + } + + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/resources/META-INF/plexus/components.xml b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 0000000000..4332d3f205 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-eclipse-compiler/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,28 @@ + + + + + + org.codehaus.plexus.compiler.Compiler + tuscany-eclipse + org.apache.tuscany.sca.tools.maven.compiler.JavaCompiler + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/NOTICE new file mode 100644 index 0000000000..25bb89c9b2 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/pom.xml new file mode 100644 index 0000000000..1d50138a8d --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/pom.xml @@ -0,0 +1,108 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 2.0-M1 + ../pom.xml + + tuscany-maven-incremental-build + maven-plugin + Apache Tuscany SCA Incremental Build Generator Maven Plugin + + + + org.apache.maven + maven-plugin-api + 2.0.5 + + + + org.apache.maven + maven-project + 2.0.5 + + + + org.apache.maven + maven-settings + 2.0.5 + + + + org.apache.maven + maven-artifact + 2.0.5 + + + + org.apache.maven + maven-model + 2.0.5 + + + + org.apache.maven + maven-core + 2.0.5 + + + + org.apache.maven.shared + maven-invoker + 2.0.7 + + + + org.codehaus.plexus + plexus-compiler-api + 1.5.3 + + + + org.codehaus.plexus + plexus-compiler-manager + 1.5.3 + + + org.codehaus.plexus + plexus-compiler-javac + 1.5.3 + runtime + + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + LATEST + + incremental + + + + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java new file mode 100644 index 0000000000..3a6870732b --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-incremental-build/src/main/java/org/apache/tuscany/sca/tools/incremental/build/plugin/IncrementalBuildMojo.java @@ -0,0 +1,415 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.tools.incremental.build.plugin; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.model.Resource; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.maven.settings.Settings; +import org.apache.maven.shared.invoker.DefaultInvocationRequest; +import org.apache.maven.shared.invoker.InvocationResult; +import org.apache.maven.shared.invoker.Invoker; +import org.apache.maven.shared.invoker.MavenInvocationException; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.cli.CommandLineException; + +/** + * @version $Rev$ $Date$ + * @goal build + * @phase validate + * @requiresDependencyResolution test + * @description Incrementally build project modules that depend on modified modules. + */ +public class IncrementalBuildMojo extends AbstractMojo { + + /** + * Keep track of modified projects. + */ + private static Set modifiedProjectIDs = new HashSet(); + + /** + * The current user system settings for use in Maven. + * + * @parameter expression="${settings}" + * @required + * @readonly + */ + private Settings settings; + + /** + * Used to invoke Maven builds. + * + * @component + */ + private Invoker invoker; + + /** + * The target directory of the compiler if fork is true. + * + * @parameter expression="${project.build.directory}" + * @required + * @readonly + */ + private File buildDirectory; + + /** + * The project to create a build for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + private File outputFile; + + public void execute() throws MojoExecutionException { + String projectID = id(project); + outputFile = getOutputFile(); + + File testMarkerFile = new File(project.getBasedir().getPath() + "/.test"); + + List goals = new ArrayList(); + String type = project.getArtifact().getType(); + if ("pom".equals(type)) { + + // Always install pom modules + goals.add("install"); + + } else { + + // Check if anything has changed in the project + boolean changed = false; + boolean testChanged = false; + boolean testFailed = false; + if (new File(project.getBasedir().getPath() + "/.modified").exists()) { + getLog().info("Found .modified marker file."); + changed = true; + } else { + changed = areSourcesStale() || areResourcesStale() || isPOMStale(); + } + if (changed) { + modifiedProjectIDs.add(projectID); + } else { + testChanged = areTestSourcesStale() || areTestResourcesStale(); + } + + // Check if a project has compile dependencies on the modified projects + // and will need to be recompiled, or has runtime or test dependencies + // on the modified projects and needs to be retested + if (changed) { + goals.add("clean"); + goals.add("install"); + getLog().info("Project " + projectID + " has changed and will be recompiled."); + + } else { + for (Artifact artifact : (List)project.getCompileArtifacts()) { + String artifactID = id(artifact); + if (modifiedProjectIDs.contains(artifactID)) { + getLog().info("Project " + projectID + " depends on modified project " + artifactID + " and will be recompiled."); + goals.add("clean"); + goals.add("install"); + break; + } + } + + if (goals.isEmpty()) { + List artifacts = new ArrayList(); + artifacts.addAll(project.getRuntimeArtifacts()); + artifacts.addAll(project.getTestArtifacts()); + for (Artifact artifact : artifacts) { + String artifactID = id(artifact); + if (modifiedProjectIDs.contains(artifactID)) { + getLog().info("Project " + projectID + " depends on modified project " + artifactID + " and will be retested."); + goals.add("test"); + break; + } + } + } + } + + if (testChanged && goals.isEmpty()) { + getLog().info("Project " + projectID + " has changed and will be retested."); + goals.add("test"); + } + + if (goals.isEmpty()) { + if (testMarkerFile.exists()) { + testFailed = true; + getLog().info("Project " + projectID + " contains failed tests and will be retested."); + goals.add("test"); + } + } + } + + // Invoke Maven with the necessary goals + if (!goals.isEmpty()) { + DefaultInvocationRequest request = new DefaultInvocationRequest(); + request.setGoals(goals); + // FIXME: The maven invoker doesn't handle the directory names with spaces + // request.setLocalRepositoryDirectory(new File(localRepository.getBasedir())); + request.setInteractive(false); + request.setShowErrors(false); + request.setRecursive(false); + // request.setDebug(true); + request.setOffline(settings.isOffline()); + request.setBaseDirectory(project.getBasedir()); + request.setPomFile(project.getFile()); + + boolean success = false; + try { + try { + InvocationResult result = invoker.execute(request); + + CommandLineException cle = result.getExecutionException(); + if (cle != null) { + throw new MojoExecutionException(cle.getMessage(), cle); + } + + int ec = result.getExitCode(); + if (ec != 0) { + throw new MojoExecutionException("Maven invocation exit code: " + ec); + } + + success = true; + + + + } catch (MavenInvocationException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } finally { + + // Create or delete a .test marker file to keep track of the latest + // test result status and trigger testing again next time the build + // is run + if (!success) { + try { + if (!testMarkerFile.exists()) { + testMarkerFile.createNewFile(); + } + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } else { + if (testMarkerFile.exists()) { + testMarkerFile.delete(); + } + } + } + } else { + getLog().info("The project is up-to-date. No build is required."); + } + } + + private File getOutputFile() { + File basedir = buildDirectory; + String finalName = project.getBuild().getFinalName(); + String classifier = project.getArtifact().getClassifier(); + if (classifier == null) { + classifier = ""; + } else if (classifier.trim().length() > 0 && !classifier.startsWith("-")) { + classifier = "-" + classifier; + } + + String pkg = project.getPackaging(); + if ("maven-plugin".equals(pkg)) { + pkg = "jar"; + } + return new File(basedir, finalName + classifier + "." + pkg); + } + + /** + * Test if any of the resources are stale + * @param resources + * @param outputDirectory + * @return + * @throws MojoExecutionException + */ + private boolean areStale(List resources, String outputDirectory) throws MojoExecutionException { + + for (Resource resource: resources) { + + File resourceDirectory = new File(resource.getDirectory()); + if (!resourceDirectory.exists()) { + continue; + } + + DirectoryScanner scanner = new DirectoryScanner(); + + scanner.setBasedir(resource.getDirectory()); + if (resource.getIncludes() != null && !resource.getIncludes().isEmpty()) { + scanner.setIncludes((String[])resource.getIncludes().toArray(new String[]{})); + } else { + scanner.setIncludes(new String[]{"**/**"}); + } + if (resource.getExcludes() != null && !resource.getExcludes().isEmpty()) { + scanner.setExcludes((String[])resource.getExcludes().toArray(new String[]{})); + } + + scanner.addDefaultExcludes(); + scanner.scan(); + + List includedFiles = Arrays.asList(scanner.getIncludedFiles()); + String targetPath = resource.getTargetPath(); + for (String source: includedFiles) { + String target; + if (source.endsWith(".java")) { + target = source.substring(0, source.length() - 5) + ".class"; + } else { + target = source; + } + + String destination; + if (targetPath != null) { + destination = targetPath + "/" + target; + } else { + destination = target; + } + + File sourceFile = new File(resource.getDirectory(), source); + File destinationFile = new File(outputDirectory, destination); + + if (!destinationFile.exists()) { + getLog().info("Source file " + sourceFile + "."); + getLog().info("Target file " + destinationFile + " could not be found."); + return true; + } else { + if (sourceFile.lastModified() > destinationFile.lastModified()) { + getLog().info("Source file " + sourceFile + " has changed."); + getLog().info("Target file " + destinationFile + " is stale."); + return true; + } else if (sourceFile.lastModified() > outputFile.lastModified()) { + getLog().info("Source file " + sourceFile + " has changed."); + getLog().info("Target build output file " + outputFile + " is stale."); + return true; + } else if (outputFile.lastModified() == 0) { + getLog().info("Target build output file " + outputFile + " could not be found."); + return true; + } + } + } + } + return false; + } + + /** + * Test if the POM resource is stale. + * + * @return + */ + private boolean isPOMStale() { + File pom = project.getFile(); + if (pom.lastModified() > outputFile.lastModified()) { + getLog().info("File " + pom + " has changed."); + getLog().info("Target build output file " + pom + " is stale."); + return true; + } else if (outputFile.lastModified() == 0) { + getLog().info("Target build output file " + outputFile + " could not be found."); + return true; + } else { + return false; + } + } + + /** + * Test if the project resources are stale. + * + * @return + * @throws MojoExecutionException + */ + private boolean areResourcesStale() throws MojoExecutionException { + return areStale(project.getResources(), project.getBuild().getOutputDirectory()); + } + + /** + * Test if the project sources are stale. + * + * @return + * @throws MojoExecutionException + */ + private boolean areSourcesStale() throws MojoExecutionException { + List resources = new ArrayList(); + for (String root: (List)project.getCompileSourceRoots()) { + if (new File(root).exists()) { + Resource resource = new Resource(); + resource.setDirectory(root); + resource.addInclude("*.java"); + resources.add(resource); + } + } + return areStale(resources, project.getBuild().getOutputDirectory()); + } + + /** + * Tests if the project test resources are stale. + * + * @return + * @throws MojoExecutionException + */ + private boolean areTestResourcesStale() throws MojoExecutionException { + return areStale(project.getTestResources(), project.getBuild().getTestOutputDirectory()); + } + + /** + * Tests if the project test sources are stale. + * + * @return + * @throws MojoExecutionException + */ + private boolean areTestSourcesStale() throws MojoExecutionException { + List resources = new ArrayList(); + for (String root: (List)project.getTestCompileSourceRoots()) { + if (new File(root).exists()) { + Resource resource = new Resource(); + resource.setDirectory(root); + resources.add(resource); + } + } + return areStale(resources, project.getBuild().getTestOutputDirectory()); + } + + /** + * Returns the qualified id of a Maven artifact . + * @param p a Maven artifact + * @return a qualified id + */ + private static String id(Artifact a) { + return a.getGroupId() + ':' + a.getArtifactId(); + } + + /** + * Returns the qualified id of a Maven project. + * @param p a Maven project + * @return a qualified id + */ + private static String id(MavenProject p) { + return p.getGroupId() + ':' + p.getArtifactId(); + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/NOTICE new file mode 100644 index 0000000000..25bb89c9b2 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/pom.xml new file mode 100644 index 0000000000..a6ff3f411c --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/pom.xml @@ -0,0 +1,45 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 2.0-M1 + ../pom.xml + + tuscany-maven-java2wsdl + maven-plugin + Apache Tuscany SCA Java2WSDL Maven Plugin + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + org.apache.tuscany.sca + tuscany-java2wsdl + 2.0-M1 + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/src/main/java/org/apache/tuscany/tools/java2wsdl/plugin/Java2WSDLGeneratorMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/src/main/java/org/apache/tuscany/tools/java2wsdl/plugin/Java2WSDLGeneratorMojo.java new file mode 100644 index 0000000000..620e32a6fd --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-java2wsdl/src/main/java/org/apache/tuscany/tools/java2wsdl/plugin/Java2WSDLGeneratorMojo.java @@ -0,0 +1,153 @@ +/* + * 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. + */ +package org.apache.tuscany.tools.java2wsdl.plugin; + +import java.util.Hashtable; +import java.util.Map; + +import org.apache.axis2.description.java2wsdl.Java2WSDLConstants; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.tuscany.tools.java2wsdl.generate.Java2WSDLGeneratorFactory; +import org.apache.ws.java2wsdl.utils.Java2WSDLCommandLineOption; + +/** + * @version $Rev$ $Date$ + * @goal generate + * @phase generate-sources + * @description Generate WSDL from a given Java class / interface + */ +public class Java2WSDLGeneratorMojo extends AbstractMojo +{ + + /** + * The name of the class for which the WSDL must be generated + * @parameter + * + */ + private String sourceClassName; + + /** + * The location where the WSDLs should be generated into + * @parameter expression="${project.build.directory}\\java2wsdl-wsdl" + */ + private String targetLocation; + + /** + * The name of the WSDL file + * @parameter + */ + private String wsdlFilename; + + + /** + * Classpaths to be included + * @parameter + * + */ + String[] classpaths; + + /** + * The name of the service + * @parameter + */ + private String serviceName; + + /** + * The binding style for the service + * @parameter + */ + private String bindingStyle; + + /** + * The binding use option + * @parameter + */ + private String bindingUse; + + /** + * The soap address + * @parameter + */ + private String soapAddress; + + public void execute() throws MojoExecutionException + { + try + { + Java2WSDLGeneratorFactory.getInstance().createGenerator().generateWSDL(createOptionsMap ()); + } + catch ( Exception e ) + { + throw new MojoExecutionException("Exception in Java2WSDL Maven Plugin ", e); + } + } + + protected Map createOptionsMap() + { + Map optionsMap = new Hashtable(); + + optionsMap.put(Java2WSDLConstants.CLASSNAME_OPTION, + new Java2WSDLCommandLineOption(Java2WSDLConstants.CLASSNAME_OPTION, new String[]{sourceClassName})); + + if ( targetLocation != null ) + { + optionsMap.put(Java2WSDLConstants.OUTPUT_LOCATION_OPTION, + new Java2WSDLCommandLineOption(Java2WSDLConstants.OUTPUT_LOCATION_OPTION, new String[]{targetLocation})); + } + + if ( wsdlFilename != null ) + { + optionsMap.put(Java2WSDLConstants.OUTPUT_FILENAME_OPTION, + new Java2WSDLCommandLineOption(Java2WSDLConstants.OUTPUT_FILENAME_OPTION, new String[]{wsdlFilename})); + } + + if ( classpaths != null && classpaths.length > 0 ) + { + optionsMap.put(Java2WSDLConstants.CLASSPATH_OPTION, + new Java2WSDLCommandLineOption(Java2WSDLConstants.CLASSPATH_OPTION, classpaths)); + } + + if ( serviceName != null ) + { + optionsMap.put(Java2WSDLConstants.SERVICE_NAME_OPTION, + new Java2WSDLCommandLineOption(Java2WSDLConstants.SERVICE_NAME_OPTION, new String[]{serviceName})); + } + + if ( bindingStyle != null ) + { + optionsMap.put(Java2WSDLConstants.STYLE_OPTION, + new Java2WSDLCommandLineOption(Java2WSDLConstants.STYLE_OPTION, new String[]{bindingStyle})); + } + + if ( bindingUse != null ) + { + optionsMap.put(Java2WSDLConstants.USE_OPTION, + new Java2WSDLCommandLineOption(Java2WSDLConstants.USE_OPTION, new String[]{bindingUse})); + } + + if ( soapAddress != null ) + { + optionsMap.put(Java2WSDLConstants.LOCATION_OPTION, + new Java2WSDLCommandLineOption(Java2WSDLConstants.LOCATION_OPTION, new String[]{soapAddress})); + } + + return optionsMap; + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/NOTICE new file mode 100644 index 0000000000..51042eab05 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/pom.xml new file mode 100644 index 0000000000..17b1ed337f --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/pom.xml @@ -0,0 +1,70 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 2.0-M1 + ../pom.xml + + tuscany-maven-osgi-junit + maven-plugin + Apache Tuscany SCA OSGi JUnit Maven Plugin + + + + + org.apache.maven + maven-plugin-api + 2.0.8 + + + + org.apache.maven + maven-project + 2.0.8 + + + + org.apache.maven.surefire + surefire-booter + 2.4.3 + + + + org.apache.maven + maven-core + 2.0.8 + + + org.apache.maven + maven-toolchain + 1.0 + + + + org.apache.tuscany.sca + tuscany-node-launcher-equinox + 2.0-M1 + + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java new file mode 100644 index 0000000000..30282c908b --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java @@ -0,0 +1,239 @@ +package org.apache.tuscany.sca.maven.plugin.surefire; + +/* + * 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.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +import org.apache.maven.surefire.booter.SurefireBooterForkException; +import org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.Commandline; +import org.apache.maven.surefire.util.UrlUtils; +import org.codehaus.plexus.util.StringUtils; + +/** + * Derived from surefire-booter 2.4.3 + * Configuration for forking tests. + * + */ +@SuppressWarnings("unchecked") +public class ForkConfiguration { + public static final String FORK_ONCE = "once"; + + public static final String FORK_ALWAYS = "always"; + + public static final String FORK_NEVER = "never"; + + private String forkMode; + + private boolean useSystemClassLoader; + private boolean useManifestOnlyJar; + + private Properties systemProperties; + + private String jvmExecutable; + + private String argLine; + + private Map environmentVariables; + + private File workingDirectory; + + private boolean debug; + + private String debugLine; + + public void setForkMode(String forkMode) { + if ("pertest".equalsIgnoreCase(forkMode)) { + this.forkMode = FORK_ALWAYS; + } else if ("none".equalsIgnoreCase(forkMode)) { + this.forkMode = FORK_NEVER; + } else if (forkMode.equals(FORK_NEVER) || forkMode.equals(FORK_ONCE) || forkMode.equals(FORK_ALWAYS)) { + this.forkMode = forkMode; + } else { + throw new IllegalArgumentException("Fork mode " + forkMode + " is not a legal value"); + } + } + + public boolean isForking() { + return !FORK_NEVER.equals(forkMode); + } + + public void setUseSystemClassLoader(boolean useSystemClassLoader) { + this.useSystemClassLoader = useSystemClassLoader; + } + + public boolean isUseSystemClassLoader() { + return useSystemClassLoader; + } + + public void setSystemProperties(Properties systemProperties) { + this.systemProperties = (Properties)systemProperties.clone(); + } + + public void setJvmExecutable(String jvmExecutable) { + this.jvmExecutable = jvmExecutable; + } + + public void setArgLine(String argLine) { + this.argLine = argLine; + } + + public void setDebugLine(String debugLine) { + this.debugLine = debugLine; + } + + public void setEnvironmentVariables(Map environmentVariables) { + this.environmentVariables = new HashMap(environmentVariables); + } + + public void setWorkingDirectory(File workingDirectory) { + this.workingDirectory = workingDirectory; + } + + public String getForkMode() { + return forkMode; + } + + public Properties getSystemProperties() { + return systemProperties; + } + + /** + * @throws SurefireBooterForkException + * @deprecated use the 2-arg alternative. + */ + public Commandline createCommandLine(List classPath) throws SurefireBooterForkException { + return createCommandLine(classPath, false); + } + + public Commandline createCommandLine(List classPath, boolean useJar) throws SurefireBooterForkException { + Commandline cli = new Commandline(); + + cli.setExecutable(jvmExecutable); + + if (argLine != null) { + cli.createArg().setLine(argLine); + } + + if (environmentVariables != null) { + Iterator iter = environmentVariables.keySet().iterator(); + + while (iter.hasNext()) { + String key = (String)iter.next(); + + String value = (String)environmentVariables.get(key); + + cli.addEnvironment(key, value); + } + } + + if (debugLine != null && !"".equals(debugLine)) { + cli.createArg().setLine(debugLine); + } + + if (useJar) { + File jarFile; + try { + jarFile = createJar(classPath); + } catch (IOException e) { + throw new SurefireBooterForkException("Error creating archive file", e); + } + + cli.createArg().setValue("-jar"); + + cli.createArg().setValue(jarFile.getAbsolutePath()); + } else { + cli.createArg().setValue("-classpath"); + + cli.createArg().setValue(StringUtils.join(classPath.iterator(), File.pathSeparator)); + + cli.createArg().setValue(OSGiSurefireBooter.class.getName()); + } + + cli.setWorkingDirectory(workingDirectory.getAbsolutePath()); + + return cli; + } + + /** + * Create a jar with just a manifest containing a Main-Class entry for SurefireBooter and a Class-Path entry + * for all classpath elements. + * + * @param classPath List<String> of all classpath elements. + * @return + * @throws IOException + */ + private File createJar(List classPath) throws IOException { + File file = File.createTempFile("surefirebooter", ".jar"); + if (!debug) { + file.deleteOnExit(); + } + FileOutputStream fos = new FileOutputStream(file); + JarOutputStream jos = new JarOutputStream(fos); + jos.setLevel(JarOutputStream.STORED); + JarEntry je = new JarEntry("META-INF/MANIFEST.MF"); + jos.putNextEntry(je); + + Manifest man = new Manifest(); + + // we can't use StringUtils.join here since we need to add a '/' to + // the end of directory entries - otherwise the jvm will ignore them. + String cp = ""; + for (Iterator it = classPath.iterator(); it.hasNext();) { + String el = (String)it.next(); + // NOTE: if File points to a directory, this entry MUST end in '/'. + cp += UrlUtils.getURL(new File(el)).toExternalForm() + " "; + } + + man.getMainAttributes().putValue("Manifest-Version", "1.0"); + man.getMainAttributes().putValue("Class-Path", cp.trim()); + man.getMainAttributes().putValue("Main-Class", OSGiSurefireBooter.class.getName()); + + man.write(jos); + jos.close(); + + return file; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public boolean isDebug() { + return debug; + } + + public void setUseManifestOnlyJar(boolean useManifestOnlyJar) { + this.useManifestOnlyJar = useManifestOnlyJar; + } + + public boolean isUseManifestOnlyJar() { + return useManifestOnlyJar; + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java new file mode 100644 index 0000000000..2bc14d4241 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java @@ -0,0 +1,984 @@ +package org.apache.tuscany.sca.maven.plugin.surefire; + +/* + * 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.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.maven.surefire.Surefire; +import org.apache.maven.surefire.booter.SurefireBooterForkException; +import org.apache.maven.surefire.booter.SurefireExecutionException; +import org.apache.maven.surefire.booter.output.FileOutputConsumerProxy; +import org.apache.maven.surefire.booter.output.ForkingStreamConsumer; +import org.apache.maven.surefire.booter.output.OutputConsumer; +import org.apache.maven.surefire.booter.output.StandardOutputConsumer; +import org.apache.maven.surefire.booter.output.SupressFooterOutputConsumerProxy; +import org.apache.maven.surefire.booter.output.SupressHeaderOutputConsumerProxy; +import org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.IOUtil; +import org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.StringUtils; +import org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.Commandline; +import org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.StreamConsumer; +import org.apache.maven.surefire.testset.TestSetFailedException; +import org.apache.maven.surefire.util.NestedRuntimeException; +import org.apache.tuscany.sca.node.equinox.launcher.EquinoxHost; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/** + * Derived from surefire-booter 2.4.3 + */ +public class OSGiSurefireBooter { + private static final String TEST_SUITE_PROPERTY_PREFIX = "testSuite."; + private static final String REPORT_PROPERTY_PREFIX = "report."; + private static final String PARAMS_SUFIX = ".params"; + private static final String TYPES_SUFIX = ".types"; + + /** + * A classloader that delegates an OSGi bundle + */ + static class BundleClassLoader extends ClassLoader { + private Bundle bundle; + + public BundleClassLoader(Bundle bundle, ClassLoader parent) { + super(parent); + this.bundle = bundle; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + return bundle.loadClass(name); + } + + @Override + protected URL findResource(String name) { + return bundle.getResource(name); + } + + @Override + protected Enumeration findResources(String name) throws IOException { + return bundle.getResources(name); + } + + } + + private List reports = new ArrayList(); + + /** + * Test classpath + */ + private List classPathUrls = new ArrayList(); + + /** + * surefire provider classpath + */ + private List surefireClassPathUrls = new ArrayList(); + + /** + * surefire boot classpath + */ + private List surefireBootClassPathUrls = new ArrayList(); + + private List testSuites = new ArrayList(); + + private boolean failIfNoTests = false; + + private int forkedProcessTimeoutInSeconds = 0; + + private boolean redirectTestOutputToFile = false; + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + private ForkConfiguration forkConfiguration; + + public static final int TESTS_SUCCEEDED_EXIT_CODE = 0; + + public static final int TESTS_FAILED_EXIT_CODE = 255; + + public static final int NO_TESTS_EXIT_CODE = 254; + + private static Method assertionStatusMethod; + + /** + * @deprecated because the OSGi classloader is really isolated - no parent. + */ + private boolean childDelegation = true; + + private File reportsDirectory; + + /** + * This field is set to true if it's running from main. It's used to help decide what classloader to use. + */ + private final boolean isForked; + + /** + * Whether to enable assertions or not (can be affected by the fork arguments, and the ability to do so based on the + * JVM). + */ + private boolean enableAssertions; + + static { + try { + assertionStatusMethod = + ClassLoader.class.getMethod("setDefaultAssertionStatus", new Class[] {boolean.class}); + } catch (NoSuchMethodException e) { + assertionStatusMethod = null; + } + } + + public OSGiSurefireBooter() { + isForked = false; + } + + private OSGiSurefireBooter(boolean isForked) { + this.isForked = isForked; + } + + // ---------------------------------------------------------------------- + // Accessors + // ---------------------------------------------------------------------- + + public void addReport(String report) { + addReport(report, null); + } + + public void addReport(String report, Object[] constructorParams) { + reports.add(new Object[] {report, constructorParams}); + } + + public void addTestSuite(String suiteClassName, Object[] constructorParams) { + testSuites.add(new Object[] {suiteClassName, constructorParams}); + } + + public void addClassPathUrl(String path) { + if (!classPathUrls.contains(path)) { + classPathUrls.add(path); + } + } + + public void addSurefireClassPathUrl(String path) { + if (!surefireClassPathUrls.contains(path)) { + surefireClassPathUrls.add(path); + } + } + + public void addSurefireBootClassPathUrl(String path) { + if (!surefireBootClassPathUrls.contains(path)) { + surefireBootClassPathUrls.add(path); + } + } + + /** + * Setting this to true will cause a failure if there are no tests to run + * + * @param redirectTestOutputToFile + */ + public void setFailIfNoTests(boolean failIfNoTests) { + this.failIfNoTests = failIfNoTests; + } + + /** + * When forking, setting this to true will make the test output to be saved in a file instead of showing it on the + * standard output + * + * @param redirectTestOutputToFile + */ + public void setRedirectTestOutputToFile(boolean redirectTestOutputToFile) { + this.redirectTestOutputToFile = redirectTestOutputToFile; + } + + /** + * Set the directory where reports will be saved + * + * @param reportsDirectory the directory + */ + public void setReportsDirectory(File reportsDirectory) { + this.reportsDirectory = reportsDirectory; + } + + /** + * Get the directory where reports will be saved + */ + public File getReportsDirectory() { + return reportsDirectory; + } + + public void setForkConfiguration(ForkConfiguration forkConfiguration) { + this.forkConfiguration = forkConfiguration; + } + + public boolean isForking() { + return forkConfiguration.isForking(); + } + + public int run() throws SurefireBooterForkException, SurefireExecutionException { + int result; + + if (ForkConfiguration.FORK_NEVER.equals(forkConfiguration.getForkMode())) { + result = runSuitesInProcess(); + } else if (ForkConfiguration.FORK_ONCE.equals(forkConfiguration.getForkMode())) { + result = runSuitesForkOnce(); + } else if (ForkConfiguration.FORK_ALWAYS.equals(forkConfiguration.getForkMode())) { + result = runSuitesForkPerTestSet(); + } else { + throw new SurefireExecutionException("Unknown forkmode: " + forkConfiguration.getForkMode(), null); + } + return result; + } + + private int runSuitesInProcess(String testSet, Properties results) throws SurefireExecutionException { + if (testSuites.size() != 1) { + throw new IllegalArgumentException("Cannot only specify testSet for single test suites"); + } + + // TODO: replace with plexus + + // noinspection CatchGenericClass,OverlyBroadCatchBlock + ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader(); + start(); + try { + ClassLoader testsClassLoader = + useSystemClassLoader() ? ClassLoader.getSystemClassLoader() : createClassLoader(classPathUrls, + null, + childDelegation); + + // TODO: assertions = true shouldn't be required for this CL if we had proper separation (see TestNG) + ClassLoader surefireClassLoader = createClassLoader(surefireClassPathUrls, testsClassLoader); + + Class surefireClass = surefireClassLoader.loadClass(Surefire.class.getName()); + + Object surefire = surefireClass.newInstance(); + + Method run = + surefireClass.getMethod("run", new Class[] {List.class, Object[].class, String.class, + ClassLoader.class, ClassLoader.class, Properties.class, + Boolean.class}); + + Thread.currentThread().setContextClassLoader(testsClassLoader); + + Integer result = + (Integer)run.invoke(surefire, new Object[] {reports, testSuites.get(0), testSet, surefireClassLoader, + testsClassLoader, results, new Boolean(failIfNoTests)}); + + return result.intValue(); + } catch (InvocationTargetException e) { + throw new SurefireExecutionException(e.getTargetException().getMessage(), e.getTargetException()); + } catch (Exception e) { + throw new SurefireExecutionException("Unable to instantiate and execute Surefire", e); + } finally { + stop(); + Thread.currentThread().setContextClassLoader(oldContextClassLoader); + } + } + + private int runSuitesInProcess() throws SurefireExecutionException { + // TODO: replace with plexus + + // noinspection CatchGenericClass,OverlyBroadCatchBlock + ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader(); + start(); + + try { + // The test classloader must be constructed first to avoid issues with commons-logging until we properly + // separate the TestNG classloader + ClassLoader testsClassLoader; + String testClassPath = getTestClassPathAsString(); + System.setProperty("surefire.test.class.path", testClassPath); + if (useManifestOnlyJar()) { + // testsClassLoader = getClass().getClassLoader(); // ClassLoader.getSystemClassLoader() + testsClassLoader = createClassLoader(classPathUrls, null, childDelegation); + // SUREFIRE-459, trick the app under test into thinking its classpath was conventional (instead of a single manifest-only jar) + System.setProperty("surefire.real.class.path", System.getProperty("java.class.path")); + System.setProperty("java.class.path", testClassPath); + } else { + testsClassLoader = createClassLoader(classPathUrls, null, childDelegation); + } + + ClassLoader surefireClassLoader = createClassLoader(surefireClassPathUrls, testsClassLoader); + + Class surefireClass = surefireClassLoader.loadClass(Surefire.class.getName()); + + Object surefire = surefireClass.newInstance(); + + Method run = + surefireClass.getMethod("run", new Class[] {List.class, List.class, ClassLoader.class, + ClassLoader.class, Boolean.class}); + + Thread.currentThread().setContextClassLoader(testsClassLoader); + + Integer result = + (Integer)run.invoke(surefire, new Object[] {reports, testSuites, surefireClassLoader, testsClassLoader, + new Boolean(failIfNoTests)}); + + return result.intValue(); + } catch (InvocationTargetException e) { + throw new SurefireExecutionException(e.getTargetException().getMessage(), e.getTargetException()); + } catch (Exception e) { + throw new SurefireExecutionException("Unable to instantiate and execute Surefire", e); + } finally { + stop(); + Thread.currentThread().setContextClassLoader(oldContextClassLoader); + } + } + + private String getTestClassPathAsString() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < classPathUrls.size(); i++) { + sb.append(classPathUrls.get(i)).append(File.pathSeparatorChar); + } + return sb.toString(); + } + + private int runSuitesForkOnce() throws SurefireBooterForkException { + return forkSuites(testSuites, true, true); + } + + private int runSuitesForkPerTestSet() throws SurefireBooterForkException { + ClassLoader testsClassLoader; + ClassLoader surefireClassLoader; + try { + testsClassLoader = createClassLoader(classPathUrls, null, false); + // TODO: assertions = true shouldn't be required if we had proper separation (see TestNG) + surefireClassLoader = createClassLoader(surefireClassPathUrls, testsClassLoader, false); + } catch (MalformedURLException e) { + throw new SurefireBooterForkException("Unable to create classloader to find test suites", e); + } + + int globalResult = 0; + + boolean showHeading = true; + Properties properties = new Properties(); + for (Iterator i = testSuites.iterator(); i.hasNext();) { + Object[] testSuite = (Object[])i.next(); + + Map testSets = getTestSets(testSuite, testsClassLoader, surefireClassLoader); + + for (Iterator j = testSets.keySet().iterator(); j.hasNext();) { + Object testSet = j.next(); + boolean showFooter = !j.hasNext() && !i.hasNext(); + int result = forkSuite(testSuite, testSet, showHeading, showFooter, properties); + if (result > globalResult) { + globalResult = result; + } + showHeading = false; + } + } + + return globalResult; + } + + private Map getTestSets(Object[] testSuite, ClassLoader testsClassLoader, ClassLoader surefireClassLoader) + throws SurefireBooterForkException { + String className = (String)testSuite[0]; + + Object[] params = (Object[])testSuite[1]; + + Object suite; + try { + suite = Surefire.instantiateObject(className, params, surefireClassLoader); + } catch (TestSetFailedException e) { + throw new SurefireBooterForkException(e.getMessage(), e.getCause()); + } catch (ClassNotFoundException e) { + throw new SurefireBooterForkException("Unable to find class for test suite '" + className + "'", e); + } catch (NoSuchMethodException e) { + throw new SurefireBooterForkException("Unable to find appropriate constructor for test suite '" + className + + "': " + + e.getMessage(), e); + } + + Map testSets; + try { + Method m = suite.getClass().getMethod("locateTestSets", new Class[] {ClassLoader.class}); + + testSets = (Map)m.invoke(suite, new Object[] {testsClassLoader}); + } catch (IllegalAccessException e) { + throw new SurefireBooterForkException("Error obtaining test sets", e); + } catch (NoSuchMethodException e) { + throw new SurefireBooterForkException("Error obtaining test sets", e); + } catch (InvocationTargetException e) { + throw new SurefireBooterForkException(e.getTargetException().getMessage(), e.getTargetException()); + } + return testSets; + } + + private int forkSuites(List testSuites, boolean showHeading, boolean showFooter) throws SurefireBooterForkException { + Properties properties = new Properties(); + + setForkProperties(testSuites, properties); + + return fork(properties, showHeading, showFooter); + } + + private int forkSuite(Object[] testSuite, + Object testSet, + boolean showHeading, + boolean showFooter, + Properties properties) throws SurefireBooterForkException { + setForkProperties(Collections.singletonList(testSuite), properties); + + if (testSet instanceof String) { + properties.setProperty("testSet", (String)testSet); + } + + return fork(properties, showHeading, showFooter); + } + + private void setForkProperties(List testSuites, Properties properties) { + addPropertiesForTypeHolder(reports, properties, REPORT_PROPERTY_PREFIX); + addPropertiesForTypeHolder(testSuites, properties, TEST_SUITE_PROPERTY_PREFIX); + + for (int i = 0; i < classPathUrls.size(); i++) { + String url = (String)classPathUrls.get(i); + properties.setProperty("classPathUrl." + i, url); + } + + for (int i = 0; i < surefireClassPathUrls.size(); i++) { + String url = (String)surefireClassPathUrls.get(i); + properties.setProperty("surefireClassPathUrl." + i, url); + } + + properties.setProperty("childDelegation", String.valueOf(childDelegation)); + properties.setProperty("enableAssertions", String.valueOf(enableAssertions)); + properties.setProperty("useSystemClassLoader", String.valueOf(useSystemClassLoader())); + properties.setProperty("useManifestOnlyJar", String.valueOf(useManifestOnlyJar())); + properties.setProperty("failIfNoTests", String.valueOf(failIfNoTests)); + properties.setProperty("mainBundleName", mainBundleName); + } + + private File writePropertiesFile(String name, Properties properties) throws IOException { + File file = File.createTempFile(name, "tmp"); + if (!forkConfiguration.isDebug()) { + file.deleteOnExit(); + } + + writePropertiesFile(file, name, properties); + + return file; + } + + private void writePropertiesFile(File file, String name, Properties properties) throws IOException { + FileOutputStream out = new FileOutputStream(file); + + try { + properties.store(out, name); + } finally { + IOUtil.close(out); + } + } + + private void addPropertiesForTypeHolder(List typeHolderList, Properties properties, String propertyPrefix) { + for (int i = 0; i < typeHolderList.size(); i++) { + Object[] report = (Object[])typeHolderList.get(i); + + String className = (String)report[0]; + Object[] params = (Object[])report[1]; + + properties.setProperty(propertyPrefix + i, className); + + if (params != null) { + String paramProperty = convert(params[0]); + String typeProperty = params[0].getClass().getName(); + for (int j = 1; j < params.length; j++) { + paramProperty += "|"; + typeProperty += "|"; + if (params[j] != null) { + paramProperty += convert(params[j]); + typeProperty += params[j].getClass().getName(); + } + } + properties.setProperty(propertyPrefix + i + PARAMS_SUFIX, paramProperty); + properties.setProperty(propertyPrefix + i + TYPES_SUFIX, typeProperty); + } + } + } + + private static String convert(Object param) { + if (param instanceof File[]) { + File[] files = (File[])param; + return "[" + StringUtils.join(files, ",") + "]"; + } else if (param instanceof Properties) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + ((Properties)param).store(baos, ""); + return new String(baos.toByteArray(), "8859_1"); + } catch (Exception e) { + throw new RuntimeException("bug in property conversion", e); + } + } else { + return param.toString(); + } + } + + private final boolean useSystemClassLoader() { + return forkConfiguration.isUseSystemClassLoader() && (isForked || forkConfiguration.isForking()); + } + + private final boolean useManifestOnlyJar() { + return forkConfiguration.isUseSystemClassLoader() && forkConfiguration.isUseManifestOnlyJar(); + } + + private int fork(Properties properties, boolean showHeading, boolean showFooter) throws SurefireBooterForkException { + File surefireProperties; + File systemProperties = null; + try { + surefireProperties = writePropertiesFile("surefire", properties); + if (forkConfiguration.getSystemProperties() != null) { + systemProperties = writePropertiesFile("surefire", forkConfiguration.getSystemProperties()); + } + } catch (IOException e) { + throw new SurefireBooterForkException("Error creating properties files for forking", e); + } + + /* + System.out.println("cp: " + classPathUrls); + System.out.println("scp: " + surefireClassPathUrls); + System.out.println("sbcp: " + surefireBootClassPathUrls); + */ + + List bootClasspath = new ArrayList(surefireBootClassPathUrls.size() + classPathUrls.size()); + + bootClasspath.addAll(surefireBootClassPathUrls); + + if (useSystemClassLoader()) { + bootClasspath.addAll(classPathUrls); + } + + Commandline cli = + forkConfiguration.createCommandLine(bootClasspath, useManifestOnlyJar()); + + cli.createArg().setFile(surefireProperties); + + if (systemProperties != null) { + cli.createArg().setFile(systemProperties); + } + + ForkingStreamConsumer out = getForkingStreamConsumer(showHeading, showFooter, redirectTestOutputToFile); + + StreamConsumer err; + + if (redirectTestOutputToFile) { + err = out; + } else { + err = getForkingStreamConsumer(showHeading, showFooter, redirectTestOutputToFile); + } + + if (forkConfiguration.isDebug()) { + System.out.println("Forking command line: " + cli); + } + + int returnCode; + + try { + returnCode = + org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.CommandLineUtils + .executeCommandLine(cli, out, err, forkedProcessTimeoutInSeconds); + } catch (org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.CommandLineException e) { + throw new SurefireBooterForkException("Error while executing forked tests.", e); + } + + if (redirectTestOutputToFile) { + // ensure the FileOutputConsumerProxy flushes/closes the output file + try { + out.getOutputConsumer().testSetCompleted(); + } catch (Exception e) { + // the FileOutputConsumerProxy might throw an IllegalStateException but that's not of interest now + } + } + + if (surefireProperties != null && surefireProperties.exists()) { + FileInputStream inStream = null; + try { + inStream = new FileInputStream(surefireProperties); + + properties.load(inStream); + } catch (FileNotFoundException e) { + throw new SurefireBooterForkException("Unable to reload properties file from forked process", e); + } catch (IOException e) { + throw new SurefireBooterForkException("Unable to reload properties file from forked process", e); + } finally { + IOUtil.close(inStream); + } + } + + return returnCode; + } + + private ClassLoader createClassLoader(List classPathUrls, ClassLoader parent) throws MalformedURLException { + return createClassLoader(classPathUrls, parent, false); + } + + private ClassLoader createClassLoader(List classPathUrls, ClassLoader parent, boolean childDelegation) + throws MalformedURLException { + Set urls = new HashSet(); + + for (Iterator i = classPathUrls.iterator(); i.hasNext();) { + String url = (String)i.next(); + + if (url != null) { + File f = new File(url); + urls.add(f.toURI().toURL()); + } + } + return bundleClassLoader; + } + + private static List processStringList(String stringList) { + String sl = stringList; + + if (sl.startsWith("[") && sl.endsWith("]")) { + sl = sl.substring(1, sl.length() - 1); + } + + List list = new ArrayList(); + + String[] stringArray = StringUtils.split(sl, ","); + + for (int i = 0; i < stringArray.length; i++) { + list.add(stringArray[i].trim()); + } + return list; + } + + private static Properties loadProperties(File file) throws IOException { + Properties p = new Properties(); + + if (file != null && file.exists()) { + FileInputStream inStream = new FileInputStream(file); + try { + p.load(inStream); + } finally { + IOUtil.close(inStream); + } + } + + return p; + } + + private static void setSystemProperties(File file) throws IOException { + Properties p = loadProperties(file); + + for (Iterator i = p.keySet().iterator(); i.hasNext();) { + String key = (String)i.next(); + + System.setProperty(key, p.getProperty(key)); + } + } + + private static Object[] constructParamObjects(String paramProperty, String typeProperty) { + Object[] paramObjects = null; + if (paramProperty != null) { + // bit of a glitch that it need sto be done twice to do an odd number of vertical bars (eg |||, |||||). + String[] params = + StringUtils.split(StringUtils.replace(StringUtils.replace(paramProperty, "||", "| |"), "||", "| |"), + "|"); + String[] types = + StringUtils + .split(StringUtils.replace(StringUtils.replace(typeProperty, "||", "| |"), "||", "| |"), "|"); + + paramObjects = new Object[params.length]; + + for (int i = 0; i < types.length; i++) { + if (types[i].trim().length() == 0) { + params[i] = null; + } else if (types[i].equals(String.class.getName())) { + paramObjects[i] = params[i]; + } else if (types[i].equals(File.class.getName())) { + paramObjects[i] = new File(params[i]); + } else if (types[i].equals(File[].class.getName())) { + List stringList = processStringList(params[i]); + File[] fileList = new File[stringList.size()]; + for (int j = 0; j < stringList.size(); j++) { + fileList[j] = new File((String)stringList.get(j)); + } + paramObjects[i] = fileList; + } else if (types[i].equals(ArrayList.class.getName())) { + paramObjects[i] = processStringList(params[i]); + } else if (types[i].equals(Boolean.class.getName())) { + paramObjects[i] = Boolean.valueOf(params[i]); + } else if (types[i].equals(Integer.class.getName())) { + paramObjects[i] = Integer.valueOf(params[i]); + } else if (types[i].equals(Properties.class.getName())) { + final Properties result = new Properties(); + final String value = params[i]; + try { + ByteArrayInputStream bais = new ByteArrayInputStream(value.getBytes("8859_1")); + result.load(bais); + } catch (Exception e) { + throw new RuntimeException("bug in property conversion", e); + } + paramObjects[i] = result; + } else { + // TODO: could attempt to construct with a String constructor if needed + throw new IllegalArgumentException("Unknown parameter type: " + types[i]); + } + } + } + return paramObjects; + } + + /** + * This method is invoked when Surefire is forked - this method parses and organizes the arguments passed to it and + * then calls the Surefire class' run method.

The system exit code will be 1 if an exception is thrown. + * + * @param args + */ + public static void main(String[] args) throws Throwable { + // noinspection CatchGenericClass,OverlyBroadCatchBlock + try { + if (args.length > 1) { + setSystemProperties(new File(args[1])); + } + + File surefirePropertiesFile = new File(args[0]); + Properties p = loadProperties(surefirePropertiesFile); + + SortedMap classPathUrls = new TreeMap(); + + SortedMap surefireClassPathUrls = new TreeMap(); + + OSGiSurefireBooter surefireBooter = new OSGiSurefireBooter(true); + + ForkConfiguration forkConfiguration = new ForkConfiguration(); + forkConfiguration.setForkMode("never"); + surefireBooter.setForkConfiguration(forkConfiguration); + + for (Enumeration e = p.propertyNames(); e.hasMoreElements();) { + String name = (String)e.nextElement(); + + if (name.startsWith(REPORT_PROPERTY_PREFIX) && !name.endsWith(PARAMS_SUFIX) + && !name.endsWith(TYPES_SUFIX)) { + String className = p.getProperty(name); + + String params = p.getProperty(name + PARAMS_SUFIX); + String types = p.getProperty(name + TYPES_SUFIX); + surefireBooter.addReport(className, constructParamObjects(params, types)); + } else if (name.startsWith(TEST_SUITE_PROPERTY_PREFIX) && !name.endsWith(PARAMS_SUFIX) + && !name.endsWith(TYPES_SUFIX)) { + String className = p.getProperty(name); + + String params = p.getProperty(name + PARAMS_SUFIX); + String types = p.getProperty(name + TYPES_SUFIX); + surefireBooter.addTestSuite(className, constructParamObjects(params, types)); + } else if (name.startsWith("classPathUrl.")) { + classPathUrls.put(Integer.valueOf(name.substring(name.indexOf('.') + 1)), p.getProperty(name)); + } else if (name.startsWith("surefireClassPathUrl.")) { + surefireClassPathUrls.put(Integer.valueOf(name.substring(name.indexOf('.') + 1)), p + .getProperty(name)); + } else if (name.startsWith("surefireBootClassPathUrl.")) { + surefireBooter.addSurefireBootClassPathUrl(p.getProperty(name)); + } else if ("childDelegation".equals(name)) { + surefireBooter.childDelegation = Boolean.valueOf(p.getProperty("childDelegation")).booleanValue(); + } else if ("enableAssertions".equals(name)) { + surefireBooter.enableAssertions = Boolean.valueOf(p.getProperty("enableAssertions")).booleanValue(); + } else if ("useSystemClassLoader".equals(name)) { + surefireBooter.forkConfiguration.setUseSystemClassLoader(Boolean.valueOf(p + .getProperty("useSystemClassLoader")).booleanValue()); + } else if ("useManifestOnlyJar".equals(name)) { + surefireBooter.forkConfiguration.setUseManifestOnlyJar(Boolean.valueOf(p + .getProperty("useManifestOnlyJar")).booleanValue()); + } else if ("failIfNoTests".equals(name)) { + surefireBooter.setFailIfNoTests(Boolean.valueOf(p.getProperty("failIfNoTests")).booleanValue()); + } else if ("mainBundleName".equals(name)) { + surefireBooter.setMainBundleName(p.getProperty("mainBundleName")); + } + } + + for (Iterator cpi = classPathUrls.keySet().iterator(); cpi.hasNext();) { + String url = (String)classPathUrls.get(cpi.next()); + surefireBooter.addClassPathUrl(url); + } + + for (Iterator scpi = surefireClassPathUrls.keySet().iterator(); scpi.hasNext();) { + String url = (String)surefireClassPathUrls.get(scpi.next()); + surefireBooter.addSurefireClassPathUrl(url); + } + + String testSet = p.getProperty("testSet"); + int result; + if (testSet != null) { + result = surefireBooter.runSuitesInProcess(testSet, p); + } else { + result = surefireBooter.runSuitesInProcess(); + } + + surefireBooter.writePropertiesFile(surefirePropertiesFile, "surefire", p); + + // noinspection CallToSystemExit + System.exit(result); + } catch (Throwable t) { + // Just throwing does getMessage() and a local trace - we want to call printStackTrace for a full trace + // noinspection UseOfSystemOutOrSystemErr + t.printStackTrace(System.err); + // noinspection ProhibitedExceptionThrown,CallToSystemExit + System.exit(1); + } + } + + public void setChildDelegation(boolean childDelegation) { + this.childDelegation = childDelegation; + } + + private ForkingStreamConsumer getForkingStreamConsumer(boolean showHeading, + boolean showFooter, + boolean redirectTestOutputToFile) { + OutputConsumer outputConsumer = new StandardOutputConsumer(); + + if (redirectTestOutputToFile) { + outputConsumer = new FileOutputConsumerProxy(outputConsumer, getReportsDirectory()); + } + + if (!showHeading) { + outputConsumer = new SupressHeaderOutputConsumerProxy(outputConsumer); + } + if (!showFooter) { + outputConsumer = new SupressFooterOutputConsumerProxy(outputConsumer); + } + + return new ForkingStreamConsumer(outputConsumer); + } + + public void setEnableAssertions(boolean enableAssertions) { + this.enableAssertions = enableAssertions; + } + + public void setForkedProcessTimeoutInSeconds(int forkedProcessTimeoutInSeconds) { + this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds; + } + + private String mainBundleName; + + public void setMainBundleName(String mainBundleName) { + this.mainBundleName = mainBundleName; + } + + private EquinoxHost host; + private BundleClassLoader bundleClassLoader; + + public EquinoxHost start() { + Set urls = new HashSet(); + + // Merge the two classpaths so that all of them will be OSGi-enabled + Set cps = new HashSet(classPathUrls); + cps.addAll(surefireClassPathUrls); + + for (String url: cps) { + if (url != null) { + File f = new File(url); + try { + urls.add(f.toURI().toURL()); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + } + + host = new EquinoxHost(urls); + BundleContext context = host.start(); + Bundle mainBundle = null; + for (Bundle bundle : context.getBundles()) { + // Fragement bundle cannot be used to load class, use the main bundle + if (mainBundleName.equals(bundle.getSymbolicName())) { + mainBundle = bundle; + break; + } + } + + bundleClassLoader = new BundleClassLoader(mainBundle, null); + if (assertionStatusMethod != null) { + try { + Object[] args = new Object[] {enableAssertions ? Boolean.TRUE : Boolean.FALSE}; + assertionStatusMethod.invoke(bundleClassLoader, args); + } catch (IllegalAccessException e) { + throw new NestedRuntimeException("Unable to access the assertion enablement method", e); + } catch (InvocationTargetException e) { + throw new NestedRuntimeException("Unable to invoke the assertion enablement method", e); + } + } + + return host; + } + + public void stop() { + if (host != null) { + host.stop(); + host = null; + bundleClassLoader = null; + } + } + + /** + * Returns a string representation of the given bundle. + * + * @param b + * @param verbose + * @return + */ + static String string(Bundle bundle, boolean verbose) { + StringBuffer sb = new StringBuffer(); + sb.append(bundle.getBundleId()).append(" ").append(bundle.getSymbolicName()); + int s = bundle.getState(); + if ((s & Bundle.UNINSTALLED) != 0) { + sb.append(" UNINSTALLED"); + } + if ((s & Bundle.INSTALLED) != 0) { + sb.append(" INSTALLED"); + } + if ((s & Bundle.RESOLVED) != 0) { + sb.append(" RESOLVED"); + } + if ((s & Bundle.STARTING) != 0) { + sb.append(" STARTING"); + } + if ((s & Bundle.STOPPING) != 0) { + sb.append(" STOPPING"); + } + if ((s & Bundle.ACTIVE) != 0) { + sb.append(" ACTIVE"); + } + + if (verbose) { + sb.append(" ").append(bundle.getLocation()); + sb.append(" ").append(bundle.getHeaders()); + } + return sb.toString(); + } + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefirePlugin.java b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefirePlugin.java new file mode 100644 index 0000000000..89cfdc38b2 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefirePlugin.java @@ -0,0 +1,1306 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.maven.plugin.surefire; + +import static org.osgi.framework.Constants.BUNDLE_MANIFESTVERSION; +import static org.osgi.framework.Constants.BUNDLE_NAME; +import static org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME; +import static org.osgi.framework.Constants.BUNDLE_VERSION; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.ArtifactUtils; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.artifact.resolver.filter.ArtifactFilter; +import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.maven.surefire.booter.SurefireBooterForkException; +import org.apache.maven.surefire.booter.SurefireExecutionException; +import org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.StringUtils; +import org.apache.maven.surefire.report.BriefConsoleReporter; +import org.apache.maven.surefire.report.BriefFileReporter; +import org.apache.maven.surefire.report.ConsoleReporter; +import org.apache.maven.surefire.report.DetailedConsoleReporter; +import org.apache.maven.surefire.report.FileReporter; +import org.apache.maven.surefire.report.ForkingConsoleReporter; +import org.apache.maven.surefire.report.XMLReporter; +import org.apache.maven.toolchain.Toolchain; +import org.apache.maven.toolchain.ToolchainManager; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.osgi.framework.Constants; +import org.osgi.framework.Version; + +/** + * Derived from maven-surefire-plugin 2.4.3 + * Run tests using Surefire. + * + * @requiresDependencyResolution test + * @goal test + * @phase test + */ +public class OSGiSurefirePlugin extends AbstractMojo { + + /** + * Set this to 'true' to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite + * convenient on occasion. + * + * @parameter expression="${skipTests}" + * @since 2.4 + */ + protected boolean skipTests; + + /** + * DEPRECATED This old parameter is just like skipTests, but bound to the old property maven.test.skip.exec. + * Use -DskipTests instead; it's shorter. + * + * @deprecated + * @parameter expression="${maven.test.skip.exec}" + * @since 2.3 + */ + protected boolean skipExec; + + /** + * Set this to 'true' to bypass unit tests entirely. Its use is NOT RECOMMENDED, especially if you + * enable it using the "maven.test.skip" property, because maven.test.skip disables both running the + * tests and compiling the tests. Consider using the skipTests parameter instead. + * + * @parameter expression="${maven.test.skip}" + */ + protected boolean skip; + + /** + * Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on + * occasion. + * + * @parameter expression="${maven.test.failure.ignore}" + */ + protected boolean testFailureIgnore; + + /** + * The base directory of the project being tested. This can be obtained in your unit test by + * System.getProperty("basedir"). + * + * @parameter expression="${basedir}" + * @required + */ + protected File basedir; + + /** + * The directory containing generated test classes of the project being tested. + * + * @parameter expression="${project.build.testOutputDirectory}" + * @required + */ + protected File testClassesDirectory; + + /** + * The directory containing generated classes of the project being tested. + * + * @parameter expression="${project.build.outputDirectory}" + * @required + */ + protected File classesDirectory; + + /** + * The Maven Project Object + * + * @parameter expression="${project}" + * @required + * @readonly + */ + protected MavenProject project; + + /** + * The classpath elements of the project being tested. + * + * @parameter expression="${project.testClasspathElements}" + * @required + * @readonly + */ + protected List classpathElements; + + /** + * Additional elements to be appended to the classpath. + * + * @parameter + * @since 2.4 + */ + protected List additionalClasspathElements; + + /** + * Base directory where all reports are written to. + * + * @parameter expression="${project.build.directory}/surefire-osgi-reports" + */ + protected File reportsDirectory; + + /** + * The test source directory containing test class sources. + * + * @parameter expression="${project.build.testSourceDirectory}" + * @required + * @since 2.2 + */ + protected File testSourceDirectory; + + /** + * Specify this parameter to run individual tests by file name, overriding the includes/excludes + * parameters. Each pattern you specify here will be used to create an + * include pattern formatted like **/${test}.java, so you can just type "-Dtest=MyTest" + * to run a single test called "foo/MyTest.java". This parameter will override the TestNG suiteXmlFiles + * parameter. + * + * @parameter expression="${test}" + */ + protected String test; + + /** + * List of patterns (separated by commas) used to specify the tests that should be included in testing. When not + * specified and when the test parameter is not specified, the default includes will be + * **/Test*.java **/*Test.java **/*TestCase.java. This parameter is ignored if + * TestNG suiteXmlFiles are specified. + * + * @parameter + */ + protected List includes; + + /** + * List of patterns (separated by commas) used to specify the tests that should be excluded in testing. When not + * specified and when the test parameter is not specified, the default excludes will be + * **/*$* (which excludes all inner classes). This parameter is ignored if + * TestNG suiteXmlFiles are specified. + * + * @parameter + */ + protected List excludes; + + /** + * ArtifactRepository of the localRepository. To obtain the directory of localRepository in unit tests use + * System.setProperty( "localRepository"). + * + * @parameter expression="${localRepository}" + * @required + * @readonly + */ + protected ArtifactRepository localRepository; + + /** + * List of System properties to pass to the JUnit tests. + * + * @parameter + */ + protected Properties systemProperties; + + /** + * List of properties for configuring all TestNG related configurations. This is the new + * preferred method of configuring TestNG. + * + * @parameter + * @since 2.4 + */ + protected Properties properties; + + /** + * Map of of plugin artifacts. + * + * @parameter expression="${plugin.artifactMap}" + * @required + * @readonly + */ + protected Map pluginArtifactMap; + + /** + * @parameter expression="${plugin.groupId}" + * @required + * @readonly + */ + protected String pluginGroupId; + /** + * @parameter expression="${plugin.artifactId}" + * @required + * @readonly + */ + protected String pluginArtifactId; + /** + * @parameter expression="${plugin.version}" + * @required + * @readonly + */ + protected String pluginVersion; + + /** + * Map of of project artifacts. + * + * @parameter expression="${project.artifactMap}" + * @required + * @readonly + */ + protected Map projectArtifactMap; + + /** + * Option to print summary of test suites or just print the test cases that has errors. + * + * @parameter expression="${surefire.printSummary}" default-value="true" + */ + protected boolean printSummary; + + /** + * Selects the formatting for the test report to be generated. Can be set as brief or plain. + * + * @parameter expression="${surefire.reportFormat}" default-value="brief" + */ + protected String reportFormat; + + /** + * Option to generate a file test report or just output the test report to the console. + * + * @parameter expression="${surefire.useFile}" default-value="true" + */ + protected boolean useFile; + + /** + * When forking, set this to true to redirect the unit test standard output to a file (found in + * reportsDirectory/testName-output.txt). + * + * @parameter expression="${maven.test.redirectTestOutputToFile}" default-value="false" + * @since 2.3 + */ + protected boolean redirectTestOutputToFile; + + /** + * Set this to "true" to cause a failure if there are no tests to run. Defaults to false. + * + * @parameter expression="${failIfNoTests}" + * @since 2.4 + */ + protected Boolean failIfNoTests; + + /** + * Option to specify the forking mode. Can be "never", "once" or "always". "none" and "pertest" are also accepted + * for backwards compatibility. + * + * @parameter expression="${forkMode}" default-value="once" + * @since 2.1 + */ + protected String forkMode; + + /** + * Option to specify the jvm (or path to the java executable) to use with the forking options. For the default, the + * jvm will be the same as the one used to run Maven. + * + * @parameter expression="${jvm}" + * @since 2.1 + */ + protected String jvm; + + /** + * Arbitrary JVM options to set on the command line. + * + * @parameter expression="${argLine}" + * @since 2.1 + */ + protected String argLine; + + /** + * Attach a debugger to the forked JVM. If set to "true", the process will suspend and + * wait for a debugger to attach on port 5005. If set to some other string, that + * string will be appended to the argLine, allowing you to configure arbitrary + * debuggability options (without overwriting the other options specified in the argLine). + * + * @parameter expression="${maven.surefire.debug}" + * @since 2.4 + */ + protected String debugForkedProcess; + + /** + * Kill the forked test process after a certain number of seconds. If set to 0, + * wait forever for the process, never timing out. + * + * @parameter expression="${surefire.timeout}" + * @since 2.4 + */ + protected int forkedProcessTimeoutInSeconds; + + /** + * Additional environments to set on the command line. + * + * @parameter + * @since 2.1.3 + */ + protected Map environmentVariables = new HashMap(); + + /** + * Command line working directory. + * + * @parameter expression="${basedir}" + * @since 2.1.3 + */ + protected File workingDirectory; + + /** + * When false it makes tests run using the standard classloader delegation instead of the default Maven isolated + * classloader. Only used when forking (forkMode is not "none").
Setting it to false helps with some problems + * caused by conflicts between xml parsers in the classpath and the Java 5 provider parser. + * + * @parameter expression="${childDelegation}" default-value="false" + * @since 2.1 + */ + protected boolean childDelegation; + + /** + * (TestNG only) Groups for this test. Only classes/methods/etc decorated with one of the groups specified here will be included + * in test run, if specified. This parameter is overridden if suiteXmlFiles are specified. + * + * @parameter expression="${groups}" + * @since 2.2 + */ + protected String groups; + + /** + * (TestNG only) Excluded groups. Any methods/classes/etc with one of the groups specified in this list will specifically not be + * run. This parameter is overridden if suiteXmlFiles are specified. + * + * @parameter expression="${excludedGroups}" + * @since 2.2 + */ + protected String excludedGroups; + + /** + * (TestNG only) List of TestNG suite xml file locations, seperated by commas. Note that suiteXmlFiles is incompatible + * with several other parameters on this plugin, like includes/excludes. This parameter is ignored if + * the "test" parameter is specified (allowing you to run a single test instead of an entire suite). + * + * @parameter + * @since 2.2 + */ + protected File[] suiteXmlFiles; + + /** + * Allows you to specify the name of the JUnit artifact. If not set, junit:junit will be used. + * + * @parameter expression="${junitArtifactName}" default-value="junit:junit" + * @since 2.3.1 + */ + protected String junitArtifactName; + + /** + * Allows you to specify the name of the TestNG artifact. If not set, org.testng:testng will be used. + * + * @parameter expression="${testNGArtifactName}" default-value="org.testng:testng" + * @since 2.3.1 + */ + protected String testNGArtifactName; + + /** + * (TestNG only) The attribute thread-count allows you to specify how many threads should be allocated for this execution. Only + * makes sense to use in conjunction with parallel. + * + * @parameter expression="${threadCount}" + * @since 2.2 + */ + protected int threadCount; + + /** + * (TestNG only) When you use the parallel attribute, TestNG will try to run all your test methods in separate threads, except for + * methods that depend on each other, which will be run in the same thread in order to respect their order of + * execution. + * + * @parameter expression="${parallel}" + * @todo test how this works with forking, and console/file output parallelism + * @since 2.2 + */ + protected String parallel; + + /** + * Whether to trim the stack trace in the reports to just the lines within the test, or show the full trace. + * + * @parameter expression="${trimStackTrace}" default-value="true" + * @since 2.2 + */ + protected boolean trimStackTrace; + + /** + * Resolves the artifacts needed. + * + * @component + */ + protected ArtifactResolver artifactResolver; + + /** + * Creates the artifact + * + * @component + */ + protected ArtifactFactory artifactFactory; + + /** + * The plugin remote repositories declared in the pom. + * + * @parameter expression="${project.pluginArtifactRepositories}" + * @since 2.2 + */ + protected List remoteRepositories; + + /** + * For retrieval of artifact's metadata. + * + * @component + */ + protected ArtifactMetadataSource metadataSource; + + protected static final String BRIEF_REPORT_FORMAT = "brief"; + + protected static final String PLAIN_REPORT_FORMAT = "plain"; + + protected Properties originalSystemProperties; + + /** + * Flag to disable the generation of report files in xml format. + * + * @parameter expression="${disableXmlReport}" default-value="false" + * @since 2.2 + */ + protected boolean disableXmlReport; + + /** + * Option to pass dependencies to the system's classloader instead of using an isolated class loader when forking. + * Prevents problems with JDKs which implement the service provider lookup mechanism by using the system's + * classloader. Default value is "true". + * + * @parameter expression="${surefire.useSystemClassLoader}" + * @since 2.3 + */ + protected Boolean useSystemClassLoader; + + /** + * By default, Surefire forks your tests using a manifest-only jar; set this parameter + * to "false" to force it to launch your tests with a plain old Java classpath. + * (See http://maven.apache.org/plugins/maven-surefire-plugin/examples/class-loading.html + * for a more detailed explanation of manifest-only jars and their benefits.) + * + * Default value is "true". Beware, setting this to "false" may cause your tests to + * fail on Windows if your classpath is too long. + * + * @parameter expression="${surefire.useManifestOnlyJar}" default-value="true" + * @since 2.4.3 + */ + protected boolean useManifestOnlyJar; + + /** + * By default, Surefire enables JVM assertions for the execution of your test cases. To disable the assertions, set + * this flag to false. + * + * @parameter expression="${enableAssertions}" default-value="true" + * @since 2.3.1 + */ + protected boolean enableAssertions; + + /** + * The current build session instance. + * + * @parameter expression="${session}" + * @required + * @readonly + */ + protected MavenSession session; + + public void execute() throws MojoExecutionException, MojoFailureException { + if (project.getPackaging().equals("pom")) { + return; + } + + if (verifyParameters()) { + OSGiSurefireBooter surefireBooter = constructSurefireBooter(); + + Log log = getLog(); + Set jarFiles = new HashSet(); + + /* + for (Object o : project.getArtifacts()) { + Artifact a = (Artifact)o; + if ("pom".equals(a.getType())) { + // Skip pom projects + continue; + } + try { + if (log.isDebugEnabled()) { + log.debug("Adding: " + a); + } + jarFiles.add(a.getFile().toURI().toURL()); + } catch (MalformedURLException e) { + getLog().error(e); + } + } + */ + + /* + * Add org.apache.tuscany.sca:tuscany-extensibility-osgi module + */ + String aid = "tuscany-extensibility-equinox"; + Artifact ext = getArtifact("org.apache.tuscany.sca", aid); + if (log.isDebugEnabled()) { + log.debug("Adding: " + ext); + } + jarFiles.add(ext.getFile().getAbsolutePath()); + + + String name = project.getBuild().getFinalName(); + String mainBundleName = null; + File mainJar = new File(project.getBuild().getDirectory(), name + "-osgi.jar"); + File testJar = new File(project.getBuild().getDirectory(), name + "-osgi-tests.jar"); + try { + Manifest manifest = createMainBundle(); + mainBundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + int sc = mainBundleName.indexOf(';'); + if (sc != -1) { + mainBundleName = mainBundleName.substring(0, sc); + } + generateJar(classesDirectory, mainJar, manifest); + Manifest testManifest = createTestFragment(manifest); + generateJar(testClassesDirectory, testJar, testManifest); + jarFiles.add(mainJar.getAbsolutePath()); + jarFiles.add(testJar.getAbsolutePath()); + } catch (IOException e) { + getLog().error(e); + } + + if (log.isDebugEnabled()) { + log.debug("Main bundle: " + mainBundleName); + } + surefireBooter.setMainBundleName(mainBundleName); + for (String url : jarFiles) { + surefireBooter.addClassPathUrl(url); + } + + getLog().info("Surefire report directory: " + reportsDirectory); + + int result; + try { + result = surefireBooter.run(); + } catch (SurefireBooterForkException e) { + throw new MojoExecutionException(e.getMessage(), e); + } catch (SurefireExecutionException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + if (originalSystemProperties != null && !surefireBooter.isForking()) { + // restore system properties, only makes sense when not forking.. + System.setProperties(originalSystemProperties); + } + + if (result == 0) + return; + + String msg; + + if (result == OSGiSurefireBooter.NO_TESTS_EXIT_CODE) { + if ((failIfNoTests == null) || !failIfNoTests.booleanValue()) + return; + // TODO: i18n + throw new MojoFailureException( + "No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)"); + } else { + // TODO: i18n + msg = + "There are test failures.\n\nPlease refer to " + reportsDirectory + + " for the individual test results."; + + } + + if (testFailureIgnore) { + getLog().error(msg); + } else { + throw new MojoFailureException(msg); + } + } + } + + protected boolean verifyParameters() throws MojoFailureException { + if (skip || skipTests || skipExec) { + getLog().info("Tests are skipped."); + return false; + } + + if (!testClassesDirectory.exists()) { + if (failIfNoTests != null && failIfNoTests.booleanValue()) { + throw new MojoFailureException("No tests to run!"); + } + getLog().info("No tests to run."); + return false; + } + + if (useSystemClassLoader != null && ForkConfiguration.FORK_NEVER.equals(forkMode)) { + getLog().warn("useSystemClassloader setting has no effect when not forking"); + } + + return true; + } + + /** + * Converts old TestNG configuration parameters over to new properties based configuration + * method. (if any are defined the old way) + */ + private void convertTestNGParameters() { + if (properties == null) { + properties = new Properties(); + } + + if (this.parallel != null) { + properties.setProperty("parallel", this.parallel); + } + if (this.excludedGroups != null) { + properties.setProperty("excludegroups", this.excludedGroups); + } + if (this.groups != null) { + properties.setProperty("groups", this.groups); + } + + if (this.threadCount > 0) { + properties.setProperty("threadcount", new Integer(this.threadCount).toString()); + } + } + + private OSGiSurefireBooter constructSurefireBooter() throws MojoExecutionException, MojoFailureException { + OSGiSurefireBooter surefireBooter = new OSGiSurefireBooter(); + + // Build up the surefire boot classpath + // * org.apache.tuscany.sca:tuscany-maven-surefire-osgi-plugin (non-transitive + // to exclude maven dependencies + // * org.apache.tuscany.sca:tuscany-node-launcher-equinox (transitive) + // * org.apache.maven.surefire:surefire-booter (transitive) + // Get the artifact for the OSGi surefire plugin + Artifact osgiArtifact = + artifactFactory.createArtifact(pluginGroupId, + pluginArtifactId, + pluginVersion, + Artifact.SCOPE_TEST, + "maven-plugin"); + try { + artifactResolver.resolve(osgiArtifact, remoteRepositories, localRepository); + surefireBooter.addSurefireBootClassPathUrl(osgiArtifact.getFile().getAbsolutePath()); + } catch (Exception e) { + throw new MojoExecutionException("Unable to resolve " + osgiArtifact); + } + + Artifact launcher = (Artifact) pluginArtifactMap.get("org.apache.tuscany.sca:tuscany-node-launcher-equinox"); + + // Look up the surefire-booter + Artifact surefireArtifact = (Artifact)pluginArtifactMap.get("org.apache.maven.surefire:surefire-booter"); + if (surefireArtifact == null) { + throw new MojoExecutionException("Unable to locate surefire-booter in the list of plugin artifacts"); + } + + surefireArtifact.isSnapshot(); // TODO: this is ridiculous, but it fixes getBaseVersion to be -SNAPSHOT if + // needed + + Artifact junitArtifact; + Artifact testNgArtifact; + try { + addArtifact(surefireBooter, surefireArtifact); + addArtifact(surefireBooter, launcher); + + junitArtifact = (Artifact)projectArtifactMap.get(junitArtifactName); + // SUREFIRE-378, junit can have an alternate artifact name + if (junitArtifact == null && "junit:junit".equals(junitArtifactName)) { + junitArtifact = (Artifact)projectArtifactMap.get("junit:junit-dep"); + } + + // TODO: this is pretty manual, but I'd rather not require the plugin > dependencies section right now + testNgArtifact = (Artifact)projectArtifactMap.get(testNGArtifactName); + + if (testNgArtifact != null) { + VersionRange range = VersionRange.createFromVersionSpec("[4.7,)"); + if (!range.containsVersion(new DefaultArtifactVersion(testNgArtifact.getVersion()))) { + throw new MojoFailureException( + "TestNG support requires version 4.7 or above. You have declared version " + testNgArtifact + .getVersion()); + } + + convertTestNGParameters(); + + if (this.testClassesDirectory != null) { + properties.setProperty("testng.test.classpath", testClassesDirectory.getAbsolutePath()); + } + + addArtifact(surefireBooter, testNgArtifact); + + // The plugin uses a JDK based profile to select the right testng. We might be explicity using a + // different one since its based on the source level, not the JVM. Prune using the filter. + addProvider(surefireBooter, "surefire-testng", surefireArtifact.getBaseVersion(), testNgArtifact); + } else if (junitArtifact != null && junitArtifact.getBaseVersion().startsWith("4")) { + addProvider(surefireBooter, "surefire-junit4", surefireArtifact.getBaseVersion(), null); + } else { + // add the JUnit provider as default - it doesn't require JUnit to be present, + // since it supports POJO tests. + addProvider(surefireBooter, "surefire-junit", surefireArtifact.getBaseVersion(), null); + } + } catch (ArtifactNotFoundException e) { + throw new MojoExecutionException("Unable to locate required surefire provider dependency: " + e + .getMessage(), e); + } catch (InvalidVersionSpecificationException e) { + throw new MojoExecutionException("Error determining the TestNG version requested: " + e.getMessage(), e); + } catch (ArtifactResolutionException e) { + throw new MojoExecutionException("Error to resolving surefire provider dependency: " + e.getMessage(), e); + } + + if (suiteXmlFiles != null && suiteXmlFiles.length > 0 && test == null) { + if (testNgArtifact == null) { + throw new MojoExecutionException("suiteXmlFiles is configured, but there is no TestNG dependency"); + } + + // TODO: properties should be passed in here too + surefireBooter.addTestSuite("org.apache.maven.surefire.testng.TestNGXmlTestSuite", + new Object[] {suiteXmlFiles, testSourceDirectory.getAbsolutePath(), + testNgArtifact.getVersion(), testNgArtifact.getClassifier(), + properties, reportsDirectory}); + } else { + List includes; + List excludes; + + if (test != null) { + // Check to see if we are running a single test. The raw parameter will + // come through if it has not been set. + + // FooTest -> **/FooTest.java + + includes = new ArrayList(); + + excludes = new ArrayList(); + + if (failIfNoTests == null) { + failIfNoTests = Boolean.TRUE; + } + + String[] testRegexes = StringUtils.split(test, ","); + + for (int i = 0; i < testRegexes.length; i++) { + String testRegex = testRegexes[i]; + if (testRegex.endsWith(".java")) { + testRegex = testRegex.substring(0, testRegex.length() - 5); + } + // Allow paths delimited by '.' or '/' + testRegex = testRegex.replace('.', '/'); + includes.add("**/" + testRegex + ".java"); + } + } else { + includes = this.includes; + + excludes = this.excludes; + + // defaults here, qdox doesn't like the end javadoc value + // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason + if (includes == null || includes.size() == 0) { + includes = + new ArrayList(Arrays + .asList(new String[] {"**/Test*.java", "**/*Test.java", "**/*TestCase.java"})); + } + if (excludes == null || excludes.size() == 0) { + excludes = new ArrayList(Arrays.asList(new String[] {"**/*$*"})); + } + } + + if (testNgArtifact != null) { + surefireBooter.addTestSuite("org.apache.maven.surefire.testng.TestNGDirectoryTestSuite", + new Object[] {testClassesDirectory, includes, excludes, + testSourceDirectory.getAbsolutePath(), + testNgArtifact.getVersion(), testNgArtifact.getClassifier(), + properties, reportsDirectory}); + } else { + String junitDirectoryTestSuite; + if (junitArtifact != null && junitArtifact.getBaseVersion() != null + && junitArtifact.getBaseVersion().startsWith("4")) { + junitDirectoryTestSuite = "org.apache.maven.surefire.junit4.JUnit4DirectoryTestSuite"; + } else { + junitDirectoryTestSuite = "org.apache.maven.surefire.junit.JUnitDirectoryTestSuite"; + } + + // fall back to JUnit, which also contains POJO support. Also it can run + // classes compiled against JUnit since it has a dependency on JUnit itself. + surefireBooter.addTestSuite(junitDirectoryTestSuite, new Object[] {testClassesDirectory, includes, + excludes}); + } + } + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + getLog().debug("Test Classpath :"); + + classpathElements.remove(classesDirectory.getAbsolutePath()); + classpathElements.remove(testClassesDirectory.getAbsolutePath()); + /* + // Check if we need to add configured classes/test classes directories here. + // If they are configured, we should remove the default to avoid conflicts. + if (!project.getBuild().getOutputDirectory().equals(classesDirectory.getAbsolutePath())) { + classpathElements.remove(project.getBuild().getOutputDirectory()); + classpathElements.add(classesDirectory.getAbsolutePath()); + } + if (!project.getBuild().getTestOutputDirectory().equals(testClassesDirectory.getAbsolutePath())) { + classpathElements.remove(project.getBuild().getTestOutputDirectory()); + classpathElements.add(testClassesDirectory.getAbsolutePath()); + } + */ + + for (Iterator i = classpathElements.iterator(); i.hasNext();) { + String classpathElement = (String)i.next(); + + getLog().debug(" " + classpathElement); + + surefireBooter.addClassPathUrl(classpathElement); + } + + Toolchain tc = getToolchain(); + + if (tc != null) { + getLog().info("Toolchain in surefire-plugin: " + tc); + if (ForkConfiguration.FORK_NEVER.equals(forkMode)) { + forkMode = ForkConfiguration.FORK_ONCE; + } + if (jvm != null) { + getLog().warn("Toolchains are ignored, 'executable' parameter is set to " + jvm); + } else { + jvm = tc.findTool("java"); //NOI18N + } + } + + if (additionalClasspathElements != null) { + for (Iterator i = additionalClasspathElements.iterator(); i.hasNext();) { + String classpathElement = (String)i.next(); + + getLog().debug(" " + classpathElement); + + surefireBooter.addClassPathUrl(classpathElement); + } + } + + // ---------------------------------------------------------------------- + // Forking + // ---------------------------------------------------------------------- + + ForkConfiguration fork = new ForkConfiguration(); + + fork.setForkMode(forkMode); + + processSystemProperties(!fork.isForking()); + + if (getLog().isDebugEnabled()) { + showMap(systemProperties, "system property"); + } + + if (fork.isForking()) { + useSystemClassLoader = useSystemClassLoader == null ? Boolean.TRUE : useSystemClassLoader; + fork.setUseSystemClassLoader(useSystemClassLoader.booleanValue()); + fork.setUseManifestOnlyJar(useManifestOnlyJar); + + fork.setSystemProperties(systemProperties); + + if ("true".equals(debugForkedProcess)) { + debugForkedProcess = + "-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"; + } + + fork.setDebugLine(debugForkedProcess); + + if (jvm == null || "".equals(jvm)) { + // use the same JVM as the one used to run Maven (the "java.home" one) + jvm = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; + getLog().debug("Using JVM: " + jvm); + } + + fork.setJvmExecutable(jvm); + + if (workingDirectory != null) { + fork.setWorkingDirectory(workingDirectory); + } else { + fork.setWorkingDirectory(basedir); + } + + fork.setArgLine(argLine); + + fork.setEnvironmentVariables(environmentVariables); + + if (getLog().isDebugEnabled()) { + showMap(environmentVariables, "environment variable"); + + fork.setDebug(true); + } + + if (argLine != null) { + List args = Arrays.asList(argLine.split(" ")); + if (args.contains("-da") || args.contains("-disableassertions")) { + enableAssertions = false; + } + } + } + + surefireBooter.setFailIfNoTests(failIfNoTests == null ? false : failIfNoTests.booleanValue()); + + surefireBooter.setForkedProcessTimeoutInSeconds(forkedProcessTimeoutInSeconds); + + surefireBooter.setRedirectTestOutputToFile(redirectTestOutputToFile); + + surefireBooter.setForkConfiguration(fork); + + surefireBooter.setChildDelegation(childDelegation); + + surefireBooter.setEnableAssertions(enableAssertions); + + surefireBooter.setReportsDirectory(reportsDirectory); + + addReporters(surefireBooter, fork.isForking()); + + return surefireBooter; + } + + private void showMap(Map map, String setting) { + for (Iterator i = map.keySet().iterator(); i.hasNext();) { + String key = (String)i.next(); + String value = (String)map.get(key); + getLog().debug("Setting " + setting + " [" + key + "]=[" + value + "]"); + } + } + + private void addProvider(OSGiSurefireBooter surefireBooter, + String provider, + String version, + Artifact filteredArtifact) throws ArtifactNotFoundException, ArtifactResolutionException { + Artifact providerArtifact = + artifactFactory.createDependencyArtifact("org.apache.maven.surefire", provider, VersionRange + .createFromVersion(version), "jar", null, Artifact.SCOPE_TEST); + ArtifactResolutionResult result = resolveArtifact(filteredArtifact, providerArtifact); + + for (Iterator i = result.getArtifacts().iterator(); i.hasNext();) { + Artifact artifact = (Artifact)i.next(); + + String key = ArtifactUtils.versionlessKey(artifact); + if("junit:junit".equals(key) || "jnuit:junit-dep".equals(key)) { + // Skip junit as it will be pulled from the test case dependencies + continue; + } + getLog().debug("Adding to surefire test classpath: " + artifact.getFile().getAbsolutePath()); + + surefireBooter.addSurefireClassPathUrl(artifact.getFile().getAbsolutePath()); + } + } + + private ArtifactResolutionResult resolveArtifact(Artifact filteredArtifact, Artifact providerArtifact) + throws ArtifactResolutionException, ArtifactNotFoundException { + ArtifactFilter filter = null; + if (filteredArtifact != null) { + filter = + new ExcludesArtifactFilter(Collections.singletonList(filteredArtifact.getGroupId() + ":" + + filteredArtifact.getArtifactId())); + } + + Artifact originatingArtifact = artifactFactory.createBuildArtifact("dummy", "dummy", "1.0", "jar"); + + return artifactResolver.resolveTransitively(Collections.singleton(providerArtifact), + originatingArtifact, + localRepository, + remoteRepositories, + metadataSource, + filter); + } + + private void addArtifact(OSGiSurefireBooter surefireBooter, Artifact surefireArtifact) + throws ArtifactNotFoundException, ArtifactResolutionException { + ArtifactResolutionResult result = resolveArtifact(null, surefireArtifact); + + for (Iterator i = result.getArtifacts().iterator(); i.hasNext();) { + Artifact artifact = (Artifact)i.next(); + + getLog().debug("Adding to surefire booter test classpath: " + artifact.getFile().getAbsolutePath()); + + surefireBooter.addSurefireBootClassPathUrl(artifact.getFile().getAbsolutePath()); + } + } + + protected void processSystemProperties(boolean setInSystem) { + if (systemProperties == null) { + systemProperties = new Properties(); + } + + originalSystemProperties = (Properties)System.getProperties().clone(); + + // We used to take all of our system properties and dump them in with the + // user specified properties for SUREFIRE-121, causing SUREFIRE-491. + // Not gonna do THAT any more... but I'm leaving this code here in case + // we need it later when we try to fix SUREFIRE-121 again. + + // Get the properties from the MavenSession instance to make embedded use work correctly + Properties userSpecifiedProperties = (Properties)session.getExecutionProperties().clone(); + userSpecifiedProperties.putAll(systemProperties); + //systemProperties = userSpecifiedProperties; + + systemProperties.setProperty("basedir", basedir.getAbsolutePath()); + systemProperties.setProperty("user.dir", workingDirectory.getAbsolutePath()); + + systemProperties.setProperty("localRepository", localRepository.getBasedir()); + + if (setInSystem) { + // Add all system properties configured by the user + Iterator iter = systemProperties.keySet().iterator(); + + while (iter.hasNext()) { + String key = (String)iter.next(); + + String value = systemProperties.getProperty(key); + + System.setProperty(key, value); + } + } + } + + /** + *

+ * Adds Reporters that will generate reports with different formatting. + *

+ * The Reporter that will be added will be based on the value of the parameter useFile, reportFormat, and + * printSummary. + * + * @param surefireBooter The surefire booter that will run tests. + * @param forking + */ + private void addReporters(OSGiSurefireBooter surefireBooter, boolean forking) { + Boolean trimStackTrace = Boolean.valueOf(this.trimStackTrace); + if (useFile) { + if (printSummary) { + if (forking) { + surefireBooter.addReport(ForkingConsoleReporter.class.getName(), new Object[] {trimStackTrace}); + } else { + surefireBooter.addReport(ConsoleReporter.class.getName(), new Object[] {trimStackTrace}); + } + } + + if (BRIEF_REPORT_FORMAT.equals(reportFormat)) { + surefireBooter.addReport(BriefFileReporter.class.getName(), new Object[] {reportsDirectory, + trimStackTrace}); + } else if (PLAIN_REPORT_FORMAT.equals(reportFormat)) { + surefireBooter.addReport(FileReporter.class.getName(), new Object[] {reportsDirectory, trimStackTrace}); + } + } else { + if (BRIEF_REPORT_FORMAT.equals(reportFormat)) { + surefireBooter.addReport(BriefConsoleReporter.class.getName(), new Object[] {trimStackTrace}); + } else if (PLAIN_REPORT_FORMAT.equals(reportFormat)) { + surefireBooter.addReport(DetailedConsoleReporter.class.getName(), new Object[] {trimStackTrace}); + } + } + + if (!disableXmlReport) { + surefireBooter.addReport(XMLReporter.class.getName(), new Object[] {reportsDirectory, trimStackTrace}); + } + } + + /** + * @return SurefirePlugin Returns the skipExec. + */ + public boolean isSkipExec() { + return this.skipTests; + } + + /** + * @param skipExec the skipExec to set + */ + public void setSkipExec(boolean skipExec) { + this.skipTests = skipExec; + } + + //TODO remove the part with ToolchainManager lookup once we depend on + //3.0.9 (have it as prerequisite). Define as regular component field then. + private Toolchain getToolchain() { + Toolchain tc = null; + try { + if (session != null) //session is null in tests.. + { + ToolchainManager toolchainManager = + (ToolchainManager)session.getContainer().lookup(ToolchainManager.ROLE); + if (toolchainManager != null) { + tc = toolchainManager.getToolchainFromBuildContext("jdk", session); + } + } + } catch (ComponentLookupException componentLookupException) { + //just ignore, could happen in pre-3.0.9 builds.. + } + return tc; + } + + protected Artifact getArtifact(String groupId, String artifactId) throws MojoExecutionException { + Artifact artifact; + VersionRange vr; + try { + vr = VersionRange.createFromVersionSpec(project.getVersion()); + } catch (InvalidVersionSpecificationException e1) { + vr = VersionRange.createFromVersion(project.getVersion()); + } + artifact = artifactFactory.createDependencyArtifact(groupId, artifactId, vr, "jar", null, Artifact.SCOPE_TEST); + + try { + artifactResolver.resolve(artifact, remoteRepositories, localRepository); + } catch (ArtifactResolutionException e) { + throw new MojoExecutionException("Unable to resolve artifact.", e); + } catch (ArtifactNotFoundException e) { + throw new MojoExecutionException("Unable to find artifact.", e); + } + + return artifact; + } + + private void generateJar(File root, File jar, Manifest mf) throws IOException { + getLog().info("Generating " + jar.toString()); + FileOutputStream fos = new FileOutputStream(jar); + JarOutputStream jos = mf != null ? new JarOutputStream(fos, mf) : new JarOutputStream(fos); + addDir(jos, root, root); + jos.close(); + } + + /** + * Convert the maven version into OSGi version + * @param mavenVersion + * @return + */ + static String osgiVersion(String mavenVersion) { + ArtifactVersion ver = new DefaultArtifactVersion(mavenVersion); + String qualifer = ver.getQualifier(); + if (qualifer != null) { + StringBuffer buf = new StringBuffer(qualifer); + for (int i = 0; i < buf.length(); i++) { + char c = buf.charAt(i); + if (Character.isLetterOrDigit(c) || c == '-' || c == '_') { + // Keep as-is + } else { + buf.setCharAt(i, '_'); + } + } + qualifer = buf.toString(); + } + Version osgiVersion = + new Version(ver.getMajorVersion(), ver.getMinorVersion(), ver.getIncrementalVersion(), qualifer); + String version = osgiVersion.toString(); + return version; + } + + private Manifest createMainBundle() throws IOException { + File mf = new File(project.getBasedir(), "META-INF/MANIFEST.MF"); + Manifest manifest = null; + if (mf.isFile()) { + manifest = new Manifest(new FileInputStream(mf)); + String bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + if (bundleName != null) { + return manifest; + } + } + if (manifest == null) { + manifest = new Manifest(); + } + Attributes attributes = manifest.getMainAttributes(); + attributes.putValue("Manifest-Version", "1.0"); + attributes.putValue(BUNDLE_MANIFESTVERSION, "2"); + attributes.putValue(BUNDLE_SYMBOLICNAME, project.getGroupId() + "." + project.getArtifactId()); + attributes.putValue(BUNDLE_NAME, project.getName()); + attributes.putValue(BUNDLE_VERSION, osgiVersion(project.getVersion())); + attributes.putValue(Constants.DYNAMICIMPORT_PACKAGE, "*"); + return manifest; + } + + private Manifest createTestFragment(Manifest mf) { + // Create a manifest + Manifest manifest = new Manifest(); + Attributes attributes = manifest.getMainAttributes(); + attributes.putValue("Manifest-Version", "1.0"); + attributes.putValue(BUNDLE_MANIFESTVERSION, "2"); + String host = mf.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + int sc = host.indexOf(';'); + if (sc != -1) { + host = host.substring(0, sc); + } + attributes.putValue(BUNDLE_SYMBOLICNAME, host + ".tests"); + attributes.putValue(BUNDLE_NAME, mf.getMainAttributes().getValue(BUNDLE_NAME) + " Tests"); + attributes.putValue(BUNDLE_VERSION, mf.getMainAttributes().getValue(BUNDLE_VERSION)); + attributes.putValue(Constants.FRAGMENT_HOST, host + ";bundle-version=\"" + + mf.getMainAttributes().getValue(BUNDLE_VERSION) + + "\""); + // The main bundle may not have the dependency on JUNIT + attributes.putValue(Constants.DYNAMICIMPORT_PACKAGE, "*"); + return manifest; + } + + private void addDir(JarOutputStream jos, File root, File dir) throws IOException, FileNotFoundException { + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + addDir(jos, root, file); + } else if (file.isFile()) { + // getLog().info(file.toString()); + String uri = root.toURI().relativize(file.toURI()).toString(); + if ("META-INF/MANIFEST.MF".equals(uri)) { + continue; + } + ZipEntry entry = new ZipEntry(uri); + jos.putNextEntry(entry); + byte[] buf = new byte[4096]; + FileInputStream in = new FileInputStream(file); + for (;;) { + int len = in.read(buf); + if (len > 0) { + jos.write(buf, 0, len); + } else { + break; + } + } + in.close(); + jos.closeEntry(); + } + } + } +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/NOTICE new file mode 100644 index 0000000000..51042eab05 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/pom.xml new file mode 100644 index 0000000000..d8f910ed17 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/pom.xml @@ -0,0 +1,52 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 2.0-M1 + ../pom.xml + + tuscany-maven-web-junit + maven-plugin + Apache Tuscany SCA Web JUnit Maven Plugin + + + + org.apache.httpcomponents + httpclient + 4.0-alpha2 + + + + org.apache.maven + maven-plugin-api + 2.0.7 + + + + org.apache.maven + maven-project + 2.0.7 + + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/src/main/java/org/apache/tuscany/tools/sca/web/junit/plugin/WebJUnitGeneratorMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/src/main/java/org/apache/tuscany/tools/sca/web/junit/plugin/WebJUnitGeneratorMojo.java new file mode 100644 index 0000000000..d1afe2c995 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/src/main/java/org/apache/tuscany/tools/sca/web/junit/plugin/WebJUnitGeneratorMojo.java @@ -0,0 +1,181 @@ +/* + * 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. + */ +package org.apache.tuscany.tools.sca.web.junit.plugin; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; + +/** + * @version $Rev$ $Date$ + * @goal generate + * @phase process-resources + * @requiresDependencyResolution runtime + * @description Generate the web.xml and geronimo-web.xml + */ +public class WebJUnitGeneratorMojo extends AbstractMojo { + private final static String ASL_HEADER = + "" + "\n"; + + private final static String GERONIMO_WEB_XML = + ASL_HEADER + "\n" + // + "\n ${context.root}" + + "\n " + + "\n " + + "\n ${groupId}" + + "\n ${artifactId}" + + "\n ${version}" + + "\n war" + + "\n " + + "\n " + + "\n " + + "\n\n"; + + private final static String WEB_XML = + ASL_HEADER + "\n" + + "\n" + + "\n ${display-name}" + + "\n " + + "\n tuscany" + + "\n org.apache.tuscany.sca.host.webapp.TuscanyServletFilter" + + "\n " + + "\n " + + "\n junit" + + "\n org.apache.tuscany.sca.host.webapp.junit.JUnitServletFilter" + + "\n " + + "\n junit.tests.path" + + "\n ${junit.tests.path}" + + "\n " + + "\n " + + "\n " + + "\n tuscany" + + "\n /*" + + "\n " + + "\n " + + "\n junit" + + "\n /junit/*" + + "\n " + + "\n\n"; + + /** + * @parameter + */ + private String testsPath; + + /** + * @parameter + */ + private boolean geronimo; + + /** + * The project to create a build for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + public void execute() throws MojoExecutionException { + File base = + new File(project.getBasedir(), "target" + File.separator + + project.getBuild().getFinalName() + + File.separator + + "WEB-INF"); + base.mkdirs(); + // Create the dir to work around the complaint from maven-war-plugin on non-existent folders + new File(project.getBasedir(), "target/classes/META-INF".replace('/', File.separatorChar)).mkdirs(); + File webxml = new File(base, "web.xml"); + getLog().info("Generating " + webxml.toString()); + + String name = project.getName(); + if (name == null) { + name = project.getGroupId() + "-" + project.getArtifactId(); + } + String content = setParameter(WEB_XML, "display-name", name); + + if (testsPath == null) { + testsPath = "/WEB-INF/classes/"; + } + content = setParameter(content, "junit.tests.path", testsPath); + + try { + FileWriter writer = new FileWriter(webxml); + writer.append(content); + writer.close(); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + if (geronimo) { + File geronimoxml = new File(base, "geronimo-web.xml"); + getLog().info("Generating " + geronimoxml.toString()); + content = setParameter(GERONIMO_WEB_XML, "groupId", project.getGroupId()); + content = setParameter(content, "artifactId", project.getArtifactId()); + content = setParameter(content, "version", project.getVersion()); + // content = setParameter(content, "context.root", "/" + project.getBuild().getFinalName()); + try { + geronimoxml.getParentFile().mkdirs(); + FileWriter writer = new FileWriter(geronimoxml); + writer.append(content); + writer.close(); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } + + // Workaround: maven-war-plugin doesn't like non-existing folders + // create target/test-classes + new File(project.getBasedir(), "target" + File.separator + "test-classes").mkdirs(); + + } + + private String setParameter(String xml, String name, String value) { + String pattern = "${" + name + "}"; + int index = xml.indexOf(pattern); + if (index != -1) { + String content = xml.substring(0, index) + value + xml.substring(index + pattern.length()); + return content; + } + return xml; + } + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/src/main/java/org/apache/tuscany/tools/sca/web/junit/plugin/WebJUnitMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/src/main/java/org/apache/tuscany/tools/sca/web/junit/plugin/WebJUnitMojo.java new file mode 100644 index 0000000000..658d65d7c3 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-web-junit/src/main/java/org/apache/tuscany/tools/sca/web/junit/plugin/WebJUnitMojo.java @@ -0,0 +1,205 @@ +/* + * 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. + */ +package org.apache.tuscany.tools.sca.web.junit.plugin; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.apache.commons.logging.LogFactory; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; + +/** + * @version $Rev$ $Date$ + * @goal test + * @phase integration-test + * @requiresDependencyResolution test + * @description Run the unit test over HTTP + */ +public class WebJUnitMojo extends AbstractMojo { + /** + * The project to create a build for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + /** + * The test cases to run + * @parameter + */ + private String testCases[]; + + /** + * The URL for the web site + * @parameter + */ + private String url; + + /** + * Timeout for the HTTP connection + * @parameter + */ + private int timeout = 300000; // 5 minutes + + /** + * To avoid throwing exceptions because we want the stop container plugin to be executed + * @parameter + */ + private boolean ignoreErrors = true; + + public void execute() throws MojoExecutionException { + if (project.getPackaging().equals("pom")) { + return; + } + + reset(); + + if (url == null) { + url = "http://localhost:8080/" + project.getBuild().getFinalName() + "/junit?op=runAll"; + } + + if (testCases != null) { + StringBuffer buf = new StringBuffer(url); + for (int i = 0; i < testCases.length; i++) { + if (i == 0) { + buf.append('?'); + } + buf.append(testCases[i]); + if (i != testCases.length - 1) { + buf.append(','); + } + } + url = buf.toString(); + } + + getLog().info("Connecting to " + url); + + int runs = 0, errors = 0, failures = 0; + String xml = ""; + + try { + HttpClient client = new DefaultHttpClient(); + HttpGet httpget = new HttpGet(url); + httpget.getParams().setParameter("http.socket.timeout", new Integer(timeout)); + + // Execute HTTP request + HttpResponse response = client.execute(httpget); + + StatusLine status = response.getStatusLine(); + if (status.getStatusCode() != HttpStatus.SC_OK) { + if (!ignoreErrors) { + throw new MojoExecutionException(status.getStatusCode() + ": " + status.getReasonPhrase()); + } + getLog().error(status.getStatusCode() + ": " + status.getReasonPhrase()); + return; + } + Header header = response.getFirstHeader("junit.errors"); + errors = header == null ? 0 : Integer.parseInt(header.getValue()); + header = response.getFirstHeader("junit.failures"); + failures = header == null ? 0 : Integer.parseInt(header.getValue()); + header = response.getFirstHeader("junit.runs"); + runs = header == null ? 0 : Integer.parseInt(header.getValue()); + getLog().info("Runs: " + runs + ", Failures: " + failures + ", Errors: " + errors); + + // Get hold of the response entity + HttpEntity entity = response.getEntity(); + + // If the response does not enclose an entity, there is no need + // to bother about connection release + if (entity != null) { + BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent())); + try { + StringBuffer sb = new StringBuffer(); + while (true) { + String line = reader.readLine(); + if (line == null) { + break; + } + sb.append(line); + } + xml = sb.toString(); + getLog().debug(xml); + + } catch (IOException ex) { + + // In case of an IOException the connection will be released + // back to the connection manager automatically + throw ex; + + } catch (RuntimeException ex) { + + // In case of an unexpected exception you may want to abort + // the HTTP request in order to shut down the underlying + // connection and release it back to the connection manager. + httpget.abort(); + throw ex; + + } finally { + + // Closing the input stream will trigger connection release + reader.close(); + + } + + } + } catch (Exception e) { + if (!ignoreErrors) { + throw new MojoExecutionException(e.getMessage(), e); + } + getLog().error(e); + } + if (errors != 0 || failures != 0) { + if (!ignoreErrors) { + throw new MojoExecutionException(xml); + } + getLog().error(xml); + } + + } + + /** + * A workaround to avoid logging conflict with Geronimo + */ + private static void reset() { + LogFactory.releaseAll(); + + // Restore a reasonable default log impl + System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog"); + + // Make SimpleLog look more like Maven logs + System.setProperty("org.apache.commons.logging.simplelog.showShortLogname", "false"); + + // Restore default Geronimo bootstrap behavior + System.getProperties().remove("geronimo.bootstrap.logging.enabled"); + } + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/LICENSE b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/LICENSE @@ -0,0 +1,205 @@ + + 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 [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/NOTICE b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/NOTICE new file mode 100644 index 0000000000..25bb89c9b2 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/pom.xml b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/pom.xml new file mode 100644 index 0000000000..0ce2fdcbaa --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/pom.xml @@ -0,0 +1,45 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 2.0-M1 + ../pom.xml + + tuscany-maven-wsdl2java + maven-plugin + Apache Tuscany SCA WSDL2Java Maven Plugin + + + + org.apache.maven + maven-plugin-api + 2.0 + + + + org.apache.tuscany.sca + tuscany-wsdl2java + 2.0-M1 + + + diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/src/main/java/org/apache/tuscany/tools/wsdl2java/plugin/WSDL2JavaGeneratorMojo.java b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/src/main/java/org/apache/tuscany/tools/wsdl2java/plugin/WSDL2JavaGeneratorMojo.java new file mode 100644 index 0000000000..8021692521 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/src/main/java/org/apache/tuscany/tools/wsdl2java/plugin/WSDL2JavaGeneratorMojo.java @@ -0,0 +1,152 @@ +/* + * 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. + */ +package org.apache.tuscany.tools.wsdl2java.plugin; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.util.List; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.tuscany.tools.wsdl2java.generate.WSDL2JavaGenerator; + +/** + * @version $Rev$ $Date$ + * @goal generate + * @phase generate-sources + * @description Generate SDO interface classes from an XML Schema + */ +public class WSDL2JavaGeneratorMojo extends AbstractMojo { + /** + * The directory containing WSDL files; defaults to ${basedir}/src/main/wsdl + * @parameter expression="${basedir}/src/main/wsdl" + */ + private String wsdlDir; + + /** + * Name of the WSDL file; if omitted all files in the directory are processed + * @parameter + */ + private File wsdlFile; + + /** + * The Java package to generate into. By default the value is derived from the schema URI. + * + * @parameter + */ + private String javaPackage; + + /** + * The directory to generate into; defaults to ${project.build.directory}/wsdl2java-source + * + * @parameter expression="${project.build.directory}/wsdl2java-source" + */ + private String targetDirectory; + + /** + * The directory to generate into; defaults to ${project.build.directory}/wsdl2java-source + * + * @parameter + */ + private WSDLFileOption[] wsdlFiles; + + /** + * @parameter expression="${project.compileSourceRoots}" + * @readonly + */ + private List compilerSourceRoots; + + public void execute() throws MojoExecutionException { + + if(null != wsdlFiles){ + for(int i=0; i< wsdlFiles.length ; ++i ){ + System.err.println("wsdlFiles" + wsdlFiles[i].getFileName()); + WSDLFileOption wf = wsdlFiles[i]; + + if(null == wf.getTargetDirectory()) + wf.setTargetDirectory(targetDirectory); + if(null == wf.getJavaPackage()){ + wf.setJavaPackage(javaPackage); + } + if(wf.getFileName() == null || wf.getFileName().length() ==0){ + throw new MojoExecutionException("no fileName specfied for wsdl."); + } + if(!wf.getFileName().canRead() || !wf.getFileName().isFile()){ + + throw new MojoExecutionException("file can not be read:"+wf.getFileName()); + } + + } + }else{ + + + + if (wsdlFile == null) { + + File[] files = new File(wsdlDir).listFiles(FILTER); + + wsdlFiles= new WSDLFileOption[files.length]; + for(int i= files.length -1; i> -1; --i){ + + + wsdlFiles[i] = new WSDLFileOption(); + wsdlFiles[i].setFileName(files[i]); + wsdlFiles[i].setJavaPackage(javaPackage); + wsdlFiles[i].setPorts(null); + wsdlFiles[i].setTargetDirectory(targetDirectory); + + + } + + } else { + wsdlFiles= new WSDLFileOption[]{new WSDLFileOption()}; + wsdlFiles[0].setFileName(wsdlFile); + wsdlFiles[0].setJavaPackage(javaPackage); + wsdlFiles[0].setPorts(null); + wsdlFiles[0].setTargetDirectory(targetDirectory); + } + } + + int genOptions = 0; + + for (int i = 0; i < wsdlFiles.length; i++) { + File file = wsdlFiles[i].getFileName(); + File marker = new File(targetDirectory, ".gen#" + file.getName()+".wsdl2java"); + if (file.lastModified() > marker.lastModified()) { + getLog().info("Generating Java service interfaces from " + file); + WSDL2JavaGenerator.generateFromWSDL(file.toString(), wsdlFiles[i].getPorts(), wsdlFiles[i].getTargetDirectory(), wsdlFiles[i].getJavaPackage(), null, genOptions); + } + try { + marker.createNewFile(); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + marker.setLastModified(System.currentTimeMillis()); + } + + compilerSourceRoots.add(targetDirectory); + } + + private static final FileFilter FILTER = new FileFilter() { + public boolean accept(File pathname) { + return (pathname.isFile() || !pathname.isHidden()); + } + }; +} \ No newline at end of file diff --git a/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/src/main/java/org/apache/tuscany/tools/wsdl2java/plugin/WSDLFileOption.java b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/src/main/java/org/apache/tuscany/tools/wsdl2java/plugin/WSDLFileOption.java new file mode 100644 index 0000000000..cc10c351b1 --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/maven-wsdl2java/src/main/java/org/apache/tuscany/tools/wsdl2java/plugin/WSDLFileOption.java @@ -0,0 +1,92 @@ +/* + * 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. + */ +package org.apache.tuscany.tools.wsdl2java.plugin; + +import java.io.File; + +public class WSDLFileOption { + /** + * Name of the WSDL file; if omitted all files in the directory are processed + * + */ + private File fileName; + + /** + * The Java package to generate into. By default the value is derived from the schema URI. + * + * + */ + private String javaPackage; + + /** + * The directory to generate into; defaults to ${project.build.directory}/wsdl2java-source + * + * + */ + private String targetDirectory; + + /** + * @parameter expression="${project.compileSourceRoots}" + * @readonly + */ + + private String ports[]; + + /** + * @parameter expression="${project.compileSourceRoots}" + * @readonly + */ + + + public WSDLFileOption(){} + + public String getJavaPackage() { + return javaPackage; + } + + public void setJavaPackage(String javaPackage) { + this.javaPackage = javaPackage; + } + + + public String[] getPorts() { + return ports; + } + + public void setPorts(String[] ports) { + this.ports = ports; + } + + public String getTargetDirectory() { + return targetDirectory; + } + + public void setTargetDirectory(String targetDirectory) { + this.targetDirectory = targetDirectory; + } + + public File getFileName() { + return fileName; + } + + public void setFileName(File fileName) { + this.fileName = fileName; + } + +} diff --git a/tags/java/sca/2.0-M1/tools/maven/pom.xml b/tags/java/sca/2.0-M1/tools/maven/pom.xml new file mode 100644 index 0000000000..cf7b01b30a --- /dev/null +++ b/tags/java/sca/2.0-M1/tools/maven/pom.xml @@ -0,0 +1,62 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-tools + 2.0-M1 + ../pom.xml + + + pom + tuscany-sca-maven-tools + Apache Tuscany SCA Maven Tools + + + + default + + true + + + maven-ant-generator + maven-bundle-plugin + maven-osgi-junit + maven-dependency-lister + maven-eclipse-compiler + maven-incremental-build + maven-java2wsdl + maven-web-junit + maven-wsdl2java + + + + + + + junit + junit + 4.5 + test + + + + -- cgit v1.2.3