1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.devacfr.maven.skins.reflow;
20
21 import java.net.URI;
22
23 import javax.annotation.Nonnull;
24 import javax.annotation.Nullable;
25
26 import org.apache.maven.doxia.site.inheritance.URIPathDescriptor;
27 import org.apache.velocity.tools.config.DefaultKey;
28
29 import com.google.common.base.Strings;
30
31 /**
32 * An Apache Velocity tool that provides utility methods to work with URIs/URLs and links.
33 *
34 * @author Andrius Velykis
35 * @since 1.0
36 */
37 // instancied by Velocity
38 @SuppressWarnings({ "checkstyle:finalclass", "checkstyle:hideutilityclassconstructor" })
39 @DefaultKey("uriTool")
40 public class URITool {
41
42 /**
43 * Resolves the link as relative to the base dir URI.
44 * <p>
45 * Relativizes only absolute links, if the link has the same scheme, host and port as the base, it is made into a
46 * relative link as viewed from the base.
47 * </p>
48 * <p>
49 * This is the same method that's used to relativize project links in Maven site.
50 * </p>
51 *
52 * @param baseDirUri
53 * URI that will serve as the base to calculate the relative one
54 * @param link
55 * The link to relativize (make it relative to the base URI if possible)
56 * @return the relative link, if calculated, or the original link if not.
57 * @since 1.0
58 */
59 @Nullable public static String relativizeLink(@Nullable final String baseDirUri, @Nullable final String link) {
60 // taken from
61 // org.apache.maven.doxia.site.decoration.inheritance.DecorationModelInheritanceAssembler
62
63 if (link == null || baseDirUri == null) {
64 return link;
65 }
66 try {
67 final URIPathDescriptor path = new URIPathDescriptor(baseDirUri, link);
68 return normalisedBaseUrl(path.relativizeLink().toString());
69 } catch (final IllegalArgumentException e) {
70 return link;
71 }
72 }
73
74 /**
75 * Creates a URI by parsing the given string.
76 *
77 * @param uri
78 * The string to be parsed into a URI
79 * @return Returns the new URI.
80 */
81 @Nonnull
82 public static URI toURI(@Nonnull final String uri) {
83 return URI.create(uri);
84 }
85
86 /**
87 * @param parentBaseUrl
88 * The base URI. Has to be a valid absolute URI. In addition, the path of the URI should not have any
89 * file part, ie <code>http://maven.apache.org/</code> is valid,
90 * <code>http://maven.apache.org/index.html</code> is not.
91 * @param childBaseUrl
92 * the new base URI. Has to be parsable as a URI.
93 * @return Returns new instance of {@link URLRebaser} allowing to calculate/relative the link as viewed from a
94 * different base. This returns the {@code parentBaseUrl} link if link is absolute.
95 * @see URIPathDescriptor#rebaseLink(String)
96 * @see URLRebaser#rebaseLink(String)
97 */
98 public static URLRebaser createURLRebaser(@Nullable final String parentBaseUrl,
99 @Nullable final String childBaseUrl) {
100 return new URLRebaser(parentBaseUrl, childBaseUrl);
101 }
102
103 /**
104 * remove url path separator ('/') to the end of path.
105 *
106 * @param baseUrl
107 * a base url
108 * @return Returns a <code>String</code> representing base path instance.
109 */
110 @Nullable public static String normalisedBaseUrl(@Nullable final String baseUrl) {
111 if (Strings.isNullOrEmpty(baseUrl)) {
112 return baseUrl;
113 }
114 if (baseUrl.endsWith("/")) {
115 return baseUrl.substring(0, baseUrl.length() - 1);
116 }
117
118 return baseUrl;
119 }
120
121 /**
122 * URL rebaser: based on an old and a new path, can rebase a link based on old path to a value based on the new
123 * path.
124 */
125 public static class URLRebaser {
126
127 /** */
128 private final String oldPath;
129
130 /** */
131 private final String newPath;
132
133 /**
134 * Construct a URL rebaser.
135 *
136 * @param oldPath
137 * the old path. The base URI. Has to be a valid absolute URI. In addition, the path of the URI
138 * should not have any file part, ie <code>http://maven.apache.org/</code> is valid,
139 * <code>http://maven.apache.org/index.html</code> is not.
140 * @param newPath
141 * the new base URI. Has to be parsable as a URI.
142 */
143 protected URLRebaser(@Nullable final String oldPath, @Nullable final String newPath) {
144 this.oldPath = oldPath;
145 this.newPath = newPath;
146 }
147
148 /**
149 * Get the new path.
150 *
151 * @return the new path.
152 */
153 @Nullable public String getNewPath() {
154 return this.newPath;
155 }
156
157 /**
158 * Get the old path.
159 *
160 * @return the old path.
161 */
162 @Nullable public String getOldPath() {
163 return this.oldPath;
164 }
165
166 /**
167 * Rebase only affects relative links, a relative link wrt an old base gets translated, so it points to the same
168 * location as viewed from a new base.
169 *
170 * @param link
171 * link to rebase
172 * @return Returns a {@link String} representing link rebased.
173 */
174 public String rebaseLink(@Nullable final String link) {
175 if (link == null || getOldPath() == null) {
176 return link;
177 }
178
179 if (link.contains("${project.")) {
180 throw new IllegalArgumentException("site.xml late interpolation ${project.*} expression found"
181 + " in link: '" + link + "'. Use early interpolation ${this.*}");
182 }
183
184 final URIPathDescriptor oldPath = new URIPathDescriptor(getOldPath(), link);
185
186 return oldPath.rebaseLink(getNewPath()).toString();
187 }
188 }
189 }