summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2011-06-20 10:14:14 +0000
committerantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2011-06-20 10:14:14 +0000
commit501aeb9ee89c60248794d2d7ab91c81d589654ff (patch)
treea4a5880bdf5a8f13c26ab5bcfbc89b031d6c5790
parentd1366f1b89e05fbe60cdfbbbd2d22ed4d7105c50 (diff)
[maven-release-plugin] copy for tag tuscany-bundle-plugin-1.0.8
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1137585 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/LICENSE205
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/NOTICE6
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/README72
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/RELEASE_NOTES56
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/pom.xml242
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/AggregatedBundleActivator.java56
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactAggregation.java72
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactManifest.java37
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactMember.java61
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java259
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleUtil.java640
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundlesMetaDataBuildMojo.java1465
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/Extension.java60
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/Feature.java59
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/HeaderParser.java331
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ModuleBundlesBuildMojo.java1338
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/OSGIArtifactVersion.java219
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ThirdPartyBundleBuildMojo.java152
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java1150
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseClasspathWriter.java635
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseCleanMojo.java208
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipsePlugin.java1877
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseProjectWriter.java357
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/Messages.java68
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/bundle/plugin/LICENSE.txt205
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/bundle/plugin/NOTICE.txt5
-rw-r--r--maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/plugin/eclipse/messages.properties81
27 files changed, 9916 insertions, 0 deletions
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/LICENSE b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/LICENSE
new file mode 100644
index 0000000000..8aa906c321
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/NOTICE b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/NOTICE
new file mode 100644
index 0000000000..444110438a
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/NOTICE
@@ -0,0 +1,6 @@
+Apache Tuscany Maven Bundle Plugin
+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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/README b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/README
new file mode 100644
index 0000000000..74b16f3266
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/README
@@ -0,0 +1,72 @@
+A Maven plugin used by the Tuscany SCA project that can build an OSGi bundle for a
+project's third-party dependencies, generate a directory containing OSGi bundles
+for all the project's module dependencies, and create Eclipse project files
+(.project, .classpath etc) to configure the Eclipse PDE environment for a project.
+
+To build, from the top maven-bundle-plugin run maven:
+
+mvn
+
+or once all the dependencies have been downloaded and a succesful build run use:
+
+mvn clean install -o
+
+So as to avoid the Tuscany SCA project using SNAPSHOT dependencies any changes
+to this module should be released and the Tuscany SCA project updated to use
+the newly released version.
+
+To release this module:
+
+mvn release:prepare
+
+followed by:
+
+mvn release:perform
+
+That will automatically create an SVN tag from the release, update the version
+numbers in the pom.xml files in the trunk and tag, and deploy the artifacts to the
+staging repository defined by the <deploy.altRepository> in your Maven settings.xml.
+While running it will prompt you for the names for the tag, release version etc.
+
+Note: there seem to be issues with having empty folders in the src tree which causes
+ release:prepare to fail, not sure why but deleting the empty folder fixes the
+ problem. You can do "mvn release:rollback" to undo a failed release.
+
+In your maven settings.xml file you must have a server defined named "apache.releases",
+and a profile named "release". For example:
+
+ <servers>
+ ...
+ <server>
+ <id>apache.releases</id>
+ <username>antelder</username>
+ <privateKey>\ant\id_dsa</privateKey>
+ <passphrase>xxx</passphrase>
+ <directoryPermissions>775</directoryPermissions>
+ <filePermissions>664</filePermissions>
+ </server>
+ </servers>
+
+ <profiles>
+ ...
+ <profile>
+ <id>release</id>
+ <properties>
+ <gpg.passphrase>...</gpg.passphrase>
+ <deploy.altRepository>apache.releases::default::scp://people.apache.org/home/antelder/public_html/tuscany/maven-bundle-plugin-1.0</deploy.altRepository>
+ </properties>
+ </profile>
+ </profiles>
+
+Call a vote to release the module, eg: http://apache.markmail.org/message/6jnlfxbx7uklt5nv
+
+After a successful vote copy the staging artifacts to the live repository, eg:
+
+cp -p -v -R maven-bundle-plugin-1.0/org/apache/tuscany/maven/plugins/ /x1/www/people.apache.org/repo/m2-ibiblio-rsync-repository/org/apache/tuscany/maven/plugins
+
+
+
+
+
+
+
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/RELEASE_NOTES b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/RELEASE_NOTES
new file mode 100644
index 0000000000..e30b357d2f
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/RELEASE_NOTES
@@ -0,0 +1,56 @@
+Apache Tuscany Maven Bundle Plugin 1.0.8 Release Notes
+======================================================
+
+- TUSCANY-3861: Rename bundle plugin to be tuscany-bundle-plugin to conform to Maven naming.
+
+Apache Tuscany Maven Bundle Plugin 1.0.7 Release Notes
+======================================================
+
+- changes to generate metadata for extensions.
+
+Apache Tuscany Maven Bundle Plugin 1.0.6 Release Notes
+======================================================
+
+- TUSCANY-3457: maven-bundle-plugin filtering manually specified manifests
+- Add new goal so that we can generate a single OSGi bundle from the modules
+
+Apache Tuscany Maven Bundle Plugin 1.0.5 Release Notes
+======================================================
+
+- Filter out system packages in export from non-bundle jars such as xerces, xalan or saxon to avoid package conflicts.
+ This now means Tuscany can be used with Apache Felix
+
+Apache Tuscany Maven Bundle Plugin 1.0.4 Release Notes
+======================================================
+
+- Add compile dependencies to the .classpath file if it doesn't supply any packages to the OSGi import. This maks this plugin more closer to the mvn eclipse:eclipse behavior.
+- Exclude the project itself from the resolution so that it can be built offline
+- Add support to include different versions of 3rd party jars into the distribution if it is omitted by a lower version in maven
+- Check the partial attr to decide if the bundle needs to be required
+- Don't generate Import-Package header for the 3rd party jars so that either local package is used if there are split packages
+- Add the option to generate a gateway bundle that aggregates split packages and export them
+- Fix svn:eol-style and svn:keywords properties for java/xml files
+- Add import statement for the generated MF
+- Upgrade to Equinox 3.5
+
+Apache Tuscany Maven Bundle Plugin 1.0.3 Release Notes
+======================================================
+
+Apache Tuscany Maven Bundle Plugin 1.0.2 Release Notes
+======================================================
+
+Apache Tuscany Maven Bundle Plugin 1.0.1 Release Notes
+======================================================
+
+TUSCANY-2877: Introducing a generic Eclipse-BuddyPolicy header for the bundles generated from dependent artifacts would be helpful
+TUSCANY-2876: In artifact aggrations, artifactMemebers is misspelled and may lead to error prone configurations
+TUSCANY-2873: Wrapping of non-OSGi components creates versions that may makes no-sense
+TUSCANY-2872: Maven Bundle Plugin throws NPE when a dependent non-OSGI jar has no manifest
+r747530: Use the equinox as the osgi dependency
+
+
+
+Apache Tuscany Maven Bundle Plugin 1.0 Release Notes
+====================================================
+
+Initial release
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/pom.xml b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/pom.xml
new file mode 100644
index 0000000000..cf313ccca5
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/pom.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache</groupId>
+ <artifactId>apache</artifactId>
+ <version>7</version>
+ </parent>
+
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-bundle-plugin</artifactId>
+ <packaging>maven-plugin</packaging>
+ <name>Apache Tuscany Maven OSGi Bundle Plugin</name>
+ <version>1.0.8</version>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/tuscany/maven-plugins/tags/tuscany-bundle-plugin-1.0.8</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/tuscany/maven-plugins/tags/tuscany-bundle-plugin-1.0.8</developerConnection>
+ <url>scm:svn:https://svn.apache.org/repos/asf/tuscany/maven-plugins/tags/tuscany-bundle-plugin-1.0.8</url>
+ </scm>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+ <build>
+ <plugins>
+
+ <plugin>
+ <inherited>true</inherited>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <altDeploymentRepository>${deploy.altRepository}</altDeploymentRepository>
+ <updateReleaseInfo>true</updateReleaseInfo>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.0-alpha-4</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>deploy</id>
+ <build>
+ <defaultGoal>deploy</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.0.4</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>2.0.8</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>2.0.8</version>
+ <exclusions>
+ <exclusion>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings</artifactId>
+ <version>2.0.8</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>2.0.8</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ <version>2.0.8</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-dependency-tree</artifactId>
+ <version>1.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <version>2.6</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse</groupId>
+ <artifactId>osgi</artifactId>
+ <version>3.5.0.v20090520</version>
+ <scope>compile</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <defaultGoal>install</defaultGoal>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>.</directory>
+ <targetPath>META-INF</targetPath>
+ <filtering>true</filtering>
+ <includes>
+ <include>LICENSE</include>
+ <include>NOTICE</include>
+ </includes>
+ </resource>
+ </resources>
+
+ <pluginManagement>
+
+ <plugins>
+ <!-- compiler plugin configuration -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+
+ <!-- jar plugin configuration -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.1</version>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Extension-Name>${project.artifactId}</Extension-Name>
+ <Specification-Title>${project.name}</Specification-Title>
+ <Specification-Vendor>The Apache Software Foundation</Specification-Vendor>
+ <Specification-Version>${project.version}</Specification-Version>
+ <Implementation-Title>${project.name}</Implementation-Title>
+ <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
+ <Implementation-Vendor>The Apache Software Foundation</Implementation-Vendor>
+ <Implementation-Version>${project.version}</Implementation-Version>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+
+ <!-- surefire plugin configuration -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.4.3</version>
+ <configuration>
+ <includes>
+ <include>**/*TestCase.java</include>
+ </includes>
+ <reportFormat>brief</reportFormat>
+ <useFile>false</useFile>
+ <forkMode>once</forkMode>
+ <argLine>-ea -Xmx256m</argLine>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.0-beta-8</version>
+ <configuration>
+ <tagBase>https://svn.apache.org/repos/asf/tuscany/maven-plugins/tags</tagBase>
+ <useReleaseProfile>false</useReleaseProfile>
+ <preparationGoals>clean install</preparationGoals>
+ <goals>deploy</goals>
+ <arguments>-Prelease,deploy</arguments>
+ <autoVersionSubmodules>true</autoVersionSubmodules>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </pluginManagement>
+
+ </build>
+
+</project>
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/AggregatedBundleActivator.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/AggregatedBundleActivator.java
new file mode 100644
index 0000000000..64999cb309
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/AggregatedBundleActivator.java
@@ -0,0 +1,56 @@
+/*
+ * 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.maven.bundle.plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * A bundle activator that delegates to others
+ */
+public class AggregatedBundleActivator implements BundleActivator {
+ public static final String BUNDLE_ACTIVATOR_LIST = "Tuscany-Bundle-Activator-List";
+ private List<BundleActivator> activators = new ArrayList<BundleActivator>();
+
+ public void start(BundleContext context) throws Exception {
+ String list = (String)context.getBundle().getHeaders().get(BUNDLE_ACTIVATOR_LIST);
+ if (list == null) {
+ return;
+ }
+ for (String cls : list.split(",")) {
+ Object i = context.getBundle().loadClass(cls).newInstance();
+ if (i instanceof BundleActivator) {
+ ((BundleActivator)i).start(context);
+ activators.add((BundleActivator)i);
+ }
+ }
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ for (BundleActivator a : activators) {
+ a.stop(context);
+ }
+
+ }
+
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactAggregation.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactAggregation.java
new file mode 100644
index 0000000000..9abbe1ebd7
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactAggregation.java
@@ -0,0 +1,72 @@
+/*
+ * 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.maven.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<ArtifactMember> artifactMembers = new ArrayList<ArtifactMember>();
+ private transient List<Artifact> artifacts = new ArrayList<Artifact>();
+
+ public List<Artifact> 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<ArtifactMember> getArtifactMembers() {
+ return artifactMembers;
+ }
+
+ public void setArtifactMembers(List<ArtifactMember> artifacts) {
+ this.artifactMembers = artifacts;
+ }
+
+ public String toString() {
+ return symbolicName + ";version=\"" + version + "\"\n" + artifactMembers;
+ }
+
+ public boolean matches(Artifact artifact) {
+ for(ArtifactMember m: artifactMembers) {
+ if(m.matches(artifact)) {
+ return true;
+ }
+ }
+ return false;
+ }
+} \ No newline at end of file
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactManifest.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactManifest.java
new file mode 100644
index 0000000000..f6eca87c8e
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactManifest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.maven.bundle.plugin;
+
+import java.io.File;
+
+/**
+ *
+ */
+public class ArtifactManifest extends ArtifactMember {
+ private File manifestFile;
+
+ public File getManifestFile() {
+ return manifestFile;
+ }
+
+ public void setManifestFile(File manifestFile) {
+ this.manifestFile = manifestFile;
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactMember.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactMember.java
new file mode 100644
index 0000000000..834ee7825e
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/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.maven.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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java
new file mode 100644
index 0000000000..9c36ae34a2
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java
@@ -0,0 +1,259 @@
+/*
+ * 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.maven.bundle.plugin;
+
+import static org.apache.tuscany.maven.bundle.plugin.AggregatedBundleActivator.BUNDLE_ACTIVATOR_LIST;
+import static org.apache.tuscany.maven.bundle.plugin.HeaderParser.merge;
+import static org.osgi.framework.Constants.BUNDLE_ACTIVATOR;
+import static org.osgi.framework.Constants.BUNDLE_CLASSPATH;
+
+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.util.ArrayList;
+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.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+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.tuscany.maven.bundle.plugin.HeaderParser.HeaderClause;
+
+/**
+ * @version $Rev$ $Date$
+ * @goal aggregate-modules
+ * @phase process-resources
+ * @requiresDependencyResolution test
+ * @description Generate an aggregated bundle that contains all the modules and 3rd party jars
+ */
+public class BundleAggregatorMojo extends AbstractMojo {
+ /**
+ * Root directory.
+ *
+ * @parameter expression="${project.build.directory}/modules"
+ */
+ private File rootDirectory;
+
+ /**
+ * Aggregated bundle
+ *
+ * @parameter expression="${project.build.directory}/singlebundle/tuscany-bundle.jar"
+ */
+ private File targetBundleFile;
+
+ /**
+ * @parameter default-value== "org.apache.tuscany.sca.bundle";
+ */
+ private String bundleName = "org.apache.tuscany.sca.bundle";
+
+ /**
+ * @parameter default-value== "2.0.0";
+ */
+ private String bundleVersion = "2.0.0";
+
+ // private static final Logger logger = Logger.getLogger(BundleAggregatorMojo.class.getName());
+
+ public static void aggregateBundles(Log log,
+ File root,
+ File[] files,
+ File targetBundleFile,
+ String bundleName,
+ String bundleVersion) throws Exception {
+ targetBundleFile.getParentFile().mkdirs();
+ Set<File> jarFiles = new HashSet<File>();
+ List<Manifest> manifests = new ArrayList<Manifest>();
+ for (File child : files) {
+ try {
+ Manifest manifest = null;
+ if (child.isDirectory()) {
+ File mf = new File(child, "META-INF/MANIFEST.MF");
+ if (mf.isFile()) {
+ FileInputStream is = new FileInputStream(mf);
+ manifest = new Manifest(is);
+ is.close();
+ if (manifest != null) {
+ String classpath = manifest.getMainAttributes().getValue("Bundle-ClassPath");
+ if (classpath != null) {
+ for (HeaderClause clause : HeaderParser.parse(classpath)) {
+ if (clause.getValue().equals(".")) {
+ continue;
+ } else {
+ jarFiles.add(new File(child, clause.getValue()));
+ }
+ }
+ } else {
+ //
+ }
+ }
+ }
+ } else if (child.getName().endsWith(".jar")) {
+ JarFile jar = new JarFile(child);
+ manifest = jar.getManifest();
+ jar.close();
+ if (manifest != null) {
+ String id = manifest.getMainAttributes().getValue("Bundle-SymbolicName");
+ if (id != null && (id.startsWith("org.eclipse.") || id
+ .startsWith("org.apache.tuscany.sca.gateway"))) {
+ manifest = null;
+ } else {
+ jarFiles.add(child);
+ }
+ }
+ }
+ if (manifest == null) {
+ continue;
+ }
+
+ log.debug("Bundle file: " + child);
+ manifests.add(manifest);
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+ Manifest merged = new Manifest();
+ Attributes attributes = merged.getMainAttributes();
+ attributes.putValue("Manifest-Version", "1.0");
+ attributes.putValue("Bundle-ManifestVersion", "2");
+ attributes.putValue("Bundle-License", "http://www.apache.org/licenses/LICENSE-2.0.txt");
+ attributes.putValue("Bundle-DocURL", "http://www.apache.org/");
+ attributes.putValue("Bundle-RequiredExecutionEnvironment", "J2SE-1.5,JavaSE-1.6");
+ attributes.putValue("Bundle-Vendor", "The Apache Software Foundation");
+ attributes.putValue("Bundle-Version", bundleVersion);
+ attributes.putValue("Bundle-SymbolicName", bundleName);
+ attributes.putValue("SCA-Version", "1.1");
+ attributes.putValue("Bundle-Name", bundleName);
+ // attributes.putValue("Bundle-ActivationPolicy", "lazy");
+ for (Manifest mf : manifests) {
+ for (Map.Entry<Object, Object> e : mf.getMainAttributes().entrySet()) {
+ Attributes.Name key = (Attributes.Name)e.getKey();
+ String name = key.toString();
+ String oldValue = attributes.getValue(name);
+ String value = (String)e.getValue();
+ if (name.equals("Export-Package") || name.equals("Import-Package")
+ || name.equals("Require-Bundle")
+ || name.equals("DynamicImport-Package")
+ || name.equals("Bundle-ClassPath")
+ || name.equals("Private-Package")
+ || name.equals("Bundle-Description")) {
+ attributes.putValue(name, merge(oldValue, value));
+ } else if (name.equals(BUNDLE_ACTIVATOR)) {
+ oldValue = attributes.getValue(BUNDLE_ACTIVATOR_LIST);
+ attributes.putValue(BUNDLE_ACTIVATOR_LIST, merge(oldValue, value));
+ } else if (name.equals("Main-Class") || name.startsWith("Eclipse-") || name.startsWith("Bundle-")) {
+ // Ignore
+ } else {
+ // Ignore
+ // attributes.putValue(name, value);
+ }
+ }
+ }
+ log.info("Generating " + targetBundleFile);
+ attributes.putValue(BUNDLE_ACTIVATOR, AggregatedBundleActivator.class.getName());
+ String bundleClassPath = attributes.getValue(BUNDLE_CLASSPATH);
+ bundleClassPath = merge(bundleClassPath, ".");
+ for (File f : jarFiles) {
+ bundleClassPath = merge(bundleClassPath, f.getName());
+ }
+ attributes.putValue(BUNDLE_CLASSPATH, bundleClassPath);
+
+ FileOutputStream fos = new FileOutputStream(targetBundleFile);
+ JarOutputStream bundle = new JarOutputStream(fos, merged);
+
+ for (File file : jarFiles) {
+ log.info("Adding " + file);
+ addEntry(bundle, file.getName(), file);
+ }
+
+ String classFile = AggregatedBundleActivator.class.getName().replace(".", "/") + ".class";
+ InputStream classStream = BundleAggregatorMojo.class.getClassLoader().getResourceAsStream(classFile);
+ addEntry(bundle, classFile, classStream);
+ bundle.close();
+ }
+
+ private static 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;
+ }
+ addEntry(jos, uri, file);
+ }
+ }
+ }
+
+ private static void addEntry(JarOutputStream jos, String name, File file) throws IOException {
+ FileInputStream in = new FileInputStream(file);
+ addEntry(jos, name, in);
+ }
+
+ private static final byte[] buf = new byte[4096];
+
+ private static void addEntry(JarOutputStream jos, String name, InputStream in) throws IOException {
+ ZipEntry entry = new ZipEntry(name);
+ jos.putNextEntry(entry);
+ for (;;) {
+ int len = in.read(buf);
+ if (len > 0) {
+ jos.write(buf, 0, len);
+ } else {
+ break;
+ }
+ }
+ in.close();
+ jos.closeEntry();
+ }
+
+ private static void generateJar(File root, File jar, Manifest mf) throws IOException {
+ FileOutputStream fos = new FileOutputStream(jar);
+ JarOutputStream jos = mf != null ? new JarOutputStream(fos, mf) : new JarOutputStream(fos);
+ addDir(jos, root, root);
+ jos.close();
+ }
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ try {
+ Log log = getLog();
+ if (!rootDirectory.isDirectory()) {
+ log.warn(rootDirectory + " is not a directory");
+ return;
+ }
+ File[] files = rootDirectory.listFiles();
+ aggregateBundles(log, rootDirectory, files, targetBundleFile, bundleName, bundleVersion);
+ } catch (Exception e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleUtil.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleUtil.java
new file mode 100644
index 0000000000..8f280e59e9
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleUtil.java
@@ -0,0 +1,640 @@
+/*
+ * 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.maven.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.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.Collections;
+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.logging.Logger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+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 {
+ static final String META_INF_SERVICES = "META-INF.services;partial=true;mandatory:=partial";
+ 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
+ */
+ public static String getBundleSymbolicName(File file) throws IOException {
+ Manifest manifest = getManifest(file);
+ return getBundleSymbolicName(manifest);
+ }
+
+ static String getBundleSymbolicName(Manifest manifest) {
+ if (manifest == null) {
+ return null;
+ }
+
+ String bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
+ 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;
+ if (file.isDirectory()) {
+ File mf = new File(file, "META-INF/MANIFEST.MF");
+ if (mf.isFile()) {
+ InputStream is = new FileInputStream(mf);
+ manifest = new Manifest(new FileInputStream(mf));
+ is.close();
+ }
+ } else {
+ JarFile jar = new JarFile(file, false);
+ manifest = jar.getManifest();
+ jar.close();
+ }
+ 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<File> jarFiles, String name, String symbolicName, String version, String dir)
+ throws IllegalStateException {
+ return libraryManifest(jarFiles, name, symbolicName, version, dir, null, null);
+ }
+ /**
+ * Generate a Bundle manifest for a set of JAR files.
+ *
+ * @param jarFiles
+ * @param name
+ * @param symbolicName
+ * @param version
+ * @param dir
+ * @param buddyPolicy
+ * @param env
+ * @return
+ * @throws IllegalStateException
+ */
+ static Manifest libraryManifest(Set<File> jarFiles, String name, String symbolicName, String version, String dir, String buddyPolicy, String env)
+ throws IllegalStateException {
+ try {
+
+ // List exported packages and bundle classpath entries
+ StringBuffer classpath = new StringBuffer();
+ Set<String> exportedPackages = new HashSet<String>();
+ for (File jarFile : jarFiles) {
+ if (!jarFile.exists()) {
+ logger.warning(jarFile + " doesn't exist.");
+ continue;
+ }
+ addPackages(jarFile, exportedPackages, version);
+ if (dir != null) {
+ classpath.append(dir).append("/");
+ }
+ classpath.append(jarFile.getName());
+ classpath.append(",");
+ }
+
+ if (env == null) {
+ env = "JavaSE-1.6";
+ }
+ Set<String> sysPackages = getSystemPackages(env);
+
+ // Generate export-package and import-package declarations
+ StringBuffer exports = new StringBuffer();
+ StringBuffer imports = new StringBuffer();
+ Set<String> pkgs = new HashSet<String>();
+ for (String export : exportedPackages) {
+ String packageName = packageName(export);
+ if (!pkgs.contains(packageName) && !sysPackages.contains(packageName)) {
+ // Add corresponding import declaration
+ if (!"META-INF.services".equals(packageName)) {
+ imports.append(export);
+ imports.append(',');
+ }
+ pkgs.add(packageName);
+ exports.append(export);
+ exports.append(',');
+ } else {
+ logger.warning("Duplicate or system 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);
+ // The system bundle has incomplete javax.transaction* packages exported
+ attributes.putValue(DYNAMICIMPORT_PACKAGE, "javax.transaction;version=\"1.1\",javax.transaction.xa;version=\"1.1\",*");
+ if (buddyPolicy != null && buddyPolicy.length() > 0){
+ attributes.putValue("Eclipse-BuddyPolicy", buddyPolicy);
+ }
+ 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);
+ write(attributes, "Eclipse-BuddyPolicy", 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<String> 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<String> packages, String version) throws IOException {
+ ZipInputStream is = new ZipInputStream(new FileInputStream(jarFile));
+ ZipEntry entry;
+ while ((entry = is.getNextEntry()) != null) {
+ String entryName = entry.getName();
+ // Export split packages for META-INF/services
+ if(entryName.startsWith("META-INF/services/")) {
+ packages.add(META_INF_SERVICES);
+ }
+ 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();
+ }
+
+ private static Set<String> getSystemPackages(String env) throws IOException {
+ Set<String> sysPackages = new HashSet<String>();
+ InputStream is = BundleUtil.class.getResourceAsStream("/" + env + ".profile");
+ if (is != null) {
+ Properties props = new Properties();
+ props.load(is);
+ String pkgs = (String)props.get("org.osgi.framework.system.packages");
+ if (pkgs != null) {
+ for (String p : pkgs.split(",")) {
+ sysPackages.add(p.trim());
+ }
+ }
+ }
+ return sysPackages;
+ }
+
+ /**
+ * 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
+ */
+ public static Set<String> getExportedPackages(File file) throws IOException {
+ if (!file.exists()) {
+ return Collections.emptySet();
+ }
+
+ Set<String> packages = new HashSet<String>();
+ Manifest manifest = getManifest(file);
+
+ // Read the export-package declaration and get a list of the packages available in a JAR
+ String bundleName = null;
+ String exports = null;
+
+ if (manifest != null) {
+ exports = manifest.getMainAttributes().getValue(EXPORT_PACKAGE);
+ bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
+ }
+
+ if (bundleName == null) {
+ Set<String> allPackages = new HashSet<String>();
+ addAllPackages(file, allPackages, "");
+ for (String p : allPackages) {
+ packages.add(packageName(p));
+ }
+ return packages;
+ }
+
+ packages.addAll(parsePackages(exports));
+
+ return packages;
+ }
+
+ public static Set<String> getImportedPackages(File file) throws IOException {
+ if (!file.exists()) {
+ return Collections.emptySet();
+ }
+
+ Manifest manifest = getManifest(file);
+
+ // Read the export-package declaration and get a list of the packages available in a JAR
+ String bundleName = null;
+ String imports = null;
+
+ if (manifest != null) {
+ imports = manifest.getMainAttributes().getValue(IMPORT_PACKAGE);
+ bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
+ if (imports != null && bundleName != null) {
+ return parsePackages(imports);
+ }
+ }
+ return Collections.emptySet();
+ }
+
+ private static Set<String> parsePackages(String header) {
+ if (header == null) {
+ return Collections.emptySet();
+ }
+ Set<String> packages = new HashSet<String>();
+ // Parse the export-package declaration, and extract the individual packages
+ StringBuffer buffer = new StringBuffer();
+ boolean q = false;
+ for (int i = 0, n = header.length(); i < n; i++) {
+ char c = header.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();
+ packages.add(packageName(export));
+ buffer = new StringBuffer();
+ continue;
+ }
+ }
+ buffer.append(c);
+ }
+ if (buffer.length() != 0) {
+ String export = buffer.toString();
+ packages.add(packageName(export));
+ }
+ return packages;
+ }
+
+ /**
+ * Convert the maven version into OSGi version
+ * @param mavenVersion
+ * @return
+ */
+ static String osgiVersion(String mavenVersion) {
+ ArtifactVersion ver = new OSGIArtifactVersion(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";
+ private static URL findInSystemBundle(String entry) {
+ ClassLoader loader = BundleUtil.class.getClassLoader();
+ return loader == null ? ClassLoader.getSystemResource(entry) : loader.getResource(entry);
+ }
+
+ 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 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;
+ }
+/* doesn't work with Equinox 3.5.0
+ 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 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;
+ }
+
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundlesMetaDataBuildMojo.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundlesMetaDataBuildMojo.java
new file mode 100644
index 0000000000..8d6cfd9aa4
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundlesMetaDataBuildMojo.java
@@ -0,0 +1,1465 @@
+/*
+ * 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.maven.bundle.plugin;
+
+import static org.apache.tuscany.maven.bundle.plugin.BundleUtil.write;
+import static org.osgi.framework.Constants.BUNDLE_CLASSPATH;
+import static org.osgi.framework.Constants.BUNDLE_VERSION;
+import static org.osgi.framework.Constants.RESOLUTION_DIRECTIVE;
+import static org.osgi.framework.Constants.RESOLUTION_OPTIONAL;
+import static org.osgi.framework.Constants.VISIBILITY_DIRECTIVE;
+import static org.osgi.framework.Constants.VISIBILITY_REEXPORT;
+
+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.Arrays;
+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.TreeSet;
+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.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.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+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;
+import org.apache.maven.shared.dependency.tree.DependencyNode;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
+import org.apache.maven.shared.dependency.tree.traversal.CollectingDependencyNodeVisitor;
+import org.osgi.framework.Constants;
+
+/**
+ * A maven plugin that generates meta-data for groups of Tuscany jars from the distribution's
+ * modules directory. The meta-data group jars either as mnaifest jars, ant filesets or
+ * simply as human readable lists of jars
+ *
+ * @version $Rev: 929729 $ $Date: 2010-03-31 22:52:37 +0100 (Wed, 31 Mar 2010) $
+ * @goal generate-meta-data
+ * @phase generate-resources
+ * @requiresDependencyResolution test
+ * @description Generate a modules directory containing OSGi bundles for all the project's module dependencies.
+ */
+public class BundlesMetaDataBuildMojo extends AbstractMojo {
+
+ private static final String GATEWAY_BUNDLE = "org.apache.tuscany.sca.gateway";
+
+ /**
+ * 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;
+
+ /**
+ * The artifact collector to use.
+ *
+ * @component
+ * @required
+ * @readonly
+ */
+ private ArtifactCollector artifactCollector;
+
+ /**
+ * The dependency tree builder to use.
+ *
+ * @component
+ * @required
+ * @readonly
+ */
+ private DependencyTreeBuilder dependencyTreeBuilder;
+
+
+ /**
+ * 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 = false;
+
+ /**
+ * Set to true to generate the contents of the modules directory.
+ *
+ * @parameter default-value="true"
+ */
+ private boolean generateModules = false;
+
+ /**
+ * Set to true to generate a PDE target platform configuration.
+ *
+ * @parameter default-value="true"
+ */
+ private boolean generateTargetPlatform = true;
+
+ /**
+ * Expand non-tuscany bundles as a folder
+ * @parameter default-value="false"
+ */
+ private boolean expandThirdPartyBundle = false;
+
+ /**
+ * 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 gateway bundle tuscany-gateway-<version>.jar that handles split packages and META-INF/services.
+ *
+ * @parameter default-value="true"
+ */
+ private boolean generateGatewayBundle;
+
+ /**
+ * @parameter default-value="false"
+ */
+ private boolean gatewayReexport;
+
+ /**
+ * 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;
+
+ /**
+ * Generate an aggregated OSGi bundle for each feature
+ * @parameter default-value="false"
+ */
+ private boolean generateAggregatedBundle = false;
+
+ /**
+ * @parameter default-value="true"
+ */
+ private boolean generateBundleStart = true;
+
+ /**
+ * @parameter default-value="true"
+ */
+ private boolean includeConflictingDepedencies = 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="jar,bundle"
+ */
+ private String artifactTypes;
+
+ /**
+ * @parameter default-value="true"
+ */
+ private boolean generateAntScript = true;
+
+ /**
+ * @parameter default-value="true"
+ */
+ private boolean generateWhichJars = true;
+
+ /**
+ * @parameter
+ */
+ private ArtifactAggregation[] artifactAggregations;
+
+ /**
+ * @parameter
+ */
+ private ArtifactManifest[] artifactManifests;
+
+ /**
+ * Feature artifact IDs to be processed and included in the features directory
+ * @parameter
+ */
+ private Feature[] features;
+
+ /**
+ * Extension artifact IDs to be processed and included in the extensions directory
+ * @parameter
+ */
+ private Extension[] extensions;
+
+ /**
+ * Inserts a generic Eclipse-BuddyPolicy header into generated artifacts manifests
+ * @parameter
+ */
+ private String eclipseBuddyPolicy = null;
+
+ private static final String XML_PI = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+ private static final String ASL_HEADER =
+ "<!--" + "\n * Licensed to the Apache Software Foundation (ASF) under one"
+ + "\n * or more contributor license agreements. See the NOTICE file"
+ + "\n * distributed with this work for additional information"
+ + "\n * regarding copyright ownership. The ASF licenses this file"
+ + "\n * to you under the Apache License, Version 2.0 (the"
+ + "\n * \"License\"); you may not use this file except in compliance"
+ + "\n * with the License. You may obtain a copy of the License at"
+ + "\n * "
+ + "\n * http://www.apache.org/licenses/LICENSE-2.0"
+ + "\n * "
+ + "\n * Unless required by applicable law or agreed to in writing,"
+ + "\n * software distributed under the License is distributed on an"
+ + "\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY"
+ + "\n * KIND, either express or implied. See the License for the"
+ + "\n * specific language governing permissions and limitations"
+ + "\n * under the License."
+ + "\n-->";
+
+ /**
+ * Group the artifacts by distribution poms
+ */
+ private class ProjectSet {
+ // Distribution projects
+ private Map<String, MavenProject> projects;
+ // Key: the pom artifact id
+ // Value: the names for the artifacts
+ private Map<String, Set<String>> nameMap = new HashMap<String, Set<String>>();
+
+ private Map<String, String> artifactToNameMap = new HashMap<String, String>();
+
+ public ProjectSet(List<MavenProject> projects) {
+ super();
+ this.projects = new HashMap<String, MavenProject>();
+ 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 &&
+ artifact.getArtifactId().equals(p.getArtifactId())){
+ a = p.getArtifact();
+ }
+ if (a != null) {
+ if (a.getScope() != null &&
+ (a.getScope().equals("provided") ||
+ a.getScope().equals("test") ||
+ a.getScope().equals("system"))){
+ // ignore the artifact
+ } else {
+ Set<String> names = nameMap.get(p.getArtifactId());
+ if (names == null) {
+ names = new TreeSet<String>();
+ nameMap.put(p.getArtifactId(), names);
+ }
+ names.add(name);
+ }
+ }
+ }
+ artifactToNameMap.put(key, name);
+ }
+ }
+
+ private Manifest findManifest(Artifact artifact) throws IOException {
+ if (artifactManifests == null) {
+ return null;
+ }
+ for (ArtifactManifest m : artifactManifests) {
+ if (m.matches(artifact)) {
+ File mf = m.getManifestFile();
+ if (mf != null) {
+ FileInputStream is = new FileInputStream(mf);
+ Manifest manifest = new Manifest(is);
+ is.close();
+ getLog().info("MANIFEST.MF found for " + artifact + " (" + mf + ")");
+ return manifest;
+ } else {
+ getLog().info("Overriding the manifest for " + artifact);
+ Manifest manifest = BundleUtil.getManifest(artifact.getFile());
+ Set<File> jarFiles = new HashSet<File>();
+ jarFiles.add(artifact.getFile());
+ String symbolicName = BundleUtil.getBundleSymbolicName(manifest);
+ if (symbolicName == null) {
+ // Not a bundle
+ continue;
+ }
+ String version = manifest.getMainAttributes().getValue(BUNDLE_VERSION);
+ manifest =
+ BundleUtil.libraryManifest(jarFiles,
+ symbolicName,
+ symbolicName,
+ version,
+ null,
+ this.eclipseBuddyPolicy,
+ this.executionEnvironment);
+ // Remove it as it will be added later on
+ manifest.getMainAttributes().remove(new Attributes.Name(BUNDLE_CLASSPATH));
+ return manifest;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the artifact filter to use when resolving the dependency tree.
+ *
+ * @return the artifact filter
+ */
+ private ArtifactFilter createResolvingArtifactFilter(String scope) {
+ ArtifactFilter filter;
+
+ // filter scope
+ if (scope != null) {
+ getLog().debug("+ Resolving dependency tree for scope '" + scope + "'");
+
+ filter = new ScopeArtifactFilter(scope);
+ } else {
+ filter = null;
+ }
+
+ return filter;
+ }
+
+ public void execute() throws MojoExecutionException {
+ Log log = getLog();
+
+ Set<Artifact> artifacts = null;
+ if (includeConflictingDepedencies) {
+ try {
+ artifacts = getDependencyArtifacts(project);
+ } catch (Exception e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+ } else {
+ artifacts = project.getArtifacts();
+ }
+
+ try {
+
+ // Create the target directory
+ File root;
+ if (targetDirectory == null) {
+ root = new File(project.getBuild().getDirectory(), "plugins/");
+ } else {
+ root = targetDirectory;
+ }
+
+ if (generateModules){
+ root.mkdirs();
+ }
+
+ // Build sets of exclude directories and included/excluded/groupids
+ Set<String> excludedFileNames = new HashSet<String>();
+ if (excludeDirectories != null) {
+ for (File f : excludeDirectories) {
+ if (f.isDirectory()) {
+ for (String n : f.list()) {
+ excludedFileNames.add(n);
+ }
+ }
+ }
+ }
+ Set<String> includedGroupIds = new HashSet<String>();
+ if (includeGroupIds != null) {
+ for (String g : includeGroupIds) {
+ includedGroupIds.add(g);
+ }
+ }
+ Set<String> excludedGroupIds = new HashSet<String>();
+ if (excludeGroupIds != null) {
+ for (String g : excludeGroupIds) {
+ excludedGroupIds.add(g);
+ }
+ }
+
+ // Find all the distribution poms
+ List<MavenProject> poms = new ArrayList<MavenProject>();
+
+ 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());
+ }
+ }
+ }
+
+ if (features != null){
+ // find all the features that require processing
+ for (Object o : project.getArtifacts()) {
+ Artifact artifact = (Artifact)o;
+ for(Feature feature : features){
+ if (artifact.getGroupId().equals(feature.getGroupId()) &&
+ artifact.getArtifactId().equals(feature.getArtifactId())) {
+ log.info("Feature: " + artifact);
+ MavenProject pomProject = buildProject(artifact);
+ poms.add(pomProject);
+ }
+ }
+ }
+
+ // force useDistributionName to true so that subsequent generation works
+ useDistributionName = true;
+ }
+
+ if (extensions != null){
+ // find all the extensions that require processing
+ // TODO - putting them in features dir for the time being
+ for (Object o : project.getArtifacts()) {
+ Artifact artifact = (Artifact)o;
+ for(Extension extension : extensions) {
+ if (artifact.getGroupId().equals(extension.getGroupId()) &&
+ artifact.getArtifactId().equals(extension.getArtifactId())) {
+ log.info("Extension: " + artifact);
+ MavenProject pomProject = buildProject(artifact);
+ poms.add(pomProject);
+ }
+ }
+ }
+
+ // force useDistributionName to true so that subsequent generation works
+ useDistributionName = true;
+ }
+
+ // If no features have been specified assume that the current
+ // project defines the feature
+ if (poms.size() == 0){
+ poms.add(project);
+ }
+
+ // Process all the dependency artifacts
+ ProjectSet bundleSymbolicNames = new ProjectSet(poms);
+ ProjectSet bundleLocations = new ProjectSet(poms);
+ ProjectSet jarNames = new ProjectSet(poms);
+ ProjectSet serviceProviders = new ProjectSet(poms);
+
+ for (Artifact artifact: artifacts) {
+
+ log.info("Processing artifact: " + artifact);
+
+ // 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;
+ }
+
+ if (artifactTypes == null) {
+ artifactTypes = "jar,bundle";
+ }
+ String types[] = artifactTypes.trim().split("( |\t|\n|\r|\f|,)+");
+ Set<String> typeSet = new HashSet<String>(Arrays.asList(types));
+
+ // Only consider JAR and WAR files
+ if (!typeSet.contains(artifact.getType())) {
+ log.debug("Artifact with unknown type is skipped: " + artifact);
+ 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);
+ }
+
+ Manifest customizedMF = findManifest(artifact);
+
+ // Get the bundle name if the artifact is an OSGi bundle
+ Manifest mf = null;
+ String bundleName = null;
+ try {
+ mf = BundleUtil.getManifest(artifactFile);
+ bundleName = BundleUtil.getBundleSymbolicName(mf);
+ } catch (IOException e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+
+ if (bundleName != null && customizedMF == null) {
+
+ // Exclude artifact if its file name is excluded
+ if (excludedFileNames.contains(artifactFile.getName())) {
+ log.debug("Artifact file is excluded: " + artifact);
+ continue;
+ }
+
+ if (generateModules){
+ // Copy an OSGi bundle as is
+ log.info("Adding OSGi bundle artifact: " + artifact);
+ }
+
+ if (!expandThirdPartyBundle || artifact.getGroupId().startsWith("org.apache.tuscany.sca")
+ || artifact.getGroupId().startsWith("org.eclipse")) {
+ if (generateModules){
+ copyFile(artifactFile, root);
+ }
+ bundleSymbolicNames.add(artifact, bundleName);
+ bundleLocations.add(artifact, artifactFile.getName());
+ jarNames.add(artifact, artifactFile.getName());
+ if (isServiceProvider(mf)) {
+ serviceProviders.add(artifact, bundleName);
+ }
+ } else {
+ // Expanding the bundle into a folder
+
+ setBundleClassPath(mf, artifactFile);
+
+ int index = artifactFile.getName().lastIndexOf('.');
+ String dirName = artifactFile.getName().substring(0, index);
+ File dir = new File(root, dirName);
+ if (generateModules){
+ 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, bundleName);
+ bundleLocations.add(artifact, dir.getName());
+ jarNames.add(artifact, dirName + "/" + artifactFile.getName());
+ if (isServiceProvider(mf)) {
+ serviceProviders.add(artifact, bundleName);
+ }
+ }
+
+ } 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;
+ }
+
+ if (generateModules){
+ // Copy a WAR as is
+ log.info("Adding WAR artifact: " + artifact);
+ copyFile(artifactFile, root);
+ }
+ } else {
+
+ int index = artifactFile.getName().lastIndexOf('.');
+ String dirName = artifactFile.getName().substring(0, index);
+ 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 manifest directory
+ File file = new File(dir, "META-INF");
+ if (generateModules){
+ // Create a bundle directory for a non-OSGi JAR
+ log.info("Adding JAR artifact: " + artifact);
+
+ file.mkdirs();
+ }
+
+ String symbolicName = null;
+ if (customizedMF == null) {
+ String version = BundleUtil.osgiVersion(artifact.getVersion());
+
+ Set<File> jarFiles = new HashSet<File>();
+ jarFiles.add(artifactFile);
+ symbolicName = (artifact.getGroupId() + "." + artifact.getArtifactId());
+ if (generateModules){
+ mf =
+ BundleUtil.libraryManifest(jarFiles,
+ symbolicName,
+ symbolicName,
+ version,
+ null,
+ this.eclipseBuddyPolicy,
+ this.executionEnvironment);
+
+ file = new File(file, "MANIFEST.MF");
+ FileOutputStream fos = new FileOutputStream(file);
+ write(mf, fos);
+ fos.close();
+ log.info("Writing generated manifest for: " + artifact + " to " + file);
+ }
+ } else {
+ mf = customizedMF;
+ symbolicName = BundleUtil.getBundleSymbolicName(mf);
+ if (symbolicName == null) {
+ throw new MojoExecutionException("Invalid customized MANIFEST.MF for " + artifact);
+ }
+ setBundleClassPath(mf, artifactFile);
+
+ // re-find the custom MF file and copy it
+ // I can't get the manifest file from the manifest itself
+ // the Manifest read/write operation seems to be filtering
+ // out some entries that I've added manually????
+ File artifactManifest = null;
+
+ if (artifactManifests != null) {
+ for (ArtifactManifest m : artifactManifests) {
+ if (m.matches(artifact)) {
+ artifactManifest = m.getManifestFile();
+ break;
+ }
+ }
+ }
+
+ if (generateModules){
+ file = new File(file, "MANIFEST.MF");
+
+ if (artifactManifest != null){
+ log.info("Copying: " + artifactManifest + " to " + file);
+ copyManifest(artifactManifest, file);
+ } else {
+ FileOutputStream fos = new FileOutputStream(file);
+ write(mf, fos);
+ fos.close();
+ log.info("Writing generated manifest for: " + artifact + " to " + file);
+ }
+ }
+ }
+
+ if (generateModules){
+ copyFile(artifactFile, dir);
+ }
+
+ bundleSymbolicNames.add(artifact, symbolicName);
+ bundleLocations.add(artifact, dir.getName());
+ jarNames.add(artifact, dirName + "/" + artifactFile.getName());
+ if (isServiceProvider(mf)) {
+ serviceProviders.add(artifact, symbolicName);
+ }
+ }
+ }
+
+
+ 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<File> jarFiles = new HashSet<File>();
+ 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,
+ this.eclipseBuddyPolicy,
+ this.executionEnvironment);
+ 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();
+ log.info("Written aggregate manifest");
+ bundleSymbolicNames.add(artifact, symbolicName);
+ bundleLocations.add(artifact, dir.getName());
+ if (isServiceProvider(mf)) {
+ serviceProviders.add(artifact, symbolicName);
+ }
+ }
+ }
+
+
+ if (generateGatewayBundle) {
+ generateGatewayBundle(serviceProviders);
+ }
+
+ /*
+ if (useDistributionName) {
+ bundleLocations.nameMap.remove(project.getArtifactId());
+ jarNames.nameMap.remove(project.getArtifactId());
+ bundleSymbolicNames.nameMap.remove(project.getArtifactId());
+ }
+ */
+
+ // 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);
+ }
+
+ if (generateWhichJars) {
+ generateWhichJars(jarNames, root, log);
+ }
+
+ if (generateAggregatedBundle) {
+ generateAggregatedBundles(bundleLocations, root, log);
+ }
+
+ } catch (Exception e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+
+ }
+
+ private Set<Artifact> getDependencyArtifacts(MavenProject project) throws DependencyTreeBuilderException,
+ ArtifactResolutionException, ArtifactNotFoundException {
+ Log log = getLog();
+ Set<Artifact> artifacts = new HashSet<Artifact>();
+ ArtifactFilter artifactFilter = createResolvingArtifactFilter(Artifact.SCOPE_RUNTIME);
+
+ // TODO: note that filter does not get applied due to MNG-3236
+
+ DependencyNode rootNode =
+ dependencyTreeBuilder.buildDependencyTree(project,
+ local,
+ factory,
+ artifactMetadataSource,
+ artifactFilter,
+ artifactCollector);
+ CollectingDependencyNodeVisitor visitor = new CollectingDependencyNodeVisitor();
+ rootNode.accept(visitor);
+
+ // Add included artifacts
+ for (Object node : visitor.getNodes()) {
+ DependencyNode depNode = (DependencyNode)node;
+ int state = depNode.getState();
+ if (state == DependencyNode.INCLUDED ) {
+ Artifact artifact = depNode.getArtifact();
+ // Exclude the project artifact to avoid offline resolution failure
+ if (!artifact.equals(project.getArtifact())) {
+ resolver.resolve(artifact, remoteRepos, local);
+ artifacts.add(artifact);
+ }
+ }
+ }
+ // Scan for newer versions that are omitted
+ for (Object node : visitor.getNodes()) {
+ DependencyNode depNode = (DependencyNode)node;
+ int state = depNode.getState();
+ if (state == DependencyNode.OMITTED_FOR_CONFLICT) {
+ Artifact artifact = depNode.getArtifact();
+ resolver.resolve(artifact, remoteRepos, local);
+ if (state == DependencyNode.OMITTED_FOR_CONFLICT) {
+ Artifact related = depNode.getRelatedArtifact();
+ if (log.isDebugEnabled()) {
+ log.debug("Dependency node: " + depNode);
+ }
+ // Compare the version
+ ArtifactVersion v1 = new DefaultArtifactVersion(artifact.getVersion());
+ ArtifactVersion v2 = new DefaultArtifactVersion(related.getVersion());
+ if (v1.compareTo(v2) > 0) {
+ // Only add newer version if it is omitted for conflict
+ if (artifacts.add(artifact)) {
+ log.info("Dependency node added: " + depNode);
+ }
+ }
+ }
+ }
+ }
+ return artifacts;
+ }
+
+ private static boolean isServiceProvider(Manifest mf) {
+ if (mf != null) {
+ String export = (String)mf.getMainAttributes().getValue(Constants.EXPORT_PACKAGE);
+ if (export != null && export.contains(BundleUtil.META_INF_SERVICES)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Generate a gateway bundle that aggregate other bundles to handle split packages
+ * @param bundleSymbolicNames
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void generateGatewayBundle(ProjectSet bundleSymbolicNames) throws FileNotFoundException, IOException {
+ Manifest manifest = new Manifest();
+ Attributes attrs = manifest.getMainAttributes();
+ StringBuffer requireBundle = new StringBuffer();
+ for (String name : new HashSet<String>(bundleSymbolicNames.artifactToNameMap.values())) {
+ requireBundle.append(name).append(";").append(RESOLUTION_DIRECTIVE).append(":=")
+ .append(RESOLUTION_OPTIONAL);
+ if (gatewayReexport) {
+ requireBundle.append(";").append(VISIBILITY_DIRECTIVE).append(":=").append(VISIBILITY_REEXPORT);
+ }
+ requireBundle.append(",");
+ }
+ int len = requireBundle.length();
+ if (len > 0 && requireBundle.charAt(len - 1) == ',') {
+ requireBundle.deleteCharAt(len - 1);
+ attrs.putValue(Constants.REQUIRE_BUNDLE, requireBundle.toString());
+ attrs.putValue("Manifest-Version", "1.0");
+ attrs.putValue("Implementation-Vendor", "The Apache Software Foundation");
+ attrs.putValue("Implementation-Vendor-Id", "org.apache");
+ attrs.putValue(Constants.BUNDLE_VERSION, "2.0.0");
+ attrs.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
+ attrs.putValue(Constants.BUNDLE_SYMBOLICNAME, GATEWAY_BUNDLE);
+ attrs.putValue(Constants.BUNDLE_NAME, "Apache Tuscany SCA Gateway Bundle");
+ attrs.putValue(Constants.BUNDLE_VENDOR, "The Apache Software Foundation");
+ attrs.putValue(Constants.EXPORT_PACKAGE, "META-INF.services");
+ attrs.putValue(Constants.DYNAMICIMPORT_PACKAGE, "*");
+ attrs.putValue(Constants.BUNDLE_ACTIVATIONPOLICY, Constants.ACTIVATION_LAZY);
+ File file = new File(targetDirectory, "tuscany-gateway-" + project.getVersion() + ".jar");
+ getLog().info("Generating gateway bundle: " + file.getAbsolutePath());
+ FileOutputStream fos = new FileOutputStream(file);
+ JarOutputStream jos = new JarOutputStream(fos, manifest);
+ addFileToJar(jos, "META-INF/LICENSE", getClass().getResource("LICENSE.txt"));
+ addFileToJar(jos, "META-INF/NOTICE", getClass().getResource("NOTICE.txt"));
+ jos.close();
+ }
+ }
+
+ private void setBundleClassPath(Manifest mf, File artifactFile) {
+ // Add the Bundle-ClassPath
+ String cp = mf.getMainAttributes().getValue(BUNDLE_CLASSPATH);
+ if (cp == null) {
+ cp = artifactFile.getName();
+ } else {
+ cp = cp + "," + artifactFile.getName();
+ }
+ mf.getMainAttributes().putValue(BUNDLE_CLASSPATH, cp);
+ }
+
+ private void generateANTPath(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException {
+ for (Map.Entry<String, Set<String>> e : jarNames.nameMap.entrySet()) {
+ Set<String> 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("<project name=\"" + name + "\">");
+ ps.println(" <property name=\"tuscany.manifest\" value=\"" + new File(feature, manifestJarName).getCanonicalPath() + "\"/>");
+ ps.println(" <dirname property=\"" + name + ".basedir\" file=\"${ant.file." + name + "}\"/>");
+ ps.println(" <path id=\"" + name + ".path" + "\">");
+ ps.println(" <fileset dir=\"${" + name + ".basedir}../../../modules\">");
+ for (String jar : jars) {
+ ps.println(" <include name=\"" + jar + "\"/>");
+ }
+ ps.println(" </fileset>");
+ ps.println(" </path>");
+ ps.println("</project>");
+ }
+ }
+
+ private void generateWhichJars(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException {
+ for (Map.Entry<String, Set<String>> e : jarNames.nameMap.entrySet()) {
+ Set<String> jars = e.getValue();
+ File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? trim(e.getKey()) : ""));
+ feature.mkdirs();
+ File whichJarsPath = new File(feature, "which-jars");
+ log.info("Generating Which Jars: " + whichJarsPath.getCanonicalPath());
+ FileOutputStream fos = new FileOutputStream(whichJarsPath);
+ PrintStream ps = new PrintStream(fos);
+
+ ps.println(ASL_HEADER);
+ String name = trim(e.getKey());
+ ps.println("Jars required to enable extension: " + name);
+ ps.println("");
+ for (String jar : jars) {
+ ps.println(jar);
+ }
+ }
+ }
+
+ private void generateManifestJar(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException {
+ for (Map.Entry<String, Set<String>> e : jarNames.nameMap.entrySet()) {
+ MavenProject pom = jarNames.getProject(e.getKey());
+ Set<String> jars = e.getValue();
+ String name = trim(e.getKey());
+ File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? trim(e.getKey()) : ""));
+ feature.mkdirs();
+ String manifestName = name + "-manifest.jar";
+ File mfJar = new File(feature, manifestName);
+ 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<String, Set<String>> e : bundleLocations.nameMap.entrySet()) {
+ Set<String> locations = new HashSet<String>(e.getValue());
+ if (generateGatewayBundle) {
+ locations.add("tuscany-gateway-" + project.getVersion() + ".jar");
+ }
+ 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);
+ int size = locations.size();
+ if (size > 0) {
+ ps.println("osgi.bundles=\\");
+ int count = 0;
+ for (String f : locations) {
+ if (f.startsWith("osgi")) {
+ count++;
+ continue;
+ }
+ ps.print(" ");
+ ps.print(f);
+ // FIXME: We should not add @start for fragments
+ if (generateBundleStart) {
+ ps.print("@:start");
+ }
+ if (count == size - 1) {
+ // Last one
+ ps.println();
+ } else {
+ ps.println(",\\");
+ }
+ count++;
+ }
+ }
+ ps.println("eclipse.ignoreApp=true");
+ // Do not shutdown
+ ps.println("osgi.noShutdown=true");
+ ps.close();
+ }
+ }
+
+ private void generateAggregatedBundles(ProjectSet bundleLocations, File root, Log log) throws Exception {
+ for (Map.Entry<String, Set<String>> e : bundleLocations.nameMap.entrySet()) {
+ Set<String> locations = new HashSet<String>(e.getValue());
+ String featureName = (useDistributionName ? trim(e.getKey()) : "");
+ File feature = new File(root, "../" + featuresName + "/" + featureName);
+// String bundleFileName = "tuscany-bundle-" + featureName + ".jar";
+// if ("".equals(featureName)) {
+// bundleFileName = "tuscany-bundle.jar";
+// }
+ String bundleFileName = "tuscany-bundle.jar";
+ File bundleFile = new File(feature, bundleFileName);
+ log.info("Generating aggregated OSGi bundle: " + bundleFile);
+ File[] files = new File[locations.size()];
+ int i = 0;
+ for (String child : locations) {
+ files[i++] = new File(root, child);
+ }
+ String bundleVersion = "2.0.0";
+ String bundleName = "org.apache.tuscany.sca.bundle";
+
+// String bundleName = "org.apache.tuscany.sca.bundle." + featureName;
+// if ("".equals(featureName)) {
+// bundleName = "org.apache.tuscany.sca.bundle";
+// }
+ BundleAggregatorMojo.aggregateBundles(log, root, files, bundleFile, bundleName, bundleVersion);
+ }
+ }
+
+ private void generatePDETarget(ProjectSet bundleSymbolicNames, File root, Log log) throws FileNotFoundException,
+ IOException {
+ for (Map.Entry<String, Set<String>> e : bundleSymbolicNames.nameMap.entrySet()) {
+ Set<String> bundles = new HashSet<String>(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");
+ }
+ if (generateGatewayBundle) {
+ bundles.add(GATEWAY_BUNDLE);
+ }
+ writeTarget(new PrintStream(targetFile), name, bundles, eclipseFeatures);
+ targetFile.close();
+
+ // Generate the PDE target definition file for PDE 3.5
+ File target35 = new File(feature, "tuscany-pde35.target");
+ log.info("Generating target definition: " + target35.getCanonicalPath());
+ FileOutputStream target35File = new FileOutputStream(target35);
+ writePDE35Target(new PrintStream(target35File), name, bundles, eclipseFeatures);
+ target35File.close();
+
+ }
+ }
+
+ private MavenProject buildProject(Artifact artifact) throws ProjectBuildingException,
+ InvalidDependencyVersionException, ArtifactResolutionException, ArtifactNotFoundException, DependencyTreeBuilderException {
+ 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)));
+ }
+ if (includeConflictingDepedencies) {
+ pomProject.setArtifacts(getDependencyArtifacts(pomProject));
+ } else {
+ 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 copyManifest(File mfFrom, File mfTo) throws FileNotFoundException, IOException {
+ byte[] buf = new byte[4096];
+ FileInputStream in = new FileInputStream(mfFrom);
+ FileOutputStream out = new FileOutputStream(mfTo);
+ 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<String> ids, String[] features) {
+ ps.println(XML_PI);
+ ps.println("<?pde version=\"3.2\"?>");
+ ps.println(ASL_HEADER);
+
+ ps.println("<target name=\"Eclipse Target - " + pom + "\">");
+
+ if (executionEnvironment != null) {
+ ps.println(" <targetJRE>");
+ ps.println(" <execEnv>" + executionEnvironment + "</execEnv>");
+ ps.println(" </targetJRE>");
+ }
+
+ if (useDefaultLocation) {
+ ps.println(" <location useDefault=\"true\"/>");
+ } else {
+ ps.println(" <location path=\"" + targetDirectory + "\"/>");
+ }
+
+ // ps.println("<content useAllPlugins=\"true\">");
+ ps.println(" <content>");
+ ps.println(" <plugins>");
+ for (String id : ids) {
+ ps.println(" <plugin id=\"" + id + "\"/>");
+ }
+ ps.println(" </plugins>");
+ ps.println(" <features>");
+ if (features != null) {
+ for (String f : features) {
+ ps.println(" <feature id=\"" + f + "\"/>");
+ }
+ }
+ ps.println(" </features>");
+ if (useDefaultLocation) {
+ ps.println(" <extraLocations>");
+ // Not sure why the extra path needs to the plugins folder
+ ps.println(" <location path=\"" + targetDirectory + "\"/>");
+ ps.println(" </extraLocations>");
+ }
+ ps.println(" </content>");
+
+ ps.println("</target>");
+
+ }
+
+ private void writePDE35Target(PrintStream ps, String pom, Set<String> ids, String[] features) {
+ ps.println(XML_PI);
+ ps.println("<?pde version=\"3.5\"?>");
+ ps.println(ASL_HEADER);
+
+ ps.println("<target name=\"Eclipse PDE 3.5 Target - " + pom + "\">");
+
+ if (executionEnvironment != null) {
+ ps
+ .println(" <targetJRE path=\"" + "org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"
+ + executionEnvironment
+ + "\"/>");
+ }
+
+ ps.println("<locations>");
+ if (ids.size() > 0) {
+ ps.println(" <location path=\"" + targetDirectory + "\" type=\"Directory\">");
+ ps.println(" <includeBundles>");
+ for (String id : ids) {
+ ps.println(" <plugin id=\"" + id + "\"/>");
+ }
+ ps.println(" </includeBundles>");
+ ps.println(" </location>");
+ }
+
+ /*
+ if (useDefaultLocation) {
+ ps.println(" <location path=\"${eclipse_home}\" type=\"Profile\"/>");
+ }
+ */
+
+ /*
+ if (features != null) {
+ for (String f : features) {
+ ps.println(" <location id=\"" + f + "\" path=\"\" type=\"Feature\"/>");
+ }
+ }
+ */
+
+ ps.println("</locations>");
+ ps.println("</target>");
+
+ }
+
+ private static void writePluginXML(PrintStream ps) {
+ ps.println(XML_PI);
+ ps.println("<?pde version=\"3.2\"?>");
+ ps.println(ASL_HEADER);
+ ps.println("<plugin>");
+ ps.println("<extension point = \"org.eclipse.pde.core.targets\">");
+ ps.println("<target");
+ ps.println("id=\"org.apache.tuscany.sca.target\"");
+ ps.println("name=\"Apache Tuscany Eclipse Target\"");
+ ps.println("path=\"tuscany.target\"/>");
+ ps.println("</extension>");
+ ps.println("</plugin>");
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/Extension.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/Extension.java
new file mode 100644
index 0000000000..dd4a9b502c
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/Extension.java
@@ -0,0 +1,60 @@
+/*
+ * 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.maven.bundle.plugin;
+
+
+public class Extension {
+ 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(Extension extension) {
+ return groupId.equals(extension.getGroupId()) && (artifactId == null || artifactId.equals("")
+ || artifactId.equals("*") || artifactId.equals(extension.getArtifactId()))
+ && (version == null || version.equals("") || version.equals("*") || version.equals(extension.getVersion()));
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/Feature.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/Feature.java
new file mode 100644
index 0000000000..41d3b2dc44
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/Feature.java
@@ -0,0 +1,59 @@
+/*
+ * 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.maven.bundle.plugin;
+
+public class Feature {
+ 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(Feature feature) {
+ return groupId.equals(feature.getGroupId()) && (artifactId == null || artifactId.equals("")
+ || artifactId.equals("*") || artifactId.equals(feature.getArtifactId()))
+ && (version == null || version.equals("") || version.equals("*") || version.equals(feature.getVersion()));
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/HeaderParser.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/HeaderParser.java
new file mode 100644
index 0000000000..c49261e3ff
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/HeaderParser.java
@@ -0,0 +1,331 @@
+/*
+ * 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.maven.bundle.plugin;
+
+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 javax.xml.namespace.QName;
+
+/**
+ * Parser for the service descriptors. The syntax of the service declaration is similar with the OSGi
+ * headers with the following exceptions:
+ * <ul>
+ * <li>Tuscany uses , and ; as the separator for attibutes
+ * <li>Tuscany
+ */
+public class HeaderParser {
+
+ private static final String PATH_SEPARATOR = ","; // OSGi style
+ // private static final String PATH_SEPARATOR = "|";
+
+ private static final String SEGMENT_SEPARATOR = ";"; // OSGi style
+ // private static final String SEGMENT_SEPARATOR = ";,";
+
+ private static final String ATTRIBUTE_SEPARATOR = "=";
+ private static final String DIRECTIVE_SEPARATOR = ":=";
+
+ private static final char QUOTE_CHAR = '"';
+ private static final String QUOTE = "\"";
+
+ // Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2,
+ // path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
+ public static List<HeaderClause> parse(String header) {
+
+ if (header != null) {
+ if (header.length() == 0) {
+ throw new IllegalArgumentException("A header cannot be an empty string.");
+ }
+
+ String[] clauseStrings = parseDelimitedString(header, PATH_SEPARATOR);
+
+ List<HeaderClause> completeList = new ArrayList<HeaderClause>();
+ for (int i = 0; (clauseStrings != null) && (i < clauseStrings.length); i++) {
+ completeList.add(parseClause(clauseStrings[i]));
+ }
+
+ return completeList;
+ }
+
+ return null;
+
+ }
+
+ // Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
+ private static HeaderClause parseClause(String clauseString) throws IllegalArgumentException {
+ // Break string into semi-colon delimited pieces.
+ String[] pieces = parseDelimitedString(clauseString, SEGMENT_SEPARATOR);
+
+ // Count the number of different paths; paths
+ // will not have an '=' in their string. This assumes
+ // that paths come first, before directives and
+ // attributes.
+ int pathCount = 0;
+ for (int pieceIdx = 0; pieceIdx < pieces.length; pieceIdx++) {
+ if (pieces[pieceIdx].indexOf('=') >= 0) {
+ break;
+ }
+ pathCount++;
+ }
+
+ // Create an array of paths.
+ String[] paths = new String[pathCount];
+ System.arraycopy(pieces, 0, paths, 0, pathCount);
+
+ // Parse the directives/attributes.
+ Map<String, String> dirsMap = new HashMap<String, String>();
+ Map<String, String> attrsMap = new HashMap<String, String>();
+ int idx = -1;
+ String sep = null;
+ for (int pieceIdx = pathCount; pieceIdx < pieces.length; pieceIdx++) {
+ // Check if it is a directive.
+ if ((idx = pieces[pieceIdx].indexOf(DIRECTIVE_SEPARATOR)) >= 0) {
+ sep = DIRECTIVE_SEPARATOR;
+ }
+ // Check if it is an attribute.
+ else if ((idx = pieces[pieceIdx].indexOf(ATTRIBUTE_SEPARATOR)) >= 0) {
+ sep = ATTRIBUTE_SEPARATOR;
+ }
+ // It is an error.
+ else {
+ throw new IllegalArgumentException("Not a directive/attribute: " + clauseString);
+ }
+
+ String key = pieces[pieceIdx].substring(0, idx).trim();
+ String value = pieces[pieceIdx].substring(idx + sep.length()).trim();
+
+ // Remove quotes, if value is quoted.
+ if (value.startsWith(QUOTE) && value.endsWith(QUOTE)) {
+ value = value.substring(1, value.length() - 1);
+ }
+
+ // Save the directive/attribute in the appropriate array.
+ if (sep.equals(DIRECTIVE_SEPARATOR)) {
+ // Check for duplicates.
+ if (dirsMap.get(key) != null) {
+ throw new IllegalArgumentException("Duplicate directive: " + key);
+ }
+ dirsMap.put(key, value);
+ } else {
+ // Check for duplicates.
+ if (attrsMap.get(key) != null) {
+ throw new IllegalArgumentException("Duplicate attribute: " + key);
+ }
+ attrsMap.put(key, value);
+ }
+ }
+
+ StringBuffer path = new StringBuffer();
+ for (int i = 0; i < paths.length; i++) {
+ path.append(paths[i]);
+ if (i != paths.length - 1) {
+ path.append(';');
+ }
+ }
+
+ HeaderClause descriptor = new HeaderClause();
+ descriptor.text = clauseString;
+ descriptor.value = path.toString();
+ descriptor.valueComponents = paths;
+ descriptor.attributes = attrsMap;
+ descriptor.directives = dirsMap;
+
+ return descriptor;
+ }
+
+ /**
+ * Parses delimited string and returns an array containing the tokens. This
+ * parser obeys quotes, so the delimiter character will be ignored if it is
+ * inside of a quote. This method assumes that the quote character is not
+ * included in the set of delimiter characters.
+ * @param value the delimited string to parse.
+ * @param delim the characters delimiting the tokens.
+ * @return an array of string tokens or null if there were no tokens.
+ **/
+ private static String[] parseDelimitedString(String value, String delim) {
+ if (value == null) {
+ value = "";
+ }
+
+ List<String> list = new ArrayList<String>();
+
+ int CHAR = 1;
+ int DELIMITER = 2;
+ int STARTQUOTE = 4;
+ int ENDQUOTE = 8;
+
+ StringBuffer sb = new StringBuffer();
+
+ int expecting = (CHAR | DELIMITER | STARTQUOTE);
+
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+
+ boolean isDelimiter = (delim.indexOf(c) >= 0);
+ boolean isQuote = (c == QUOTE_CHAR);
+
+ if (isDelimiter && ((expecting & DELIMITER) > 0)) {
+ list.add(sb.toString().trim());
+ sb.delete(0, sb.length());
+ expecting = (CHAR | DELIMITER | STARTQUOTE);
+ } else if (isQuote && ((expecting & STARTQUOTE) > 0)) {
+ sb.append(c);
+ expecting = CHAR | ENDQUOTE;
+ } else if (isQuote && ((expecting & ENDQUOTE) > 0)) {
+ sb.append(c);
+ expecting = (CHAR | STARTQUOTE | DELIMITER);
+ } else if ((expecting & CHAR) > 0) {
+ sb.append(c);
+ } else {
+ throw new IllegalArgumentException("Invalid delimited string: " + value);
+ }
+ }
+
+ if (sb.length() > 0) {
+ list.add(sb.toString().trim());
+ }
+
+ return (String[])list.toArray(new String[list.size()]);
+ }
+
+ public static class HeaderClause {
+ private String text;
+ private String value;
+ private String[] valueComponents;
+ private Map<String, String> attributes;
+ private Map<String, String> directives;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String[] getValueComponents() {
+ return valueComponents;
+ }
+
+ public void setValueComponents(String[] valueComponents) {
+ this.valueComponents = valueComponents;
+ }
+
+ public Map<String, String> getAttributes() {
+ return attributes;
+ }
+
+ public Map<String, String> getDirectives() {
+ return directives;
+ }
+
+ public String toString() {
+ String text = null;
+ if (text == null) {
+ StringBuffer buf = new StringBuffer();
+ if (value == null) {
+ int start = buf.length();
+ for (int i = 0; i < valueComponents.length; i++) {
+ if (i != valueComponents.length - 1) {
+ buf.append(valueComponents[i]).append(';');
+ } else {
+ buf.append(valueComponents[i]);
+ }
+ }
+ int end = buf.length();
+ if (end > start) {
+ value = buf.substring(start, end);
+ }
+ }
+ buf.append(value);
+ for (Map.Entry<String, String> e : attributes.entrySet()) {
+ buf.append(';').append(e.getKey()).append("=\"").append(e.getValue()).append("\"");
+ }
+ for (Map.Entry<String, String> e : directives.entrySet()) {
+ buf.append(';').append(e.getKey()).append(":=\"").append(e.getValue()).append("\"");
+ }
+ text = buf.toString();
+ }
+ return text;
+ }
+
+ }
+
+ /**
+ * Returns a QName object from a QName expressed as {ns}name
+ * or ns#name.
+ *
+ * @param qname
+ * @return
+ */
+ public static QName getQName(String qname) {
+ if (qname == null) {
+ return null;
+ }
+ qname = qname.trim();
+ if (qname.startsWith("{")) {
+ int h = qname.indexOf('}');
+ if (h != -1) {
+ return new QName(qname.substring(1, h), qname.substring(h + 1));
+ }
+ } else {
+ int h = qname.indexOf('#');
+ if (h != -1) {
+ return new QName(qname.substring(0, h), qname.substring(h + 1));
+ }
+ }
+ return new QName(qname);
+ }
+
+ public static String toHeader(List<HeaderClause> descriptors) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < descriptors.size(); i++) {
+ HeaderClause descriptor = descriptors.get(i);
+ buf.append(descriptor);
+ if (i != descriptors.size() - 1) {
+ buf.append(',');
+ }
+ }
+ return buf.toString();
+ }
+
+ public static String merge(String... headers) {
+ List<HeaderClause> merged = new ArrayList<HeaderClause>();
+ for (String header : headers) {
+ if (header == null || header.length() == 0) {
+ continue;
+ }
+ List<HeaderClause> descriptors = parse(header);
+ merged.addAll(descriptors);
+ }
+ Set<String> values = new HashSet<String>();
+ for (Iterator<HeaderClause> i = merged.iterator(); i.hasNext();) {
+ if (!values.add(i.next().getValue())) {
+ i.remove();
+ }
+ }
+ return toHeader(merged);
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ModuleBundlesBuildMojo.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ModuleBundlesBuildMojo.java
new file mode 100644
index 0000000000..12733181e8
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ModuleBundlesBuildMojo.java
@@ -0,0 +1,1338 @@
+/*
+ * 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.maven.bundle.plugin;
+
+import static org.apache.tuscany.maven.bundle.plugin.BundleUtil.write;
+import static org.osgi.framework.Constants.BUNDLE_CLASSPATH;
+import static org.osgi.framework.Constants.BUNDLE_VERSION;
+import static org.osgi.framework.Constants.RESOLUTION_DIRECTIVE;
+import static org.osgi.framework.Constants.RESOLUTION_OPTIONAL;
+import static org.osgi.framework.Constants.VISIBILITY_DIRECTIVE;
+import static org.osgi.framework.Constants.VISIBILITY_REEXPORT;
+
+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.Arrays;
+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.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.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+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;
+import org.apache.maven.shared.dependency.tree.DependencyNode;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
+import org.apache.maven.shared.dependency.tree.traversal.CollectingDependencyNodeVisitor;
+import org.osgi.framework.Constants;
+
+/**
+ * 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 {
+
+ private static final String GATEWAY_BUNDLE = "org.apache.tuscany.sca.gateway";
+
+ /**
+ * 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;
+
+ /**
+ * The artifact collector to use.
+ *
+ * @component
+ * @required
+ * @readonly
+ */
+ private ArtifactCollector artifactCollector;
+
+ /**
+ * The dependency tree builder to use.
+ *
+ * @component
+ * @required
+ * @readonly
+ */
+ private DependencyTreeBuilder dependencyTreeBuilder;
+
+
+ /**
+ * 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;
+
+ /**
+ * Expand non-tuscany bundles as a folder
+ * @parameter default-value="false"
+ */
+ private boolean expandThirdPartyBundle = false;
+
+ /**
+ * 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 gateway bundle tuscany-gateway-<version>.jar that handles split packages and META-INF/services.
+ *
+ * @parameter default-value="true"
+ */
+ private boolean generateGatewayBundle;
+
+ /**
+ * @parameter default-value="false"
+ */
+ private boolean gatewayReexport;
+
+ /**
+ * 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;
+
+ /**
+ * Generate an aggregated OSGi bundle for each feature
+ * @parameter default-value="false"
+ */
+ private boolean generateAggregatedBundle = false;
+
+ /**
+ * @parameter default-value="true"
+ */
+ private boolean generateBundleStart = true;
+
+ /**
+ * @parameter default-value="true"
+ */
+ private boolean includeConflictingDepedencies = 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="jar,bundle"
+ */
+ private String artifactTypes;
+
+ /**
+ * @parameter default-value="true"
+ */
+ private boolean generateAntScript = true;
+
+ /**
+ * @parameter
+ */
+ private ArtifactAggregation[] artifactAggregations;
+
+ /**
+ * @parameter
+ */
+ private ArtifactManifest[] artifactManifests;
+
+ /**
+ * Inserts a generic Eclipse-BuddyPolicy header into generated artifacts manifests
+ * @parameter
+ */
+ private String eclipseBuddyPolicy = null;
+
+ private static final String XML_PI = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+ private static final String ASL_HEADER =
+ "<!--" + "\n * Licensed to the Apache Software Foundation (ASF) under one"
+ + "\n * or more contributor license agreements. See the NOTICE file"
+ + "\n * distributed with this work for additional information"
+ + "\n * regarding copyright ownership. The ASF licenses this file"
+ + "\n * to you under the Apache License, Version 2.0 (the"
+ + "\n * \"License\"); you may not use this file except in compliance"
+ + "\n * with the License. You may obtain a copy of the License at"
+ + "\n * "
+ + "\n * http://www.apache.org/licenses/LICENSE-2.0"
+ + "\n * "
+ + "\n * Unless required by applicable law or agreed to in writing,"
+ + "\n * software distributed under the License is distributed on an"
+ + "\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY"
+ + "\n * KIND, either express or implied. See the License for the"
+ + "\n * specific language governing permissions and limitations"
+ + "\n * under the License."
+ + "\n-->";
+
+ /**
+ * Group the artifacts by distribution poms
+ */
+ private class ProjectSet {
+ // Distribution projects
+ private Map<String, MavenProject> projects;
+ // Key: the pom artifact id
+ // Value: the names for the artifacts
+ private Map<String, Set<String>> nameMap = new HashMap<String, Set<String>>();
+
+ private Map<String, String> artifactToNameMap = new HashMap<String, String>();
+
+ public ProjectSet(List<MavenProject> projects) {
+ super();
+ this.projects = new HashMap<String, MavenProject>();
+ 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<String> names = nameMap.get(p.getArtifactId());
+ if (names == null) {
+ names = new HashSet<String>();
+ nameMap.put(p.getArtifactId(), names);
+ }
+ names.add(name);
+ }
+ }
+ artifactToNameMap.put(key, name);
+ }
+ }
+
+ private Manifest findManifest(Artifact artifact) throws IOException {
+ if (artifactManifests == null) {
+ return null;
+ }
+ for (ArtifactManifest m : artifactManifests) {
+ if (m.matches(artifact)) {
+ File mf = m.getManifestFile();
+ if (mf != null) {
+ FileInputStream is = new FileInputStream(mf);
+ Manifest manifest = new Manifest(is);
+ is.close();
+ getLog().info("MANIFEST.MF found for " + artifact + " (" + mf + ")");
+ return manifest;
+ } else {
+ getLog().info("Overriding the manifest for " + artifact);
+ Manifest manifest = BundleUtil.getManifest(artifact.getFile());
+ Set<File> jarFiles = new HashSet<File>();
+ jarFiles.add(artifact.getFile());
+ String symbolicName = BundleUtil.getBundleSymbolicName(manifest);
+ if (symbolicName == null) {
+ // Not a bundle
+ continue;
+ }
+ String version = manifest.getMainAttributes().getValue(BUNDLE_VERSION);
+ manifest =
+ BundleUtil.libraryManifest(jarFiles,
+ symbolicName,
+ symbolicName,
+ version,
+ null,
+ this.eclipseBuddyPolicy,
+ this.executionEnvironment);
+ // Remove it as it will be added later on
+ manifest.getMainAttributes().remove(new Attributes.Name(BUNDLE_CLASSPATH));
+ return manifest;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the artifact filter to use when resolving the dependency tree.
+ *
+ * @return the artifact filter
+ */
+ private ArtifactFilter createResolvingArtifactFilter(String scope) {
+ ArtifactFilter filter;
+
+ // filter scope
+ if (scope != null) {
+ getLog().debug("+ Resolving dependency tree for scope '" + scope + "'");
+
+ filter = new ScopeArtifactFilter(scope);
+ } else {
+ filter = null;
+ }
+
+ return filter;
+ }
+
+ public void execute() throws MojoExecutionException {
+ Log log = getLog();
+
+ Set<Artifact> artifacts = null;
+ if (includeConflictingDepedencies) {
+ try {
+ artifacts = getDependencyArtifacts(project);
+ } catch (Exception e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+ } else {
+ artifacts = project.getArtifacts();
+ }
+
+ 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<String> excludedFileNames = new HashSet<String>();
+ if (excludeDirectories != null) {
+ for (File f : excludeDirectories) {
+ if (f.isDirectory()) {
+ for (String n : f.list()) {
+ excludedFileNames.add(n);
+ }
+ }
+ }
+ }
+ Set<String> includedGroupIds = new HashSet<String>();
+ if (includeGroupIds != null) {
+ for (String g : includeGroupIds) {
+ includedGroupIds.add(g);
+ }
+ }
+ Set<String> excludedGroupIds = new HashSet<String>();
+ if (excludeGroupIds != null) {
+ for (String g : excludeGroupIds) {
+ excludedGroupIds.add(g);
+ }
+ }
+
+ // Find all the distribution poms
+ List<MavenProject> poms = new ArrayList<MavenProject>();
+ 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);
+ ProjectSet serviceProviders = new ProjectSet(poms);
+
+ for (Artifact artifact: artifacts) {
+
+ // 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;
+ }
+
+ if (artifactTypes == null) {
+ artifactTypes = "jar,bundle";
+ }
+ String types[] = artifactTypes.trim().split("( |\t|\n|\r|\f|,)+");
+ Set<String> typeSet = new HashSet<String>(Arrays.asList(types));
+
+ // Only consider JAR and WAR files
+ if (!typeSet.contains(artifact.getType())) {
+ log.debug("Artifact with unknown type is skipped: " + artifact);
+ 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);
+ }
+
+ Manifest customizedMF = findManifest(artifact);
+
+ // Get the bundle name if the artifact is an OSGi bundle
+ Manifest mf = null;
+ String bundleName = null;
+ try {
+ mf = BundleUtil.getManifest(artifactFile);
+ bundleName = BundleUtil.getBundleSymbolicName(mf);
+ } catch (IOException e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+
+ if (bundleName != null && customizedMF == 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);
+
+ if (!expandThirdPartyBundle || artifact.getGroupId().startsWith("org.apache.tuscany.sca")
+ || artifact.getGroupId().startsWith("org.eclipse")) {
+ copyFile(artifactFile, root);
+ bundleSymbolicNames.add(artifact, bundleName);
+ bundleLocations.add(artifact, artifactFile.getName());
+ jarNames.add(artifact, artifactFile.getName());
+ if (isServiceProvider(mf)) {
+ serviceProviders.add(artifact, bundleName);
+ }
+ } else {
+ // Expanding the bundle into a folder
+
+ setBundleClassPath(mf, artifactFile);
+
+ int index = artifactFile.getName().lastIndexOf('.');
+ String dirName = artifactFile.getName().substring(0, index);
+ File dir = new File(root, dirName);
+
+ 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, bundleName);
+ bundleLocations.add(artifact, dir.getName());
+ jarNames.add(artifact, dirName + "/" + artifactFile.getName());
+ if (isServiceProvider(mf)) {
+ serviceProviders.add(artifact, bundleName);
+ }
+ }
+
+ } 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 {
+
+ int index = artifactFile.getName().lastIndexOf('.');
+ String dirName = artifactFile.getName().substring(0, index);
+ 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);
+
+ // create manifest directory
+ File file = new File(dir, "META-INF");
+ file.mkdirs();
+
+ String symbolicName = null;
+ if (customizedMF == null) {
+ String version = BundleUtil.osgiVersion(artifact.getVersion());
+
+ Set<File> jarFiles = new HashSet<File>();
+ jarFiles.add(artifactFile);
+ symbolicName = (artifact.getGroupId() + "." + artifact.getArtifactId());
+ mf =
+ BundleUtil.libraryManifest(jarFiles,
+ symbolicName,
+ symbolicName,
+ version,
+ null,
+ this.eclipseBuddyPolicy,
+ this.executionEnvironment);
+
+ file = new File(file, "MANIFEST.MF");
+ FileOutputStream fos = new FileOutputStream(file);
+ write(mf, fos);
+ fos.close();
+ log.info("Writing generated manifest for: " + artifact + " to " + file);
+ } else {
+ mf = customizedMF;
+ symbolicName = BundleUtil.getBundleSymbolicName(mf);
+ if (symbolicName == null) {
+ throw new MojoExecutionException("Invalid customized MANIFEST.MF for " + artifact);
+ }
+ setBundleClassPath(mf, artifactFile);
+
+ // re-find the custom MF file and copy it
+ // I can't get the manifest file from the manifest itself
+ // the Manifest read/write operation seems to be filtering
+ // out some entries that I've added manually????
+ File artifactManifest = null;
+
+ if (artifactManifests != null) {
+ for (ArtifactManifest m : artifactManifests) {
+ if (m.matches(artifact)) {
+ artifactManifest = m.getManifestFile();
+ break;
+ }
+ }
+ }
+
+ file = new File(file, "MANIFEST.MF");
+
+ if (artifactManifest != null){
+ log.info("Copying: " + artifactManifest + " to " + file);
+ copyManifest(artifactManifest, file);
+ } else {
+ FileOutputStream fos = new FileOutputStream(file);
+ write(mf, fos);
+ fos.close();
+ log.info("Writing generated manifest for: " + artifact + " to " + file);
+ }
+ }
+
+ copyFile(artifactFile, dir);
+ bundleSymbolicNames.add(artifact, symbolicName);
+ bundleLocations.add(artifact, dir.getName());
+ jarNames.add(artifact, dirName + "/" + artifactFile.getName());
+ if (isServiceProvider(mf)) {
+ serviceProviders.add(artifact, symbolicName);
+ }
+ }
+ }
+
+ 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<File> jarFiles = new HashSet<File>();
+ 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,
+ this.eclipseBuddyPolicy,
+ this.executionEnvironment);
+ 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();
+ log.info("Written aggregate manifest");
+ bundleSymbolicNames.add(artifact, symbolicName);
+ bundleLocations.add(artifact, dir.getName());
+ if (isServiceProvider(mf)) {
+ serviceProviders.add(artifact, symbolicName);
+ }
+ }
+ }
+
+ if (generateGatewayBundle) {
+ generateGatewayBundle(serviceProviders);
+ }
+
+ /*
+ if (useDistributionName) {
+ bundleLocations.nameMap.remove(project.getArtifactId());
+ jarNames.nameMap.remove(project.getArtifactId());
+ bundleSymbolicNames.nameMap.remove(project.getArtifactId());
+ }
+ */
+
+ // 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);
+ }
+
+ if (generateAggregatedBundle) {
+ generateAggregatedBundles(bundleLocations, root, log);
+ }
+
+ } catch (Exception e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
+
+ }
+
+ private Set<Artifact> getDependencyArtifacts(MavenProject project) throws DependencyTreeBuilderException,
+ ArtifactResolutionException, ArtifactNotFoundException {
+ Log log = getLog();
+ Set<Artifact> artifacts = new HashSet<Artifact>();
+ ArtifactFilter artifactFilter = createResolvingArtifactFilter(Artifact.SCOPE_RUNTIME);
+
+ // TODO: note that filter does not get applied due to MNG-3236
+
+ DependencyNode rootNode =
+ dependencyTreeBuilder.buildDependencyTree(project,
+ local,
+ factory,
+ artifactMetadataSource,
+ artifactFilter,
+ artifactCollector);
+ CollectingDependencyNodeVisitor visitor = new CollectingDependencyNodeVisitor();
+ rootNode.accept(visitor);
+
+ // Add included artifacts
+ for (Object node : visitor.getNodes()) {
+ DependencyNode depNode = (DependencyNode)node;
+ int state = depNode.getState();
+ if (state == DependencyNode.INCLUDED ) {
+ Artifact artifact = depNode.getArtifact();
+ // Exclude the project artifact to avoid offline resolution failure
+ if (!artifact.equals(project.getArtifact())) {
+ resolver.resolve(artifact, remoteRepos, local);
+ artifacts.add(artifact);
+ }
+ }
+ }
+ // Scan for newer versions that are omitted
+ for (Object node : visitor.getNodes()) {
+ DependencyNode depNode = (DependencyNode)node;
+ int state = depNode.getState();
+ if (state == DependencyNode.OMITTED_FOR_CONFLICT) {
+ Artifact artifact = depNode.getArtifact();
+ resolver.resolve(artifact, remoteRepos, local);
+ if (state == DependencyNode.OMITTED_FOR_CONFLICT) {
+ Artifact related = depNode.getRelatedArtifact();
+ if (log.isDebugEnabled()) {
+ log.debug("Dependency node: " + depNode);
+ }
+ // Compare the version
+ ArtifactVersion v1 = new DefaultArtifactVersion(artifact.getVersion());
+ ArtifactVersion v2 = new DefaultArtifactVersion(related.getVersion());
+ if (v1.compareTo(v2) > 0) {
+ // Only add newer version if it is omitted for conflict
+ if (artifacts.add(artifact)) {
+ log.info("Dependency node added: " + depNode);
+ }
+ }
+ }
+ }
+ }
+ return artifacts;
+ }
+
+ private static boolean isServiceProvider(Manifest mf) {
+ if (mf != null) {
+ String export = (String)mf.getMainAttributes().getValue(Constants.EXPORT_PACKAGE);
+ if (export != null && export.contains(BundleUtil.META_INF_SERVICES)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Generate a gateway bundle that aggregate other bundles to handle split packages
+ * @param bundleSymbolicNames
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void generateGatewayBundle(ProjectSet bundleSymbolicNames) throws FileNotFoundException, IOException {
+ Manifest manifest = new Manifest();
+ Attributes attrs = manifest.getMainAttributes();
+ StringBuffer requireBundle = new StringBuffer();
+ for (String name : new HashSet<String>(bundleSymbolicNames.artifactToNameMap.values())) {
+ requireBundle.append(name).append(";").append(RESOLUTION_DIRECTIVE).append(":=")
+ .append(RESOLUTION_OPTIONAL);
+ if (gatewayReexport) {
+ requireBundle.append(";").append(VISIBILITY_DIRECTIVE).append(":=").append(VISIBILITY_REEXPORT);
+ }
+ requireBundle.append(",");
+ }
+ int len = requireBundle.length();
+ if (len > 0 && requireBundle.charAt(len - 1) == ',') {
+ requireBundle.deleteCharAt(len - 1);
+ attrs.putValue(Constants.REQUIRE_BUNDLE, requireBundle.toString());
+ attrs.putValue("Manifest-Version", "1.0");
+ attrs.putValue("Implementation-Vendor", "The Apache Software Foundation");
+ attrs.putValue("Implementation-Vendor-Id", "org.apache");
+ attrs.putValue(Constants.BUNDLE_VERSION, "2.0.0");
+ attrs.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
+ attrs.putValue(Constants.BUNDLE_SYMBOLICNAME, GATEWAY_BUNDLE);
+ attrs.putValue(Constants.BUNDLE_NAME, "Apache Tuscany SCA Gateway Bundle");
+ attrs.putValue(Constants.BUNDLE_VENDOR, "The Apache Software Foundation");
+ attrs.putValue(Constants.EXPORT_PACKAGE, "META-INF.services");
+ attrs.putValue(Constants.DYNAMICIMPORT_PACKAGE, "*");
+ attrs.putValue(Constants.BUNDLE_ACTIVATIONPOLICY, Constants.ACTIVATION_LAZY);
+ File file = new File(targetDirectory, "tuscany-gateway-" + project.getVersion() + ".jar");
+ getLog().info("Generating gateway bundle: " + file.getAbsolutePath());
+ FileOutputStream fos = new FileOutputStream(file);
+ JarOutputStream jos = new JarOutputStream(fos, manifest);
+ addFileToJar(jos, "META-INF/LICENSE", getClass().getResource("LICENSE.txt"));
+ addFileToJar(jos, "META-INF/NOTICE", getClass().getResource("NOTICE.txt"));
+ jos.close();
+ }
+ }
+
+ private void setBundleClassPath(Manifest mf, File artifactFile) {
+ // Add the Bundle-ClassPath
+ String cp = mf.getMainAttributes().getValue(BUNDLE_CLASSPATH);
+ if (cp == null) {
+ cp = artifactFile.getName();
+ } else {
+ cp = cp + "," + artifactFile.getName();
+ }
+ mf.getMainAttributes().putValue(BUNDLE_CLASSPATH, cp);
+ }
+
+ private void generateANTPath(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException {
+ for (Map.Entry<String, Set<String>> e : jarNames.nameMap.entrySet()) {
+ Set<String> 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("<project name=\"tuscany." + name + "\">");
+ ps.println(" <property name=\"tuscany.distro\" value=\"" + name + "\"/>");
+ ps.println(" <property name=\"tuscany.manifest\" value=\"" + new File(feature, manifestJarName)
+ .getCanonicalPath()
+ + "\"/>");
+ ps.println(" <path id=\"" + "tuscany.path" + "\">");
+ ps.println(" <fileset dir=\"" + root.getCanonicalPath() + "\">");
+ for (String jar : jars) {
+ ps.println(" <include name=\"" + jar + "\"/>");
+ }
+ ps.println(" </fileset>");
+ ps.println(" </path>");
+ ps.println("</project>");
+ }
+ }
+
+ private void generateManifestJar(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException {
+ for (Map.Entry<String, Set<String>> e : jarNames.nameMap.entrySet()) {
+ MavenProject pom = jarNames.getProject(e.getKey());
+ Set<String> 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<String, Set<String>> e : bundleLocations.nameMap.entrySet()) {
+ Set<String> locations = new HashSet<String>(e.getValue());
+ if (generateGatewayBundle) {
+ locations.add("tuscany-gateway-" + project.getVersion() + ".jar");
+ }
+ 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);
+ int size = locations.size();
+ if (size > 0) {
+ ps.println("osgi.bundles=\\");
+ int count = 0;
+ for (String f : locations) {
+ if (f.startsWith("osgi")) {
+ count++;
+ continue;
+ }
+ ps.print(" ");
+ ps.print(f);
+ // FIXME: We should not add @start for fragments
+ if (generateBundleStart) {
+ ps.print("@:start");
+ }
+ if (count == size - 1) {
+ // Last one
+ ps.println();
+ } else {
+ ps.println(",\\");
+ }
+ count++;
+ }
+ }
+ ps.println("eclipse.ignoreApp=true");
+ // Do not shutdown
+ ps.println("osgi.noShutdown=true");
+ ps.close();
+ }
+ }
+
+ private void generateAggregatedBundles(ProjectSet bundleLocations, File root, Log log) throws Exception {
+ for (Map.Entry<String, Set<String>> e : bundleLocations.nameMap.entrySet()) {
+ Set<String> locations = new HashSet<String>(e.getValue());
+ String featureName = (useDistributionName ? trim(e.getKey()) : "");
+ File feature = new File(root, "../" + featuresName + "/" + featureName);
+// String bundleFileName = "tuscany-bundle-" + featureName + ".jar";
+// if ("".equals(featureName)) {
+// bundleFileName = "tuscany-bundle.jar";
+// }
+ String bundleFileName = "tuscany-bundle.jar";
+ File bundleFile = new File(feature, bundleFileName);
+ log.info("Generating aggregated OSGi bundle: " + bundleFile);
+ File[] files = new File[locations.size()];
+ int i = 0;
+ for (String child : locations) {
+ files[i++] = new File(root, child);
+ }
+ String bundleVersion = "2.0.0";
+ String bundleName = "org.apache.tuscany.sca.bundle";
+
+// String bundleName = "org.apache.tuscany.sca.bundle." + featureName;
+// if ("".equals(featureName)) {
+// bundleName = "org.apache.tuscany.sca.bundle";
+// }
+ BundleAggregatorMojo.aggregateBundles(log, root, files, bundleFile, bundleName, bundleVersion);
+ }
+ }
+
+ private void generatePDETarget(ProjectSet bundleSymbolicNames, File root, Log log) throws FileNotFoundException,
+ IOException {
+ for (Map.Entry<String, Set<String>> e : bundleSymbolicNames.nameMap.entrySet()) {
+ Set<String> bundles = new HashSet<String>(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");
+ }
+ if (generateGatewayBundle) {
+ bundles.add(GATEWAY_BUNDLE);
+ }
+ writeTarget(new PrintStream(targetFile), name, bundles, eclipseFeatures);
+ targetFile.close();
+
+ // Generate the PDE target definition file for PDE 3.5
+ File target35 = new File(feature, "tuscany-pde35.target");
+ log.info("Generating target definition: " + target35.getCanonicalPath());
+ FileOutputStream target35File = new FileOutputStream(target35);
+ writePDE35Target(new PrintStream(target35File), name, bundles, eclipseFeatures);
+ target35File.close();
+
+ }
+ }
+
+ private MavenProject buildProject(Artifact artifact) throws ProjectBuildingException,
+ InvalidDependencyVersionException, ArtifactResolutionException, ArtifactNotFoundException, DependencyTreeBuilderException {
+ 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)));
+ }
+ if (includeConflictingDepedencies) {
+ pomProject.setArtifacts(getDependencyArtifacts(pomProject));
+ } else {
+ 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 copyManifest(File mfFrom, File mfTo) throws FileNotFoundException, IOException {
+ byte[] buf = new byte[4096];
+ FileInputStream in = new FileInputStream(mfFrom);
+ FileOutputStream out = new FileOutputStream(mfTo);
+ 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<String> ids, String[] features) {
+ ps.println(XML_PI);
+ ps.println("<?pde version=\"3.2\"?>");
+ ps.println(ASL_HEADER);
+
+ ps.println("<target name=\"Eclipse Target - " + pom + "\">");
+
+ if (executionEnvironment != null) {
+ ps.println(" <targetJRE>");
+ ps.println(" <execEnv>" + executionEnvironment + "</execEnv>");
+ ps.println(" </targetJRE>");
+ }
+
+ if (useDefaultLocation) {
+ ps.println(" <location useDefault=\"true\"/>");
+ } else {
+ ps.println(" <location path=\"" + targetDirectory + "\"/>");
+ }
+
+ // ps.println("<content useAllPlugins=\"true\">");
+ ps.println(" <content>");
+ ps.println(" <plugins>");
+ for (String id : ids) {
+ ps.println(" <plugin id=\"" + id + "\"/>");
+ }
+ ps.println(" </plugins>");
+ ps.println(" <features>");
+ if (features != null) {
+ for (String f : features) {
+ ps.println(" <feature id=\"" + f + "\"/>");
+ }
+ }
+ ps.println(" </features>");
+ if (useDefaultLocation) {
+ ps.println(" <extraLocations>");
+ // Not sure why the extra path needs to the plugins folder
+ ps.println(" <location path=\"" + targetDirectory + "\"/>");
+ ps.println(" </extraLocations>");
+ }
+ ps.println(" </content>");
+
+ ps.println("</target>");
+
+ }
+
+ private void writePDE35Target(PrintStream ps, String pom, Set<String> ids, String[] features) {
+ ps.println(XML_PI);
+ ps.println("<?pde version=\"3.5\"?>");
+ ps.println(ASL_HEADER);
+
+ ps.println("<target name=\"Eclipse PDE 3.5 Target - " + pom + "\">");
+
+ if (executionEnvironment != null) {
+ ps
+ .println(" <targetJRE path=\"" + "org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"
+ + executionEnvironment
+ + "\"/>");
+ }
+
+ ps.println("<locations>");
+ if (ids.size() > 0) {
+ ps.println(" <location path=\"" + targetDirectory + "\" type=\"Directory\">");
+ ps.println(" <includeBundles>");
+ for (String id : ids) {
+ ps.println(" <plugin id=\"" + id + "\"/>");
+ }
+ ps.println(" </includeBundles>");
+ ps.println(" </location>");
+ }
+
+ /*
+ if (useDefaultLocation) {
+ ps.println(" <location path=\"${eclipse_home}\" type=\"Profile\"/>");
+ }
+ */
+
+ /*
+ if (features != null) {
+ for (String f : features) {
+ ps.println(" <location id=\"" + f + "\" path=\"\" type=\"Feature\"/>");
+ }
+ }
+ */
+
+ ps.println("</locations>");
+ ps.println("</target>");
+
+ }
+
+ private static void writePluginXML(PrintStream ps) {
+ ps.println(XML_PI);
+ ps.println("<?pde version=\"3.2\"?>");
+ ps.println(ASL_HEADER);
+ ps.println("<plugin>");
+ ps.println("<extension point = \"org.eclipse.pde.core.targets\">");
+ ps.println("<target");
+ ps.println("id=\"org.apache.tuscany.sca.target\"");
+ ps.println("name=\"Apache Tuscany Eclipse Target\"");
+ ps.println("path=\"tuscany.target\"/>");
+ ps.println("</extension>");
+ ps.println("</plugin>");
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/OSGIArtifactVersion.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/OSGIArtifactVersion.java
new file mode 100644
index 0000000000..d87ae0cb9f
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/OSGIArtifactVersion.java
@@ -0,0 +1,219 @@
+/*
+ * 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.maven.bundle.plugin;
+
+import java.util.StringTokenizer;
+
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+
+public class OSGIArtifactVersion implements ArtifactVersion {
+ private Integer buildNumber;
+
+ private Integer incrementalVersion;
+
+ private Integer majorVersion;
+
+ private Integer minorVersion;
+
+ private String qualifier;
+
+ private String unparsed;
+
+ public OSGIArtifactVersion(String version) {
+ parseVersion(version);
+ }
+
+ public int compareTo(Object o) {
+ ArtifactVersion otherVersion = (ArtifactVersion)o;
+
+ int result = getMajorVersion() - otherVersion.getMajorVersion();
+ if (result == 0) {
+ result = getMinorVersion() - otherVersion.getMinorVersion();
+ }
+ if (result == 0) {
+ result = getIncrementalVersion() - otherVersion.getIncrementalVersion();
+ }
+ if (result == 0) {
+ if (this.qualifier != null) {
+ String otherQualifier = otherVersion.getQualifier();
+
+ if (otherQualifier != null) {
+ if ((this.qualifier.length() > otherQualifier.length()) && this.qualifier
+ .startsWith(otherQualifier)) {
+ // here, the longer one that otherwise match is
+ // considered older
+ result = -1;
+ } else if ((this.qualifier.length() < otherQualifier.length()) && otherQualifier
+ .startsWith(this.qualifier)) {
+ // here, the longer one that otherwise match is
+ // considered older
+ result = 1;
+ } else {
+ result = this.qualifier.compareTo(otherQualifier);
+ }
+ } else {
+ // otherVersion has no qualifier but we do - that's newer
+ result = -1;
+ }
+ } else if (otherVersion.getQualifier() != null) {
+ // otherVersion has a qualifier but we don't, we're newer
+ result = 1;
+ } else {
+ result = getBuildNumber() - otherVersion.getBuildNumber();
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (false == (other instanceof ArtifactVersion)) {
+ return false;
+ }
+
+ return 0 == compareTo(other);
+ }
+
+ public int getBuildNumber() {
+ return this.buildNumber != null ? this.buildNumber.intValue() : 0;
+ }
+
+ public int getIncrementalVersion() {
+ return this.incrementalVersion != null ? this.incrementalVersion.intValue() : 0;
+ }
+
+ public int getMajorVersion() {
+ return this.majorVersion != null ? this.majorVersion.intValue() : 0;
+ }
+
+ public int getMinorVersion() {
+ return this.minorVersion != null ? this.minorVersion.intValue() : 0;
+ }
+
+ public String getQualifier() {
+ return this.qualifier;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1229;
+
+ result = 1223 * result + getMajorVersion();
+ result = 1223 * result + getMinorVersion();
+ result = 1223 * result + getIncrementalVersion();
+ result = 1223 * result + getBuildNumber();
+
+ if (null != getQualifier()) {
+ result = 1223 * result + getQualifier().hashCode();
+ }
+
+ return result;
+ }
+
+ public final void parseVersion(String version) {
+ this.unparsed = version;
+
+ int index = version.indexOf("-");
+
+ String part1;
+ String part2 = null;
+
+ if (index < 0) {
+ part1 = version;
+ } else {
+ part1 = version.substring(0, index);
+ part2 = version.substring(index + 1);
+ }
+
+ if (part2 != null) {
+ try {
+ if ((part2.length() == 1) || !part2.startsWith("0")) {
+ this.buildNumber = Integer.valueOf(part2);
+ } else {
+ this.qualifier = part2;
+ }
+ } catch (NumberFormatException e) {
+ this.qualifier = part2;
+ }
+ }
+
+ if ((part1.indexOf(".") < 0) && !part1.startsWith("0")) {
+ try {
+ this.majorVersion = Integer.valueOf(part1);
+ } catch (NumberFormatException e) {
+ // qualifier is the whole version, including "-"
+ this.qualifier = version;
+ this.buildNumber = null;
+ }
+ } else {
+ StringTokenizer tok = new StringTokenizer(part1, ".");
+
+ String s;
+
+ if (tok.hasMoreTokens()) {
+ s = tok.nextToken();
+ try {
+ this.majorVersion = Integer.valueOf(s);
+
+ if (tok.hasMoreTokens()) {
+ s = tok.nextToken();
+ try {
+ this.minorVersion = Integer.valueOf(s);
+ if (tok.hasMoreTokens()) {
+
+ s = tok.nextToken();
+ try {
+ this.incrementalVersion = Integer.valueOf(s);
+
+ } catch (NumberFormatException e) {
+ this.qualifier = s;
+ }
+ }
+ } catch (NumberFormatException e) {
+ this.qualifier = s;
+ }
+ }
+ } catch (NumberFormatException e) {
+ this.qualifier = s;
+ }
+ }
+
+ if (tok.hasMoreTokens()) {
+ StringBuffer qualifier = new StringBuffer(this.qualifier != null ? this.qualifier : "");
+ qualifier.append(tok.nextToken());
+ while (tok.hasMoreTokens()) {
+ qualifier.append("_");
+ qualifier.append(tok.nextToken());
+ }
+
+ this.qualifier = qualifier.toString();
+ }
+
+ }
+ }
+
+ @Override
+ public String toString() {
+ return this.unparsed;
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ThirdPartyBundleBuildMojo.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/bundle/plugin/ThirdPartyBundleBuildMojo.java
new file mode 100644
index 0000000000..880f1379e0
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/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.maven.bundle.plugin;
+
+import static org.apache.tuscany.maven.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<File> jarFiles = new HashSet<File>();
+ 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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java
new file mode 100644
index 0000000000..6fc8295a4e
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/AbstractIdeSupportMojo.java
@@ -0,0 +1,1150 @@
+/*
+ * 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.maven.plugin.eclipse;
+
+import java.io.File;
+import java.io.FileInputStream;
+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.Set;
+import java.util.TreeSet;
+import java.util.jar.Manifest;
+
+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.ArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.execution.RuntimeInformation;
+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.eclipse.Messages;
+import org.apache.maven.plugin.ide.IdeDependency;
+import org.apache.maven.plugin.ide.IdeUtils;
+import org.apache.maven.project.MavenProject;
+import org.apache.tuscany.maven.bundle.plugin.BundleUtil;
+import org.codehaus.plexus.logging.LogEnabled;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * Abstract base plugin which takes care of the common stuff usually needed by maven IDE plugins. A plugin extending
+ * AbstractIdeSupportMojo should implement the <code>setup()</code> and <code>writeConfiguration()</code> methods, plus
+ * the getters needed to get the various configuration flags and required components. The lifecycle:
+ *
+ * <pre>
+ * *** 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
+ * </pre>
+ *
+ * @author Fabrizio Giustina
+ * @version $Id: AbstractIdeSupportMojo.java 727620 2008-12-18 02:35:18Z baerrach $
+ */
+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;
+
+ /**
+ * 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;
+
+ /**
+ * The runtime information for Maven, used to retrieve Maven's version number.
+ *
+ * @component
+ */
+ private RuntimeInformation runtimeInformation;
+
+ /**
+ * 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 <code>true</code>
+ * remote repositories are checked for sources: in order to avoid repeated check for unavailable source archives, a
+ * status cache is mantained. To reset this cache run <code>mvn eclipse:remove-cache</code>, or use the
+ * <code>forceRecheck</code> option.
+ *
+ * @parameter expression="${downloadSources}"
+ */
+ protected boolean downloadSources;
+
+ /**
+ * Enables/disables the downloading of javadoc attachments. Defaults to false. When this flag is <code>true</code>
+ * remote repositories are checked for javadocs: in order to avoid repeated check for unavailable javadoc archives,
+ * a status cache is mantained. To reset this cache run <code>mvn eclipse:remove-cache</code>, or use the
+ * <code>forceRecheck</code> option.
+ *
+ * @parameter expression="${downloadJavadocs}"
+ */
+ protected boolean downloadJavadocs;
+
+ /**
+ * Enables/disables the rechecking of the remote repository for downloading source/javadoc attachments. Defaults to
+ * false. When this flag is <code>true</code> and the source or javadoc attachment has a status cache to indicate
+ * that it is not available, then the remote repository will be rechecked for a source or javadoc attachment and the
+ * status cache updated to reflect the new state.
+ *
+ * @parameter expression="${forceRecheck}"
+ */
+ protected boolean forceRecheck;
+
+ /**
+ * Plexus logger needed for debugging manual artifact resolution.
+ */
+ protected Logger logger;
+
+ /**
+ * Getter for <code>artifactMetadataSource</code>.
+ *
+ * @return Returns the artifactMetadataSource.
+ */
+ public ArtifactMetadataSource getArtifactMetadataSource()
+ {
+ return artifactMetadataSource;
+ }
+
+ /**
+ * Setter for <code>artifactMetadataSource</code>.
+ *
+ * @param artifactMetadataSource The artifactMetadataSource to set.
+ */
+ public void setArtifactMetadataSource( ArtifactMetadataSource artifactMetadataSource )
+ {
+ this.artifactMetadataSource = artifactMetadataSource;
+ }
+
+ /**
+ * Getter for <code>project</code>.
+ *
+ * @return Returns the project.
+ */
+ public MavenProject getProject()
+ {
+ return project;
+ }
+
+ /**
+ * Setter for <code>project</code>.
+ *
+ * @param project The project to set.
+ */
+ public void setProject( MavenProject project )
+ {
+ this.project = project;
+ }
+
+ /**
+ * Getter for <code>reactorProjects</code>.
+ *
+ * @return Returns the reactorProjects.
+ */
+ public List getReactorProjects()
+ {
+ return reactorProjects;
+ }
+
+ /**
+ * Setter for <code>reactorProjects</code>.
+ *
+ * @param reactorProjects The reactorProjects to set.
+ */
+ public void setReactorProjects( List reactorProjects )
+ {
+ this.reactorProjects = reactorProjects;
+ }
+
+ /**
+ * Getter for <code>remoteArtifactRepositories</code>.
+ *
+ * @return Returns the remoteArtifactRepositories.
+ */
+ public List getRemoteArtifactRepositories()
+ {
+ return remoteArtifactRepositories;
+ }
+
+ /**
+ * Setter for <code>remoteArtifactRepositories</code>.
+ *
+ * @param remoteArtifactRepositories The remoteArtifactRepositories to set.
+ */
+ public void setRemoteArtifactRepositories( List remoteArtifactRepositories )
+ {
+ this.remoteArtifactRepositories = remoteArtifactRepositories;
+ }
+
+ /**
+ * Getter for <code>artifactFactory</code>.
+ *
+ * @return Returns the artifactFactory.
+ */
+ public ArtifactFactory getArtifactFactory()
+ {
+ return artifactFactory;
+ }
+
+ /**
+ * Setter for <code>artifactFactory</code>.
+ *
+ * @param artifactFactory The artifactFactory to set.
+ */
+ public void setArtifactFactory( ArtifactFactory artifactFactory )
+ {
+ this.artifactFactory = artifactFactory;
+ }
+
+ /**
+ * Getter for <code>artifactResolver</code>.
+ *
+ * @return Returns the artifactResolver.
+ */
+ public ArtifactResolver getArtifactResolver()
+ {
+ return artifactResolver;
+ }
+
+ /**
+ * Setter for <code>artifactResolver</code>.
+ *
+ * @param artifactResolver The artifactResolver to set.
+ */
+ public void setArtifactResolver( ArtifactResolver artifactResolver )
+ {
+ this.artifactResolver = artifactResolver;
+ }
+
+ /**
+ * Getter for <code>executedProject</code>.
+ *
+ * @return Returns the executedProject.
+ */
+ public MavenProject getExecutedProject()
+ {
+ return executedProject;
+ }
+
+ /**
+ * Setter for <code>executedProject</code>.
+ *
+ * @param executedProject The executedProject to set.
+ */
+ public void setExecutedProject( MavenProject executedProject )
+ {
+ this.executedProject = executedProject;
+ }
+
+ /**
+ * Getter for <code>localRepository</code>.
+ *
+ * @return Returns the localRepository.
+ */
+ public ArtifactRepository getLocalRepository()
+ {
+ return localRepository;
+ }
+
+ /**
+ * Setter for <code>localRepository</code>.
+ *
+ * @param localRepository The localRepository to set.
+ */
+ public void setLocalRepository( ArtifactRepository localRepository )
+ {
+ this.localRepository = localRepository;
+ }
+
+ /**
+ * Getter for <code>downloadJavadocs</code>.
+ *
+ * @return Returns the downloadJavadocs.
+ */
+ public boolean getDownloadJavadocs()
+ {
+ return downloadJavadocs;
+ }
+
+ /**
+ * Setter for <code>downloadJavadocs</code>.
+ *
+ * @param downloadJavadoc The downloadJavadocs to set.
+ */
+ public void setDownloadJavadocs( boolean downloadJavadoc )
+ {
+ downloadJavadocs = downloadJavadoc;
+ }
+
+ /**
+ * Getter for <code>downloadSources</code>.
+ *
+ * @return Returns the downloadSources.
+ */
+ public boolean getDownloadSources()
+ {
+ return downloadSources;
+ }
+
+ /**
+ * Setter for <code>downloadSources</code>.
+ *
+ * @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 <code>false</code> if projects available in a reactor build should be considered normal dependencies,
+ * <code>true</code> if referenced project will be linked and not need artifact resolution.
+ *
+ * @return <code>true</code> 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 <code>true</code> if execution should continue or <code>false</code> 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 <code>IdeDependency</code> 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();
+ Set<String> imported = Collections.emptySet();
+ try {
+ imported = BundleUtil.getImportedPackages(project.getBasedir());
+ } catch (IOException e1) {
+ throw new MojoExecutionException(e1.getMessage(), e1);
+ }
+ 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( "AbstractIdeSupportMojo.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( "AbstractIdeSupportMojo.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( "AbstractIdeSupportMojo.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
+ if ("pom".equals(art.getType())) {
+ continue;
+ }
+ File artifactFile = art.getFile();
+ MavenProject reactorProject = getReactorProject(art);
+ if (reactorProject != null) {
+ artifactFile = reactorProject.getBasedir();
+ }
+ boolean isOsgiBundle = false;
+ String osgiSymbolicName = null;
+ try {
+ osgiSymbolicName = BundleUtil.getBundleSymbolicName(artifactFile);
+ } catch (IOException e) {
+ getLog().error("Unable to read jar manifest from " + artifactFile, e);
+ }
+ 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 );
+ } else {
+ // Check this compile dependency is an OSGi package supplier
+ if (!imported.isEmpty()) {
+ Set<String> exported = Collections.emptySet();
+ try {
+ exported = BundleUtil.getExportedPackages(artifactFile);
+ } catch (IOException e) {
+ getLog().error("Unable to read jar manifest from " + art.getFile(), e);
+ }
+ boolean matched = false;
+ for (String p : imported) {
+ if (exported.contains(p)) {
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ dependencies.add(dep);
+ } else {
+ getLog()
+ .debug("Compile dependency is skipped as it is added through OSGi dependency: " + art);
+ }
+ } else {
+ 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 <code>resolved</code> 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(
+ "AbstractIdeSupportMojo.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 <code>true</code> if the artifact is produced by a reactor projectart.
+ */
+ protected boolean isAvailableAsAReactorProject( Artifact artifact )
+ {
+ return getReactorProject( artifact ) != null;
+ }
+
+ /**
+ * Checks the list of reactor projects to see if the artifact is included.
+ *
+ * @param artifact the artifact to check if it is in the reactor
+ * @return the reactor project or null if it is not in the reactor
+ */
+ protected MavenProject getReactorProject( 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 reactorProject;
+ }
+ else
+ {
+ getLog().info(
+ "Artifact "
+ + artifact.getId()
+ + " already available as a reactor project, but with different version. Expected: "
+ + artifact.getVersion() + ", found: " + reactorProject.getVersion() );
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @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( "AbstractIdeSupportMojo.unabletoparseversion", new Object[] { //$NON-NLS-1$
+ projectId, d.getVersion(),
+ d.getManagementKey(), e.getMessage() } ),
+ e );
+ }
+ }
+ }
+ else
+ {
+ map = Collections.EMPTY_MAP;
+ }
+ return map;
+ }
+
+ /**
+ * Resolve source artifacts and download them if <code>downloadSources</code> is <code>true</code>. Source and
+ * javadocs artifacts will be attached to the <code>IdeDependency</code> Resolve source and javadoc artifacts. The
+ * resolved artifacts will be downloaded based on the <code>downloadSources</code> and <code>downloadJavadocs</code>
+ * attributes. Source and
+ *
+ * @param deps resolved dependencies
+ */
+ private void resolveSourceAndJavadocArtifacts( IdeDependency[] deps )
+ {
+ final List missingSources =
+ resolveDependenciesWithClassifier( deps, "sources", getDownloadSources() );
+ missingSourceDependencies.addAll( missingSources );
+
+ final List missingJavadocs =
+ resolveDependenciesWithClassifier( deps, "javadoc", getDownloadJavadocs() );
+ missingJavadocDependencies.addAll( missingJavadocs );
+ }
+
+ /**
+ * Resolve the required artifacts for each of the dependency. <code>sources</code> or <code>javadoc</code> artifacts
+ * (depending on the <code>classifier</code>) are attached to the dependency.
+ *
+ * @param deps resolved dependencies
+ * @param inClassifier the classifier we are looking for (either <code>sources</code> or <code>javadoc</code>)
+ * @param includeRemoteRepositories flag whether we should search remote repositories for the artifacts or not
+ * @return the list of dependencies for which the required artifact was not found
+ */
+ private List resolveDependenciesWithClassifier( IdeDependency[] deps, String inClassifier,
+ boolean includeRemoteRepositories )
+ {
+ 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 );
+ }
+
+ Artifact baseArtifact =
+ artifactFactory.createArtifactWithClassifier( dependency.getGroupId(), dependency.getArtifactId(),
+ dependency.getVersion(), dependency.getType(),
+ dependency.getClassifier() );
+ baseArtifact =
+ IdeUtils.resolveArtifact( artifactResolver, baseArtifact, remoteRepos, localRepository, getLog() );
+ if (!baseArtifact.isResolved()) {
+ // base artifact does not exist - no point checking for javadoc/sources
+ continue;
+ }
+
+ Artifact artifact =
+ IdeUtils.createArtifactWithClassifier( dependency.getGroupId(), dependency.getArtifactId(),
+ dependency.getVersion(), dependency.getClassifier(),
+ inClassifier, artifactFactory );
+ File notAvailableMarkerFile = IdeUtils.getNotAvailableMarkerFile( localRepository, artifact );
+
+ if (forceRecheck && notAvailableMarkerFile.exists()) {
+ if (!notAvailableMarkerFile.delete()) {
+ getLog().warn( Messages.getString( "AbstractIdeSupportMojo.unabletodeletenotavailablemarkerfile", notAvailableMarkerFile ) );
+ }
+ }
+
+ if ( !notAvailableMarkerFile.exists() )
+ {
+ artifact =
+ IdeUtils.resolveArtifact( artifactResolver, artifact, remoteRepos, localRepository, getLog() );
+ if ( artifact.isResolved() )
+ {
+ if ( "sources".equals( inClassifier ) )
+ {
+ dependency.setSourceAttachment( artifact.getFile() );
+ }
+ else if ( "javadoc".equals( inClassifier ) )
+ {
+ dependency.setJavadocAttachment( artifact.getFile() );
+ }
+ }
+ else
+ {
+ if ( includeRemoteRepositories )
+ {
+ try
+ {
+ notAvailableMarkerFile.createNewFile();
+ getLog().debug( Messages.getString( "AbstractIdeSupportMojo.creatednotavailablemarkerfile", notAvailableMarkerFile ) );
+ }
+ catch ( IOException e )
+ {
+ getLog().warn( Messages.getString( "AbstractIdeSupportMojo.failedtocreatenotavailablemarkerfile",
+ notAvailableMarkerFile ) );
+ }
+ }
+ // 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( "AbstractIdeSupportMojo.sourcesnotavailable" ) ); //$NON-NLS-1$
+ }
+ else
+ {
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.sourcesnotdownloaded" ) ); //$NON-NLS-1$
+ }
+
+ for ( Iterator it = missingSourceDependencies.iterator(); it.hasNext(); )
+ {
+ IdeDependency art = (IdeDependency) it.next();
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.sourcesmissingitem", art.getId() ) ); //$NON-NLS-1$
+ }
+ msg.append( "\n" ); //$NON-NLS-1$
+ }
+
+ if ( !missingJavadocDependencies.isEmpty() )
+ {
+ if ( getDownloadJavadocs() )
+ {
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.javadocnotavailable" ) ); //$NON-NLS-1$
+ }
+ else
+ {
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.javadocnotdownloaded" ) ); //$NON-NLS-1$
+ }
+
+ for ( Iterator it = missingJavadocDependencies.iterator(); it.hasNext(); )
+ {
+ IdeDependency art = (IdeDependency) it.next();
+ msg.append( Messages.getString( "AbstractIdeSupportMojo.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 );
+ }
+
+ /**
+ * Checks whether the currently running Maven satisfies the specified version (range).
+ *
+ * @param version The version range to test for, must not be <code>null</code>.
+ * @return <code>true</code> if the current Maven version matches the specified version range, <code>false</code>
+ * otherwise.
+ */
+ protected boolean isMavenVersion( String version )
+ {
+ try
+ {
+ VersionRange versionRange = VersionRange.createFromVersionSpec( version );
+ ArtifactVersion mavenVersion = runtimeInformation.getApplicationVersion();
+ return versionRange.containsVersion( mavenVersion );
+ }
+ catch ( InvalidVersionSpecificationException e )
+ {
+ throw new IllegalArgumentException( e.getMessage() );
+ }
+ }
+
+ // [rfeng]
+ 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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseClasspathWriter.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseClasspathWriter.java
new file mode 100644
index 0000000000..3fec54ba35
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseClasspathWriter.java
@@ -0,0 +1,635 @@
+/*
+ * 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.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.Messages;
+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 <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
+ * @author <a href="mailto:kenney@neonics.com">Kenney Westerhof</a>
+ * @author <a href="mailto:fgiust@apache.org">Fabrizio Giustina</a>
+ * @version $Id: EclipseClasspathWriter.java 750073 2009-03-04 16:55:01Z aheritier $
+ */
+public class EclipseClasspathWriter
+ extends AbstractEclipseWriter
+{
+
+ /**
+ *
+ */
+ private static final String ORG_ECLIPSE_AJDT_INPATH = "org.eclipse.ajdt.inpath";
+
+ /**
+ *
+ */
+ private static final String ORG_ECLIPSE_AJDT_ASPECTPATH = "org.eclipse.ajdt.aspectpath";
+
+ /**
+ *
+ */
+ private static final String NAME = "name";
+
+ /**
+ *
+ */
+ private static final String VALUE = "value";
+
+ /**
+ *
+ */
+ private static final String ATTRIBUTE = "attribute";
+
+ /**
+ *
+ */
+ private static final String ATTRIBUTES = "attributes";
+
+ /**
+ * Eclipse build path variable M2_REPO
+ */
+ protected 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.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<EclipseSourceDir>
+ List specialSources = new ArrayList();
+
+ // Map<String,List<EclipseSourceDir>>
+ Map byOutputDir = new HashMap();
+
+ for ( int j = 0; j < config.getSourceDirs().length; j++ )
+ {
+ EclipseSourceDir dir = config.getSourceDirs()[j];
+
+ // List<EclipseSourceDir>
+ List byOutputDirs = (List) byOutputDir.get( dir.getOutput() );
+ if ( byOutputDirs == null )
+ {
+ // ArrayList<EclipseSourceDir>
+ 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() );
+ }
+
+ String includes = dir.getInclude();
+
+ if ( !dir.isResource() )
+ {
+ // automatically include java files only: eclipse doesn't have the concept of a source only directory so it
+ // will try to include non-java files found in maven source dirs
+ includes = StringUtils.isEmpty( includes ) ? "**/*.java" : includes + "|**/*.java";
+ }
+
+ if ( StringUtils.isNotEmpty( includes ) )
+ {
+ writer.addAttribute( ATTR_INCLUDING, includes );
+ }
+
+ 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();
+
+ }
+
+ /*
+ // 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
+ // <copy> 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",
+ "<project>/"
+ + 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();
+
+ Set addedDependencies = new HashSet();
+ // TODO if (..magic property equals orderDependencies..)
+
+ // ----------------------------------------------------------------------
+ // Java API dependencies that may complete the classpath container so must
+ // be declared BEFORE so that container access rules don't fail
+ // ----------------------------------------------------------------------
+ IdeDependency[] depsToWrite = config.getDepsOrdered();
+ for ( int j = 0; j < depsToWrite.length; j++ )
+ {
+ IdeDependency dep = depsToWrite[j];
+ if ( dep.isJavaApi() )
+ {
+ String depId = getDependencyId( dep );
+ if ( !addedDependencies.contains( depId ) )
+ {
+ addDependency( writer, dep );
+ addedDependencies.add( depId );
+ }
+ }
+ }
+
+ // ----------------------------------------------------------------------
+ // The dependencies
+ // ----------------------------------------------------------------------
+ for ( int j = 0; j < depsToWrite.length; j++ )
+ {
+ IdeDependency dep = depsToWrite[j];
+
+ if ( dep.isAddedToClasspath() )
+ {
+ String depId = getDependencyId( dep );
+ /* avoid duplicates in the classpath for artifacts with different types (like ejbs or test-jars) */
+ if ( !addedDependencies.contains( depId ) )
+ {
+ addDependency( writer, dep );
+ addedDependencies.add( depId );
+ }
+ }
+ }
+
+ // ----------------------------------------------------------------------
+ // 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
+ }
+
+ writer.endElement();
+
+ IOUtil.close( w );
+
+ }
+
+ private String getDependencyId( IdeDependency dep )
+ {
+ String depId =
+ dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getClassifier() + ":" + dep.getVersion();
+
+ if ( dep.isReferencedProject() )
+ {
+ // This dependency will be refered as an eclipse project
+ depId = dep.getEclipseProjectName();
+ }
+ return depId;
+ }
+
+ 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$
+ }
+
+ }
+
+ }
+
+ // Skip aspectj libraries since they are in the container.
+ if ( ( config.getAjdtVersion() != 0 ) && dep.getArtifactId().toLowerCase().startsWith( "aspectj" ) )
+ {
+ return;
+ }
+
+ 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 ( dep.isAjdtDependency() && ( config.getAjdtVersion() >= 1.5 ) )
+ {
+ if ( !attributeElemOpen )
+ {
+ writer.startElement( ATTRIBUTES ); //$NON-NLS-1$
+ attributeElemOpen = true;
+ }
+
+ writer.startElement( ATTRIBUTE ); //$NON-NLS-1$
+ writer.addAttribute( NAME, ORG_ECLIPSE_AJDT_ASPECTPATH ); //$NON-NLS-1$ //$NON-NLS-2$
+ writer.addAttribute( VALUE, Boolean.TRUE.toString() ); //$NON-NLS-1$ //$NON-NLS-2$
+ writer.endElement();
+
+ }
+
+ if ( dep.isAjdtWeaveDependency() && ( config.getAjdtVersion() >= 1.5 ) )
+ {
+ if ( !attributeElemOpen )
+ {
+ writer.startElement( ATTRIBUTES ); //$NON-NLS-1$
+ attributeElemOpen = true;
+ }
+
+ writer.startElement( ATTRIBUTE ); //$NON-NLS-1$
+ writer.addAttribute( NAME, ORG_ECLIPSE_AJDT_INPATH ); //$NON-NLS-1$ //$NON-NLS-2$
+ writer.addAttribute( VALUE, Boolean.TRUE.toString() ); //$NON-NLS-1$ //$NON-NLS-2$
+ writer.endElement();
+
+ }
+
+ if ( attributeElemOpen )
+ {
+ writer.endElement();
+ }
+ writer.endElement();
+
+ }
+}
diff --git a/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseCleanMojo.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseCleanMojo.java
new file mode 100644
index 0000000000..397f5e34d6
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseCleanMojo.java
@@ -0,0 +1,208 @@
+/*
+ * 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.maven.plugin.eclipse;
+
+import java.io.File;
+
+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.apache.maven.plugin.ide.IdeUtils;
+
+/**
+ * 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$
+
+ /**
+ * AJDT preferences.
+ */
+ private static final String FILE_AJDT_PREFS = ".settings/org.eclipse.ajdt.ui.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 ) );
+ delete( new File( basedir, FILE_AJDT_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
+ {
+ IdeUtils.delete( f, getLog() );
+ }
+
+ /**
+ * Getter for <code>basedir</code>.
+ *
+ * @return Returns the basedir.
+ */
+ public File getBasedir()
+ {
+ return this.basedir;
+ }
+
+ /**
+ * Setter for <code>basedir</code>.
+ *
+ * @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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipsePlugin.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipsePlugin.java
new file mode 100644
index 0000000000..781bc130d9
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipsePlugin.java
@@ -0,0 +1,1877 @@
+/*
+ * 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.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 org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.handler.ArtifactHandler;
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Plugin;
+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.EclipseAjdtWriter;
+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:
+ * <ul>
+ * <li><code>.project</code> and <code>.classpath</code> files</li>
+ * <li><code>.setting/org.eclipse.jdt.core.prefs</code> with project specific compiler settings</li>
+ * <li>various configuration files for WTP (Web Tools Project), if the parameter <code>wtpversion</code> is set to a
+ * valid version (WTP configuration is not generated by default)</li>
+ * </ul>
+ * If this goal is run on a multiproject root, dependencies between modules will be configured as direct project
+ * dependencies in Eclipse (unless <code>useProjectReferences</code> is set to <code>false</code>).
+ *
+ * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
+ * @author <a href="mailto:fgiust@apache.org">Fabrizio Giustina</a>
+ * @version $Id: EclipsePlugin.java 756392 2009-03-20 09:46:09Z baerrach $
+ * @goal eclipse
+ * @execute phase="generate-resources"
+ */
+public class EclipsePlugin
+ extends AbstractIdeSupportMojo
+{
+ private static final String WEAVE_DEPENDENCY = "weaveDependency";
+
+ private static final String WEAVE_DEPENDENCIES = "weaveDependencies";
+
+ private static final String ASPECT_LIBRARY = "aspectLibrary";
+
+ private static final String ASPECT_LIBRARIES = "aspectLibraries";
+
+ private static final String ASPECT_DIRECTORY = "aspectDirectory";
+
+ private static final String TEST_ASPECT_DIRECTORY = "testAspectDirectory";
+
+ private static final String ASPECTJ_MAVEN_PLUGIN = "aspectj-maven-plugin";
+
+ private static final String ORG_CODEHAUS_MOJO = "org.codehaus.mojo";
+
+ private static final String DEFAULT_TEST_ASPECT_DIRECTORY = "src/test/aspect";
+
+ private static final String DEFAULT_ASPECT_DIRECTORY = "src/main/aspect";
+
+ 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 BUILDER_AJDT_CORE_JAVA = "org.eclipse.ajdt.core.ajbuilder"; //$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$
+
+ private static final String NATURE_AJDT_CORE_JAVA = "org.eclipse.ajdt.ui.ajnature"; //$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 ASPECTJ_RT_CONTAINER = "org.eclipse.ajdt.core.ASPECTJRT_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 <code>org.eclipse.jdt.core.javanature</code> nature plus the
+ * needed WTP natures are added. Natures added using this property <strong>replace</strong> the default list.
+ *
+ * <pre>
+ * &lt;projectnatures&gt;
+ * &lt;projectnature&gt;org.eclipse.jdt.core.javanature&lt;/projectnature&gt;
+ * &lt;projectnature&gt;org.eclipse.wst.common.modulecore.ModuleCoreNature&lt;/projectnature&gt;
+ * &lt;/projectnatures&gt;
+ * </pre>
+ *
+ * @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.
+ *
+ * <pre>
+ * &lt;additionalProjectnatures&gt;
+ * &lt;projectnature&gt;org.springframework.ide.eclipse.core.springnature&lt;/projectnature&gt;
+ * &lt;/additionalProjectnatures&gt;
+ * </pre>
+ *
+ * @parameter
+ */
+ private List additionalProjectnatures;
+
+ /**
+ * List of eclipse project facets to be added to the default ones.
+ *
+ * <pre>
+ * &lt;additionalProjectFacets&gt;
+ * &lt;jst.jsf&gt;1.1&lt;jst.jsf/&gt;
+ * &lt;/additionalProjectFacets&gt;
+ * </pre>
+ *
+ * @parameter
+ */
+ private Map additionalProjectFacets;
+
+ /**
+ * List of eclipse build commands. By default the <code>org.eclipse.jdt.core.javabuilder</code> 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 <code>additionalBuildCommands</code> parameter for
+ * that. Configuration example: Old style:
+ *
+ * <pre>
+ * &lt;buildcommands&gt;
+ * &lt;buildcommand&gt;org.eclipse.wst.common.modulecore.ComponentStructuralBuilder&lt;/buildcommand&gt;
+ * &lt;buildcommand&gt;org.eclipse.jdt.core.javabuilder&lt;/buildcommand&gt;
+ * &lt;buildcommand&gt;org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver&lt;/buildcommand&gt;
+ * &lt;/buildcommands&gt;
+ * </pre>
+ *
+ * For new style, see <code>additionalBuildCommands</code>.
+ *
+ * @parameter
+ */
+ private List buildcommands;
+
+ /**
+ * List of eclipse build commands to be added to the default ones. Old style:
+ *
+ * <pre>
+ * &lt;additionalBuildcommands&gt;
+ * &lt;buildcommand&gt;org.springframework.ide.eclipse.core.springbuilder&lt;/buildcommand&gt;
+ * &lt;/additionalBuildcommands&gt;
+ * </pre>
+ *
+ * New style:
+ *
+ * <pre>
+ * &lt;additionalBuildcommands&gt;
+ * &lt;buildCommand&gt;
+ * &lt;name&gt;org.ui.externaltools.ExternalToolBuilder&lt;/name&gt;
+ * &lt;triggers&gt;auto,full,incremental,&lt;/triggers&gt;
+ * &lt;arguments&gt;
+ * &lt;LaunchConfigHandle&gt;&amp;lt;project&amp;gt;./externalToolBuilders/MavenBuilder.launch&lt;/LaunchConfighandle&gt;
+ * &lt;/arguments&gt;
+ * &lt;/buildCommand&gt;
+ * &lt;/additionalBuildcommands&gt;
+ * </pre>
+ *
+ * Note the difference between <code>build<strong>c</strong>ommand</code> and
+ * <code>build<strong>C</strong>ommand</code>. You can mix and match old and new-style configuration entries.
+ *
+ * @parameter
+ */
+ private List additionalBuildcommands;
+
+ /**
+ * List of container classpath entries. By default the <code>org.eclipse.jdt.launching.JRE_CONTAINER</code>
+ * classpath container is added. Configuration example:
+ *
+ * <pre>
+ * &lt;classpathContainers&gt;
+ * &lt;classpathContainer&gt;org.eclipse.jdt.launching.JRE_CONTAINER&lt;/classpathContainer&gt;
+ * &lt;classpathContainer&gt;org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v5.5&lt;/classpathContainer&gt;
+ * &lt;classpathContainer&gt;org.eclipse.jst.j2ee.internal.web.container/artifact&lt;/classpathContainer&gt;
+ * &lt;/classpathContainers&gt;
+ * </pre>
+ *
+ * @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;
+
+ /**
+ * Is it an AJDT project? If yes, the plugin adds the necessary natures and build commands to the .project file.
+ */
+ private boolean ajdt;
+
+ /**
+ * 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.
+ *
+ * <pre>
+ * &lt;plugin&gt;
+ * &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
+ * &lt;artifactId&gt;maven-eclipse-plugin&lt;/artifactId&gt;
+ * &lt;configuration&gt;
+ * &lt;additionalConfig&gt;
+ * &lt;file&gt;
+ * &lt;name&gt;.checkstyle&lt;/name&gt;
+ * &lt;content&gt;
+ * &lt;![CDATA[&lt;fileset-config file-format-version=&quot;1.2.0&quot; simple-config=&quot;true&quot;&gt;
+ * &lt;fileset name=&quot;all&quot; enabled=&quot;true&quot; check-config-name=&quot;acme corporate style&quot; local=&quot;false&quot;&gt;
+ * &lt;file-match-pattern match-pattern=&quot;.&quot; include-pattern=&quot;true&quot;/&gt;
+ * &lt;/fileset&gt;
+ * &lt;filter name=&quot;NonSrcDirs&quot; enabled=&quot;true&quot;/&gt;
+ * &lt;/fileset-config&gt;]]&gt;
+ * &lt;/content&gt;
+ * &lt;/file&gt;
+ * &lt;/additionalConfig&gt;
+ * &lt;/configuration&gt;
+ * &lt;/plugin&gt;
+ * </pre>
+ *
+ * Instead of the content you can also define (from version 2.5) an url to download the file :
+ *
+ * <pre>
+ * &lt;plugin&gt;
+ * &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
+ * &lt;artifactId&gt;maven-eclipse-plugin&lt;/artifactId&gt;
+ * &lt;configuration&gt;
+ * &lt;additionalConfig&gt;
+ * &lt;file&gt;
+ * &lt;name&gt;.checkstyle&lt;/name&gt;
+ * &lt;url&gt;http://some.place.org/path/to/file&lt;/url&gt;
+ * &lt;/file&gt;
+ * &lt;/additionalConfig&gt;
+ * &lt;/configuration&gt;
+ * </pre>
+ *
+ * or a location :
+ *
+ * <pre>
+ * &lt;plugin&gt;
+ * &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
+ * &lt;artifactId&gt;maven-eclipse-plugin&lt;/artifactId&gt;
+ * &lt;configuration&gt;
+ * &lt;additionalConfig&gt;
+ * &lt;file&gt;
+ * &lt;name&gt;.checkstyle&lt;/name&gt;
+ * &lt;location&gt;/checkstyle-config.xml&lt;/location&gt;
+ * &lt;/file&gt;
+ * &lt;/additionalConfig&gt;
+ * &lt;/configuration&gt;
+ * &lt;dependencies&gt;
+ * &lt;!-- The file defined in the location is stored in this dependency --&gt;
+ * &lt;dependency&gt;
+ * &lt;groupId&gt;eclipsetest&lt;/groupId&gt;
+ * &lt;artifactId&gt;checkstyle-config&lt;/artifactId&gt;
+ * &lt;version&gt;1.0&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * &lt;/dependencies&gt;
+ * &lt;/plugin&gt;
+ * </pre>
+ *
+ * @parameter
+ */
+ private EclipseConfigFile[] additionalConfig;
+
+ /**
+ * If set to <code>true</code>, 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 <code>true</code>, 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 <code>[groupId]</code>, <code>[artifactId]</code> and <code>[version]</code>
+ * variables. eg. <code>[groupId].[artifactId]-[version]</code>
+ *
+ * @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.
+ *
+ * If workspace is not defined, then an attempt to locate it by checking up the directory hierarchy will be made.
+ *
+ * @since 2.5
+ * @parameter expression="${eclipse.workspace}"
+ */
+ protected File 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;
+
+ /**
+ * The version of AJDT for which configuration files will be generated. The default value is "1.5", supported
+ * versions are "none", "1.4", and "1.5".
+ *
+ * @parameter expression="${eclipse.ajdtVersion}" default-value="1.5"
+ */
+ private String ajdtVersion;
+
+ protected final boolean isJavaProject()
+ {
+ return isJavaProject;
+ }
+
+ protected final boolean isPdeProject()
+ {
+ return pde;
+ }
+
+ /**
+ * Getter for <code>buildcommands</code>.
+ *
+ * @return Returns the buildcommands.
+ */
+ public final List getBuildcommands()
+ {
+ return buildcommands;
+ }
+
+ /**
+ * Setter for <code>buildcommands</code>.
+ *
+ * @param buildcommands The buildcommands to set.
+ */
+ public final void setBuildcommands( List buildcommands )
+ {
+ this.buildcommands = buildcommands;
+ }
+
+ /**
+ * Getter for <code>buildOutputDirectory</code>.
+ *
+ * @return Returns the buildOutputDirectory.
+ */
+ public final File getBuildOutputDirectory()
+ {
+ return buildOutputDirectory;
+ }
+
+ /**
+ * Setter for <code>buildOutputDirectory</code>.
+ *
+ * @param buildOutputDirectory The buildOutputDirectory to set.
+ */
+ public final void setBuildOutputDirectory( File buildOutputDirectory )
+ {
+ this.buildOutputDirectory = buildOutputDirectory;
+ }
+
+ /**
+ * Getter for <code>classpathContainers</code>.
+ *
+ * @return Returns the classpathContainers.
+ */
+ public final List getClasspathContainers()
+ {
+ return classpathContainers;
+ }
+
+ /**
+ * Setter for <code>classpathContainers</code>.
+ *
+ * @param classpathContainers The classpathContainers to set.
+ */
+ public final void setClasspathContainers( List classpathContainers )
+ {
+ this.classpathContainers = classpathContainers;
+ }
+
+ /**
+ * Getter for <code>eclipseProjectDir</code>.
+ *
+ * @return Returns the eclipseProjectDir.
+ */
+ public final File getEclipseProjectDir()
+ {
+ return eclipseProjectDir;
+ }
+
+ /**
+ * Setter for <code>eclipseProjectDir</code>.
+ *
+ * @param eclipseProjectDir The eclipseProjectDir to set.
+ */
+ public final void setEclipseProjectDir( File eclipseProjectDir )
+ {
+ this.eclipseProjectDir = eclipseProjectDir;
+ }
+
+ /**
+ * Getter for <code>projectnatures</code>.
+ *
+ * @return Returns the projectnatures.
+ */
+ public final List getProjectnatures()
+ {
+ return projectnatures;
+ }
+
+ /**
+ * Setter for <code>projectnatures</code>.
+ *
+ * @param projectnatures The projectnatures to set.
+ */
+ public final void setProjectnatures( List projectnatures )
+ {
+ this.projectnatures = projectnatures;
+ }
+
+ /**
+ * Getter for <code>useProjectReferences</code>.
+ *
+ * @return Returns the useProjectReferences.
+ */
+ public final boolean getUseProjectReferences()
+ {
+ return useProjectReferences;
+ }
+
+ /**
+ * Setter for <code>useProjectReferences</code>.
+ *
+ * @param useProjectReferences The useProjectReferences to set.
+ */
+ public final void setUseProjectReferences( boolean useProjectReferences )
+ {
+ this.useProjectReferences = useProjectReferences;
+ }
+
+ /**
+ * Getter for <code>wtpversion</code>.
+ *
+ * @return Returns the wtpversion.
+ */
+ public final String getWtpversion()
+ {
+ return wtpversion;
+ }
+
+ /**
+ * Setter for <code>wtpversion</code>.
+ *
+ * @param wtpversion The wtpversion to set.
+ */
+ public final void setWtpversion( String wtpversion )
+ {
+ this.wtpversion = wtpversion;
+ }
+
+ /**
+ * Getter for <code>additionalBuildcommands</code>.
+ *
+ * @return Returns the additionalBuildcommands.
+ */
+ public final List getAdditionalBuildcommands()
+ {
+ return additionalBuildcommands;
+ }
+
+ /**
+ * Setter for <code>additionalBuildcommands</code>.
+ *
+ * @param additionalBuildcommands The additionalBuildcommands to set.
+ */
+ public final void setAdditionalBuildcommands( List additionalBuildcommands )
+ {
+ this.additionalBuildcommands = additionalBuildcommands;
+ }
+
+ /**
+ * Getter for <code>additionalProjectnatures</code>.
+ *
+ * @return Returns the additionalProjectnatures.
+ */
+ public final List getAdditionalProjectnatures()
+ {
+ return additionalProjectnatures;
+ }
+
+ /**
+ * Setter for <code>additionalProjectnatures</code>.
+ *
+ * @param additionalProjectnatures The additionalProjectnatures to set.
+ */
+ public final void setAdditionalProjectnatures( List additionalProjectnatures )
+ {
+ this.additionalProjectnatures = additionalProjectnatures;
+ }
+
+ /**
+ * Getter for <code>addVersionToProjectName</code>.
+ */
+ public final boolean isAddVersionToProjectName()
+ {
+ return addVersionToProjectName;
+ }
+
+ /**
+ * Setter for <code>addVersionToProjectName</code>.
+ */
+ public final void setAddVersionToProjectName( boolean addVersionToProjectName )
+ {
+ this.addVersionToProjectName = addVersionToProjectName;
+ }
+
+ /**
+ * Getter for <code>addGroupIdToProjectName</code>.
+ */
+ public final boolean isAddGroupIdToProjectName()
+ {
+ return addGroupIdToProjectName;
+ }
+
+ /**
+ * Setter for <code>addGroupIdToProjectName</code>.
+ */
+ public final void setAddGroupIdToProjectName( boolean addGroupIdToProjectName )
+ {
+ this.addGroupIdToProjectName = addGroupIdToProjectName;
+ }
+
+ /**
+ * Getter for <code>projectNameTemplate</code>
+ *
+ * @return projectNameTemplate
+ */
+ public final String getProjectNameTemplate()
+ {
+ return projectNameTemplate;
+ }
+
+ /**
+ * Setter for <code>projectNameTemplate</code>.
+ *
+ * @param projectNameTemplate projectNameTemplate
+ */
+ public final void setProjectNameTemplate( String projectNameTemplate )
+ {
+ this.projectNameTemplate = projectNameTemplate;
+ }
+
+ /**
+ * @see org.apache.maven.plugin.Mojo#execute()
+ */
+ public final boolean setup()
+ throws MojoExecutionException
+ {
+ boolean ready = true;
+
+ checkDeprecations();
+ setProjectNameTemplate( IdeUtils.calculateProjectNameTemplate( getProjectNameTemplate(), isAddVersionToProjectName(),
+ isAddGroupIdToProjectName(), getLog() ) );
+ ajdt = enableAjdt( executedProject ) && !ajdtVersion.equals( "none" );
+ 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;
+ }
+
+ /**
+ * Convert any Strings in the <code>commands</code> List to <code>BuildCommand</code>s. The conversion happens
+ * in situ.
+ *
+ * @param commands a list of commands to convert into <code>BuildCommand</code>
+ */
+ protected final 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 ) );
+ }
+ }
+
+ /**
+ * Extension point for subclasses.
+ * <p>
+ * Called during <code>setup</code>.
+ *
+ * @throws MojoExecutionException mojo failures.
+ */
+ protected void setupExtras()
+ throws MojoExecutionException
+ {
+ // extension point.
+ }
+
+ private 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;
+ }
+
+ /**
+ * Extension point for subclasses.
+ * <p>
+ * Called during <code>setup</code> and used to validate that the configuration is sane.
+ *
+ * @throws MojoExecutionException mojo failures.
+ */
+ protected void validateExtras() throws MojoExecutionException
+ {
+ // 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;
+ }
+
+ checkDeprecationsExtras();
+ }
+
+ /**
+ * Extension point for subclasses.
+ * <p>
+ * Check for any extra deprecations and log warnings. Called during <code>setup</code>
+ */
+ protected void checkDeprecationsExtras()
+ {
+ // provided for extension.
+ }
+
+ public final void writeConfiguration( IdeDependency[] deps )
+ throws MojoExecutionException
+ {
+ EclipseWriterConfig config = createEclipseWriterConfig( deps );
+
+ if ( wtpmanifest && isJavaProject() )
+ {
+ EclipseManifestWriter.addManifestResource( getLog(), config );
+ }
+ // NOTE: This could change the config!
+ writeConfigurationExtras( 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 ( ajdt && ajdtVersion.equals( "1.4" ) )
+ {
+ new EclipseAjdtWriter().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() } ) );
+ }
+
+ private 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() ) );
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Create the <code>EclipseWriterConfig</code> for the specified dependencies.
+ *
+ * @param deps the project dependencies
+ * @return a configured <code>EclipseWriterConfig</code>
+ * @throws MojoExecutionException mojo failures.
+ */
+ protected final 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( getProjectNameTemplate() );
+
+ String projectName = IdeUtils.getProjectName( config.getProjectNameTemplate(), project );
+
+ config.setEclipseProjectName( projectName );
+
+ config.setWtpapplicationxml( wtpapplicationxml );
+
+ config.setWtpVersion( wtpVersionFloat );
+
+ float ajdtVersionFloat;
+ try
+ {
+ ajdtVersionFloat = Float.parseFloat( ajdtVersion );
+ }
+ catch ( NumberFormatException e )
+ {
+ ajdtVersionFloat = 0.0f;
+ }
+
+ config.setAjdtVersion( ajdtVersionFloat );
+
+ 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 ) );
+ }
+ }
+ }
+
+ if ( ajdt )
+ {
+ buildAjdtWeaveDeps( deps );
+ buildAspectjDeps( deps );
+ }
+
+ 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. <br/> <b> NOTE: This could change the config! </b>
+ *
+ * @param config
+ * @throws MojoExecutionException
+ */
+ protected void writeConfigurationExtras( 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$
+ }
+ }
+
+ /**
+ * Fill getProjectnatures() with values.
+ * <p>
+ * Subclasses should call super and then calculate their own additions and insert them via
+ * <code>getProjectnatures().addAll()</code>.
+ *
+ * @param packaging the pom's packaging
+ */
+ 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 )
+ {
+ if ( ajdt )
+ {
+ projectnatures.add( NATURE_AJDT_CORE_JAVA );
+ }
+
+ 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 );
+ }
+
+ }
+
+ /**
+ * Fill getClasspathContainers() with values.
+ * <p>
+ * Subclasses should call super and then calculate their own additions and insert them via
+ * <code>getClasspathContainers().addAll()</code>.
+ *
+ * @param packaging the pom's packaging
+ */
+ protected void fillDefaultClasspathContainers( String packaging )
+ {
+ classpathContainers = new ArrayList();
+
+ if ( getWorkspaceConfiguration().getDefaultClasspathContainer() != null )
+ {
+ getLog().info(
+ "Adding default classpath container: "
+ + getWorkspaceConfiguration().getDefaultClasspathContainer() );
+ classpathContainers.add( getWorkspaceConfiguration().getDefaultClasspathContainer() );
+ }
+ if ( pde )
+ {
+ classpathContainers.add( REQUIRED_PLUGINS_CONTAINER );
+ }
+
+ if ( ajdt )
+ {
+ classpathContainers.add( ASPECTJ_RT_CONTAINER );
+ }
+ }
+
+ /**
+ * Fill getBuildcommands() with values.
+ * <p>
+ * Subclasses should call super and then calculate their own additions and insert them via
+ * <code>getBuildcommands().addAll()</code>.
+ *
+ * @param packaging the pom's packaging
+ */
+ 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 )
+ {
+ if ( ajdt )
+ {
+ buildcommands.add( new BuildCommand( BUILDER_AJDT_CORE_JAVA ) );
+ }
+ else
+ {
+ 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 final EclipseSourceDir[] buildDirectoryList( MavenProject project, File basedir, File buildOutputDirectory )
+ throws MojoExecutionException
+ {
+ File projectBaseDir = project.getFile().getParentFile();
+
+ String mainOutput = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, buildOutputDirectory, false );
+
+ // 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 );
+ }
+
+ Set mainDirectories = new LinkedHashSet();
+
+ extractSourceDirs( mainDirectories, project.getCompileSourceRoots(), basedir, projectBaseDir, false, null );
+
+ extractResourceDirs( mainDirectories, project.getBuild().getResources(), basedir, projectBaseDir, false,
+ mainOutput );
+
+ Set testDirectories = new LinkedHashSet();
+
+ extractSourceDirs( testDirectories, project.getTestCompileSourceRoots(), basedir, projectBaseDir, true,
+ testOutput );
+
+ extractResourceDirs( testDirectories, project.getBuild().getTestResources(), basedir, projectBaseDir, true,
+ testOutput );
+
+ // avoid duplicated entries
+ Set directories = new LinkedHashSet();
+
+ // NOTE: Since MNG-3118, test classes come before main classes
+ boolean testBeforeMain = isMavenVersion( "[2.0.8,)" );
+
+ if ( testBeforeMain )
+ {
+ directories.addAll( testDirectories );
+ directories.removeAll( mainDirectories );
+ directories.addAll( mainDirectories );
+ }
+ else
+ {
+ directories.addAll( mainDirectories );
+ directories.addAll( testDirectories );
+ }
+ if ( ajdt )
+ extractAspectDirs( directories, project, basedir, projectBaseDir, 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() );
+
+ if ( sourceRootFile.isDirectory() )
+ {
+ String sourceRoot =
+ IdeUtils.toRelativeAndFixSeparator( projectBaseDir, sourceRootFile,
+ !projectBaseDir.equals( basedir ) );
+
+ directories.add( new EclipseSourceDir( sourceRoot, output, false, test, null, null, false ) );
+ }
+ }
+ }
+
+ final void extractResourceDirs( Set directories, List resources, 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() ) );
+ }
+ }
+
+ private void extractAspectDirs( Set directories, MavenProject project, File basedir, File projectBaseDir,
+ String testOutput )
+ throws MojoExecutionException
+ {
+ Xpp3Dom configuration = getAspectjConfiguration( project );
+ if ( configuration != null )
+ {
+ String aspectDirectory = DEFAULT_ASPECT_DIRECTORY;
+ Xpp3Dom aspectDirectoryElement = configuration.getChild( ASPECT_DIRECTORY );
+ if ( aspectDirectoryElement != null )
+ {
+ aspectDirectory = aspectDirectoryElement.getValue();
+ }
+
+ File aspectDirectoryFile = new File( basedir, aspectDirectory );
+ if ( aspectDirectoryFile.exists() && aspectDirectoryFile.isDirectory() )
+ {
+ String sourceRoot =
+ IdeUtils.toRelativeAndFixSeparator( projectBaseDir, aspectDirectoryFile,
+ !projectBaseDir.equals( basedir ) );
+
+ directories.add( new EclipseSourceDir( sourceRoot, null, false, false, null, null, false ) );
+ }
+
+ String testAspectDirectory = DEFAULT_TEST_ASPECT_DIRECTORY;
+ Xpp3Dom testAspectDirectoryElement = configuration.getChild( TEST_ASPECT_DIRECTORY );
+ if ( testAspectDirectoryElement != null )
+ {
+ testAspectDirectory = testAspectDirectoryElement.getValue();
+ }
+
+ File testAspectDirectoryFile = new File( basedir, testAspectDirectory );
+ if ( testAspectDirectoryFile.exists() && testAspectDirectoryFile.isDirectory() )
+ {
+ String sourceRoot =
+ IdeUtils.toRelativeAndFixSeparator( projectBaseDir, testAspectDirectoryFile,
+ !projectBaseDir.equals( basedir ) );
+
+ directories.add( new EclipseSourceDir( sourceRoot, testOutput, false, true, null, null, false ) );
+ }
+ }
+ }
+
+ private boolean enableAjdt( MavenProject project )
+ {
+ boolean enable = false;
+ List buildPlugins = project.getBuildPlugins();
+ for ( Iterator it = buildPlugins.iterator(); it.hasNext(); )
+ {
+ Plugin plugin = (Plugin) it.next();
+ if ( plugin.getGroupId().equals( ORG_CODEHAUS_MOJO )
+ && plugin.getArtifactId().equals( ASPECTJ_MAVEN_PLUGIN ) )
+ {
+ enable = true;
+ break;
+ }
+ }
+
+ return enable;
+ }
+
+ private Xpp3Dom getAspectjConfiguration( MavenProject project )
+ {
+ Xpp3Dom configuration = null;
+ List buildPlugins = project.getBuildPlugins();
+ for ( Iterator it = buildPlugins.iterator(); it.hasNext(); )
+ {
+ Plugin plugin = (Plugin) it.next();
+ if ( plugin.getGroupId().equals( ORG_CODEHAUS_MOJO )
+ && plugin.getArtifactId().equals( ASPECTJ_MAVEN_PLUGIN ) )
+ {
+ configuration = (Xpp3Dom) plugin.getConfiguration();
+ break;
+ }
+ }
+
+ return configuration;
+ }
+
+ private void buildAspectjDeps( IdeDependency[] deps )
+ throws MojoExecutionException
+ {
+ Xpp3Dom configuration = getAspectjConfiguration( executedProject );
+ if ( configuration != null )
+ {
+ Xpp3Dom aspectLibrariesParent = configuration.getChild( ASPECT_LIBRARIES );
+ if ( aspectLibrariesParent != null )
+ {
+ Xpp3Dom[] aspectLibraries = aspectLibrariesParent.getChildren( ASPECT_LIBRARY );
+ outerLoop: for ( int i = 0; i < aspectLibraries.length; i++ )
+ {
+ String artifactId = aspectLibraries[i].getChild( POM_ELT_ARTIFACT_ID ).getValue();
+ String groupId = aspectLibraries[i].getChild( POM_ELT_GROUP_ID ).getValue();
+ for ( int j = 0; j < deps.length; j++ )
+ {
+ if ( deps[j].getArtifactId().equals( artifactId ) && deps[j].getGroupId().equals( groupId ) )
+ {
+ deps[j].setAjdtDependency( true );
+ continue outerLoop;
+ }
+ }
+
+ throw new MojoExecutionException( "AspectLibrary is not a dependency of project" );
+ }
+ }
+ }
+ }
+
+ private void buildAjdtWeaveDeps( IdeDependency[] deps )
+ throws MojoExecutionException
+ {
+ Xpp3Dom configuration = getAspectjConfiguration( executedProject );
+ if ( configuration != null )
+ {
+ Xpp3Dom weaveDependenciesParent = configuration.getChild( WEAVE_DEPENDENCIES );
+ if ( weaveDependenciesParent != null )
+ {
+ Xpp3Dom[] weaveDependencies = weaveDependenciesParent.getChildren( WEAVE_DEPENDENCY );
+ outerLoop: for ( int i = 0; i < weaveDependencies.length; i++ )
+ {
+ String artifactId = weaveDependencies[i].getChild( POM_ELT_ARTIFACT_ID ).getValue();
+ String groupId = weaveDependencies[i].getChild( POM_ELT_GROUP_ID ).getValue();
+ for ( int j = 0; j < deps.length; j++ )
+ {
+ if ( deps[j].getArtifactId().equals( artifactId ) && deps[j].getGroupId().equals( groupId ) )
+ {
+ deps[j].setAjdtWeaveDependency( true );
+ continue outerLoop;
+ }
+ }
+
+ throw new MojoExecutionException( "WeaveDependency is not a dependency of project" );
+ }
+ }
+ }
+ }
+
+ /**
+ * {@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();
+ }
+ }
+ }
+ MavenProject reactorProject = getReactorProject( artifact );
+ if ( reactorProject != null ) {
+ return IdeUtils.getProjectName( getProjectNameTemplateForMavenProject( reactorProject ), artifact );
+ }
+ return IdeUtils.getProjectName( getProjectNameTemplate(), artifact );
+ }
+
+ /**
+ * @param mavenProject the project to get the projectNameTemplate configuration from
+ * @return the projectNameTemplate configuration from the specified MavenProject
+ */
+ private String getProjectNameTemplateForMavenProject( MavenProject mavenProject )
+ {
+ String projectNameTemplate = null;
+ boolean addVersionToProjectName = false;
+ boolean addGroupIdToProjectName = false;
+
+ Build build = mavenProject.getBuild();
+ if ( build != null )
+ {
+ Plugin plugin = (Plugin) build.getPluginsAsMap().get( "org.apache.maven.plugins:maven-eclipse-plugin" );
+ if ( plugin != null )
+ {
+ Xpp3Dom config = (Xpp3Dom) plugin.getConfiguration();
+ if ( config != null )
+ {
+ Xpp3Dom projectNameTemplateNode = config.getChild( "projectNameTemplate" );
+ if ( projectNameTemplateNode != null )
+ {
+ projectNameTemplate = projectNameTemplateNode.getValue();
+ }
+ Xpp3Dom addVersionToProjectNameNode = config.getChild( "addVersionToProjectName" );
+ addVersionToProjectName = addVersionToProjectNameNode != null;
+ Xpp3Dom addGroupIdToProjectNameNode = config.getChild( "addGroupIdToProjectName" );
+ addGroupIdToProjectName = addGroupIdToProjectNameNode != null;
+ }
+ }
+ }
+ return IdeUtils.calculateProjectNameTemplate(projectNameTemplate, addVersionToProjectName, addGroupIdToProjectName, getLog());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected final IdeDependency[] getWorkspaceArtefacts()
+ {
+ return getWorkspaceConfiguration().getWorkspaceArtefacts();
+ }
+
+ public final WorkspaceConfiguration getWorkspaceConfiguration()
+ {
+ if ( workspaceConfiguration == null )
+ {
+ workspaceConfiguration = new WorkspaceConfiguration();
+ locateWorkspace();
+ getLog().info( Messages.getString( "EclipsePlugin.workspace", workspace ) );
+ workspaceConfiguration.setWorkspaceDirectory( workspace );
+
+ new ReadWorkspaceLocations().init( getLog(), workspaceConfiguration, project, wtpdefaultserver );
+ }
+ return workspaceConfiguration;
+ }
+
+ /**
+ * If workspace is not defined, then attempt to locate it by checking up the directory hierarchy.
+ */
+ private void locateWorkspace()
+ {
+ if ( workspace == null )
+ {
+ File currentWorkingDirectory = new File( "." ).getAbsoluteFile();
+ while ( currentWorkingDirectory != null )
+ {
+ File metadataDirectory = new File( currentWorkingDirectory, ".metadata" );
+ logger.debug( "Checking for eclipse workspace at " + currentWorkingDirectory );
+ if ( metadataDirectory.exists() && metadataDirectory.isDirectory() )
+ {
+ logger.debug( " Found workspace at " + currentWorkingDirectory );
+ workspace = currentWorkingDirectory;
+ return;
+ }
+ currentWorkingDirectory = currentWorkingDirectory.getParentFile();
+ }
+ }
+ }
+
+ public final 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 <code>true</code> 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;
+ }
+
+ /**
+ * Checks if jar has to be resolved for the given artifact
+ *
+ * @param art the artifact to check
+ * @return true if resolution should happen
+ */
+ protected final 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 final 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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseProjectWriter.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseProjectWriter.java
new file mode 100644
index 0000000000..14d8a8becd
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/EclipseProjectWriter.java
@@ -0,0 +1,357 @@
+/*
+ * 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.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.ArrayList;
+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.Messages;
+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 <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
+ * @author <a href="mailto:kenney@neonics.com">Kenney Westerhof</a>
+ * @author <a href="mailto:fgiust@apache.org">Fabrizio Giustina</a>
+ * @version $Id: EclipseProjectWriter.java 728546 2008-12-21 22:56:51Z bentmann $
+ */
+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() )
+ {
+ List duplicates = new ArrayList();
+ for ( int j = 0; j < config.getDepsOrdered().length; j++ )
+ {
+ IdeDependency dep = config.getDepsOrdered()[j];
+ // Avoid duplicates entries when same project is refered using multiple types
+ // (ejb, test-jar ...)
+ if ( dep.isReferencedProject() && !duplicates.contains( dep.getEclipseProjectName() ) )
+ {
+ writer.startElement( "project" ); //$NON-NLS-1$
+ writer.writeText( dep.getEclipseProjectName() );
+ writer.endElement();
+ duplicates.add( dep.getEclipseProjectName() );
+ }
+ }
+ }
+
+ 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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/Messages.java b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/maven/plugin/eclipse/Messages.java
new file mode 100644
index 0000000000..5916f50f80
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/java/org/apache/tuscany/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.maven.plugin.eclipse;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @author <a href="mailto:fgiust@users.sourceforge.net">Fabrizio Giustina</a>
+ * @version $Id: Messages.java 728546 2008-12-21 22:56:51Z bentmann $
+ */
+public class Messages
+{
+
+ private static final String BUNDLE_NAME = "org.apache.tuscany.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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/bundle/plugin/LICENSE.txt b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/bundle/plugin/LICENSE.txt
new file mode 100644
index 0000000000..6e529a25c4
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/bundle/plugin/NOTICE.txt b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/bundle/plugin/NOTICE.txt
new file mode 100644
index 0000000000..db5ab284d5
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/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/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/plugin/eclipse/messages.properties b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/plugin/eclipse/messages.properties
new file mode 100644
index 0000000000..35332a2058
--- /dev/null
+++ b/maven-plugins/tags/tuscany-bundle-plugin-1.0.8/src/main/resources/org/apache/tuscany/maven/plugin/eclipse/messages.properties
@@ -0,0 +1,81 @@
+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.wrote=Wrote Eclipse project for "{0}" to {1}.
+EclipsePlugin.missingelement=Missing element from the project descriptor: "{0}"
+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.foundadir={0} is a directory, ignoring.
+EclipsePlugin.workspace=Using Eclipse Workspace: {0}
+EclipsePlugin.cantcanonicalize=Can't canonicalize system path: {0}
+EclipsePlugin.unchangedmanifest=Not writing Manifest file as it is unchanged: {0}
+EclipsePlugin.invalidvminworkspace=Workspace defines a VM that does not contain a valid jre/lib/rt.jar: {0}
+
+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
+
+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}
+
+Rad6LibCopier.cantdeletefile=Failed to delete file: {0}
+
+MyEclipseSpringBeansWriter.baseDirDoesNotExist=The (basedir) path declared in the project's dependencies doesn't exist: {0}
+
+EclipseToMavenMojo.eclipseDirectoryPrompt=Eclipse directory?
+EclipseToMavenMojo.errorreadingfromstandardinput=Unable to read from standard input
+EclipseToMavenMojo.directoydoesnotexist=Directory {0} doesn't exists
+EclipseToMavenMojo.plugindirectorydoesnotexist=Plugin directory {0} doesn't exists
+EclipseToMavenMojo.remoterepositorydeployto=Will deploy artifacts to remote repository {0}
+EclipseToMavenMojo.processingfile=Processing file {0}
+EclipseToMavenMojo.processingplugin=Processing {0} of {1}
+EclipseToMavenMojo.skippingfile=Skipping file {0}
+EclipseToMavenMojo.unabletoresolveversionrange=Unable to resolve version range for dependency {0} in project {1}
+EclipseToMavenMojo.unabletoaccessjar=Unable to access jar {0}
+EclipseToMavenMojo.plugindoesnothavemanifest=Plugin {0} does not have a manifest; skipping..
+EclipseToMavenMojo.unabletoreadbundlefrommanifest=Unable to read bundle name/version from manifest, skipping...
+EclipseToMavenMojo.errorprocessingplugin=Error processing plugin {0}
+EclipseToMavenMojo.errorwritingtemporarypom=Error writing temporary pom file: {0}
+EclipseToMavenMojo.errordeployartifacttorepository=Unable to deploy artifact to repository.
+EclipseToMavenMojo.errorinstallartifacttorepository=Unable to install artifact to repository.
+EclipseToMavenMojo.errorgettingjarfileforplugin=Error getting the jar file for plugin {0}
+EclipseToMavenMojo.invalidsyntaxforrepository=Invalid syntax for repository.
+EclipseToMavenMojo.invalidremoterepositorysyntax=Invalid syntax for remote repository. Use "id::layout::url".
+EclipseToMavenMojo.cannotfindrepositorylayout=Cannot find repository layout: {0}
+EclipseToMavenMojo.missingversionforbundle=Missing version for bundle {0}, assuming any version > 0
+
+AbstractIdeSupportMojo.sourcesnotavailable=\n Sources for some artifacts are not available.\n List of artifacts without a source archive:
+AbstractIdeSupportMojo.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:
+AbstractIdeSupportMojo.sourcesmissingitem=\n o {0}
+AbstractIdeSupportMojo.javadocnotavailable=\n Javadoc for some artifacts is not available.\n List of artifacts without a javadoc archive:
+AbstractIdeSupportMojo.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:
+AbstractIdeSupportMojo.javadocmissingitem=\n o {0}
+AbstractIdeSupportMojo.artifactresolution=An error occurred during dependency resolution of the following artifact:\n {0}:{1}:{2}\nCaused by: {3}
+AbstractIdeSupportMojo.artifactdownload=An error occurred during dependency resolution.\n Failed to retrieve {0}:{1}-{2}\nCaused by: {3}
+AbstractIdeSupportMojo.unabletoparseversion={0}: unable to parse version '{1}' for dependency '{2}': {3}
+AbstractIdeSupportMojo.failedtocreatenotavailablemarkerfile=Error creating not available file {0}
+AbstractIdeSupportMojo.creatednotavailablemarkerfile=Not available marker file created: {0}
+AbstractIdeSupportMojo.unabletodeletenotavailablemarkerfile=Unable to delete marker file: {0}
+
+IdeUtils.errorresolving=Error resolving {0} artifact. Artifact id: {1} (Message: {2})
+
+RemoveCacheMojo.checking=Checking cache for not available markers
+RemoveCacheMojo.complete=Done