001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *  http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    
021    package org.apache.geronimo.mavenplugins.car;
022    
023    import java.io.File;
024    import java.io.FileOutputStream;
025    import java.io.IOException;
026    import java.io.StringReader;
027    import java.util.Collections;
028    import java.util.List;
029    
030    import org.apache.geronimo.kernel.config.ConfigurationData;
031    import org.apache.geronimo.kernel.config.ConfigurationStore;
032    import org.apache.geronimo.kernel.config.InvalidConfigException;
033    import org.apache.geronimo.kernel.config.NoSuchConfigException;
034    import org.apache.geronimo.kernel.repository.Artifact;
035    import org.apache.geronimo.system.configuration.RepositoryConfigurationStore;
036    import org.apache.geronimo.system.plugin.PluginInstallerGBean;
037    import org.apache.geronimo.system.plugin.PluginXmlUtil;
038    import org.apache.geronimo.system.plugin.model.ArtifactType;
039    import org.apache.geronimo.system.plugin.model.DependencyType;
040    import org.apache.geronimo.system.plugin.model.LicenseType;
041    import org.apache.geronimo.system.plugin.model.PluginArtifactType;
042    import org.apache.geronimo.system.plugin.model.PluginType;
043    import org.apache.geronimo.system.repository.Maven2Repository;
044    import org.apache.maven.model.License;
045    import org.apache.maven.model.Plugin;
046    import org.apache.maven.model.PluginExecution;
047    import org.apache.maven.model.Resource;
048    import org.codehaus.plexus.configuration.PlexusConfiguration;
049    import org.codehaus.plexus.util.xml.Xpp3Dom;
050    
051    /**
052     * Generate a geronimo-plugin.xml file based on configuration in the pom and car-maven-plugin configuration.
053     *
054     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
055     * @goal prepare-metadata
056     */
057    public class PluginMetadataGeneratorMojo
058            extends AbstractCarMojo {
059    
060    
061        /**
062         * The Geronimo repository where modules will be packaged up from.
063         *
064         * @parameter expression="${project.build.directory}/repository"
065         * @required
066         */
067        private File targetRepository = null;
068    
069        /**
070         * Directory for generated plugin metadata file.
071         *
072         * @parameter expression="${project.build.directory}/resources/"
073         * @required
074         */
075        protected File targetDir = null;
076    
077        /**
078         * Name of generated plugin metadata file.
079         *
080         * @parameter default-value="META-INF/geronimo-plugin.xml"
081         * @required
082         */
083        protected String pluginMetadataFileName = null;
084    
085        /**
086         * Full path of generated plugin metadata file.
087         *
088         * @ parameter expression="${project.build.directory}/resources/META-INF/geronimo-plugin.xml"
089         * @required
090         */
091    //    protected File targetFile = null;
092    
093        /**
094         * Whether licenses (copied from maven licence elements) are OSI approved.
095         *
096         * @parameter default-value="false"
097         */
098        private boolean osiApproved;
099    
100        /**
101         * Category of the geronimo plugin.
102         *
103         * @parameter
104         */
105        private String category;
106    
107        /**
108         * Dependencies explicitly listed in the car-maven-plugin configuration
109         *
110         * @parameter
111         */
112        private List<Dependency> dependencies = Collections.emptyList();
113    
114        /**
115         * Configuration of use of maven dependencies.  If missing or if value element is false, use the explicit list in the car-maven-plugin configuration.
116         * If present and true, use the maven dependencies in the current pom file of scope null, runtime, or compile.  In addition, the version of the maven
117         * dependency can be included or not depending on the includeVersion element.
118         *
119         * @parameter
120         */
121        private UseMavenDependencies useMavenDependencies;
122    
123        /**
124         * Shared configuration from parent that we merge since maven is incompetent at it.  This is a plugin-artifactType element without moduleId or dependencies.
125         * Do not attempt to include more than one of these in the parent poms since maven will not merge them correctly.
126         *
127         * @parameter
128         */
129        private PlexusConfiguration commonInstance;
130    
131        /**
132         * Configuration for this instance itself.  This is a plugin-artifactType element without moduleId or dependencies. Do not include more than one of these in the parent poms
133         * since maven will not merge them correctly.  Actually we have to fish this out of the model since maven mangles the xml for us.
134         */
135    //    private PlexusConfiguration instance;
136        protected void doExecute() throws Exception {
137    
138            PluginType metadata = new PluginType();
139            metadata.setName(project.getName());
140            metadata.setAuthor(project.getOrganization() == null? "unknown": project.getOrganization().getName());
141            metadata.setUrl(project.getOrganization() == null? "unknown": project.getOrganization().getUrl());
142            metadata.setDescription(project.getDescription());
143            metadata.setCategory(category);
144    
145            if (project.getLicenses() != null) {
146                for (Object licenseObj : project.getLicenses()) {
147                    License license = (License) licenseObj;
148                    LicenseType licenseType = new LicenseType();
149                    licenseType.setValue(license.getName());
150                    licenseType.setOsiApproved(osiApproved);
151                    metadata.getLicense().add(licenseType);
152                }
153            }
154    
155            PluginArtifactType instance;
156            Plugin plugin = (Plugin) project.getModel().getBuild().getPluginsAsMap().get("org.apache.geronimo.buildsupport:car-maven-plugin");
157            if (plugin == null) {
158                throw new Error("Unable to resolve car plugin");
159            }
160    
161            Xpp3Dom dom;
162            if (plugin.getExecutions().isEmpty()) {
163                dom = (Xpp3Dom) plugin.getConfiguration();
164            } else {
165                if (plugin.getExecutions().size() > 1) {
166                    throw new IllegalStateException("Cannot determine correct configuration for PluginMetadataGeneratorMojo: " + plugin.getExecutionsAsMap().keySet());
167                }
168                dom = (Xpp3Dom) ((PluginExecution) plugin.getExecutions().get(0)).getConfiguration();
169            }
170            Xpp3Dom instanceDom = dom.getChild("instance");
171    
172            if (instanceDom == null || instanceDom.getChild("plugin-artifact") == null) {
173                instance = new PluginArtifactType();
174            } else {
175                String instanceString = instanceDom.getChild("plugin-artifact").toString();
176                instance = PluginXmlUtil.loadPluginArtifactMetadata(new StringReader(instanceString.replace("#{", "${")));
177            }
178            if (this.commonInstance != null && this.commonInstance.getChild("plugin-artifact") != null) {
179                PluginArtifactType commonInstance = PluginXmlUtil.loadPluginArtifactMetadata(new StringReader(this.commonInstance.getChild("plugin-artifact").toString().replace("#{", "${")));
180                //merge
181                if (instance.getArtifactAlias().isEmpty()) {
182                    instance.getArtifactAlias().addAll(commonInstance.getArtifactAlias());
183                }
184                if (instance.getConfigSubstitution().isEmpty()) {
185                    instance.getConfigSubstitution().addAll(commonInstance.getConfigSubstitution());
186                }
187                //it doesn't make sense to copy a "generic" config.xml content into a specific module.
188    //            if ((instance.getConfigXmlContent() == null || instance.getConfigXmlContent().getGbean().isEmpty())
189    //                    && (commonInstance.getConfigXmlContent() != null && !commonInstance.getConfigXmlContent().getGbean().isEmpty())) {
190    //                instance.setConfigXmlContent(new ConfigXmlContentType());
191    //                instance.getConfigXmlContent().getGbean().addAll(commonInstance.getConfigXmlContent().getGbean());
192    //            }
193                if (instance.getCopyFile().isEmpty()) {
194                    instance.getCopyFile().addAll(commonInstance.getCopyFile());
195                }
196                if (instance.getDependency().isEmpty()) {
197                    instance.getDependency().addAll(commonInstance.getDependency());
198                }
199                if (instance.getGeronimoVersion().isEmpty()) {
200                    instance.getGeronimoVersion().addAll(commonInstance.getGeronimoVersion());
201                }
202                if (instance.getJvmVersion().isEmpty()) {
203                    instance.getJvmVersion().addAll(commonInstance.getJvmVersion());
204                }
205                if (instance.getObsoletes().isEmpty()) {
206                    instance.getObsoletes().addAll(commonInstance.getObsoletes());
207                }
208                if (instance.getPrerequisite().isEmpty()) {
209                    instance.getPrerequisite().addAll(commonInstance.getPrerequisite());
210                }
211                if (instance.getSourceRepository().isEmpty()) {
212                    instance.getSourceRepository().addAll(commonInstance.getSourceRepository());
213                }
214            }
215            metadata.getPluginArtifact().add(instance);
216    
217            ArtifactType artifactType = new ArtifactType();
218            artifactType.setGroupId(project.getGroupId());
219            artifactType.setArtifactId(project.getArtifactId());
220            artifactType.setVersion(project.getVersion());
221            ArtifactType existingArtifact = instance.getModuleId();
222            if (existingArtifact != null && existingArtifact.getType() != null) {
223                artifactType.setType(existingArtifact.getType());
224            } else {
225                artifactType.setType(project.getArtifact().getType());
226            }
227            instance.setModuleId(artifactType);
228            addDependencies(instance);
229            targetDir.mkdirs();
230            File targetFile = new File(targetDir.toURI().resolve(pluginMetadataFileName));
231            targetFile.getParentFile().mkdirs();
232            FileOutputStream out = new FileOutputStream(targetFile);
233            try {
234                PluginXmlUtil.writePluginMetadata(metadata, out);
235            } finally {
236                out.close();
237            }
238            Resource resource = new Resource();
239            resource.setDirectory(targetDir.getPath());
240            resource.addInclude(pluginMetadataFileName);
241            getProject().getResources().add(resource);
242        }
243    
244        private void addDependencies(PluginArtifactType instance) throws InvalidConfigException, IOException, NoSuchConfigException {
245            if (useMavenDependencies == null || !useMavenDependencies.isValue()) {
246                for (Dependency dependency : dependencies) {
247                    instance.getDependency().add(dependency.toDependencyType());
248                }
249            } else {
250                if (targetRepository.exists() && targetRepository.isDirectory()) {
251                    Maven2Repository targetRepo = new Maven2Repository(targetRepository);
252                    ConfigurationStore configStore = new RepositoryConfigurationStore(targetRepo);
253                    Artifact pluginArtifact = PluginInstallerGBean.toArtifact(instance.getModuleId());
254                    ConfigurationData data = configStore.loadConfiguration(pluginArtifact);
255                    PluginInstallerGBean.addGeronimoDependencies(data, instance.getDependency(), useMavenDependencies.isIncludeVersion());
256                } else {
257                    List<org.apache.maven.model.Dependency> includedDependencies = project.getOriginalModel().getDependencies();
258                    List<org.apache.maven.model.Dependency> artifacts = project.getDependencies();
259                    for (org.apache.maven.model.Dependency dependency : includedDependencies) {
260                        dependency = resolveDependency(dependency, artifacts);
261                        if (includeDependency(dependency)) {
262                            DependencyType gdep = toGeronimoDependency(dependency, useMavenDependencies.isIncludeVersion());
263                            instance.getDependency().add(gdep);
264                        }
265                    }
266                }
267    
268            }
269        }
270    
271        private static DependencyType toGeronimoDependency(final org.apache.maven.model.Dependency dependency, boolean includeVersion) {
272            DependencyType dependencyType = new DependencyType();
273            dependencyType.setGroupId(dependency.getGroupId());
274            dependencyType.setArtifactId(dependency.getArtifactId());
275            if (includeVersion) {
276                dependencyType.setVersion(dependency.getVersion());
277            }
278            dependencyType.setType(dependency.getType());
279            dependencyType.setStart(true);
280            return dependencyType;
281        }
282    }