001: package org.apache.maven.project.inheritance;
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.model.Build;
023: import org.apache.maven.model.Dependency;
024: import org.apache.maven.model.DependencyManagement;
025: import org.apache.maven.model.DeploymentRepository;
026: import org.apache.maven.model.DistributionManagement;
027: import org.apache.maven.model.Model;
028: import org.apache.maven.model.PluginManagement;
029: import org.apache.maven.model.Reporting;
030: import org.apache.maven.model.Scm;
031: import org.apache.maven.model.Site;
032: import org.apache.maven.project.ModelUtils;
033: import org.codehaus.plexus.util.StringUtils;
034:
035: import java.util.ArrayList;
036: import java.util.Iterator;
037: import java.util.LinkedHashMap;
038: import java.util.LinkedList;
039: import java.util.List;
040: import java.util.Map;
041: import java.util.Properties;
042: import java.util.StringTokenizer;
043: import java.util.TreeMap;
044:
045: /**
046: * @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
047: * @version $Id: DefaultModelInheritanceAssembler.java,v 1.4 2004/08/23 20:24:54
048: * jdcasey Exp $
049: * @todo generate this with modello to keep it in sync with changes in the model.
050: */
051: public class DefaultModelInheritanceAssembler implements
052: ModelInheritanceAssembler {
053: public void copyModel(Model dest, Model source) {
054: assembleModelInheritance(dest, source, null, false);
055: }
056:
057: public void assembleModelInheritance(Model child, Model parent,
058: String childPathAdjustment) {
059: assembleModelInheritance(child, parent, childPathAdjustment,
060: true);
061: }
062:
063: public void assembleModelInheritance(Model child, Model parent) {
064: assembleModelInheritance(child, parent, null, true);
065: }
066:
067: private void assembleModelInheritance(Model child, Model parent,
068: String childPathAdjustment, boolean appendPaths) {
069: // cannot inherit from null parent.
070: if (parent == null) {
071: return;
072: }
073:
074: // Group id
075: if (child.getGroupId() == null) {
076: child.setGroupId(parent.getGroupId());
077: }
078:
079: // version
080: if (child.getVersion() == null) {
081: // The parent version may have resolved to something different, so we take what we asked for...
082: // instead of - child.setVersion( parent.getVersion() );
083:
084: if (child.getParent() != null) {
085: child.setVersion(child.getParent().getVersion());
086: }
087: }
088:
089: // inceptionYear
090: if (child.getInceptionYear() == null) {
091: child.setInceptionYear(parent.getInceptionYear());
092: }
093:
094: // url
095: if (child.getUrl() == null) {
096: if (parent.getUrl() != null) {
097: child.setUrl(appendPath(parent.getUrl(), child
098: .getArtifactId(), childPathAdjustment,
099: appendPaths));
100: } else {
101: child.setUrl(parent.getUrl());
102: }
103: }
104:
105: assembleDistributionInheritence(child, parent,
106: childPathAdjustment, appendPaths);
107:
108: // issueManagement
109: if (child.getIssueManagement() == null) {
110: child.setIssueManagement(parent.getIssueManagement());
111: }
112:
113: // description
114: if (child.getDescription() == null) {
115: child.setDescription(parent.getDescription());
116: }
117:
118: // Organization
119: if (child.getOrganization() == null) {
120: child.setOrganization(parent.getOrganization());
121: }
122:
123: // Scm
124: assembleScmInheritance(child, parent, childPathAdjustment,
125: appendPaths);
126:
127: // ciManagement
128: if (child.getCiManagement() == null) {
129: child.setCiManagement(parent.getCiManagement());
130: }
131:
132: // developers
133: if (child.getDevelopers().size() == 0) {
134: child.setDevelopers(parent.getDevelopers());
135: }
136:
137: // licenses
138: if (child.getLicenses().size() == 0) {
139: child.setLicenses(parent.getLicenses());
140: }
141:
142: // developers
143: if (child.getContributors().size() == 0) {
144: child.setContributors(parent.getContributors());
145: }
146:
147: // mailingLists
148: if (child.getMailingLists().size() == 0) {
149: child.setMailingLists(parent.getMailingLists());
150: }
151:
152: // Build
153: assembleBuildInheritance(child, parent);
154:
155: assembleDependencyInheritance(child, parent);
156:
157: child.setRepositories(ModelUtils.mergeRepositoryLists(child
158: .getRepositories(), parent.getRepositories()));
159: child.setPluginRepositories(ModelUtils.mergeRepositoryLists(
160: child.getPluginRepositories(), parent
161: .getPluginRepositories()));
162:
163: assembleReportingInheritance(child, parent);
164:
165: assembleDependencyManagementInheritance(child, parent);
166:
167: Properties props = new Properties();
168: props.putAll(parent.getProperties());
169: props.putAll(child.getProperties());
170:
171: child.setProperties(props);
172: }
173:
174: private void assembleDependencyManagementInheritance(Model child,
175: Model parent) {
176: DependencyManagement parentDepMgmt = parent
177: .getDependencyManagement();
178:
179: DependencyManagement childDepMgmt = child
180: .getDependencyManagement();
181:
182: if (parentDepMgmt != null) {
183: if (childDepMgmt == null) {
184: child.setDependencyManagement(parentDepMgmt);
185: } else {
186: List childDeps = childDepMgmt.getDependencies();
187:
188: Map mappedChildDeps = new TreeMap();
189: for (Iterator it = childDeps.iterator(); it.hasNext();) {
190: Dependency dep = (Dependency) it.next();
191: mappedChildDeps.put(dep.getManagementKey(), dep);
192: }
193:
194: for (Iterator it = parentDepMgmt.getDependencies()
195: .iterator(); it.hasNext();) {
196: Dependency dep = (Dependency) it.next();
197: if (!mappedChildDeps.containsKey(dep
198: .getManagementKey())) {
199: childDepMgmt.addDependency(dep);
200: }
201: }
202: }
203: }
204: }
205:
206: private void assembleReportingInheritance(Model child, Model parent) {
207: // Reports :: aggregate
208: Reporting childReporting = child.getReporting();
209: Reporting parentReporting = parent.getReporting();
210:
211: if (parentReporting != null) {
212: if (childReporting == null) {
213: childReporting = new Reporting();
214: child.setReporting(childReporting);
215: }
216:
217: childReporting.setExcludeDefaults(parentReporting
218: .isExcludeDefaults());
219:
220: if (StringUtils
221: .isEmpty(childReporting.getOutputDirectory())) {
222: childReporting.setOutputDirectory(parentReporting
223: .getOutputDirectory());
224: }
225:
226: ModelUtils.mergeReportPluginLists(childReporting,
227: parentReporting, true);
228: }
229: }
230:
231: private void assembleDependencyInheritance(Model child, Model parent) {
232: Map depsMap = new LinkedHashMap();
233:
234: List deps = parent.getDependencies();
235:
236: if (deps != null) {
237: for (Iterator it = deps.iterator(); it.hasNext();) {
238: Dependency dependency = (Dependency) it.next();
239: depsMap.put(dependency.getManagementKey(), dependency);
240: }
241: }
242:
243: deps = child.getDependencies();
244:
245: if (deps != null) {
246: for (Iterator it = deps.iterator(); it.hasNext();) {
247: Dependency dependency = (Dependency) it.next();
248: depsMap.put(dependency.getManagementKey(), dependency);
249: }
250: }
251:
252: child.setDependencies(new ArrayList(depsMap.values()));
253: }
254:
255: private void assembleBuildInheritance(Model child, Model parent) {
256: Build childBuild = child.getBuild();
257: Build parentBuild = parent.getBuild();
258:
259: if (parentBuild != null) {
260: if (childBuild == null) {
261: childBuild = new Build();
262: child.setBuild(childBuild);
263: }
264:
265: // The build has been set but we want to step in here and fill in
266: // values that have not been set by the child.
267:
268: if (childBuild.getSourceDirectory() == null) {
269: childBuild.setSourceDirectory(parentBuild
270: .getSourceDirectory());
271: }
272:
273: if (childBuild.getScriptSourceDirectory() == null) {
274: childBuild.setScriptSourceDirectory(parentBuild
275: .getScriptSourceDirectory());
276: }
277:
278: if (childBuild.getTestSourceDirectory() == null) {
279: childBuild.setTestSourceDirectory(parentBuild
280: .getTestSourceDirectory());
281: }
282:
283: if (childBuild.getOutputDirectory() == null) {
284: childBuild.setOutputDirectory(parentBuild
285: .getOutputDirectory());
286: }
287:
288: if (childBuild.getTestOutputDirectory() == null) {
289: childBuild.setTestOutputDirectory(parentBuild
290: .getTestOutputDirectory());
291: }
292:
293: // Extensions are accumlated
294: ModelUtils.mergeExtensionLists(childBuild, parentBuild);
295:
296: if (childBuild.getDirectory() == null) {
297: childBuild.setDirectory(parentBuild.getDirectory());
298: }
299:
300: if (childBuild.getDefaultGoal() == null) {
301: childBuild.setDefaultGoal(parentBuild.getDefaultGoal());
302: }
303:
304: if (childBuild.getFinalName() == null) {
305: childBuild.setFinalName(parentBuild.getFinalName());
306: }
307:
308: ModelUtils.mergeFilterLists(childBuild.getFilters(),
309: parentBuild.getFilters());
310:
311: List resources = childBuild.getResources();
312: if (resources == null || resources.isEmpty()) {
313: childBuild.setResources(parentBuild.getResources());
314: }
315:
316: resources = childBuild.getTestResources();
317: if (resources == null || resources.isEmpty()) {
318: childBuild.setTestResources(parentBuild
319: .getTestResources());
320: }
321:
322: // Plugins are aggregated if Plugin.inherit != false
323: ModelUtils.mergePluginLists(childBuild, parentBuild, true);
324:
325: // Plugin management :: aggregate
326: PluginManagement dominantPM = childBuild
327: .getPluginManagement();
328: PluginManagement recessivePM = parentBuild
329: .getPluginManagement();
330:
331: if (dominantPM == null && recessivePM != null) {
332: childBuild.setPluginManagement(recessivePM);
333: } else {
334: ModelUtils.mergePluginLists(childBuild
335: .getPluginManagement(), parentBuild
336: .getPluginManagement(), false);
337: }
338: }
339: }
340:
341: private void assembleScmInheritance(Model child, Model parent,
342: String childPathAdjustment, boolean appendPaths) {
343: if (parent.getScm() != null) {
344: Scm parentScm = parent.getScm();
345:
346: Scm childScm = child.getScm();
347:
348: if (childScm == null) {
349: childScm = new Scm();
350:
351: child.setScm(childScm);
352: }
353:
354: if (StringUtils.isEmpty(childScm.getConnection())
355: && !StringUtils.isEmpty(parentScm.getConnection())) {
356: childScm.setConnection(appendPath(parentScm
357: .getConnection(), child.getArtifactId(),
358: childPathAdjustment, appendPaths));
359: }
360:
361: if (StringUtils.isEmpty(childScm.getDeveloperConnection())
362: && !StringUtils.isEmpty(parentScm
363: .getDeveloperConnection())) {
364: childScm.setDeveloperConnection(appendPath(parentScm
365: .getDeveloperConnection(), child
366: .getArtifactId(), childPathAdjustment,
367: appendPaths));
368: }
369:
370: if (StringUtils.isEmpty(childScm.getUrl())
371: && !StringUtils.isEmpty(parentScm.getUrl())) {
372: childScm.setUrl(appendPath(parentScm.getUrl(), child
373: .getArtifactId(), childPathAdjustment,
374: appendPaths));
375: }
376: }
377: }
378:
379: private void assembleDistributionInheritence(Model child,
380: Model parent, String childPathAdjustment,
381: boolean appendPaths) {
382: if (parent.getDistributionManagement() != null) {
383: DistributionManagement parentDistMgmt = parent
384: .getDistributionManagement();
385:
386: DistributionManagement childDistMgmt = child
387: .getDistributionManagement();
388:
389: if (childDistMgmt == null) {
390: childDistMgmt = new DistributionManagement();
391:
392: child.setDistributionManagement(childDistMgmt);
393: }
394:
395: if (childDistMgmt.getSite() == null) {
396: if (parentDistMgmt.getSite() != null) {
397: Site site = new Site();
398:
399: childDistMgmt.setSite(site);
400:
401: site.setId(parentDistMgmt.getSite().getId());
402:
403: site.setName(parentDistMgmt.getSite().getName());
404:
405: site.setUrl(parentDistMgmt.getSite().getUrl());
406:
407: if (site.getUrl() != null) {
408: site.setUrl(appendPath(site.getUrl(), child
409: .getArtifactId(), childPathAdjustment,
410: appendPaths));
411: }
412: }
413: }
414:
415: if (childDistMgmt.getRepository() == null) {
416: if (parentDistMgmt.getRepository() != null) {
417: DeploymentRepository repository = copyDistributionRepository(parentDistMgmt
418: .getRepository());
419: childDistMgmt.setRepository(repository);
420: }
421: }
422:
423: if (childDistMgmt.getSnapshotRepository() == null) {
424: if (parentDistMgmt.getSnapshotRepository() != null) {
425: DeploymentRepository repository = copyDistributionRepository(parentDistMgmt
426: .getSnapshotRepository());
427: childDistMgmt.setSnapshotRepository(repository);
428: }
429: }
430:
431: if (StringUtils.isEmpty(childDistMgmt.getDownloadUrl())) {
432: childDistMgmt.setDownloadUrl(parentDistMgmt
433: .getDownloadUrl());
434: }
435:
436: // NOTE: We SHOULD NOT be inheriting status, since this is an assessment of the POM quality.
437: // NOTE: We SHOULD NOT be inheriting relocation, since this relates to a single POM
438: }
439: }
440:
441: private static DeploymentRepository copyDistributionRepository(
442: DeploymentRepository parentRepository) {
443: DeploymentRepository repository = new DeploymentRepository();
444:
445: repository.setId(parentRepository.getId());
446:
447: repository.setName(parentRepository.getName());
448:
449: repository.setUrl(parentRepository.getUrl());
450:
451: repository.setLayout(parentRepository.getLayout());
452:
453: repository.setUniqueVersion(parentRepository.isUniqueVersion());
454:
455: return repository;
456: }
457:
458: // TODO: This should eventually be migrated to DefaultPathTranslator.
459: protected String appendPath(String parentPath, String childPath,
460: String pathAdjustment, boolean appendPaths) {
461: String uncleanPath = parentPath;
462:
463: if (appendPaths) {
464: if (pathAdjustment != null)
465: uncleanPath += "/" + pathAdjustment;
466:
467: if (childPath != null)
468: uncleanPath += "/" + childPath;
469: }
470:
471: String cleanedPath = "";
472:
473: int protocolIdx = uncleanPath.indexOf("://");
474:
475: if (protocolIdx > -1) {
476: cleanedPath = uncleanPath.substring(0, protocolIdx + 3);
477: uncleanPath = uncleanPath.substring(protocolIdx + 3);
478: }
479:
480: if (uncleanPath.startsWith("/"))
481: cleanedPath += "/";
482:
483: return cleanedPath + resolvePath(uncleanPath);
484: }
485:
486: // TODO: Move this to plexus-utils' PathTool.
487: private static String resolvePath(String uncleanPath) {
488: LinkedList pathElements = new LinkedList();
489:
490: StringTokenizer tokenizer = new StringTokenizer(uncleanPath,
491: "/");
492:
493: while (tokenizer.hasMoreTokens()) {
494: String token = (String) tokenizer.nextToken();
495:
496: if (token.equals("")) {
497: // Empty path entry ("...//.."), remove.
498: } else if (token.equals("..")) {
499: if (pathElements.isEmpty()) {
500: // FIXME: somehow report to the user
501: // that there are too many '..' elements.
502: // For now, ignore the extra '..'.
503: } else {
504: pathElements.removeLast();
505: }
506: } else {
507: pathElements.addLast(token);
508: }
509: }
510:
511: StringBuffer cleanedPath = new StringBuffer();
512:
513: while (!pathElements.isEmpty()) {
514: cleanedPath.append(pathElements.removeFirst());
515: if (!pathElements.isEmpty())
516: cleanedPath.append('/');
517: }
518:
519: return cleanedPath.toString();
520: }
521:
522: }
|