001: package org.apache.maven.plugin.version;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import org.apache.maven.artifact.Artifact;
023: import org.apache.maven.artifact.ArtifactUtils;
024: import org.apache.maven.artifact.factory.ArtifactFactory;
025: import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
026: import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
027: import org.apache.maven.artifact.metadata.ResolutionGroup;
028: import org.apache.maven.artifact.repository.ArtifactRepository;
029: import org.apache.maven.artifact.versioning.ArtifactVersion;
030: import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
031: import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
032: import org.apache.maven.artifact.versioning.VersionRange;
033: import org.apache.maven.execution.MavenSession;
034: import org.apache.maven.execution.RuntimeInformation;
035: import org.apache.maven.model.Plugin;
036: import org.apache.maven.model.ReportPlugin;
037: import org.apache.maven.plugin.InvalidPluginException;
038: import org.apache.maven.project.MavenProject;
039: import org.apache.maven.project.MavenProjectBuilder;
040: import org.apache.maven.project.ProjectBuildingException;
041: import org.codehaus.plexus.logging.AbstractLogEnabled;
042: import org.codehaus.plexus.util.StringUtils;
043:
044: import java.util.HashMap;
045: import java.util.Iterator;
046: import java.util.List;
047: import java.util.Map;
048:
049: public class DefaultPluginVersionManager extends AbstractLogEnabled
050: implements PluginVersionManager {
051: private ArtifactFactory artifactFactory;
052:
053: private ArtifactMetadataSource artifactMetadataSource;
054:
055: private MavenProjectBuilder mavenProjectBuilder;
056:
057: private RuntimeInformation runtimeInformation;
058:
059: public String resolvePluginVersion(String groupId,
060: String artifactId, MavenProject project,
061: MavenSession session)
062: throws PluginVersionResolutionException,
063: InvalidPluginException, PluginVersionNotFoundException {
064: return resolvePluginVersion(groupId, artifactId, project,
065: session.getLocalRepository(), false);
066: }
067:
068: public String resolveReportPluginVersion(String groupId,
069: String artifactId, MavenProject project,
070: MavenSession session)
071: throws PluginVersionResolutionException,
072: InvalidPluginException, PluginVersionNotFoundException {
073: return resolvePluginVersion(groupId, artifactId, project,
074: session.getLocalRepository(), true);
075: }
076:
077: private String resolvePluginVersion(String groupId,
078: String artifactId, MavenProject project,
079: ArtifactRepository localRepository,
080: boolean resolveAsReportPlugin)
081: throws PluginVersionResolutionException,
082: InvalidPluginException, PluginVersionNotFoundException {
083: // first pass...if the plugin is specified in the pom, try to retrieve the version from there.
084: String version = getVersionFromPluginConfig(groupId,
085: artifactId, project, resolveAsReportPlugin);
086: getLogger().debug("Version from POM: " + version);
087:
088: // NOTE: We CANNOT check the current project version here, so delay it until later.
089: // It will prevent plugins from building themselves, if they are part of the lifecycle mapping.
090:
091: // if there was no explicit version, try for one in the reactor
092: if (version == null) {
093: if (project.getProjectReferences() != null) {
094: String refId = ArtifactUtils.versionlessKey(groupId,
095: artifactId);
096: MavenProject ref = (MavenProject) project
097: .getProjectReferences().get(refId);
098: if (ref != null) {
099: version = ref.getVersion();
100: }
101: }
102: }
103: getLogger().debug(
104: "Version from another POM in the reactor: " + version);
105:
106: // third pass...we're always checking for latest install/deploy, so retrieve the version for LATEST metadata and
107: // also set that resolved version as the <useVersion/> in settings.xml.
108: if (StringUtils.isEmpty(version)) {
109: // 1. resolve the version to be used
110: version = resolveMetaVersion(groupId, artifactId, project,
111: localRepository, Artifact.LATEST_VERSION);
112: getLogger().debug(
113: "Version from LATEST metadata: " + version);
114: }
115:
116: // final pass...retrieve the version for RELEASE and also set that resolved version as the <useVersion/>
117: // in settings.xml.
118: if (StringUtils.isEmpty(version)) {
119: // 1. resolve the version to be used
120: version = resolveMetaVersion(groupId, artifactId, project,
121: localRepository, Artifact.RELEASE_VERSION);
122: getLogger().debug(
123: "Version from RELEASE metadata: " + version);
124: }
125:
126: // if we still haven't found a version, then fail early before we get into the update goop.
127: if (StringUtils.isEmpty(version)) {
128: throw new PluginVersionNotFoundException(groupId,
129: artifactId);
130: }
131:
132: return version;
133: }
134:
135: private String getVersionFromPluginConfig(String groupId,
136: String artifactId, MavenProject project,
137: boolean resolveAsReportPlugin) {
138: String version = null;
139:
140: if (resolveAsReportPlugin) {
141: if (project.getReportPlugins() != null) {
142: for (Iterator it = project.getReportPlugins()
143: .iterator(); it.hasNext() && version == null;) {
144: ReportPlugin plugin = (ReportPlugin) it.next();
145:
146: if (groupId.equals(plugin.getGroupId())
147: && artifactId
148: .equals(plugin.getArtifactId())) {
149: version = plugin.getVersion();
150: }
151: }
152: }
153: } else {
154: if (project.getBuildPlugins() != null) {
155: for (Iterator it = project.getBuildPlugins().iterator(); it
156: .hasNext()
157: && version == null;) {
158: Plugin plugin = (Plugin) it.next();
159:
160: if (groupId.equals(plugin.getGroupId())
161: && artifactId
162: .equals(plugin.getArtifactId())) {
163: version = plugin.getVersion();
164: }
165: }
166: }
167: }
168:
169: return version;
170: }
171:
172: private String resolveMetaVersion(String groupId,
173: String artifactId, MavenProject project,
174: ArtifactRepository localRepository, String metaVersionId)
175: throws PluginVersionResolutionException,
176: InvalidPluginException {
177: Artifact artifact = artifactFactory.createProjectArtifact(
178: groupId, artifactId, metaVersionId);
179:
180: String key = artifact.getDependencyConflictId();
181:
182: String version = null;
183:
184: // This takes the spec version and resolves a real version
185: try {
186: ResolutionGroup resolutionGroup = artifactMetadataSource
187: .retrieve(artifact, localRepository, project
188: .getPluginArtifactRepositories());
189:
190: // switching this out with the actual resolved artifact instance, since the MMSource re-creates the pom
191: // artifact.
192: artifact = resolutionGroup.getPomArtifact();
193: } catch (ArtifactMetadataRetrievalException e) {
194: throw new PluginVersionResolutionException(groupId,
195: artifactId, e.getMessage(), e);
196: }
197:
198: String artifactVersion = artifact.getVersion();
199:
200: // make sure this artifact was actually resolved to a file in the repo...
201: if (artifact.getFile() != null) {
202: boolean pluginValid = false;
203:
204: while (!pluginValid && artifactVersion != null) {
205: pluginValid = true;
206: MavenProject pluginProject;
207: try {
208: artifact = artifactFactory.createProjectArtifact(
209: groupId, artifactId, artifactVersion);
210: pluginProject = mavenProjectBuilder
211: .buildFromRepository(artifact, project
212: .getPluginArtifactRepositories(),
213: localRepository, false);
214: } catch (ProjectBuildingException e) {
215: throw new InvalidPluginException(
216: "Unable to build project information for plugin '"
217: + ArtifactUtils.versionlessKey(
218: groupId, artifactId)
219: + "': " + e.getMessage(), e);
220: }
221:
222: // if we don't have the required Maven version, then ignore an update
223: if (pluginProject.getPrerequisites() != null
224: && pluginProject.getPrerequisites().getMaven() != null) {
225: DefaultArtifactVersion requiredVersion = new DefaultArtifactVersion(
226: pluginProject.getPrerequisites().getMaven());
227:
228: if (runtimeInformation.getApplicationVersion()
229: .compareTo(requiredVersion) < 0) {
230: getLogger()
231: .info(
232: "Ignoring available plugin update: "
233: + artifactVersion
234: + " as it requires Maven version "
235: + requiredVersion);
236:
237: VersionRange vr;
238: try {
239: vr = VersionRange
240: .createFromVersionSpec("(,"
241: + artifactVersion + ")");
242: } catch (InvalidVersionSpecificationException e) {
243: throw new PluginVersionResolutionException(
244: groupId, artifactId,
245: "Error getting available plugin versions: "
246: + e.getMessage(), e);
247: }
248:
249: getLogger().debug("Trying " + vr);
250: try {
251: List versions = artifactMetadataSource
252: .retrieveAvailableVersions(
253: artifact,
254: localRepository,
255: project
256: .getPluginArtifactRepositories());
257: ArtifactVersion v = vr
258: .matchVersion(versions);
259: artifactVersion = v != null ? v.toString()
260: : null;
261: } catch (ArtifactMetadataRetrievalException e) {
262: throw new PluginVersionResolutionException(
263: groupId, artifactId,
264: "Error getting available plugin versions: "
265: + e.getMessage(), e);
266: }
267:
268: if (artifactVersion != null) {
269: getLogger().debug(
270: "Found " + artifactVersion);
271: pluginValid = false;
272: }
273: }
274: }
275: }
276: }
277:
278: if (!metaVersionId.equals(artifactVersion)) {
279: version = artifactVersion;
280: }
281:
282: return version;
283: }
284:
285: }
|