1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.doxia.tools;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.File;
26 import java.io.IOException;
27 import java.io.Reader;
28 import java.io.StringReader;
29 import java.io.StringWriter;
30 import java.net.MalformedURLException;
31 import java.net.URL;
32 import java.nio.file.Files;
33 import java.util.AbstractMap;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Locale;
39 import java.util.Map;
40 import java.util.Objects;
41 import java.util.StringTokenizer;
42
43 import org.apache.commons.io.FilenameUtils;
44 import org.apache.maven.RepositoryUtils;
45 import org.apache.maven.artifact.Artifact;
46 import org.apache.maven.artifact.DefaultArtifact;
47 import org.apache.maven.artifact.handler.ArtifactHandler;
48 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
49 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
50 import org.apache.maven.artifact.versioning.VersionRange;
51 import org.apache.maven.doxia.site.Banner;
52 import org.apache.maven.doxia.site.Body;
53 import org.apache.maven.doxia.site.Image;
54 import org.apache.maven.doxia.site.LinkItem;
55 import org.apache.maven.doxia.site.Logo;
56 import org.apache.maven.doxia.site.Menu;
57 import org.apache.maven.doxia.site.MenuItem;
58 import org.apache.maven.doxia.site.PublishDate;
59 import org.apache.maven.doxia.site.SiteModel;
60 import org.apache.maven.doxia.site.Skin;
61 import org.apache.maven.doxia.site.Version;
62 import org.apache.maven.doxia.site.decoration.DecorationModel;
63 import org.apache.maven.doxia.site.decoration.io.xpp3.DecorationXpp3Reader;
64 import org.apache.maven.doxia.site.inheritance.SiteModelInheritanceAssembler;
65 import org.apache.maven.doxia.site.io.xpp3.SiteXpp3Reader;
66 import org.apache.maven.doxia.site.io.xpp3.SiteXpp3Writer;
67 import org.apache.maven.model.DistributionManagement;
68 import org.apache.maven.model.Plugin;
69 import org.apache.maven.project.MavenProject;
70 import org.apache.maven.reporting.MavenReport;
71 import org.codehaus.plexus.i18n.I18N;
72 import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
73 import org.codehaus.plexus.interpolation.InterpolationException;
74 import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
75 import org.codehaus.plexus.interpolation.MapBasedValueSource;
76 import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
77 import org.codehaus.plexus.interpolation.PrefixedPropertiesValueSource;
78 import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
79 import org.codehaus.plexus.util.IOUtil;
80 import org.codehaus.plexus.util.ReaderFactory;
81 import org.codehaus.plexus.util.StringUtils;
82 import org.codehaus.plexus.util.xml.Xpp3Dom;
83 import org.codehaus.plexus.util.xml.pull.MXParser;
84 import org.codehaus.plexus.util.xml.pull.XmlPullParser;
85 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
86 import org.eclipse.aether.RepositorySystem;
87 import org.eclipse.aether.RepositorySystemSession;
88 import org.eclipse.aether.repository.LocalArtifactRequest;
89 import org.eclipse.aether.repository.LocalArtifactResult;
90 import org.eclipse.aether.repository.LocalRepositoryManager;
91 import org.eclipse.aether.repository.RemoteRepository;
92 import org.eclipse.aether.resolution.ArtifactRequest;
93 import org.eclipse.aether.resolution.ArtifactResolutionException;
94 import org.eclipse.aether.resolution.ArtifactResult;
95 import org.eclipse.aether.transfer.ArtifactNotFoundException;
96 import org.slf4j.Logger;
97 import org.slf4j.LoggerFactory;
98
99
100
101
102
103
104 @Singleton
105 @Named
106 public class DefaultSiteTool implements SiteTool {
107 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSiteTool.class);
108
109
110
111
112
113
114
115
116 @Inject
117 protected RepositorySystem repositorySystem;
118
119
120
121
122 @Inject
123 private ArtifactHandlerManager artifactHandlerManager;
124
125
126
127
128 @Inject
129 protected I18N i18n;
130
131
132
133
134 @Inject
135 protected SiteModelInheritanceAssembler assembler;
136
137
138
139
140
141
142 public Artifact getSkinArtifactFromRepository(
143 RepositorySystemSession repoSession, List<RemoteRepository> remoteProjectRepositories, Skin skin)
144 throws SiteToolException {
145 Objects.requireNonNull(repoSession, "repoSession cannot be null");
146 Objects.requireNonNull(remoteProjectRepositories, "remoteProjectRepositories cannot be null");
147 Objects.requireNonNull(skin, "skin cannot be null");
148
149 String version = skin.getVersion();
150 try {
151 if (version == null) {
152 version = Artifact.RELEASE_VERSION;
153 }
154 VersionRange versionSpec = VersionRange.createFromVersionSpec(version);
155 String type = "jar";
156 Artifact artifact = new DefaultArtifact(
157 skin.getGroupId(),
158 skin.getArtifactId(),
159 versionSpec,
160 Artifact.SCOPE_RUNTIME,
161 type,
162 null,
163 artifactHandlerManager.getArtifactHandler(type));
164 ArtifactRequest request =
165 new ArtifactRequest(RepositoryUtils.toArtifact(artifact), remoteProjectRepositories, "remote-skin");
166 ArtifactResult result = repositorySystem.resolveArtifact(repoSession, request);
167
168 return RepositoryUtils.toArtifact(result.getArtifact());
169 } catch (InvalidVersionSpecificationException e) {
170 throw new SiteToolException("The skin version '" + version + "' is not valid", e);
171 } catch (ArtifactResolutionException e) {
172 if (e.getCause() instanceof ArtifactNotFoundException) {
173 throw new SiteToolException("The skin does not exist", e.getCause());
174 }
175
176 throw new SiteToolException("Unable to find skin", e);
177 }
178 }
179
180
181
182
183
184
185 @Deprecated
186 public String getRelativePath(String to, String from) {
187 Objects.requireNonNull(to, "to cannot be null");
188 Objects.requireNonNull(from, "from cannot be null");
189
190 if (to.contains(":") && from.contains(":")) {
191 String toScheme = to.substring(0, to.lastIndexOf(':'));
192 String fromScheme = from.substring(0, from.lastIndexOf(':'));
193 if (!toScheme.equals(fromScheme)) {
194 return to;
195 }
196 }
197
198 URL toUrl = null;
199 URL fromUrl = null;
200
201 String toPath = to;
202 String fromPath = from;
203
204 try {
205 toUrl = new URL(to);
206 } catch (MalformedURLException e) {
207 try {
208 toUrl = new File(getNormalizedPath(to)).toURI().toURL();
209 } catch (MalformedURLException e1) {
210 LOGGER.warn("Unable to load a URL for '" + to + "'", e);
211 return to;
212 }
213 }
214
215 try {
216 fromUrl = new URL(from);
217 } catch (MalformedURLException e) {
218 try {
219 fromUrl = new File(getNormalizedPath(from)).toURI().toURL();
220 } catch (MalformedURLException e1) {
221 LOGGER.warn("Unable to load a URL for '" + from + "'", e);
222 return to;
223 }
224 }
225
226 if (toUrl != null && fromUrl != null) {
227
228
229 if ((toUrl.getProtocol().equalsIgnoreCase(fromUrl.getProtocol()))
230 && (toUrl.getHost().equalsIgnoreCase(fromUrl.getHost()))
231 && (toUrl.getPort() == fromUrl.getPort())) {
232
233
234 toPath = toUrl.getFile();
235 fromPath = fromUrl.getFile();
236 } else {
237
238
239 return to;
240 }
241 } else if ((toUrl != null && fromUrl == null) || (toUrl == null && fromUrl != null)) {
242
243
244 return to;
245 }
246
247
248
249
250
251 String relativePath = getRelativeFilePath(fromPath, toPath);
252
253 if (relativePath == null) {
254 relativePath = to;
255 }
256
257 if (LOGGER.isDebugEnabled() && !relativePath.toString().equals(to)) {
258 LOGGER.debug("Mapped url: " + to + " to relative path: " + relativePath);
259 }
260
261 return relativePath;
262 }
263
264 private static String getRelativeFilePath(final String oldPath, final String newPath) {
265
266
267 String fromPath = new File(oldPath).getPath();
268 String toPath = new File(newPath).getPath();
269
270
271 if (toPath.matches("^\\[a-zA-Z]:")) {
272 toPath = toPath.substring(1);
273 }
274 if (fromPath.matches("^\\[a-zA-Z]:")) {
275 fromPath = fromPath.substring(1);
276 }
277
278
279 if (fromPath.startsWith(":", 1)) {
280 fromPath = Character.toLowerCase(fromPath.charAt(0)) + fromPath.substring(1);
281 }
282 if (toPath.startsWith(":", 1)) {
283 toPath = Character.toLowerCase(toPath.charAt(0)) + toPath.substring(1);
284 }
285
286
287
288
289 if ((toPath.startsWith(":", 1) && fromPath.startsWith(":", 1))
290 && (!toPath.substring(0, 1).equals(fromPath.substring(0, 1)))) {
291
292
293
294 return null;
295 }
296
297 if ((toPath.startsWith(":", 1) && !fromPath.startsWith(":", 1))
298 || (!toPath.startsWith(":", 1) && fromPath.startsWith(":", 1))) {
299
300
301
302
303 return null;
304 }
305
306 final String relativePath = buildRelativePath(toPath, fromPath, File.separatorChar);
307
308 return relativePath.toString();
309 }
310
311
312 public File getSiteDescriptor(File siteDirectory, Locale locale) {
313 Objects.requireNonNull(siteDirectory, "siteDirectory cannot be null");
314 Objects.requireNonNull(locale, "locale cannot be null");
315
316 String variant = locale.getVariant();
317 String country = locale.getCountry();
318 String language = locale.getLanguage();
319
320 File siteDescriptor = null;
321
322 if (!variant.isEmpty()) {
323 siteDescriptor = new File(siteDirectory, "site_" + language + "_" + country + "_" + variant + ".xml");
324 }
325
326 if ((siteDescriptor == null || !siteDescriptor.isFile()) && !country.isEmpty()) {
327 siteDescriptor = new File(siteDirectory, "site_" + language + "_" + country + ".xml");
328 }
329
330 if ((siteDescriptor == null || !siteDescriptor.isFile()) && !language.isEmpty()) {
331 siteDescriptor = new File(siteDirectory, "site_" + language + ".xml");
332 }
333
334 if (siteDescriptor == null || !siteDescriptor.isFile()) {
335 siteDescriptor = new File(siteDirectory, "site.xml");
336 }
337
338 return siteDescriptor;
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352
353 File getSiteDescriptorFromRepository(
354 MavenProject project,
355 RepositorySystemSession repoSession,
356 List<RemoteRepository> remoteProjectRepositories,
357 Locale locale)
358 throws SiteToolException {
359 Objects.requireNonNull(project, "project cannot be null");
360 Objects.requireNonNull(repoSession, "repoSession cannot be null");
361 Objects.requireNonNull(remoteProjectRepositories, "remoteProjectRepositories cannot be null");
362 Objects.requireNonNull(locale, "locale cannot be null");
363
364 try {
365 File siteDescriptor = resolveSiteDescriptor(project, repoSession, remoteProjectRepositories, locale);
366 if (siteDescriptor == null) {
367 LOGGER.debug("Site descriptor not found");
368 return null;
369 } else {
370 return siteDescriptor;
371 }
372 } catch (ArtifactResolutionException e) {
373 throw new SiteToolException("Unable to locate site descriptor", e);
374 }
375 }
376
377
378 public SiteModel getSiteModel(
379 File siteDirectory,
380 Locale locale,
381 MavenProject project,
382 List<MavenProject> reactorProjects,
383 RepositorySystemSession repoSession,
384 List<RemoteRepository> remoteProjectRepositories)
385 throws SiteToolException {
386 Objects.requireNonNull(locale, "locale cannot be null");
387 Objects.requireNonNull(project, "project cannot be null");
388 Objects.requireNonNull(reactorProjects, "reactorProjects cannot be null");
389 Objects.requireNonNull(repoSession, "repoSession cannot be null");
390 Objects.requireNonNull(remoteProjectRepositories, "remoteProjectRepositories cannot be null");
391
392 LOGGER.debug("Computing site model of '" + project.getId() + "' for "
393 + (locale.equals(SiteTool.DEFAULT_LOCALE) ? "default locale" : "locale '" + locale + "'"));
394
395 Map.Entry<SiteModel, MavenProject> result =
396 getSiteModel(0, siteDirectory, locale, project, repoSession, remoteProjectRepositories);
397 SiteModel siteModel = result.getKey();
398 MavenProject parentProject = result.getValue();
399
400 if (siteModel == null) {
401 LOGGER.debug("Using default site descriptor");
402 siteModel = getDefaultSiteModel();
403 }
404
405
406 String siteDescriptorContent = siteModelToString(siteModel);
407
408
409 siteDescriptorContent = getInterpolatedSiteDescriptorContent(project, siteDescriptorContent, false);
410
411 siteModel = readSiteModel(siteDescriptorContent, project, locale);
412
413 if (parentProject != null) {
414 populateParentMenu(siteModel, locale, project, parentProject, true);
415 }
416
417 try {
418 populateModulesMenu(siteModel, locale, project, reactorProjects, true);
419 } catch (IOException e) {
420 throw new SiteToolException("Error while populating modules menu", e);
421 }
422
423 return siteModel;
424 }
425
426
427 public String getInterpolatedSiteDescriptorContent(
428 Map<String, String> props, MavenProject aProject, String siteDescriptorContent) throws SiteToolException {
429 Objects.requireNonNull(props, "props cannot be null");
430
431
432 return getInterpolatedSiteDescriptorContent(aProject, siteDescriptorContent, false);
433 }
434
435 private String getInterpolatedSiteDescriptorContent(
436 MavenProject aProject, String siteDescriptorContent, boolean isEarly) throws SiteToolException {
437 Objects.requireNonNull(aProject, "aProject cannot be null");
438 Objects.requireNonNull(siteDescriptorContent, "siteDescriptorContent cannot be null");
439
440 RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
441
442 if (isEarly) {
443 interpolator.addValueSource(new PrefixedObjectValueSource("this.", aProject));
444 interpolator.addValueSource(new PrefixedPropertiesValueSource("this.", aProject.getProperties()));
445 } else {
446 interpolator.addValueSource(new PrefixedObjectValueSource("project.", aProject));
447 interpolator.addValueSource(new MapBasedValueSource(aProject.getProperties()));
448
449 try {
450 interpolator.addValueSource(new EnvarBasedValueSource());
451 } catch (IOException e) {
452
453 throw new SiteToolException("Cannot interpolate environment properties", e);
454 }
455 }
456
457 interpolator.addPostProcessor(new InterpolationPostProcessor() {
458 @Override
459 public Object execute(String expression, Object value) {
460 if (value != null) {
461
462 return value.toString()
463 .replace("&", "&")
464 .replace("<", "<")
465 .replace(">", ">")
466 .replace("\"", """)
467 .replace("'", "'");
468 }
469 return null;
470 }
471 });
472
473 try {
474 return interpolator.interpolate(siteDescriptorContent);
475 } catch (InterpolationException e) {
476 throw new SiteToolException("Cannot interpolate site descriptor", e);
477 }
478 }
479
480
481
482
483
484
485
486
487
488
489
490 private void populateParentMenu(
491 SiteModel siteModel,
492 Locale locale,
493 MavenProject project,
494 MavenProject parentProject,
495 boolean keepInheritedRefs) {
496 Objects.requireNonNull(siteModel, "siteModel cannot be null");
497 Objects.requireNonNull(locale, "locale cannot be null");
498 Objects.requireNonNull(project, "project cannot be null");
499 Objects.requireNonNull(parentProject, "parentProject cannot be null");
500
501 Menu menu = siteModel.getMenuRef("parent");
502
503 if (menu == null) {
504 return;
505 }
506
507 if (keepInheritedRefs && menu.isInheritAsRef()) {
508 return;
509 }
510
511 String parentUrl = getDistMgmntSiteUrl(parentProject);
512
513 if (parentUrl != null) {
514 if (parentUrl.endsWith("/")) {
515 parentUrl += "index.html";
516 } else {
517 parentUrl += "/index.html";
518 }
519
520 parentUrl = getRelativePath(parentUrl, getDistMgmntSiteUrl(project));
521 } else {
522
523 File parentBasedir = parentProject.getBasedir();
524
525 if (parentBasedir != null) {
526
527 String parentPath = parentBasedir.getAbsolutePath();
528 String projectPath = project.getBasedir().getAbsolutePath();
529 parentUrl = getRelativePath(parentPath, projectPath) + "/index.html";
530 }
531 }
532
533
534 if (parentUrl == null) {
535 LOGGER.warn("Unable to find a URL to the parent project. The parent menu will NOT be added.");
536 } else {
537 if (menu.getName() == null) {
538 menu.setName(i18n.getString("site-tool", locale, "siteModel.menu.parentproject"));
539 }
540
541 MenuItem item = new MenuItem();
542 item.setName(parentProject.getName());
543 item.setHref(parentUrl);
544 menu.addItem(item);
545 }
546 }
547
548
549
550
551
552
553
554
555
556
557
558
559
560 private void populateModulesMenu(
561 SiteModel siteModel,
562 Locale locale,
563 MavenProject project,
564 List<MavenProject> reactorProjects,
565 boolean keepInheritedRefs)
566 throws SiteToolException, IOException {
567 Objects.requireNonNull(siteModel, "siteModel cannot be null");
568 Objects.requireNonNull(locale, "locale cannot be null");
569 Objects.requireNonNull(project, "project cannot be null");
570 Objects.requireNonNull(reactorProjects, "reactorProjects cannot be null");
571
572 Menu menu = siteModel.getMenuRef("modules");
573
574 if (menu == null) {
575 return;
576 }
577
578 if (keepInheritedRefs && menu.isInheritAsRef()) {
579 return;
580 }
581
582
583 if (!project.getModules().isEmpty()) {
584 if (menu.getName() == null) {
585 menu.setName(i18n.getString("site-tool", locale, "siteModel.menu.projectmodules"));
586 }
587
588 for (String module : project.getModules()) {
589 MavenProject moduleProject = getModuleFromReactor(project, reactorProjects, module);
590
591 if (moduleProject == null) {
592 LOGGER.debug("Module " + module + " not found in reactor");
593 continue;
594 }
595
596 final String pluginId = "org.apache.maven.plugins:maven-site-plugin";
597 String skipFlag = getPluginParameter(moduleProject, pluginId, "skip");
598 if (skipFlag == null) {
599 skipFlag = moduleProject.getProperties().getProperty("maven.site.skip");
600 }
601
602 String siteUrl = "true".equalsIgnoreCase(skipFlag) ? null : getDistMgmntSiteUrl(moduleProject);
603 String itemName =
604 (moduleProject.getName() == null) ? moduleProject.getArtifactId() : moduleProject.getName();
605 String defaultSiteUrl = "true".equalsIgnoreCase(skipFlag) ? null : moduleProject.getArtifactId();
606
607 appendMenuItem(project, menu, itemName, siteUrl, defaultSiteUrl);
608 }
609 } else if (siteModel.getMenuRef("modules").getInherit() == null) {
610
611 siteModel.removeMenuRef("modules");
612 }
613 }
614
615 private MavenProject getModuleFromReactor(MavenProject project, List<MavenProject> reactorProjects, String module)
616 throws IOException {
617 File moduleBasedir = new File(project.getBasedir(), module).getCanonicalFile();
618
619 for (MavenProject reactorProject : reactorProjects) {
620 if (moduleBasedir.equals(reactorProject.getBasedir())) {
621 return reactorProject;
622 }
623 }
624
625
626 return null;
627 }
628
629
630 public void populateReportsMenu(SiteModel siteModel, Locale locale, Map<String, List<MavenReport>> categories) {
631 Objects.requireNonNull(siteModel, "siteModel cannot be null");
632 Objects.requireNonNull(locale, "locale cannot be null");
633 Objects.requireNonNull(categories, "categories cannot be null");
634
635 Menu menu = siteModel.getMenuRef("reports");
636
637 if (menu == null) {
638 return;
639 }
640
641 if (menu.getName() == null) {
642 menu.setName(i18n.getString("site-tool", locale, "siteModel.menu.projectdocumentation"));
643 }
644
645 boolean found = false;
646 if (menu.getItems().isEmpty()) {
647 List<MavenReport> categoryReports = categories.get(MavenReport.CATEGORY_PROJECT_INFORMATION);
648 if (!isEmptyList(categoryReports)) {
649 MenuItem item = createCategoryMenu(
650 i18n.getString("site-tool", locale, "siteModel.menu.projectinformation"),
651 "/project-info.html",
652 categoryReports,
653 locale);
654 menu.getItems().add(item);
655 found = true;
656 }
657
658 categoryReports = categories.get(MavenReport.CATEGORY_PROJECT_REPORTS);
659 if (!isEmptyList(categoryReports)) {
660 MenuItem item = createCategoryMenu(
661 i18n.getString("site-tool", locale, "siteModel.menu.projectreports"),
662 "/project-reports.html",
663 categoryReports,
664 locale);
665 menu.getItems().add(item);
666 found = true;
667 }
668 }
669 if (!found) {
670 siteModel.removeMenuRef("reports");
671 }
672 }
673
674
675 public List<Locale> getSiteLocales(String locales) {
676 if (locales == null) {
677 return Collections.singletonList(DEFAULT_LOCALE);
678 }
679
680 String[] localesArray = StringUtils.split(locales, ",");
681 List<Locale> localesList = new ArrayList<>(localesArray.length);
682 List<Locale> availableLocales = Arrays.asList(Locale.getAvailableLocales());
683
684 for (String localeString : localesArray) {
685 Locale locale = codeToLocale(localeString);
686
687 if (locale == null) {
688 continue;
689 }
690
691 if (!availableLocales.contains(locale)) {
692 if (LOGGER.isWarnEnabled()) {
693 LOGGER.warn("The locale defined by '" + locale
694 + "' is not available in this Java Virtual Machine ("
695 + System.getProperty("java.version")
696 + " from " + System.getProperty("java.vendor") + ") - IGNORING");
697 }
698 continue;
699 }
700
701 Locale bundleLocale = i18n.getBundle("site-tool", locale).getLocale();
702 if (!(bundleLocale.equals(locale) || bundleLocale.getLanguage().equals(locale.getLanguage()))) {
703 if (LOGGER.isWarnEnabled()) {
704 LOGGER.warn("The locale '" + locale + "' (" + locale.getDisplayName(Locale.ENGLISH)
705 + ") is not currently supported by Maven Site - IGNORING."
706 + System.lineSeparator() + "Contributions are welcome and greatly appreciated!"
707 + System.lineSeparator() + "If you want to contribute a new translation, please visit "
708 + "https://maven.apache.org/plugins/localization.html for detailed instructions.");
709 }
710
711 continue;
712 }
713
714 localesList.add(locale);
715 }
716
717 if (localesList.isEmpty()) {
718 localesList = Collections.singletonList(DEFAULT_LOCALE);
719 }
720
721 return localesList;
722 }
723
724
725
726
727
728
729
730
731
732
733
734
735
736 private Locale codeToLocale(String localeCode) {
737 if (localeCode == null) {
738 return null;
739 }
740
741 if ("system".equalsIgnoreCase(localeCode)) {
742 return Locale.getDefault();
743 }
744
745 if ("default".equalsIgnoreCase(localeCode)) {
746 return SiteTool.DEFAULT_LOCALE;
747 }
748
749 String language = "";
750 String country = "";
751 String variant = "";
752
753 StringTokenizer tokenizer = new StringTokenizer(localeCode, "_");
754 final int maxTokens = 3;
755 if (tokenizer.countTokens() > maxTokens) {
756 if (LOGGER.isWarnEnabled()) {
757 LOGGER.warn("Invalid java.util.Locale format for '" + localeCode + "' entry - IGNORING");
758 }
759 return null;
760 }
761
762 if (tokenizer.hasMoreTokens()) {
763 language = tokenizer.nextToken();
764 if (tokenizer.hasMoreTokens()) {
765 country = tokenizer.nextToken();
766 if (tokenizer.hasMoreTokens()) {
767 variant = tokenizer.nextToken();
768 }
769 }
770 }
771
772 return new Locale(language, country, variant);
773 }
774
775
776
777
778
779
780
781
782
783
784 protected static String getNormalizedPath(String path) {
785 String normalized = FilenameUtils.normalize(path);
786 if (normalized == null) {
787 normalized = path;
788 }
789 return (normalized == null) ? null : normalized.replace('\\', '/');
790 }
791
792
793
794
795
796
797
798
799
800
801
802 private ArtifactRequest createSiteDescriptorArtifactRequest(
803 MavenProject project, String localeStr, List<RemoteRepository> remoteProjectRepositories) {
804 String type = "xml";
805 ArtifactHandler artifactHandler = artifactHandlerManager.getArtifactHandler(type);
806 Artifact artifact = new DefaultArtifact(
807 project.getGroupId(),
808 project.getArtifactId(),
809 project.getVersion(),
810 Artifact.SCOPE_RUNTIME,
811 type,
812 "site" + (localeStr.isEmpty() ? "" : "_" + localeStr),
813 artifactHandler);
814 return new ArtifactRequest(
815 RepositoryUtils.toArtifact(artifact), remoteProjectRepositories, "remote-site-descriptor");
816 }
817
818
819
820
821
822
823
824
825
826 private File resolveSiteDescriptor(
827 MavenProject project,
828 RepositorySystemSession repoSession,
829 List<RemoteRepository> remoteProjectRepositories,
830 Locale locale)
831 throws ArtifactResolutionException {
832 String variant = locale.getVariant();
833 String country = locale.getCountry();
834 String language = locale.getLanguage();
835
836 String localeStr = null;
837 File siteDescriptor = null;
838 boolean found = false;
839
840 if (!variant.isEmpty()) {
841 localeStr = language + "_" + country + "_" + variant;
842 ArtifactRequest request =
843 createSiteDescriptorArtifactRequest(project, localeStr, remoteProjectRepositories);
844
845 deletePseudoSiteDescriptorMarkerFile(repoSession, request);
846
847 try {
848 ArtifactResult result = repositorySystem.resolveArtifact(repoSession, request);
849
850 siteDescriptor = result.getArtifact().getFile();
851 found = true;
852 } catch (ArtifactResolutionException e) {
853
854 if (e.getResult().getExceptions().stream().anyMatch(re -> re instanceof ArtifactNotFoundException)) {
855 LOGGER.debug("No site descriptor found for '" + project.getId() + "' for locale '" + localeStr
856 + "', trying without variant...");
857 } else {
858 throw e;
859 }
860 }
861 }
862
863 if (!found && !country.isEmpty()) {
864 localeStr = language + "_" + country;
865 ArtifactRequest request =
866 createSiteDescriptorArtifactRequest(project, localeStr, remoteProjectRepositories);
867
868 deletePseudoSiteDescriptorMarkerFile(repoSession, request);
869
870 try {
871 ArtifactResult result = repositorySystem.resolveArtifact(repoSession, request);
872
873 siteDescriptor = result.getArtifact().getFile();
874 found = true;
875 } catch (ArtifactResolutionException e) {
876
877 if (e.getResult().getExceptions().stream().anyMatch(re -> re instanceof ArtifactNotFoundException)) {
878 LOGGER.debug("No site descriptor found for '" + project.getId() + "' for locale '" + localeStr
879 + "', trying without country...");
880 } else {
881 throw e;
882 }
883 }
884 }
885
886 if (!found && !language.isEmpty()) {
887 localeStr = language;
888 ArtifactRequest request =
889 createSiteDescriptorArtifactRequest(project, localeStr, remoteProjectRepositories);
890
891 deletePseudoSiteDescriptorMarkerFile(repoSession, request);
892
893 try {
894 ArtifactResult result = repositorySystem.resolveArtifact(repoSession, request);
895
896 siteDescriptor = result.getArtifact().getFile();
897 found = true;
898 } catch (ArtifactResolutionException e) {
899
900 if (e.getResult().getExceptions().stream().anyMatch(re -> re instanceof ArtifactNotFoundException)) {
901 LOGGER.debug("No site descriptor found for '" + project.getId() + "' for locale '" + localeStr
902 + "', trying without language (default locale)...");
903 } else {
904 throw e;
905 }
906 }
907 }
908
909 if (!found) {
910 localeStr = SiteTool.DEFAULT_LOCALE.toString();
911 ArtifactRequest request =
912 createSiteDescriptorArtifactRequest(project, localeStr, remoteProjectRepositories);
913
914 deletePseudoSiteDescriptorMarkerFile(repoSession, request);
915
916 try {
917 ArtifactResult result = repositorySystem.resolveArtifact(repoSession, request);
918
919 siteDescriptor = result.getArtifact().getFile();
920 } catch (ArtifactResolutionException e) {
921
922 if (e.getResult().getExceptions().stream().anyMatch(re -> re instanceof ArtifactNotFoundException)) {
923 LOGGER.debug("No site descriptor found for '" + project.getId() + "' with default locale");
924 return null;
925 }
926
927 throw e;
928 }
929 }
930
931 return siteDescriptor;
932 }
933
934
935 private void deletePseudoSiteDescriptorMarkerFile(RepositorySystemSession repoSession, ArtifactRequest request) {
936 LocalRepositoryManager lrm = repoSession.getLocalRepositoryManager();
937
938 LocalArtifactRequest localRequest =
939 new LocalArtifactRequest(request.getArtifact(), request.getRepositories(), request.getRequestContext());
940
941 LocalArtifactResult localResult = lrm.find(repoSession, localRequest);
942 File localArtifactFile = localResult.getFile();
943
944 try {
945 if (localResult.isAvailable() && Files.size(localArtifactFile.toPath()) == 0L) {
946 LOGGER.debug(
947 "Deleting 0-byte pseudo marker file for artifact '{}' at '{}'",
948 localRequest.getArtifact(),
949 localArtifactFile);
950 Files.delete(localArtifactFile.toPath());
951 }
952 } catch (IOException e) {
953 LOGGER.debug("Failed to delete 0-byte pseudo marker file for artifact '{}'", localRequest.getArtifact(), e);
954 }
955 }
956
957
958
959
960
961
962
963
964
965
966
967 private Map.Entry<SiteModel, MavenProject> getSiteModel(
968 int depth,
969 File siteDirectory,
970 Locale locale,
971 MavenProject project,
972 RepositorySystemSession repoSession,
973 List<RemoteRepository> remoteProjectRepositories)
974 throws SiteToolException {
975
976 File siteDescriptor;
977 if (project.getBasedir() == null) {
978
979 try {
980 siteDescriptor =
981 getSiteDescriptorFromRepository(project, repoSession, remoteProjectRepositories, locale);
982 } catch (SiteToolException e) {
983 throw new SiteToolException("The site descriptor cannot be resolved from the repository", e);
984 }
985 } else {
986
987 siteDescriptor = getSiteDescriptor(siteDirectory, locale);
988 }
989
990
991 SiteModel siteModel = null;
992 Reader siteDescriptorReader = null;
993 try {
994 if (siteDescriptor != null && siteDescriptor.exists()) {
995 LOGGER.debug("Reading" + (depth == 0 ? "" : (" parent level " + depth)) + " site descriptor from "
996 + siteDescriptor);
997
998 siteDescriptorReader = ReaderFactory.newXmlReader(siteDescriptor);
999
1000 String siteDescriptorContent = IOUtil.toString(siteDescriptorReader);
1001
1002
1003 siteDescriptorContent = getInterpolatedSiteDescriptorContent(project, siteDescriptorContent, true);
1004
1005 siteModel = readSiteModel(siteDescriptorContent, project, locale);
1006 siteModel.setLastModified(siteDescriptor.lastModified());
1007 } else {
1008 LOGGER.debug("No" + (depth == 0 ? "" : (" parent level " + depth)) + " site descriptor");
1009 }
1010 } catch (IOException e) {
1011 throw new SiteToolException(
1012 "The site descriptor for '" + project.getId() + "' cannot be read from " + siteDescriptor, e);
1013 } finally {
1014 IOUtil.close(siteDescriptorReader);
1015 }
1016
1017
1018 MavenProject parentProject = project.getParent();
1019
1020
1021 if (parentProject != null && (siteModel == null || siteModel.isMergeParent() || siteModel.isRequireParent())) {
1022 depth++;
1023 LOGGER.debug("Looking for site descriptor of level " + depth + " parent project: " + parentProject.getId());
1024
1025 File parentSiteDirectory = null;
1026 if (parentProject.getBasedir() != null) {
1027
1028 String siteRelativePath = getRelativeFilePath(
1029 project.getBasedir().getAbsolutePath(),
1030 siteDescriptor.getParentFile().getAbsolutePath());
1031
1032 parentSiteDirectory = new File(parentProject.getBasedir(), siteRelativePath);
1033
1034
1035 }
1036
1037 SiteModel parentSiteModel = getSiteModel(
1038 depth, parentSiteDirectory, locale, parentProject, repoSession, remoteProjectRepositories)
1039 .getKey();
1040
1041 if (siteModel != null) {
1042 if (siteModel.isRequireParent() && parentSiteModel == null) {
1043 throw new SiteToolException(
1044 "The site descriptor for '" + project.getId() + "' requires a parent site descriptor for '"
1045 + parentProject.getId() + "' or any of its parents but none could be found!");
1046 }
1047 }
1048
1049
1050 if (siteModel == null && parentSiteModel != null) {
1051
1052
1053 siteModel = new SiteModel();
1054 }
1055
1056 String name = project.getName();
1057 if (siteModel != null && StringUtils.isNotEmpty(siteModel.getName())) {
1058 name = siteModel.getName();
1059 }
1060
1061
1062 String projectDistMgmnt = getDistMgmntSiteUrl(project);
1063 String parentDistMgmnt = getDistMgmntSiteUrl(parentProject);
1064 if (LOGGER.isDebugEnabled()) {
1065 LOGGER.debug("Site model inheritance: assembling child with level " + depth
1066 + " parent: distributionManagement.site.url child = " + projectDistMgmnt + " and parent = "
1067 + parentDistMgmnt);
1068 }
1069 assembler.assembleModelInheritance(
1070 name,
1071 siteModel,
1072 parentSiteModel,
1073 projectDistMgmnt,
1074 parentDistMgmnt == null ? projectDistMgmnt : parentDistMgmnt);
1075 } else if (parentProject == null && siteModel != null && siteModel.isRequireParent()) {
1076 throw new SiteToolException("The site descriptor for '" + project.getId()
1077 + "' requires a parent site descriptor but no parent is defined in the POM.");
1078 }
1079
1080 return new AbstractMap.SimpleEntry<>(siteModel, parentProject);
1081 }
1082
1083
1084
1085
1086
1087
1088 private SiteModel readSiteModel(String siteDescriptorContent, MavenProject project, Locale locale)
1089 throws SiteToolException {
1090 try {
1091 if (project != null && isOldSiteModel(siteDescriptorContent)) {
1092 LOGGER.warn(
1093 "Site model of '" + project.getId() + "' for "
1094 + (locale.equals(SiteTool.DEFAULT_LOCALE)
1095 ? "default locale"
1096 : "locale '" + locale + "'")
1097 + " is still using the old pre-version 2.0.0 model. You MUST migrate to the new model as soon as possible otherwise your build will break in the future!");
1098 return convertOldToNewSiteModel(
1099 new DecorationXpp3Reader().read(new StringReader(siteDescriptorContent)));
1100 } else {
1101 return new SiteXpp3Reader().read(new StringReader(siteDescriptorContent));
1102 }
1103 } catch (XmlPullParserException e) {
1104 throw new SiteToolException("Error parsing site descriptor", e);
1105 } catch (IOException e) {
1106 throw new SiteToolException("Error reading site descriptor", e);
1107 }
1108 }
1109
1110 private SiteModel convertOldToNewSiteModel(DecorationModel oldModel) {
1111 SiteModel newModel = new SiteModel();
1112 newModel.setName(oldModel.getName());
1113 newModel.setCombineSelf(oldModel.getCombineSelf());
1114 if (oldModel.getBannerLeft() != null) {
1115 newModel.setBannerLeft(convertBanner(oldModel.getBannerLeft()));
1116 }
1117 if (oldModel.getBannerRight() != null) {
1118 newModel.setBannerRight(convertBanner(oldModel.getBannerRight()));
1119 }
1120 if (!oldModel.isDefaultPublishDate()) {
1121 PublishDate newPublishDate = new PublishDate();
1122 newPublishDate.setFormat(oldModel.getPublishDate().getFormat());
1123 newPublishDate.setPosition(oldModel.getPublishDate().getPosition());
1124 newPublishDate.setTimezone(oldModel.getPublishDate().getTimezone());
1125 newModel.setPublishDate(newPublishDate);
1126 }
1127 if (!oldModel.isDefaultVersion()) {
1128 Version newVersion = new Version();
1129 newVersion.setPosition(oldModel.getVersion().getPosition());
1130 newModel.setVersion(newVersion);
1131 }
1132 newModel.setEdit(oldModel.getEdit());
1133 if (oldModel.getSkin() != null) {
1134 Skin newSkin = new Skin();
1135 newSkin.setGroupId(oldModel.getSkin().getGroupId());
1136 newSkin.setArtifactId(oldModel.getSkin().getArtifactId());
1137 newSkin.setVersion(oldModel.getSkin().getVersion());
1138 newModel.setSkin(newSkin);
1139 }
1140
1141 for (org.apache.maven.doxia.site.decoration.Logo oldLogo : oldModel.getPoweredBy()) {
1142 Logo newLogo = new Logo();
1143 newLogo.setName(oldLogo.getName());
1144 newLogo.setHref(oldLogo.getHref());
1145 newLogo.setTarget(oldLogo.getTarget());
1146 if (oldLogo.getImg() != null) {
1147 newLogo.setImage(convertImage(
1148 oldLogo.getImg(),
1149 oldLogo.getPosition(),
1150 oldLogo.getHeight(),
1151 oldLogo.getWidth(),
1152 oldLogo.getBorder(),
1153 oldLogo.getAlt()));
1154 }
1155 newModel.addPoweredBy(newLogo);
1156 }
1157 newModel.setLastModified(oldModel.getLastModified());
1158 if (oldModel.getBody() != null) {
1159 Body newBody = new Body();
1160 newBody.setHead(oldModel.getBody().getHead());
1161 for (org.apache.maven.doxia.site.decoration.LinkItem oldLink :
1162 oldModel.getBody().getLinks()) {
1163 newBody.addLink(convertLinkItem(oldLink));
1164 }
1165 for (org.apache.maven.doxia.site.decoration.LinkItem oldBreadcrumb :
1166 oldModel.getBody().getBreadcrumbs()) {
1167 newBody.addBreadcrumb(convertLinkItem(oldBreadcrumb));
1168 }
1169
1170 for (org.apache.maven.doxia.site.decoration.Menu oldMenu :
1171 oldModel.getBody().getMenus()) {
1172 Menu newMenu = new Menu();
1173 newMenu.setName(oldMenu.getName());
1174 newMenu.setInherit(oldMenu.getInherit());
1175 newMenu.setInheritAsRef(oldMenu.isInheritAsRef());
1176 newMenu.setRef(oldMenu.getRef());
1177 if (oldMenu.getImg() != null) {
1178 newMenu.setImage(convertImage(
1179 oldMenu.getImg(),
1180 oldMenu.getPosition(),
1181 oldMenu.getHeight(),
1182 oldMenu.getWidth(),
1183 oldMenu.getBorder(),
1184 oldMenu.getAlt()));
1185 }
1186 newMenu.setItems(convertMenuItems(oldMenu.getItems()));
1187 newBody.addMenu(newMenu);
1188 }
1189
1190 newBody.setFooter(oldModel.getBody().getFooter());
1191 newModel.setBody(newBody);
1192 }
1193 newModel.setCustom(oldModel.getCustom());
1194
1195 return newModel;
1196 }
1197
1198 private Banner convertBanner(org.apache.maven.doxia.site.decoration.Banner oldBanner) {
1199 Banner newBanner = new Banner();
1200 newBanner.setName(oldBanner.getName());
1201 newBanner.setHref(oldBanner.getHref());
1202 if (oldBanner.getSrc() != null) {
1203 newBanner.setImage(convertImage(
1204 oldBanner.getSrc(),
1205 null,
1206 oldBanner.getHeight(),
1207 oldBanner.getWidth(),
1208 oldBanner.getBorder(),
1209 oldBanner.getAlt()));
1210 }
1211
1212 return newBanner;
1213 }
1214
1215 private Image convertImage(String src, String position, String height, String width, String border, String alt) {
1216 Image newImage = new Image();
1217 newImage.setSrc(src);
1218 newImage.setPosition(position);
1219 newImage.setHeight(height);
1220 newImage.setWidth(width);
1221 if (border != null) {
1222 newImage.setStyle("border: " + border + ";");
1223 }
1224 newImage.setAlt(alt);
1225
1226 return newImage;
1227 }
1228
1229 private LinkItem convertLinkItem(org.apache.maven.doxia.site.decoration.LinkItem oldLinkItem) {
1230 LinkItem newLinkItem = new LinkItem();
1231 newLinkItem.setName(oldLinkItem.getName());
1232 newLinkItem.setHref(oldLinkItem.getHref());
1233 newLinkItem.setTarget(oldLinkItem.getTarget());
1234 if (oldLinkItem.getImg() != null) {
1235 newLinkItem.setImage(convertImage(
1236 oldLinkItem.getImg(),
1237 oldLinkItem.getPosition(),
1238 oldLinkItem.getHeight(),
1239 oldLinkItem.getWidth(),
1240 oldLinkItem.getBorder(),
1241 oldLinkItem.getAlt()));
1242 }
1243
1244 return newLinkItem;
1245 }
1246
1247 private List<MenuItem> convertMenuItems(List<org.apache.maven.doxia.site.decoration.MenuItem> oldMenuItems) {
1248 List<MenuItem> newMenuItems = new ArrayList<>();
1249 for (org.apache.maven.doxia.site.decoration.MenuItem oldMenuItem : oldMenuItems) {
1250 MenuItem newMenuItem = new MenuItem();
1251 newMenuItem.setName(oldMenuItem.getName());
1252 newMenuItem.setHref(oldMenuItem.getHref());
1253 newMenuItem.setTarget(oldMenuItem.getTarget());
1254 newMenuItem.setCollapse(oldMenuItem.isCollapse());
1255 newMenuItem.setRef(oldMenuItem.getRef());
1256 newMenuItem.setItems(convertMenuItems(oldMenuItem.getItems()));
1257 if (oldMenuItem.getImg() != null) {
1258 newMenuItem.setImage(convertImage(
1259 oldMenuItem.getImg(),
1260 oldMenuItem.getPosition(),
1261 oldMenuItem.getHeight(),
1262 oldMenuItem.getWidth(),
1263 oldMenuItem.getBorder(),
1264 oldMenuItem.getAlt()));
1265 }
1266 newMenuItems.add(newMenuItem);
1267 }
1268
1269 return newMenuItems;
1270 }
1271
1272 private boolean isOldSiteModel(String siteDescriptorContent) throws XmlPullParserException, IOException {
1273 XmlPullParser parser = new MXParser();
1274 parser.setInput(new StringReader(siteDescriptorContent));
1275
1276 if (!(parser.getEventType() == XmlPullParser.START_DOCUMENT && parser.next() == XmlPullParser.START_TAG)) {
1277 return false;
1278 }
1279 if ("project".equals(parser.getName())) {
1280 return true;
1281 }
1282
1283 return false;
1284 }
1285
1286 private SiteModel getDefaultSiteModel() throws SiteToolException {
1287 String siteDescriptorContent;
1288
1289 Reader reader = null;
1290 try {
1291 reader = ReaderFactory.newXmlReader(getClass().getResourceAsStream("/default-site.xml"));
1292 siteDescriptorContent = IOUtil.toString(reader);
1293 } catch (IOException e) {
1294 throw new SiteToolException("Error reading default site descriptor", e);
1295 } finally {
1296 IOUtil.close(reader);
1297 }
1298
1299 return readSiteModel(siteDescriptorContent, null, SiteTool.DEFAULT_LOCALE);
1300 }
1301
1302 private String siteModelToString(SiteModel siteModel) throws SiteToolException {
1303 StringWriter writer = new StringWriter();
1304
1305 try {
1306 new SiteXpp3Writer().write(writer, siteModel);
1307 return writer.toString();
1308 } catch (IOException e) {
1309 throw new SiteToolException("Error reading site descriptor", e);
1310 } finally {
1311 IOUtil.close(writer);
1312 }
1313 }
1314
1315 private static String buildRelativePath(final String toPath, final String fromPath, final char separatorChar) {
1316
1317 StringTokenizer toTokeniser = new StringTokenizer(toPath, String.valueOf(separatorChar));
1318 StringTokenizer fromTokeniser = new StringTokenizer(fromPath, String.valueOf(separatorChar));
1319
1320 int count = 0;
1321
1322
1323 while (toTokeniser.hasMoreTokens() && fromTokeniser.hasMoreTokens()) {
1324 if (separatorChar == '\\') {
1325 if (!fromTokeniser.nextToken().equalsIgnoreCase(toTokeniser.nextToken())) {
1326 break;
1327 }
1328 } else {
1329 if (!fromTokeniser.nextToken().equals(toTokeniser.nextToken())) {
1330 break;
1331 }
1332 }
1333
1334 count++;
1335 }
1336
1337
1338
1339
1340 toTokeniser = new StringTokenizer(toPath, String.valueOf(separatorChar));
1341 fromTokeniser = new StringTokenizer(fromPath, String.valueOf(separatorChar));
1342
1343 while (count-- > 0) {
1344 fromTokeniser.nextToken();
1345 toTokeniser.nextToken();
1346 }
1347
1348 StringBuilder relativePath = new StringBuilder();
1349
1350
1351 while (fromTokeniser.hasMoreTokens()) {
1352 fromTokeniser.nextToken();
1353
1354 relativePath.append("..");
1355
1356 if (fromTokeniser.hasMoreTokens()) {
1357 relativePath.append(separatorChar);
1358 }
1359 }
1360
1361 if (relativePath.length() != 0 && toTokeniser.hasMoreTokens()) {
1362 relativePath.append(separatorChar);
1363 }
1364
1365
1366 while (toTokeniser.hasMoreTokens()) {
1367 relativePath.append(toTokeniser.nextToken());
1368
1369 if (toTokeniser.hasMoreTokens()) {
1370 relativePath.append(separatorChar);
1371 }
1372 }
1373 return relativePath.toString();
1374 }
1375
1376
1377
1378
1379
1380
1381
1382
1383 private void appendMenuItem(MavenProject project, Menu menu, String name, String href, String defaultHref) {
1384 String selectedHref = href;
1385
1386 if (selectedHref == null) {
1387 selectedHref = defaultHref;
1388 }
1389
1390 MenuItem item = new MenuItem();
1391 item.setName(name);
1392
1393 if (selectedHref != null) {
1394 String baseUrl = getDistMgmntSiteUrl(project);
1395 if (baseUrl != null) {
1396 selectedHref = getRelativePath(selectedHref, baseUrl);
1397 }
1398
1399 if (selectedHref.endsWith("/")) {
1400 item.setHref(selectedHref + "index.html");
1401 } else {
1402 item.setHref(selectedHref + "/index.html");
1403 }
1404 }
1405 menu.addItem(item);
1406 }
1407
1408
1409
1410
1411
1412
1413
1414
1415 private MenuItem createCategoryMenu(String name, String href, List<MavenReport> categoryReports, Locale locale) {
1416 MenuItem item = new MenuItem();
1417 item.setName(name);
1418 item.setCollapse(true);
1419 item.setHref(href);
1420
1421
1422
1423
1424 for (MavenReport report : categoryReports) {
1425 MenuItem subitem = new MenuItem();
1426 subitem.setName(report.getName(locale));
1427 subitem.setHref(report.getOutputName() + ".html");
1428 item.getItems().add(subitem);
1429 }
1430
1431 return item;
1432 }
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444 private static boolean isEmptyList(List<?> list) {
1445 return list == null || list.isEmpty();
1446 }
1447
1448
1449
1450
1451
1452
1453
1454 private static String getDistMgmntSiteUrl(MavenProject project) {
1455 return getDistMgmntSiteUrl(project.getDistributionManagement());
1456 }
1457
1458 private static String getDistMgmntSiteUrl(DistributionManagement distMgmnt) {
1459 if (distMgmnt != null
1460 && distMgmnt.getSite() != null
1461 && distMgmnt.getSite().getUrl() != null) {
1462
1463 return urlEncode(distMgmnt.getSite().getUrl());
1464 }
1465
1466 return null;
1467 }
1468
1469
1470
1471
1472
1473
1474 private static Plugin getPlugin(MavenProject project, String pluginId) {
1475 if ((project.getBuild() == null) || (project.getBuild().getPluginsAsMap() == null)) {
1476 return null;
1477 }
1478
1479 Plugin plugin = project.getBuild().getPluginsAsMap().get(pluginId);
1480
1481 if ((plugin == null)
1482 && (project.getBuild().getPluginManagement() != null)
1483 && (project.getBuild().getPluginManagement().getPluginsAsMap() != null)) {
1484 plugin = project.getBuild().getPluginManagement().getPluginsAsMap().get(pluginId);
1485 }
1486
1487 return plugin;
1488 }
1489
1490
1491
1492
1493
1494
1495
1496 private static String getPluginParameter(MavenProject project, String pluginId, String param) {
1497 Plugin plugin = getPlugin(project, pluginId);
1498 if (plugin != null) {
1499 Xpp3Dom xpp3Dom = (Xpp3Dom) plugin.getConfiguration();
1500 if (xpp3Dom != null
1501 && xpp3Dom.getChild(param) != null
1502 && StringUtils.isNotEmpty(xpp3Dom.getChild(param).getValue())) {
1503 return xpp3Dom.getChild(param).getValue();
1504 }
1505 }
1506
1507 return null;
1508 }
1509
1510 private static String urlEncode(final String url) {
1511 if (url == null) {
1512 return null;
1513 }
1514
1515 try {
1516 return new File(url).toURI().toURL().toExternalForm();
1517 } catch (MalformedURLException ex) {
1518 return url;
1519 }
1520 }
1521 }