001 /**
002 * Copyright 2004-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.maven.common;
017
018 import java.util.Properties;
019
020 import org.apache.commons.lang.StringUtils;
021 import org.apache.maven.model.Scm;
022 import org.apache.maven.plugin.AbstractMojo;
023 import org.apache.maven.plugin.MojoExecutionException;
024 import org.apache.maven.project.MavenProject;
025
026 /**
027 * Extracts information contained in a pom and exposes it as project properties
028 *
029 * eg major version, scm type, scm url
030 *
031 */
032 public class Extractor {
033 PropertiesUtils utils = new PropertiesUtils();
034
035 public void handleSVNBranch(AbstractMojo mojo, MavenProject project, String property) {
036 String scmType = getScmType(project.getScm());
037 if (!"svn".equalsIgnoreCase(scmType)) {
038 mojo.getLog().warn("This should only be used with Subversion");
039 }
040 String scmUrl = getScmUrl(project.getScm());
041 String branch = getBranch(scmUrl);
042
043 if (!StringUtils.isEmpty(branch)) {
044 project.getProperties().setProperty(property, branch);
045 mojo.getLog().info(property + "=" + branch);
046 } else {
047 mojo.getLog().debug("SVN branch could not be determined");
048 }
049 }
050
051 public void handleSVNTagBase(AbstractMojo mojo, MavenProject project, String property) {
052 String scmType = getScmType(project.getScm());
053 if (!"svn".equalsIgnoreCase(scmType)) {
054 mojo.getLog().warn("This should only be used with Subversion");
055 }
056 String scmUrl = getScmUrl(project.getScm());
057 String tagBase = getTagBase(scmUrl);
058
059 if (!StringUtils.isEmpty(tagBase)) {
060 project.getProperties().setProperty(property, tagBase);
061 mojo.getLog().info(property + "=" + tagBase);
062 } else {
063 mojo.getLog().debug("SVN tag base could not be determined");
064 }
065 }
066
067 public void handleMajorVersion(AbstractMojo mojo, MavenProject project, String property) {
068 String majorVersion = getMajorVersion(project.getVersion());
069 if (!StringUtils.isEmpty(majorVersion)) {
070 project.getProperties().setProperty(property, majorVersion);
071 mojo.getLog().info(property + "=" + majorVersion);
072 } else {
073 mojo.getLog().info("Major version could not be determined");
074 }
075 }
076
077 public void handleScmUrl(AbstractMojo mojo, MavenProject project, String property) {
078 String scmUrl = getScmUrl(project.getScm());
079 if (!StringUtils.isEmpty(scmUrl)) {
080 project.getProperties().setProperty(property, scmUrl);
081 mojo.getLog().info(property + "=" + scmUrl);
082 } else {
083 mojo.getLog().info("scm url could not be determined");
084 }
085 }
086
087 public void handleScmType(AbstractMojo mojo, MavenProject project, String property) {
088 String scmType = getScmType(project.getScm());
089 if (!StringUtils.isEmpty(scmType)) {
090 project.getProperties().setProperty(property, scmType);
091 mojo.getLog().info(property + "=" + scmType);
092 } else {
093 mojo.getLog().info("scm type could not be determined");
094 }
095 }
096
097 public String getActualUrl(MavenProject project, String property) throws MojoExecutionException {
098 Properties props = utils.getMavenProperties(project);
099 String rawUrl = props.getProperty(property);
100 if (StringUtils.isBlank(rawUrl)) {
101 throw new MojoExecutionException("The project property '" + property + "' is blank");
102 }
103 String resolvedValue = utils.getResolvedValue(rawUrl, props);
104 if (StringUtils.isBlank(resolvedValue)) {
105 throw new MojoExecutionException("Resolved value for '" + property + "' is blank");
106 }
107 return resolvedValue;
108 }
109
110 public Scm getTrimmedScm(Scm scm) {
111 String trimmedDeveloperConnection = getTrimmedScmUrl(scm.getDeveloperConnection());
112 String trimmedConnection = getTrimmedScmUrl(scm.getConnection());
113 String trimmedUrl = scm.getUrl().trim();
114 Scm trimmedScm = new Scm();
115 trimmedScm.setDeveloperConnection(trimmedDeveloperConnection);
116 trimmedScm.setConnection(trimmedConnection);
117 trimmedScm.setUrl(trimmedUrl);
118 return trimmedScm;
119 }
120
121 public String getScmUrl(Scm scm) {
122 String devCon = scm.getDeveloperConnection();
123 String con = scm.getConnection();
124 String scmUrl = StringUtils.isEmpty(devCon) ? con : devCon;
125 if (StringUtils.isEmpty(scmUrl)) {
126 return null;
127 }
128 return getTrimmedScmUrl(scmUrl);
129 }
130
131 protected String getTrimmedScmUrl(String url) {
132 String[] tokens = StringUtils.splitByWholeSeparatorPreserveAllTokens(url.trim(), ":");
133 if (tokens == null || tokens.length < 3) {
134 throw new IllegalArgumentException("Unable to trim url " + url);
135 }
136 StringBuilder sb = new StringBuilder();
137 for (int i = 2; i < tokens.length; i++) {
138 if (i != 2) {
139 sb.append(":");
140 }
141 sb.append(tokens[i]);
142 }
143 return sb.toString();
144 }
145
146 public String getScmType(Scm scm) {
147 String scmType1 = getScmType(scm.getDeveloperConnection());
148 String scmType2 = getScmType(scm.getConnection());
149 if (!StringUtils.isEmpty(scmType1)) {
150 return scmType1;
151 } else if (!StringUtils.isEmpty(scmType2)) {
152 return scmType2;
153 } else {
154 return null;
155 }
156 }
157
158 public String getScmType(String url) {
159 if (StringUtils.isEmpty(url)) {
160 return null;
161 }
162 String[] tokens = StringUtils.splitByWholeSeparatorPreserveAllTokens(url, ":");
163 if (tokens == null || tokens.length < 2) {
164 return null;
165 } else {
166 return tokens[1];
167 }
168 }
169
170 public String getBranch(String url) {
171 int pos = url.lastIndexOf("/trunk");
172 if (pos != -1) {
173 return "trunk";
174 }
175 String token = "/branches/";
176 pos = url.lastIndexOf(token);
177 if (pos == -1) {
178 return null;
179 }
180 String s = url.substring(pos + token.length());
181 pos = s.indexOf("/");
182 if (pos == -1) {
183 return s;
184 } else {
185 return s.substring(0, pos);
186 }
187 }
188
189 public void validateTrimmedScm(Scm scm, String actualUrl) {
190 validateUrls(scm.getDeveloperConnection(), actualUrl);
191 validateUrls(scm.getConnection(), actualUrl);
192 validateUrls(scm.getUrl(), actualUrl);
193 }
194
195 public void validateUrls(String url, String actualUrl) {
196 if (StringUtils.isBlank(url)) {
197 throw new IllegalArgumentException("url cannot be blank");
198 }
199 if (StringUtils.isBlank(actualUrl)) {
200 throw new IllegalArgumentException("actualUrl cannot be blank");
201 }
202 if (!url.equals(actualUrl)) {
203 throw new IllegalArgumentException("URL's don't match. url=[" + url + "] actual=[" + actualUrl);
204 }
205 }
206
207 public String getTagBase(String url) {
208 int pos1 = url.lastIndexOf("/branches");
209 int pos2 = url.lastIndexOf("/trunk");
210 int pos = Math.max(pos1, pos2);
211 if (pos == -1) {
212 return null;
213 } else {
214 return url.substring(0, pos) + "/tags";
215 }
216 }
217
218 public String getMajorVersion(String version) {
219 if (StringUtils.isEmpty(version)) {
220 return null;
221 }
222 int pos = getPos(version);
223 if (pos == -1) {
224 return version;
225 } else {
226 int peekAhead = peekAhead(pos, version);
227 return version.substring(0, peekAhead);
228 }
229 }
230
231 protected int peekAhead(int pos, String version) {
232 // Attempt to peek ahead one character after the dot/dash
233 int index = pos + 1;
234
235 // If we go past the end of the string, forget it
236 if (index >= version.length()) {
237 return pos;
238 }
239
240 // Is that character an integer?
241 char c = version.charAt(index);
242
243 if (isInteger(c)) {
244 // If so, include it
245 return index + 1;
246 } else {
247 // If not return the original
248 return pos;
249 }
250 }
251
252 protected int getPos(String version) {
253 int pos1 = version.indexOf(".");
254 int pos2 = version.indexOf("-");
255 // No dot or dash
256 if (pos1 == pos2 && pos2 == -1) {
257 return -1;
258 }
259 // Dash but no dot
260 if (pos1 == -1 && pos2 != -1) {
261 return pos2;
262 }
263 // Dot but no dash
264 if (pos1 != -1 && pos2 == -1) {
265 return pos1;
266 }
267
268 // Both a dot and a dash, use the first one
269 return Math.min(pos1, pos2);
270
271 }
272
273 protected boolean isInteger(char c) {
274 switch (c) {
275 case '0':
276 case '1':
277 case '2':
278 case '3':
279 case '4':
280 case '5':
281 case '6':
282 case '7':
283 case '8':
284 case '9':
285 return true;
286 default:
287 return false;
288 }
289 }
290 }